Android系统Surface机制的SurfaceFlinger服务渲染应用程序UI的过程分析.docx

上传人:b****3 文档编号:5403729 上传时间:2022-12-16 格式:DOCX 页数:61 大小:367.73KB
下载 相关 举报
Android系统Surface机制的SurfaceFlinger服务渲染应用程序UI的过程分析.docx_第1页
第1页 / 共61页
Android系统Surface机制的SurfaceFlinger服务渲染应用程序UI的过程分析.docx_第2页
第2页 / 共61页
Android系统Surface机制的SurfaceFlinger服务渲染应用程序UI的过程分析.docx_第3页
第3页 / 共61页
Android系统Surface机制的SurfaceFlinger服务渲染应用程序UI的过程分析.docx_第4页
第4页 / 共61页
Android系统Surface机制的SurfaceFlinger服务渲染应用程序UI的过程分析.docx_第5页
第5页 / 共61页
点击查看更多>>
下载资源
资源描述

Android系统Surface机制的SurfaceFlinger服务渲染应用程序UI的过程分析.docx

《Android系统Surface机制的SurfaceFlinger服务渲染应用程序UI的过程分析.docx》由会员分享,可在线阅读,更多相关《Android系统Surface机制的SurfaceFlinger服务渲染应用程序UI的过程分析.docx(61页珍藏版)》请在冰豆网上搜索。

Android系统Surface机制的SurfaceFlinger服务渲染应用程序UI的过程分析.docx

Android系统Surface机制的SurfaceFlinger服务渲染应用程序UI的过程分析

Android系统Surface机制的SurfaceFlinger服务渲染应用程序UI的过程分析

在前面的一系列文章中,我们学习了Android应用程序与SurfaceFlinger服务的关系,以及SurfaceFlinger服务的启动过程、初始化硬件帧缓冲区的过程、线程模型。

SurfaceFlinger服务所做的一切都是为了给Android应用程序提服务的,即为Android应用程序渲染它们的UI。

在本文中,我们就详细分析SurfaceFlinger服务渲染Android应用程序UI的过程。

从前面一文可以知道,SurfaceFlinger服务是通过它的UI渲染线程来将应用程序的UI渲染到硬件帧缓冲区中去的,因此,接下来我们就通过分析SurfaceFlinger服务的UI渲染线程的执行过程来分应用程序UI的渲染过程,这个过程如图1所示。

从图1就可以看出,SurfaceFlinger服务的UI渲染线程的执行过程如下所示:

1.调用SurfaceFlinger类的成员函数handleConsoleEvents来处理控制台事件。

2.调用SurfaceFlinger类的成员函数handleTransaction来处理系统显示屏以及应用程序窗口的属性变化,例如大小、旋转方向变化等。

3.调用SurfaceFlinger类的成员函数handlePageFlip来让各个应用程序窗口设置它们当前所要渲染的图形缓冲区。

4.如果SurfaceFlinger服务在编译的时候指定了USE_COMPOSITION_BYPASS宏,并且当前需要渲染的应用程序窗口只有一个,那么就会调用SurfaceFlinger类的成员函数handleBypassLayer来直接将这个应用程序窗口的图形缓冲区渲染到硬件帧缓冲区中去,否则的话,就要调用SurfaceFlinger类的成员函数handleRepaint来合成所有的应用程序窗口的图形缓冲区到一个主图形缓冲区中去。

5.调用SurfaceFlinger类的成员函数postFramebuffer将前面得到的主图形缓冲区渲染到硬件帧缓冲区中去。

前面一文中,我们已经分析过第1步的实现了,而通过前面这一系列文章的学习,我们也已经了解了应用程序窗口的图形缓冲区的创建过程,因此,接下来我们就在这些知识的基础上来详细分析第2步到第5的实现,即分别分析SurfaceFlinger类的成员函数handleTransaction、handlePageFlip、handleBypassLayer和postFramebuffer的实现。

1.handleTransaction

SurfaceFlinger类的成员函数handleTransaction是用来处理系统显示屏以及应用程序窗口的属性变化的,这个过程如图2所示。

这个过程可以分为6个步骤,接下来我们就详细分析每一个步骤。

Step1.SurfaceFlinger.handleTransaction

[cpp]viewplaincopy在CODE上查看代码片派生到我的代码片

voidSurfaceFlinger:

:

handleTransaction(uint32_ttransactionFlags)

