Android下SF合成流程重学习之onMessageInvalidate

本文详细解析了AndroidSurfaceFlinger中onMessageInvalidate的处理流程,涉及事务管理、Buffer获取、帧率切换以及图形合成的各个环节,重点讲解了事务处理、layer和display状态的变化、Buffer的latching过程以及与GPU合成的关系。

Android下SF合成流程重学习之onMessageInvalidate



引言

虽然看了很多关于Android Graphics图形栈的文章和博客,但是都没有形成自己的知识点。每次学习了,仅仅是学习了而已,没有形成自己的知识体系,这次趁着有时间,这次必须把这个事情干透彻了!

本篇引用的代码,主要是Android R的。

并且Android下Graphics图形栈牵涉的点,太多了,这篇博客我们着重分析SF合成流程重学习之onMessageInvalidate的处理流程!




SurfaceFlinger layer之间的对应关系

先用一张图来看下各个部分之间layer的对应关系。接下来会根据这个图来解析是如何进行转换的,如下:

image




一. SF处理事务和处理Buffer

在SF的onMessageInvalidate主要是用来,处理事物和处理相关Buffer的,我们在下面的博客中详细分析!

在这里插入图片描述




1.1 onMessageInvalidate

文件: frameworks/native/services/surfaceflinger/Surfaceflinger.cpp

void SurfaceFlinger::onMessageInvalidate(nsecs_t expectedVSyncTime) {
   
   
    ATRACE_CALL();
    const nsecs_t frameStart = systemTime();
    // expectedVSyncTime 是vsync回调带过来的时间戳,通过nextAnticipatedVSyncTimeFrom 计算得到
    if (expectedVSyncTime >= frameStart) {
   
   
        mExpectedPresentTime = expectedVSyncTime;
    } else {
   
   
        mExpectedPresentTime = mScheduler->getDispSyncExpectedPresentTime(frameStart);
    }
     // 存储上一帧的expectedVSyncTime
    const nsecs_t lastScheduledPresentTime = mScheduledPresentTime;
    mScheduledPresentTime = expectedVSyncTime;

   ...
     // 根据上一帧的present fence判断当前这一帧是否pending
    const TracedOrdinal<bool> framePending = {
   
   "PrevFramePending",
                                              previousFramePending(graceTimeForPresentFenceMs)};

    // 若framePending  或者 上一帧present fence释放的时间  > 上一帧vsync计算的时间戳 + vsync周期的一半
    // 则当前帧要丢掉
    DisplayStatInfo stats;
    mScheduler->getDisplayStatInfo(&stats);
    const nsecs_t frameMissedSlop = stats.vsyncPeriod / 2;
    const nsecs_t previousPresentTime = previousFramePresentTime();
    const TracedOrdinal<bool> frameMissed = {
   
   "PrevFrameMissed",
                                             framePending ||
                                                     (previousPresentTime >= 0 &&
                                                      (lastScheduledPresentTime <
                                                       previousPresentTime - frameMissedSlop))};
    // 根据合成类型判断丢帧的类型
    const TracedOrdinal<bool> hwcFrameMissed = {
   
   "PrevHwcFrameMissed",
                                                mHadDeviceComposition && frameMissed};
    const TracedOrdinal<bool> gpuFrameMissed = {
   
   "PrevGpuFrameMissed",
                                                mHadClientComposition && frameMissed};
   
    ...
    // 这部分涉及帧率切换,先是通过performSetActiveConfig 将新的帧率给到hwc,然后下一帧再更新sf这边的状态
    if (mSetActiveConfigPending) {
   
   
        if (framePending) {
   
   
            mEventQueue->invalidate();
            return;
        }

        // We received the present fence from the HWC, so we assume it successfully updated
        // the config, hence we update SF.
        mSetActiveConfigPending = false;
        ON_MAIN_THREAD(setActiveConfigInternal());
    }
}
  //  mPropagateBackpressure 可以通过adb shell setprop debug.sf.disable_backpressure x 来控制,表示系统是否允许丢帧
  //  若允许丢帧则skip这次刷帧
  if (framePending && mPropagateBackpressure) {
   
   
        if ((hwcFrameMissed && !gpuFrameMissed) || mPropagateBackpressureClientComposition) {
   
   
            signalLayerUpdate();
            return;
        }
    }
 ....
   bool refreshNeeded;
    {
   
   
        ConditionalLockGuard<std::mutex> lock(mTracingLock, mTracingEnabled);
        // 主要的逻辑在这两个函数,简单理解为处理layer或者display的事务和layer的buffer
        refreshNeeded = handleMessageTransaction();
        refreshNeeded |= handleMessageInvalidate();
       ...
    }
    // 帧率切换,SurfaceFlinger主线程执行
   ON_MAIN_THREAD(performSetActiveConfig());
   ...
   // 若layer的事务有变化或者有新的buffer,则触发refresh
   signalRefresh();
}

