您的位置:首页 > 产品设计 > UI/UE

GUI系统之SurfaceFlinger(18)postFramebuffer

2013-08-02 10:35 363 查看
文章都是通过阅读源码分析出来的,还在不断完善与改进中,其中难免有些地方理解得不对,欢迎大家批评指正。

转载请注明:From LXS. http://blog.csdn.net/uiop78uiop78/
GUI系统之SurfaceFlinger章节目录:

blog.csdn.net/uiop78uiop78/article/details/8954508

1.1.1 postFramebuffer

在多缓冲区机制中,只有把显示数据写入framebuffer才能真正在物理屏幕上显示。前面几个小节的输出都是backbuffers,我们还需要最后一步——postFramebuffer。

void SurfaceFlinger::postFramebuffer()

{…

const DisplayHardware&hw(graphicPlane(0).displayHardware());



hw.flip(mSwapRegion);//交换前后台buffer

size_t numLayers =mVisibleLayersSortedByZ.size();

for (size_t i = 0; i <numLayers; i++) {

mVisibleLayersSortedByZ[i]->onLayerDisplayed();

}



}

先从opengl本地窗口的角度来想一下:

Ø queueBuffer

一旦“生产者”完成生产后,它需要把当前的buffer重新入队,以使“消费者”可以做接下来的处理

Ø dequeueBuffer

为了“生产者”可以继续下一轮的工作,它会重新deque

基本的思路就是这样子,不过Android系统将一些步骤封装到了DisplayHardware中,我们稍后会看到。

DisplayHardware::flip完成后,分别通知各可见Layer它们的内容已经显示出来了。

void DisplayHardware::flip(const Region& dirty) const

{…

mPageFlipCount++;//flip计数

if (mHwc->initCheck()== NO_ERROR) {

mHwc->commit();

} else {

eglSwapBuffers(dpy, surface);

}



}

分为两条路径:

(1)commit

成员变量mHwc是在DisplayHardware::init中生成的一个HWComposer对象。只要HWC_HARDWARE_MODULE_ID模块可以正常加载,且hwc_open能打开hwc_composer_device设备,那么initCheck()就返回NO_ERROR,否则就是NO_INIT。

此时我们通过HWComposer::commit来执行flip,这个函数直接调用如下硬件接口:

mHwc->set(mHwc,mDpy, mSur, mList);

set()和后面的eglSwapBuffers是基本等价的,原型如下:

int (*set)(struct hwc_composer_device *dev,hwc_display_t dpy,

hwc_surface_t sur,hwc_layer_list_t* list);

其中最后一个list必须与最近一次的prepare()所用列表完全一致。假如list为空或者列表数量为0的话,说明SurfaceFlinger已经利用OpenGL ES做了composition,此时set就和eglSwapBuffers一样。当list不为空,且layer的compositionType == HWC_OVERLAY,那么HWComposer需要进行硬件合成。

如果成功执行的话,set返回0,否则就是HWC_EGL_ERROR。可以通过eglGetError()来获得具体的error。感兴趣的读者可以自己挑选一个具体的平台实现来分析,比如三星的crespo(路径是/device/Samsung/crespo/libhwcomposer)。

(2)eglSwapBuffers

以libagl为例,这个函数又调用了如下的swapBuffers:

/*frameworks/native/opengl/libagl/Egl.cpp*/

EGLBoolean egl_window_surface_v2_t::swapBuffers()

{…

nativeWindow->queueBuffer(nativeWindow, buffer);



// dequeue一个新的buffer

if (nativeWindow->dequeueBuffer(nativeWindow, &buffer) == NO_ERROR) {



} else {

returnsetError(EGL_BAD_CURRENT_SURFACE, EGL_FALSE);

}

return EGL_TRUE;

}

这和我们一开始的推测是一致的——通过queueBuffer来入队,然后通过dequeueBuffer重新申请一个buffer以用于下一轮的刷新。关于SurfaceFlinger中所使用的这一OpenGL本地窗口,即FramebufferNativeWindow的缓冲区管理,我们在前几个小节已经分析过了,大家可以结合这里的场景再看一遍
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: