博客
关于我
强烈建议你试试无所不能的chatGPT,快点击我
07.显示系统:第005课_Vsync机制:第007节_rebuildLayerStacks源码分析
阅读量:729 次
发布时间:2019-03-21

本文共 2695 字,大约阅读时间需要 8 分钟。

前面讲解了那么多的基础知识,现在 我们可以进入界面合成流程的分析了。下面是一个手机APP的界面图:

在这里插入图片描述
在其中有很多个应用程序,从图上的标记,我们就知道了4个APP,那么这些APP的界面时怎么合成的呢?有两种方法:
1.在FrameBuffer上一次画出每个APP,然后在FrameBuffer上显示出来。
比如这对这四个APP:先获得一个FrameBuffer,先画出分别画出APP1,2,3,如下:
在这里插入图片描述
然后把FrameBuffer推送给LCD。

2.各个APP写入不同的window,通过硬件合成后,在LED上直接显示(硬件方式)。

软件显示

首先我们来讲解第一种方法,使用openGL,其可以使用软件合成也能通过GPU合成。我们打开SurfaceFlinger.cpp找到其中的init函数:

void SurfaceFlinger::init() {
mHwc = new HWComposer(this); loadHwcModule(); /*获得HW文件,如果不能获得,则不会设置mHwc*/ hw_get_module(HWC_HARDWARE_MODULE_ID, &module) != 0) int err = hwc_open_1(module, &mHwc); mHwc = NULL;

如果不通过硬件合成单元,这返回失败mHwc = NULL。那么是怎么判断系统是否存在硬件合成单元的呢?在HWComposer这个类中存在initCheck函数:

status_t HWComposer::initCheck() const {
return mHwc ? NO_ERROR : NO_INIT;}

如果mHwc 被设置了,说明其有硬件合成放单元,否则代表没有。下面我们查看SurfaceFlinger.cpp中handleMessageRefresh方法,我们知道这在这个函数之中刷新界面的。

void SurfaceFlinger::handleMessageRefresh() {
setUpHWComposer(); /*如果存在硬件合成单元(以后进行详细讲解)*/ if (hwc.initCheck() == NO_ERROR) {
..... /*对于使用openGL刷新界面我们需要着重关注这个函数*/ doComposition();

在讲解doComposition之前,我们测试一下其内部会实现哪些动作:在FramerBuffer依次画出每个应用程序,然后提交给LCD。

1.绘画出每一个Layer
2.suapBuffer
如下图:
在这里插入图片描述
下面我们进入doComposition函数的分析,下面是他详细的流程图:
在这里插入图片描述

doComposition()	/*对所有显示器进行循环*/	for (size_t dpy=0 ; dpy
& hw(mDisplays[dpy]); /*如果其显示器为开启状态*/ if (hw->isDisplayOn()) {
// repaint the framebuffer (if needed) /*重新绘画framebuffer*/ doDisplayComposition(hw, dirtyRegion); /*合成多个surface*/ doComposeSurfaces(hw, dirtyRegion); /*如果使用openGL*/ if (hasGlesComposition) {
eglMakeCurrent(mEGLDisplay, EGL_NO_SURFACE, EGL_NO_SURFACE, EGL_NO_CONTEXT); /*如果使用硬件合成单元*/ if (hasHwcComposition) ....... // we start with the whole screen area /*确定要绘制的区域*/ const Region bounds(hw->getBounds()); /*把区域写成黑色*/ drawWormhole(hw, region); /*对于每一个layer*/ for (size_t i=0 ; i
draw(hw, clip); onDraw(hw, clip, false); drawWithOpenGL(hw, clip, useIdentityTransform); /*对每个显示器使用drawWithOpenGL函数之后执行doDisplayComposition*/ doDisplayComposition() doComposeSurfaces(hw, dirtyRegion) // swap buffers (presentation) hw->swapBuffers(getHwComposer());

可以看到,其最终调用到drawWithOpenGL函数,其上的swapBuffers在DisplayDevice.cpp中实现:

void DisplayDevice::swapBuffers(HWComposer& hwc) const {
success = eglSwapBuffers(mDisplay, mSurface); d->swapBuffers(); /*当前的buffer*/ previousBuffer = buffer; /*把当前的buffer放入队列中*/ nativeWindow->queueBuffer(nativeWindow, buffer, -1); /*获得一个新的buffer*/ nativeWindow->dequeueBuffer(nativeWindow, &buffer, &fenceFd) == NO_ERROR)

通过上面的分析我们可以绘画出以下流程:

在这里插入图片描述

转载地址:http://sligz.baihongyu.com/

你可能感兴趣的文章