{

Vector>ditchedLayers;

/*

*Performandcommitthetransaction

*/

{//scopeforthelock

Mutex:

:

Autolock_l(mStateLock);

constnsecs_tnow=systemTime();

mDebugInTransaction=now;

handleTransactionLocked(transactionFlags,ditchedLayers);

mLastTransactionTime=systemTime()-now;

mDebugInTransaction=0;

//herethetransactionhasbeencommitted

}

/*

*Clean-upalllayersthatwentaway

*(dothiswithoutthelockheld)

*/

constsize_tcount=ditchedLayers.size();

for(size_ti=0;i

if(ditchedLayers[i]!

=0){

//LOGD("ditchinglayer%p",ditchedLayers[i].get());

ditchedLayers[i]->ditch();

}

}

}

这个函数定义在文件frameworks/base/services/surfaceflinger/SurfaceFlinger.cpp中。

SurfaceFlinger类的成员函数handleTransaction是通过调用另外一个成员函数handleTransactionLocked来处理系统显示屏以及应用程序窗口的属性变化的,而SurfaceFlinger类的成员函数handleTransactionLocked在处理完成系统显示屏以及应用程序窗口的属性变化之后,会返回系统中那些已经销毁了的应用程序窗口。

从这一系列文章可以知道,在SurfaceFlinger服务这一侧,应用程序窗口一般是使用一个Layer对象来描述的,又由于Layer类是从LayerBase类继承下来的,因此,我们可以那些已经销毁了的应用程序窗口保存在一个类型为sp的向量ditchedLayers中。

SurfaceFlinger类的成员函数handleTransaction最后就调用保存在向量ditchedLayers中的每一个LayerBase对象的成员函数dtich来执行被销毁的应用程序窗口的清理操作,接下来我们就继续分析SurfaceFlinger类的成员函数handleTransactionLocked,看看它是如何处理系统显示屏以及应用程序窗口的属性变化的。

Step2.SurfaceFlinger.handleTransactionLocked

SurfaceFlinger类的成员函数handleTransactionLocked定义在文件rameworks/base/services/surfaceflinger/SurfaceFlinger.cpp中,我们分三段来阅读:

[cpp]viewplaincopy在CODE上查看代码片派生到我的代码片

voidSurfaceFlinger:

:

handleTransactionLocked(

uint32_ttransactionFlags,Vector>&ditchedLayers)

