SurfaceFlinger::commit frameMissed计算


services/surfaceflinger/SurfaceFlinger.cpp



// frameTime:当前时间       expectedVsyncTime:期待的上屏时间,未来的硬件vsync时间
bool SurfaceFlinger::commit(nsecs_t frameTime, int64_t vsyncId, nsecs_t expectedVsyncTime)
        FTL_FAKE_GUARD(kMainThreadContext) {
    ATRACE_CALL();
    // calculate the expected present time once and use the cached
    // value throughout this frame to make sure all layers are
    // seeing this same value.
    if (expectedVsyncTime >= frameTime) {
        mExpectedPresentTime = expectedVsyncTime;
    } else {
        const DisplayStatInfo stats = mScheduler->getDisplayStatInfo(frameTime);
        mExpectedPresentTime = calculateExpectedPresentTime(stats);
    }

    const nsecs_t lastScheduledPresentTime = mScheduledPresentTime;
    mScheduledPresentTime = expectedVsyncTime;

    const auto vsyncIn = [&] {
        if (!ATRACE_ENABLED()) return 0.f;
        return (mExpectedPresentTime - systemTime()) / 1e6f;
    }();
    // 打印相关的trace 在未来的的多少毫秒内提交(从现在到规划上帧的硬件vsync时间)
    ATRACE_FORMAT("%s %" PRId64 " vsyncIn %.2fms%s", __func__, vsyncId, vsyncIn,
                  mExpectedPresentTime == expectedVsyncTime ? "" : " (adjusted)");

    // When Backpressure propagation is enabled we want to give a small grace period
    // for the present fence to fire instead of just giving up on this frame to handle cases
    // where present fence is just about to get signaled.
    const int graceTimeForPresentFenceMs =
            (mPropagateBackpressureClientComposition || !mHadClientComposition) ? 1 : 0;
    ATRACE_INT("graceTimeForPresentFenceMs", graceTimeForPresentFenceMs);

    // Pending frames may trigger backpressure propagation.

    /*
     * previousFramePending  上一帧的PresentFence的是否已经single, 没有single的话则previousFramePending 为ture
     *  说明 上一帧的 合成定然超时
     * */
    const TracedOrdinal<bool> framePending = {"PrevFramePending",
                                              previousFramePending(graceTimeForPresentFenceMs)};

    // Frame missed counts for metrics tracking.
    // A frame is missed if the prior frame is still pending. If no longer pending,
    // then we still count the frame as missed if the predicted present time
    // was further in the past than when the fence actually fired.

    // Add some slop to correct for drift. This should generally be
    // smaller than a typical frame duration, but should not be so small
    // that it reports reasonable drift as a missed frame.
    const DisplayStatInfo stats = mScheduler->getDisplayStatInfo(systemTime());
    const nsecs_t frameMissedSlop = stats.vsyncPeriod / 2;
    // 获取上一帧 PresentFence 的 sigle time
    const nsecs_t previousPresentTime = previousFramePresentTime();

    /*
     * 总结一下:
     *        previousPresentTime:上一帧 PresentFence 的 sigle time
     *        lastScheduledPresentTime:当前帧的期待的上屏时间,未来的硬件vsync时间
     *        framePending: 上一帧的合成是否超时
     *        frameMissedSlop:当前周期的一半
     * */

    /*
     * frameMissed 主要是用来 表明 当前的帧的合成  frameMissed: 用来在正式合成前预测 当前帧的合成是否错过  当前帧的期待的上屏时间
     * */
    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};
    /*
     * TracedOrdinal 重载了类型转换运算符, 故  if (frameMissed) 相当于把 TracedOrdinal 转换为  bool,
     * 触发了 类型抓换操作,根据 TracedOrdinal的定义,返回的是 TracedOrdinal.mData
     * */
    if (frameMissed) {
        mFrameMissedCount++;
        mTimeStats->incrementMissedFrames();
    }

    if (hwcFrameMissed) {
        mHwcFrameMissedCount++;
    }

    if (gpuFrameMissed) {
        mGpuFrameMissedCount++;
    }

  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
`SurfaceFlinger::latchBuffers()` 是 Android 系统中 SurfaceFlinger 的一个函数,其主要作用是将当前帧的所有 Surface 的图像数据(Buffer)复制到对应的 Display 中去。 在 Android 中,每个 Surface 都对应一个 BufferQueue,即一个 Buffer 以队列的形式存储在 Surface 中。当应用程序需要更新 Surface 上的图像时,会将新图像对应的 Buffer 放入 BufferQueue 的尾部,而 SurfaceFlinger 则会从 BufferQueue 的头部取出最新的 Buffer,并将其渲染到对应的 Display 上。 在 `latchBuffers()` 函数中,SurfaceFlinger 会先遍历所有的 Display,对于每个 Display,它会执行以下操作: 1. 获取 Display 对应的 Surface。 2. 获取 Surface 中的当前 Buffer。 3. 如果当前 Buffer 已经被刷到了 Display 上,则跳过该 Surface。 4. 否则,将当前 Buffer 的内容复制到 Display 中。 具体实现过程可以参考以下代码片段: ```c++ void SurfaceFlinger::latchBuffers() { // 遍历所有的 Display for (const auto& [displayToken, display] : mDisplays) { // 获取 Display 对应的 Surface const auto& [layerStack, z, displaySurface] = display; sp<const DisplayDevice> hw(displaySurface->getPhysicalDisplay()); if (hw == nullptr) { continue; } // 获取 Surface 中的当前 Buffer const auto& [layerStackRequest, layerRequest, releaseFence] = getLayerStackRequestAndReleaseFenceLocked(hw->getCompositionDisplayId()); const auto& [fence, buffer] = mGraphicBufferProducer->dequeueBuffer(false, false); // 如果当前 Buffer 已经被刷到了 Display 上,则跳过该 Surface if (buffer->getGenerationNumber() <= hw->getReleasedFrameNumber()) { mGraphicBufferProducer->cancelBuffer(buffer, fence); continue; } // 将当前 Buffer 的内容复制到 Display 中 hw->setReleasedFrameNumber(buffer->getGenerationNumber()); hw->compositionComplete(); mGraphicBufferProducer->queueBuffer(buffer, -1, std::move(fence)); } } ``` 需要注意的是,`latchBuffers()` 函数并不是在每次 Surface 更新时都会被调用,而是在 SurfaceFlinger 的主循环中以一定的频率被调用,以确保所有的 Surface 都能及时地被渲染到对应的 Display 上。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值