android 图形学之图层数据送显(八)

cpp 复制代码
void Scheduler::onFrameSignal(ICompositor& compositor, VsyncId vsyncId,
                              TimePoint expectedVsyncTime) {
   

    pacesetterPtr->targeterPtr->beginFrame(beginFrameArgs, *pacesetterPtr->schedulePtr);

    ui::PhysicalDisplayVector<PhysicalDisplayId> presentableDisplays = {pacesetterPtr->displayId};
    {
        FrameTargets targets;
        targets.try_emplace(pacesetterPtr->displayId, &pacesetterPtr->targeterPtr->target());

        const bool followerDisplayBackpressure =
                FlagManager::getInstance().follower_display_backpressure();
        if (!followerDisplayBackpressure) {
            expectedVsyncTime = pacesetterPtr->targeterPtr->target().expectedPresentTime();
        }
           ..............先省略.....................................

            targeter.beginFrame(followerBeginFrameArgs, *display.schedulePtr);
            targets.try_emplace(id, &targeter.target());
            presentableDisplays.push_back(id);
        }
        // 执行surfaceflinger::commit的方法
        if (!compositor.commit(pacesetterPtr->displayId, targets)) {
            compositor.sendNotifyExpectedPresentHint(pacesetterPtr->displayId);
            mSchedulerCallback.onCommitNotComposited();
            return;
        }
    }

    // The pacesetter may have changed or been registered anew during commit.
    pacesetterPtr = pacesetterPtrLocked();

    //执行surfaceflinger::composite的合成的方法
    const auto resultsPerDisplay = compositor.composite(pacesetterPtr->displayId, targeters);
    compositor.sendNotifyExpectedPresentHint(pacesetterPtr->displayId);
    compositor.sample();

    for (const auto& [id, targeter] : targeters) {
        const auto resultOpt = resultsPerDisplay.get(id);
        LOG_ALWAYS_FATAL_IF(!resultOpt);
        targeter->endFrame(*resultOpt);
    }
}

先分析commit的方法。核心的提交的入口,每帧由Scheduler调用。pacesetterId是主显示器(决定VSync节奏),frameTargets包含所有显示器的帧时间目标。

