SurfaceFlinger事務(wù)處理

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

一泞辐、SurfaceFlinger事務(wù)處理handleTransaction()

這里為什么要用Transaction(事務(wù))這個詞呢腕铸? 我們從數(shù)據(jù)庫事務(wù)概念大致可以看出一點(diǎn)端倪, 它的其中一個很重要的信息就是說"將一組相關(guān)操作組合成一個單元去處理", 這個有點(diǎn)意思惜犀,這個思路也運(yùn)用在了SurfaceFlinger里,為什么呢狠裹?handleTransaction就是處理一次事務(wù)虽界,因?yàn)槊恳粋€Vsync去刷新一次,但是在一個Vsync周期里涛菠,Layer中的屬性可能改變了莉御,由于Layer的屬性有很多,如果改變一個就去觸發(fā)相關(guān)操作俗冻,這樣顯然是浪費(fèi)資源的事情礁叔,所以正確的做法就是當(dāng)Layer屬性的值改變了,然后記錄下來迄薄,最后在 handleTransaction 一次就處理完了琅关。

事務(wù)標(biāo)志位有三種基本類形(可以是多種組合)

enum {
    eTransactionNeeded        = 0x01,  //Layer的屬性發(fā)生變化了,表示需要處理事務(wù)
    eTraversalNeeded          = 0x02,  //遍歷的是SurfaceFlinger中所有的Layer
    eDisplayTransactionNeeded = 0x04,  //這個是顯示器相關(guān)的事務(wù),如顯示器hotplug
    eTransactionMask          = 0x07   //掩碼
};

1.1 SurfaceFlinger中幾個重要變量

  • State mCurrentState
    SurfaceFlinger下一幀的狀態(tài)

  • State mDrawingState
    當(dāng)前正在繪制的狀態(tài)讥蔽,這個是SurfaceFlinger處理完事務(wù)后更新出來的狀態(tài)涣易,是最終的狀態(tài)

  • mVisibleRegionsDirty
    表示當(dāng)前可見區(qū)域是否臟了,如果臟了的話冶伞,比如(layer added/removed, Display added/remove相關(guān))在最后合成的時候會對每個屏幕重建layer stack, 但是一般都為false

struct State {
    LayerVector layersSortedByZ;  //SurfaceFlinger中所有的按照Z order排序的 Layer
    DefaultKeyedVector< wp<IBinder>, DisplayDeviceState> displays;  //外接的顯示屏
};

1.2 handleTransaction

void SurfaceFlinger::handleTransaction(uint32_t transactionFlags)
{
    ATRACE_CALL();

    // here we keep a copy of the drawing state (that is the state that's
    // going to be overwritten by handleTransactionLocked()) outside of
    // mStateLock so that the side-effects of the State assignment
    // don't happen with mStateLock held (which can cause deadlocks).
    //保存 mDrawingState, 但是這里根本沒有使用到
    State drawingState(mDrawingState);

    Mutex::Autolock _l(mStateLock);
    const nsecs_t now = systemTime();
    mDebugInTransaction = now;

    // Here we're guaranteed that some transaction flags are set
    // so we can call handleTransactionLocked() unconditionally.
    // We call getTransactionFlags(), which will also clear the flags,
    // with mStateLock held to guarantee that mCurrentState won't change
    // until the transaction is committed.

    //獲得SurfaceFlinger中的Transaction標(biāo)志位
    transactionFlags = getTransactionFlags(eTransactionMask);
    handleTransactionLocked(transactionFlags); //真正處理事務(wù)的函數(shù)

    mLastTransactionTime = systemTime() - now;
    mDebugInTransaction = 0;
    invalidateHwcGeometry();
    // here the transaction has been committed
}

1.3 handleTransactionLocked

