diff options
18 files changed, 155 insertions, 88 deletions
diff --git a/libs/gui/BLASTBufferQueue.cpp b/libs/gui/BLASTBufferQueue.cpp index 8024482531..52d3fa33f0 100644 --- a/libs/gui/BLASTBufferQueue.cpp +++ b/libs/gui/BLASTBufferQueue.cpp @@ -159,9 +159,7 @@ BLASTBufferQueue::BLASTBufferQueue(const std::string& name, const sp<SurfaceCont mBufferItemConsumer->setDefaultBufferFormat(convertBufferFormat(format)); mBufferItemConsumer->setBlastBufferQueue(this); - int extraBufferCount = 0; - ComposerService::getComposerService()->getExtraBufferCount(&extraBufferCount); - mMaxAcquiredBuffers = 1 + extraBufferCount; + ComposerService::getComposerService()->getMaxAcquiredBufferCount(&mMaxAcquiredBuffers); mBufferItemConsumer->setMaxAcquiredBufferCount(mMaxAcquiredBuffers); mTransformHint = mSurfaceControl->getTransformHint(); @@ -308,18 +306,20 @@ void BLASTBufferQueue::transactionCallback(nsecs_t /*latchTime*/, const sp<Fence // So we pass in a weak pointer to the BBQ and if it still alive, then we release the buffer. // Otherwise, this is a no-op. static void releaseBufferCallbackThunk(wp<BLASTBufferQueue> context, uint64_t graphicBufferId, - const sp<Fence>& releaseFence, uint32_t transformHint) { + const sp<Fence>& releaseFence, uint32_t transformHint, + uint32_t currentMaxAcquiredBufferCount) { sp<BLASTBufferQueue> blastBufferQueue = context.promote(); ALOGV("releaseBufferCallbackThunk graphicBufferId=%" PRIu64 " blastBufferQueue=%s", graphicBufferId, blastBufferQueue ? "alive" : "dead"); if (blastBufferQueue) { - blastBufferQueue->releaseBufferCallback(graphicBufferId, releaseFence, transformHint); + blastBufferQueue->releaseBufferCallback(graphicBufferId, releaseFence, transformHint, + currentMaxAcquiredBufferCount); } } void BLASTBufferQueue::releaseBufferCallback(uint64_t graphicBufferId, - const sp<Fence>& releaseFence, - uint32_t transformHint) { + const sp<Fence>& releaseFence, uint32_t transformHint, + uint32_t currentMaxAcquiredBufferCount) { ATRACE_CALL(); std::unique_lock _lock{mMutex}; BQA_LOGV("releaseBufferCallback graphicBufferId=%" PRIu64, graphicBufferId); @@ -330,15 +330,36 @@ void BLASTBufferQueue::releaseBufferCallback(uint64_t graphicBufferId, mBufferItemConsumer->setTransformHint(mTransformHint); } - auto it = mSubmitted.find(graphicBufferId); - if (it == mSubmitted.end()) { - BQA_LOGE("ERROR: releaseBufferCallback without corresponding submitted buffer %" PRIu64, - graphicBufferId); - return; + // Calculate how many buffers we need to hold before we release them back + // to the buffer queue. This will prevent higher latency when we are running + // on a lower refresh rate than the max supported. We only do that for EGL + // clients as others don't care about latency + const bool isEGL = [&] { + const auto it = mSubmitted.find(graphicBufferId); + return it != mSubmitted.end() && it->second.mApi == NATIVE_WINDOW_API_EGL; + }(); + + const auto numPendingBuffersToHold = + isEGL ? std::max(0u, mMaxAcquiredBuffers - currentMaxAcquiredBufferCount) : 0; + mPendingRelease.emplace_back(ReleasedBuffer{graphicBufferId, releaseFence}); + + // Release all buffers that are beyond the ones that we need to hold + while (mPendingRelease.size() > numPendingBuffersToHold) { + const auto releaseBuffer = mPendingRelease.front(); + mPendingRelease.pop_front(); + auto it = mSubmitted.find(releaseBuffer.bufferId); + if (it == mSubmitted.end()) { + BQA_LOGE("ERROR: releaseBufferCallback without corresponding submitted buffer %" PRIu64, + graphicBufferId); + return; + } + + mBufferItemConsumer->releaseBuffer(it->second, releaseBuffer.releaseFence); + mSubmitted.erase(it); } - mBufferItemConsumer->releaseBuffer(it->second, releaseFence); - mSubmitted.erase(it); + ATRACE_INT("PendingRelease", mPendingRelease.size()); + mNumAcquired--; processNextBufferLocked(false /* useNextTransaction */); mCallbackCV.notify_all(); @@ -420,7 +441,8 @@ void BLASTBufferQueue::processNextBufferLocked(bool useNextTransaction) { auto releaseBufferCallback = std::bind(releaseBufferCallbackThunk, wp<BLASTBufferQueue>(this) /* callbackContext */, - std::placeholders::_1, std::placeholders::_2, std::placeholders::_3); + std::placeholders::_1, std::placeholders::_2, std::placeholders::_3, + std::placeholders::_4); t->setBuffer(mSurfaceControl, buffer, releaseBufferCallback); t->setDataspace(mSurfaceControl, static_cast<ui::Dataspace>(bufferItem.mDataSpace)); t->setHdrMetadata(mSurfaceControl, bufferItem.mHdrMetadata); diff --git a/libs/gui/ISurfaceComposer.cpp b/libs/gui/ISurfaceComposer.cpp index 71e18a97c9..0d7795e1ba 100644 --- a/libs/gui/ISurfaceComposer.cpp +++ b/libs/gui/ISurfaceComposer.cpp @@ -1215,16 +1215,17 @@ public: return reply.readInt32(); } - status_t getExtraBufferCount(int* extraBuffers) const override { + status_t getMaxAcquiredBufferCount(int* buffers) const override { Parcel data, reply; data.writeInterfaceToken(ISurfaceComposer::getInterfaceDescriptor()); - status_t err = remote()->transact(BnSurfaceComposer::GET_EXTRA_BUFFER_COUNT, data, &reply); + status_t err = + remote()->transact(BnSurfaceComposer::GET_MAX_ACQUIRED_BUFFER_COUNT, data, &reply); if (err != NO_ERROR) { - ALOGE("getExtraBufferCount failed to read data: %s (%d)", strerror(-err), err); + ALOGE("getMaxAcquiredBufferCount failed to read data: %s (%d)", strerror(-err), err); return err; } - return reply.readInt32(extraBuffers); + return reply.readInt32(buffers); } }; @@ -2069,14 +2070,14 @@ status_t BnSurfaceComposer::onTransact( SAFE_PARCEL(reply->writeInt32, priority); return NO_ERROR; } - case GET_EXTRA_BUFFER_COUNT: { + case GET_MAX_ACQUIRED_BUFFER_COUNT: { CHECK_INTERFACE(ISurfaceComposer, data, reply); - int extraBuffers = 0; - int err = getExtraBufferCount(&extraBuffers); + int buffers = 0; + int err = getMaxAcquiredBufferCount(&buffers); if (err != NO_ERROR) { return err; } - SAFE_PARCEL(reply->writeInt32, extraBuffers); + SAFE_PARCEL(reply->writeInt32, buffers); return NO_ERROR; } case OVERRIDE_HDR_TYPES: { diff --git a/libs/gui/ITransactionCompletedListener.cpp b/libs/gui/ITransactionCompletedListener.cpp index 63d07ba1fb..17499ecd50 100644 --- a/libs/gui/ITransactionCompletedListener.cpp +++ b/libs/gui/ITransactionCompletedListener.cpp @@ -119,6 +119,7 @@ status_t SurfaceStats::writeToParcel(Parcel* output) const { SAFE_PARCEL(output->writeBool, false); } SAFE_PARCEL(output->writeUint32, transformHint); + SAFE_PARCEL(output->writeUint32, currentMaxAcquiredBufferCount); SAFE_PARCEL(output->writeParcelable, eventStats); SAFE_PARCEL(output->writeInt32, static_cast<int32_t>(jankData.size())); for (const auto& data : jankData) { @@ -138,6 +139,7 @@ status_t SurfaceStats::readFromParcel(const Parcel* input) { SAFE_PARCEL(input->read, *previousReleaseFence); } SAFE_PARCEL(input->readUint32, &transformHint); + SAFE_PARCEL(input->readUint32, ¤tMaxAcquiredBufferCount); SAFE_PARCEL(input->readParcelable, &eventStats); int32_t jankData_size = 0; @@ -251,11 +253,13 @@ public: stats); } - void onReleaseBuffer(uint64_t graphicBufferId, sp<Fence> releaseFence, - uint32_t transformHint) override { + void onReleaseBuffer(uint64_t graphicBufferId, sp<Fence> releaseFence, uint32_t transformHint, + uint32_t currentMaxAcquiredBufferCount) override { callRemoteAsync<decltype( &ITransactionCompletedListener::onReleaseBuffer)>(Tag::ON_RELEASE_BUFFER, - graphicBufferId, releaseFence, transformHint); + graphicBufferId, releaseFence, + transformHint, + currentMaxAcquiredBufferCount); } }; diff --git a/libs/gui/SurfaceComposerClient.cpp b/libs/gui/SurfaceComposerClient.cpp index 660c5bd97d..c69435d328 100644 --- a/libs/gui/SurfaceComposerClient.cpp +++ b/libs/gui/SurfaceComposerClient.cpp @@ -328,7 +328,8 @@ void TransactionCompletedListener::onTransactionCompleted(ListenerStats listener surfaceStats.previousReleaseFence ? surfaceStats.previousReleaseFence : Fence::NO_FENCE, - surfaceStats.transformHint); + surfaceStats.transformHint, + surfaceStats.currentMaxAcquiredBufferCount); } } } @@ -364,9 +365,9 @@ void TransactionCompletedListener::onTransactionCompleted(ListenerStats listener } } -void TransactionCompletedListener::onReleaseBuffer(uint64_t graphicBufferId, - sp<Fence> releaseFence, - uint32_t transformHint) { +void TransactionCompletedListener::onReleaseBuffer(uint64_t graphicBufferId, sp<Fence> releaseFence, + uint32_t transformHint, + uint32_t currentMaxAcquiredBufferCount) { ReleaseBufferCallback callback; { std::scoped_lock<std::mutex> lock(mMutex); @@ -376,7 +377,7 @@ void TransactionCompletedListener::onReleaseBuffer(uint64_t graphicBufferId, ALOGE("Could not call release buffer callback, buffer not found %" PRIu64, graphicBufferId); return; } - callback(graphicBufferId, releaseFence, transformHint); + callback(graphicBufferId, releaseFence, transformHint, currentMaxAcquiredBufferCount); } ReleaseBufferCallback TransactionCompletedListener::popReleaseBufferCallbackLocked( diff --git a/libs/gui/include/gui/BLASTBufferQueue.h b/libs/gui/include/gui/BLASTBufferQueue.h index d63425e41b..0981e760a5 100644 --- a/libs/gui/include/gui/BLASTBufferQueue.h +++ b/libs/gui/include/gui/BLASTBufferQueue.h @@ -90,7 +90,7 @@ public: void transactionCallback(nsecs_t latchTime, const sp<Fence>& presentFence, const std::vector<SurfaceControlStats>& stats); void releaseBufferCallback(uint64_t graphicBufferId, const sp<Fence>& releaseFence, - uint32_t transformHint); + uint32_t transformHint, uint32_t currentMaxAcquiredBufferCount); void setNextTransaction(SurfaceComposerClient::Transaction *t); void mergeWithNextTransaction(SurfaceComposerClient::Transaction* t, uint64_t frameNumber); void setTransactionCompleteCallback(uint64_t frameNumber, @@ -141,6 +141,15 @@ private: // buffer or the buffer has been presented and a new buffer is ready to be presented. std::unordered_map<uint64_t /* bufferId */, BufferItem> mSubmitted GUARDED_BY(mMutex); + // Keep a queue of the released buffers instead of immediately releasing + // the buffers back to the buffer queue. This would be controlled by SF + // setting the max acquired buffer count. + struct ReleasedBuffer { + uint64_t bufferId; + sp<Fence> releaseFence; + }; + std::deque<ReleasedBuffer> mPendingRelease GUARDED_BY(mMutex); + ui::Size mSize GUARDED_BY(mMutex); ui::Size mRequestedSize GUARDED_BY(mMutex); int32_t mFormat GUARDED_BY(mMutex); diff --git a/libs/gui/include/gui/ISurfaceComposer.h b/libs/gui/include/gui/ISurfaceComposer.h index 439d90ad10..2a3f6a43d9 100644 --- a/libs/gui/include/gui/ISurfaceComposer.h +++ b/libs/gui/include/gui/ISurfaceComposer.h @@ -537,22 +537,21 @@ public: 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. + * Gets the number of buffers SurfaceFlinger would need acquire. This number + * would be propagated to the client via MIN_UNDEQUEUED_BUFFERS so that the + * client could allocate enough buffers to match SF expectations of the + * pipeline depth. 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. + * number of additional buffers on top of the 2 buffers already present + * in MIN_UNDEQUEUED_BUFFERS. */ - virtual status_t getExtraBufferCount(int* extraBuffers) const = 0; + virtual status_t getMaxAcquiredBufferCount(int* buffers) const = 0; }; // ---------------------------------------------------------------------------- @@ -615,7 +614,7 @@ public: SET_FRAME_TIMELINE_INFO, ADD_TRANSACTION_TRACE_LISTENER, GET_GPU_CONTEXT_PRIORITY, - GET_EXTRA_BUFFER_COUNT, + GET_MAX_ACQUIRED_BUFFER_COUNT, GET_DYNAMIC_DISPLAY_INFO, ADD_FPS_LISTENER, REMOVE_FPS_LISTENER, diff --git a/libs/gui/include/gui/ITransactionCompletedListener.h b/libs/gui/include/gui/ITransactionCompletedListener.h index 3bfeef1922..d286c34ec8 100644 --- a/libs/gui/include/gui/ITransactionCompletedListener.h +++ b/libs/gui/include/gui/ITransactionCompletedListener.h @@ -101,12 +101,14 @@ public: SurfaceStats() = default; SurfaceStats(const sp<IBinder>& sc, nsecs_t time, const sp<Fence>& prevReleaseFence, - uint32_t hint, FrameEventHistoryStats frameEventStats, - std::vector<JankData> jankData, uint64_t previousBufferId) + uint32_t hint, uint32_t currentMaxAcquiredBuffersCount, + FrameEventHistoryStats frameEventStats, std::vector<JankData> jankData, + uint64_t previousBufferId) : surfaceControl(sc), acquireTime(time), previousReleaseFence(prevReleaseFence), transformHint(hint), + currentMaxAcquiredBufferCount(currentMaxAcquiredBuffersCount), eventStats(frameEventStats), jankData(std::move(jankData)), previousBufferId(previousBufferId) {} @@ -115,6 +117,7 @@ public: nsecs_t acquireTime = -1; sp<Fence> previousReleaseFence; uint32_t transformHint = 0; + uint32_t currentMaxAcquiredBufferCount = 0; FrameEventHistoryStats eventStats; std::vector<JankData> jankData; uint64_t previousBufferId; @@ -159,7 +162,8 @@ public: virtual void onTransactionCompleted(ListenerStats stats) = 0; virtual void onReleaseBuffer(uint64_t graphicBufferId, sp<Fence> releaseFence, - uint32_t transformHint) = 0; + uint32_t transformHint, + uint32_t currentMaxAcquiredBufferCount) = 0; }; class BnTransactionCompletedListener : public SafeBnInterface<ITransactionCompletedListener> { diff --git a/libs/gui/include/gui/SurfaceComposerClient.h b/libs/gui/include/gui/SurfaceComposerClient.h index 5aa132cd92..fa91bfa010 100644 --- a/libs/gui/include/gui/SurfaceComposerClient.h +++ b/libs/gui/include/gui/SurfaceComposerClient.h @@ -83,7 +83,7 @@ using TransactionCompletedCallback = const std::vector<SurfaceControlStats>& /*stats*/)>; using ReleaseBufferCallback = std::function<void(uint64_t /* graphicsBufferId */, const sp<Fence>& /*releaseFence*/, - uint32_t transformHint)>; + uint32_t transformHint, uint32_t currentMaxAcquiredBufferCount)>; using SurfaceStatsCallback = std::function<void(void* /*context*/, nsecs_t /*latchTime*/, @@ -729,7 +729,7 @@ public: // BnTransactionCompletedListener overrides void onTransactionCompleted(ListenerStats stats) override; void onReleaseBuffer(uint64_t /* graphicsBufferId */, sp<Fence> releaseFence, - uint32_t transformHint) override; + uint32_t transformHint, uint32_t currentMaxAcquiredBufferCount) override; private: ReleaseBufferCallback popReleaseBufferCallbackLocked(uint64_t /* graphicsBufferId */); diff --git a/libs/gui/tests/Surface_test.cpp b/libs/gui/tests/Surface_test.cpp index b8d34c3160..59b0c04bc3 100644 --- a/libs/gui/tests/Surface_test.cpp +++ b/libs/gui/tests/Surface_test.cpp @@ -902,7 +902,7 @@ public: int getGPUContextPriority() override { return 0; }; - status_t getExtraBufferCount(int* /*extraBuffers*/) const override { return NO_ERROR; } + status_t getMaxAcquiredBufferCount(int* /*buffers*/) const override { return NO_ERROR; } protected: IBinder* onAsBinder() override { return nullptr; } diff --git a/services/surfaceflinger/BufferStateLayer.cpp b/services/surfaceflinger/BufferStateLayer.cpp index d68a0e0b47..955c2f88b0 100644 --- a/services/surfaceflinger/BufferStateLayer.cpp +++ b/services/surfaceflinger/BufferStateLayer.cpp @@ -44,12 +44,12 @@ using PresentState = frametimeline::SurfaceFrame::PresentState; namespace { void callReleaseBufferCallback(const sp<ITransactionCompletedListener>& listener, const sp<GraphicBuffer>& buffer, const sp<Fence>& releaseFence, - uint32_t transformHint) { + uint32_t transformHint, uint32_t currentMaxAcquiredBufferCount) { if (!listener) { return; } listener->onReleaseBuffer(buffer->getId(), releaseFence ? releaseFence : Fence::NO_FENCE, - transformHint); + transformHint, currentMaxAcquiredBufferCount); } } // namespace @@ -75,7 +75,9 @@ BufferStateLayer::~BufferStateLayer() { if (mBufferInfo.mBuffer != nullptr && !isClone()) { callReleaseBufferCallback(mDrawingState.releaseBufferListener, mBufferInfo.mBuffer->getBuffer(), mBufferInfo.mFence, - mTransformHint); + mTransformHint, + mFlinger->getMaxAcquiredBufferCountForCurrentRefreshRate( + mOwnerUid)); } } @@ -199,6 +201,8 @@ void BufferStateLayer::releasePendingBuffer(nsecs_t dequeueReadyTime) { for (const auto& handle : mDrawingState.callbackHandles) { handle->transformHint = mTransformHint; handle->dequeueReadyTime = dequeueReadyTime; + handle->currentMaxAcquiredBufferCount = + mFlinger->getMaxAcquiredBufferCountForCurrentRefreshRate(mOwnerUid); } // If there are multiple transactions in this frame, set the previous id on the earliest @@ -429,9 +433,10 @@ bool BufferStateLayer::setBuffer(const std::shared_ptr<renderengine::ExternalTex // dropped and we should decrement the pending buffer count and // call any release buffer callbacks if set. callReleaseBufferCallback(mCurrentState.releaseBufferListener, - mCurrentState.buffer->getBuffer(), - mCurrentState.acquireFence, - mTransformHint); + mCurrentState.buffer->getBuffer(), mCurrentState.acquireFence, + mTransformHint, + mFlinger->getMaxAcquiredBufferCountForCurrentRefreshRate( + mOwnerUid)); decrementPendingBufferCount(); if (mCurrentState.bufferSurfaceFrameTX != nullptr) { addSurfaceFrameDroppedForBuffer(mCurrentState.bufferSurfaceFrameTX); @@ -951,7 +956,9 @@ void BufferStateLayer::bufferMayChange(const sp<GraphicBuffer>& newBuffer) { // call any release buffer callbacks if set. callReleaseBufferCallback(mDrawingState.releaseBufferListener, mDrawingState.buffer->getBuffer(), mDrawingState.acquireFence, - mTransformHint); + mTransformHint, + mFlinger->getMaxAcquiredBufferCountForCurrentRefreshRate( + mOwnerUid)); decrementPendingBufferCount(); } } diff --git a/services/surfaceflinger/Scheduler/Scheduler.cpp b/services/surfaceflinger/Scheduler/Scheduler.cpp index 4b8cbfb621..e0b364020b 100644 --- a/services/surfaceflinger/Scheduler/Scheduler.cpp +++ b/services/surfaceflinger/Scheduler/Scheduler.cpp @@ -205,6 +205,10 @@ std::unique_ptr<VSyncSource> Scheduler::makePrimaryDispSyncSource( } std::optional<Fps> Scheduler::getFrameRateOverride(uid_t uid) const { + if (!mRefreshRateConfigs.supportsFrameRateOverride()) { + return std::nullopt; + } + std::lock_guard lock(mFrameRateOverridesMutex); { const auto iter = mFrameRateOverridesFromBackdoor.find(uid); @@ -224,10 +228,6 @@ std::optional<Fps> Scheduler::getFrameRateOverride(uid_t uid) const { } bool Scheduler::isVsyncValid(nsecs_t expectedVsyncTimestamp, uid_t uid) const { - if (!mRefreshRateConfigs.supportsFrameRateOverride()) { - return true; - } - const auto frameRate = getFrameRateOverride(uid); if (!frameRate.has_value()) { return true; diff --git a/services/surfaceflinger/SurfaceFlinger.cpp b/services/surfaceflinger/SurfaceFlinger.cpp index c1d28b1746..a39ae5819d 100644 --- a/services/surfaceflinger/SurfaceFlinger.cpp +++ b/services/surfaceflinger/SurfaceFlinger.cpp @@ -5247,7 +5247,7 @@ status_t SurfaceFlinger::CheckTransactCodeCredentials(uint32_t code) { case CAPTURE_DISPLAY: case SET_FRAME_TIMELINE_INFO: case GET_GPU_CONTEXT_PRIORITY: - case GET_EXTRA_BUFFER_COUNT: { + case GET_MAX_ACQUIRED_BUFFER_COUNT: { // This is not sensitive information, so should not require permission control. return OK; } @@ -6800,25 +6800,38 @@ 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()) { +int SurfaceFlinger::calculateMaxAcquiredBufferCount(Fps refreshRate, + std::chrono::nanoseconds presentLatency) { + auto pipelineDepth = presentLatency.count() / refreshRate.getPeriodNsecs(); + if (presentLatency.count() % refreshRate.getPeriodNsecs()) { pipelineDepth++; } - return std::max(0ll, pipelineDepth - 2); + return std::max(1ll, pipelineDepth - 1); } -status_t SurfaceFlinger::getExtraBufferCount(int* extraBuffers) const { +status_t SurfaceFlinger::getMaxAcquiredBufferCount(int* buffers) 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); + *buffers = getMaxAcquiredBufferCountForRefreshRate(maxSupportedRefreshRate); return NO_ERROR; } +int SurfaceFlinger::getMaxAcquiredBufferCountForCurrentRefreshRate(uid_t uid) const { + const auto refreshRate = [&] { + const auto frameRateOverride = mScheduler->getFrameRateOverride(uid); + if (frameRateOverride.has_value()) { + return frameRateOverride.value(); + } + return mRefreshRateConfigs->getCurrentRefreshRate().getFps(); + }(); + return getMaxAcquiredBufferCountForRefreshRate(refreshRate); +} + +int SurfaceFlinger::getMaxAcquiredBufferCountForRefreshRate(Fps refreshRate) const { + const auto vsyncConfig = mVsyncConfiguration->getConfigsForRefreshRate(refreshRate).late; + const auto presentLatency = vsyncConfig.appWorkDuration + vsyncConfig.sfWorkDuration; + return calculateMaxAcquiredBufferCount(refreshRate, presentLatency); +} + void SurfaceFlinger::TransactionState::traverseStatesWithBuffers( std::function<void(const layer_state_t&)> visitor) { for (const auto& state : states) { diff --git a/services/surfaceflinger/SurfaceFlinger.h b/services/surfaceflinger/SurfaceFlinger.h index a3fa8d654f..22d17eb153 100644 --- a/services/surfaceflinger/SurfaceFlinger.h +++ b/services/surfaceflinger/SurfaceFlinger.h @@ -708,7 +708,7 @@ private: int getGPUContextPriority() override; - status_t getExtraBufferCount(int* extraBuffers) const override; + status_t getMaxAcquiredBufferCount(int* buffers) const override; // Implements IBinder::DeathRecipient. void binderDied(const wp<IBinder>& who) override; @@ -923,6 +923,8 @@ private: size_t getMaxTextureSize() const; size_t getMaxViewportDims() const; + int getMaxAcquiredBufferCountForCurrentRefreshRate(uid_t uid) const; + /* * Display and layer stack management */ @@ -1062,6 +1064,7 @@ private: // Calculates the expected present time for this frame. For negative offsets, performs a // correction using the predicted vsync for the next frame instead. + nsecs_t calculateExpectedPresentTime(DisplayStatInfo) const; /* @@ -1177,8 +1180,9 @@ private: std::vector<ui::ColorMode> getDisplayColorModes(PhysicalDisplayId displayId) REQUIRES(mStateLock); - static int calculateExtraBufferCount(Fps maxSupportedRefreshRate, - std::chrono::nanoseconds presentLatency); + static int calculateMaxAcquiredBufferCount(Fps refreshRate, + std::chrono::nanoseconds presentLatency); + int getMaxAcquiredBufferCountForRefreshRate(Fps refreshRate) const; sp<StartPropertySetThread> mStartPropertySetThread; surfaceflinger::Factory& mFactory; diff --git a/services/surfaceflinger/TransactionCallbackInvoker.cpp b/services/surfaceflinger/TransactionCallbackInvoker.cpp index 4f4c02be6c..fdf16a797f 100644 --- a/services/surfaceflinger/TransactionCallbackInvoker.cpp +++ b/services/surfaceflinger/TransactionCallbackInvoker.cpp @@ -235,8 +235,9 @@ status_t TransactionCallbackInvoker::addCallbackHandle(const sp<CallbackHandle>& handle->dequeueReadyTime); transactionStats->surfaceStats.emplace_back(surfaceControl, handle->acquireTime, handle->previousReleaseFence, - handle->transformHint, eventStats, jankData, - handle->previousBufferId); + handle->transformHint, + handle->currentMaxAcquiredBufferCount, + eventStats, jankData, handle->previousBufferId); } return NO_ERROR; } diff --git a/services/surfaceflinger/TransactionCallbackInvoker.h b/services/surfaceflinger/TransactionCallbackInvoker.h index 184b15103e..444bec646e 100644 --- a/services/surfaceflinger/TransactionCallbackInvoker.h +++ b/services/surfaceflinger/TransactionCallbackInvoker.h @@ -45,6 +45,7 @@ public: nsecs_t acquireTime = -1; nsecs_t latchTime = -1; uint32_t transformHint = 0; + uint32_t currentMaxAcquiredBufferCount = 0; std::shared_ptr<FenceTime> gpuCompositionDoneFence{FenceTime::NO_FENCE}; CompositorTiming compositorTiming; nsecs_t refreshStartTime = 0; diff --git a/services/surfaceflinger/tests/ReleaseBufferCallback_test.cpp b/services/surfaceflinger/tests/ReleaseBufferCallback_test.cpp index fb7d41c81e..5aa809dc8b 100644 --- a/services/surfaceflinger/tests/ReleaseBufferCallback_test.cpp +++ b/services/surfaceflinger/tests/ReleaseBufferCallback_test.cpp @@ -30,7 +30,8 @@ using android::hardware::graphics::common::V1_1::BufferUsage; class ReleaseBufferCallbackHelper { public: static void function(void* callbackContext, uint64_t graphicsBufferId, - const sp<Fence>& releaseFence) { + const sp<Fence>& releaseFence, + uint32_t /*currentMaxAcquiredBufferCount*/) { if (!callbackContext) { FAIL() << "failed to get callback context"; } @@ -66,7 +67,7 @@ public: android::ReleaseBufferCallback getCallback() { return std::bind(function, static_cast<void*>(this) /* callbackContext */, - std::placeholders::_1, std::placeholders::_2); + std::placeholders::_1, std::placeholders::_2, std::placeholders::_3); } std::mutex mMutex; diff --git a/services/surfaceflinger/tests/unittests/SchedulerTest.cpp b/services/surfaceflinger/tests/unittests/SchedulerTest.cpp index 423d0ccbff..f680d802e6 100644 --- a/services/surfaceflinger/tests/unittests/SchedulerTest.cpp +++ b/services/surfaceflinger/tests/unittests/SchedulerTest.cpp @@ -210,14 +210,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)); +TEST_F(SchedulerTest, calculateMaxAcquiredBufferCount) { + EXPECT_EQ(1, mFlinger.calculateMaxAcquiredBufferCount(Fps(60), 30ms)); + EXPECT_EQ(2, mFlinger.calculateMaxAcquiredBufferCount(Fps(90), 30ms)); + EXPECT_EQ(3, mFlinger.calculateMaxAcquiredBufferCount(Fps(120), 30ms)); - EXPECT_EQ(1, mFlinger.calculateExtraBufferCount(Fps(60), 40ms)); + EXPECT_EQ(2, mFlinger.calculateMaxAcquiredBufferCount(Fps(60), 40ms)); - EXPECT_EQ(0, mFlinger.calculateExtraBufferCount(Fps(60), 10ms)); + EXPECT_EQ(1, mFlinger.calculateMaxAcquiredBufferCount(Fps(60), 10ms)); } MATCHER(Is120Hz, "") { diff --git a/services/surfaceflinger/tests/unittests/TestableSurfaceFlinger.h b/services/surfaceflinger/tests/unittests/TestableSurfaceFlinger.h index d78f36cd27..b363146e10 100644 --- a/services/surfaceflinger/tests/unittests/TestableSurfaceFlinger.h +++ b/services/surfaceflinger/tests/unittests/TestableSurfaceFlinger.h @@ -391,9 +391,9 @@ public: auto getGPUContextPriority() { return mFlinger->getGPUContextPriority(); } - auto calculateExtraBufferCount(Fps maxSupportedRefreshRate, - std::chrono::nanoseconds presentLatency) const { - return SurfaceFlinger::calculateExtraBufferCount(maxSupportedRefreshRate, presentLatency); + auto calculateMaxAcquiredBufferCount(Fps refreshRate, + std::chrono::nanoseconds presentLatency) const { + return SurfaceFlinger::calculateMaxAcquiredBufferCount(refreshRate, presentLatency); } /* ------------------------------------------------------------------------ |