SurfaceFlinger合成二

onMessageInvalidate过程

/frameworks/native/services/surfaceflinger/SurfaceFlinger.cpp
void SurfaceFlinger::onMessageInvalidate(nsecs_t expectedVSyncTime) {
......
bool refreshNeeded;//@1
{
        ConditionalLockGuard<std::mutex> lock(mTracingLock, mTracingEnabled);

        refreshNeeded = handleMessageTransaction();//@2
        refreshNeeded |= handleMessageInvalidate();//@3
        if (mTracingEnabled) {
            mAddCompositionStateToTrace =
                    mTracing.flagIsSetLocked(SurfaceTracing::TRACE_COMPOSITION);
            if (mVisibleRegionsDirty && !mAddCompositionStateToTrace) {
                mTracing.notifyLocked("visibleRegionsDirty");
            }
        }
    }
......

    refreshNeeded |= mRepaintEverything; //@4
    if (refreshNeeded && CC_LIKELY(mBootStage != BootStage::BOOTLOADER)) { //@5
        mLastJankDuration = jankDurationToUpload;
        // Signal a refresh if a transaction modified the window state,
        // a new buffer was latched, or if HWC has requested a full
        // repaint
        if (mFrameStartTime <= 0) {
            // We should only use the time of the first invalidate
            // message that signals a refresh as the beginning of the
            // frame. Otherwise the real frame time will be
            // underestimated.
            mFrameStartTime = frameStart;
        }
        signalRefresh();  //@6
    }
}

@1处refreshNeeded这个变量的值最后会用来判定是否执行 @6处,是否需要刷新
@2处handleMessageTransaction 有要处理的transaction则返回true;
@3处handleMessageInvalidate 总体意思就是layer latch到了buffer,则返回true,且结果和之前的refreshNeeded进行或操作。
@4 refreshNeeded 和mRepaintEverything 进行或操作,mRepaintEverything在updateVrFlinger的时候会置为true。
@5处进行判断符合条件后执行到@6处
@6处就会申请再一次的刷新最后执行到SurfaceFlinger.cpp的onMessageRefresh。

主要关心一下 handleMessageTransaction、handleMessageInvalidate,其他内容先忽略。

一、handleMessageTransaction处理

bool SurfaceFlinger::handleMessageTransaction() {
    ATRACE_CALL();
    uint32_t transactionFlags = peekTransactionFlags();

    bool flushedATransaction = flushTransactionQueues();

    bool runHandleTransaction =
            (transactionFlags && (transactionFlags != eTransactionFlushNeeded)) ||
            flushedATransaction ||
            mForceTraversal;

    if (runHandleTransaction) {
        handleTransaction(eTransactionMask);\\@1
    } else {
        getTransactionFlags(eTransactionFlushNeeded);
    }

    if (transactionFlushNeeded()) {
        setTransactionFlags(eTransactionFlushNeeded);
    }

    return runHandleTransaction;
}

这个过程就是处理应用传过来的各种Transition。
@1处 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).
    State drawingState(mDrawingState);

    Mutex::Autolock _l(mStateLock);@1
    mDebugInTransaction = systemTime();

    // 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.

    mVSyncModulator->onTransactionHandled();
    transactionFlags = getTransactionFlags(eTransactionMask);@2
    handleTransactionLocked(transactionFlags);@3

    mDebugInTransaction = 0;
    invalidateHwcGeometry();
    // here the transaction has been committed
}

@1处 获取mStateLock锁,才能继续执行。
@2处会获取一个transactionFlags, 分为以下几种类别

enum {
    eTransactionNeeded = 0x01,
    eTraversalNeeded = 0x02,
    eDisplayTransactionNeeded = 0x04,
    eTransformHintUpdateNeeded = 0x08,
    eTransactionFlushNeeded = 0x10,
    eTransactionMask = 0x1f,
};

各个Flag处理过程基本上相似,我们会看下eTraversalNeeded的处理。
@3处会执行 handleTransactionLocked(transactionFlags);