void SurfaceFlinger::handleTransactionLocked(uint32_t transactionFlags)
{
    //獲得當(dāng)前所有Layer
    const LayerVector& currentLayers(mCurrentState.layersSortedByZ);
    const size_t count = currentLayers.size();

    // Notify all layers of available frames
    for (size_t i = 0; i < count; ++i) {
        //檢查當(dāng)前Frame是否是SyncPoint需要的(也就說之前想延遲的Buffer已經(jīng)到來了), 如果是新症,則設(shè)置SyncPoint中mFrameIsAvailable為true
        currentLayers[i]->notifyAvailableFrames();
    }

    /*
     * Traversal of the children
     * (perform the transaction for each of them if needed)
     */
    //遍歷所有的Layer, 讓Layer去執(zhí)行自己的事務(wù)
    if (transactionFlags & eTraversalNeeded) {
        for (size_t i=0 ; i<count ; i++) {
            const sp<Layer>& layer(currentLayers[i]);
            // 獲得Layer的Transaction flags
            uint32_t trFlags = layer->getTransactionFlags(eTransactionNeeded);
            if (!trFlags) continue;
            // Layer處理自己的事務(wù)
            const uint32_t flags = layer->doTransaction(0);
            if (flags & Layer::eVisibleRegion) 
                //如果Layer的可見區(qū)域改變了,則SurfaceFlinger就標(biāo)注出當(dāng)前可視區(qū)域改變了
                mVisibleRegionsDirty = true;
        }
    }

    /*
     * Perform display own transactions if needed
     */
    //跟顯示器相關(guān)的事務(wù)响禽,比如hotplug顯示屏, 初始化/銷除顯示屏徒爹,顯示屏的配置變化,
    if (transactionFlags & eDisplayTransactionNeeded) {
    }

    if (transactionFlags & (eTraversalNeeded|eDisplayTransactionNeeded)) {
        // The transform hint might have changed for some layers
        // (either because a display has changed, or because a layer
        // as changed).
        //
        // Walk through all the layers in currentLayers,
        // and update their transform hint.
        //
        // If a layer is visible only on a single display, then that
        // display is used to calculate the hint, otherwise we use the
        // default display.
        //
        // NOTE: we do this here, rather than in rebuildLayerStacks() so that
        // the hint is set before we acquire a buffer from the surface texture.
        //
        // NOTE: layer transactions have taken place already, so we use their
        // drawing state. However, SurfaceFlinger's own transaction has not
        // happened yet, so we must use the current state layer list
        // (soon to become the drawing state list).
        //
        sp<const DisplayDevice> disp;
        uint32_t currentlayerStack = 0;
        for (size_t i=0; i<count; i++) {
            // NOTE: we rely on the fact that layers are sorted by
            // layerStack first (so we don't have to traverse the list
            // of displays for every layer).
            const sp<Layer>& layer(currentLayers[i]);
            //獲得Layer的 layer stack
            uint32_t layerStack = layer->getDrawingState().layerStack;
            
            //通過遍歷所有的Display來找到Layer所在的顯示屏
            if (i==0 || currentlayerStack != layerStack) {
                currentlayerStack = layerStack;
                // figure out if this layerstack is mirrored
                // (more than one display) if so, pick the default display,
                // if not, pick the only display it's on.
                disp.clear();
                for (size_t dpy=0 ; dpy<mDisplays.size() ; dpy++) {
                    sp<const DisplayDevice> hw(mDisplays[dpy]);
                    if (hw->getLayerStack() == currentlayerStack) {
                        if (disp == NULL) {
                            disp = hw;
                        } else {
                            disp = NULL;
                            break;
                        }
                    }
                }
            }
            if (disp == NULL) {
                // NOTE: TEMPORARY FIX ONLY. Real fix should cause layers to
                // redraw after transform hint changes. See bug 8508397.

                // could be null when this layer is using a layerStack
                // that is not visible on any display. Also can occur at
                // screen off/on times.
                disp = getDefaultDisplayDevice();
            }
            //更新Layer的旋轉(zhuǎn)方向芋类,最終會體現(xiàn)在 BufferQueueCore中的mTransformHint變量
            layer->updateTransformHint(disp);
        }
    }

    /*
     * Perform our own transaction if needed
     */
    //前面都是執(zhí)行的Layer相關(guān)的事務(wù)
    //下面就是執(zhí)行SurfaceFlinger自己的事務(wù)
    const LayerVector& layers(mDrawingState.layersSortedByZ);
    if (currentLayers.size() > layers.size()) {
        // layers have been added , 有新的Layer加入
        mVisibleRegionsDirty = true;
    }

    // some layers might have been removed, so
    // we need to update the regions they're exposing.
    //下面有Layer移出了的情況
    if (mLayersRemoved) {
        mLayersRemoved = false;
        mVisibleRegionsDirty = true;
        const size_t count = layers.size();
        for (size_t i=0 ; i<count ; i++) {
            const sp<Layer>& layer(layers[i]);
            if (currentLayers.indexOf(layer) < 0) {
                // this layer is not visible anymore
                // TODO: we could traverse the tree from front to back and
                //       compute the actual visible region
                // TODO: we could cache the transformed region
                const Layer::State& s(layer->getDrawingState());
                //獲得移除的Layer的可見區(qū)域, 這塊可見區(qū)域就是dirty的
                Region visibleReg = s.active.transform.transform(
                        Region(Rect(s.active.w, s.active.h)));
                //找到被移除掉的Layer所在的Display, 然后更新Diplay的dirty 區(qū)域隆嗅,也就是對region做或運(yùn)算
                invalidateLayerStack(s.layerStack, visibleReg);
            }
        }
    }

    //提交事務(wù)
    commitTransaction();
    //更新Display中光標(biāo)的位置
    updateCursorAsync();
}

