天天看點

07.顯示系統:第005課_Vsync機制:第007節_rebuildLayerStacks源碼分析

通過前面小節的講解我們知道,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();
           

以上函數都做了哪些工作呢?下面是一個草圖:

07.顯示系統:第005課_Vsync機制:第007節_rebuildLayerStacks源碼分析

我們猜測一下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,如下體所示:

07.顯示系統:第005課_Vsync機制:第007節_rebuildLayerStacks源碼分析

在最上面的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;
}
           

代碼注釋比較詳細,有興趣的同學可以分析一下。

繼續閱讀