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的差异很有意思。后文会重点解释。
从上面两个序列图来看,SKIA和 OpenGL操作Surface的初始化过程,在形式上是很类似的。
对于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将其渲染到屏幕
}