1.4 commitTransaction

void SurfaceFlinger::commitTransaction()
{
    //mLayersPendingRemoval是保存的是pending 著需要移除的Layer. 比如APP調(diào)用destroySurface
    if (!mLayersPendingRemoval.isEmpty()) { 
        // Notify removed layers now that they can't be drawn from
        for (size_t i = 0; i < mLayersPendingRemoval.size(); i++) {
            mLayersPendingRemoval[i]->onRemoved(); //回調(diào) onRemoved, 調(diào)用Consumer的consumerDisconnect侯繁,清理BufferQueueBuffer
        }    
        mLayersPendingRemoval.clear();
    }    

    // If this transaction is part of a window animation then the next frame
    // we composite should be considered an animation as well.
    mAnimCompositionPending = mAnimTransactionPending;
    //更新 mDrawingState
    mDrawingState = mCurrentState;
    mTransactionPending = false;
    mAnimTransactionPending = false;
    //釋放mTransactionCV, 如果SurfaceFlinger正在處理事務(wù)榛瓮,而這時如果調(diào)用setTransactionState就可能會一直等著mTransactionCV, 
    //因?yàn)閟etTransactionState可能會改變SurfaceFlinger的Transaction標(biāo)志位,導(dǎo)致前后不一致
    mTransactionCV.broadcast();
}

二巫击、Layer處理自己的事務(wù)

2.1 Layer中重要變量

  • sp<NativeHandle> mSidebandStream; //sideband buffer stream

  • std::list<std::shared_ptr<SyncPoint>> mLocalSyncPoints;
    //一系列的SyncPoint, 這些SyncPoint是在特定的Frame來了才更新

  • State mCurrentState;
    表示Layer下一幀的屬性狀態(tài)禀晓,當(dāng)某個屬性變化時,直接操作該變量

  • State mDrawingState;
    表示當(dāng)前正在繪制的幀的屬性狀態(tài)坝锰。Layer處理完事務(wù)后粹懒,最終的用于繪制的狀態(tài)

struct State {
    Geometry active;  //當(dāng)前Layer的可見區(qū)域
    Geometry requested; //請求的Layer的可見區(qū)域, 在Layer做doTransaction時會將 requested賦值給active. setSize/setMatrix/setPosition
    uint32_t z;
    uint32_t layerStack; //layerStack指明當(dāng)前Layer屬于哪個Display,Display的layer stack可以用 hw->getLayerStack獲得
    uint8_t alpha;
    uint8_t flags;
    uint8_t mask;
    uint8_t reserved[2];
    int32_t sequence; //當(dāng)Layer的屬性變化時顷级, sequence就會加1
    bool modified;  //當(dāng)Layer的屬性變化了凫乖,該變量就會被置為true