cpp 复制代码
bool SurfaceFlinger::commit(PhysicalDisplayId pacesetterId,
                            const scheduler::FrameTargets& frameTargets) EXCLUDES(mStateLock) {
    const scheduler::FrameTarget& pacesetterFrameTarget = *frameTargets.get(pacesetterId)->get();
    //提取pacesetter显示器的帧目标及其Vsync_Id
    const VsyncId vsyncId = pacesetterFrameTarget.vsyncId();
    SFTRACE_NAME(ftl::Concat(__func__, ' ', ftl::to_underlying(vsyncId)).c_str());

    if (pacesetterFrameTarget.didMissFrame()) {
        mTimeStats->incrementMissedFrames();
    }

    // SF::processHotplugDisconnect() does not immediately propagate the display removal to the
    // Scheduler and CompositionEngine, but instead requires a call to processDisplayChangesLocked()
    // to process the rest in the next commit. We should retry the commit with the new pacesetter
    // after display transactions have been propagated.
    {
    //支持动态pacesetter切换。如果开启了pacesetter_selection flag且当前pacesetter已被移除(热插拔),先处理显示器变更,重新调度下一帧本次commit直接返回false,不合成
        const bool hasPacesetterDisplay =
                FTL_FAKE_GUARD(mStateLock, mPhysicalDisplays.contains(pacesetterId));
        if (FlagManager::getInstance().pacesetter_selection() && !hasPacesetterDisplay) {
            FTL_FAKE_GUARD(mStateLock, processDisplayChangesLocked());
            mScheduler->scheduleFrame();
            return false;
        }
    }

    // If a mode set is pending and the fence hasn't fired yet, wait for the next commit.
    //如果有显示器正在进行模式切换且fence还未触发,推迟本帧,等待模式切换完成。避免模式切换过程中提交新帧导致的crash
    if (std::any_of(frameTargets.begin(), frameTargets.end(),
                    [this](const auto& pair) FTL_FAKE_GUARD(kMainThreadContext) {
                        const auto [displayId, target] = pair;
                        return target->isFramePending() &&
                                mDisplayModeController.isModeSetPending(displayId);
                    })) {
        mScheduler->scheduleFrame();
        return false;
    }

    {
        Mutex::Autolock lock(mStateLock);

        for (const auto [displayId, _] : frameTargets) {
           //遍历所有目标显示器,完成已就绪的模式切换。若某显示器还没就绪,重新调度并返回false
            if (mDisplayModeController.isModeSetPending(displayId)) {
                if (!finalizeDisplayModeChange(displayId)) {
                    mScheduler->scheduleFrame();
                    return false;
                }
            }
        }
    }
//检测HWWC是否背压。若开启GPU合成回退或已miss HWC帧,则
//1、通知VSyncTracker本帧miss
//2、计算已消耗的时间
//3、重新调度commit,本帧放弃合成
    if (pacesetterFrameTarget.wouldBackpressureHwc()) {
        if (mBackpressureGpuComposition || pacesetterFrameTarget.didMissHwcFrame()) {
            mScheduler->getVsyncSchedule()->getTracker().onFrameMissed(
                    pacesetterFrameTarget.expectedPresentTime());
            const Duration slack = TimePoint::now() - pacesetterFrameTarget.frameBeginTime();
            scheduleCommit(FrameHint::kNone, slack);
            return false;
        }
    }
    SFTRACE_NAME_FOR_TRACK(WorkloadTracer::TRACK_NAME, "Commit");
    const Period vsyncPeriod = mScheduler->getVsyncSchedule()->period();

    // Save this once per commit + composite to ensure consistency
    // TODO: b/240619471 - Consider removing front internal display check once AOD is fixed
    const auto frontInternalDisplay = FTL_FAKE_GUARD(mStateLock, getFrontInternalDisplayLocked());
    mPowerHintSessionEnabled = mPowerAdvisor->usePowerHintSession() && frontInternalDisplay &&
            frontInternalDisplay->getPowerMode() == hal::PowerMode::ON;
  //判断是否启用启用了动态性能框架
    if (mPowerHintSessionEnabled) {
        mPowerAdvisor->setCommitStart(pacesetterFrameTarget.frameBeginTime());
        mPowerAdvisor->setExpectedPresentTime(pacesetterFrameTarget.expectedPresentTime());

        // Frame delay is how long we should have minus how long we actually have.
        const Duration idealSfWorkDuration =
                mScheduler->vsyncModulator().getVsyncConfig().sfWorkDuration;
        const Duration frameDelay =
                idealSfWorkDuration - pacesetterFrameTarget.expectedFrameDuration();
        //计算frame delay (理想状态SF工作时长-实际可用时长),上报给PowerAdvisor用于CPU/GPU频率调节
        mPowerAdvisor->setFrameDelay(frameDelay);
        mPowerAdvisor->setTotalFrameTargetWorkDuration(idealSfWorkDuration);
        
        const Period idealVsyncPeriod =
                mDisplayModeController.getActiveMode(pacesetterId).fps.getPeriod();
        //更新工作的时长
        mPowerAdvisor->updateTargetWorkDuration(idealVsyncPeriod);
    }
    //刷新率切换指示器、HDR/SDR比例指示器的逐帧动画更新
    if (mRefreshRateOverlaySpinner) {
        Mutex::Autolock lock(mStateLock);
        for (const auto& [_, display] : mDisplays) {
            display->animateRefreshRateOverlay();
        }
    }
    if (mHdrSdrRatioOverlay) {
        Mutex::Autolock lock(mStateLock);
        for (const auto& [_, display] : mDisplays) {
            display->animateHdrSdrRatioOverlay();
        }
    }

    // Composite if transactions were committed, or if requested by HWC.
    //读取并清零mustComposite标志
    bool mustComposite = mMustComposite.exchange(false);
    {//FrameTimeline 记录SF唤醒时间,Vsync周期,刷新率(用于jank追踪)
        mFrameTimeline->setSfWakeUp(ftl::to_underlying(vsyncId),
                                    pacesetterFrameTarget.frameBeginTime().ns(),
                                    Fps::fromPeriodNsecs(vsyncPeriod.ns()),
                                    mScheduler->getPacesetterRefreshRate());
        //清除并获取事务刷新的标志
        const bool flushTransactions = clearTransactionFlags(eTransactionFlushNeeded);
        bool transactionsAreEmpty = false;
        //处理所有待提交的事务
        //1、更新每个Layer的drawing state,返回是否有变更需要合成
        mustComposite |= updateLayerSnapshots(vsyncId, pacesetterFrameTarget.frameBeginTime().ns(),
                                              pacesetterFrameTarget.expectedPresentTime().ns(),
                                              flushTransactions, transactionsAreEmpty);

        // Tell VsyncTracker that we are going to present this frame before scheduling
        // setTransactionFlags which will schedule another SF frame. This was if the tracker
        // needs to adjust the vsync timeline, it will be done before the next frame.
        //需要合成,通知VSyncTracker帧开始(用于动态调整VSync相位)
        if (mustComposite) {
            mScheduler->getVsyncSchedule()
                    ->getTracker()
                    .onFrameBegin(pacesetterFrameTarget.expectedPresentTime(),
                                  pacesetterFrameTarget.lastSignaledFrameTime());
        }
        if (transactionFlushNeeded()) {
            setTransactionFlags(eTransactionFlushNeeded);
        }

        // This has to be called after latchBuffers because we want to include the layers that have
        // been latched in the commit callback
        if (transactionsAreEmpty) {
            // Invoke empty transaction callbacks early.
            //空事务--->发送所有回调
            mTransactionCallbackInvoker.sendCallbacks(false /* onCommitOnly */);
        } else {
            // Invoke OnCommit callbacks.
            //非空事务--->仅发送OnCommit回调
            mTransactionCallbackInvoker.sendCallbacks(true /* onCommitOnly */);
        }
    }

    // Layers need to get updated (in the previous line) before we can use them for
    // choosing the refresh rate.
    // Hold mStateLock as chooseRefreshRateForContent promotes wp<Layer> to sp<Layer>
    // and may eventually call to ~Layer() if it holds the last reference
    //刷新率选择与显示器模式变更发起
    {
        SFTRACE_NAME_FOR_TRACK(WorkloadTracer::TRACK_NAME, "Refresh Rate Selection");
        //保存并清零updateAttachedChoreographer标志
        bool updateAttachedChoreographer = mUpdateAttachedChoreographer;
        mUpdateAttachedChoreographer = false;

        Mutex::Autolock lock(mStateLock);
        //根据需要的内容选择刷新率
        mScheduler->chooseRefreshRateForContent(&mLayerHierarchyBuilder.getHierarchy(),
                                                updateAttachedChoreographer);
        initiateDisplayModeChanges();
    }
    //光标位置异步更新(低延迟,不阻塞主线程)
    updateCursorAsync();
    //仅当不合成时更新InputFlinger(窗口输入区域)。合成时会在onCompositionPresented中更新,避免重复
    if (!mustComposite) {
        updateInputFlinger(vsyncId, pacesetterFrameTarget.frameBeginTime());
    }
    doActiveLayersTracingIfNeeded(false, mVisibleRegionsDirty,
                                  pacesetterFrameTarget.frameBeginTime(), vsyncId);

    mLastCommittedVsyncId = vsyncId;

    persistDisplayBrightness(mustComposite);
    // 返回值:本帧是否需要合成 mustComposite  启动阶段不合成
    return mustComposite && CC_LIKELY(mBootStage != BootStage::BOOTLOADER);
}

