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

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

Merge "SurfaceFlinger: frame rate heuristic during config change" into rvc-dev...

Merge "SurfaceFlinger: frame rate heuristic during config change" into rvc-dev am: 36725c77 am: 06b8b6eb am: 6da45eb0

Change-Id: I937b7f6017e505dc6a8d69f88e9b5588f384807d
parents bb7dc621 6da45eb0
Loading
Loading
Loading
Loading
+9 −0
Original line number Original line Diff line number Diff line
@@ -52,6 +52,8 @@ public:
    // Sets the display size. Client is responsible for synchronization.
    // Sets the display size. Client is responsible for synchronization.
    virtual void setDisplayArea(uint32_t displayArea) = 0;
    virtual void setDisplayArea(uint32_t displayArea) = 0;


    virtual void setConfigChangePending(bool pending) = 0;

    // Marks the layer as active, and records the given state to its history.
    // Marks the layer as active, and records the given state to its history.
    virtual void record(Layer*, nsecs_t presentTime, nsecs_t now) = 0;
    virtual void record(Layer*, nsecs_t presentTime, nsecs_t now) = 0;


@@ -78,6 +80,8 @@ public:


    void setDisplayArea(uint32_t /*displayArea*/) override {}
    void setDisplayArea(uint32_t /*displayArea*/) override {}


    void setConfigChangePending(bool /*pending*/) override {}

    // Marks the layer as active, and records the given state to its history.
    // Marks the layer as active, and records the given state to its history.
    void record(Layer*, nsecs_t presentTime, nsecs_t now) override;
    void record(Layer*, nsecs_t presentTime, nsecs_t now) override;


@@ -134,6 +138,8 @@ public:
    // Sets the display size. Client is responsible for synchronization.
    // Sets the display size. Client is responsible for synchronization.
    void setDisplayArea(uint32_t displayArea) override { mDisplayArea = displayArea; }
    void setDisplayArea(uint32_t displayArea) override { mDisplayArea = displayArea; }


    void setConfigChangePending(bool pending) override { mConfigChangePending = pending; }

    // Marks the layer as active, and records the given state to its history.
    // Marks the layer as active, and records the given state to its history.
    void record(Layer*, nsecs_t presentTime, nsecs_t now) override;
    void record(Layer*, nsecs_t presentTime, nsecs_t now) override;