    Rect crop;  
    Rect finalCrop; 
    // If set, defers this state update until the Layer identified by handle
    // receives a frame with the given frameNumber
    sp<IBinder> handle; //延遲更新特定的Frame
    uint64_t frameNumber; //這個就是Handle要延遲的Frame號

    // the transparentRegion hint is a bit special, it's latched only
    // when we receive a buffer -- this is because it's "content"
    // dependent.
    Region activeTransparentRegion;
    Region requestedTransparentRegion;
};

struct Geometry {
    uint32_t w;
    uint32_t h;
    Transform transform; //Geometry的傳輸矩陣
};

2.2 doTransaction

// Layer處理的事務(wù)
uint32_t Layer::doTransaction(uint32_t flags) {
    ATRACE_CALL();

    pushPendingState(); //將mCurrentState保存到mPendingStates中 
  //獲得Layer的mCurrentState, 這里為什么不直接用mCurrentState呢?是因?yàn)榉乐筸CurrentState在處理的時候被其它線程給改變了
    Layer::State c = getCurrentState(); 
    if (!applyPendingStates(&c)) { //針對 SyncPoints相關(guān)
        return 0;
    }    

    //獲得上一次的Drawing state
    const Layer::State& s(getDrawingState());

    //如果requested的可見區(qū)域與舊的可見區(qū)域不同了,則size changed
    const bool sizeChanged = (c.requested.w != s.requested.w) ||
                             (c.requested.h != s.requested.h);

    if (sizeChanged) {
        // 如果size changed, 把新的 w|h 設(shè)置到 BufferQueueCore中的 mDefaultWidth|mDefaultHeight中去
        mSurfaceFlingerConsumer->setDefaultBufferSize(
                c.requested.w, c.requested.h);
    }

    //如果新的請求的 w|h 與新的原本要顯示的區(qū)域不同帽芽,表明是  resize了
    const bool resizePending = (c.requested.w != c.active.w) ||
            (c.requested.h != c.active.h);
    if (!isFixedSize()) {
        if (resizePending && mSidebandStream == NULL) {
            //resize只發(fā)生在非固定尺寸模式删掀,并且sideband layer(sideband buffer stream)為空的情況
            // don't let Layer::doTransaction update the drawing state
            // if we have a pending resize, unless we are in fixed-size mode.
            // the drawing state will be updated only once we receive a buffer
            // with the correct size.
            //
            // in particular, we want to make sure the clip (which is part
            // of the geometry state) is latched together with the size but is
            // latched immediately when no resizing is involved.
            //
            // If a sideband stream is attached, however, we want to skip this
            // optimization so that transactions aren't missed when a buffer
            // never arrives

            flags |= eDontUpdateGeometryState;
        }
    }

    // always set active to requested, unless we're asked not to
    // this is used by Layer, which special cases resizes.
    if (flags & eDontUpdateGeometryState)  { //這個是在resize里面做的,
    } else {
        //這里是允許更新 可見區(qū)域
        Layer::State& editCurrentState(getCurrentState());
        if (mFreezePositionUpdates) {
            float tx = c.active.transform.tx();
            float ty = c.active.transform.ty();
            c.active = c.requested;
            c.active.transform.set(tx, ty);
            editCurrentState.active = c.active;
        } else {
            editCurrentState.active = editCurrentState.requested;
            c.active = c.requested;
        }
    }

    if (s.active != c.active) {
        // invalidate and recompute the visible regions if needed
        flags |= Layer::eVisibleRegion;
    }

    // 只要Layer有屬性發(fā)生變化了导街,sequence就會加1,這樣可以很直觀判斷是否當(dāng)前的state和舊的state是否發(fā)生變化了
    // 但是這樣并不能保證sequence相同披泪,但是屬性變化的這種情況
    if (c.sequence != s.sequence) {
        // invalidate and recompute the visible regions if needed
        flags |= eVisibleRegion;
        this->contentDirty = true;

        // we may use linear filtering, if the matrix scales us
        const uint8_t type = c.active.transform.getType();
        mNeedsFiltering = (!c.active.transform.preserveRects() ||
                (type >= Transform::SCALE));
    }

    // If the layer is hidden, signal and clear out all local sync points so
    // that transactions for layers depending on this layer's frames becoming
    // visible are not blocked
    //是否Layer是hide的
    if (c.flags & layer_state_t::eLayerHidden) {
        Mutex::Autolock lock(mLocalSyncPointMutex);
        for (auto& point : mLocalSyncPoints) {
            point->setFrameAvailable();
        }
        mLocalSyncPoints.clear();
    }

    // Commit the transaction
    //提交事務(wù)
    commitTransaction(c);
    return flags;
}  