接下来看下合成时期的代码:composite()方法

csharp 复制代码
CompositeResultsPerDisplay SurfaceFlinger::composite(
        PhysicalDisplayId pacesetterId, const scheduler::FrameTargeters& frameTargeters) {
    SFTRACE_ASYNC_FOR_TRACK_BEGIN(WorkloadTracer::TRACK_NAME, "Composition",
                                  WorkloadTracer::COMPOSITION_TRACE_COOKIE);
         //获取主显示器的帧目标
    const scheduler::FrameTarget& pacesetterTarget =
            frameTargeters.get(pacesetterId)->get()->target();
        //提取vsyncId,设置trace名称便于perfetto关联帧
    const VsyncId vsyncId = pacesetterTarget.vsyncId();
    SFTRACE_NAME(ftl::Concat(__func__, ' ', ftl::to_underlying(vsyncId)).c_str());
    //创建传给 CompositionEngine 的刷新参数对象。
    compositionengine::CompositionRefreshArgs refreshArgs;
    //把 SF 自身设为 ADPF power callback(负载升高时可 hint)。
    // adpf load up hint
    refreshArgs.powerCallback = this;
    //在 mStateLock 假守卫下读显示器列表,预留 outputs 容量。
    const auto& displays = FTL_FAKE_GUARD(mStateLock, mDisplays);
    //收集所有 display id,trace 各屏电源模式,并告知 PowerAdvisor 当前有哪些屏。
    refreshArgs.outputs.reserve(displays.size());

    std::vector<DisplayId> displayIds;
    for (const auto& [_, display] : displays) {
        displayIds.push_back(display->getId());
        display->tracePowerMode();
    }
    mPowerAdvisor->setDisplays(displayIds);
    //把本帧需要从缓存剔除的 buffer id 挪进 refreshArgs(避免重复 uncache)。
    refreshArgs.bufferIdsToUncache = std::move(mBufferIdsToUncache);
    refreshArgs.outputColorSetting = mDisplayColorSetting;
    refreshArgs.forceOutputColorMode = mForceColorMode;   //输出颜色策略与强制 color mode。

    refreshArgs.updatingOutputGeometryThisFrame = mVisibleRegionsDirty;  //可见区域脏 → 本帧要重算 output 几何。
    refreshArgs.updatingGeometryThisFrame = mGeometryDirty.exchange(false) ||
            mVisibleRegionsDirty || mDrawingState.colorMatrixChanged;
    refreshArgs.internalDisplayRotationFlags = getFrontInternalDisplayRotationFlags();  //内屏旋转标志(影响 buffer transform)
    //若颜色矩阵变了,写入矩阵并清标志(少见路径,CC_UNLIKELY)。
    if (CC_UNLIKELY(mDrawingState.colorMatrixChanged)) {
        refreshArgs.colorTransformMatrix = mDrawingState.colorMatrix;
        mDrawingState.colorMatrixChanged = false;
    }
   //按调试开关 / 慢 follower 屏等,把某些 layer stack 强制标为 GPU(client)合成。
    setForcedClientCompositionLayerStacks(refreshArgs);

    // TODO(b/255601557) Update frameInterval per display
    //用 pacesetter 的 expected present time 算下一帧 interval(目前全局一份,TODO 按屏)。
    refreshArgs.frameInterval =
            mScheduler->getNextFrameInterval(pacesetterId, pacesetterTarget.expectedPresentTime());
    //若 Scheduler 已 schedule 下一帧,带上 callback 时间。
    const auto scheduledFrameResultOpt = mScheduler->getScheduledFrameResult();
    const auto scheduledFrameTimeOpt = scheduledFrameResultOpt
            ? std::optional{scheduledFrameResultOpt->callbackTime}
            : std::nullopt;
    refreshArgs.scheduledFrameTime = scheduledFrameTimeOpt; 
    refreshArgs.hasTrustedPresentationListener = mNumTrustedPresentationListeners > 0;
    // Store the present time just before calling to the composition engine so we could notify
    // the scheduler.
    const auto presentTime = systemTime();
    refreshArgs.refreshStartTime = presentTime; //记录"即将进 CompositionEngine"的系统时间,既作 refreshStartTime,也给后面的 onCompositionPresented 用。
    //把 displays 拆成:主线程要 present 的 outputs,以及可选的可卸载到后台 GPU 合成的 outputs(多屏优化)。
    //C++语法,结构化绑定的变量,addOutputsToRefreshArgs返回一个结构化的变量
    auto [mainThreadRefreshArgs, optionalOffloadedRefreshArgs] =
            addOutputsToRefreshArgs(pacesetterId, refreshArgs, frameTargeters);
    //kCursorOnly=false:处理全部层,不只是光标。把主线程 outputs 对应的 layer snapshot 填进 args,返回 (Layer*, LayerFE*) 列表。
    constexpr bool kCursorOnly = false;
    const auto layers = addLayerSnapshotsToCompositionArgs(mainThreadRefreshArgs, kCursorOnly);
   //预合成准备:必要时置 visible region dirty;对每层 onPreComposition;挂上 release fence future。
    prepareLayersForComposition(mainThreadRefreshArgs, kCursorOnly, layers);
   //校验 / 配置 readback(截图一类需求)。
    for (auto& [layer, layerFE] : layers) {
        validateForReadback(layerFE);
    }
    setupOutputsForReadback(mainThreadRefreshArgs.outputs);

    std::vector<std::pair<Layer*, LayerFE*>> offloadedLayers;
    if (optionalOffloadedRefreshArgs) {
        offloadedLayers =
                addLayerSnapshotsToCompositionArgs(*optionalOffloadedRefreshArgs, kCursorOnly);

        prepareLayersForComposition(*optionalOffloadedRefreshArgs, kCursorOnly, offloadedLayers);
    }

    std::unordered_set<uint32_t> mainThreadLayerStacks;
    for (auto& output : mainThreadRefreshArgs.outputs) { //收集主线程 outputs 的 layerStack,后面用来分流 "有排队帧的层"。
        mainThreadLayerStacks.insert(output->getState().layerFilter.layerStack.id);
    }
    //预留 layersWithQueuedFrames 容量。
    mainThreadRefreshArgs.layersWithQueuedFrames.reserve(mLayersWithQueuedFrames.size());
    if (optionalOffloadedRefreshArgs) {
        optionalOffloadedRefreshArgs->layersWithQueuedFrames.reserve(
                mLayersWithQueuedFrames.size());
    }
    //遍历 mLayersWithQueuedFrames:有 LayerFE 的层按所属 layerStack 分到主线程或卸载 args;若 release fence promise 还没建或已用完,给未上屏层挂上 UNASSIGNED 的 future。
    for (auto& [layer, _] : mLayersWithQueuedFrames) {
        if (const auto& layerFE =
                    layer->getCompositionEngineLayerFE({static_cast<uint32_t>(layer->sequence)})) {
            if (!optionalOffloadedRefreshArgs ||
                (layerFE->mSnapshot != nullptr &&
                 layerFE->mSnapshot->outputFilter.layerStack != ui::UNASSIGNED_LAYER_STACK &&
                 mainThreadLayerStacks.count(layerFE->mSnapshot->outputFilter.layerStack.id))) {
                mainThreadRefreshArgs.layersWithQueuedFrames.push_back(layerFE);
            } else {
                optionalOffloadedRefreshArgs->layersWithQueuedFrames.push_back(layerFE);
            }
            // Some layers are not displayed and do not yet have a future release fence
            if (layerFE->getReleaseFencePromiseStatus() ==
                        LayerFE::ReleaseFencePromiseStatus::UNINITIALIZED ||
                layerFE->getReleaseFencePromiseStatus() ==
                        LayerFE::ReleaseFencePromiseStatus::FULFILLED) {
                // layerStack is unassigned because layer is not on a display
                attachReleaseFenceFutureToLayer(layer.get(), layerFE.get(),
                                                ui::UNASSIGNED_LAYER_STACK);
            }
        }
    }
    //有卸载 args 则异步启动 GPU 合成,拿到 future,主线程可并行做 HWC present。
    std::optional<std::future<void>> offloadedCompositionFuture;
    if (optionalOffloadedRefreshArgs) {
        offloadedCompositionFuture =
                offloadGpuCompositedDisplays(std::move(*optionalOffloadedRefreshArgs),
                                             offloadedLayers);
    }
   //合成核心:CompositionEngine 对主线程 outputs 做 validate → 选 HWC/GPU 策略 → RenderEngine / Composer HAL present。
    mCompositionEngine->present(mainThreadRefreshArgs);
   //present 后收尾 readback。
    finalizeReadback(mainThreadRefreshArgs.outputs);
   //本帧有几何 / 可见区域更新 → ADPF 标记 VISIBLE_REGION。
    ftl::Flags<adpf::Workload> compositedWorkload;
    if (mainThreadRefreshArgs.updatingGeometryThisFrame ||
        mainThreadRefreshArgs.updatingOutputGeometryThisFrame) {
        compositedWorkload |= adpf::Workload::VISIBLE_REGION;
    }
    if (mFrontEndDisplayInfosChanged) {
        compositedWorkload |= adpf::Workload::DISPLAY_CHANGES;
        SFTRACE_INSTANT_FOR_TRACK(WorkloadTracer::TRACK_NAME, "Display Changes");
    }

    ftl::StaticVector<char, WorkloadTracer::COMPOSITION_SUMMARY_SIZE> compositionSummary;
    auto lastLayerStack = ui::UNASSIGNED_LAYER_STACK;
    //遍历主线程 layers:stealCompositionResult() 取回本层合成结果;按 layerStack 用空格分隔;用 [...] 标 HWC cached set;单字符描述每层是 GPU 大写 / DPU 小写 / 特效等;有 effect 则加 EFFECTS;有 client composition fence 则记回 Layer;可选 picture profile 追踪。
    uint64_t prevOverrideBufferId = 0;
    for (auto& [layer, layerFE] : layers) {
        CompositionResult compositionResult{layerFE->stealCompositionResult()};
        if (lastLayerStack != layerFE->mSnapshot->outputFilter.layerStack) {
            if (lastLayerStack != ui::UNASSIGNED_LAYER_STACK) {
                // add a space to separate displays
                compositionSummary.push_back(' ');
            }
            lastLayerStack = layerFE->mSnapshot->outputFilter.layerStack;
        }

        // If there are N layers in a cached set they should all share the same buffer id.
        // The first layer in the cached set will be not skipped and layers 1..N-1 will be skipped.
        // We expect all layers in the cached set to be marked as composited by HWC.
        // Here is a made up example of how it is visualized
        //
        //      [b:rrc][s:cc]
        //
        // This should be interpreted to mean that there are 2 cached sets.
        // So there are only 2 non skipped layers -- b and s.
        // The layers rrc and cc are flattened into layers b and s respectively.
        const LayerFE::HwcLayerDebugState& hwcState = layerFE->getLastHwcState();
        if (hwcState.overrideBufferId != prevOverrideBufferId) {
            // End the existing run.
            if (prevOverrideBufferId) {
                compositionSummary.push_back(']');
            }
            // Start a new run.
            if (hwcState.overrideBufferId) {
                compositionSummary.push_back('[');
            }
        }

        compositionSummary.push_back(layerFE->mSnapshot->classifyCompositionForDebug(hwcState));

        if (hwcState.overrideBufferId && !hwcState.wasSkipped) {
            compositionSummary.push_back(':');
        }
        prevOverrideBufferId = hwcState.overrideBufferId;

        if (layerFE->mSnapshot->hasEffect()) {
            compositedWorkload |= adpf::Workload::EFFECTS;
        }

        if (compositionResult.lastClientCompositionFence) {
            layer->setWasClientComposed(compositionResult.lastClientCompositionFence);
        }
        if (com_android_graphics_libgui_flags_apply_picture_profiles()) {
            mActivePictureTracker.onLayerComposed(*layer, *layerFE, compositionResult);
        }
    }
    // End the last run.
    if (prevOverrideBufferId) {
        compositionSummary.push_back(']');
    }

    // Concisely describe the layers composited this frame using single chars. GPU composited layers
    // are uppercase, DPU composited are lowercase. Special chars denote effects (blur, shadow,
    // etc.). This provides a snapshot of the compositing workload.
    SFTRACE_INSTANT_FOR_TRACK(WorkloadTracer::TRACK_NAME,
                              ftl::Concat("Layers: ", layers.size(), " ",
                                          ftl::truncated<WorkloadTracer::COMPOSITION_SUMMARY_SIZE>(
                                                  std::string_view(compositionSummary.begin(),
                                                                   compositionSummary.size())))
                                      .c_str());
    //把工作负载交给 PowerAdvisor,结束 Composition 异步 trace。
    mPowerAdvisor->setCompositedWorkload(compositedWorkload);
    SFTRACE_ASYNC_FOR_TRACK_END(WorkloadTracer::TRACK_NAME,
                                WorkloadTracer::COMPOSITION_TRACE_COOKIE);
    SFTRACE_NAME_FOR_TRACK(WorkloadTracer::TRACK_NAME, "Post Composition");
    SFTRACE_NAME("postComposition");
    //支持 HDCP 时:非 secure 屏上却有 secure layer → 启动 HDCP 协商。
    if (mDisplayModeController.supportsHdcp()) {
        for (const auto& [id, _] : frameTargeters) {
            ftl::FakeGuard guard(mStateLock);
            if (const auto display = getCompositionDisplayLocked(id)) {
                if (!display->isSecure() && display->hasSecureLayers()) {
                    mDisplayModeController.startHdcpNegotiation(id);
                }
            }
        }
    }

    moveSnapshotsFromCompositionArgs(mainThreadRefreshArgs, layers);  //把主线程 args 里的 snapshot 所有权挪回 Layer(避免 CompositionEngine 持有过久)。
    if (optionalOffloadedRefreshArgs) {  //等卸载合成完成,再同样归还 snapshot。
        offloadedCompositionFuture->wait();
        moveSnapshotsFromCompositionArgs(*optionalOffloadedRefreshArgs, offloadedLayers);
    }
    mTimeStats->recordFrameDuration(pacesetterTarget.frameBeginTime().ns(), systemTime());//记录本帧从 frameBeginTime 到现在的 duration。

    // Send a power hint after presentation is finished.
    if (mPowerHintSessionEnabled) {
        // Now that the current frame has been presented above, PowerAdvisor needs the present time
        // of the previous frame (whose fence is signaled by now) to determine how long the HWC had
        // waited on that fence to retire before presenting.
        // TODO(b/355238809) `presentFenceForPreviousFrame` might not always be signaled (e.g. on
        // devices
        //  where HWC does not block on the previous present fence). Revise this assumtion.
        const auto& previousPresentFence = pacesetterTarget.presentFenceForPreviousFrame();

        mPowerAdvisor->setSfPresentTiming(TimePoint::fromNs(previousPresentFence->getSignalTime()),
                                          TimePoint::now());
        mPowerAdvisor->reportActualWorkDuration();
    }
    //通知 Scheduler "合成已 present";若它要求再合成一帧,则 scheduleComposite。
    if (mScheduler->onCompositionPresented(presentTime)) {
        scheduleComposite(FrameHint::kNone);
    }
    //重置 expected present hint 状态,并走 onCompositionPresented(更新各屏 fence、延迟等)。
    mNotifyExpectedPresentMap[pacesetterId].hintStatus = NotifyExpectedPresentHintStatus::Start;
    onCompositionPresented(pacesetterId, frameTargeters, presentTime);
    //记住上一帧是否用过 GPU 合成,然后清空本帧 coverage 表。
    const bool hadGpuComposited =
            multiDisplayUnion(mCompositionCoverage).test(CompositionCoverage::Gpu);
    mCompositionCoverage.clear();
    
    TimeStats::ClientCompositionRecord clientCompositionRecord;
    //按每屏 CompositionDisplay state:标 HWC / GpuReuse / Gpu,并统计策略预测是否启用/成功。
    for (const auto& [_, display] : FTL_FAKE_GUARD(mStateLock, mDisplays)) {
        const auto& state = display->getCompositionDisplay()->getState();
        CompositionCoverageFlags& flags =
                mCompositionCoverage.try_emplace(display->getDisplayIdVariant()).first->second;

        if (state.usesDeviceComposition) {
            flags |= CompositionCoverage::Hwc;
        }

        if (state.reusedClientComposition) {
            flags |= CompositionCoverage::GpuReuse;
        } else if (state.usesClientComposition) {
            flags |= CompositionCoverage::Gpu;
        }

        clientCompositionRecord.predicted |=
                (state.strategyPrediction != CompositionStrategyPredictionState::DISABLED);
        clientCompositionRecord.predictionSucceeded |=
                (state.strategyPrediction == CompositionStrategyPredictionState::SUCCESS);
    }

    const auto coverage = multiDisplayUnion(mCompositionCoverage);
    const bool hasGpuComposited = coverage.test(CompositionCoverage::Gpu);

    clientCompositionRecord.hadClientComposition = hasGpuComposited;
    clientCompositionRecord.reused = coverage.test(CompositionCoverage::GpuReuse);
    clientCompositionRecord.changed = hadGpuComposited != hasGpuComposited;

    mTimeStats->pushCompositionStrategyState(clientCompositionRecord);

    using namespace ftl::flag_operators;
    //本帧有 GPU 合成或 reuse → 通知 VsyncModulator(可拉长/调整 SF 工作窗口)。
    // TODO(b/160583065): Enable skip validation when SF caches all client composition layers.
    const bool hasGpuUseOrReuse =
            coverage.any(CompositionCoverage::Gpu | CompositionCoverage::GpuReuse);
    mScheduler->modulateVsync({}, &VsyncModulator::onDisplayRefresh, hasGpuUseOrReuse);
    //清空"有排队帧"的层集合(本帧已消费)。
    mLayersWithQueuedFrames.clear();
    doActiveLayersTracingIfNeeded(true, mVisibleRegionsDirty, pacesetterTarget.frameBeginTime(),
                                  vsyncId);
    //把本帧 vsync / 时间同步给 InputFlinger。
    updateInputFlinger(vsyncId, pacesetterTarget.frameBeginTime());
    //可见区域曾脏则标 HDR 层信息需更新,并清 mVisibleRegionsDirty。
    if (mVisibleRegionsDirty) mHdrLayerInfoChanged = true;
    mVisibleRegionsDirty = false;
    //CompositionEngine 若还要再更新(如某些异步路径)→ 再 schedule 一次 commit。
    if (mCompositionEngine->needsAnotherUpdate()) {
        scheduleCommit(FrameHint::kNone);
    }

    if (mPowerHintSessionEnabled) {
        mPowerAdvisor->setCompositeEnd(TimePoint::now());
    }

    CompositeResultsPerDisplay resultsPerDisplay;

    // Filter out virtual displays.
    for (const auto& [idVar, coverage] : mCompositionCoverage) {
        if (const auto idOpt = asPhysicalDisplayId(idVar)) {
            resultsPerDisplay.try_emplace(*idOpt, CompositeResult{coverage});
        }
    }
    //返回给 Scheduler;调用方会对每个 targeter 调 endFrame。
    return resultsPerDisplay;
}
cpp 复制代码
void CompositionEngine::present(CompositionRefreshArgs& args) {
    SFTRACE_CALL();
    ALOGV(__FUNCTION__);

    preComposition(args);

    {
        // latchedLayers is used to track the set of front-end layer state that
        // has been latched across all outputs for the prepare step, and is not
        // needed for anything else.
        LayerFESet latchedLayers;

        for (const auto& output : args.outputs) {
            output->prepare(args, latchedLayers);
        }
    }

    // Offloading the HWC call for `present` allows us to simultaneously call it
    // on multiple displays. This is desirable because these calls block and can
    // be slow.
    offloadOutputs(args.outputs);

    ui::DisplayVector<ftl::Future<std::monostate>> presentFutures;
    for (const auto& output : args.outputs) {
    //这里有关送显
        presentFutures.push_back(output->present(args));
    }

    {
        SFTRACE_NAME("Waiting on HWC");
        for (auto& future : presentFutures) {
            // TODO(b/185536303): Call ftl::Future::wait() once it exists, since
            // we do not need the return value of get().
            future.get();
        }
    }
    postComposition(args);
}