上述onMessageInvalidate概括来说,其主要处理的事情如下:

  • 判断当前帧是否丢掉
  • handleMessageTr
<think>嗯,用户这次想深入了解AndroidSurfaceFlinger合成流程,看来是个移动图形系统方向的开发者或技术研究者。从ta直接引用四篇技术文档的精准度来看,至少是中级以上水平,可能正在排查合成性能问题或优化渲染流程。用户引用的资料很专业,但略显零散:第一篇讲onMessageInvalidate的触发机制,第二篇涉及合成耗时问题定位,第三篇详细说明Output::finishFrame的GPU/DEVICE合成分支,第四篇提到commit和composite的调用关系。需要把这些碎片串联成完整流程。核心难点在于区分两种合成路径:当HWC支持硬件合成时走DEVICE路径(效率高),否则降级为GPU合成。用户提供的引用[3]特别有价值,其中Output::finishFrame的代码片段清晰展示了这个分支逻辑。准备从刷新信号触发开始梳理:-首先commit阶段会收集所有layer状态变更(引用[4])-然后prepareFrame让HWC决定合成策略(引用[3]关键描述)-DEVICE合成直接present,GPU合成需走composeSurfaces特别注意引用[2]里transaction找不到Surface的案例,这可能是合成跳过某些帧的表现点需要提醒合成耗时分析的技巧,因为用户显然关心性能(引用[2]标题)。合成问题往往出在Layer太多或HWC能力不足,应该补充trace看板的使用建议。那些中文技术博客的引用质量不错,但可以引导用户参考官方文档避免碎片化知识。最后生成的三个问题都直击要害:用户接下来可能会问Layer合并原理、vsync机制的影响,或者具体合成策略的配置方法。特别是DEVICE合成的实现细节值得深挖,毕竟硬件加速才是优化点。</think> 根据引用文档的分析,SurfaceFlingerSF合成流程的核心步骤可归纳如下(兼容GPU/DEVICE两种合成方式): --- ### **SF合成核心流程** 1. **触发合成信号** - Vsync信号或动画等事件触发`onMessageInvalidate()`,启动合成周期[^1][^4]。 - `Scheduler::onFrameSignal()`调用`commit()`检测是否需要更新内容: ```cpp if (!compositor.commit(frameTime, vsyncId, expectedVsyncTime)) return; // 无更新则跳过合成 compositor.composite(frameTime, vsyncId); // 执行合成 ``` 2. **合成策略决策(prepareFrame)** - `prepareFrame()`向HWC(硬件合成器)提交图层信息,由HWC决定合成方式: - **DEVICE合成**:HWC完全支持硬件合成,直接进入Present阶段[^3]。 - **GPU合成**:HWC无法处理部分图层,降级为GPU合成[^3]。 - 根据HWC返回的`changes`更新Layer合成方式(如切换GPU/DEVICE路径)[^3]。 3. **执行合成(composeSurfaces)** - **GPU合成路径**: - 调用`Output::composeSurfaces()`生成像素数据,返回`optReadyFence`(GPU完成栅格化的同步信号)[^3]。 ```cpp auto optReadyFence = composeSurfaces(Region::INVALID_REGION, refreshArgs); ``` - **DEVICE合成路径**:跳过此步骤(由HWC直接处理合成)[^3]。 4. **提交结果上屏(Present)** - GPU合成:通过`mRenderSurface->queueBuffer()`提交帧缓冲区,携带`optReadyFence`确保时序[^3]。 - DEVICE合成:HWC直接调用`presentDisplay()`输出结果[^3]。 5. **完成帧(finishFrame)** - 清理临时数据,记录合成耗时(用于性能分析)[^2][^3]。 --- ### **流程关键点** - **合成方式选择**:HWC能力决定性能瓶颈。若HWC拒绝合成,强制GPU路径增加负载[^3]。 - **同步机制**:`optReadyFence`确保GPU合成完成后才提交缓冲区,避免撕裂[^3]。 - **问题定位**: - 若事务中缺失关键Layer(如`Surface(name=Task=23#1131)`),表明合成跳过动画帧[^2]。 - 耗时分析需关注`commit()`/`composite()`时间戳及HWC日志[^2][^4]。 --- ### **典型问题示例** 1. **合成路径降级** 当HWC无法处理复杂图层(如半透+旋转)时,回退到GPU合成导致帧率下降。可通过`dumpsys SurfaceFlinger`检查`CompositionType`确认各Layer合成方式。 2. **事务丢失** 引用[^2]中`transactionReadyTimelineChec`缺失动画Layer,表明SF未处理该帧。常见于动画Surface未正确绑定到合成树。 ---
评论 1
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
红包 添加红包
表情包 插入表情
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值