您当前的位置: 首页 >  ui

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

发布时间:2019-04-08 15:56:03 ,浏览量:6

通过前面小节的讲解我们知道,surfaceflinger在接收到Vsync信号之后,会执行一系列的函数,这些函数做了哪些事情呢?在之前提到SurfaceFlinger.cpp中:

void SurfaceFlinger::onMessageReceived(int32_t what) { case MessageQueue::INVALIDATE: { /*处理事务,实际大部分做了一些标志位的操作*/ bool refreshNeeded = handleMessageTransaction(); /*切换各个层的buffer*/ refreshNeeded |= handleMessageInvalidate(); /*发出一个界面更新的信号,最终导致handleMessageRefresh被调用*/ refreshNeeded |= mRepaintEverything; case MessageQueue::REFRESH: { handleMessageRefresh(); 

以上函数都做了哪些工作呢?下面是一个草图: 在这里插入图片描述 我们猜测一下handleMessageRefresh函数会做什么事情。在android系统中存在对个应用程序,每个程序都有有一个Layer,这些Layer从上到下,一层层的排放,上面的层会挡住下面的。那么handleMessageRefresh会去算出每个层的可视区域,最终在他他们合并显示出来。如下图:

主要工作如下: 1.计算各个Layer的显示区域 2.合成显示:a(软件).使用openGL把各个Layer的可视区域在一个内存上描绘出来。b(硬件).使用HWcomposer合成 下面我们查看handleMessageRefresh:

void SurfaceFlinger::handleMessageRefresh() { /*做一些预先的处理*/ preComposition(); /*计算各个层的可视区域。对每个屏幕构建可视的Layer*/ rebuildLayerStacks(); setUpHWComposer(); doDebugFlashRegions(); doComposition(); postComposition(refreshStartTime); 

首先我们来看看preComposition

preComposition
void SurfaceFlinger::preComposition() /*在Layer.cpp中实现*/ onPreComposition() /*如果有多个buffer需要处理返回true*/ return mQueuedFrames > 0 || mSidebandStreamChanged || mAutoRefresh; needExtraInvalidate = true; signalLayerUpdate(); 
rebuildLayerStacks
void SurfaceFlinger::rebuildLayerStacks() { // rebuild the visible layer list per screen /*对每个显示器质性for中代码*/ for (size_t dpy=0 ; dpy<mDisplays.size() ; dpy++) { /*如果显示器是打开的状态*/ if (hw->isDisplayOn()) { /*计算可视区域*/ SurfaceFlinger::computeVisibleRegions(layers,hw->getLayerStack(), dirtyRegion, opaqueRegion); 

假设有多个APP,如下体所示: 在这里插入图片描述 在最上面的APP可以完全显示,下面的APP会被遮挡一部分。怎么计算各个Layer的可视区域了? 1.从Z轴最大的层开始计算, 2.Z轴小的Layer会被他上面的Layer遮盖 下面我们使用一个例子来讲解这些代码: 假设有3个层:

void SurfaceFlinger::computeVisibleRegions( const LayerVector& currentLayers, uint32_t layerStack, Region& outDirtyRegion, Region& outOpaqueRegion) { ATRACE_CALL(); /*在当前层之上的不透明区域*/ Region aboveOpaqueLayers; /*当前层之前的被遮盖的区域:.opaque+transucent,当前层之上各层课时区域*/ Region aboveCoveredLayers; /**/ Region dirty; outDirtyRegion.clear(); /*当前需要合成的Layer层数*/ size_t i = currentLayers.size(); while (i--) { /*从Z轴最大的那一层开始处理*/ const sp<Layer>& layer = currentLayers[i]; // start with the whole surface at its current location const Layer::State& s(layer->getDrawingState()); // only consider the layers on the given layer stack if (s.layerStack != layerStack) continue; /*
         * opaqueRegion: area of a surface that is fully opaque.
         */ Region opaqueRegion; /*
         * visibleRegion: area of a surface that is visible on screen
         * and not fully transparent. This is essentially the layer's
         * footprint minus the opaque regions above it.
         * Areas covered by a translucent surface are considered visible.
         */ Region visibleRegion; /*
         * coveredRegion: area of a surface that is covered by all
         * visible regions above it (which includes the translucent areas).
         */ Region coveredRegion; /*
         * transparentRegion: area of a surface that is hinted to be completely
         * transparent. This is only used to tell when the layer has no visible
         * non-transparent regions and can be removed from the layer list. It
         * does not affect the visibleRegion of this layer or any layers
         * beneath it. The hint may not be correct if apps don't respect the
         * SurfaceView restrictions (which, sadly, some don't).
         */ Region transparentRegion; // handle hidden surfaces by setting the visible region to empty if (CC_LIKELY(layer->isVisible())) { const bool translucent = !layer->isOpaque(s); Rect bounds(s.active.transform.transform(layer->computeBounds())); visibleRegion.set(bounds); if (!visibleRegion.isEmpty()) { // Remove the transparent area from the visible region if (translucent) { const Transform tr(s.active.transform); if (tr.preserveRects()) { // transform the transparent region transparentRegion = tr.transform(s.activeTransparentRegion); } else { // transformation too complex, can't do the // transparent region optimization. transparentRegion.clear(); } } // compute the opaque region const int32_t layerOrientation = s.active.transform.getOrientation(); if (s.alpha==255 && !translucent && ((layerOrientation & Transform::ROT_INVALID) == false)) { // the opaque region is the layer's footprint opaqueRegion = visibleRegion; } } } // Clip the covered region to the visible region coveredRegion = aboveCoveredLayers.intersect(visibleRegion); // Update aboveCoveredLayers for next (lower) layer aboveCoveredLayers.orSelf(visibleRegion); // subtract the opaque region covered by the layers above us visibleRegion.subtractSelf(aboveOpaqueLayers); // compute this layer's dirty region if (layer->contentDirty) { // we need to invalidate the whole region dirty = visibleRegion; // as well, as the old visible region dirty.orSelf(layer->visibleRegion); layer->contentDirty = false; } else { /* compute the exposed region:
             *   the exposed region consists of two components:
             *   1) what's VISIBLE now and was COVERED before
             *   2) what's EXPOSED now less what was EXPOSED before
             *
             * note that (1) is conservative, we start with the whole
             * visible region but only keep what used to be covered by
             * something -- which mean it may have been exposed.
             *
             * (2) handles areas that were not covered by anything but got
             * exposed because of a resize.
             */ const Region newExposed = visibleRegion - coveredRegion; const Region oldVisibleRegion = layer->visibleRegion; const Region oldCoveredRegion = layer->coveredRegion; const Region oldExposed = oldVisibleRegion - oldCoveredRegion; dirty = (visibleRegion&oldCoveredRegion) | (newExposed-oldExposed); } dirty.subtractSelf(aboveOpaqueLayers); // accumulate to the screen dirty region outDirtyRegion.orSelf(dirty); // Update aboveOpaqueLayers for next (lower) layer aboveOpaqueLayers.orSelf(opaqueRegion); // Store the visible region in screen space layer->setVisibleRegion(visibleRegion); layer->setCoveredRegion(coveredRegion); layer->setVisibleNonTransparentRegion( visibleRegion.subtract(transparentRegion)); } outOpaqueRegion = aboveOpaqueLayers; } 

代码注释比较详细,有兴趣的同学可以分析一下。

关注
打赏
1688896170
查看更多评论

暂无认证

  • 6浏览

    0关注

    115984博文

    0收益

  • 0浏览

    0点赞

    0打赏

    0留言

私信
关注
热门博文
立即登录/注册

微信扫码登录

0.0805s