{

constLayerVector¤tLayers(mCurrentState.layersSortedByZ);

constsize_tcount=currentLayers.size();

/*

*Traversalofthechildren

*(performthetransactionforeachofthemifneeded)

*/

constboollayersNeedTransaction=transactionFlags&eTraversalNeeded;

if(layersNeedTransaction){

for(size_ti=0;i

constsp&layer=currentLayers[i];

uint32_ttrFlags=layer->getTransactionFlags(eTransactionNeeded);

if(!

trFlags)continue;

constuint32_tflags=layer->doTransaction(0);

if(flags&Layer:

:

eVisibleRegion)

mVisibleRegionsDirty=true;

}

}

这段代码用来处理应用程序窗口的属性变化。

参数transactionFlags最开始是从SurfaceFlinger类的成员函数threadLoop传进来的。

从前面一文可以知道,SurfaceFlinger类的成员函数threadLoop在调用另外一个成员函数handleTransaction来处理系统显示屏以及应用程序窗口的属性变化之前,首先会调用成员函数getTransactionFlags来检查系统显示屏或者应用程序窗口的属性是否发生了变化。

如果系统显示屏的属性发生了变化,那么传到这里的参数transactionFlags的eTransactionNeeded位就会等于1,而如果有应用程序窗口的属性发生了变化,那么传到这里的参数transactionFlags的eTraversalNeeded位就会等于1。

为了方便描述,我们假设系统显示屏以及应用程序窗口的属性都发生了变化。

SurfaceFlinger类的成员变量mCurrentState指向了一个State对象,用来描述SufaceFlinger服务的当前状态,其中,这个State对象的成员变量layersSortedByZ是一个类型为LayerVector的向量,它里面保存了SufaceFlinger服务当前所需要渲染的应用程序窗口,而这些应用程序窗口都是使用一个LayerBase对象来描述的。

这段代码首先获得SufaceFlinger服务当前所需要渲染的应用程序窗口,接着再通过一个for循环来依次检查每一个应用程序窗口的属性是否发生了变化。

如果某一个应用程序窗口的属性被修改过,那么调用用来描述这个应用程序窗口的一个LayerBase对象的成员函数getTransactionFlags得到的返回值trFlags就不会等于0,在这种情况下,这段代码就会调用这个LayerBase对象的成员函数doTransaction来处理对应的应用程序窗口的属性变化。

在LayerBase类中,有一个类型为int32_t的成员变量mTransactionFlags,每当SurfaceFlinger服务修改某一个应用程序窗口的属性时,都会将与其对应的LayerBase的成员变量mTransactionFlags的相应的位设置为1,这样LayerBase类的成员函数getTransactionFlags就可以通过这个成员变量来判断一个应用程序窗口的属性是否发生变化了。

如果一个应用程序窗口发生的属性变化是可见区域发生了改变,那么对应的LayerBase对象的成员函数doTransaction的返回值flags的Layer:

:

eVisibleRegion位就会等于1。

在这种情况下,这段代码就会将SurfaceFlinger类的成员变量mVisibleRegionsDirty的值设置为true,表示后面要重新计算各个应用程序窗口的可见区域。

为了方便描述,我们假设发生了属性变化的应用程序窗口是一个普通类型的Surface,即用来描述它的实际是一个从LayerBase类继承下来的Layer对象。

在这种情况下,前面实际上调用了Layer类的成员函数doTransaction来处理一个应用程序窗口的属性变化。

在接下来的Step3中,我们再详细分析Layer类的成员函数doTransaction的实现,现在我们接着往下阅读SurfaceFlinger类的成员函数handleTransactionLocked的代码:

[cpp]viewplaincopy在CODE上查看代码片派生到我的代码片

/*

*Performourowntransactionifneeded

*/

if(transactionFlags&eTransactionNeeded){

if(mCurrentState.orientation!

=mDrawingState.orientation){

//theorientationhaschanged,recomputeallvisibleregions

//andinvalidateeverything.

constintdpy=0;

constintorientation=mCurrentState.orientation;

constuint32_ttype=mCurrentState.orientationType;

GraphicPlane&plane(graphicPlane(dpy));

plane.setOrientation(orientation);

//updatethesharedcontrolblock

constDisplayHardware&hw(plane.displayHardware());

volatiledisplay_cblk_t*dcblk=mServerCblk->displays+dpy;

dcblk->orientation=orientation;

dcblk->w=plane.getWidth();

dcblk->h=plane.getHeight();

mVisibleRegionsDirty=true;

mDirtyRegion.set(hw.bounds());

}

if(mCurrentState.freezeDisplay!

=mDrawingState.freezeDisplay){

//freezingorunfreezingthedisplay->triggeranimationifneeded

mFreezeDisplay=mCurrentState.freezeDisplay;

if(mFreezeDisplay)

mFreezeDisplayTime=0;

}

if(currentLayers.size()>mDrawingState.layersSortedByZ.size()){

//layershavebeenadded

mVisibleRegionsDirty=true;

}

//somelayersmighthavebeenremoved,so

//weneedtoupdatetheregionsthey'reexposing.

if(mLayersRemoved){

mLayersRemoved=false;

mVisibleRegionsDirty=true;

constLayerVector&previousLayers(mDrawingState.layersSortedByZ);

constsize_tcount=previousLayers.size();

for(size_ti=0;i

constsp&layer(previousLayers[i]);

if(currentLayers.indexOf(layer)<0){

//thislayerisnotvisibleanymore

ditchedLayers.add(layer);

mDirtyRegionRemovedLayer.orSelf(layer->visibleRegionScreen);

}

}

}

}

这段代码用来处理系统显示屏的属性变化。

在分析这段代码之前,我们首先了解SurfaceFlinger类的另外一个成员变量mDrawingState的含义。

SurfaceFlinger类的成员变量mDrawingState与前面所介绍的成员变量mCurrentState类似,它的类型也为State,不过它是用来描述SufaceFlinger服务的上一次渲染状态的。

通过这两个成员变量的比较,我们就可以知道系统显示屏的哪一个属性发生了变化。

前面提到,当系统显示屏的属性发生了变化,那么参数transactionFlags的eTransactionNeeded位就会等于1,在这种情况,这段代码就需要完成四件事情。

第一件事情是判断系统显示屏的旋转方向是否发生变化。

State类的成员变量orientation用来描述显示屏的方向,因此,当SurfaceFlinger类的成员变量mCurrentState所描述的一个State对象的成员变量orientation的值不等于SurfaceFlinger类的成员变量mDrawingState所描述的一个State对象的成员变量orientation的值时,就说明系统显示屏的旋转方向发生了变化。

在这种情况下,我们就需要将系统显示屏的旋转方向设置为SurfaceFlinger类的成员变量mCurrentState所描述的一个State对象的成员变量orientation的值,这是通过调用编号为0的一个GraphicPlane对象的成员函数setOrientation来实现的。

SurfaceFlinger服务的UI渲染线程在初始化的过程中,除了会初始化硬件帧缓冲区之外,还会创建一个类型为surface_flinger_cblk_t的对象,用来描述系统显示屏的信息,例如大小和旋转方向等,以便其它进程可以通过这个surface_flinger_cblk_t对象来获得系统显示屏的信息。

这个surface_flinger_cblk_t对象就保存在SurfaceFlinger类的成员变量mServerCblk中。

因此,当系统显示屏的旋转方向发生了变化时,我们还需要将变化后的旋转方向保存在SurfaceFlinger类的成员变量mServerCblk所描述的一个surface_flinger_cblk_t对象中。

由于系统显示屏的旋转方向变化一般意味着宽度和高度也会发生变化,因此,我们还需要将旋转发生变化后得到的系统显示屏的宽度和高度值保存在SurfaceFlinger类的成员变量mServerCblk所描述的一个surface_flinger_cblk_t对象中。

系统显示屏的旋转方向同时也意味着我们需要重新计算各个应用程序窗口的可见区域以及重新绘制整个显示屏,因此,在这种情况下,我们还需要将SurfaceFlinger类的成员变量mVisibleRegionsDirty的值设置为true,以及将SurfaceFlinger类的成员变量mDirtyRegion的大小设置为整个显示屏的大小,即将系统UI的脏区域设置为整个显示屏的大小。

第二件事情是判断系统显示屏的冻结状态是否发生变化。

State类的成员变量freezeDisplay用来描述显示屏的冻结状态,因此,当SurfaceFlinger类的成员变量mCurrentState所描述的一个State对象的成员变量freezeDisplay的值不等于SurfaceFlinger类的成员变量mDrawingState所描述的一个State对象的成员变量freezeDisplay的值时,就说明系统显示屏的冻结状态发生了变化。

在这种情况下,我们就需要将SurfaceFlinger类的成员变量mFreezeDisplay的值设置为SurfaceFlinger类的成员变量mCurrentState所描述的一个State对象的成员变量freezeDisplay的值。

如果显示屏的是由解冻状态变化为冻结状态的,那么还需要将显示屏的冻结时间设置为0,即将SurfaceFlinger类的成员变量mFreezeDisplayTime的值设置为0,以便可以将显示屏进入到冻结状态的最长时间设置为一个默认值,这一点可以参考前面一文。

第三件事情是判断是否新增了应用程序窗口。

State类的成员变量layersSortedByZ是一个类型LayerVector的向量,里面保存的是SurfaceFlinger服务在某一个状态下所拥有的应用程序窗口,因此,当SurfaceFlinger类的成员变量mCurrentState所描述的一个State对象的成员变量layersSortedByZ所指向的一个向量的大小值大于SurfaceFlinger类的成员变量mDrawingState所描述的一个State对象的成员变量layersSortedByZ所指向的一个向量的大小值时,就说明系统新增了应用程序窗口。

在这种情况下,我们就需要将SurfaceFlinger类的成员变量mVisibleRegionsDirty的值设置为true,以表示我们需要重新计算各个应用程序窗口的可见区域。

第四件事情是判断是否移除了某些应用程序窗口。

SurfaceFlinger类的成员变量mLayersRemoved用来描述是否有应用程序窗口被移除了。

如果有有应用程序窗口被移除的话,那么这个成员变量的值就会等于true。

在这种情况下,我们就需要是哪些应用程序窗口被移除了。

计算的方法很简单,如果一个应用程序窗口存在于SurfaceFlinger类的成员变量mDrawingState所描述的一个State对象的成员变量layersSortedByZ所指向的一个向量中,但是不存在于SurfaceFlinger类的成员变量mCurrentState所描述的一个State对象的成员变量layersSortedByZ所指向的一个向量中,那么就说明这个应用程序窗口被移除了,因此,就需要将它保存输出参数ditchedLayers所描述的一个向量中,以便可以返回给上一步来处理。

SurfaceFlinger类的成员变量mDirtyRegionRemovedLayer用来描述那些被移除了的应用程序窗口所占用的区域,因此,每当我们移除一个应用程序窗口的时候,都需要将它所占用的区域增加到SurfaceFlinger类的成员变量mDirtyRegionRemovedLayer所描述的一个区域去。

当处理完成那些被移除的应用程序窗口之后,我们就需要将SurfaceFlinger类的成员变量mLayersRemoved的值设置为false,并且将SurfaceFlinger类的成员变量mVisibleRegionsDirty的值设置为true,以表示我们需要重新计算现存的各个应用程序窗口的可见区域。

处理完成系统显示屏的属性变化之后,我们接着向下阅读SurfaceFlinger类的成员函数handleTransactionLocked的最后一行代码:

展开阅读全文
相关资源
猜你喜欢
相关搜索

当前位置:首页 > 医药卫生 > 基础医学

copyright@ 2008-2022 冰豆网网站版权所有

经营许可证编号:鄂ICP备2022015515号-1