从应用的行为理解Surface

Surface是Android对后台缓冲区的抽象,它是一块在应用和SurfaceFlinger之间共享的内存区域。所有的Android界面,在往屏幕上绘制内容前,都需要先获得一个或者多个Surface,然后使用2D(SKIA)或者3D(OpenGL ES)引擎往这个缓冲区上绘制内容。内容绘制结束后,通知SurfaceFlinger将内容渲染到屏幕(Frame Buffer)上去。

本文不打算深入SurfaceFlinger的工作原理,仅着眼于2D/3D应用对Surface的使用,以增加对Android Surface的理解。

在Android里面,应用对Surface的使用主要有三个步骤:

1,初始化 Surface。初始化过程通常分为下述几个过程:

SurfaceComposerClient,建立和SF的连接。其通信接口由Client表达。

SurfaceControl,使用Client对象和SF通信,创建Layer和GraphicsBuffer。

Surface,创建通信接口UserClient,用于管理客户端和SF之间使用的Buffer状态,如前后台。

设定后台缓冲地址,设定了后台缓冲区地址后,绘图引擎就可以直接在这个缓冲区绘图了。

2,应用使用2D/3D绘图引擎在Surface的后台缓冲区绘图;

3,绘图结束,告知SF将Surface渲染到屏幕上。

在后台缓冲区绘图时,2D引擎SKIA需要维护一个SkCanvas的绘图上下文。OpenGL ES在后台缓冲区绘图时其实也有一个绘图上下文,用对象ogles_context_t描述,不过客户端通常接触不到这个对象。其实SKIA和OpenGL 都是有限状态机,绘图上下文就是用来记录这个状态机的当前状态。

后台缓冲区绘图的绘图行为可以描述为:绘图引擎根据当前的绘图上下文,用绘图原语在后台缓冲区绘图的过程。

初始化 Surface和绘图结束两个步骤中, SKIA和OpenGL的差异很有意思。后文会重点解释。

1.初始化 Surface



从上面两个序列图来看,SKIA和 OpenGL操作Surface的初始化过程,在形式上是很类似的。

2.绘图结束

对于2D 应用,绘图结束使用函数Surface::unlockAndPost来通知SurfaceFlinger。

对于OpenGL应用,则是通过eglSwapBuffers来通知SurfaceFlinger。

Surface::unlockAndPost

{

mLockedBuffer->unlock//没找到相应实现

Surface::queueBuffer,将当前Surafce插入ready队列,并通知SF将其渲染到屏幕。

}

eglSwapBuffers

egl_window_surface_v2_t::swapBuffers

{

egl_window_surface_v2_t::unlock//没找到相应实现

Surface::queueBuffer(nativeWindow->queueBuffer),将当前Surafce插入ready队列,并通知SF将其渲染到屏幕

}