Android应用程序请求SurfaceFlinger服务渲染Surface的过程分析
在前面一篇文章中,我们分析了Android应用程序请求SurfaceFlinger服务创建Surface的过程。有了Surface之后,Android应用程序就可以在上面绘制自己的UI了,接着再请求SurfaceFlinger服务将这个已经绘制好了UI的Surface渲染到设备显示屏上去。在本文中,我们就将详细分析Android应用程序请求SurfaceFlinger服务渲染Surface的过程。
Android应用程序在请求SurfaceFlinger服务渲染一个Surface之前,首先要将该Surface作为当前活动的绘图上下文,以便可以使用OpengGL库或者其它库的API来在上面绘制UI,我们以Android系统的开机动画应用程序bootanim为例,来说明这个问题。
从前面Android应用程序请求SurfaceFlinger服务创建Surface的过程分析一文可以知道,Android系统的开机动画应用程序bootanim是在BootAnimation类的成员函数readyToRun中请求SurfaceFlinger服务创建Surface的。这个Surface创建完成之后,就会被设置为当前活动的绘图上下文,如下所示:
图1 SharedBufferStack的结构示意图
从图1就可以看出,每一个UI元数据缓冲区都可能对应有一个UI数据缓冲区,这个UI数据缓冲区又可以称为图形缓冲区,它使用一个GraphicBuffer对象来描述。注意,一个UI元数据缓冲区只有第一次被使用时,Android应用程序才会为它创建一个图形缓冲区,因此,我们才说每一个UI元数据缓冲区都可能对应有一个UI数据缓冲区。例如,在图1中,目前只使到了编号为1和2的UI元数据缓冲区,因此,只有它们才有对应的图形缓冲区,而编号为3、4和5的UI元数据缓冲区没有。
Android应用程序渲染一个Surface的过程大致如下所示:
1. 从UI元数据缓冲区堆栈中得到一个空闲的UI元数据缓冲区;
2. 请求SurfaceFlinger服务为这个空闲的UI元数据缓冲区分配一个图形缓冲区;
3. 在图形缓冲区上面绘制好UI之后,即填充好UI数据之后,就将前面得到的空闲UI元数据缓冲区添加到UI元数据缓冲区堆栈中的待渲染队列中去;
4. 请求SurfaceFlinger服务渲染前面已经准备好了图形缓冲区的Surface;
5. SurfaceFlinger服务从即将要渲染的Surface的UI元数据缓冲区堆栈的待渲染队列中找到待渲染的UI元数据缓冲区;
6. SurfaceFlinger服务得到了待渲染的UI元数据缓冲区之后,接着再找到在前面第2步为它所分配的图形缓冲区,最后就可以将这个图形缓冲区渲染到设备显示屏上去。
这个过程的第1步、第3步和第5步涉到UI元数据缓冲区堆栈的一些出入栈操作,为了方便后面描述Android应用程序请求SurfaceFlinger服务渲染Surface的过程,我们首先介绍一下UI元数据缓冲区堆栈的一些出入栈操作。
在前面Android应用程序请求SurfaceFlinger服务创建Surface的过程分析一文中,我们分析了用来描述UI元数据缓冲区堆栈的SharedBufferServer和SharedBufferClient类的父类SharedBufferBase,它有一个成员函数waitForCondition,用来等待一个条件得到满足,它定义在文件frameworks/base/include/private/surfaceflinger/SharedBufferStack.h中,如下所示:
图2 分配空闲UI元数据缓冲区及其图形缓冲区的过程
这个过程一共分为12个步骤,接下来我们就详细分析每一个步骤。
Step 1. Surface.dequeueBuffer
这个过程一共分为4个步骤,接下来我们就详细分析每一个步骤。
Step 1. Surface.queueBuffer
图 4 SurfaceFlinger服务渲染Surface的过程
这个过程一共分为6个步骤,接下来我们就详细分析每一个步骤。
Step 1. SurfaceFlinger.threadLoop
status_t Layer::BufferManager::setActiveBufferIndex(size_t index) { mActiveBuffer = index; return NO_ERROR;}这个函数定义在文件frameworks/base/services/surfaceflinger/Layer.cpp中。
BufferManager类的成员变量mActiveBuffer用来描述一个Surface的当前激活的图形缓冲区的编号。由于参数index正好就是描述一个Surface的当前激活的图形缓冲区的编号,因此,函数就可以将它保存在BufferManager类的成员变量mActiveBuffer中。
前面在分析空闲UI元数据缓冲区及其图形缓冲区的分配过程的Step 10时提到,BufferManager类有一个类型BufferData数组的成员变量mBufferData,它里面保存了SurfaceFlinger服务为一个Surface所分配的图形缓冲区,这样,后面SurfaceFlinger服务在渲染一个Surface时,就可以通过与它所关联的一个BufferManager对象的成员变量mActiveBuffer来在另外一个成员变量mBufferData中找到当前激活的图形缓冲区。
这一步执行完成之后,SurfaceFlinger服务渲染Surface的图形缓冲区的过程就分析完成了。这个过程虽然只是一个粗略的过程,但是已经足够我们理解Android应用程序请求SurfaceFlinger服务渲染Surface的过程了,同时也为后面我们从正面分析SurfaceFlinger服务的实现原理理清了思路,以及打下了良好的基础。
至此,Android应用程序和SurfaceFlinger服务的关系我们就学习完成了。要重新学习,请参考前面Android应用程序与SurfaceFlinger服务的关系概述和学习计划一文。接下来,我们还会继续分析SurfaceFlinger服务的实现原理,敬请关注!