Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit c6feeb41 authored by Ady Abraham's avatar Ady Abraham Committed by Automerger Merge Worker
Browse files

SurfaceFlinger: refresh rate heuristic for TextureView am: c9664832

Change-Id: Ia677b7aba985cae77504ae4803e7e1c214ef4211
parents b948aed6 c9664832
Loading
Loading
Loading
Loading
+28 −5
Original line number Diff line number Diff line
@@ -111,23 +111,46 @@ std::optional<float> LayerInfoV2::calculateRefreshRateIfPossible() {

    // Calculate the refresh rate by finding the average delta between frames
    nsecs_t totalPresentTimeDeltas = 0;
    nsecs_t totalQueueTimeDeltas = 0;
    auto missingPresentTime = false;
    for (auto it = mFrameTimes.begin(); it != mFrameTimes.end() - 1; ++it) {
        // If there are no presentation timestamp provided we can't calculate the refresh rate
        totalQueueTimeDeltas +=
                std::max(((it + 1)->queueTime - it->queueTime), mHighRefreshRatePeriod);

        if (it->presetTime == 0 || (it + 1)->presetTime == 0) {
            return std::nullopt;
            missingPresentTime = true;
            continue;
        }

        totalPresentTimeDeltas +=
                std::max(((it + 1)->presetTime - it->presetTime), mHighRefreshRatePeriod);
    }

    // If there are no presentation timestamps provided we can't calculate the refresh rate
    if (missingPresentTime && mLastReportedRefreshRate == 0) {
        return std::nullopt;
    }

    // Calculate the average frame time based on presentation timestamps. If those
    // doesn't exist, we look at the time the buffer was queued only. We can do that only if
    // we calculated a refresh rate based on presentation timestamps in the past. The reason
    // we look at the queue time is to handle cases where hwui attaches presentation timestamps
    // when implementing render ahead for specific refresh rates. When hwui no longer provides
    // presentation timestamps we look at the queue time to see if the current refresh rate still
    // matches the content.
    const float averageFrameTime =
            static_cast<float>(totalPresentTimeDeltas) / (mFrameTimes.size() - 1);
            static_cast<float>(missingPresentTime ? totalQueueTimeDeltas : totalPresentTimeDeltas) /
            (mFrameTimes.size() - 1);

    // Now once we calculated the refresh rate we need to make sure that all the frames we captured
    // are evenly distributed and we don't calculate the average across some burst of frames.
    for (auto it = mFrameTimes.begin(); it != mFrameTimes.end() - 1; ++it) {
        const nsecs_t presentTimeDeltas =
                std::max(((it + 1)->presetTime - it->presetTime), mHighRefreshRatePeriod);
        const auto presentTimeDeltas = [&] {
            const auto delta = missingPresentTime ? (it + 1)->queueTime - it->queueTime
                                                  : (it + 1)->presetTime - it->presetTime;
            return std::max(delta, mHighRefreshRatePeriod);
        }();

        if (std::abs(presentTimeDeltas - averageFrameTime) > 2 * averageFrameTime) {
            return std::nullopt;
        }
+1 −0
Original line number Diff line number Diff line
@@ -88,6 +88,7 @@ public:
        // buffer as Max as we don't know anything about this layer or Min as this layer is
        // posting infrequent updates.
        mFrameTimeValidSince = std::chrono::steady_clock::now();
        mLastReportedRefreshRate = 0.0f;
    }

private: