SurfaceFlinger之Refresh

本內(nèi)容基于自己對于代碼的理解以及網(wǎng)上大牛的博客參考寫的,作為回顧時的參考之用。

SurfaceFlinger在經(jīng)過事務(wù)處理以及Page Flip之后,所有的數(shù)據(jù)都準(zhǔn)備好,最后一步就是把內(nèi)容刷新到屏幕上署咽。

1. handleMessageRefresh

void SurfaceFlinger::handleMessageRefresh() {
    ATRACE_CALL();

#ifdef ENABLE_FENCE_TRACKING
    nsecs_t refreshStartTime = systemTime(SYSTEM_TIME_MONOTONIC);
#else
    nsecs_t refreshStartTime = 0; 
#endif
    static nsecs_t previousExpectedPresent = 0; 
    nsecs_t expectedPresent = mPrimaryDispSync.computeNextRefresh(0);
    static bool previousFrameMissed = false;
    bool frameMissed = (expectedPresent == previousExpectedPresent);
    if (frameMissed != previousFrameMissed) {
        ATRACE_INT("FrameMissed", static_cast<int>(frameMissed));
    }    
    previousFrameMissed = frameMissed;

    if (CC_UNLIKELY(mDropMissedFrames && frameMissed)) {
        // Latch buffers, but don't send anything to HWC, then signal another
        // wakeup for the next vsync
        preComposition();
        repaintEverything();
    } else {
        preComposition();
        rebuildLayerStacks();
        //setUpHWComposer先會遍歷各個設(shè)備DisplayDevice,然后根據(jù)可見layer數(shù)量嗜价,調(diào)用createWorkList創(chuàng)建hwc_layer_list_t列表艇抠,
        //然后在每個設(shè)備上遍歷可見layer,將layer的mActiveBuffer設(shè)置到HWComposer中去久锥,最后調(diào)用了HWComposer的prepare函數(shù)家淤。
        setUpHWComposer();
        doDebugFlashRegions();
        //合成所有層的圖像, 經(jīng)過這一步后,就顯示新的內(nèi)容了瑟由。
        doComposition();
        postComposition(refreshStartTime);
    }    

    previousExpectedPresent = mPrimaryDispSync.computeNextRefresh(0);
}

setUpHWComposer 參考Android6.0 圖像合成過程詳解(一) setUpHWComposer函數(shù)

doComposition請Android6.0 圖像合成過程詳解(二) doComposition函數(shù)

2. preComposition

void SurfaceFlinger::preComposition()
{
    mPowerHintThread->requestPowerHint(); //電源管理相關(guān)

    bool needExtraInvalidate = false;
    const LayerVector& layers(mDrawingState.layersSortedByZ);
    const size_t count = layers.size();
    for (size_t i=0 ; i<count ; i++) {
        if (layers[i]->onPreComposition()) { //調(diào)用Layer的 onPreComposition
            needExtraInvalidate = true;
        }
    }
    if (needExtraInvalidate) {
        signalLayerUpdate(); //如果需要invalidate的話絮重,觸發(fā)下一個VSYNC
    }
}
  • Layer.cpp
bool Layer::onPreComposition() {
    mRefreshPending = false;
    //自動刷新或還有QUEUED的Frame, 以及設(shè)置了side band
    return mQueuedFrames > 0 || mSidebandStreamChanged || mAutoRefresh; 
}

3. rebuildLayerStacks

void SurfaceFlinger::rebuildLayerStacks() {
    // rebuild the visible layer list per screen
    if (CC_UNLIKELY(mVisibleRegionsDirty)) { //重建屏幕的Layer Stack
        ATRACE_CALL();
        mVisibleRegionsDirty = false;
        invalidateHwcGeometry();

        const LayerVector& layers(mDrawingState.layersSortedByZ);
        for (size_t dpy=0 ; dpy<mDisplays.size() ; dpy++) {
            Region opaqueRegion;
            Region dirtyRegion;
            Vector< sp<Layer> > layersSortedByZ;
            const sp<DisplayDevice>& hw(mDisplays[dpy]);
            const Transform& tr(hw->getTransform());
            const Rect bounds(hw->getBounds());
            if (hw->isDisplayOn()) {
                //對該DISPLAY的所有Layer計算可視化區(qū)域
                SurfaceFlinger::computeVisibleRegions(layers,
                        hw->getLayerStack(), dirtyRegion, opaqueRegion);

                const size_t count = layers.size();
                for (size_t i=0 ; i<count ; i++) {
                    const sp<Layer>& layer(layers[i]);
                    const Layer::State& s(layer->getDrawingState());
                    if (s.layerStack == hw->getLayerStack()) {
                        Region drawRegion(tr.transform(
                                layer->visibleNonTransparentRegion));
                        drawRegion.andSelf(bounds);
                        if (!drawRegion.isEmpty()) {
                            layersSortedByZ.add(layer);
                        }
                    }
                }
            }
            //設(shè)置 on-screen上的變量, layers,  dirty區(qū)域
            hw->setVisibleLayersSortedByZ(layersSortedByZ);
            hw->undefinedRegion.set(bounds); //整個屏幕size
            hw->undefinedRegion.subtractSelf(tr.transform(opaqueRegion)); //這個沒有內(nèi)容的區(qū)域歹苦,一般就是黑色區(qū)域了
            hw->dirtyRegion.orSelf(dirtyRegion); //dirty 區(qū)域
        }
    }
}

