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

Commit 7ab5603a authored by Ana Krulec's avatar Ana Krulec
Browse files

SF: Adding dynamic switching between 30 and 60 Hz in Scheduler.

Turn on frame skipping when 30Hz.
Record FPS in systrace: 24, 30, 60.

Results from paying youtube app:
file:///Users/akrulec/Desktop/scheduler_24_fps_trace.html
file:///Users/akrulec/Desktop/scheduler_30_fps_trace.html
file:///Users/akrulec/Desktop/scheduler_60_fps_trace.html

see go/surface-flinger-scheduler for more info.

Test: SF tests pass.
Change-Id: Ief8efbd5f16a74ed8f84906cb341a368118423a7
parent c556dfee
Loading
Loading
Loading
Loading
+5 −0
Original line number Diff line number Diff line
@@ -353,6 +353,11 @@ void BufferQueueLayer::setHwcLayerBuffer(const sp<const DisplayDevice>& display)
void BufferQueueLayer::onFrameAvailable(const BufferItem& item) {
    // Add this buffer from our internal queue tracker
    { // Autolock scope
        // Report the timestamp to the Scheduler.
        if (mFlinger->mUseScheduler) {
            mFlinger->mScheduler->addNewFrameTimestamp(item.mTimestamp, item.mIsAutoTimestamp);
        }

        Mutex::Autolock lock(mQueueItemLock);
        // Reset the frame number tracker when we receive the first buffer after
        // a frame number reset
+58 −0
Original line number Diff line number Diff line
@@ -14,11 +14,14 @@
 * limitations under the License.
 */

#define ATRACE_TAG ATRACE_TAG_GRAPHICS

#include "Scheduler.h"

#include <cinttypes>
#include <cstdint>
#include <memory>
#include <numeric>

#include <android/hardware/configstore/1.0/ISurfaceFlingerConfigs.h>
#include <android/hardware/configstore/1.1/ISurfaceFlingerConfigs.h>
@@ -27,6 +30,7 @@

#include <gui/ISurfaceComposer.h>
#include <ui/DisplayStatInfo.h>
#include <utils/Trace.h>

#include "DispSync.h"
#include "DispSyncSource.h"
@@ -196,4 +200,58 @@ void Scheduler::setIgnorePresentFences(bool ignore) {
    mPrimaryDispSync->setIgnorePresentFences(ignore);
}

void Scheduler::makeHWSyncAvailable(bool makeAvailable) {
    std::lock_guard<std::mutex> lock(mHWVsyncLock);
    mHWVsyncAvailable = makeAvailable;
}

void Scheduler::addNewFrameTimestamp(const nsecs_t newFrameTimestamp, bool isAutoTimestamp) {
    ATRACE_INT("AutoTimestamp", isAutoTimestamp);
    // Video does not have timestamp automatically set, so we discard timestamps that are
    // coming in from other sources for now.
    if (isAutoTimestamp) {
        return;
    }
    int64_t differenceMs = (newFrameTimestamp - mPreviousFrameTimestamp) / 1000000;
    mPreviousFrameTimestamp = newFrameTimestamp;

    if (differenceMs < 10 || differenceMs > 100) {
        // Dismiss noise.
        return;
    }
    ATRACE_INT("TimestampDiff", differenceMs);

    mTimeDifferences[mCounter % ARRAY_SIZE] = differenceMs;
    mCounter++;
    nsecs_t average = calculateAverage();
    ATRACE_INT("TimestampAverage", average);

    // TODO(b/113612090): This are current numbers from trial and error while running videos
    // from YouTube at 24, 30, and 60 fps.
    if (average > 14 && average < 18) {
        ATRACE_INT("FPS", 60);
    } else if (average > 31 && average < 34) {
        ATRACE_INT("FPS", 30);
        updateFrameSkipping(1);
        return;
    } else if (average > 39 && average < 42) {
        ATRACE_INT("FPS", 24);
    }
    updateFrameSkipping(0);
}

nsecs_t Scheduler::calculateAverage() const {
    nsecs_t sum = std::accumulate(mTimeDifferences.begin(), mTimeDifferences.end(), 0);
    return (sum / ARRAY_SIZE);
}

void Scheduler::updateFrameSkipping(const int64_t skipCount) {
    ATRACE_INT("FrameSkipCount", skipCount);
    if (mSkipCount != skipCount) {
        // Only update DispSync if it hasn't been updated yet.
        mPrimaryDispSync->setRefreshSkipCount(skipCount);
        mSkipCount = skipCount;
    }
}

} // namespace android
+18 −1
Original line number Diff line number Diff line
@@ -102,6 +102,8 @@ public:
    void addResyncSample(const nsecs_t timestamp);
    void addPresentFence(const std::shared_ptr<FenceTime>& fenceTime);
    void setIgnorePresentFences(bool ignore);
    void makeHWSyncAvailable(bool makeAvailable);
    void addNewFrameTimestamp(const nsecs_t newFrameTimestamp, bool isAutoTimestamp);

protected:
    virtual std::unique_ptr<EventThread> makeEventThread(
@@ -110,6 +112,9 @@ protected:
            impl::EventThread::InterceptVSyncsCallback interceptCallback);

private:
    nsecs_t calculateAverage() const;
    void updateFrameSkipping(const int64_t skipCount);

    // TODO(b/113612090): Instead of letting BufferQueueLayer to access mDispSync directly, it
    // should make request to Scheduler to compute next refresh.
    friend class BufferQueueLayer;
@@ -133,6 +138,18 @@ private:

    std::unique_ptr<DispSync> mPrimaryDispSync;
    std::unique_ptr<EventControlThread> mEventControlThread;

    // TODO(b/113612090): The following set of variables needs to be revised. For now, this is
    // a proof of concept. We turn on frame skipping if the difference between the timestamps
    // is between 32 and 34ms. We expect this currently for 30fps videos, so we render them at 30Hz.
    nsecs_t mPreviousFrameTimestamp = 0;
    // Keeping track of whether we are skipping the refresh count. If we want to
    // simulate 30Hz rendering, we skip every other frame, and this variable is set
    // to 1.
    int64_t mSkipCount = 0;
    static constexpr size_t ARRAY_SIZE = 30;
    std::array<int64_t, ARRAY_SIZE> mTimeDifferences;
    size_t mCounter = 0;
};

} // namespace android
+4 −0
Original line number Diff line number Diff line
@@ -1245,6 +1245,10 @@ void SurfaceFlinger::resyncToHardwareVsync(bool makeAvailable) {

    if (makeAvailable) {
        mHWVsyncAvailable = true;
        // TODO(b/113612090): This is silly, but necessary evil until we turn on the flag for good.
        if (mUseScheduler) {
            mScheduler->makeHWSyncAvailable(true);
        }
    } else if (!mHWVsyncAvailable) {
        // Hardware vsync is not currently available, so abort the resync
        // attempt for now