2.3 pushPendingState

void Layer::pushPendingState() {
    //只要Layer的屬性改變了,都會將modified置為true
    if (!mCurrentState.modified) {
        return;
    }
    
    // If this transaction is waiting on the receipt of a frame, generate a sync
    // point and send it to the remote layer.
    if (mCurrentState.handle != nullptr) { //表示當(dāng)前需要等著特定的frame(frame number號標(biāo)識)
        sp<Handle> handle = static_cast<Handle*>(mCurrentState.handle.get());
        sp<Layer> handleLayer = handle->owner.promote();
        if (handleLayer == nullptr) { 
            ALOGE("[%s] Unable to promote Layer handle", mName.string());
            // If we can't promote the layer we are intended to wait on,
            // then it is expired or otherwise invalid. Allow this transaction
            // to be applied as per normal (no synchronization).
            mCurrentState.handle = nullptr;
        } else {
            //創(chuàng)建一個 SyncPoint搬瑰, 表示只在 frameNumber的這個Frame才更新 
            auto syncPoint = std::make_shared<SyncPoint>(
                    mCurrentState.frameNumber);
            if (handleLayer->addSyncPoint(syncPoint)) { //加入到 mLocalSyncPoints
                mRemoteSyncPoints.push_back(std::move(syncPoint));
            } else {
                // We already missed the frame we're supposed to synchronize
                // on, so go ahead and apply the state update
                mCurrentState.handle = nullptr;
            }
        }

        // Wake us up to check if the frame has been received
        setTransactionFlags(eTransactionNeeded);
    }
    //將當(dāng)前的狀態(tài)保存在mPendingStates, 接下來會處理到
    mPendingStates.push_back(mCurrentState);
}

//提交事務(wù)款票, 也就是更新 Layer的 mDrawingState
void Layer::commitTransaction(const State& stateToCommit) {
    mDrawingState = stateToCommit;
}
最后編輯于
?著作權(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)我...
    茶點(diǎn)故事閱讀 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
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡飒责,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 37,550評論 2 333
  • 正文 我和宋清朗相戀三年赘娄,在試婚紗的時候發(fā)現(xiàn)自己被綠了。 大學(xué)時的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片宏蛉。...
    茶點(diǎn)故事閱讀 39,727評論 1 348
  • 序言:一個原本活蹦亂跳的男人離奇死亡遣臼,死狀恐怖,靈堂內(nèi)的尸體忽然破棺而出拾并,到底是詐尸還是另有隱情揍堰,我是刑警寧澤,帶...
    沈念sama閱讀 35,428評論 5 343
  • 正文 年R本政府宣布嗅义,位于F島的核電站屏歹,受9級特大地震影響,放射性物質(zhì)發(fā)生泄漏之碗。R本人自食惡果不足惜蝙眶,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 41,022評論 3 326
  • 文/蒙蒙 一、第九天 我趴在偏房一處隱蔽的房頂上張望褪那。 院中可真熱鬧幽纷,春花似錦、人聲如沸博敬。這莊子的主人今日做“春日...
    開封第一講書人閱讀 31,672評論 0 22
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽冶忱。三九已至尾菇,卻和暖如春境析,著一層夾襖步出監(jiān)牢的瞬間,已是汗流浹背派诬。 一陣腳步聲響...
    開封第一講書人閱讀 32,826評論 1 269
  • 我被黑心中介騙來泰國打工劳淆, 沒想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留,地道東北人默赂。 一個月前我還...
    沈念sama閱讀 47,734評論 2 368
  • 正文 我出身青樓沛鸵,卻偏偏與公主長得像,于是被迫代替她去往敵國和親缆八。 傳聞我的和親對象是個殘疾皇子曲掰,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 44,619評論 2 354

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