diff options
| author | 2020-07-16 18:39:33 -0700 | |
|---|---|---|
| committer | 2020-07-17 23:02:56 +0000 | |
| commit | 29d0da35d9024daf4b14d6b3d3843ae5216ec4e7 (patch) | |
| tree | 83d1293e8c29b3c82aa768980b93cb3fe51e45a4 | |
| parent | 6c420207c528ac887cefecfbe00cf1fd686ad7db (diff) | |
SF: add a spinner to refresh rate overlay
Add a spinner to refresh rate overlay to visualize when the
display updates.
Test: adb shell setprop sf.debug.show_refresh_rate_overlay_spinner 1
and enable refresh rate overlay
Change-Id: I089df8437cffb45ef631772fe0179970f21abfa0
| -rw-r--r-- | services/surfaceflinger/RefreshRateOverlay.cpp | 98 | ||||
| -rw-r--r-- | services/surfaceflinger/RefreshRateOverlay.h | 15 | ||||
| -rw-r--r-- | services/surfaceflinger/SurfaceFlinger.cpp | 10 | ||||
| -rw-r--r-- | services/surfaceflinger/SurfaceFlinger.h | 2 |
4 files changed, 91 insertions, 34 deletions
diff --git a/services/surfaceflinger/RefreshRateOverlay.cpp b/services/surfaceflinger/RefreshRateOverlay.cpp index f602412930..d8477e7bc2 100644 --- a/services/surfaceflinger/RefreshRateOverlay.cpp +++ b/services/surfaceflinger/RefreshRateOverlay.cpp @@ -106,41 +106,71 @@ void RefreshRateOverlay::SevenSegmentDrawer::drawDigit(int digit, int left, cons drawSegment(Segment::Buttom, left, color, buffer, pixels); } -sp<GraphicBuffer> RefreshRateOverlay::SevenSegmentDrawer::drawNumber(int number, - const half4& color) { - if (number < 0 || number > 1000) return nullptr; +std::vector<sp<GraphicBuffer>> RefreshRateOverlay::SevenSegmentDrawer::drawNumber( + int number, const half4& color, bool showSpinner) { + if (number < 0 || number > 1000) return {}; const auto hundreds = number / 100; const auto tens = (number / 10) % 10; const auto ones = number % 10; - sp<GraphicBuffer> buffer = - new GraphicBuffer(BUFFER_WIDTH, BUFFER_HEIGHT, HAL_PIXEL_FORMAT_RGBA_8888, 1, - GRALLOC_USAGE_SW_WRITE_RARELY | GRALLOC_USAGE_HW_COMPOSER | - GRALLOC_USAGE_HW_TEXTURE, - "RefreshRateOverlayBuffer"); - uint8_t* pixels; - buffer->lock(GRALLOC_USAGE_SW_WRITE_RARELY, reinterpret_cast<void**>(&pixels)); - // Clear buffer content - drawRect(Rect(BUFFER_WIDTH, BUFFER_HEIGHT), half4(0), buffer, pixels); - int left = 0; - if (hundreds != 0) { - drawDigit(hundreds, left, color, buffer, pixels); + std::vector<sp<GraphicBuffer>> buffers; + const auto loopCount = showSpinner ? 6 : 1; + for (int i = 0; i < loopCount; i++) { + sp<GraphicBuffer> buffer = + new GraphicBuffer(BUFFER_WIDTH, BUFFER_HEIGHT, HAL_PIXEL_FORMAT_RGBA_8888, 1, + GRALLOC_USAGE_SW_WRITE_RARELY | GRALLOC_USAGE_HW_COMPOSER | + GRALLOC_USAGE_HW_TEXTURE, + "RefreshRateOverlayBuffer"); + uint8_t* pixels; + buffer->lock(GRALLOC_USAGE_SW_WRITE_RARELY, reinterpret_cast<void**>(&pixels)); + // Clear buffer content + drawRect(Rect(BUFFER_WIDTH, BUFFER_HEIGHT), half4(0), buffer, pixels); + int left = 0; + if (hundreds != 0) { + drawDigit(hundreds, left, color, buffer, pixels); + } left += DIGIT_WIDTH + DIGIT_SPACE; - } - if (tens != 0) { - drawDigit(tens, left, color, buffer, pixels); + if (tens != 0) { + drawDigit(tens, left, color, buffer, pixels); + } left += DIGIT_WIDTH + DIGIT_SPACE; - } - drawDigit(ones, left, color, buffer, pixels); - buffer->unlock(); - return buffer; + drawDigit(ones, left, color, buffer, pixels); + left += DIGIT_WIDTH + DIGIT_SPACE; + + if (showSpinner) { + switch (i) { + case 0: + drawSegment(Segment::Upper, left, color, buffer, pixels); + break; + case 1: + drawSegment(Segment::UpperRight, left, color, buffer, pixels); + break; + case 2: + drawSegment(Segment::LowerRight, left, color, buffer, pixels); + break; + case 3: + drawSegment(Segment::Buttom, left, color, buffer, pixels); + break; + case 4: + drawSegment(Segment::LowerLeft, left, color, buffer, pixels); + break; + case 5: + drawSegment(Segment::UpperLeft, left, color, buffer, pixels); + break; + } + } + + buffer->unlock(); + buffers.emplace_back(buffer); + } + return buffers; } -RefreshRateOverlay::RefreshRateOverlay(SurfaceFlinger& flinger) - : mFlinger(flinger), mClient(new Client(&mFlinger)) { +RefreshRateOverlay::RefreshRateOverlay(SurfaceFlinger& flinger, bool showSpinner) + : mFlinger(flinger), mClient(new Client(&mFlinger)), mShowSpinner(showSpinner) { createLayer(); primeCache(); } @@ -176,7 +206,7 @@ void RefreshRateOverlay::primeCache() { if (allRefreshRates.size() == 1) { auto fps = allRefreshRates.begin()->second->getFps(); half4 color = {LOW_FPS_COLOR, ALPHA}; - mBufferCache.emplace(fps, SevenSegmentDrawer::drawNumber(fps, color)); + mBufferCache.emplace(fps, SevenSegmentDrawer::drawNumber(fps, color, mShowSpinner)); return; } @@ -196,12 +226,12 @@ void RefreshRateOverlay::primeCache() { color.g = HIGH_FPS_COLOR.g * fpsScale + LOW_FPS_COLOR.g * (1 - fpsScale); color.b = HIGH_FPS_COLOR.b * fpsScale + LOW_FPS_COLOR.b * (1 - fpsScale); color.a = ALPHA; - mBufferCache.emplace(fps, SevenSegmentDrawer::drawNumber(fps, color)); + mBufferCache.emplace(fps, SevenSegmentDrawer::drawNumber(fps, color, mShowSpinner)); } } void RefreshRateOverlay::setViewport(ui::Size viewport) { - Rect frame(viewport.width >> 3, viewport.height >> 5); + Rect frame((3 * viewport.width) >> 4, viewport.height >> 5); frame.offsetBy(viewport.width >> 5, viewport.height >> 4); mLayer->setFrame(frame); @@ -209,7 +239,19 @@ void RefreshRateOverlay::setViewport(ui::Size viewport) { } void RefreshRateOverlay::changeRefreshRate(const RefreshRate& refreshRate) { - auto buffer = mBufferCache[refreshRate.getFps()]; + mCurrentFps = refreshRate.getFps(); + auto buffer = mBufferCache[*mCurrentFps][mFrame]; + mLayer->setBuffer(buffer, Fence::NO_FENCE, 0, 0, {}); + + mFlinger.mTransactionFlags.fetch_or(eTransactionMask); +} + +void RefreshRateOverlay::onInvalidate() { + if (!mCurrentFps.has_value()) return; + + const auto& buffers = mBufferCache[*mCurrentFps]; + mFrame = (mFrame + 1) % buffers.size(); + auto buffer = buffers[mFrame]; mLayer->setBuffer(buffer, Fence::NO_FENCE, 0, 0, {}); mFlinger.mTransactionFlags.fetch_or(eTransactionMask); diff --git a/services/surfaceflinger/RefreshRateOverlay.h b/services/surfaceflinger/RefreshRateOverlay.h index 35c80201d7..1a8938fbd4 100644 --- a/services/surfaceflinger/RefreshRateOverlay.h +++ b/services/surfaceflinger/RefreshRateOverlay.h @@ -38,15 +38,17 @@ using RefreshRate = scheduler::RefreshRateConfigs::RefreshRate; class RefreshRateOverlay { public: - explicit RefreshRateOverlay(SurfaceFlinger&); + RefreshRateOverlay(SurfaceFlinger&, bool showSpinner); void setViewport(ui::Size); void changeRefreshRate(const RefreshRate&); + void onInvalidate(); private: class SevenSegmentDrawer { public: - static sp<GraphicBuffer> drawNumber(int number, const half4& color); + static std::vector<sp<GraphicBuffer>> drawNumber(int number, const half4& color, + bool showSpinner); static uint32_t getHeight() { return BUFFER_HEIGHT; } static uint32_t getWidth() { return BUFFER_WIDTH; } @@ -65,7 +67,7 @@ private: static constexpr uint32_t DIGIT_SPACE = 16; static constexpr uint32_t BUFFER_HEIGHT = DIGIT_HEIGHT; static constexpr uint32_t BUFFER_WIDTH = - 3 * DIGIT_WIDTH + 2 * DIGIT_SPACE; // Digit|Space|Digit|Space|Digit + 4 * DIGIT_WIDTH + 3 * DIGIT_SPACE; // Digit|Space|Digit|Space|Digit|Space|Spinner }; bool createLayer(); @@ -77,11 +79,14 @@ private: sp<IBinder> mIBinder; sp<IGraphicBufferProducer> mGbp; - std::unordered_map<int, sp<GraphicBuffer>> mBufferCache; - + std::unordered_map<int, std::vector<sp<GraphicBuffer>>> mBufferCache; + std::optional<int> mCurrentFps; + int mFrame = 0; static constexpr float ALPHA = 0.8f; const half3 LOW_FPS_COLOR = half3(1.0f, 0.0f, 0.0f); const half3 HIGH_FPS_COLOR = half3(0.0f, 1.0f, 0.0f); + + const bool mShowSpinner; }; } // namespace android diff --git a/services/surfaceflinger/SurfaceFlinger.cpp b/services/surfaceflinger/SurfaceFlinger.cpp index aa7b90348a..1f8e588391 100644 --- a/services/surfaceflinger/SurfaceFlinger.cpp +++ b/services/surfaceflinger/SurfaceFlinger.cpp @@ -469,6 +469,8 @@ SurfaceFlinger::SurfaceFlinger(Factory& factory) : SurfaceFlinger(factory, SkipI mKernelIdleTimerEnabled = mSupportKernelIdleTimer = sysprop::support_kernel_idle_timer(false); base::SetProperty(KERNEL_IDLE_TIMER_PROP, mKernelIdleTimerEnabled ? "true" : "false"); + + mRefreshRateOverlaySpinner = property_get_bool("sf.debug.show_refresh_rate_overlay_spinner", 0); } SurfaceFlinger::~SurfaceFlinger() = default; @@ -1964,6 +1966,12 @@ void SurfaceFlinger::onMessageInvalidate(nsecs_t expectedVSyncTime) { mTracingEnabledChanged = false; } + if (mRefreshRateOverlaySpinner) { + if (Mutex::Autolock lock(mStateLock); mRefreshRateOverlay) { + mRefreshRateOverlay->onInvalidate(); + } + } + bool refreshNeeded; { ConditionalLockGuard<std::mutex> lock(mTracingLock, mTracingEnabled); @@ -6253,7 +6261,7 @@ void SurfaceFlinger::enableRefreshRateOverlay(bool enable) { static_cast<void>(schedule([=] { std::unique_ptr<RefreshRateOverlay> overlay; if (enable) { - overlay = std::make_unique<RefreshRateOverlay>(*this); + overlay = std::make_unique<RefreshRateOverlay>(*this, mRefreshRateOverlaySpinner); } { diff --git a/services/surfaceflinger/SurfaceFlinger.h b/services/surfaceflinger/SurfaceFlinger.h index 7ab0729f35..d56321da0c 100644 --- a/services/surfaceflinger/SurfaceFlinger.h +++ b/services/surfaceflinger/SurfaceFlinger.h @@ -547,6 +547,8 @@ private: bool mKernelIdleTimerEnabled = false; // Keeps track of whether the kernel timer is supported on the SF side. bool mSupportKernelIdleTimer = false; + // Show spinner with refresh rate overlay + bool mRefreshRateOverlaySpinner = false; /* ------------------------------------------------------------------------ * Message handling */ |