void SurfaceFlinger::handleTransactionLocked(uint32_t transactionFlags)
{
......
    if ((transactionFlags & eTraversalNeeded) || mForceTraversal) { @1
        mForceTraversal = false;
        mCurrentState.traverse([&](Layer* layer) {
            uint32_t trFlags = layer->getTransactionFlags(eTransactionNeeded);@2
            if (!trFlags) return; @3

            const uint32_t flags = layer->doTransaction(0);@4
            if (flags & Layer::eVisibleRegion) @5
                mVisibleRegionsDirty = true; @6

            if (flags & Layer::eInputInfoChanged) {
                mInputInfoChanged = true;
            }
        });
    }

@1处满足条件,@2处遍历所有的layer,看这个layer是否需要doTransaction。
@3处如果不需要的话,进入到下一个循环,
@4处执行layer的doTransaction
@5个layer计算可见区域是否发生变化
@6可见区域发生变化

执行getTransactionFlags, trFlags不为0则会继续执行。
显然,不是每个Layer在每次handleTransactionLocked中都需要调用doTransaction,判断标准就是Layer::getTransactionFlags返回的标志中是否指明了eTransactionNeeded

二、handleMessageInvalidate

bool SurfaceFlinger::handleMessageInvalidate() {
    ATRACE_CALL();
    bool refreshNeeded = handlePageFlip();//@1

    if (mVisibleRegionsDirty) {
        computeLayerBounds();
    }

    for (auto& layer : mLayersPendingRefresh) {
        Region visibleReg;
        visibleReg.set(layer->getScreenBounds());
        invalidateLayerStack(layer, visibleReg);
    }
    mLayersPendingRefresh.clear();
    return refreshNeeded;
}

handlePageFlip

/frameworks/native/services/surfaceflinger/SurfaceFlinger.cpp
bool SurfaceFlinger::handlePageFlip()
{
    ATRACE_CALL();
......
    mDrawingState.traverse([&](Layer* layer) {   @1
        if (layer->hasReadyFrame()) {           @2
            frameQueued = true;
            if (layer->shouldPresentNow(expectedPresentTime)) {     @3
                mLayersWithQueuedFrames.push_back(layer);       @4
            } else {
                ATRACE_NAME("!layer->shouldPresentNow()");
                layer->useEmptyDamage();
            }
        } else {
            layer->useEmptyDamage();
        }
    });

    // The client can continue submitting buffers for offscreen layers, but they will not
    // be shown on screen. Therefore, we need to latch and release buffers of offscreen
    // layers to ensure dequeueBuffer doesn't block indefinitely.
    for (Layer* offscreenLayer : mOffscreenLayers) {  @5
        offscreenLayer->traverse(LayerVector::StateSet::Drawing,
                                         [&](Layer* l) { l->latchAndReleaseBuffer(); });
    }

    if (!mLayersWithQueuedFrames.empty()) {  @6
        // mStateLock is needed for latchBuffer as LayerRejecter::reject()
        // writes to Layer current state. See also b/119481871
        Mutex::Autolock lock(mStateLock);

        for (auto& layer : mLayersWithQueuedFrames) {
            if (layer->latchBuffer(visibleRegions, latchTime, expectedPresentTime)) { @7
                mLayersPendingRefresh.push_back(layer);
            }
            layer->useSurfaceDamage();   @8
            if (layer->isBufferLatched()) {
                newDataLatched = true;
            }
        }
    }

    mVisibleRegionsDirty |= visibleRegions;

    // If we will need to wake up at some time in the future to deal with a
    // queued frame that shouldn't be displayed during this vsync period, wake
    // up during the next vsync period to check again.
    if (frameQueued && (mLayersWithQueuedFrames.empty() || !newDataLatched)) {
        signalLayerUpdate();
    }

    // enter boot animation on first buffer latch
    if (CC_UNLIKELY(mBootStage == BootStage::BOOTLOADER && newDataLatched)) {
        ALOGI("Enter boot animation");
        mBootStage = BootStage::BOOTANIMATION;
    }

    mDrawingState.traverse([&](Layer* layer) { layer->updateCloneBufferInfo(); }); @9

    // Only continue with the refresh if there is actually new work to do
    return !mLayersWithQueuedFrames.empty() && newDataLatched;
}

@1处 需要进行合成的数据保存在mDrawingState中。遍历获取到的Layer列表,并且把layer作为参数传给语句块。
@2处 判断layer是不是有Queued的Frame,
@3处 如果shouldPresentNow返回true,@4该Layer标记为mLayersWithQueuedFrames;否则,Layer使用空的DamageRegion。
@5处遍历mOffscreenLayers(mOffscreenLayers是一组没有父层的图层,不在屏幕上面绘制,只被主线程访问)。主要是调用layer的latchAndReleaseBuffer方法,作用注释描述很明确。
@6 mLayersWithQueuedFrames不为空,说明存有适合的layer,接下来获取mStateLock锁,进行遍历mLayersWithQueuedFrames。
@7处 latchBuffer,获取buffer成功后,把此layer 存入mLayersPendingRefresh中,注意传入了一个visibleRegions参数。
@8处 Layer使用空的DamageRegion。DamageRegion后面研究。
@9处 保存此layer的BufferInfo,下一次BufferLayer latchBuffer时候会比较上次buffer的状态,那个时候会用到。

接着看一下handlePageFlip中重要子方法:shouldPresentNow 和latchBuffer

1、shouldPresentNow

/frameworks/native/services/surfaceflinger/BufferQueueLayer.cpp
bool BufferQueueLayer::shouldPresentNow(nsecs_t expectedPresentTime) const {
    if (getSidebandStreamChanged() || getAutoRefresh()) {
        return true;
    }

    if (!hasFrameUpdate()) {
        return false;
    }

    Mutex::Autolock lock(mQueueItemLock);

    const int64_t addedTime = mQueueItems[0].mTimestamp; //@1

    // Ignore timestamps more than a second in the future
    const bool isPlausible = addedTime < (expectedPresentTime + s2ns(1)); @2
    ALOGW_IF(!isPlausible,
             "[%s] Timestamp %" PRId64 " seems implausible "
             "relative to expectedPresent %" PRId64,
             getDebugName(), addedTime, expectedPresentTime);

    if (!isPlausible) {
        mFlinger->mTimeStats->incrementBadDesiredPresent(getSequence());
    }

    const bool isDue = addedTime < expectedPresentTime;  @3
    return isDue || !isPlausible;
}

可以看到影响返回值的就是isDue 和 isPlausible两个值
@1处获取Buffer的时间戳,
@2处判断 Buffer的时间戳 和 期望显示时间再加1秒 之间的关系。注释很明确,忽略超过一秒的时间戳。
@3处 如果Buffer的时间戳小于期望的时间,则为true。

最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 194,088评论 5 459
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 81,715评论 2 371
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 141,361评论 0 319
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 52,099评论 1 263
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 60,987评论 4 355
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 46,063评论 1 272
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 36,486评论 3 381
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 35,175评论 0 253
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 39,440评论 1 290
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 34,518评论 2 309
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 36,305评论 1 326
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 32,190评论 3 312
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 37,550评论 3 298
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 28,880评论 0 17
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 30,152评论 1 250
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 41,451评论 2 341
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 40,637评论 2 335

推荐阅读更多精彩内容