4. computeVisibleRegions

計算該Display上的可視區(qū)域
void SurfaceFlinger::computeVisibleRegions(
        const LayerVector& currentLayers, uint32_t layerStack,
        Region& outDirtyRegion, Region& outOpaqueRegion)
{
    ATRACE_CALL();

    //
    Region aboveOpaqueLayers;
    //
    Region aboveCoveredLayers;
    Region dirty;

    outDirtyRegion.clear();

    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
        //只考慮一個DISPLAY device上所有的Layer
        if (s.layerStack != layerStack)
            continue;

        /*
         * opaqueRegion: area of a surface that is fully opaque.
         */
        Region opaqueRegion; //具體一層Layer的完全不透明區(qū)域

        /*
         * 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;  //具體一層Layer的可見區(qū)域

        /*
         * coveredRegion: area of a surface that is covered by all
         * visible regions above it (which includes the translucent areas).
         */
        Region coveredRegion;//具體一層Layer的被覆蓋的區(qū)域

        /*
         * 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; //具體一層的透明區(qū)域


        // handle hidden surfaces by setting the visible region to empty
        if (CC_LIKELY(layer->isVisible())) {
            //是否是半透明狀態(tài)
            const bool translucent = !layer->isOpaque(s);
            //計算Layer的可視區(qū)域
            Rect bounds(s.active.transform.transform(layer->computeBounds()));
            // 具體一層Layer的初始化可視區(qū)域
            visibleRegion.set(bounds);
            if (!visibleRegion.isEmpty()) {//如果該Layer層可視區(qū)域不為空
                // Remove the transparent area from the visible region
                if (translucent) { //如果是半透明的區(qū)域, 計算透明區(qū)域大小
                    const Transform tr(s.active.transform);
                    if (tr.preserveRects()) { //如果矩陣是一些常規(guī)矩陣,比如平移殴瘦、縮放狠角、旋轉(zhuǎn)這些
                        // transform the transparent region
                        //獲得透明的區(qū)域
                        transparentRegion = tr.transform(s.activeTransparentRegion);
                    } else {
                        //矩陣變換太復(fù)雜,不用優(yōu)化了. 囧 ...
                        // 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; //完全不透明的區(qū)域
                }
            }
        }

        // Clip the covered region to the visible region
        // 當(dāng)前區(qū)域被前面的Layer覆蓋的區(qū)域 
        coveredRegion = aboveCoveredLayers.intersect(visibleRegion);

        // Update aboveCoveredLayers for next (lower) layer
        //之前的Layer和自己所占的總的區(qū)域蚪腋,相對于下一個Layer,就是已經(jīng)覆蓋的總區(qū)域
        aboveCoveredLayers.orSelf(visibleRegion);

        // subtract the opaque region covered by the layers above us
        //除了之前的Layer覆蓋的區(qū)域外丰歌,我這層Layer還剩多少可視區(qū)域
        visibleRegion.subtractSelf(aboveOpaqueLayers);

        // compute this layer's dirty region
        if (layer->contentDirty) { //這個值在 Layer的doTransaction中可能為True, 當(dāng)新舊的sequence不一致時
            // we need to invalidate the whole region
            dirty = visibleRegion;  // invalidate整個區(qū)域
            // as well, as the old visible region
            dirty.orSelf(layer->visibleRegion); //整個Dirty的區(qū)域要加上上一個可視區(qū)域,這個在之前有講屉凯,自己想一下為什么
            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區(qū)域
            dirty = (visibleRegion&oldCoveredRegion) | (newExposed-oldExposed);
        }
        //Layer的區(qū)域減掉上層Layer的覆蓋的區(qū)域
        dirty.subtractSelf(aboveOpaqueLayers);

        // accumulate to the screen dirty region
        //outDirtyRegion是整個屏幕的臟區(qū)域立帖,這個肯定是累加的
        outDirtyRegion.orSelf(dirty);

        // Update aboveOpaqueLayers for next (lower) layer
        aboveOpaqueLayers.orSelf(opaqueRegion);

        // Store the visible region in screen space
        // 保存到這些區(qū)域到 Layer中,以便下一次合成使用
        layer->setVisibleRegion(visibleRegion);
        layer->setCoveredRegion(coveredRegion);
        layer->setVisibleNonTransparentRegion(
                visibleRegion.subtract(transparentRegion));
    }
    //完全不透明的區(qū)域
    outOpaqueRegion = aboveOpaqueLayers;
}
最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
  • 序言:七十年代末悠砚,一起剝皮案震驚了整個濱河市晓勇,隨后出現(xiàn)的幾起案子,更是在濱河造成了極大的恐慌,老刑警劉巖绑咱,帶你破解...
    沈念sama閱讀 216,591評論 6 501
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件绰筛,死亡現(xiàn)場離奇詭異,居然都是意外死亡描融,警方通過查閱死者的電腦和手機(jī)别智,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 92,448評論 3 392
  • 文/潘曉璐 我一進(jìn)店門,熙熙樓的掌柜王于貴愁眉苦臉地迎上來稼稿,“玉大人,你說我怎么就攤上這事讳窟∪眉撸” “怎么了?”我有些...
    開封第一講書人閱讀 162,823評論 0 353
  • 文/不壞的土叔 我叫張陵丽啡,是天一觀的道長谋右。 經(jīng)常有香客問我,道長补箍,這世上最難降的妖魔是什么改执? 我笑而不...
    開封第一講書人閱讀 58,204評論 1 292
  • 正文 為了忘掉前任,我火速辦了婚禮坑雅,結(jié)果婚禮上辈挂,老公的妹妹穿的比我還像新娘。我一直安慰自己裹粤,他們只是感情好终蒂,可當(dāng)我...
    茶點故事閱讀 67,228評論 6 388
  • 文/花漫 我一把揭開白布。 她就那樣靜靜地躺著遥诉,像睡著了一般拇泣。 火紅的嫁衣襯著肌膚如雪。 梳的紋絲不亂的頭發(fā)上矮锈,一...
    開封第一講書人閱讀 51,190評論 1 299
  • 那天霉翔,我揣著相機(jī)與錄音,去河邊找鬼苞笨。 笑死债朵,一個胖子當(dāng)著我的面吹牛,可吹牛的內(nèi)容都是我干的猫缭。 我是一名探鬼主播葱弟,決...
    沈念sama閱讀 40,078評論 3 418
  • 文/蒼蘭香墨 我猛地睜開眼,長吁一口氣:“原來是場噩夢啊……” “哼猜丹!你這毒婦竟也來了芝加?” 一聲冷哼從身側(cè)響起,我...
    開封第一講書人閱讀 38,923評論 0 274
  • 序言:老撾萬榮一對情侶失蹤,失蹤者是張志新(化名)和其女友劉穎藏杖,沒想到半個月后将塑,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體,經(jīng)...
    沈念sama閱讀 45,334評論 1 310
  • 正文 獨居荒郊野嶺守林人離奇死亡蝌麸,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點故事閱讀 37,550評論 2 333
  • 正文 我和宋清朗相戀三年点寥,在試婚紗的時候發(fā)現(xiàn)自己被綠了。 大學(xué)時的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片来吩。...
    茶點故事閱讀 39,727評論 1 348
  • 序言:一個原本活蹦亂跳的男人離奇死亡敢辩,死狀恐怖,靈堂內(nèi)的尸體忽然破棺而出弟疆,到底是詐尸還是另有隱情戚长,我是刑警寧澤,帶...
    沈念sama閱讀 35,428評論 5 343
  • 正文 年R本政府宣布怠苔,位于F島的核電站同廉,受9級特大地震影響,放射性物質(zhì)發(fā)生泄漏柑司。R本人自食惡果不足惜迫肖,卻給世界環(huán)境...
    茶點故事閱讀 41,022評論 3 326
  • 文/蒙蒙 一、第九天 我趴在偏房一處隱蔽的房頂上張望攒驰。 院中可真熱鬧蟆湖,春花似錦、人聲如沸玻粪。這莊子的主人今日做“春日...
    開封第一講書人閱讀 31,672評論 0 22
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽奶段。三九已至饥瓷,卻和暖如春,著一層夾襖步出監(jiān)牢的瞬間痹籍,已是汗流浹背呢铆。 一陣腳步聲響...
    開封第一講書人閱讀 32,826評論 1 269
  • 我被黑心中介騙來泰國打工, 沒想到剛下飛機(jī)就差點兒被人妖公主榨干…… 1. 我叫王不留蹲缠,地道東北人棺克。 一個月前我還...
    沈念sama閱讀 47,734評論 2 368
  • 正文 我出身青樓,卻偏偏與公主長得像线定,于是被迫代替她去往敵國和親娜谊。 傳聞我的和親對象是個殘疾皇子,可洞房花燭夜當(dāng)晚...
    茶點故事閱讀 44,619評論 2 354

推薦閱讀更多精彩內(nèi)容