07.显示系统:第005课_Vsync机制:第007节_rebuildLayerStacks源码分析

前面讲解了那么多的基础知识,现在 我们可以进入界面合成流程的分析了。下面是一个手机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<mDisplays.size() ; dpy++) {
        const sp<DisplayDevice>& 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<count ; ++i) {
						layer->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)

通过上面的分析我们可以绘画出以下流程:
在这里插入图片描述

猜你喜欢

转载自blog.csdn.net/weixin_43013761/article/details/89184654