@@ -178,6 +184,9 @@ private:


    // Whether to use priority sent from WindowManager to determine the relevancy of the layer.
    // Whether to use priority sent from WindowManager to determine the relevancy of the layer.
    const bool mUseFrameRatePriority;
    const bool mUseFrameRatePriority;

    // Whether a config change is in progress or not
    std::atomic<bool> mConfigChangePending = false;
};
};


} // namespace impl
} // namespace impl
+1 −1
Original line number Original line Diff line number Diff line
@@ -103,7 +103,7 @@ void LayerHistoryV2::record(Layer* layer, nsecs_t presentTime, nsecs_t now) {
    LOG_FATAL_IF(it == mLayerInfos.end(), "%s: unknown layer %p", __FUNCTION__, layer);
    LOG_FATAL_IF(it == mLayerInfos.end(), "%s: unknown layer %p", __FUNCTION__, layer);


    const auto& info = it->second;
    const auto& info = it->second;
    info->setLastPresentTime(presentTime, now);
    info->setLastPresentTime(presentTime, now, mConfigChangePending);


    // Activate layer if inactive.
    // Activate layer if inactive.
    if (const auto end = activeLayers().end(); it >= end) {
    if (const auto end = activeLayers().end(); it >= end) {
+46 −22
Original line number Original line Diff line number Diff line
@@ -34,12 +34,15 @@ LayerInfoV2::LayerInfoV2(const std::string& name, nsecs_t highRefreshRatePeriod,
        mDefaultVote(defaultVote),
        mDefaultVote(defaultVote),
        mLayerVote({defaultVote, 0.0f}) {}
        mLayerVote({defaultVote, 0.0f}) {}


void LayerInfoV2::setLastPresentTime(nsecs_t lastPresentTime, nsecs_t now) {
void LayerInfoV2::setLastPresentTime(nsecs_t lastPresentTime, nsecs_t now,
                                     bool pendingConfigChange) {
    lastPresentTime = std::max(lastPresentTime, static_cast<nsecs_t>(0));
    lastPresentTime = std::max(lastPresentTime, static_cast<nsecs_t>(0));


    mLastUpdatedTime = std::max(lastPresentTime, now);
    mLastUpdatedTime = std::max(lastPresentTime, now);


    FrameTimeData frameTime = {.presetTime = lastPresentTime, .queueTime = mLastUpdatedTime};
    FrameTimeData frameTime = {.presetTime = lastPresentTime,
                               .queueTime = mLastUpdatedTime,
                               .pendingConfigChange = pendingConfigChange};


    mFrameTimes.push_back(frameTime);
    mFrameTimes.push_back(frameTime);
    if (mFrameTimes.size() > HISTORY_SIZE) {
    if (mFrameTimes.size() > HISTORY_SIZE) {
@@ -80,21 +83,20 @@ bool LayerInfoV2::hasEnoughDataForHeuristic() const {
    return true;
    return true;
}
}


std::optional<float> LayerInfoV2::calculateRefreshRateIfPossible() {
std::pair<nsecs_t, bool> LayerInfoV2::calculateAverageFrameTime() const {
    static constexpr float MARGIN = 1.0f; // 1Hz

    if (!hasEnoughDataForHeuristic()) {
        ALOGV("Not enough data");
        return std::nullopt;
    }

    // Calculate the refresh rate by finding the average delta between frames
    nsecs_t totalPresentTimeDeltas = 0;
    nsecs_t totalPresentTimeDeltas = 0;
    nsecs_t totalQueueTimeDeltas = 0;
    nsecs_t totalQueueTimeDeltas = 0;
    auto missingPresentTime = false;
    bool missingPresentTime = false;
    int numFrames = 0;
    for (auto it = mFrameTimes.begin(); it != mFrameTimes.end() - 1; ++it) {
    for (auto it = mFrameTimes.begin(); it != mFrameTimes.end() - 1; ++it) {
        // Ignore frames captured during a config change
        if (it->pendingConfigChange || (it + 1)->pendingConfigChange) {
            continue;
        }

        totalQueueTimeDeltas +=
        totalQueueTimeDeltas +=
                std::max(((it + 1)->queueTime - it->queueTime), mHighRefreshRatePeriod);
                std::max(((it + 1)->queueTime - it->queueTime), mHighRefreshRatePeriod);
        numFrames++;


        if (it->presetTime == 0 || (it + 1)->presetTime == 0) {
        if (it->presetTime == 0 || (it + 1)->presetTime == 0) {
            missingPresentTime = true;
            missingPresentTime = true;
@@ -105,11 +107,6 @@ std::optional<float> LayerInfoV2::calculateRefreshRateIfPossible() {
                std::max(((it + 1)->presetTime - it->presetTime), mHighRefreshRatePeriod);
                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
    // 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
    // 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 calculated a refresh rate based on presentation timestamps in the past. The reason
@@ -117,13 +114,18 @@ std::optional<float> LayerInfoV2::calculateRefreshRateIfPossible() {
    // when implementing render ahead for specific refresh rates. When hwui no longer provides
    // 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
    // presentation timestamps we look at the queue time to see if the current refresh rate still
    // matches the content.
    // matches the content.
    const float averageFrameTime =
    const auto averageFrameTime =
            static_cast<float>(missingPresentTime ? totalQueueTimeDeltas : totalPresentTimeDeltas) /
            static_cast<float>(missingPresentTime ? totalQueueTimeDeltas : totalPresentTimeDeltas) /
            (mFrameTimes.size() - 1);
            numFrames;
    return {static_cast<nsecs_t>(averageFrameTime), missingPresentTime};
}


    // Now once we calculated the refresh rate we need to make sure that all the frames we captured
bool LayerInfoV2::isRefreshRateStable(nsecs_t averageFrameTime, bool missingPresentTime) const {
    // 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) {
    for (auto it = mFrameTimes.begin(); it != mFrameTimes.end() - 1; ++it) {
        // Ignore frames captured during a config change
        if (it->pendingConfigChange || (it + 1)->pendingConfigChange) {
            continue;
        }
        const auto presentTimeDeltas = [&] {
        const auto presentTimeDeltas = [&] {
            const auto delta = missingPresentTime ? (it + 1)->queueTime - it->queueTime
            const auto delta = missingPresentTime ? (it + 1)->queueTime - it->queueTime
                                                  : (it + 1)->presetTime - it->presetTime;
                                                  : (it + 1)->presetTime - it->presetTime;
@@ -131,8 +133,30 @@ std::optional<float> LayerInfoV2::calculateRefreshRateIfPossible() {
        }();
        }();


        if (std::abs(presentTimeDeltas - averageFrameTime) > 2 * averageFrameTime) {
        if (std::abs(presentTimeDeltas - averageFrameTime) > 2 * averageFrameTime) {
            return false;
        }
    }

    return true;
}

std::optional<float> LayerInfoV2::calculateRefreshRateIfPossible() {
    static constexpr float MARGIN = 1.0f; // 1Hz

    if (!hasEnoughDataForHeuristic()) {
        ALOGV("Not enough data");
        return std::nullopt;
        return std::nullopt;
    }
    }

    const auto [averageFrameTime, missingPresentTime] = calculateAverageFrameTime();

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

    if (!isRefreshRateStable(averageFrameTime, missingPresentTime)) {
        return std::nullopt;
    }
    }


    const auto refreshRate = 1e9f / averageFrameTime;
    const auto refreshRate = 1e9f / averageFrameTime;
+4 −1
Original line number Original line Diff line number Diff line
@@ -63,7 +63,7 @@ public:
    // Records the last requested present time. It also stores information about when
    // Records the last requested present time. It also stores information about when
    // the layer was last updated. If the present time is farther in the future than the
    // the layer was last updated. If the present time is farther in the future than the
    // updated time, the updated time is the present time.
    // updated time, the updated time is the present time.
    void setLastPresentTime(nsecs_t lastPresentTime, nsecs_t now);
    void setLastPresentTime(nsecs_t lastPresentTime, nsecs_t now, bool pendingConfigChange);


    // Sets an explicit layer vote. This usually comes directly from the application via
    // Sets an explicit layer vote. This usually comes directly from the application via
    // ANativeWindow_setFrameRate API
    // ANativeWindow_setFrameRate API
@@ -93,11 +93,14 @@ private:
    struct FrameTimeData {
    struct FrameTimeData {
        nsecs_t presetTime; // desiredPresentTime, if provided
        nsecs_t presetTime; // desiredPresentTime, if provided
        nsecs_t queueTime;  // buffer queue time
        nsecs_t queueTime;  // buffer queue time
        bool pendingConfigChange;
    };
    };


    bool isFrequent(nsecs_t now) const;
    bool isFrequent(nsecs_t now) const;
    bool hasEnoughDataForHeuristic() const;
    bool hasEnoughDataForHeuristic() const;
    std::optional<float> calculateRefreshRateIfPossible();
    std::optional<float> calculateRefreshRateIfPossible();
    std::pair<nsecs_t, bool> calculateAverageFrameTime() const;
    bool isRefreshRateStable(nsecs_t averageFrameTime, bool missingPresentTime) const;


    const std::string mName;
    const std::string mName;


+6 −0
Original line number Original line Diff line number Diff line
@@ -423,6 +423,12 @@ void Scheduler::recordLayerHistory(Layer* layer, nsecs_t presentTime) {
    }
    }
}
}


void Scheduler::setConfigChangePending(bool pending) {
    if (mLayerHistory) {
        mLayerHistory->setConfigChangePending(pending);
    }
}

void Scheduler::chooseRefreshRateForContent() {
void Scheduler::chooseRefreshRateForContent() {
    if (!mLayerHistory) return;
    if (!mLayerHistory) return;


Loading