diff options
author | 2021-02-09 22:28:39 +0000 | |
---|---|---|
committer | 2021-02-09 22:28:39 +0000 | |
commit | d486b821b2534d73fcdb33c0456f441fd9b6f6f3 (patch) | |
tree | 06c605fe6fe4792e199543cee2397c25a5259a65 | |
parent | 42c3aefc765bc1aba9aad9be0cd2afa1c33862f3 (diff) | |
parent | 564f9deb6d5c9ee27bd6a84f7c6e4544ad9e174a (diff) |
Merge "SurfaceFlinger: expose vsync id extra buffers" into sc-dev
-rw-r--r-- | libs/gui/ISurfaceComposer.cpp | 22 | ||||
-rw-r--r-- | libs/gui/Surface.cpp | 15 | ||||
-rw-r--r-- | libs/gui/include/gui/ISurfaceComposer.h | 19 | ||||
-rw-r--r-- | libs/gui/include/gui/Surface.h | 2 | ||||
-rw-r--r-- | libs/gui/tests/Surface_test.cpp | 2 | ||||
-rw-r--r-- | libs/nativewindow/include/system/window.h | 6 | ||||
-rw-r--r-- | services/surfaceflinger/SurfaceFlinger.cpp | 24 | ||||
-rw-r--r-- | services/surfaceflinger/SurfaceFlinger.h | 5 | ||||
-rw-r--r-- | services/surfaceflinger/tests/unittests/SchedulerTest.cpp | 12 | ||||
-rw-r--r-- | services/surfaceflinger/tests/unittests/TestableSurfaceFlinger.h | 5 |
10 files changed, 110 insertions, 2 deletions
diff --git a/libs/gui/ISurfaceComposer.cpp b/libs/gui/ISurfaceComposer.cpp index 10d48a35bf..762746c0ce 100644 --- a/libs/gui/ISurfaceComposer.cpp +++ b/libs/gui/ISurfaceComposer.cpp @@ -1235,6 +1235,18 @@ public: } return reply.readInt32(); } + + status_t getExtraBufferCount(int* extraBuffers) const override { + Parcel data, reply; + data.writeInterfaceToken(ISurfaceComposer::getInterfaceDescriptor()); + status_t err = remote()->transact(BnSurfaceComposer::GET_EXTRA_BUFFER_COUNT, data, &reply); + if (err != NO_ERROR) { + ALOGE("getExtraBufferCount failed to read data: %s (%d)", strerror(-err), err); + return err; + } + + return reply.readInt32(extraBuffers); + } }; // Out-of-line virtual method definition to trigger vtable emission in this @@ -2107,6 +2119,16 @@ status_t BnSurfaceComposer::onTransact( SAFE_PARCEL(reply->writeInt32, priority); return NO_ERROR; } + case GET_EXTRA_BUFFER_COUNT: { + CHECK_INTERFACE(ISurfaceComposer, data, reply); + int extraBuffers = 0; + int err = getExtraBufferCount(&extraBuffers); + if (err != NO_ERROR) { + return err; + } + SAFE_PARCEL(reply->writeInt32, extraBuffers); + return NO_ERROR; + } default: { return BBinder::onTransact(code, data, reply, flags); } diff --git a/libs/gui/Surface.cpp b/libs/gui/Surface.cpp index 59ad8d28bd..07fc0694d6 100644 --- a/libs/gui/Surface.cpp +++ b/libs/gui/Surface.cpp @@ -1499,6 +1499,9 @@ int Surface::perform(int operation, va_list args) case NATIVE_WINDOW_SET_FRAME_TIMELINE_INFO: res = dispatchSetFrameTimelineInfo(args); break; + case NATIVE_WINDOW_GET_EXTRA_BUFFER_COUNT: + res = dispatchGetExtraBufferCount(args); + break; default: res = NAME_NOT_FOUND; break; @@ -1815,6 +1818,14 @@ int Surface::dispatchSetFrameTimelineInfo(va_list args) { return setFrameTimelineInfo({frameTimelineVsyncId, inputEventId}); } +int Surface::dispatchGetExtraBufferCount(va_list args) { + ATRACE_CALL(); + auto extraBuffers = static_cast<int*>(va_arg(args, int*)); + + ALOGV("Surface::dispatchGetExtraBufferCount"); + return getExtraBufferCount(extraBuffers); +} + bool Surface::transformToDisplayInverse() { return (mTransform & NATIVE_WINDOW_TRANSFORM_INVERSE_DISPLAY) == NATIVE_WINDOW_TRANSFORM_INVERSE_DISPLAY; @@ -2584,4 +2595,8 @@ status_t Surface::setFrameTimelineInfo(const FrameTimelineInfo& frameTimelineInf return composerService()->setFrameTimelineInfo(mGraphicBufferProducer, frameTimelineInfo); } +status_t Surface::getExtraBufferCount(int* extraBuffers) const { + return composerService()->getExtraBufferCount(extraBuffers); +} + }; // namespace android diff --git a/libs/gui/include/gui/ISurfaceComposer.h b/libs/gui/include/gui/ISurfaceComposer.h index 6d1a3ab334..292838e9ae 100644 --- a/libs/gui/include/gui/ISurfaceComposer.h +++ b/libs/gui/include/gui/ISurfaceComposer.h @@ -505,6 +505,24 @@ public: * Gets priority of the RenderEngine in SurfaceFlinger. */ virtual int getGPUContextPriority() = 0; + + /** + * Gets the extra buffers a client would need to allocate if it passes + * the Choreographer#getVsyncId with its buffers. + * + * When Choreographer#getVsyncId is passed to SurfaceFlinger, it is used + * as an indication of when to latch the buffer. SurfaceFlinger will make + * sure that it will give the app at least the time configured as the + * 'appDuration' before trying to latch the buffer. + * + * The total buffers needed for a given configuration is basically the + * numbers of vsyncs a single buffer is used across the stack. For the default + * configuration a buffer is held ~1 vsync by the app, ~1 vsync by SurfaceFlinger + * and 1 vsync by the display. The extra buffers are calculated as the + * number of additional buffers on top of the 3 buffers already allocated + * by the app. + */ + virtual status_t getExtraBufferCount(int* extraBuffers) const = 0; }; // ---------------------------------------------------------------------------- @@ -567,6 +585,7 @@ public: SET_FRAME_TIMELINE_INFO, ADD_TRANSACTION_TRACE_LISTENER, GET_GPU_CONTEXT_PRIORITY, + GET_EXTRA_BUFFER_COUNT, // Always append new enum to the end. }; diff --git a/libs/gui/include/gui/Surface.h b/libs/gui/include/gui/Surface.h index b6b5c7ca5e..58812214d2 100644 --- a/libs/gui/include/gui/Surface.h +++ b/libs/gui/include/gui/Surface.h @@ -189,6 +189,7 @@ public: virtual status_t setFrameRate(float frameRate, int8_t compatibility, bool shouldBeSeamless); virtual status_t setFrameTimelineInfo(const FrameTimelineInfo& info); + virtual status_t getExtraBufferCount(int* extraBuffers) const; protected: virtual ~Surface(); @@ -275,6 +276,7 @@ private: int dispatchAddQueryInterceptor(va_list args); int dispatchGetLastQueuedBuffer(va_list args); int dispatchSetFrameTimelineInfo(va_list args); + int dispatchGetExtraBufferCount(va_list args); bool transformToDisplayInverse(); protected: diff --git a/libs/gui/tests/Surface_test.cpp b/libs/gui/tests/Surface_test.cpp index 80e4c770dc..43909ac00d 100644 --- a/libs/gui/tests/Surface_test.cpp +++ b/libs/gui/tests/Surface_test.cpp @@ -889,6 +889,8 @@ public: int getGPUContextPriority() override { return 0; }; + status_t getExtraBufferCount(int* /*extraBuffers*/) const override { return NO_ERROR; } + protected: IBinder* onAsBinder() override { return nullptr; } diff --git a/libs/nativewindow/include/system/window.h b/libs/nativewindow/include/system/window.h index ffe4412b72..7aa2cf4404 100644 --- a/libs/nativewindow/include/system/window.h +++ b/libs/nativewindow/include/system/window.h @@ -256,6 +256,7 @@ enum { NATIVE_WINDOW_GET_LAST_QUEUED_BUFFER = 46, /* private */ NATIVE_WINDOW_SET_QUERY_INTERCEPTOR = 47, /* private */ NATIVE_WINDOW_SET_FRAME_TIMELINE_INFO = 48, /* private */ + NATIVE_WINDOW_GET_EXTRA_BUFFER_COUNT = 49, /* private */ // clang-format on }; @@ -1030,6 +1031,11 @@ static inline int native_window_set_frame_timeline_info(struct ANativeWindow* wi frameTimelineVsyncId, inputEventId); } +static inline int native_window_get_extra_buffer_count( + struct ANativeWindow* window, int* extraBuffers) { + return window->perform(window, NATIVE_WINDOW_GET_EXTRA_BUFFER_COUNT, extraBuffers); +} + // ------------------------------------------------------------------------------------------------ // Candidates for APEX visibility // These functions are planned to be made stable for APEX modules, but have not diff --git a/services/surfaceflinger/SurfaceFlinger.cpp b/services/surfaceflinger/SurfaceFlinger.cpp index f785cae6cb..04e9a6d3ff 100644 --- a/services/surfaceflinger/SurfaceFlinger.cpp +++ b/services/surfaceflinger/SurfaceFlinger.cpp @@ -5030,8 +5030,9 @@ status_t SurfaceFlinger::CheckTransactCodeCredentials(uint32_t code) { case CAPTURE_DISPLAY: case SET_DISPLAY_BRIGHTNESS: case SET_FRAME_TIMELINE_INFO: - // This is not sensitive information, so should not require permission control. - case GET_GPU_CONTEXT_PRIORITY: { + case GET_GPU_CONTEXT_PRIORITY: + case GET_EXTRA_BUFFER_COUNT: { + // This is not sensitive information, so should not require permission control. return OK; } case ADD_REGION_SAMPLING_LISTENER: @@ -6456,6 +6457,25 @@ int SurfaceFlinger::getGPUContextPriority() { return getRenderEngine().getContextPriority(); } +int SurfaceFlinger::calculateExtraBufferCount(Fps maxSupportedRefreshRate, + std::chrono::nanoseconds presentLatency) { + auto pipelineDepth = presentLatency.count() / maxSupportedRefreshRate.getPeriodNsecs(); + if (presentLatency.count() % maxSupportedRefreshRate.getPeriodNsecs()) { + pipelineDepth++; + } + return std::max(0ll, pipelineDepth - 2); +} + +status_t SurfaceFlinger::getExtraBufferCount(int* extraBuffers) const { + const auto maxSupportedRefreshRate = mRefreshRateConfigs->getSupportedRefreshRateRange().max; + const auto vsyncConfig = + mVsyncConfiguration->getConfigsForRefreshRate(maxSupportedRefreshRate).late; + const auto presentLatency = vsyncConfig.appWorkDuration + vsyncConfig.sfWorkDuration; + + *extraBuffers = calculateExtraBufferCount(maxSupportedRefreshRate, presentLatency); + return NO_ERROR; +} + } // namespace android #if defined(__gl_h_) diff --git a/services/surfaceflinger/SurfaceFlinger.h b/services/surfaceflinger/SurfaceFlinger.h index ed5b098fb0..a62d0b9a95 100644 --- a/services/surfaceflinger/SurfaceFlinger.h +++ b/services/surfaceflinger/SurfaceFlinger.h @@ -622,6 +622,8 @@ private: int getGPUContextPriority() override; + status_t getExtraBufferCount(int* extraBuffers) const override; + // Implements IBinder::DeathRecipient. void binderDied(const wp<IBinder>& who) override; @@ -1052,6 +1054,9 @@ private: return std::nullopt; } + static int calculateExtraBufferCount(Fps maxSupportedRefreshRate, + std::chrono::nanoseconds presentLatency); + sp<StartPropertySetThread> mStartPropertySetThread; surfaceflinger::Factory& mFactory; diff --git a/services/surfaceflinger/tests/unittests/SchedulerTest.cpp b/services/surfaceflinger/tests/unittests/SchedulerTest.cpp index 694790f86a..e46a270ea8 100644 --- a/services/surfaceflinger/tests/unittests/SchedulerTest.cpp +++ b/services/surfaceflinger/tests/unittests/SchedulerTest.cpp @@ -69,6 +69,8 @@ protected: Scheduler::ConnectionHandle mConnectionHandle; mock::EventThread* mEventThread; sp<MockEventThreadConnection> mEventThreadConnection; + + TestableSurfaceFlinger mFlinger; }; SchedulerTest::SchedulerTest() { @@ -187,4 +189,14 @@ TEST_F(SchedulerTest, onNonPrimaryDisplayModeChanged_invalidParameters) { EXPECT_CALL(*mEventThread, onModeChanged(_, _, _)).Times(0); } +TEST_F(SchedulerTest, calculateExtraBufferCount) { + EXPECT_EQ(0, mFlinger.calculateExtraBufferCount(Fps(60), 30ms)); + EXPECT_EQ(1, mFlinger.calculateExtraBufferCount(Fps(90), 30ms)); + EXPECT_EQ(2, mFlinger.calculateExtraBufferCount(Fps(120), 30ms)); + + EXPECT_EQ(1, mFlinger.calculateExtraBufferCount(Fps(60), 40ms)); + + EXPECT_EQ(0, mFlinger.calculateExtraBufferCount(Fps(60), 10ms)); +} + } // namespace android diff --git a/services/surfaceflinger/tests/unittests/TestableSurfaceFlinger.h b/services/surfaceflinger/tests/unittests/TestableSurfaceFlinger.h index 6aa6d3194d..ce2bfefc44 100644 --- a/services/surfaceflinger/tests/unittests/TestableSurfaceFlinger.h +++ b/services/surfaceflinger/tests/unittests/TestableSurfaceFlinger.h @@ -391,6 +391,11 @@ public: auto getGPUContextPriority() { return mFlinger->getGPUContextPriority(); } + auto calculateExtraBufferCount(Fps maxSupportedRefreshRate, + std::chrono::nanoseconds presentLatency) const { + return SurfaceFlinger::calculateExtraBufferCount(maxSupportedRefreshRate, presentLatency); + } + /* ------------------------------------------------------------------------ * Read-only access to private data to assert post-conditions. */ |