Loading services/surfaceflinger/BufferQueueLayer.cpp +5 −0 Original line number Diff line number Diff line Loading @@ -352,6 +352,11 @@ void BufferQueueLayer::setHwcLayerBuffer(DisplayId displayId) { 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 Loading services/surfaceflinger/Scheduler/Scheduler.cpp +58 −0 Original line number Diff line number Diff line Loading @@ -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> Loading @@ -27,6 +30,7 @@ #include <gui/ISurfaceComposer.h> #include <ui/DisplayStatInfo.h> #include <utils/Trace.h> #include "DispSync.h" #include "DispSyncSource.h" Loading Loading @@ -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 services/surfaceflinger/Scheduler/Scheduler.h +18 −1 Original line number Diff line number Diff line Loading @@ -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( Loading @@ -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; Loading @@ -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 services/surfaceflinger/SurfaceFlinger.cpp +4 −0 Original line number Diff line number Diff line Loading @@ -1255,6 +1255,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 Loading Loading
services/surfaceflinger/BufferQueueLayer.cpp +5 −0 Original line number Diff line number Diff line Loading @@ -352,6 +352,11 @@ void BufferQueueLayer::setHwcLayerBuffer(DisplayId displayId) { 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 Loading
services/surfaceflinger/Scheduler/Scheduler.cpp +58 −0 Original line number Diff line number Diff line Loading @@ -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> Loading @@ -27,6 +30,7 @@ #include <gui/ISurfaceComposer.h> #include <ui/DisplayStatInfo.h> #include <utils/Trace.h> #include "DispSync.h" #include "DispSyncSource.h" Loading Loading @@ -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
services/surfaceflinger/Scheduler/Scheduler.h +18 −1 Original line number Diff line number Diff line Loading @@ -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( Loading @@ -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; Loading @@ -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
services/surfaceflinger/SurfaceFlinger.cpp +4 −0 Original line number Diff line number Diff line Loading @@ -1255,6 +1255,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 Loading