void CompositionEngine::postComposition(CompositionRefreshArgs& args) {
    SFTRACE_CALL();
    ALOGV(__FUNCTION__);

    const bool force_slower_follower_gpu_composition =
            FlagManager::getInstance().force_slower_follower_gpu_composition();
    for (auto& layerFE : args.layers) {
        if (layerFE->getReleaseFencePromiseStatus() ==
            LayerFE::ReleaseFencePromiseStatus::INITIALIZED) {
            if (force_slower_follower_gpu_composition) {
                layerFE->setReleaseFence(layerFE->getAndClearLastClientTargetAcquireFence());
            } else {
                layerFE->setReleaseFence(Fence::NO_FENCE);
            }
        }
    }

    // List of layersWithQueuedFrames does not necessarily overlap with
    // list of layers, so those layersWithQueuedFrames also need any
    // unfulfilled promises to be resolved for completeness.
    for (auto& layerFE : args.layersWithQueuedFrames) {
        if (layerFE->getReleaseFencePromiseStatus() ==
            LayerFE::ReleaseFencePromiseStatus::INITIALIZED) {
            if (force_slower_follower_gpu_composition) {
                layerFE->setReleaseFence(layerFE->getAndClearLastClientTargetAcquireFence());
            } else {
                layerFE->setReleaseFence(Fence::NO_FENCE);
            }
        }
    }
}
相关推荐
天空之城--1 小时前
Android Flutter行业动态与学习参考(2026年8月)
android·flutter
quantdash_cc2 小时前
基于 QuantDash 5 分钟 K 线的网格交易策略参数网格搜索寻优实战
android·开发语言·pandas·量化·quantdash
杉氧3 小时前
原生交互:如何在 Flutter 中嵌入 Android/iOS 原生组件并解决手势冲突
android·flutter·dart
Android打工仔3 小时前
Continuation 的链式关系 —— 一个 suspend 函数如何把结果交还给调用者?
android·kotlin
hunterandroid3 小时前
[Android 从零到一] Kotlin Channel 与复杂并发场景:从生产者-消费者到结构化并发治理
android
FlightYe4 小时前
linux系统编程(八):阻塞与非阻塞IO对比
android·linux·运维·服务器·github·vim
恋猫de小郭4 小时前
Flutter iOS Deep Link 为什么会突然失效:一系列难以言喻的问题
android·前端·flutter
Kapaseker5 小时前
小白都看得懂的 Skill 教程 - 初识 Skill
android·kotlin·vibecoding
神奇小梵5 小时前
安全和开发的需要了解的知识————下载内容的安全,和下载内容如何运行
android·windows·安全·个人开发