From 58ca29d421dbec323e7f854ee8226b2d365c00be Mon Sep 17 00:00:00 2001 From: Siarhei Vishniakou Date: Wed, 13 Jan 2021 10:28:00 -1000 Subject: Add inputEventId to SurfaceFrame SurfaceFrame will now be aware of the id of the input event that caused the current frame. The flow of input event id is inputflinger -> app -> surfaceflinger. Here, we are adding the 'inputEventId' parameter to the 'setFrameTimelineVsync' call. This call will now be responsible for setting two pieces of information: the vsync id, and the input event id. Since it will no longer be limited to the vsync id, we rename this call to "setFrameTimelineInfo". Once the inputEventId is stored in SurfaceFrame, we will add a binder call to send the frame timing information to inputflinger (separate, future CL). This will allow input to reconstruct the entire sequence of events (at what time was input event getting processed in system_server, app, and surfaceflinger) and will provide the ability to measure end-to-end touch latency. In a separate change, we will also add ATRACE calls to allow manual / script-based latency analysis for local debugging. We will now know which input event is being processed in surfaceflinger. Bug: 169866723 Bug: 129481165 Design doc: https://docs.google.com/document/d/1G3bLaZYSmbe6AKcL-6ZChvrw_B_LXEz29Z6Ed9QoYXY/edit# Test: atest WMShellUnitTests SurfaceParcelable_test libgui_test IPC_test SurfaceFlinger_test Change-Id: If7e0eee82603b38b396b53ad7ced660973efcb50 --- services/surfaceflinger/BufferQueueLayer.cpp | 14 ++++++-------- 1 file changed, 6 insertions(+), 8 deletions(-) (limited to 'services/surfaceflinger/BufferQueueLayer.cpp') diff --git a/services/surfaceflinger/BufferQueueLayer.cpp b/services/surfaceflinger/BufferQueueLayer.cpp index 32e6b1098f..52197873c5 100644 --- a/services/surfaceflinger/BufferQueueLayer.cpp +++ b/services/surfaceflinger/BufferQueueLayer.cpp @@ -384,8 +384,8 @@ status_t BufferQueueLayer::updateFrameNumber(nsecs_t latchTime) { return NO_ERROR; } -void BufferQueueLayer::setFrameTimelineVsyncForBuffer(int64_t frameTimelineVsyncId) { - mFrameTimelineVsyncId = frameTimelineVsyncId; +void BufferQueueLayer::setFrameTimelineInfoForBuffer(const FrameTimelineInfo& frameTimelineInfo) { + mFrameTimelineInfo = frameTimelineInfo; } // ----------------------------------------------------------------------- @@ -445,9 +445,8 @@ void BufferQueueLayer::onFrameAvailable(const BufferItem& item) { } auto surfaceFrame = - mFlinger->mFrameTimeline->createSurfaceFrameForToken(mFrameTimelineVsyncId, - mOwnerPid, mOwnerUid, mName, - mName); + mFlinger->mFrameTimeline->createSurfaceFrameForToken(mFrameTimelineInfo, mOwnerPid, + mOwnerUid, mName, mName); surfaceFrame->setActualQueueTime(systemTime()); mQueueItems.push_back({item, surfaceFrame}); @@ -485,9 +484,8 @@ void BufferQueueLayer::onFrameReplaced(const BufferItem& item) { } auto surfaceFrame = - mFlinger->mFrameTimeline->createSurfaceFrameForToken(mFrameTimelineVsyncId, - mOwnerPid, mOwnerUid, mName, - mName); + mFlinger->mFrameTimeline->createSurfaceFrameForToken(mFrameTimelineInfo, mOwnerPid, + mOwnerUid, mName, mName); surfaceFrame->setActualQueueTime(systemTime()); mQueueItems[mQueueItems.size() - 1].item = item; mQueueItems[mQueueItems.size() - 1].surfaceFrame = std::move(surfaceFrame); -- cgit v1.2.3-59-g8ed1b From 97cb066a0049c7ed8268ab436df0cc3cc843dabb Mon Sep 17 00:00:00 2001 From: Adithya Srinivasan Date: Thu, 14 Jan 2021 23:49:46 +0000 Subject: Fix Transaction tracking for FrameTimeline The current setup only supports one SurfaceFrame per DrawingState for Transactions. This becomes problematic if more than one Transaction is submitted for the same vsync, on the same layer. On top of this, the Blast transactions can have a buffer that could result in a buffer drop. This change adds the support to hold multiple SurfaceFrames in the Layer's State. It also adds a bufferSurfaceFrame that's intended only for Blast Transactions with a Buffer. All other Transactions are tracked in the bufferlessSurfaceFrames. Additionally, this change also adds a lastLatchTime. It is needed for classifying BufferStuffing properly. Bug: 176106798 Test: open any app from the launcher and at the same time check dumpsys Change-Id: Id3b8369ca206f8b89be3041e5fc018f1f1be1d23 --- services/surfaceflinger/BufferQueueLayer.cpp | 27 +- services/surfaceflinger/BufferQueueLayer.h | 5 - services/surfaceflinger/BufferStateLayer.cpp | 25 +- services/surfaceflinger/BufferStateLayer.h | 4 +- .../surfaceflinger/FrameTimeline/FrameTimeline.cpp | 4 + services/surfaceflinger/Layer.cpp | 139 +++++++- services/surfaceflinger/Layer.h | 46 ++- services/surfaceflinger/RefreshRateOverlay.cpp | 4 +- services/surfaceflinger/SurfaceFlinger.cpp | 9 +- services/surfaceflinger/tests/unittests/Android.bp | 1 + .../unittests/TransactionSurfaceFrameTest.cpp | 367 +++++++++++++++++++++ 11 files changed, 578 insertions(+), 53 deletions(-) create mode 100644 services/surfaceflinger/tests/unittests/TransactionSurfaceFrameTest.cpp (limited to 'services/surfaceflinger/BufferQueueLayer.cpp') diff --git a/services/surfaceflinger/BufferQueueLayer.cpp b/services/surfaceflinger/BufferQueueLayer.cpp index 52197873c5..3615a0209f 100644 --- a/services/surfaceflinger/BufferQueueLayer.cpp +++ b/services/surfaceflinger/BufferQueueLayer.cpp @@ -282,8 +282,7 @@ status_t BufferQueueLayer::updateTexImage(bool& recomputeVisibleRegions, nsecs_t mConsumer->mergeSurfaceDamage(mQueueItems[0].item.mSurfaceDamage); mFlinger->mTimeStats->removeTimeRecord(layerId, mQueueItems[0].item.mFrameNumber); if (mQueueItems[0].surfaceFrame) { - mQueueItems[0].surfaceFrame->setPresentState(PresentState::Dropped); - mFlinger->mFrameTimeline->addSurfaceFrame(mQueueItems[0].surfaceFrame); + addSurfaceFrameDroppedForBuffer(mQueueItems[0].surfaceFrame); } mQueueItems.erase(mQueueItems.begin()); mQueuedFrames--; @@ -298,8 +297,7 @@ status_t BufferQueueLayer::updateTexImage(bool& recomputeVisibleRegions, nsecs_t Mutex::Autolock lock(mQueueItemLock); for (auto& [item, surfaceFrame] : mQueueItems) { if (surfaceFrame) { - surfaceFrame->setPresentState(PresentState::Dropped); - mFlinger->mFrameTimeline->addSurfaceFrame(surfaceFrame); + addSurfaceFrameDroppedForBuffer(surfaceFrame); } } mQueueItems.clear(); @@ -329,8 +327,7 @@ status_t BufferQueueLayer::updateTexImage(bool& recomputeVisibleRegions, nsecs_t mConsumer->mergeSurfaceDamage(mQueueItems[0].item.mSurfaceDamage); mFlinger->mTimeStats->removeTimeRecord(layerId, mQueueItems[0].item.mFrameNumber); if (mQueueItems[0].surfaceFrame) { - mQueueItems[0].surfaceFrame->setPresentState(PresentState::Dropped); - mFlinger->mFrameTimeline->addSurfaceFrame(mQueueItems[0].surfaceFrame); + addSurfaceFrameDroppedForBuffer(mQueueItems[0].surfaceFrame); } mQueueItems.erase(mQueueItems.begin()); mQueuedFrames--; @@ -342,11 +339,9 @@ status_t BufferQueueLayer::updateTexImage(bool& recomputeVisibleRegions, nsecs_t FrameTracer::FrameEvent::LATCH); if (mQueueItems[0].surfaceFrame) { - mQueueItems[0].surfaceFrame->setAcquireFenceTime( - mQueueItems[0].item.mFenceTime->getSignalTime()); - mQueueItems[0].surfaceFrame->setPresentState(PresentState::Presented, mLastLatchTime); - mFlinger->mFrameTimeline->addSurfaceFrame(mQueueItems[0].surfaceFrame); - mLastLatchTime = latchTime; + addSurfaceFramePresentedForBuffer(mQueueItems[0].surfaceFrame, + mQueueItems[0].item.mFenceTime->getSignalTime(), + latchTime); } mQueueItems.erase(mQueueItems.begin()); } @@ -444,10 +439,7 @@ void BufferQueueLayer::onFrameAvailable(const BufferItem& item) { } } - auto surfaceFrame = - mFlinger->mFrameTimeline->createSurfaceFrameForToken(mFrameTimelineInfo, mOwnerPid, - mOwnerUid, mName, mName); - surfaceFrame->setActualQueueTime(systemTime()); + auto surfaceFrame = createSurfaceFrameForBuffer(mFrameTimelineInfo, systemTime(), mName); mQueueItems.push_back({item, surfaceFrame}); mQueuedFrames++; @@ -483,10 +475,7 @@ void BufferQueueLayer::onFrameReplaced(const BufferItem& item) { return; } - auto surfaceFrame = - mFlinger->mFrameTimeline->createSurfaceFrameForToken(mFrameTimelineInfo, mOwnerPid, - mOwnerUid, mName, mName); - surfaceFrame->setActualQueueTime(systemTime()); + auto surfaceFrame = createSurfaceFrameForBuffer(mFrameTimelineInfo, systemTime(), mName); mQueueItems[mQueueItems.size() - 1].item = item; mQueueItems[mQueueItems.size() - 1].surfaceFrame = std::move(surfaceFrame); diff --git a/services/surfaceflinger/BufferQueueLayer.h b/services/surfaceflinger/BufferQueueLayer.h index 41ff01262e..0ea02e19a7 100644 --- a/services/surfaceflinger/BufferQueueLayer.h +++ b/services/surfaceflinger/BufferQueueLayer.h @@ -149,11 +149,6 @@ private: // a buffer to correlate the buffer with the vsync id. Can only be accessed // with the SF state lock held. FrameTimelineInfo mFrameTimelineInfo; - - // Keeps track of the time SF latched the last buffer from this layer. - // Used in buffer stuffing analysis in FrameTimeline. - // TODO(b/176106798): Find a way to do this for BLASTBufferQueue as well. - nsecs_t mLastLatchTime = 0; }; } // namespace android diff --git a/services/surfaceflinger/BufferStateLayer.cpp b/services/surfaceflinger/BufferStateLayer.cpp index 3dc62e3091..e470eb940c 100644 --- a/services/surfaceflinger/BufferStateLayer.cpp +++ b/services/surfaceflinger/BufferStateLayer.cpp @@ -28,6 +28,7 @@ #include +#include #include #include #include @@ -38,6 +39,7 @@ namespace android { +using PresentState = frametimeline::SurfaceFrame::PresentState; // clang-format off const std::array BufferStateLayer::IDENTITY_MATRIX{ 1, 0, 0, 0, @@ -335,7 +337,8 @@ bool BufferStateLayer::addFrameEvent(const sp& acquireFence, nsecs_t post bool BufferStateLayer::setBuffer(const sp& buffer, const sp& acquireFence, nsecs_t postTime, nsecs_t desiredPresentTime, bool isAutoTimestamp, const client_cache_t& clientCacheId, uint64_t frameNumber, - std::optional /* dequeueTime */) { + std::optional /* dequeueTime */, + const FrameTimelineInfo& info) { ATRACE_CALL(); if (mCurrentState.buffer) { @@ -345,6 +348,10 @@ bool BufferStateLayer::setBuffer(const sp& buffer, const sp& buffer, const sp(mDrawingState.acquireFence)); mFlinger->mTimeStats->setLatchTime(layerId, mDrawingState.frameNumber, latchTime); + auto& bufferSurfaceFrame = mDrawingState.bufferSurfaceFrameTX; + if (bufferSurfaceFrame != nullptr && + bufferSurfaceFrame->getPresentState() != PresentState::Presented) { + // Update only if the bufferSurfaceFrame wasn't already presented. A Presented + // bufferSurfaceFrame could be seen here if a pending state was applied successfully and we + // are processing the next state. + addSurfaceFramePresentedForBuffer(bufferSurfaceFrame, + mDrawingState.acquireFence->getSignalTime(), latchTime); + bufferSurfaceFrame.reset(); + } + mCurrentStateModified = false; return NO_ERROR; diff --git a/services/surfaceflinger/BufferStateLayer.h b/services/surfaceflinger/BufferStateLayer.h index b93d567e20..ea832a2078 100644 --- a/services/surfaceflinger/BufferStateLayer.h +++ b/services/surfaceflinger/BufferStateLayer.h @@ -72,7 +72,7 @@ public: bool setBuffer(const sp& buffer, const sp& acquireFence, nsecs_t postTime, nsecs_t desiredPresentTime, bool isAutoTimestamp, const client_cache_t& clientCacheId, uint64_t frameNumber, - std::optional dequeueTime) override; + std::optional dequeueTime, const FrameTimelineInfo& info) override; bool setAcquireFence(const sp& fence) override; bool setDataspace(ui::Dataspace dataspace) override; bool setHdrMetadata(const HdrMetadata& hdrMetadata) override; @@ -124,6 +124,8 @@ protected: private: friend class SlotGenerationTest; + friend class TransactionSurfaceFrameTest; + inline void tracePendingBufferCount(); bool updateFrameEventHistory(const sp& acquireFence, nsecs_t postedTime, diff --git a/services/surfaceflinger/FrameTimeline/FrameTimeline.cpp b/services/surfaceflinger/FrameTimeline/FrameTimeline.cpp index 3743716876..3f833f4890 100644 --- a/services/surfaceflinger/FrameTimeline/FrameTimeline.cpp +++ b/services/surfaceflinger/FrameTimeline/FrameTimeline.cpp @@ -312,6 +312,10 @@ void SurfaceFrame::setAcquireFenceTime(nsecs_t acquireFenceTime) { void SurfaceFrame::setPresentState(PresentState presentState, nsecs_t lastLatchTime) { std::scoped_lock lock(mMutex); + LOG_ALWAYS_FATAL_IF(mPresentState != PresentState::Unknown, + "setPresentState called on a SurfaceFrame from Layer - %s, that has a " + "PresentState - %s set already.", + mDebugName.c_str(), toString(mPresentState).c_str()); mPresentState = presentState; mLastLatchTime = lastLatchTime; } diff --git a/services/surfaceflinger/Layer.cpp b/services/surfaceflinger/Layer.cpp index 08a5f0fdb8..df14003c75 100644 --- a/services/surfaceflinger/Layer.cpp +++ b/services/surfaceflinger/Layer.cpp @@ -841,13 +841,35 @@ void Layer::pushPendingState() { setTransactionFlags(eTransactionNeeded); mFlinger->setTransactionFlags(eTraversalNeeded); } + if (mCurrentState.bufferlessSurfaceFramesTX.size() >= State::kStateSurfaceFramesThreshold) { + // Ideally, the currentState would only contain one SurfaceFrame per transaction (assuming + // each Tx uses a different token). We don't expect the current state to hold a huge amount + // of SurfaceFrames. However, in the event it happens, this debug statement will leave a + // trail that can help in debugging. + ALOGW("Bufferless SurfaceFrames size on current state of layer %s is %" PRIu32 "", + mName.c_str(), static_cast(mCurrentState.bufferlessSurfaceFramesTX.size())); + } mPendingStates.push_back(mCurrentState); + // Since the current state along with the SurfaceFrames has been pushed into the pendingState, + // we no longer need to retain them. If multiple states are pushed and applied together, we have + // a merging logic to address the SurfaceFrames at mergeSurfaceFrames(). + mCurrentState.bufferlessSurfaceFramesTX.clear(); ATRACE_INT(mTransactionName.c_str(), mPendingStates.size()); } +void Layer::mergeSurfaceFrames(State& source, State& target) { + // No need to merge BufferSurfaceFrame as the target's surfaceFrame, if it exists, will be used + // directly. Dropping of source's SurfaceFrame is taken care of at setBuffer(). + target.bufferlessSurfaceFramesTX.merge(source.bufferlessSurfaceFramesTX); + source.bufferlessSurfaceFramesTX.clear(); +} + void Layer::popPendingState(State* stateToCommit) { ATRACE_CALL(); + if (stateToCommit != nullptr) { + mergeSurfaceFrames(*stateToCommit, mPendingStates[0]); + } *stateToCommit = mPendingStates[0]; mPendingStates.pop_front(); ATRACE_INT(mTransactionName.c_str(), mPendingStates.size()); @@ -906,20 +928,6 @@ bool Layer::applyPendingStates(State* stateToCommit) { mFlinger->setTraversalNeeded(); } - if (stateUpdateAvailable) { - mSurfaceFrame = - mFlinger->mFrameTimeline - ->createSurfaceFrameForToken(stateToCommit->frameTimelineInfo, mOwnerPid, - mOwnerUid, mName, mTransactionName); - mSurfaceFrame->setActualQueueTime(stateToCommit->postTime); - // For transactions we set the acquire fence time to the post time as we - // don't have a buffer. For BufferStateLayer it is overridden in - // BufferStateLayer::applyPendingStates - mSurfaceFrame->setAcquireFenceTime(stateToCommit->postTime); - - onSurfaceFrameCreated(mSurfaceFrame); - } - mCurrentState.modified = false; return stateUpdateAvailable; } @@ -1048,10 +1056,22 @@ uint32_t Layer::doTransaction(uint32_t flags) { return flags; } -void Layer::commitTransaction(const State& stateToCommit) { +void Layer::commitTransaction(State& stateToCommit) { mDrawingState = stateToCommit; - mSurfaceFrame->setPresentState(PresentState::Presented); - mFlinger->mFrameTimeline->addSurfaceFrame(mSurfaceFrame); + + // Set the present state for all bufferlessSurfaceFramesTX to Presented. The + // bufferSurfaceFrameTX will be presented in latchBuffer. + for (auto& [token, surfaceFrame] : mDrawingState.bufferlessSurfaceFramesTX) { + if (surfaceFrame->getPresentState() != PresentState::Presented) { + // With applyPendingStates, we could end up having presented surfaceframes from previous + // states + surfaceFrame->setPresentState(PresentState::Presented); + mFlinger->mFrameTimeline->addSurfaceFrame(surfaceFrame); + } + } + // Clear the surfaceFrames from the old state now that it has been copied into DrawingState. + stateToCommit.bufferSurfaceFrameTX.reset(); + stateToCommit.bufferlessSurfaceFramesTX.clear(); } uint32_t Layer::getTransactionFlags(uint32_t flags) { @@ -1474,11 +1494,94 @@ bool Layer::setFrameRate(FrameRate frameRate) { return true; } -void Layer::setFrameTimelineInfoForTransaction(const FrameTimelineInfo& info, nsecs_t postTime) { +void Layer::setFrameTimelineVsyncForBufferTransaction(const FrameTimelineInfo& info, + nsecs_t postTime) { + mCurrentState.postTime = postTime; + + // Check if one of the bufferlessSurfaceFramesTX contains the same vsyncId. This can happen if + // there are two transactions with the same token, the first one without a buffer and the + // second one with a buffer. We promote the bufferlessSurfaceFrame to a bufferSurfaceFrameTX + // in that case. + auto it = mCurrentState.bufferlessSurfaceFramesTX.find(info.vsyncId); + if (it != mCurrentState.bufferlessSurfaceFramesTX.end()) { + // Promote the bufferlessSurfaceFrame to a bufferSurfaceFrameTX + mCurrentState.bufferSurfaceFrameTX = it->second; + mCurrentState.bufferlessSurfaceFramesTX.erase(it); + mCurrentState.bufferSurfaceFrameTX->setActualQueueTime(postTime); + } else { + mCurrentState.bufferSurfaceFrameTX = + createSurfaceFrameForBuffer(info, postTime, mTransactionName); + } +} + +void Layer::setFrameTimelineVsyncForBufferlessTransaction(const FrameTimelineInfo& info, + nsecs_t postTime) { mCurrentState.frameTimelineInfo = info; mCurrentState.postTime = postTime; mCurrentState.modified = true; setTransactionFlags(eTransactionNeeded); + + if (const auto& bufferSurfaceFrameTX = mCurrentState.bufferSurfaceFrameTX; + bufferSurfaceFrameTX != nullptr) { + if (bufferSurfaceFrameTX->getToken() == info.vsyncId) { + // BufferSurfaceFrame takes precedence over BufferlessSurfaceFrame. If the same token is + // being used for BufferSurfaceFrame, don't create a new one. + return; + } + } + // For Transactions without a buffer, we create only one SurfaceFrame per vsyncId. If multiple + // transactions use the same vsyncId, we just treat them as one SurfaceFrame (unless they are + // targeting different vsyncs). + auto it = mCurrentState.bufferlessSurfaceFramesTX.find(info.vsyncId); + if (it == mCurrentState.bufferlessSurfaceFramesTX.end()) { + auto surfaceFrame = createSurfaceFrameForTransaction(info, postTime); + mCurrentState.bufferlessSurfaceFramesTX[info.vsyncId] = surfaceFrame; + } else { + if (it->second->getPresentState() == PresentState::Presented) { + // If the SurfaceFrame was already presented, its safe to overwrite it since it must + // have been from previous vsync. + it->second = createSurfaceFrameForTransaction(info, postTime); + } + } +} + +void Layer::addSurfaceFrameDroppedForBuffer( + std::shared_ptr& surfaceFrame) { + surfaceFrame->setPresentState(PresentState::Dropped); + mFlinger->mFrameTimeline->addSurfaceFrame(surfaceFrame); +} + +void Layer::addSurfaceFramePresentedForBuffer( + std::shared_ptr& surfaceFrame, nsecs_t acquireFenceTime, + nsecs_t currentLatchTime) { + surfaceFrame->setAcquireFenceTime(acquireFenceTime); + surfaceFrame->setPresentState(PresentState::Presented, mLastLatchTime); + mFlinger->mFrameTimeline->addSurfaceFrame(surfaceFrame); + mLastLatchTime = currentLatchTime; +} + +std::shared_ptr Layer::createSurfaceFrameForTransaction( + const FrameTimelineInfo& info, nsecs_t postTime) { + auto surfaceFrame = + mFlinger->mFrameTimeline->createSurfaceFrameForToken(info, mOwnerPid, mOwnerUid, mName, + mTransactionName); + // For Transactions, the post time is considered to be both queue and acquire fence time. + surfaceFrame->setActualQueueTime(postTime); + surfaceFrame->setAcquireFenceTime(postTime); + onSurfaceFrameCreated(surfaceFrame); + return surfaceFrame; +} + +std::shared_ptr Layer::createSurfaceFrameForBuffer( + const FrameTimelineInfo& info, nsecs_t queueTime, std::string debugName) { + auto surfaceFrame = + mFlinger->mFrameTimeline->createSurfaceFrameForToken(info, mOwnerPid, mOwnerUid, mName, + debugName); + // For buffers, acquire fence time will set during latch. + surfaceFrame->setActualQueueTime(queueTime); + // TODO(b/178542907): Implement onSurfaceFrameCreated for BQLayer as well. + onSurfaceFrameCreated(surfaceFrame); + return surfaceFrame; } Layer::FrameRate Layer::getFrameRateForLayerTree() const { diff --git a/services/surfaceflinger/Layer.h b/services/surfaceflinger/Layer.h index 4b40c8ed83..89f26966fb 100644 --- a/services/surfaceflinger/Layer.h +++ b/services/surfaceflinger/Layer.h @@ -309,6 +309,20 @@ public: // When the transaction was posted nsecs_t postTime; + + // SurfaceFrame that tracks the timeline of Transactions that contain a Buffer. Only one + // such SurfaceFrame exists because only one buffer can be presented on the layer per vsync. + // If multiple buffers are queued, the prior ones will be dropped, along with the + // SurfaceFrame that's tracking them. + std::shared_ptr bufferSurfaceFrameTX; + // A map of token(frametimelineVsyncId) to the SurfaceFrame that's tracking a transaction + // that contains the token. Only one SurfaceFrame exisits for transactions that share the + // same token, unless they are presented in different vsyncs. + std::unordered_map> + bufferlessSurfaceFramesTX; + // An arbitrary threshold for the number of BufferlessSurfaceFrames in the state. Used to + // trigger a warning if the number of SurfaceFrames crosses the threshold. + static constexpr uint32_t kStateSurfaceFramesThreshold = 25; }; /* @@ -447,7 +461,8 @@ public: virtual bool setBuffer(const sp& /*buffer*/, const sp& /*acquireFence*/, nsecs_t /*postTime*/, nsecs_t /*desiredPresentTime*/, bool /*isAutoTimestamp*/, const client_cache_t& /*clientCacheId*/, - uint64_t /* frameNumber */, std::optional /* dequeueTime */) { + uint64_t /* frameNumber */, std::optional /* dequeueTime */, + const FrameTimelineInfo& /*info*/) { return false; }; virtual bool setAcquireFence(const sp& /*fence*/) { return false; }; @@ -611,6 +626,12 @@ public: virtual void pushPendingState(); + /* + * Merges the BufferlessSurfaceFrames from source with the target. If the same token exists in + * both source and target, target's SurfaceFrame will be retained. + */ + void mergeSurfaceFrames(State& source, State& target); + /** * Returns active buffer size in the correct orientation. Buffer size is determined by undoing * any buffer transformations. If the layer has no buffer then return INVALID_RECT. @@ -866,8 +887,20 @@ public: bool setFrameRate(FrameRate); virtual void setFrameTimelineInfoForBuffer(const FrameTimelineInfo& /*info*/) {} - void setFrameTimelineInfoForTransaction(const FrameTimelineInfo& frameTimelineInfo, - nsecs_t postTime); + void setFrameTimelineVsyncForBufferTransaction(const FrameTimelineInfo& info, nsecs_t postTime); + void setFrameTimelineVsyncForBufferlessTransaction(const FrameTimelineInfo& info, + nsecs_t postTime); + + void addSurfaceFrameDroppedForBuffer( + std::shared_ptr& surfaceFrame); + void addSurfaceFramePresentedForBuffer( + std::shared_ptr& surfaceFrame, nsecs_t acquireFenceTime, + nsecs_t currentLatchTime); + + std::shared_ptr createSurfaceFrameForTransaction( + const FrameTimelineInfo& info, nsecs_t postTime); + std::shared_ptr createSurfaceFrameForBuffer( + const FrameTimelineInfo& info, nsecs_t queueTime, std::string debugName); // Creates a new handle each time, so we only expect // this to be called once. @@ -972,6 +1005,7 @@ protected: friend class TestableSurfaceFlinger; friend class RefreshRateSelectionTest; friend class SetFrameRateTest; + friend class TransactionSurfaceFrameTest; virtual void setInitialValuesForClone(const sp& clonedFrom); virtual std::optional prepareClientComposition( @@ -980,7 +1014,7 @@ protected: const LayerFE::LayerSettings&, const Rect& layerStackRect, ui::Dataspace outputDataspace); virtual void preparePerFrameCompositionState(); - virtual void commitTransaction(const State& stateToCommit); + virtual void commitTransaction(State& stateToCommit); virtual bool applyPendingStates(State* stateToCommit); virtual uint32_t doTransactionResize(uint32_t flags, Layer::State* stateToCommit); virtual void onSurfaceFrameCreated(const std::shared_ptr&) {} @@ -1116,6 +1150,10 @@ protected: // If created from a system process, the value can be passed in. pid_t mOwnerPid; + // Keeps track of the time SF latched the last buffer from this layer. + // Used in buffer stuffing analysis in FrameTimeline. + nsecs_t mLastLatchTime = 0; + private: virtual void setTransformHint(ui::Transform::RotationFlags) {} diff --git a/services/surfaceflinger/RefreshRateOverlay.cpp b/services/surfaceflinger/RefreshRateOverlay.cpp index 9230e72f45..49ffc81359 100644 --- a/services/surfaceflinger/RefreshRateOverlay.cpp +++ b/services/surfaceflinger/RefreshRateOverlay.cpp @@ -238,7 +238,7 @@ void RefreshRateOverlay::changeRefreshRate(const Fps& fps) { auto buffer = getOrCreateBuffers(*mCurrentFps)[mFrame]; mLayer->setBuffer(buffer, Fence::NO_FENCE, 0, 0, true, {}, mLayer->getHeadFrameNumber(-1 /* expectedPresentTime */), - std::nullopt /* dequeueTime */); + std::nullopt /* dequeueTime */, FrameTimelineInfo{}); mFlinger.mTransactionFlags.fetch_or(eTransactionMask); } @@ -251,7 +251,7 @@ void RefreshRateOverlay::onInvalidate() { auto buffer = buffers[mFrame]; mLayer->setBuffer(buffer, Fence::NO_FENCE, 0, 0, true, {}, mLayer->getHeadFrameNumber(-1 /* expectedPresentTime */), - std::nullopt /* dequeueTime */); + std::nullopt /* dequeueTime */, FrameTimelineInfo{}); mFlinger.mTransactionFlags.fetch_or(eTransactionMask); } diff --git a/services/surfaceflinger/SurfaceFlinger.cpp b/services/surfaceflinger/SurfaceFlinger.cpp index e9b587510a..4712328f18 100644 --- a/services/surfaceflinger/SurfaceFlinger.cpp +++ b/services/surfaceflinger/SurfaceFlinger.cpp @@ -3931,10 +3931,11 @@ uint32_t SurfaceFlinger::setClientStateLocked( flags |= eTraversalNeeded; } } + FrameTimelineInfo info; if (what & layer_state_t::eFrameTimelineInfoChanged) { - layer->setFrameTimelineInfoForTransaction(s.frameTimelineInfo, postTime); + info = s.frameTimelineInfo; } else if (frameTimelineInfo.vsyncId != FrameTimelineInfo::INVALID_VSYNC_ID) { - layer->setFrameTimelineInfoForTransaction(frameTimelineInfo, postTime); + info = frameTimelineInfo; } if (what & layer_state_t::eFixedTransformHintChanged) { if (layer->setFixedTransformHint(s.fixedTransformHint)) { @@ -3993,9 +3994,11 @@ uint32_t SurfaceFlinger::setClientStateLocked( : layer->getHeadFrameNumber(-1 /* expectedPresentTime */) + 1; if (layer->setBuffer(buffer, s.acquireFence, postTime, desiredPresentTime, isAutoTimestamp, - s.cachedBuffer, frameNumber, dequeueBufferTimestamp)) { + s.cachedBuffer, frameNumber, dequeueBufferTimestamp, info)) { flags |= eTraversalNeeded; } + } else if (info.vsyncId != FrameTimelineInfo::INVALID_VSYNC_ID) { + layer->setFrameTimelineVsyncForBufferlessTransaction(info, postTime); } if (layer->setTransactionCompletedListeners(callbackHandles)) flags |= eTraversalNeeded; diff --git a/services/surfaceflinger/tests/unittests/Android.bp b/services/surfaceflinger/tests/unittests/Android.bp index 13b26fcc97..7ae09fa0b4 100644 --- a/services/surfaceflinger/tests/unittests/Android.bp +++ b/services/surfaceflinger/tests/unittests/Android.bp @@ -73,6 +73,7 @@ cc_test { "FrameTracerTest.cpp", "TimerTest.cpp", "TransactionApplicationTest.cpp", + "TransactionSurfaceFrameTest.cpp", "StrongTypingTest.cpp", "VSyncDispatchTimerQueueTest.cpp", "VSyncDispatchRealtimeTest.cpp", diff --git a/services/surfaceflinger/tests/unittests/TransactionSurfaceFrameTest.cpp b/services/surfaceflinger/tests/unittests/TransactionSurfaceFrameTest.cpp new file mode 100644 index 0000000000..aa6798d84c --- /dev/null +++ b/services/surfaceflinger/tests/unittests/TransactionSurfaceFrameTest.cpp @@ -0,0 +1,367 @@ +/* + * Copyright 2021 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#undef LOG_TAG +#define LOG_TAG "LibSurfaceFlingerUnittests" + +#include +#include +#include +#include +#include + +#include "TestableSurfaceFlinger.h" +#include "mock/DisplayHardware/MockComposer.h" +#include "mock/MockEventThread.h" +#include "mock/MockVsyncController.h" + +namespace android { + +using testing::_; +using testing::Mock; +using testing::Return; +using FakeHwcDisplayInjector = TestableSurfaceFlinger::FakeHwcDisplayInjector; +using PresentState = frametimeline::SurfaceFrame::PresentState; + +class TransactionSurfaceFrameTest : public testing::Test { +public: + TransactionSurfaceFrameTest() { + const ::testing::TestInfo* const test_info = + ::testing::UnitTest::GetInstance()->current_test_info(); + ALOGD("**** Setting up for %s.%s\n", test_info->test_case_name(), test_info->name()); + setupScheduler(); + setupComposer(0); + } + + ~TransactionSurfaceFrameTest() { + const ::testing::TestInfo* const test_info = + ::testing::UnitTest::GetInstance()->current_test_info(); + ALOGD("**** Tearing down after %s.%s\n", test_info->test_case_name(), test_info->name()); + } + + sp createBufferStateLayer() { + sp client; + LayerCreationArgs args(mFlinger.flinger(), client, "buffer-state-layer", 100, 100, 0, + LayerMetadata()); + return new BufferStateLayer(args); + } + + void commitTransaction(Layer* layer) { + layer->pushPendingState(); + // After pushing the state, the currentState should not store any BufferlessSurfaceFrames + EXPECT_EQ(0u, layer->mCurrentState.bufferlessSurfaceFramesTX.size()); + auto c = layer->getCurrentState(); + if (layer->applyPendingStates(&c)) { + layer->commitTransaction(c); + } + } + + void setupScheduler() { + auto eventThread = std::make_unique(); + auto sfEventThread = std::make_unique(); + + EXPECT_CALL(*eventThread, registerDisplayEventConnection(_)); + EXPECT_CALL(*eventThread, createEventConnection(_, _)) + .WillOnce(Return(new EventThreadConnection(eventThread.get(), /*callingUid=*/0, + ResyncCallback()))); + + EXPECT_CALL(*sfEventThread, registerDisplayEventConnection(_)); + EXPECT_CALL(*sfEventThread, createEventConnection(_, _)) + .WillOnce(Return(new EventThreadConnection(sfEventThread.get(), /*callingUid=*/0, + ResyncCallback()))); + + auto vsyncController = std::make_unique(); + auto vsyncTracker = std::make_unique(); + + EXPECT_CALL(*vsyncTracker, nextAnticipatedVSyncTimeFrom(_)).WillRepeatedly(Return(0)); + EXPECT_CALL(*vsyncTracker, currentPeriod()) + .WillRepeatedly(Return(FakeHwcDisplayInjector::DEFAULT_VSYNC_PERIOD)); + EXPECT_CALL(*vsyncTracker, nextAnticipatedVSyncTimeFrom(_)).WillRepeatedly(Return(0)); + mFlinger.setupScheduler(std::move(vsyncController), std::move(vsyncTracker), + std::move(eventThread), std::move(sfEventThread)); + } + + void setupComposer(uint32_t virtualDisplayCount) { + mComposer = new Hwc2::mock::Composer(); + EXPECT_CALL(*mComposer, getMaxVirtualDisplayCount()).WillOnce(Return(virtualDisplayCount)); + mFlinger.setupComposer(std::unique_ptr(mComposer)); + + Mock::VerifyAndClear(mComposer); + } + + TestableSurfaceFlinger mFlinger; + Hwc2::mock::Composer* mComposer = nullptr; + FenceToFenceTimeMap fenceFactory; + client_cache_t mClientCache; + + void PresentedSurfaceFrameForBufferlessTransaction() { + sp layer = createBufferStateLayer(); + layer->setFrameTimelineVsyncForBufferlessTransaction({/*vsyncId*/ 1, /*inputEventId*/ 0}, + 10); + EXPECT_EQ(1u, layer->mCurrentState.bufferlessSurfaceFramesTX.size()); + ASSERT_TRUE(layer->mCurrentState.bufferSurfaceFrameTX == nullptr); + const auto surfaceFrame = layer->mCurrentState.bufferlessSurfaceFramesTX.at(/*token*/ 1); + commitTransaction(layer.get()); + EXPECT_EQ(1, surfaceFrame->getToken()); + EXPECT_EQ(PresentState::Presented, surfaceFrame->getPresentState()); + } + + void PresentedSurfaceFrameForBufferTransaction() { + sp layer = createBufferStateLayer(); + sp fence(new Fence()); + auto acquireFence = fenceFactory.createFenceTimeForTest(fence); + sp buffer{new GraphicBuffer(1, 1, HAL_PIXEL_FORMAT_RGBA_8888, 1, 0)}; + layer->setBuffer(buffer, fence, 10, 20, false, mClientCache, 1, std::nullopt, + {/*vsyncId*/ 1, /*inputEventId*/ 0}); + acquireFence->signalForTest(12); + + commitTransaction(layer.get()); + EXPECT_EQ(0u, layer->mCurrentState.bufferlessSurfaceFramesTX.size()); + ASSERT_NE(nullptr, layer->mCurrentState.bufferSurfaceFrameTX); + const auto& surfaceFrame = layer->mCurrentState.bufferSurfaceFrameTX; + // Buffers are presented only at latch time. + EXPECT_EQ(PresentState::Unknown, surfaceFrame->getPresentState()); + + bool computeVisisbleRegions; + layer->updateTexImage(computeVisisbleRegions, 15, 0); + + EXPECT_EQ(1, surfaceFrame->getToken()); + EXPECT_EQ(PresentState::Presented, surfaceFrame->getPresentState()); + } + + void DroppedSurfaceFrameForBufferTransaction() { + sp layer = createBufferStateLayer(); + + sp fence1(new Fence()); + auto acquireFence1 = fenceFactory.createFenceTimeForTest(fence1); + sp buffer1{new GraphicBuffer(1, 1, HAL_PIXEL_FORMAT_RGBA_8888, 1, 0)}; + layer->setBuffer(buffer1, fence1, 10, 20, false, mClientCache, 1, std::nullopt, + {/*vsyncId*/ 1, /*inputEventId*/ 0}); + EXPECT_EQ(0u, layer->mCurrentState.bufferlessSurfaceFramesTX.size()); + ASSERT_NE(nullptr, layer->mCurrentState.bufferSurfaceFrameTX); + const auto droppedSurfaceFrame = layer->mCurrentState.bufferSurfaceFrameTX; + + sp fence2(new Fence()); + auto acquireFence2 = fenceFactory.createFenceTimeForTest(fence2); + sp buffer2{new GraphicBuffer(1, 1, HAL_PIXEL_FORMAT_RGBA_8888, 1, 0)}; + layer->setBuffer(buffer2, fence2, 10, 20, false, mClientCache, 1, std::nullopt, + {/*vsyncId*/ 1, /*inputEventId*/ 0}); + acquireFence2->signalForTest(12); + + EXPECT_EQ(0u, layer->mCurrentState.bufferlessSurfaceFramesTX.size()); + ASSERT_NE(nullptr, layer->mCurrentState.bufferSurfaceFrameTX); + const auto& presentedSurfaceFrame = layer->mCurrentState.bufferSurfaceFrameTX; + + commitTransaction(layer.get()); + bool computeVisisbleRegions; + layer->updateTexImage(computeVisisbleRegions, 15, 0); + + EXPECT_EQ(1, droppedSurfaceFrame->getToken()); + EXPECT_EQ(PresentState::Dropped, droppedSurfaceFrame->getPresentState()); + + EXPECT_EQ(1, presentedSurfaceFrame->getToken()); + EXPECT_EQ(PresentState::Presented, presentedSurfaceFrame->getPresentState()); + } + + void BufferlessSurfaceFramePromotedToBufferSurfaceFrame() { + sp layer = createBufferStateLayer(); + + layer->setFrameTimelineVsyncForBufferlessTransaction({/*vsyncId*/ 1, /*inputEventId*/ 0}, + 10); + + EXPECT_EQ(1u, layer->mCurrentState.bufferlessSurfaceFramesTX.size()); + ASSERT_EQ(nullptr, layer->mCurrentState.bufferSurfaceFrameTX); + + sp fence(new Fence()); + auto acquireFence = fenceFactory.createFenceTimeForTest(fence); + sp buffer{new GraphicBuffer(1, 1, HAL_PIXEL_FORMAT_RGBA_8888, 1, 0)}; + + layer->setBuffer(buffer, fence, 10, 20, false, mClientCache, 1, std::nullopt, + {/*vsyncId*/ 1, /*inputEventId*/ 0}); + acquireFence->signalForTest(12); + + EXPECT_EQ(0u, layer->mCurrentState.bufferlessSurfaceFramesTX.size()); + ASSERT_NE(nullptr, layer->mCurrentState.bufferSurfaceFrameTX); + const auto& surfaceFrame = layer->mCurrentState.bufferSurfaceFrameTX; + + commitTransaction(layer.get()); + EXPECT_EQ(1, surfaceFrame->getToken()); + // Buffers are presented only at latch time. + EXPECT_EQ(PresentState::Unknown, surfaceFrame->getPresentState()); + + bool computeVisisbleRegions; + layer->updateTexImage(computeVisisbleRegions, 15, 0); + + EXPECT_EQ(PresentState::Presented, surfaceFrame->getPresentState()); + } + + void BufferlessSurfaceFrameNotCreatedIfBufferSufaceFrameExists() { + sp layer = createBufferStateLayer(); + sp fence(new Fence()); + auto acquireFence = fenceFactory.createFenceTimeForTest(fence); + sp buffer{new GraphicBuffer(1, 1, HAL_PIXEL_FORMAT_RGBA_8888, 1, 0)}; + + layer->setBuffer(buffer, fence, 10, 20, false, mClientCache, 1, std::nullopt, + {/*vsyncId*/ 1, /*inputEventId*/ 0}); + EXPECT_EQ(0u, layer->mCurrentState.bufferlessSurfaceFramesTX.size()); + ASSERT_NE(nullptr, layer->mCurrentState.bufferSurfaceFrameTX); + + layer->setFrameTimelineVsyncForBufferlessTransaction({/*vsyncId*/ 1, /*inputEventId*/ 0}, + 10); + EXPECT_EQ(0u, layer->mCurrentState.bufferlessSurfaceFramesTX.size()); + ASSERT_NE(nullptr, layer->mCurrentState.bufferSurfaceFrameTX); + } + + void MultipleSurfaceFramesPresentedTogether() { + sp layer = createBufferStateLayer(); + layer->setFrameTimelineVsyncForBufferlessTransaction({/*vsyncId*/ 1, /*inputEventId*/ 0}, + 10); + EXPECT_EQ(1u, layer->mCurrentState.bufferlessSurfaceFramesTX.size()); + ASSERT_EQ(nullptr, layer->mCurrentState.bufferSurfaceFrameTX); + const auto bufferlessSurfaceFrame1 = + layer->mCurrentState.bufferlessSurfaceFramesTX.at(/*token*/ 1); + + layer->setFrameTimelineVsyncForBufferlessTransaction({/*vsyncId*/ 4, /*inputEventId*/ 0}, + 10); + EXPECT_EQ(2u, layer->mCurrentState.bufferlessSurfaceFramesTX.size()); + ASSERT_EQ(nullptr, layer->mCurrentState.bufferSurfaceFrameTX); + const auto bufferlessSurfaceFrame2 = layer->mCurrentState.bufferlessSurfaceFramesTX[4]; + + sp fence(new Fence()); + auto acquireFence = fenceFactory.createFenceTimeForTest(fence); + sp buffer{new GraphicBuffer(1, 1, HAL_PIXEL_FORMAT_RGBA_8888, 1, 0)}; + + layer->setBuffer(buffer, fence, 10, 20, false, mClientCache, 1, std::nullopt, + {/*vsyncId*/ 3, /*inputEventId*/ 0}); + EXPECT_EQ(2u, layer->mCurrentState.bufferlessSurfaceFramesTX.size()); + ASSERT_NE(nullptr, layer->mCurrentState.bufferSurfaceFrameTX); + const auto& bufferSurfaceFrameTX = layer->mCurrentState.bufferSurfaceFrameTX; + + acquireFence->signalForTest(12); + + commitTransaction(layer.get()); + + EXPECT_EQ(1, bufferlessSurfaceFrame1->getToken()); + EXPECT_EQ(PresentState::Presented, bufferlessSurfaceFrame1->getPresentState()); + + EXPECT_EQ(4, bufferlessSurfaceFrame2->getToken()); + EXPECT_EQ(PresentState::Presented, bufferlessSurfaceFrame2->getPresentState()); + + EXPECT_EQ(3, bufferSurfaceFrameTX->getToken()); + // Buffers are presented only at latch time. + EXPECT_EQ(PresentState::Unknown, bufferSurfaceFrameTX->getPresentState()); + + bool computeVisisbleRegions; + layer->updateTexImage(computeVisisbleRegions, 15, 0); + + EXPECT_EQ(PresentState::Presented, bufferSurfaceFrameTX->getPresentState()); + } + + void MergePendingStates_BufferlessSurfaceFramesWithoutOverlappingToken() { + sp layer = createBufferStateLayer(); + layer->setFrameTimelineVsyncForBufferlessTransaction({/*vsyncId*/ 1, /*inputEventId*/ 0}, + 10); + EXPECT_EQ(1u, layer->mCurrentState.bufferlessSurfaceFramesTX.size()); + ASSERT_EQ(nullptr, layer->mCurrentState.bufferSurfaceFrameTX); + const auto bufferlessSurfaceFrame1 = + layer->mCurrentState.bufferlessSurfaceFramesTX.at(/*token*/ 1); + + layer->pushPendingState(); + EXPECT_EQ(0u, layer->mCurrentState.bufferlessSurfaceFramesTX.size()); + + layer->setFrameTimelineVsyncForBufferlessTransaction({/*vsyncId*/ 2, /*inputEventId*/ 0}, + 12); + EXPECT_EQ(1u, layer->mCurrentState.bufferlessSurfaceFramesTX.size()); + ASSERT_EQ(nullptr, layer->mCurrentState.bufferSurfaceFrameTX); + const auto bufferlessSurfaceFrame2 = + layer->mCurrentState.bufferlessSurfaceFramesTX.at(/*token*/ 2); + + commitTransaction(layer.get()); + + EXPECT_EQ(1, bufferlessSurfaceFrame1->getToken()); + EXPECT_EQ(PresentState::Presented, bufferlessSurfaceFrame1->getPresentState()); + EXPECT_EQ(10, bufferlessSurfaceFrame1->getActuals().endTime); + + EXPECT_EQ(2, bufferlessSurfaceFrame2->getToken()); + EXPECT_EQ(PresentState::Presented, bufferlessSurfaceFrame2->getPresentState()); + EXPECT_EQ(12, bufferlessSurfaceFrame2->getActuals().endTime); + } + + void MergePendingStates_BufferlessSurfaceFramesWithOverlappingToken() { + sp layer = createBufferStateLayer(); + layer->setFrameTimelineVsyncForBufferlessTransaction({/*vsyncId*/ 1, /*inputEventId*/ 0}, + 10); + EXPECT_EQ(1u, layer->mCurrentState.bufferlessSurfaceFramesTX.size()); + ASSERT_EQ(nullptr, layer->mCurrentState.bufferSurfaceFrameTX); + const auto bufferlessSurfaceFrame1 = + layer->mCurrentState.bufferlessSurfaceFramesTX.at(/*token*/ 1); + + layer->pushPendingState(); + EXPECT_EQ(0u, layer->mCurrentState.bufferlessSurfaceFramesTX.size()); + + layer->setFrameTimelineVsyncForBufferlessTransaction({/*vsyncId*/ 1, /*inputEventId*/ 0}, + 12); + EXPECT_EQ(1u, layer->mCurrentState.bufferlessSurfaceFramesTX.size()); + ASSERT_EQ(nullptr, layer->mCurrentState.bufferSurfaceFrameTX); + const auto bufferlessSurfaceFrame2 = + layer->mCurrentState.bufferlessSurfaceFramesTX.at(/*token*/ 1); + + commitTransaction(layer.get()); + + EXPECT_EQ(1, bufferlessSurfaceFrame1->getToken()); + EXPECT_EQ(PresentState::Unknown, bufferlessSurfaceFrame1->getPresentState()); + + EXPECT_EQ(1, bufferlessSurfaceFrame2->getToken()); + EXPECT_EQ(PresentState::Presented, bufferlessSurfaceFrame2->getPresentState()); + EXPECT_EQ(12, bufferlessSurfaceFrame2->getActuals().endTime); + } +}; + +TEST_F(TransactionSurfaceFrameTest, PresentedBufferlessSurfaceFrame) { + PresentedSurfaceFrameForBufferlessTransaction(); +} + +TEST_F(TransactionSurfaceFrameTest, PresentedBufferSurfaceFrame) { + PresentedSurfaceFrameForBufferTransaction(); +} + +TEST_F(TransactionSurfaceFrameTest, DroppedBufferSurfaceFrame) { + DroppedSurfaceFrameForBufferTransaction(); +} + +TEST_F(TransactionSurfaceFrameTest, BufferlessSurfaceFramePromotedToBufferSurfaceFrame) { + BufferlessSurfaceFramePromotedToBufferSurfaceFrame(); +} + +TEST_F(TransactionSurfaceFrameTest, BufferlessSurfaceFrameNotCreatedIfBufferSufaceFrameExists) { + BufferlessSurfaceFrameNotCreatedIfBufferSufaceFrameExists(); +} + +TEST_F(TransactionSurfaceFrameTest, MultipleSurfaceFramesPresentedTogether) { + MultipleSurfaceFramesPresentedTogether(); +} + +TEST_F(TransactionSurfaceFrameTest, + MergePendingStates_BufferlessSurfaceFramesWithoutOverlappingToken) { + MergePendingStates_BufferlessSurfaceFramesWithoutOverlappingToken(); +} + +TEST_F(TransactionSurfaceFrameTest, + MergePendingStates_BufferlessSurfaceFramesWithOverlappingToken) { + MergePendingStates_BufferlessSurfaceFramesWithOverlappingToken(); +} + +} // namespace android \ No newline at end of file -- cgit v1.2.3-59-g8ed1b From 1a48fab10b3b5b9ab9bfb3c5166d72843e861535 Mon Sep 17 00:00:00 2001 From: Rahul Sharma Date: Wed, 9 Jun 2021 11:21:40 +0530 Subject: Fix for FWR SF crash bug:176224224 Test: Stress test Change-Id: I89110a28c27ebc66f28466b61bf99ef0c4c3437d --- services/surfaceflinger/BufferQueueLayer.cpp | 25 +++++++++++++++---------- 1 file changed, 15 insertions(+), 10 deletions(-) (limited to 'services/surfaceflinger/BufferQueueLayer.cpp') diff --git a/services/surfaceflinger/BufferQueueLayer.cpp b/services/surfaceflinger/BufferQueueLayer.cpp index e7f373ff3f..2f2e6731fe 100644 --- a/services/surfaceflinger/BufferQueueLayer.cpp +++ b/services/surfaceflinger/BufferQueueLayer.cpp @@ -125,11 +125,11 @@ bool BufferQueueLayer::isBufferDue(nsecs_t expectedPresentTime) const { // ----------------------------------------------------------------------- bool BufferQueueLayer::fenceHasSignaled() const { + Mutex::Autolock lock(mQueueItemLock); if (!hasFrameUpdate()) { return true; } - Mutex::Autolock lock(mQueueItemLock); if (mQueueItems[0].item.mIsDroppable) { // Even though this buffer's fence may not have signaled yet, it could // be replaced by another buffer before it has a chance to, which means @@ -148,11 +148,12 @@ bool BufferQueueLayer::fenceHasSignaled() const { } bool BufferQueueLayer::framePresentTimeIsCurrent(nsecs_t expectedPresentTime) const { + Mutex::Autolock lock(mQueueItemLock); + if (!hasFrameUpdate() || isRemovedFromCurrentState()) { return true; } - Mutex::Autolock lock(mQueueItemLock); return mQueueItems[0].item.mTimestamp <= expectedPresentTime; } @@ -264,13 +265,15 @@ status_t BufferQueueLayer::updateTexImage(bool& recomputeVisibleRegions, nsecs_t // and return early if (queuedBuffer) { Mutex::Autolock lock(mQueueItemLock); - mConsumer->mergeSurfaceDamage(mQueueItems[0].item.mSurfaceDamage); - mFlinger->mTimeStats->removeTimeRecord(layerId, mQueueItems[0].item.mFrameNumber); - if (mQueueItems[0].surfaceFrame) { - addSurfaceFrameDroppedForBuffer(mQueueItems[0].surfaceFrame); + if (mQueuedFrames > 0) { + mConsumer->mergeSurfaceDamage(mQueueItems[0].item.mSurfaceDamage); + mFlinger->mTimeStats->removeTimeRecord(layerId, mQueueItems[0].item.mFrameNumber); + if (mQueueItems[0].surfaceFrame) { + addSurfaceFrameDroppedForBuffer(mQueueItems[0].surfaceFrame); + } + mQueueItems.erase(mQueueItems.begin()); + mQueuedFrames--; } - mQueueItems.erase(mQueueItems.begin()); - mQueuedFrames--; } return BAD_VALUE; } else if (updateResult != NO_ERROR || mUpdateTexImageFailed) { @@ -300,6 +303,7 @@ status_t BufferQueueLayer::updateTexImage(bool& recomputeVisibleRegions, nsecs_t return BAD_VALUE; } + bool more_frames_pending = false; if (queuedBuffer) { // Autolock scope auto currentFrameNumber = mConsumer->getFrameNumber(); @@ -308,7 +312,7 @@ status_t BufferQueueLayer::updateTexImage(bool& recomputeVisibleRegions, nsecs_t // Remove any stale buffers that have been dropped during // updateTexImage - while (mQueueItems[0].item.mFrameNumber != currentFrameNumber) { + while (mQueuedFrames > 0 && mQueueItems[0].item.mFrameNumber != currentFrameNumber) { mConsumer->mergeSurfaceDamage(mQueueItems[0].item.mSurfaceDamage); mFlinger->mTimeStats->removeTimeRecord(layerId, mQueueItems[0].item.mFrameNumber); if (mQueueItems[0].surfaceFrame) { @@ -329,11 +333,12 @@ status_t BufferQueueLayer::updateTexImage(bool& recomputeVisibleRegions, nsecs_t latchTime); } mQueueItems.erase(mQueueItems.begin()); + more_frames_pending = (mQueuedFrames.fetch_sub(1) > 1); } // Decrement the queued-frames count. Signal another event if we // have more frames pending. - if ((queuedBuffer && mQueuedFrames.fetch_sub(1) > 1) || mAutoRefresh) { + if ((queuedBuffer && more_frames_pending) || mAutoRefresh) { mFlinger->signalLayerUpdate(); } -- cgit v1.2.3-59-g8ed1b From f3441822fb8360cacd2d30bcb6731c2841597fc9 Mon Sep 17 00:00:00 2001 From: Huihong Luo Date: Wed, 16 Jun 2021 15:41:07 -0700 Subject: Re-introduce debug.sf.latch_unsignaled This pretty much reverts this commit: Ia453eaf895554adbb2fa9c11c2bc8609e1037ea5. Some devices may find this helpful to improve performance, but there is a risk of pipeline stall from misbehaving apps. Bug: 173694115 Test: manual Change-Id: I48c3095061dc106fa08d36b8ef17eccb04fb6eb1 --- services/surfaceflinger/BufferQueueLayer.cpp | 5 +++++ services/surfaceflinger/BufferStateLayer.cpp | 4 ++++ services/surfaceflinger/SurfaceFlinger.cpp | 5 ++++- services/surfaceflinger/SurfaceFlinger.h | 2 ++ 4 files changed, 15 insertions(+), 1 deletion(-) (limited to 'services/surfaceflinger/BufferQueueLayer.cpp') diff --git a/services/surfaceflinger/BufferQueueLayer.cpp b/services/surfaceflinger/BufferQueueLayer.cpp index b236fd24ff..2fa89364ae 100644 --- a/services/surfaceflinger/BufferQueueLayer.cpp +++ b/services/surfaceflinger/BufferQueueLayer.cpp @@ -126,6 +126,11 @@ bool BufferQueueLayer::isBufferDue(nsecs_t expectedPresentTime) const { bool BufferQueueLayer::fenceHasSignaled() const { Mutex::Autolock lock(mQueueItemLock); + + if (SurfaceFlinger::enableLatchUnsignaled) { + return true; + } + if (!hasFrameUpdate()) { return true; } diff --git a/services/surfaceflinger/BufferStateLayer.cpp b/services/surfaceflinger/BufferStateLayer.cpp index 2a49a0a340..645e883364 100644 --- a/services/surfaceflinger/BufferStateLayer.cpp +++ b/services/surfaceflinger/BufferStateLayer.cpp @@ -635,6 +635,10 @@ FloatRect BufferStateLayer::computeSourceBounds(const FloatRect& parentBounds) c // Interface implementation for BufferLayer // ----------------------------------------------------------------------- bool BufferStateLayer::fenceHasSignaled() const { + if (SurfaceFlinger::enableLatchUnsignaled) { + return true; + } + const bool fenceSignaled = getDrawingState().acquireFence->getStatus() == Fence::Status::Signaled; if (!fenceSignaled) { diff --git a/services/surfaceflinger/SurfaceFlinger.cpp b/services/surfaceflinger/SurfaceFlinger.cpp index 27f00386d0..67287a71a0 100644 --- a/services/surfaceflinger/SurfaceFlinger.cpp +++ b/services/surfaceflinger/SurfaceFlinger.cpp @@ -311,6 +311,7 @@ Dataspace SurfaceFlinger::wideColorGamutCompositionDataspace = Dataspace::V0_SRG ui::PixelFormat SurfaceFlinger::wideColorGamutCompositionPixelFormat = ui::PixelFormat::RGBA_8888; bool SurfaceFlinger::useFrameRateApi; bool SurfaceFlinger::enableSdrDimming; +bool SurfaceFlinger::enableLatchUnsignaled; std::string decodeDisplayColorSetting(DisplayColorSetting displayColorSetting) { switch(displayColorSetting) { @@ -480,6 +481,8 @@ SurfaceFlinger::SurfaceFlinger(Factory& factory) : SurfaceFlinger(factory, SkipI // Debug property overrides ro. property enableSdrDimming = property_get_bool("debug.sf.enable_sdr_dimming", enable_sdr_dimming(false)); + + enableLatchUnsignaled = base::GetBoolProperty("debug.sf.latch_unsignaled"s, false); } SurfaceFlinger::~SurfaceFlinger() = default; @@ -3566,7 +3569,7 @@ bool SurfaceFlinger::transactionIsReadyToBeApplied( for (const ComposerState& state : states) { const layer_state_t& s = state.state; const bool acquireFenceChanged = (s.what & layer_state_t::eAcquireFenceChanged); - if (acquireFenceChanged && s.acquireFence && + if (acquireFenceChanged && s.acquireFence && !enableLatchUnsignaled && s.acquireFence->getStatus() == Fence::Status::Unsignaled) { ATRACE_NAME("fence unsignaled"); return false; diff --git a/services/surfaceflinger/SurfaceFlinger.h b/services/surfaceflinger/SurfaceFlinger.h index 1d6f016933..6cff608ee3 100644 --- a/services/surfaceflinger/SurfaceFlinger.h +++ b/services/surfaceflinger/SurfaceFlinger.h @@ -270,6 +270,8 @@ public: // being treated as native display brightness static bool enableSdrDimming; + static bool enableLatchUnsignaled; + // must be called before clients can connect void init() ANDROID_API; -- cgit v1.2.3-59-g8ed1b From 9691b9c07fe135b3bd1ea5375daf9aa57ec3b797 Mon Sep 17 00:00:00 2001 From: baocheng sun Date: Tue, 3 Aug 2021 19:27:06 +0800 Subject: sf: send sideband frame to hwc when recieve a buffer Bug: 186383891 Test: tunnel and nontunnel playback switch in netflix Change-Id: Ic6ee886503639e8c6652589217e0aec893ffd681 --- services/surfaceflinger/BufferLayer.cpp | 3 ++- services/surfaceflinger/BufferQueueLayer.cpp | 5 ++--- services/surfaceflinger/BufferStateLayer.cpp | 4 ++-- .../include/compositionengine/LayerFECompositionState.h | 2 ++ 4 files changed, 8 insertions(+), 6 deletions(-) (limited to 'services/surfaceflinger/BufferQueueLayer.cpp') diff --git a/services/surfaceflinger/BufferLayer.cpp b/services/surfaceflinger/BufferLayer.cpp index b600fad66d..d805294b07 100644 --- a/services/surfaceflinger/BufferLayer.cpp +++ b/services/surfaceflinger/BufferLayer.cpp @@ -287,7 +287,7 @@ void BufferLayer::preparePerFrameCompositionState() { // Sideband layers auto* compositionState = editCompositionState(); - if (compositionState->sidebandStream.get()) { + if (compositionState->sidebandStream.get() && !compositionState->sidebandStreamHasFrame) { compositionState->compositionType = Hwc2::IComposerClient::Composition::SIDEBAND; return; } else { @@ -303,6 +303,7 @@ void BufferLayer::preparePerFrameCompositionState() { ? 0 : mBufferInfo.mBufferSlot; compositionState->acquireFence = mBufferInfo.mFence; + compositionState->sidebandStreamHasFrame = false; } bool BufferLayer::onPreComposition(nsecs_t refreshStartTime) { diff --git a/services/surfaceflinger/BufferQueueLayer.cpp b/services/surfaceflinger/BufferQueueLayer.cpp index 81254ac64e..e4f642e1f6 100644 --- a/services/surfaceflinger/BufferQueueLayer.cpp +++ b/services/surfaceflinger/BufferQueueLayer.cpp @@ -197,11 +197,10 @@ uint64_t BufferQueueLayer::getFrameNumber(nsecs_t expectedPresentTime) const { bool BufferQueueLayer::latchSidebandStream(bool& recomputeVisibleRegions) { // We need to update the sideband stream if the layer has both a buffer and a sideband stream. - const bool updateSidebandStream = hasFrameUpdate() && mSidebandStream.get(); + editCompositionState()->sidebandStreamHasFrame = hasFrameUpdate() && mSidebandStream.get(); bool sidebandStreamChanged = true; - if (mSidebandStreamChanged.compare_exchange_strong(sidebandStreamChanged, false) || - updateSidebandStream) { + if (mSidebandStreamChanged.compare_exchange_strong(sidebandStreamChanged, false)) { // mSidebandStreamChanged was changed to false mSidebandStream = mConsumer->getSidebandStream(); auto* layerCompositionState = editCompositionState(); diff --git a/services/surfaceflinger/BufferStateLayer.cpp b/services/surfaceflinger/BufferStateLayer.cpp index 6253036c41..e329aa0f1c 100644 --- a/services/surfaceflinger/BufferStateLayer.cpp +++ b/services/surfaceflinger/BufferStateLayer.cpp @@ -703,9 +703,9 @@ void BufferStateLayer::setAutoRefresh(bool autoRefresh) { bool BufferStateLayer::latchSidebandStream(bool& recomputeVisibleRegions) { // We need to update the sideband stream if the layer has both a buffer and a sideband stream. - const bool updateSidebandStream = hasFrameUpdate() && mSidebandStream.get(); + editCompositionState()->sidebandStreamHasFrame = hasFrameUpdate() && mSidebandStream.get(); - if (mSidebandStreamChanged.exchange(false) || updateSidebandStream) { + if (mSidebandStreamChanged.exchange(false)) { const State& s(getDrawingState()); // mSidebandStreamChanged was true mSidebandStream = s.sidebandStream; diff --git a/services/surfaceflinger/CompositionEngine/include/compositionengine/LayerFECompositionState.h b/services/surfaceflinger/CompositionEngine/include/compositionengine/LayerFECompositionState.h index a45be8a7a2..222128096f 100644 --- a/services/surfaceflinger/CompositionEngine/include/compositionengine/LayerFECompositionState.h +++ b/services/surfaceflinger/CompositionEngine/include/compositionengine/LayerFECompositionState.h @@ -167,6 +167,8 @@ struct LayerFECompositionState { // The handle to use for a sideband stream for this layer sp sidebandStream; + // If true, this sideband layer has a frame update + bool sidebandStreamHasFrame{false}; // The color for this layer half4 color; -- cgit v1.2.3-59-g8ed1b From e3ce49da3f975eb9d9f516e460b83f1bdec188d6 Mon Sep 17 00:00:00 2001 From: Siarhei Vishniakou Date: Tue, 29 Sep 2020 19:08:13 -0500 Subject: Remove some clang warnings Fix some clang warnings: 1. Unused variable (use constexpr instead of #define) 2. -Wextra warnings 3. Remove unused import Bug: 167947340 Test: compile and observe warnings Change-Id: Ie4a7bb1aad30f0e6556d23621ec6268185bec536 --- services/inputflinger/InputManager.h | 1 - services/inputflinger/reader/Macros.h | 2 +- .../reader/mapper/MultiTouchInputMapper.cpp | 30 +++++++++++----------- services/surfaceflinger/BufferQueueLayer.cpp | 7 +++-- 4 files changed, 19 insertions(+), 21 deletions(-) (limited to 'services/surfaceflinger/BufferQueueLayer.cpp') diff --git a/services/inputflinger/InputManager.h b/services/inputflinger/InputManager.h index 4c07c22154..f053568143 100644 --- a/services/inputflinger/InputManager.h +++ b/services/inputflinger/InputManager.h @@ -30,7 +30,6 @@ #include #include -#include #include #include #include diff --git a/services/inputflinger/reader/Macros.h b/services/inputflinger/reader/Macros.h index 827e31a1bd..0dfe7f1c81 100644 --- a/services/inputflinger/reader/Macros.h +++ b/services/inputflinger/reader/Macros.h @@ -31,7 +31,7 @@ #define DEBUG_VIRTUAL_KEYS 0 // Log debug messages about pointers. -#define DEBUG_POINTERS 0 +static constexpr bool DEBUG_POINTERS = false; // Log debug messages about pointer assignment calculations. #define DEBUG_POINTER_ASSIGNMENT 0 diff --git a/services/inputflinger/reader/mapper/MultiTouchInputMapper.cpp b/services/inputflinger/reader/mapper/MultiTouchInputMapper.cpp index fab7f4ca14..4bd1cd8d12 100644 --- a/services/inputflinger/reader/mapper/MultiTouchInputMapper.cpp +++ b/services/inputflinger/reader/mapper/MultiTouchInputMapper.cpp @@ -95,13 +95,13 @@ void MultiTouchMotionAccumulator::process(const RawEvent* rawEvent) { } if (mCurrentSlot < 0 || size_t(mCurrentSlot) >= mSlotCount) { -#if DEBUG_POINTERS - if (newSlot) { - ALOGW("MultiTouch device emitted invalid slot index %d but it " - "should be between 0 and %zd; ignoring this slot.", - mCurrentSlot, mSlotCount - 1); + if (DEBUG_POINTERS) { + if (newSlot) { + ALOGW("MultiTouch device emitted invalid slot index %d but it " + "should be between 0 and %zd; ignoring this slot.", + mCurrentSlot, mSlotCount - 1); + } } -#endif } else { Slot* slot = &mSlots[mCurrentSlot]; // If mUsingSlotsProtocol is true, it means the raw pointer has axis info of @@ -273,19 +273,19 @@ void MultiTouchInputMapper::syncTouch(nsecs_t when, RawState* outState) { if (id) { outState->rawPointerData.canceledIdBits.markBit(id.value()); } -#if DEBUG_POINTERS - ALOGI("Stop processing slot %zu for it received a palm event from device %s", inIndex, - getDeviceName().c_str()); -#endif + if (DEBUG_POINTERS) { + ALOGI("Stop processing slot %zu for it received a palm event from device %s", + inIndex, getDeviceName().c_str()); + } continue; } if (outCount >= MAX_POINTERS) { -#if DEBUG_POINTERS - ALOGD("MultiTouch device %s emitted more than maximum of %d pointers; " - "ignoring the rest.", - getDeviceName().c_str(), MAX_POINTERS); -#endif + if (DEBUG_POINTERS) { + ALOGD("MultiTouch device %s emitted more than maximum of %d pointers; " + "ignoring the rest.", + getDeviceName().c_str(), MAX_POINTERS); + } break; // too many fingers! } diff --git a/services/surfaceflinger/BufferQueueLayer.cpp b/services/surfaceflinger/BufferQueueLayer.cpp index e4f642e1f6..d51db88662 100644 --- a/services/surfaceflinger/BufferQueueLayer.cpp +++ b/services/surfaceflinger/BufferQueueLayer.cpp @@ -17,7 +17,6 @@ // TODO(b/129481165): remove the #pragma below and fix conversion issues #pragma clang diagnostic push #pragma clang diagnostic ignored "-Wconversion" -#pragma clang diagnostic ignored "-Wextra" #undef LOG_TAG #define LOG_TAG "BufferQueueLayer" @@ -171,7 +170,7 @@ uint64_t BufferQueueLayer::getFrameNumber(nsecs_t expectedPresentTime) const { expectedPresentTime = 0; } - for (int i = 1; i < mQueueItems.size(); i++) { + for (size_t i = 1; i < mQueueItems.size(); i++) { const bool fenceSignaled = mQueueItems[i].item.mFenceTime->getSignalTime() != Fence::SIGNAL_TIME_PENDING; if (!fenceSignaled) { @@ -243,7 +242,7 @@ status_t BufferQueueLayer::updateTexImage(bool& recomputeVisibleRegions, nsecs_t uint64_t lastSignaledFrameNumber = mLastFrameNumberReceived; { Mutex::Autolock lock(mQueueItemLock); - for (int i = 0; i < mQueueItems.size(); i++) { + for (size_t i = 0; i < mQueueItems.size(); i++) { bool fenceSignaled = mQueueItems[i].item.mFenceTime->getSignalTime() != Fence::SIGNAL_TIME_PENDING; if (!fenceSignaled) { @@ -629,4 +628,4 @@ void BufferQueueLayer::ContentsChangedListener::abandon() { } // namespace android // TODO(b/129481165): remove the #pragma below and fix conversion issues -#pragma clang diagnostic pop // ignored "-Wconversion -Wextra" +#pragma clang diagnostic pop // ignored "-Wconversion" -- cgit v1.2.3-59-g8ed1b From ba4320c070e62f3ef7aea27c04684f5b53c5707d Mon Sep 17 00:00:00 2001 From: chaviw Date: Wed, 15 Sep 2021 15:20:53 -0500 Subject: Combine Buffer Properties when calling setBuffer There are several properties, like releaseCallback, acquireFence, frameNumber, that are tied to the buffer being set. If a new buffer is set, all those properties should also be overwritten, rather than through a separate call. 1. Remove Transaction.setAcquireFence and Transaction.setFrameNumber and added them to the setBuffer as optional 2. Combine all the buffer info into a struct called BufferData that's sent to SF as one. This will also help with merging or overwriting buffer data since the callback, frameNumber, and acquireFence should also be updated. 3. Combine the functions in SF so there's no longer a separate call to BSL to set fence. Instead, send all buffer related data to BSL.setBuffer Test: SurfaceFlinger_test Fixes: 200065015 Change-Id: I53ad12dd105cd4cac6c3a7ecd48279d1b3cd2b8f --- libs/gui/BLASTBufferQueue.cpp | 7 +- libs/gui/LayerState.cpp | 139 ++++++++------- libs/gui/SurfaceComposerClient.cpp | 86 ++++----- libs/gui/include/gui/LayerState.h | 71 +++++--- libs/gui/include/gui/SurfaceComposerClient.h | 9 +- services/surfaceflinger/BufferLayer.cpp | 8 - services/surfaceflinger/BufferLayer.h | 4 - services/surfaceflinger/BufferQueueLayer.cpp | 33 ---- services/surfaceflinger/BufferQueueLayer.h | 1 - services/surfaceflinger/BufferStateLayer.cpp | 111 ++++++------ services/surfaceflinger/BufferStateLayer.h | 16 +- services/surfaceflinger/Layer.h | 14 +- services/surfaceflinger/SurfaceFlinger.cpp | 52 +----- services/surfaceflinger/SurfaceFlinger.h | 8 +- services/surfaceflinger/tests/IPC_test.cpp | 6 +- .../surfaceflinger/tests/LayerCallback_test.cpp | 3 +- .../tests/LayerRenderTypeTransaction_test.cpp | 4 +- .../tests/ReleaseBufferCallback_test.cpp | 18 +- .../tests/unittests/TransactionFrameTracerTest.cpp | 22 +-- .../unittests/TransactionSurfaceFrameTest.cpp | 196 +++++++++++---------- 20 files changed, 361 insertions(+), 447 deletions(-) (limited to 'services/surfaceflinger/BufferQueueLayer.cpp') diff --git a/libs/gui/BLASTBufferQueue.cpp b/libs/gui/BLASTBufferQueue.cpp index 379b090c5b..cc209f39f5 100644 --- a/libs/gui/BLASTBufferQueue.cpp +++ b/libs/gui/BLASTBufferQueue.cpp @@ -468,12 +468,12 @@ void BLASTBufferQueue::processNextBufferLocked(bool useNextTransaction) { std::bind(releaseBufferCallbackThunk, wp(this) /* callbackContext */, std::placeholders::_1, std::placeholders::_2, std::placeholders::_3, std::placeholders::_4); - t->setBuffer(mSurfaceControl, buffer, releaseCallbackId, releaseBufferCallback); + sp fence = bufferItem.mFence ? new Fence(bufferItem.mFence->dup()) : Fence::NO_FENCE; + t->setBuffer(mSurfaceControl, buffer, fence, bufferItem.mFrameNumber, releaseCallbackId, + releaseBufferCallback); t->setDataspace(mSurfaceControl, static_cast(bufferItem.mDataSpace)); t->setHdrMetadata(mSurfaceControl, bufferItem.mHdrMetadata); t->setSurfaceDamageRegion(mSurfaceControl, bufferItem.mSurfaceDamage); - t->setAcquireFence(mSurfaceControl, - bufferItem.mFence ? new Fence(bufferItem.mFence->dup()) : Fence::NO_FENCE); t->addTransactionCompletedCallback(transactionCallbackThunk, static_cast(this)); mSurfaceControlsWithPendingCallback.push(mSurfaceControl); @@ -486,7 +486,6 @@ void BLASTBufferQueue::processNextBufferLocked(bool useNextTransaction) { if (!bufferItem.mIsAutoTimestamp) { t->setDesiredPresentTime(bufferItem.mTimestamp); } - t->setFrameNumber(mSurfaceControl, bufferItem.mFrameNumber); if (!mNextFrameTimelineInfoQueue.empty()) { t->setFrameTimelineInfo(mNextFrameTimelineInfoQueue.front()); diff --git a/libs/gui/LayerState.cpp b/libs/gui/LayerState.cpp index a419a63056..cf61209d6c 100644 --- a/libs/gui/LayerState.cpp +++ b/libs/gui/LayerState.cpp @@ -64,12 +64,10 @@ layer_state_t::layer_state_t() frameRateCompatibility(ANATIVEWINDOW_FRAME_RATE_COMPATIBILITY_DEFAULT), changeFrameRateStrategy(ANATIVEWINDOW_CHANGE_FRAME_RATE_ONLY_IF_SEAMLESS), fixedTransformHint(ui::Transform::ROT_INVALID), - frameNumber(0), autoRefresh(false), isTrustedOverlay(false), bufferCrop(Rect::INVALID_RECT), destinationFrame(Rect::INVALID_RECT), - releaseBufferListener(nullptr), dropInputMode(gui::DropInputMode::NONE) { matrix.dsdx = matrix.dtdy = 1.0f; matrix.dsdy = matrix.dtdx = 0.0f; @@ -104,20 +102,6 @@ status_t layer_state_t::write(Parcel& output) const SAFE_PARCEL(output.writeBool, transformToDisplayInverse); SAFE_PARCEL(output.write, orientedDisplaySpaceRect); - if (buffer) { - SAFE_PARCEL(output.writeBool, true); - SAFE_PARCEL(output.write, *buffer); - } else { - SAFE_PARCEL(output.writeBool, false); - } - - if (acquireFence) { - SAFE_PARCEL(output.writeBool, true); - SAFE_PARCEL(output.write, *acquireFence); - } else { - SAFE_PARCEL(output.writeBool, false); - } - SAFE_PARCEL(output.writeUint32, static_cast(dataspace)); SAFE_PARCEL(output.write, hdrMetadata); SAFE_PARCEL(output.write, surfaceDamageRegion); @@ -133,8 +117,6 @@ status_t layer_state_t::write(Parcel& output) const SAFE_PARCEL(output.write, colorTransform.asArray(), 16 * sizeof(float)); SAFE_PARCEL(output.writeFloat, cornerRadius); SAFE_PARCEL(output.writeUint32, backgroundBlurRadius); - SAFE_PARCEL(output.writeStrongBinder, cachedBuffer.token.promote()); - SAFE_PARCEL(output.writeUint64, cachedBuffer.id); SAFE_PARCEL(output.writeParcelable, metadata); SAFE_PARCEL(output.writeFloat, bgColorAlpha); SAFE_PARCEL(output.writeUint32, static_cast(bgColorDataspace)); @@ -151,9 +133,7 @@ status_t layer_state_t::write(Parcel& output) const SAFE_PARCEL(output.writeByte, frameRateCompatibility); SAFE_PARCEL(output.writeByte, changeFrameRateStrategy); SAFE_PARCEL(output.writeUint32, fixedTransformHint); - SAFE_PARCEL(output.writeUint64, frameNumber); SAFE_PARCEL(output.writeBool, autoRefresh); - SAFE_PARCEL(output.writeStrongBinder, IInterface::asBinder(releaseBufferListener)); SAFE_PARCEL(output.writeUint32, blurRegions.size()); for (auto region : blurRegions) { @@ -174,8 +154,8 @@ status_t layer_state_t::write(Parcel& output) const SAFE_PARCEL(output.write, destinationFrame); SAFE_PARCEL(output.writeBool, isTrustedOverlay); - SAFE_PARCEL(output.writeStrongBinder, releaseBufferEndpoint); SAFE_PARCEL(output.writeUint32, static_cast(dropInputMode)); + SAFE_PARCEL(bufferData.write, output); return NO_ERROR; } @@ -217,19 +197,6 @@ status_t layer_state_t::read(const Parcel& input) SAFE_PARCEL(input.readBool, &transformToDisplayInverse); SAFE_PARCEL(input.read, orientedDisplaySpaceRect); - bool tmpBool = false; - SAFE_PARCEL(input.readBool, &tmpBool); - if (tmpBool) { - buffer = new GraphicBuffer(); - SAFE_PARCEL(input.read, *buffer); - } - - SAFE_PARCEL(input.readBool, &tmpBool); - if (tmpBool) { - acquireFence = new Fence(); - SAFE_PARCEL(input.read, *acquireFence); - } - uint32_t tmpUint32 = 0; SAFE_PARCEL(input.readUint32, &tmpUint32); dataspace = static_cast(tmpUint32); @@ -237,6 +204,8 @@ status_t layer_state_t::read(const Parcel& input) SAFE_PARCEL(input.read, hdrMetadata); SAFE_PARCEL(input.read, surfaceDamageRegion); SAFE_PARCEL(input.readInt32, &api); + + bool tmpBool = false; SAFE_PARCEL(input.readBool, &tmpBool); if (tmpBool) { sidebandStream = NativeHandle::create(input.readNativeHandle(), true); @@ -245,10 +214,6 @@ status_t layer_state_t::read(const Parcel& input) SAFE_PARCEL(input.read, &colorTransform, 16 * sizeof(float)); SAFE_PARCEL(input.readFloat, &cornerRadius); SAFE_PARCEL(input.readUint32, &backgroundBlurRadius); - sp tmpBinder; - SAFE_PARCEL(input.readNullableStrongBinder, &tmpBinder); - cachedBuffer.token = tmpBinder; - SAFE_PARCEL(input.readUint64, &cachedBuffer.id); SAFE_PARCEL(input.readParcelable, &metadata); SAFE_PARCEL(input.readFloat, &bgColorAlpha); @@ -273,15 +238,8 @@ status_t layer_state_t::read(const Parcel& input) SAFE_PARCEL(input.readByte, &changeFrameRateStrategy); SAFE_PARCEL(input.readUint32, &tmpUint32); fixedTransformHint = static_cast(tmpUint32); - SAFE_PARCEL(input.readUint64, &frameNumber); SAFE_PARCEL(input.readBool, &autoRefresh); - tmpBinder = nullptr; - SAFE_PARCEL(input.readNullableStrongBinder, &tmpBinder); - if (tmpBinder) { - releaseBufferListener = checked_interface_cast(tmpBinder); - } - uint32_t numRegions = 0; SAFE_PARCEL(input.readUint32, &numRegions); blurRegions.clear(); @@ -305,11 +263,10 @@ status_t layer_state_t::read(const Parcel& input) SAFE_PARCEL(input.read, destinationFrame); SAFE_PARCEL(input.readBool, &isTrustedOverlay); - SAFE_PARCEL(input.readNullableStrongBinder, &releaseBufferEndpoint); - uint32_t mode; SAFE_PARCEL(input.readUint32, &mode); dropInputMode = static_cast(mode); + SAFE_PARCEL(bufferData.read, input); return NO_ERROR; } @@ -460,12 +417,7 @@ void layer_state_t::merge(const layer_state_t& other) { } if (other.what & eBufferChanged) { what |= eBufferChanged; - buffer = other.buffer; - releaseBufferEndpoint = other.releaseBufferEndpoint; - } - if (other.what & eAcquireFenceChanged) { - what |= eAcquireFenceChanged; - acquireFence = other.acquireFence; + bufferData = other.bufferData; } if (other.what & eDataspaceChanged) { what |= eDataspaceChanged; @@ -498,10 +450,6 @@ void layer_state_t::merge(const layer_state_t& other) { what |= eInputInfoChanged; windowInfoHandle = new WindowInfoHandle(*other.windowInfoHandle); } - if (other.what & eCachedBufferChanged) { - what |= eCachedBufferChanged; - cachedBuffer = other.cachedBuffer; - } if (other.what & eBackgroundColorChanged) { what |= eBackgroundColorChanged; color = other.color; @@ -530,10 +478,6 @@ void layer_state_t::merge(const layer_state_t& other) { what |= eFixedTransformHintChanged; fixedTransformHint = other.fixedTransformHint; } - if (other.what & eFrameNumberChanged) { - what |= eFrameNumberChanged; - frameNumber = other.frameNumber; - } if (other.what & eAutoRefreshChanged) { what |= eAutoRefreshChanged; autoRefresh = other.autoRefresh; @@ -542,13 +486,6 @@ void layer_state_t::merge(const layer_state_t& other) { what |= eTrustedOverlayChanged; isTrustedOverlay = other.isTrustedOverlay; } - if (other.what & eReleaseBufferListenerChanged) { - if (releaseBufferListener) { - ALOGW("Overriding releaseBufferListener"); - } - what |= eReleaseBufferListenerChanged; - releaseBufferListener = other.releaseBufferListener; - } if (other.what & eStretchChanged) { what |= eStretchChanged; stretchEffect = other.stretchEffect; @@ -576,11 +513,11 @@ void layer_state_t::merge(const layer_state_t& other) { } bool layer_state_t::hasBufferChanges() const { - return (what & layer_state_t::eBufferChanged) || (what & layer_state_t::eCachedBufferChanged); + return what & layer_state_t::eBufferChanged; } bool layer_state_t::hasValidBuffer() const { - return buffer || cachedBuffer.isValid(); + return bufferData.buffer || bufferData.cachedBuffer.isValid(); } status_t layer_state_t::matrix22_t::write(Parcel& output) const { @@ -741,4 +678,66 @@ status_t LayerCaptureArgs::read(const Parcel& input) { return NO_ERROR; } +status_t BufferData::write(Parcel& output) const { + SAFE_PARCEL(output.writeInt32, flags.get()); + + if (buffer) { + SAFE_PARCEL(output.writeBool, true); + SAFE_PARCEL(output.write, *buffer); + } else { + SAFE_PARCEL(output.writeBool, false); + } + + if (acquireFence) { + SAFE_PARCEL(output.writeBool, true); + SAFE_PARCEL(output.write, *acquireFence); + } else { + SAFE_PARCEL(output.writeBool, false); + } + + SAFE_PARCEL(output.writeUint64, frameNumber); + SAFE_PARCEL(output.writeStrongBinder, IInterface::asBinder(releaseBufferListener)); + SAFE_PARCEL(output.writeStrongBinder, releaseBufferEndpoint); + + SAFE_PARCEL(output.writeStrongBinder, cachedBuffer.token.promote()); + SAFE_PARCEL(output.writeUint64, cachedBuffer.id); + + return NO_ERROR; +} + +status_t BufferData::read(const Parcel& input) { + int32_t tmpInt32; + SAFE_PARCEL(input.readInt32, &tmpInt32); + flags = Flags(tmpInt32); + + bool tmpBool = false; + SAFE_PARCEL(input.readBool, &tmpBool); + if (tmpBool) { + buffer = new GraphicBuffer(); + SAFE_PARCEL(input.read, *buffer); + } + + SAFE_PARCEL(input.readBool, &tmpBool); + if (tmpBool) { + acquireFence = new Fence(); + SAFE_PARCEL(input.read, *acquireFence); + } + + SAFE_PARCEL(input.readUint64, &frameNumber); + + sp tmpBinder = nullptr; + SAFE_PARCEL(input.readNullableStrongBinder, &tmpBinder); + if (tmpBinder) { + releaseBufferListener = checked_interface_cast(tmpBinder); + } + SAFE_PARCEL(input.readNullableStrongBinder, &releaseBufferEndpoint); + + tmpBinder = nullptr; + SAFE_PARCEL(input.readNullableStrongBinder, &tmpBinder); + cachedBuffer.token = tmpBinder; + SAFE_PARCEL(input.readUint64, &cachedBuffer.id); + + return NO_ERROR; +} + }; // namespace android diff --git a/libs/gui/SurfaceComposerClient.cpp b/libs/gui/SurfaceComposerClient.cpp index bbd3cca6ce..aca59b6d3b 100644 --- a/libs/gui/SurfaceComposerClient.cpp +++ b/libs/gui/SurfaceComposerClient.cpp @@ -805,7 +805,7 @@ void SurfaceComposerClient::Transaction::cacheBuffers() { layer_state_t* s = &(mComposerStates[handle].state); if (!(s->what & layer_state_t::eBufferChanged)) { continue; - } else if (s->what & layer_state_t::eCachedBufferChanged) { + } else if (s->bufferData.flags.test(BufferData::BufferDataChange::cachedBufferChanged)) { // If eBufferChanged and eCachedBufferChanged are both trued then that means // we already cached the buffer in a previous call to cacheBuffers, perhaps // from writeToParcel on a Transaction that was merged in to this one. @@ -814,23 +814,22 @@ void SurfaceComposerClient::Transaction::cacheBuffers() { // Don't try to cache a null buffer. Sending null buffers is cheap so we shouldn't waste // time trying to cache them. - if (!s->buffer) { + if (!s->bufferData.buffer) { continue; } uint64_t cacheId = 0; - status_t ret = BufferCache::getInstance().getCacheId(s->buffer, &cacheId); + status_t ret = BufferCache::getInstance().getCacheId(s->bufferData.buffer, &cacheId); if (ret == NO_ERROR) { // Cache-hit. Strip the buffer and send only the id. - s->what &= ~static_cast(layer_state_t::eBufferChanged); - s->buffer = nullptr; + s->bufferData.buffer = nullptr; } else { // Cache-miss. Include the buffer and send the new cacheId. - cacheId = BufferCache::getInstance().cache(s->buffer); + cacheId = BufferCache::getInstance().cache(s->bufferData.buffer); } - s->what |= layer_state_t::eCachedBufferChanged; - s->cachedBuffer.token = BufferCache::getInstance().getToken(); - s->cachedBuffer.id = cacheId; + s->bufferData.flags |= BufferData::BufferDataChange::cachedBufferChanged; + s->bufferData.cachedBuffer.token = BufferCache::getInstance().getToken(); + s->bufferData.cachedBuffer.id = cacheId; // If we have more buffers than the size of the cache, we should stop caching so we don't // evict other buffers in this transaction @@ -1289,22 +1288,33 @@ SurfaceComposerClient::Transaction::setTransformToDisplayInverse(const sp& sc, const sp& buffer, const ReleaseCallbackId& id, - ReleaseBufferCallback callback) { + const sp& sc, const sp& buffer, + const std::optional>& fence, const std::optional& frameNumber, + const ReleaseCallbackId& id, ReleaseBufferCallback callback) { layer_state_t* s = getLayerState(sc); if (!s) { mStatus = BAD_INDEX; return *this; } removeReleaseBufferCallback(s); - s->what |= layer_state_t::eBufferChanged; - s->buffer = buffer; - s->releaseBufferEndpoint = IInterface::asBinder(TransactionCompletedListener::getIInstance()); + BufferData bufferData; + bufferData.buffer = buffer; + if (frameNumber) { + bufferData.frameNumber = *frameNumber; + bufferData.flags |= BufferData::BufferDataChange::frameNumberChanged; + } + if (fence) { + bufferData.acquireFence = *fence; + bufferData.flags |= BufferData::BufferDataChange::fenceChanged; + } + bufferData.releaseBufferEndpoint = + IInterface::asBinder(TransactionCompletedListener::getIInstance()); if (mIsAutoTimestamp) { mDesiredPresentTime = systemTime(); } - setReleaseBufferCallback(s, id, callback); - + setReleaseBufferCallback(&bufferData, id, callback); + s->what |= layer_state_t::eBufferChanged; + s->bufferData = bufferData; registerSurfaceControlForCallback(sc); mContainsBuffer = true; @@ -1312,51 +1322,33 @@ SurfaceComposerClient::Transaction& SurfaceComposerClient::Transaction::setBuffe } void SurfaceComposerClient::Transaction::removeReleaseBufferCallback(layer_state_t* s) { - if (!s->releaseBufferListener) { + if (!(s->what & layer_state_t::eBufferChanged)) { return; } - s->what &= ~static_cast(layer_state_t::eReleaseBufferListenerChanged); - s->releaseBufferListener = nullptr; auto listener = TransactionCompletedListener::getInstance(); - listener->removeReleaseBufferCallback(s->releaseCallbackId); - s->releaseCallbackId = ReleaseCallbackId::INVALID_ID; + listener->removeReleaseBufferCallback(s->bufferData.releaseCallbackId); } -void SurfaceComposerClient::Transaction::setReleaseBufferCallback(layer_state_t* s, +void SurfaceComposerClient::Transaction::setReleaseBufferCallback(BufferData* bufferData, const ReleaseCallbackId& id, ReleaseBufferCallback callback) { if (!callback) { return; } - if (!s->buffer) { + if (!bufferData->buffer) { ALOGW("Transaction::setReleaseBufferCallback" "ignored trying to set a callback on a null buffer."); return; } - s->what |= layer_state_t::eReleaseBufferListenerChanged; - s->releaseBufferListener = TransactionCompletedListener::getIInstance(); - s->releaseCallbackId = id; + bufferData->releaseBufferListener = TransactionCompletedListener::getIInstance(); + bufferData->releaseCallbackId = id; auto listener = TransactionCompletedListener::getInstance(); listener->setReleaseBufferCallback(id, callback); } -SurfaceComposerClient::Transaction& SurfaceComposerClient::Transaction::setAcquireFence( - const sp& sc, const sp& fence) { - layer_state_t* s = getLayerState(sc); - if (!s) { - mStatus = BAD_INDEX; - return *this; - } - s->what |= layer_state_t::eAcquireFenceChanged; - s->acquireFence = fence; - - registerSurfaceControlForCallback(sc); - return *this; -} - SurfaceComposerClient::Transaction& SurfaceComposerClient::Transaction::setDataspace( const sp& sc, ui::Dataspace dataspace) { layer_state_t* s = getLayerState(sc); @@ -1506,20 +1498,6 @@ SurfaceComposerClient::Transaction& SurfaceComposerClient::Transaction::notifyPr return *this; } -SurfaceComposerClient::Transaction& SurfaceComposerClient::Transaction::setFrameNumber( - const sp& sc, uint64_t frameNumber) { - layer_state_t* s = getLayerState(sc); - if (!s) { - mStatus = BAD_INDEX; - return *this; - } - - s->what |= layer_state_t::eFrameNumberChanged; - s->frameNumber = frameNumber; - - return *this; -} - SurfaceComposerClient::Transaction& SurfaceComposerClient::Transaction::setInputWindowInfo( const sp& sc, const WindowInfo& info) { layer_state_t* s = getLayerState(sc); diff --git a/libs/gui/include/gui/LayerState.h b/libs/gui/include/gui/LayerState.h index b27102bcce..1f5d289a43 100644 --- a/libs/gui/include/gui/LayerState.h +++ b/libs/gui/include/gui/LayerState.h @@ -58,6 +58,44 @@ struct client_cache_t { bool isValid() const { return token != nullptr; } }; +struct BufferData { + enum class BufferDataChange : uint32_t { + fenceChanged = 0x01, + frameNumberChanged = 0x02, + cachedBufferChanged = 0x04, + }; + + sp buffer; + sp acquireFence; + + // Used by BlastBufferQueue to forward the framenumber generated by the + // graphics producer. + uint64_t frameNumber = 0; + + // Listens to when the buffer is safe to be released. This is used for blast + // layers only. The callback includes a release fence as well as the graphic + // buffer id to identify the buffer. + sp releaseBufferListener = nullptr; + + // Keeps track of the release callback id associated with the listener. This + // is not sent to the server since the id can be reconstructed there. This + // is used to remove the old callback from the client process map if it is + // overwritten by another setBuffer call. + ReleaseCallbackId releaseCallbackId = ReleaseCallbackId::INVALID_ID; + + // Stores which endpoint the release information should be sent to. We don't want to send the + // releaseCallbackId and release fence to all listeners so we store which listener the setBuffer + // was called with. + sp releaseBufferEndpoint; + + Flags flags; + + client_cache_t cachedBuffer; + + status_t write(Parcel& output) const; + status_t read(const Parcel& input); +}; + /* * Used to communicate layer information between SurfaceFlinger and its clients. */ @@ -82,7 +120,7 @@ struct layer_state_t { eTransparentRegionChanged = 0x00000020, eFlagsChanged = 0x00000040, eLayerStackChanged = 0x00000080, - eReleaseBufferListenerChanged = 0x00000400, + /* unused 0x00000400, */ eShadowRadiusChanged = 0x00000800, eLayerCreated = 0x00001000, eBufferCropChanged = 0x00002000, @@ -94,7 +132,7 @@ struct layer_state_t { eTransformToDisplayInverseChanged = 0x00080000, eCropChanged = 0x00100000, eBufferChanged = 0x00200000, - eAcquireFenceChanged = 0x00400000, + /* unused 0x00400000, */ eDataspaceChanged = 0x00800000, eHdrMetadataChanged = 0x01000000, eSurfaceDamageRegionChanged = 0x02000000, @@ -105,7 +143,7 @@ struct layer_state_t { eInputInfoChanged = 0x40000000, eCornerRadiusChanged = 0x80000000, eDestinationFrameChanged = 0x1'00000000, - eCachedBufferChanged = 0x2'00000000, + /* unused = 0x2'00000000, */ eBackgroundColorChanged = 0x4'00000000, eMetadataChanged = 0x8'00000000, eColorSpaceAgnosticChanged = 0x10'00000000, @@ -114,7 +152,7 @@ struct layer_state_t { eBackgroundBlurRadiusChanged = 0x80'00000000, eProducerDisconnect = 0x100'00000000, eFixedTransformHintChanged = 0x200'00000000, - eFrameNumberChanged = 0x400'00000000, + /* unused 0x400'00000000, */ eBlurRegionsChanged = 0x800'00000000, eAutoRefreshChanged = 0x1000'00000000, eStretchChanged = 0x2000'00000000, @@ -169,8 +207,7 @@ struct layer_state_t { bool transformToDisplayInverse; Rect crop; Rect orientedDisplaySpaceRect; - sp buffer; - sp acquireFence; + BufferData bufferData; ui::Dataspace dataspace; HdrMetadata hdrMetadata; Region surfaceDamageRegion; @@ -181,8 +218,6 @@ struct layer_state_t { sp windowInfoHandle = new gui::WindowInfoHandle(); - client_cache_t cachedBuffer; - LayerMetadata metadata; // The following refer to the alpha, and dataspace, respectively of @@ -216,10 +251,6 @@ struct layer_state_t { // otherwise the value will be a valid ui::Rotation. ui::Transform::RotationFlags fixedTransformHint; - // Used by BlastBufferQueue to forward the framenumber generated by the - // graphics producer. - uint64_t frameNumber; - // Indicates that the consumer should acquire the next frame as soon as it // can and not wait for a frame to become available. This is only relevant // in shared buffer mode. @@ -235,22 +266,6 @@ struct layer_state_t { Rect bufferCrop; Rect destinationFrame; - // Listens to when the buffer is safe to be released. This is used for blast - // layers only. The callback includes a release fence as well as the graphic - // buffer id to identify the buffer. - sp releaseBufferListener; - - // Keeps track of the release callback id associated with the listener. This - // is not sent to the server since the id can be reconstructed there. This - // is used to remove the old callback from the client process map if it is - // overwritten by another setBuffer call. - ReleaseCallbackId releaseCallbackId; - - // Stores which endpoint the release information should be sent to. We don't want to send the - // releaseCallbackId and release fence to all listeners so we store which listener the setBuffer - // was called with. - sp releaseBufferEndpoint; - // Force inputflinger to drop all input events for the layer and its children. gui::DropInputMode dropInputMode; }; diff --git a/libs/gui/include/gui/SurfaceComposerClient.h b/libs/gui/include/gui/SurfaceComposerClient.h index 403ca0a166..82249a32f9 100644 --- a/libs/gui/include/gui/SurfaceComposerClient.h +++ b/libs/gui/include/gui/SurfaceComposerClient.h @@ -399,8 +399,7 @@ public: void cacheBuffers(); void registerSurfaceControlForCallback(const sp& sc); - void setReleaseBufferCallback(layer_state_t*, const ReleaseCallbackId&, - ReleaseBufferCallback); + void setReleaseBufferCallback(BufferData*, const ReleaseCallbackId&, ReleaseBufferCallback); void removeReleaseBufferCallback(layer_state_t*); public: @@ -473,10 +472,10 @@ public: Transaction& setTransformToDisplayInverse(const sp& sc, bool transformToDisplayInverse); Transaction& setBuffer(const sp& sc, const sp& buffer, + const std::optional>& fence = std::nullopt, + const std::optional& frameNumber = std::nullopt, const ReleaseCallbackId& id = ReleaseCallbackId::INVALID_ID, ReleaseBufferCallback callback = nullptr); - Transaction& setCachedBuffer(const sp& sc, int32_t bufferId); - Transaction& setAcquireFence(const sp& sc, const sp& fence); Transaction& setDataspace(const sp& sc, ui::Dataspace dataspace); Transaction& setHdrMetadata(const sp& sc, const HdrMetadata& hdrMetadata); Transaction& setSurfaceDamageRegion(const sp& sc, @@ -501,8 +500,6 @@ public: // ONLY FOR BLAST ADAPTER Transaction& notifyProducerDisconnect(const sp& sc); - // Set the framenumber generated by the graphics producer to mimic BufferQueue behaviour. - Transaction& setFrameNumber(const sp& sc, uint64_t frameNumber); Transaction& setInputWindowInfo(const sp& sc, const gui::WindowInfo& info); Transaction& setFocusedWindow(const gui::FocusRequest& request); diff --git a/services/surfaceflinger/BufferLayer.cpp b/services/surfaceflinger/BufferLayer.cpp index d805294b07..ef05fe2138 100644 --- a/services/surfaceflinger/BufferLayer.cpp +++ b/services/surfaceflinger/BufferLayer.cpp @@ -620,14 +620,6 @@ bool BufferLayer::needsFilteringForScreenshots(const DisplayDevice* display, return sourceCrop.getHeight() != frameHeight || sourceCrop.getWidth() != frameWidth; } -uint64_t BufferLayer::getHeadFrameNumber(nsecs_t expectedPresentTime) const { - if (hasFrameUpdate()) { - return getFrameNumber(expectedPresentTime); - } else { - return mCurrentFrameNumber; - } -} - Rect BufferLayer::getBufferSize(const State& s) const { // If we have a sideband stream, or we are scaling the buffer then return the layer size since // we cannot determine the buffer size. diff --git a/services/surfaceflinger/BufferLayer.h b/services/surfaceflinger/BufferLayer.h index 760c8b9f3c..2da73f81e5 100644 --- a/services/surfaceflinger/BufferLayer.h +++ b/services/surfaceflinger/BufferLayer.h @@ -164,8 +164,6 @@ protected: void updateCloneBufferInfo() override; uint64_t mPreviousFrameNumber = 0; - uint64_t getHeadFrameNumber(nsecs_t expectedPresentTime) const override; - void setTransformHint(ui::Transform::RotationFlags displayTransformHint) override; // Transform hint provided to the producer. This must be accessed holding @@ -189,8 +187,6 @@ protected: private: virtual bool fenceHasSignaled() const = 0; virtual bool framePresentTimeIsCurrent(nsecs_t expectedPresentTime) const = 0; - virtual uint64_t getFrameNumber(nsecs_t expectedPresentTime) const = 0; - // Latch sideband stream and returns true if the dirty region should be updated. virtual bool latchSidebandStream(bool& recomputeVisibleRegions) = 0; diff --git a/services/surfaceflinger/BufferQueueLayer.cpp b/services/surfaceflinger/BufferQueueLayer.cpp index d51db88662..8bbe43865a 100644 --- a/services/surfaceflinger/BufferQueueLayer.cpp +++ b/services/surfaceflinger/BufferQueueLayer.cpp @@ -161,39 +161,6 @@ bool BufferQueueLayer::framePresentTimeIsCurrent(nsecs_t expectedPresentTime) co return mQueueItems[0].item.mTimestamp <= expectedPresentTime; } -uint64_t BufferQueueLayer::getFrameNumber(nsecs_t expectedPresentTime) const { - Mutex::Autolock lock(mQueueItemLock); - uint64_t frameNumber = mQueueItems[0].item.mFrameNumber; - - // The head of the queue will be dropped if there are signaled and timely frames behind it - if (isRemovedFromCurrentState()) { - expectedPresentTime = 0; - } - - for (size_t i = 1; i < mQueueItems.size(); i++) { - const bool fenceSignaled = - mQueueItems[i].item.mFenceTime->getSignalTime() != Fence::SIGNAL_TIME_PENDING; - if (!fenceSignaled) { - break; - } - - // We don't drop frames without explicit timestamps - if (mQueueItems[i].item.mIsAutoTimestamp) { - break; - } - - const nsecs_t desiredPresent = mQueueItems[i].item.mTimestamp; - if (desiredPresent < expectedPresentTime - BufferQueueConsumer::MAX_REASONABLE_NSEC || - desiredPresent > expectedPresentTime) { - break; - } - - frameNumber = mQueueItems[i].item.mFrameNumber; - } - - return frameNumber; -} - bool BufferQueueLayer::latchSidebandStream(bool& recomputeVisibleRegions) { // We need to update the sideband stream if the layer has both a buffer and a sideband stream. editCompositionState()->sidebandStreamHasFrame = hasFrameUpdate() && mSidebandStream.get(); diff --git a/services/surfaceflinger/BufferQueueLayer.h b/services/surfaceflinger/BufferQueueLayer.h index b3b7948935..be2902bba6 100644 --- a/services/surfaceflinger/BufferQueueLayer.h +++ b/services/surfaceflinger/BufferQueueLayer.h @@ -89,7 +89,6 @@ protected: }; private: - uint64_t getFrameNumber(nsecs_t expectedPresentTime) const override; bool latchSidebandStream(bool& recomputeVisibleRegions) override; void setTransformHint(ui::Transform::RotationFlags displayTransformHint) override; diff --git a/services/surfaceflinger/BufferStateLayer.cpp b/services/surfaceflinger/BufferStateLayer.cpp index 7466c0638c..82e5d4633c 100644 --- a/services/surfaceflinger/BufferStateLayer.cpp +++ b/services/surfaceflinger/BufferStateLayer.cpp @@ -406,15 +406,55 @@ bool BufferStateLayer::addFrameEvent(const sp& acquireFence, nsecs_t post return true; } -bool BufferStateLayer::setBuffer(const std::shared_ptr& buffer, - const sp& acquireFence, nsecs_t postTime, +std::shared_ptr BufferStateLayer::getBufferFromBufferData( + const BufferData& bufferData) { + bool cacheIdChanged = bufferData.flags.test(BufferData::BufferDataChange::cachedBufferChanged); + bool bufferSizeExceedsLimit = false; + std::shared_ptr buffer = nullptr; + if (cacheIdChanged && bufferData.buffer != nullptr) { + bufferSizeExceedsLimit = + mFlinger->exceedsMaxRenderTargetSize(bufferData.buffer->getWidth(), + bufferData.buffer->getHeight()); + if (!bufferSizeExceedsLimit) { + ClientCache::getInstance().add(bufferData.cachedBuffer, bufferData.buffer); + buffer = ClientCache::getInstance().get(bufferData.cachedBuffer); + } + } else if (cacheIdChanged) { + buffer = ClientCache::getInstance().get(bufferData.cachedBuffer); + } else if (bufferData.buffer != nullptr) { + bufferSizeExceedsLimit = + mFlinger->exceedsMaxRenderTargetSize(bufferData.buffer->getWidth(), + bufferData.buffer->getHeight()); + if (!bufferSizeExceedsLimit) { + buffer = std::make_shared< + renderengine::ExternalTexture>(bufferData.buffer, mFlinger->getRenderEngine(), + renderengine::ExternalTexture::Usage::READABLE); + } + } + ALOGE_IF(bufferSizeExceedsLimit, + "Attempted to create an ExternalTexture for layer %s that exceeds render target size " + "limit.", + getDebugName()); + return buffer; +} + +bool BufferStateLayer::setBuffer(const BufferData& bufferData, nsecs_t postTime, nsecs_t desiredPresentTime, bool isAutoTimestamp, - const client_cache_t& clientCacheId, uint64_t frameNumber, - std::optional dequeueTime, const FrameTimelineInfo& info, - const sp& releaseBufferListener, - const sp& releaseBufferEndpoint) { + std::optional dequeueTime, + const FrameTimelineInfo& info) { ATRACE_CALL(); + const std::shared_ptr& buffer = + getBufferFromBufferData(bufferData); + if (!buffer) { + return false; + } + + const bool frameNumberChanged = + bufferData.flags.test(BufferData::BufferDataChange::frameNumberChanged); + const uint64_t frameNumber = + frameNumberChanged ? bufferData.frameNumber : mDrawingState.frameNumber + 1; + if (mDrawingState.buffer) { mReleasePreviousBuffer = true; if (mDrawingState.buffer != mBufferInfo.mBuffer || @@ -438,9 +478,17 @@ bool BufferStateLayer::setBuffer(const std::shared_ptr(mDrawingState.acquireFence); + // The acquire fences of BufferStateLayers have already signaled before they are set + mCallbackHandleAcquireTime = mDrawingState.acquireFenceTime->getSignalTime(); + mDrawingState.modified = true; setTransactionFlags(eTransactionNeeded); @@ -462,7 +510,7 @@ bool BufferStateLayer::setBuffer(const std::shared_ptrmScheduler->recordLayerHistory(this, presentTime, LayerHistory::LayerUpdateType::Buffer); - addFrameEvent(acquireFence, postTime, isAutoTimestamp ? 0 : desiredPresentTime); + addFrameEvent(mDrawingState.acquireFence, postTime, isAutoTimestamp ? 0 : desiredPresentTime); setFrameTimelineVsyncForBufferTransaction(info, postTime); @@ -477,20 +525,7 @@ bool BufferStateLayer::setBuffer(const std::shared_ptrgetBuffer()->getWidth(); mDrawingState.height = mDrawingState.buffer->getBuffer()->getHeight(); - mDrawingState.releaseBufferEndpoint = releaseBufferEndpoint; - - return true; -} - -bool BufferStateLayer::setAcquireFence(const sp& fence) { - mDrawingState.acquireFence = fence; - mDrawingState.acquireFenceTime = std::make_unique(fence); - - // The acquire fences of BufferStateLayers have already signaled before they are set - mCallbackHandleAcquireTime = mDrawingState.acquireFenceTime->getSignalTime(); - - mDrawingState.modified = true; - setTransactionFlags(eTransactionNeeded); + mDrawingState.releaseBufferEndpoint = bufferData.releaseBufferEndpoint; return true; } @@ -659,36 +694,6 @@ bool BufferStateLayer::onPreComposition(nsecs_t refreshStartTime) { return BufferLayer::onPreComposition(refreshStartTime); } -uint64_t BufferStateLayer::getFrameNumber(nsecs_t /*expectedPresentTime*/) const { - return mDrawingState.frameNumber; -} - -/** - * This is the frameNumber used for deferred transaction signalling. We need to use this because - * of cases where we defer a transaction for a surface to itself. In the BLAST world this - * may not make a huge amount of sense (Why not just merge the Buffer transaction with the - * deferred transaction?) but this is an important legacy use case, for example moving - * a window at the same time it draws makes use of this kind of technique. So anyway - * imagine we have something like this: - * - * Transaction { // containing - * Buffer -> frameNumber = 2 - * DeferTransactionUntil -> frameNumber = 2 - * Random other stuff - * } - * Now imagine mFrameNumber returned mDrawingState.frameNumber (or mCurrentFrameNumber). - * Prior to doTransaction SurfaceFlinger will call notifyAvailableFrames, but because we - * haven't swapped mDrawingState to mDrawingState yet we will think the sync point - * is not ready. So we will return false from applyPendingState and not swap - * current state to drawing state. But because we don't swap current state - * to drawing state the number will never update and we will be stuck. This way - * we can see we need to return the frame number for the buffer we are about - * to apply. - */ -uint64_t BufferStateLayer::getHeadFrameNumber(nsecs_t /* expectedPresentTime */) const { - return mDrawingState.frameNumber; -} - void BufferStateLayer::setAutoRefresh(bool autoRefresh) { if (!mAutoRefresh.exchange(autoRefresh)) { mFlinger->signalLayerUpdate(); diff --git a/services/surfaceflinger/BufferStateLayer.h b/services/surfaceflinger/BufferStateLayer.h index 124e91ac61..87b68ea71b 100644 --- a/services/surfaceflinger/BufferStateLayer.h +++ b/services/surfaceflinger/BufferStateLayer.h @@ -55,13 +55,9 @@ public: bool setTransform(uint32_t transform) override; bool setTransformToDisplayInverse(bool transformToDisplayInverse) override; bool setCrop(const Rect& crop) override; - bool setBuffer(const std::shared_ptr& buffer, - const sp& acquireFence, nsecs_t postTime, nsecs_t desiredPresentTime, - bool isAutoTimestamp, const client_cache_t& clientCacheId, uint64_t frameNumber, - std::optional dequeueTime, const FrameTimelineInfo& info, - const sp& transactionListener, - const sp& releaseBufferEndpoint) override; - bool setAcquireFence(const sp& fence) override; + bool setBuffer(const BufferData& bufferData, nsecs_t postTime, nsecs_t desiredPresentTime, + bool isAutoTimestamp, std::optional dequeueTime, + const FrameTimelineInfo& info) override; bool setDataspace(ui::Dataspace dataspace) override; bool setHdrMetadata(const HdrMetadata& hdrMetadata) override; bool setSurfaceDamageRegion(const Region& surfaceDamage) override; @@ -105,7 +101,6 @@ public: protected: void gatherBufferInfo() override; - uint64_t getHeadFrameNumber(nsecs_t expectedPresentTime) const; void onSurfaceFrameCreated(const std::shared_ptr& surfaceFrame); ui::Transform getInputTransform() const override; Rect getInputBounds() const override; @@ -122,8 +117,6 @@ private: status_t addReleaseFence(const sp& ch, const sp& releaseFence); - uint64_t getFrameNumber(nsecs_t expectedPresentTime) const override; - bool latchSidebandStream(bool& recomputeVisibleRegions) override; bool hasFrameUpdate() const override; @@ -143,6 +136,9 @@ private: bool bufferNeedsFiltering() const override; + std::shared_ptr getBufferFromBufferData( + const BufferData& bufferData); + sp mPreviousReleaseFence; ReleaseCallbackId mPreviousReleaseCallbackId = ReleaseCallbackId::INVALID_ID; uint64_t mPreviousReleasedFrameNumber = 0; diff --git a/services/surfaceflinger/Layer.h b/services/surfaceflinger/Layer.h index 8c281d53e4..f29ebde66b 100644 --- a/services/surfaceflinger/Layer.h +++ b/services/surfaceflinger/Layer.h @@ -416,17 +416,11 @@ public: // Used only to set BufferStateLayer state virtual bool setTransform(uint32_t /*transform*/) { return false; }; virtual bool setTransformToDisplayInverse(bool /*transformToDisplayInverse*/) { return false; }; - virtual bool setBuffer(const std::shared_ptr& /*buffer*/, - const sp& /*acquireFence*/, nsecs_t /*postTime*/, - nsecs_t /*desiredPresentTime*/, bool /*isAutoTimestamp*/, - const client_cache_t& /*clientCacheId*/, uint64_t /* frameNumber */, - std::optional /* dequeueTime */, - const FrameTimelineInfo& /*info*/, - const sp& /* releaseBufferListener */, - const sp& /* releaseBufferEndpoint */) { + virtual bool setBuffer(const BufferData&, nsecs_t /*postTime*/, nsecs_t /*desiredPresentTime*/, + bool /*isAutoTimestamp*/, std::optional /* dequeueTime */, + const FrameTimelineInfo& /*info*/) { return false; }; - virtual bool setAcquireFence(const sp& /*fence*/) { return false; }; virtual bool setDataspace(ui::Dataspace /*dataspace*/) { return false; }; virtual bool setHdrMetadata(const HdrMetadata& /*hdrMetadata*/) { return false; }; virtual bool setSurfaceDamageRegion(const Region& /*surfaceDamage*/) { return false; }; @@ -527,8 +521,6 @@ public: virtual bool shouldPresentNow(nsecs_t /*expectedPresentTime*/) const { return false; } - virtual uint64_t getHeadFrameNumber(nsecs_t /* expectedPresentTime */) const { return 0; } - /* * called after composition. * returns true if the layer latched a new buffer this frame. diff --git a/services/surfaceflinger/SurfaceFlinger.cpp b/services/surfaceflinger/SurfaceFlinger.cpp index 88715e36aa..da3d22e318 100644 --- a/services/surfaceflinger/SurfaceFlinger.cpp +++ b/services/surfaceflinger/SurfaceFlinger.cpp @@ -3570,9 +3570,10 @@ bool SurfaceFlinger::transactionIsReadyToBeApplied( for (const ComposerState& state : states) { const layer_state_t& s = state.state; - const bool acquireFenceChanged = (s.what & layer_state_t::eAcquireFenceChanged); - if (acquireFenceChanged && s.acquireFence && !enableLatchUnsignaled && - s.acquireFence->getStatus() == Fence::Status::Unsignaled) { + const bool acquireFenceChanged = + s.bufferData.flags.test(BufferData::BufferDataChange::fenceChanged); + if (acquireFenceChanged && s.bufferData.acquireFence && !enableLatchUnsignaled && + s.bufferData.acquireFence->getStatus() == Fence::Status::Unsignaled) { ATRACE_NAME("fence unsignaled"); return false; } @@ -4069,9 +4070,6 @@ uint32_t SurfaceFlinger::setClientStateLocked( if (what & layer_state_t::eCropChanged) { if (layer->setCrop(s.crop)) flags |= eTraversalNeeded; } - if (what & layer_state_t::eAcquireFenceChanged) { - if (layer->setAcquireFence(s.acquireFence)) flags |= eTraversalNeeded; - } if (what & layer_state_t::eDataspaceChanged) { if (layer->setDataspace(s.dataspace)) flags |= eTraversalNeeded; } @@ -4198,43 +4196,11 @@ uint32_t SurfaceFlinger::setClientStateLocked( callbackHandles.emplace_back(new CallbackHandle(listener, callbackIds, s.surface)); } } - bool bufferChanged = what & layer_state_t::eBufferChanged; - bool cacheIdChanged = what & layer_state_t::eCachedBufferChanged; - bool bufferSizeExceedsLimit = false; - std::shared_ptr buffer; - if (bufferChanged && cacheIdChanged && s.buffer != nullptr) { - bufferSizeExceedsLimit = - exceedsMaxRenderTargetSize(s.buffer->getWidth(), s.buffer->getHeight()); - if (!bufferSizeExceedsLimit) { - ClientCache::getInstance().add(s.cachedBuffer, s.buffer); - buffer = ClientCache::getInstance().get(s.cachedBuffer); - } - } else if (cacheIdChanged) { - buffer = ClientCache::getInstance().get(s.cachedBuffer); - } else if (bufferChanged && s.buffer != nullptr) { - bufferSizeExceedsLimit = - exceedsMaxRenderTargetSize(s.buffer->getWidth(), s.buffer->getHeight()); - if (!bufferSizeExceedsLimit) { - buffer = std::make_shared< - renderengine::ExternalTexture>(s.buffer, getRenderEngine(), - renderengine::ExternalTexture::Usage::READABLE); - } - } - ALOGE_IF(bufferSizeExceedsLimit, - "Attempted to create an ExternalTexture for layer %s that exceeds render target size " - "limit.", - layer->getDebugName()); - if (buffer) { - const bool frameNumberChanged = what & layer_state_t::eFrameNumberChanged; - const uint64_t frameNumber = frameNumberChanged - ? s.frameNumber - : layer->getHeadFrameNumber(-1 /* expectedPresentTime */) + 1; - - if (layer->setBuffer(buffer, s.acquireFence, postTime, desiredPresentTime, isAutoTimestamp, - s.cachedBuffer, frameNumber, dequeueBufferTimestamp, frameTimelineInfo, - s.releaseBufferListener, s.releaseBufferEndpoint)) { - flags |= eTraversalNeeded; - } + + if (what & layer_state_t::eBufferChanged && + layer->setBuffer(s.bufferData, postTime, desiredPresentTime, isAutoTimestamp, + dequeueBufferTimestamp, frameTimelineInfo)) { + flags |= eTraversalNeeded; } else if (frameTimelineInfo.vsyncId != FrameTimelineInfo::INVALID_VSYNC_ID) { layer->setFrameTimelineVsyncForBufferlessTransaction(frameTimelineInfo, postTime); } diff --git a/services/surfaceflinger/SurfaceFlinger.h b/services/surfaceflinger/SurfaceFlinger.h index 141d7ac34f..5ef3fffece 100644 --- a/services/surfaceflinger/SurfaceFlinger.h +++ b/services/surfaceflinger/SurfaceFlinger.h @@ -363,6 +363,10 @@ protected: return static_cast(findDisplay(p)); } + bool exceedsMaxRenderTargetSize(uint32_t width, uint32_t height) const { + return width > mMaxRenderTargetSize || height > mMaxRenderTargetSize; + } + private: friend class BufferLayer; friend class BufferQueueLayer; @@ -939,10 +943,6 @@ private: void readPersistentProperties(); - bool exceedsMaxRenderTargetSize(uint32_t width, uint32_t height) const { - return width > mMaxRenderTargetSize || height > mMaxRenderTargetSize; - } - uint32_t getMaxAcquiredBufferCountForCurrentRefreshRate(uid_t uid) const; /* diff --git a/services/surfaceflinger/tests/IPC_test.cpp b/services/surfaceflinger/tests/IPC_test.cpp index 8d7e175cec..94e1e0c95c 100644 --- a/services/surfaceflinger/tests/IPC_test.cpp +++ b/services/surfaceflinger/tests/IPC_test.cpp @@ -161,8 +161,7 @@ public: Color::RED); transaction->setLayerStack(mSurfaceControl, ui::DEFAULT_LAYER_STACK) .setLayer(mSurfaceControl, std::numeric_limits::max()) - .setBuffer(mSurfaceControl, gb) - .setAcquireFence(mSurfaceControl, fence) + .setBuffer(mSurfaceControl, gb, fence) .show(mSurfaceControl) .addTransactionCompletedCallback(mCallbackHelper.function, mCallbackHelper.getContext()); @@ -312,8 +311,7 @@ TEST_F(IPCTest, MergeBasic) { Transaction transaction; transaction.setLayerStack(sc, ui::DEFAULT_LAYER_STACK) .setLayer(sc, std::numeric_limits::max() - 1) - .setBuffer(sc, gb) - .setAcquireFence(sc, fence) + .setBuffer(sc, gb, fence) .show(sc) .addTransactionCompletedCallback(helper1.function, helper1.getContext()); diff --git a/services/surfaceflinger/tests/LayerCallback_test.cpp b/services/surfaceflinger/tests/LayerCallback_test.cpp index 965aac301d..e8759e503b 100644 --- a/services/surfaceflinger/tests/LayerCallback_test.cpp +++ b/services/surfaceflinger/tests/LayerCallback_test.cpp @@ -66,8 +66,7 @@ public: return err; } - transaction.setBuffer(layer, buffer); - transaction.setAcquireFence(layer, fence); + transaction.setBuffer(layer, buffer, fence); } if (setBackgroundColor) { diff --git a/services/surfaceflinger/tests/LayerRenderTypeTransaction_test.cpp b/services/surfaceflinger/tests/LayerRenderTypeTransaction_test.cpp index c8eeac66e9..0e2bc3df0e 100644 --- a/services/surfaceflinger/tests/LayerRenderTypeTransaction_test.cpp +++ b/services/surfaceflinger/tests/LayerRenderTypeTransaction_test.cpp @@ -1353,7 +1353,7 @@ TEST_P(LayerRenderTypeTransactionTest, DISABLED_SetFenceBasic_BufferState) { return; } - Transaction().setBuffer(layer, buffer).setAcquireFence(layer, fence).apply(); + Transaction().setBuffer(layer, buffer, fence).apply(); status_t status = fence->wait(1000); ASSERT_NE(static_cast(Fence::Status::Unsignaled), status); @@ -1375,7 +1375,7 @@ TEST_P(LayerRenderTypeTransactionTest, SetFenceNull_BufferState) { sp fence = Fence::NO_FENCE; - Transaction().setBuffer(layer, buffer).setAcquireFence(layer, fence).apply(); + Transaction().setBuffer(layer, buffer, fence).apply(); auto shot = getScreenCapture(); shot->expectColor(Rect(0, 0, 32, 32), Color::RED); diff --git a/services/surfaceflinger/tests/ReleaseBufferCallback_test.cpp b/services/surfaceflinger/tests/ReleaseBufferCallback_test.cpp index c4d42fad36..3847a51b7c 100644 --- a/services/surfaceflinger/tests/ReleaseBufferCallback_test.cpp +++ b/services/surfaceflinger/tests/ReleaseBufferCallback_test.cpp @@ -85,9 +85,7 @@ public: sp fence, CallbackHelper& callback, const ReleaseCallbackId& id, ReleaseBufferCallbackHelper& releaseCallback) { Transaction t; - t.setFrameNumber(layer, id.framenumber); - t.setBuffer(layer, buffer, id, releaseCallback.getCallback()); - t.setAcquireFence(layer, fence); + t.setBuffer(layer, buffer, fence, id.framenumber, id, releaseCallback.getCallback()); t.addTransactionCompletedCallback(callback.function, callback.getContext()); t.apply(); } @@ -302,8 +300,8 @@ TEST_F(ReleaseBufferCallbackTest, DISABLED_FrameDropping) { nsecs_t time = systemTime() + std::chrono::nanoseconds(100ms).count(); Transaction t; - t.setBuffer(layer, firstBuffer, firstBufferCallbackId, releaseCallback->getCallback()); - t.setAcquireFence(layer, Fence::NO_FENCE); + t.setBuffer(layer, firstBuffer, std::nullopt, std::nullopt, firstBufferCallbackId, + releaseCallback->getCallback()); t.addTransactionCompletedCallback(transactionCallback.function, transactionCallback.getContext()); t.setDesiredPresentTime(time); @@ -318,8 +316,8 @@ TEST_F(ReleaseBufferCallbackTest, DISABLED_FrameDropping) { // Dropping frames in transaction queue emits a callback sp secondBuffer = getBuffer(); ReleaseCallbackId secondBufferCallbackId(secondBuffer->getId(), generateFrameNumber()); - t.setBuffer(layer, secondBuffer, secondBufferCallbackId, releaseCallback->getCallback()); - t.setAcquireFence(layer, Fence::NO_FENCE); + t.setBuffer(layer, secondBuffer, std::nullopt, std::nullopt, secondBufferCallbackId, + releaseCallback->getCallback()); t.addTransactionCompletedCallback(transactionCallback.function, transactionCallback.getContext()); t.setDesiredPresentTime(time); @@ -361,10 +359,8 @@ TEST_F(ReleaseBufferCallbackTest, DISABLED_Merge_Different_Processes) { ReleaseCallbackId secondBufferCallbackId(secondBuffer->getId(), generateFrameNumber()); Transaction transaction1; - transaction1.setFrameNumber(layer, secondBufferCallbackId.framenumber); - transaction1.setBuffer(layer, secondBuffer, secondBufferCallbackId, - releaseCallback->getCallback()); - transaction1.setAcquireFence(layer, Fence::NO_FENCE); + transaction1.setBuffer(layer, secondBuffer, std::nullopt, secondBufferCallbackId.framenumber, + secondBufferCallbackId, releaseCallback->getCallback()); transaction1.addTransactionCompletedCallback(callback1.function, callback1.getContext()); // Set a different TransactionCompletedListener to mimic a second process diff --git a/services/surfaceflinger/tests/unittests/TransactionFrameTracerTest.cpp b/services/surfaceflinger/tests/unittests/TransactionFrameTracerTest.cpp index a749ece835..bd6a7805ec 100644 --- a/services/surfaceflinger/tests/unittests/TransactionFrameTracerTest.cpp +++ b/services/surfaceflinger/tests/unittests/TransactionFrameTracerTest.cpp @@ -46,6 +46,7 @@ public: ALOGD("**** Setting up for %s.%s\n", test_info->test_case_name(), test_info->name()); setupScheduler(); mFlinger.setupComposer(std::make_unique()); + mFlinger.setupRenderEngine(std::unique_ptr(mRenderEngine)); } ~TransactionFrameTracerTest() { @@ -92,21 +93,17 @@ public: } TestableSurfaceFlinger mFlinger; - renderengine::mock::RenderEngine mRenderEngine; + renderengine::mock::RenderEngine* mRenderEngine = new renderengine::mock::RenderEngine(); FenceToFenceTimeMap fenceFactory; - client_cache_t mClientCache; void BLASTTransactionSendsFrameTracerEvents() { sp layer = createBufferStateLayer(); sp fence(new Fence()); - const auto buffer = std::make_shared< - renderengine::ExternalTexture>(new GraphicBuffer(1, 1, HAL_PIXEL_FORMAT_RGBA_8888, - 1, 0), - mRenderEngine, false); + const auto buffer = new GraphicBuffer(1, 1, HAL_PIXEL_FORMAT_RGBA_8888, 1, 0); int32_t layerId = layer->getSequence(); - uint64_t bufferId = buffer->getBuffer()->getId(); + uint64_t bufferId = buffer->getId(); uint64_t frameNumber = 5; nsecs_t dequeueTime = 10; nsecs_t postTime = 20; @@ -117,9 +114,14 @@ public: EXPECT_CALL(*mFlinger.getFrameTracer(), traceTimestamp(layerId, bufferId, frameNumber, postTime, FrameTracer::FrameEvent::QUEUE, /*duration*/ 0)); - layer->setBuffer(buffer, fence, postTime, /*desiredPresentTime*/ 30, false, mClientCache, - frameNumber, dequeueTime, FrameTimelineInfo{}, - nullptr /* releaseBufferCallback */, nullptr /* releaseBufferEndpoint*/); + BufferData bufferData; + bufferData.buffer = buffer; + bufferData.acquireFence = fence; + bufferData.frameNumber = frameNumber; + bufferData.flags |= BufferData::BufferDataChange::fenceChanged; + bufferData.flags |= BufferData::BufferDataChange::frameNumberChanged; + layer->setBuffer(bufferData, postTime, /*desiredPresentTime*/ 30, false, dequeueTime, + FrameTimelineInfo{}); commitTransaction(layer.get()); bool computeVisisbleRegions; diff --git a/services/surfaceflinger/tests/unittests/TransactionSurfaceFrameTest.cpp b/services/surfaceflinger/tests/unittests/TransactionSurfaceFrameTest.cpp index 2a7921f661..2b5b7b5a5b 100644 --- a/services/surfaceflinger/tests/unittests/TransactionSurfaceFrameTest.cpp +++ b/services/surfaceflinger/tests/unittests/TransactionSurfaceFrameTest.cpp @@ -46,6 +46,7 @@ public: ALOGD("**** Setting up for %s.%s\n", test_info->test_case_name(), test_info->name()); setupScheduler(); mFlinger.setupComposer(std::make_unique()); + mFlinger.setupRenderEngine(std::unique_ptr(mRenderEngine)); } ~TransactionSurfaceFrameTest() { @@ -92,10 +93,9 @@ public: } TestableSurfaceFlinger mFlinger; - renderengine::mock::RenderEngine mRenderEngine; + renderengine::mock::RenderEngine* mRenderEngine = new renderengine::mock::RenderEngine(); FenceToFenceTimeMap fenceFactory; - client_cache_t mClientCache; void PresentedSurfaceFrameForBufferlessTransaction() { sp layer = createBufferStateLayer(); @@ -114,13 +114,15 @@ public: sp layer = createBufferStateLayer(); sp fence(new Fence()); auto acquireFence = fenceFactory.createFenceTimeForTest(fence); - const auto buffer = std::make_shared< - renderengine::ExternalTexture>(new GraphicBuffer(1, 1, HAL_PIXEL_FORMAT_RGBA_8888, - 1, 0), - mRenderEngine, false); - layer->setBuffer(buffer, fence, 10, 20, false, mClientCache, 1, std::nullopt, - {/*vsyncId*/ 1, /*inputEventId*/ 0}, nullptr /* releaseBufferCallback */, - nullptr /* releaseBufferEndpoint */); + const auto buffer = new GraphicBuffer(1, 1, HAL_PIXEL_FORMAT_RGBA_8888, 1, 0); + BufferData bufferData; + bufferData.buffer = buffer; + bufferData.acquireFence = fence; + bufferData.frameNumber = 1; + bufferData.flags |= BufferData::BufferDataChange::fenceChanged; + bufferData.flags |= BufferData::BufferDataChange::frameNumberChanged; + layer->setBuffer(bufferData, 10, 20, false, std::nullopt, + {/*vsyncId*/ 1, /*inputEventId*/ 0}); acquireFence->signalForTest(12); commitTransaction(layer.get()); @@ -143,27 +145,30 @@ public: sp fence1(new Fence()); auto acquireFence1 = fenceFactory.createFenceTimeForTest(fence1); - const auto buffer1 = std::make_shared< - renderengine::ExternalTexture>(new GraphicBuffer(1, 1, HAL_PIXEL_FORMAT_RGBA_8888, - 1, 0), - mRenderEngine, false); - layer->setBuffer(buffer1, fence1, 10, 20, false, mClientCache, 1, std::nullopt, - {/*vsyncId*/ 1, /*inputEventId*/ 0}, nullptr /* releaseBufferCallback */, - nullptr /* releaseBufferEndpoint */); + const auto buffer1 = new GraphicBuffer(1, 1, HAL_PIXEL_FORMAT_RGBA_8888, 1, 0); + BufferData bufferData; + bufferData.buffer = buffer1; + bufferData.acquireFence = fence1; + bufferData.frameNumber = 1; + bufferData.flags |= BufferData::BufferDataChange::fenceChanged; + bufferData.flags |= BufferData::BufferDataChange::frameNumberChanged; + layer->setBuffer(bufferData, 10, 20, false, std::nullopt, + {/*vsyncId*/ 1, /*inputEventId*/ 0}); EXPECT_EQ(0u, layer->mDrawingState.bufferlessSurfaceFramesTX.size()); ASSERT_NE(nullptr, layer->mDrawingState.bufferSurfaceFrameTX); const auto droppedSurfaceFrame = layer->mDrawingState.bufferSurfaceFrameTX; sp fence2(new Fence()); auto acquireFence2 = fenceFactory.createFenceTimeForTest(fence2); - const auto buffer2 = std::make_shared< - renderengine::ExternalTexture>(new GraphicBuffer(1, 1, HAL_PIXEL_FORMAT_RGBA_8888, - 1, 0), - mRenderEngine, false); + const auto buffer2 = new GraphicBuffer(1, 1, HAL_PIXEL_FORMAT_RGBA_8888, 1, 0); nsecs_t start = systemTime(); - layer->setBuffer(buffer2, fence2, 10, 20, false, mClientCache, 1, std::nullopt, - {/*vsyncId*/ 1, /*inputEventId*/ 0}, nullptr /* releaseBufferCallback */, - nullptr /* releaseBufferEndpoint */); + bufferData.buffer = buffer2; + bufferData.acquireFence = fence2; + bufferData.frameNumber = 1; + bufferData.flags |= BufferData::BufferDataChange::fenceChanged; + bufferData.flags |= BufferData::BufferDataChange::frameNumberChanged; + layer->setBuffer(bufferData, 10, 20, false, std::nullopt, + {/*vsyncId*/ 1, /*inputEventId*/ 0}); nsecs_t end = systemTime(); acquireFence2->signalForTest(12); @@ -198,13 +203,15 @@ public: sp fence(new Fence()); auto acquireFence = fenceFactory.createFenceTimeForTest(fence); - const auto buffer = std::make_shared< - renderengine::ExternalTexture>(new GraphicBuffer(1, 1, HAL_PIXEL_FORMAT_RGBA_8888, - 1, 0), - mRenderEngine, false); - layer->setBuffer(buffer, fence, 10, 20, false, mClientCache, 1, std::nullopt, - {/*vsyncId*/ 1, /*inputEventId*/ 0}, nullptr /* releaseBufferCallback */, - nullptr /* releaseBufferEndpoint */); + const auto buffer = new GraphicBuffer(1, 1, HAL_PIXEL_FORMAT_RGBA_8888, 1, 0); + BufferData bufferData; + bufferData.buffer = buffer; + bufferData.acquireFence = fence; + bufferData.frameNumber = 1; + bufferData.flags |= BufferData::BufferDataChange::fenceChanged; + bufferData.flags |= BufferData::BufferDataChange::frameNumberChanged; + layer->setBuffer(bufferData, 10, 20, false, std::nullopt, + {/*vsyncId*/ 1, /*inputEventId*/ 0}); acquireFence->signalForTest(12); EXPECT_EQ(0u, layer->mDrawingState.bufferlessSurfaceFramesTX.size()); @@ -227,13 +234,15 @@ public: sp layer = createBufferStateLayer(); sp fence(new Fence()); auto acquireFence = fenceFactory.createFenceTimeForTest(fence); - const auto buffer = std::make_shared< - renderengine::ExternalTexture>(new GraphicBuffer(1, 1, HAL_PIXEL_FORMAT_RGBA_8888, - 1, 0), - mRenderEngine, false); - layer->setBuffer(buffer, fence, 10, 20, false, mClientCache, 1, std::nullopt, - {/*vsyncId*/ 1, /*inputEventId*/ 0}, nullptr /* releaseBufferCallback */, - nullptr /* releaseBufferEndpoint */); + const auto buffer = new GraphicBuffer(1, 1, HAL_PIXEL_FORMAT_RGBA_8888, 1, 0); + BufferData bufferData; + bufferData.buffer = buffer; + bufferData.acquireFence = fence; + bufferData.frameNumber = 1; + bufferData.flags |= BufferData::BufferDataChange::fenceChanged; + bufferData.flags |= BufferData::BufferDataChange::frameNumberChanged; + layer->setBuffer(bufferData, 10, 20, false, std::nullopt, + {/*vsyncId*/ 1, /*inputEventId*/ 0}); EXPECT_EQ(0u, layer->mDrawingState.bufferlessSurfaceFramesTX.size()); ASSERT_NE(nullptr, layer->mDrawingState.bufferSurfaceFrameTX); @@ -260,13 +269,15 @@ public: sp fence(new Fence()); auto acquireFence = fenceFactory.createFenceTimeForTest(fence); - const auto buffer = std::make_shared< - renderengine::ExternalTexture>(new GraphicBuffer(1, 1, HAL_PIXEL_FORMAT_RGBA_8888, - 1, 0), - mRenderEngine, false); - layer->setBuffer(buffer, fence, 10, 20, false, mClientCache, 1, std::nullopt, - {/*vsyncId*/ 3, /*inputEventId*/ 0}, nullptr /* releaseBufferCallback */, - nullptr /* releaseBufferEndpoint */); + const auto buffer = new GraphicBuffer(1, 1, HAL_PIXEL_FORMAT_RGBA_8888, 1, 0); + BufferData bufferData; + bufferData.buffer = buffer; + bufferData.acquireFence = fence; + bufferData.frameNumber = 1; + bufferData.flags |= BufferData::BufferDataChange::fenceChanged; + bufferData.flags |= BufferData::BufferDataChange::frameNumberChanged; + layer->setBuffer(bufferData, 10, 20, false, std::nullopt, + {/*vsyncId*/ 3, /*inputEventId*/ 0}); EXPECT_EQ(2u, layer->mDrawingState.bufferlessSurfaceFramesTX.size()); ASSERT_NE(nullptr, layer->mDrawingState.bufferSurfaceFrameTX); const auto bufferSurfaceFrameTX = layer->mDrawingState.bufferSurfaceFrameTX; @@ -299,25 +310,28 @@ public: sp fence1(new Fence()); auto acquireFence1 = fenceFactory.createFenceTimeForTest(fence1); - const auto buffer1 = std::make_shared< - renderengine::ExternalTexture>(new GraphicBuffer(1, 1, HAL_PIXEL_FORMAT_RGBA_8888, - 1, 0), - mRenderEngine, false); - layer->setBuffer(buffer1, fence1, 10, 20, false, mClientCache, 1, std::nullopt, - {/*vsyncId*/ 1, /*inputEventId*/ 0}, nullptr /* releaseBufferCallback */, - nullptr /* releaseBufferEndpoint */); + const auto buffer1 = new GraphicBuffer(1, 1, HAL_PIXEL_FORMAT_RGBA_8888, 1, 0); + BufferData bufferData; + bufferData.buffer = buffer1; + bufferData.acquireFence = fence1; + bufferData.frameNumber = 1; + bufferData.flags |= BufferData::BufferDataChange::fenceChanged; + bufferData.flags |= BufferData::BufferDataChange::frameNumberChanged; + layer->setBuffer(bufferData, 10, 20, false, std::nullopt, + {/*vsyncId*/ 1, /*inputEventId*/ 0}); ASSERT_NE(nullptr, layer->mDrawingState.bufferSurfaceFrameTX); const auto droppedSurfaceFrame = layer->mDrawingState.bufferSurfaceFrameTX; sp fence2(new Fence()); auto acquireFence2 = fenceFactory.createFenceTimeForTest(fence2); - const auto buffer2 = std::make_shared< - renderengine::ExternalTexture>(new GraphicBuffer(1, 1, HAL_PIXEL_FORMAT_RGBA_8888, - 1, 0), - mRenderEngine, false); - layer->setBuffer(buffer2, fence2, 10, 20, false, mClientCache, 1, std::nullopt, - {/*vsyncId*/ 1, /*inputEventId*/ 0}, nullptr /* releaseBufferCallback */, - nullptr /* releaseBufferEndpoint */); + const auto buffer2 = new GraphicBuffer(1, 1, HAL_PIXEL_FORMAT_RGBA_8888, 1, 0); + bufferData.buffer = buffer2; + bufferData.acquireFence = fence2; + bufferData.frameNumber = 1; + bufferData.flags |= BufferData::BufferDataChange::fenceChanged; + bufferData.flags |= BufferData::BufferDataChange::frameNumberChanged; + layer->setBuffer(bufferData, 10, 20, false, std::nullopt, + {/*vsyncId*/ 1, /*inputEventId*/ 0}); acquireFence2->signalForTest(12); ASSERT_NE(nullptr, layer->mDrawingState.bufferSurfaceFrameTX); @@ -342,27 +356,30 @@ public: sp fence1(new Fence()); auto acquireFence1 = fenceFactory.createFenceTimeForTest(fence1); - const auto buffer1 = std::make_shared< - renderengine::ExternalTexture>(new GraphicBuffer(1, 1, HAL_PIXEL_FORMAT_RGBA_8888, - 1, 0), - mRenderEngine, false); - layer->setBuffer(buffer1, fence1, 10, 20, false, mClientCache, 1, std::nullopt, - {/*vsyncId*/ 1, /*inputEventId*/ 0}, nullptr /* releaseBufferCallback */, - nullptr /* releaseBufferEndpoint */); + const auto buffer1 = new GraphicBuffer(1, 1, HAL_PIXEL_FORMAT_RGBA_8888, 1, 0); + BufferData bufferData; + bufferData.buffer = buffer1; + bufferData.acquireFence = fence1; + bufferData.frameNumber = 1; + bufferData.flags |= BufferData::BufferDataChange::fenceChanged; + bufferData.flags |= BufferData::BufferDataChange::frameNumberChanged; + layer->setBuffer(bufferData, 10, 20, false, std::nullopt, + {/*vsyncId*/ 1, /*inputEventId*/ 0}); EXPECT_EQ(0u, layer->mDrawingState.bufferlessSurfaceFramesTX.size()); ASSERT_NE(nullptr, layer->mDrawingState.bufferSurfaceFrameTX); const auto droppedSurfaceFrame1 = layer->mDrawingState.bufferSurfaceFrameTX; sp fence2(new Fence()); auto acquireFence2 = fenceFactory.createFenceTimeForTest(fence2); - const auto buffer2 = std::make_shared< - renderengine::ExternalTexture>(new GraphicBuffer(1, 1, HAL_PIXEL_FORMAT_RGBA_8888, - 1, 0), - mRenderEngine, false); + const auto buffer2 = new GraphicBuffer(1, 1, HAL_PIXEL_FORMAT_RGBA_8888, 1, 0); auto dropStartTime1 = systemTime(); - layer->setBuffer(buffer2, fence2, 10, 20, false, mClientCache, 1, std::nullopt, - {/*vsyncId*/ FrameTimelineInfo::INVALID_VSYNC_ID, /*inputEventId*/ 0}, - nullptr /* releaseBufferCallback */, nullptr /* releaseBufferEndpoint */); + bufferData.buffer = buffer2; + bufferData.acquireFence = fence2; + bufferData.frameNumber = 1; + bufferData.flags |= BufferData::BufferDataChange::fenceChanged; + bufferData.flags |= BufferData::BufferDataChange::frameNumberChanged; + layer->setBuffer(bufferData, 10, 20, false, std::nullopt, + {/*vsyncId*/ FrameTimelineInfo::INVALID_VSYNC_ID, /*inputEventId*/ 0}); auto dropEndTime1 = systemTime(); EXPECT_EQ(0u, layer->mDrawingState.bufferlessSurfaceFramesTX.size()); ASSERT_NE(nullptr, layer->mDrawingState.bufferSurfaceFrameTX); @@ -370,14 +387,15 @@ public: sp fence3(new Fence()); auto acquireFence3 = fenceFactory.createFenceTimeForTest(fence3); - const auto buffer3 = std::make_shared< - renderengine::ExternalTexture>(new GraphicBuffer(1, 1, HAL_PIXEL_FORMAT_RGBA_8888, - 1, 0), - mRenderEngine, false); + const auto buffer3 = new GraphicBuffer(1, 1, HAL_PIXEL_FORMAT_RGBA_8888, 1, 0); auto dropStartTime2 = systemTime(); - layer->setBuffer(buffer3, fence3, 10, 20, false, mClientCache, 1, std::nullopt, - {/*vsyncId*/ 2, /*inputEventId*/ 0}, nullptr /* releaseBufferCallback */, - nullptr /* releaseBufferEndpoint */); + bufferData.buffer = buffer3; + bufferData.acquireFence = fence3; + bufferData.frameNumber = 1; + bufferData.flags |= BufferData::BufferDataChange::fenceChanged; + bufferData.flags |= BufferData::BufferDataChange::frameNumberChanged; + layer->setBuffer(bufferData, 10, 20, false, std::nullopt, + {/*vsyncId*/ 2, /*inputEventId*/ 0}); auto dropEndTime2 = systemTime(); acquireFence3->signalForTest(12); @@ -413,16 +431,16 @@ public: uint32_t surfaceFramesPendingClassification = 0; std::vector> bufferlessSurfaceFrames; for (int i = 0; i < 10; i += 2) { - sp fence1(new Fence()); - const auto buffer1 = std::make_shared< - renderengine::ExternalTexture>(new GraphicBuffer(1, 1, - HAL_PIXEL_FORMAT_RGBA_8888, 1, - 0), - mRenderEngine, false); - layer->setBuffer(buffer1, fence1, 10, 20, false, mClientCache, 1, std::nullopt, - {/*vsyncId*/ 1, /*inputEventId*/ 0}, - nullptr /* releaseBufferCallback */, - nullptr /* releaseBufferEndpoint */); + sp fence(new Fence()); + const auto buffer = new GraphicBuffer(1, 1, HAL_PIXEL_FORMAT_RGBA_8888, 1, 0); + BufferData bufferData; + bufferData.buffer = buffer; + bufferData.acquireFence = fence; + bufferData.frameNumber = 1; + bufferData.flags |= BufferData::BufferDataChange::fenceChanged; + bufferData.flags |= BufferData::BufferDataChange::frameNumberChanged; + layer->setBuffer(bufferData, 10, 20, false, std::nullopt, + {/*vsyncId*/ 1, /*inputEventId*/ 0}); layer->setFrameTimelineVsyncForBufferlessTransaction({/*vsyncId*/ 2, /*inputEventId*/ 0}, 10); -- cgit v1.2.3-59-g8ed1b From 1dc4bfa7abbdab74ad7dd29d3c860583bfe0fd0c Mon Sep 17 00:00:00 2001 From: Alec Mouri Date: Fri, 1 Oct 2021 16:31:08 -0700 Subject: Remove buffer occupancy stats These statistics tracked double and triple buffering rates in SurfaceFlinger, both of which are not possible to track in BufferStateLayer, nor were these histograms particularly looked at when BufferQueueLayer was using this. Bug: 170662799 Bug: 199699421 Test: builds Change-Id: I6c65db1cb4de790e5bf46eaff5dee5f3491a6641 --- services/surfaceflinger/BufferLayer.cpp | 5 +-- services/surfaceflinger/BufferLayer.h | 2 +- services/surfaceflinger/BufferQueueLayer.cpp | 10 ----- services/surfaceflinger/BufferQueueLayer.h | 2 - services/surfaceflinger/Layer.h | 10 +---- services/surfaceflinger/SurfaceFlinger.cpp | 62 +--------------------------- services/surfaceflinger/SurfaceFlinger.h | 21 ---------- 7 files changed, 7 insertions(+), 105 deletions(-) (limited to 'services/surfaceflinger/BufferQueueLayer.cpp') diff --git a/services/surfaceflinger/BufferLayer.cpp b/services/surfaceflinger/BufferLayer.cpp index d805294b07..ffb0a188ca 100644 --- a/services/surfaceflinger/BufferLayer.cpp +++ b/services/surfaceflinger/BufferLayer.cpp @@ -346,13 +346,13 @@ TimeStats::SetFrameRateVote frameRateToSetFrameRateVotePayload(Layer::FrameRate } } // namespace -bool BufferLayer::onPostComposition(const DisplayDevice* display, +void BufferLayer::onPostComposition(const DisplayDevice* display, const std::shared_ptr& glDoneFence, const std::shared_ptr& presentFence, const CompositorTiming& compositorTiming) { // mFrameLatencyNeeded is true when a new frame was latched for the // composition. - if (!mBufferInfo.mFrameLatencyNeeded) return false; + if (!mBufferInfo.mFrameLatencyNeeded) return; // Update mFrameEventHistory. { @@ -426,7 +426,6 @@ bool BufferLayer::onPostComposition(const DisplayDevice* display, mFrameTracker.advanceFrame(); mBufferInfo.mFrameLatencyNeeded = false; - return true; } void BufferLayer::gatherBufferInfo() { diff --git a/services/surfaceflinger/BufferLayer.h b/services/surfaceflinger/BufferLayer.h index 760c8b9f3c..6607cb5890 100644 --- a/services/surfaceflinger/BufferLayer.h +++ b/services/surfaceflinger/BufferLayer.h @@ -77,7 +77,7 @@ public: bool isHdrY410() const override; - bool onPostComposition(const DisplayDevice*, const std::shared_ptr& glDoneFence, + void onPostComposition(const DisplayDevice*, const std::shared_ptr& glDoneFence, const std::shared_ptr& presentFence, const CompositorTiming&) override; diff --git a/services/surfaceflinger/BufferQueueLayer.cpp b/services/surfaceflinger/BufferQueueLayer.cpp index d51db88662..19569a5119 100644 --- a/services/surfaceflinger/BufferQueueLayer.cpp +++ b/services/surfaceflinger/BufferQueueLayer.cpp @@ -65,16 +65,6 @@ void BufferQueueLayer::setTransformHint(ui::Transform::RotationFlags displayTran mConsumer->setTransformHint(mTransformHint); } -std::vector BufferQueueLayer::getOccupancyHistory(bool forceFlush) { - std::vector history; - status_t result = mConsumer->getOccupancyHistory(forceFlush, &history); - if (result != NO_ERROR) { - ALOGW("[%s] Failed to obtain occupancy history (%d)", getDebugName(), result); - return {}; - } - return history; -} - void BufferQueueLayer::releasePendingBuffer(nsecs_t dequeueReadyTime) { if (!mConsumer->releasePendingBuffer()) { return; diff --git a/services/surfaceflinger/BufferQueueLayer.h b/services/surfaceflinger/BufferQueueLayer.h index b3b7948935..0b808752de 100644 --- a/services/surfaceflinger/BufferQueueLayer.h +++ b/services/surfaceflinger/BufferQueueLayer.h @@ -44,8 +44,6 @@ public: void onLayerDisplayed(const sp& releaseFence) override; - std::vector getOccupancyHistory(bool forceFlush) override; - // If a buffer was replaced this frame, release the former buffer void releasePendingBuffer(nsecs_t dequeueReadyTime) override; diff --git a/services/surfaceflinger/Layer.h b/services/surfaceflinger/Layer.h index 8c281d53e4..d4544be1d7 100644 --- a/services/surfaceflinger/Layer.h +++ b/services/surfaceflinger/Layer.h @@ -533,12 +533,10 @@ public: * called after composition. * returns true if the layer latched a new buffer this frame. */ - virtual bool onPostComposition(const DisplayDevice*, + virtual void onPostComposition(const DisplayDevice*, const std::shared_ptr& /*glDoneFence*/, const std::shared_ptr& /*presentFence*/, - const CompositorTiming&) { - return false; - } + const CompositorTiming&) {} // If a buffer was replaced this frame, release the former buffer virtual void releasePendingBuffer(nsecs_t /*dequeueReadyTime*/) { } @@ -599,10 +597,6 @@ public: } virtual FrameRate getFrameRateForLayerTree() const; - virtual std::vector getOccupancyHistory(bool /*forceFlush*/) { - return {}; - } - virtual bool getTransformToDisplayInverse() const { return false; } // Returns how rounded corners should be drawn for this layer. diff --git a/services/surfaceflinger/SurfaceFlinger.cpp b/services/surfaceflinger/SurfaceFlinger.cpp index 88715e36aa..57c6e8a4c1 100644 --- a/services/surfaceflinger/SurfaceFlinger.cpp +++ b/services/surfaceflinger/SurfaceFlinger.cpp @@ -2282,13 +2282,9 @@ void SurfaceFlinger::postComposition() { } for (const auto& layer: mLayersWithQueuedFrames) { - const bool frameLatched = - layer->onPostComposition(display, glCompositionDoneFenceTime, - mPreviousPresentFences[0].fenceTime, compositorTiming); + layer->onPostComposition(display, glCompositionDoneFenceTime, + mPreviousPresentFences[0].fenceTime, compositorTiming); layer->releasePendingBuffer(/*dequeueReadyTime*/ now); - if (frameLatched) { - recordBufferingStats(layer->getName(), layer->getOccupancyHistory(false)); - } } std::vector, sp>> @@ -3213,8 +3209,6 @@ void SurfaceFlinger::doCommitTransactions() { if (!mLayersPendingRemoval.isEmpty()) { // Notify removed layers now that they can't be drawn from for (const auto& l : mLayersPendingRemoval) { - recordBufferingStats(l->getName(), l->getOccupancyHistory(true)); - // Ensure any buffers set to display on any children are released. if (l->isRemovedFromCurrentState()) { l->latchAndReleaseBuffer(); @@ -4824,24 +4818,6 @@ void SurfaceFlinger::dumpStaticScreenStats(std::string& result) const { bucketTimeSec, percent); } -void SurfaceFlinger::recordBufferingStats(const std::string& layerName, - std::vector&& history) { - Mutex::Autolock lock(getBE().mBufferingStatsMutex); - auto& stats = getBE().mBufferingStats[layerName]; - for (const auto& segment : history) { - if (!segment.usedThirdBuffer) { - stats.twoBufferTime += segment.totalTime; - } - if (segment.occupancyAverage < 1.0f) { - stats.doubleBufferedTime += segment.totalTime; - } else if (segment.occupancyAverage < 2.0f) { - stats.tripleBufferedTime += segment.totalTime; - } - ++stats.numSegments; - stats.totalTime += segment.totalTime; - } -} - void SurfaceFlinger::dumpFrameEventsLocked(std::string& result) { result.append("Layer frame timestamps:\n"); // Traverse all layers to dump frame-events for each layer @@ -4849,38 +4825,6 @@ void SurfaceFlinger::dumpFrameEventsLocked(std::string& result) { [&] (Layer* layer) { layer->dumpFrameEvents(result); }); } -void SurfaceFlinger::dumpBufferingStats(std::string& result) const { - result.append("Buffering stats:\n"); - result.append(" [Layer name] " - " \n"); - Mutex::Autolock lock(getBE().mBufferingStatsMutex); - typedef std::tuple BufferTuple; - std::map> sorted; - for (const auto& statsPair : getBE().mBufferingStats) { - const char* name = statsPair.first.c_str(); - const SurfaceFlingerBE::BufferingStats& stats = statsPair.second; - if (stats.numSegments == 0) { - continue; - } - float activeTime = ns2ms(stats.totalTime) / 1000.0f; - float twoBufferRatio = static_cast(stats.twoBufferTime) / - stats.totalTime; - float doubleBufferRatio = static_cast( - stats.doubleBufferedTime) / stats.totalTime; - float tripleBufferRatio = static_cast( - stats.tripleBufferedTime) / stats.totalTime; - sorted.insert({activeTime, {name, twoBufferRatio, - doubleBufferRatio, tripleBufferRatio}}); - } - for (const auto& sortedPair : sorted) { - float activeTime = sortedPair.first; - const BufferTuple& values = sortedPair.second; - StringAppendF(&result, " [%s] %.2f %.3f %.3f %.3f\n", std::get<0>(values).c_str(), - activeTime, std::get<1>(values), std::get<2>(values), std::get<3>(values)); - } - result.append("\n"); -} - void SurfaceFlinger::dumpDisplayIdentificationData(std::string& result) const { for (const auto& [token, display] : mDisplays) { const auto displayId = PhysicalDisplayId::tryCast(display->getId()); @@ -5072,8 +5016,6 @@ void SurfaceFlinger::dumpAllLocked(const DumpArgs& args, std::string& result) co StringAppendF(&result, "HWC missed frame count: %u\n", mHwcFrameMissedCount.load()); StringAppendF(&result, "GPU missed frame count: %u\n\n", mGpuFrameMissedCount.load()); - dumpBufferingStats(result); - /* * Dump the visible layer list */ diff --git a/services/surfaceflinger/SurfaceFlinger.h b/services/surfaceflinger/SurfaceFlinger.h index 141d7ac34f..a8e92484b7 100644 --- a/services/surfaceflinger/SurfaceFlinger.h +++ b/services/surfaceflinger/SurfaceFlinger.h @@ -32,7 +32,6 @@ #include #include #include -#include #include #include #include @@ -155,22 +154,6 @@ struct SurfaceFlingerBE { nsecs_t mFrameBuckets[NUM_BUCKETS] = {}; nsecs_t mTotalTime = 0; std::atomic mLastSwapTime = 0; - - // Double- vs. triple-buffering stats - struct BufferingStats { - size_t numSegments = 0; - nsecs_t totalTime = 0; - - // "Two buffer" means that a third buffer was never used, whereas - // "double-buffered" means that on average the segment only used two - // buffers (though it may have used a third for some part of the - // segment) - nsecs_t twoBufferTime = 0; - nsecs_t doubleBufferedTime = 0; - nsecs_t tripleBufferedTime = 0; - }; - mutable Mutex mBufferingStatsMutex; - std::unordered_map mBufferingStats; }; class SurfaceFlinger : public BnSurfaceComposer, @@ -1160,10 +1143,6 @@ private: void dumpStaticScreenStats(std::string& result) const; // Not const because each Layer needs to query Fences and cache timestamps. void dumpFrameEventsLocked(std::string& result); - - void recordBufferingStats(const std::string& layerName, - std::vector&& history); - void dumpBufferingStats(std::string& result) const; void dumpDisplayIdentificationData(std::string& result) const REQUIRES(mStateLock); void dumpRawDisplayIdentificationData(const DumpArgs&, std::string& result) const; void dumpWideColorInfo(std::string& result) const REQUIRES(mStateLock); -- cgit v1.2.3-59-g8ed1b From e0e0cde7fa7d4dc34fb68c862f4a255d7d3252c7 Mon Sep 17 00:00:00 2001 From: Dominik Laskowski Date: Fri, 30 Jul 2021 10:42:05 -0700 Subject: SF: Decouple MessageQueue Define an ICompositor interface against which MessageQueue (which ought to be an implementation detail of Scheduler) is implemented. Change the equivocal invalidate/refresh nomenclature to commit/composite. Schedule sampling only after composite. Bug: 185535769 Test: libsurfaceflinger_unittest Change-Id: I0c18f312459bae48531449f24f7b53c104fc5812 --- services/surfaceflinger/BufferLayer.cpp | 2 +- services/surfaceflinger/BufferQueueLayer.cpp | 8 +- services/surfaceflinger/BufferStateLayer.cpp | 4 +- .../compositionengine/CompositionRefreshArgs.h | 4 +- .../CompositionEngine/src/Output.cpp | 2 +- services/surfaceflinger/DisplayDevice.cpp | 4 +- services/surfaceflinger/DisplayDevice.h | 2 +- services/surfaceflinger/RefreshRateOverlay.cpp | 2 +- services/surfaceflinger/RefreshRateOverlay.h | 2 +- services/surfaceflinger/RegionSamplingThread.cpp | 2 +- services/surfaceflinger/Scheduler/MessageQueue.cpp | 93 ++++++------ services/surfaceflinger/Scheduler/MessageQueue.h | 81 +++++----- services/surfaceflinger/Scheduler/Scheduler.cpp | 14 +- services/surfaceflinger/Scheduler/Scheduler.h | 6 +- services/surfaceflinger/SurfaceFlinger.cpp | 166 +++++++-------------- services/surfaceflinger/SurfaceFlinger.h | 68 ++++----- .../SurfaceFlingerDefaultFactory.cpp | 4 +- .../surfaceflinger/SurfaceFlingerDefaultFactory.h | 2 +- services/surfaceflinger/SurfaceFlingerFactory.h | 7 +- .../tests/unittests/CompositionTest.cpp | 10 +- .../tests/unittests/MessageQueueTest.cpp | 101 ++++++------- .../tests/unittests/SetFrameRateTest.cpp | 18 +-- .../unittests/SurfaceFlinger_CreateDisplayTest.cpp | 10 +- .../SurfaceFlinger_DestroyDisplayTest.cpp | 4 +- .../tests/unittests/SurfaceFlinger_HotplugTest.cpp | 10 +- .../SurfaceFlinger_OnInitializeDisplaysTest.cpp | 5 +- .../SurfaceFlinger_SetPowerModeInternalTest.cpp | 2 +- .../tests/unittests/TestableSurfaceFlinger.h | 20 ++- .../tests/unittests/TransactionApplicationTest.cpp | 14 +- .../tests/unittests/mock/MockMessageQueue.h | 9 +- .../tests/unittests/mock/MockSchedulerCallback.h | 4 +- 31 files changed, 304 insertions(+), 376 deletions(-) (limited to 'services/surfaceflinger/BufferQueueLayer.cpp') diff --git a/services/surfaceflinger/BufferLayer.cpp b/services/surfaceflinger/BufferLayer.cpp index ef05fe2138..160b2ea5c0 100644 --- a/services/surfaceflinger/BufferLayer.cpp +++ b/services/surfaceflinger/BufferLayer.cpp @@ -486,7 +486,7 @@ bool BufferLayer::latchBuffer(bool& recomputeVisibleRegions, nsecs_t latchTime, // try again later if (!fenceHasSignaled()) { ATRACE_NAME("!fenceHasSignaled()"); - mFlinger->signalLayerUpdate(); + mFlinger->onLayerUpdate(); return false; } diff --git a/services/surfaceflinger/BufferQueueLayer.cpp b/services/surfaceflinger/BufferQueueLayer.cpp index 8bbe43865a..bf38177d99 100644 --- a/services/surfaceflinger/BufferQueueLayer.cpp +++ b/services/surfaceflinger/BufferQueueLayer.cpp @@ -228,7 +228,7 @@ status_t BufferQueueLayer::updateTexImage(bool& recomputeVisibleRegions, nsecs_t if (updateResult == BufferQueue::PRESENT_LATER) { // Producer doesn't want buffer to be displayed yet. Signal a // layer update so we check again at the next opportunity. - mFlinger->signalLayerUpdate(); + mFlinger->onLayerUpdate(); return BAD_VALUE; } else if (updateResult == BufferLayerConsumer::BUFFER_REJECTED) { // If the buffer has been rejected, remove it from the shadow queue @@ -309,7 +309,7 @@ status_t BufferQueueLayer::updateTexImage(bool& recomputeVisibleRegions, nsecs_t // Decrement the queued-frames count. Signal another event if we // have more frames pending. if ((queuedBuffer && more_frames_pending) || mAutoRefresh) { - mFlinger->signalLayerUpdate(); + mFlinger->onLayerUpdate(); } return NO_ERROR; @@ -412,7 +412,7 @@ void BufferQueueLayer::onFrameAvailable(const BufferItem& item) { mFlinger->mInterceptor->saveBufferUpdate(layerId, item.mGraphicBuffer->getWidth(), item.mGraphicBuffer->getHeight(), item.mFrameNumber); - mFlinger->signalLayerUpdate(); + mFlinger->onLayerUpdate(); mConsumer->onBufferAvailable(item); } @@ -458,7 +458,7 @@ void BufferQueueLayer::onSidebandStreamChanged() { bool sidebandStreamChanged = false; if (mSidebandStreamChanged.compare_exchange_strong(sidebandStreamChanged, true)) { // mSidebandStreamChanged was changed to true - mFlinger->signalLayerUpdate(); + mFlinger->onLayerUpdate(); } } diff --git a/services/surfaceflinger/BufferStateLayer.cpp b/services/surfaceflinger/BufferStateLayer.cpp index 4eeaba154f..f0099c268d 100644 --- a/services/surfaceflinger/BufferStateLayer.cpp +++ b/services/surfaceflinger/BufferStateLayer.cpp @@ -595,7 +595,7 @@ bool BufferStateLayer::setSidebandStream(const sp& sidebandStream) setTransactionFlags(eTransactionNeeded); if (!mSidebandStreamChanged.exchange(true)) { // mSidebandStreamChanged was false - mFlinger->signalLayerUpdate(); + mFlinger->onLayerUpdate(); } return true; } @@ -713,7 +713,7 @@ bool BufferStateLayer::onPreComposition(nsecs_t refreshStartTime) { void BufferStateLayer::setAutoRefresh(bool autoRefresh) { if (!mAutoRefresh.exchange(autoRefresh)) { - mFlinger->signalLayerUpdate(); + mFlinger->onLayerUpdate(); } } diff --git a/services/surfaceflinger/CompositionEngine/include/compositionengine/CompositionRefreshArgs.h b/services/surfaceflinger/CompositionEngine/include/compositionengine/CompositionRefreshArgs.h index 95d553d02f..93586eddd8 100644 --- a/services/surfaceflinger/CompositionEngine/include/compositionengine/CompositionRefreshArgs.h +++ b/services/surfaceflinger/CompositionEngine/include/compositionengine/CompositionRefreshArgs.h @@ -85,8 +85,8 @@ struct CompositionRefreshArgs { // to prevent an early presentation of a frame. std::shared_ptr previousPresentFence; - // The predicted next invalidation time - std::optional nextInvalidateTime; + // If set, a frame has been scheduled for that time. + std::optional scheduledFrameTime; }; } // namespace android::compositionengine diff --git a/services/surfaceflinger/CompositionEngine/src/Output.cpp b/services/surfaceflinger/CompositionEngine/src/Output.cpp index 048d7c2b4a..fad1fa74dd 100644 --- a/services/surfaceflinger/CompositionEngine/src/Output.cpp +++ b/services/surfaceflinger/CompositionEngine/src/Output.cpp @@ -1314,7 +1314,7 @@ void Output::postFramebuffer() { void Output::renderCachedSets(const CompositionRefreshArgs& refreshArgs) { if (mPlanner) { - mPlanner->renderCachedSets(getState(), refreshArgs.nextInvalidateTime); + mPlanner->renderCachedSets(getState(), refreshArgs.scheduledFrameTime); } } diff --git a/services/surfaceflinger/DisplayDevice.cpp b/services/surfaceflinger/DisplayDevice.cpp index 3397118c05..fd09ae4066 100644 --- a/services/surfaceflinger/DisplayDevice.cpp +++ b/services/surfaceflinger/DisplayDevice.cpp @@ -466,9 +466,9 @@ bool DisplayDevice::onKernelTimerChanged(std::optional desiredMod return false; } -void DisplayDevice::onInvalidate() { +void DisplayDevice::animateRefreshRateOverlay() { if (mRefreshRateOverlay) { - mRefreshRateOverlay->onInvalidate(); + mRefreshRateOverlay->animate(); } } diff --git a/services/surfaceflinger/DisplayDevice.h b/services/surfaceflinger/DisplayDevice.h index 4a731bddf1..4b9718f608 100644 --- a/services/surfaceflinger/DisplayDevice.h +++ b/services/surfaceflinger/DisplayDevice.h @@ -234,7 +234,7 @@ public: void enableRefreshRateOverlay(bool enable, bool showSpinner); bool isRefreshRateOverlayEnabled() const { return mRefreshRateOverlay != nullptr; } bool onKernelTimerChanged(std::optional, bool timerExpired); - void onInvalidate(); + void animateRefreshRateOverlay(); void onVsync(nsecs_t timestamp); nsecs_t getVsyncPeriodFromHWC() const; diff --git a/services/surfaceflinger/RefreshRateOverlay.cpp b/services/surfaceflinger/RefreshRateOverlay.cpp index ec81e6317c..2502d66a67 100644 --- a/services/surfaceflinger/RefreshRateOverlay.cpp +++ b/services/surfaceflinger/RefreshRateOverlay.cpp @@ -284,7 +284,7 @@ void RefreshRateOverlay::changeRefreshRate(const Fps& fps) { t.apply(); } -void RefreshRateOverlay::onInvalidate() { +void RefreshRateOverlay::animate() { if (!mCurrentFps.has_value()) return; const auto& buffers = getOrCreateBuffers(*mCurrentFps); diff --git a/services/surfaceflinger/RefreshRateOverlay.h b/services/surfaceflinger/RefreshRateOverlay.h index 354510a9d7..65d446c751 100644 --- a/services/surfaceflinger/RefreshRateOverlay.h +++ b/services/surfaceflinger/RefreshRateOverlay.h @@ -46,7 +46,7 @@ public: void setLayerStack(ui::LayerStack); void setViewport(ui::Size); void changeRefreshRate(const Fps&); - void onInvalidate(); + void animate(); private: class SevenSegmentDrawer { diff --git a/services/surfaceflinger/RegionSamplingThread.cpp b/services/surfaceflinger/RegionSamplingThread.cpp index aa2fec56ad..9465b197b2 100644 --- a/services/surfaceflinger/RegionSamplingThread.cpp +++ b/services/surfaceflinger/RegionSamplingThread.cpp @@ -150,7 +150,7 @@ void RegionSamplingThread::checkForStaleLuma() { if (mSampleRequestTime.has_value()) { ATRACE_INT(lumaSamplingStepTag, static_cast(samplingStep::waitForSamplePhase)); mSampleRequestTime.reset(); - mFlinger.scheduleRegionSamplingThread(); + mFlinger.scheduleSample(); } } diff --git a/services/surfaceflinger/Scheduler/MessageQueue.cpp b/services/surfaceflinger/Scheduler/MessageQueue.cpp index 4d51125156..043a536216 100644 --- a/services/surfaceflinger/Scheduler/MessageQueue.cpp +++ b/services/surfaceflinger/Scheduler/MessageQueue.cpp @@ -27,49 +27,55 @@ #include "EventThread.h" #include "FrameTimeline.h" #include "MessageQueue.h" -#include "SurfaceFlinger.h" namespace android::impl { -void MessageQueue::Handler::dispatchRefresh() { - if ((mEventMask.fetch_or(eventMaskRefresh) & eventMaskRefresh) == 0) { - mQueue.mLooper->sendMessage(this, Message(MessageQueue::REFRESH)); +void MessageQueue::Handler::dispatchComposite() { + if ((mEventMask.fetch_or(kComposite) & kComposite) == 0) { + mQueue.mLooper->sendMessage(this, Message(kComposite)); } } -void MessageQueue::Handler::dispatchInvalidate(int64_t vsyncId, nsecs_t expectedVSyncTimestamp) { - if ((mEventMask.fetch_or(eventMaskInvalidate) & eventMaskInvalidate) == 0) { +void MessageQueue::Handler::dispatchCommit(int64_t vsyncId, nsecs_t expectedVsyncTime) { + if ((mEventMask.fetch_or(kCommit) & kCommit) == 0) { mVsyncId = vsyncId; - mExpectedVSyncTime = expectedVSyncTimestamp; - mQueue.mLooper->sendMessage(this, Message(MessageQueue::INVALIDATE)); + mExpectedVsyncTime = expectedVsyncTime; + mQueue.mLooper->sendMessage(this, Message(kCommit)); } } -bool MessageQueue::Handler::invalidatePending() { - constexpr auto pendingMask = eventMaskInvalidate | eventMaskRefresh; - return (mEventMask.load() & pendingMask) != 0; +bool MessageQueue::Handler::isFramePending() const { + constexpr auto kPendingMask = kCommit | kComposite; + return (mEventMask.load() & kPendingMask) != 0; } void MessageQueue::Handler::handleMessage(const Message& message) { + const nsecs_t frameTime = systemTime(); switch (message.what) { - case INVALIDATE: - mEventMask.fetch_and(~eventMaskInvalidate); - mQueue.mFlinger->onMessageReceived(message.what, mVsyncId, mExpectedVSyncTime); - break; - case REFRESH: - mEventMask.fetch_and(~eventMaskRefresh); - mQueue.mFlinger->onMessageReceived(message.what, mVsyncId, mExpectedVSyncTime); + case kCommit: + mEventMask.fetch_and(~kCommit); + if (!mQueue.mCompositor.commit(frameTime, mVsyncId, mExpectedVsyncTime)) { + return; + } + // Composite immediately, rather than after pending tasks through scheduleComposite. + [[fallthrough]]; + case kComposite: + mEventMask.fetch_and(~kComposite); + mQueue.mCompositor.composite(frameTime); + mQueue.mCompositor.sample(); break; } } -// --------------------------------------------------------------------------- +MessageQueue::MessageQueue(ICompositor& compositor) + : MessageQueue(compositor, sp::make(*this)) {} -void MessageQueue::init(const sp& flinger) { - mFlinger = flinger; - mLooper = new Looper(true); - mHandler = new Handler(*this); -} +constexpr bool kAllowNonCallbacks = true; + +MessageQueue::MessageQueue(ICompositor& compositor, sp handler) + : mCompositor(compositor), + mLooper(sp::make(kAllowNonCallbacks)), + mHandler(std::move(handler)) {} // TODO(b/169865816): refactor VSyncInjections to use MessageQueue directly // and remove the EventThread from MessageQueue @@ -110,11 +116,13 @@ void MessageQueue::vsyncCallback(nsecs_t vsyncTime, nsecs_t targetWakeupTime, ns { std::lock_guard lock(mVsync.mutex); mVsync.lastCallbackTime = std::chrono::nanoseconds(vsyncTime); - mVsync.scheduled = false; + mVsync.scheduledFrameTime.reset(); } - mHandler->dispatchInvalidate(mVsync.tokenManager->generateTokenForPredictions( - {targetWakeupTime, readyTime, vsyncTime}), - vsyncTime); + + const auto vsyncId = mVsync.tokenManager->generateTokenForPredictions( + {targetWakeupTime, readyTime, vsyncTime}); + + mHandler->dispatchCommit(vsyncId, vsyncTime); } void MessageQueue::initVsync(scheduler::VSyncDispatch& dispatch, @@ -135,8 +143,8 @@ void MessageQueue::setDuration(std::chrono::nanoseconds workDuration) { ATRACE_CALL(); std::lock_guard lock(mVsync.mutex); mVsync.workDuration = workDuration; - if (mVsync.scheduled) { - mVsync.expectedWakeupTime = mVsync.registration->schedule( + if (mVsync.scheduledFrameTime) { + mVsync.scheduledFrameTime = mVsync.registration->schedule( {mVsync.workDuration.get().count(), /*readyDuration=*/0, mVsync.lastCallbackTime.count()}); } @@ -168,7 +176,7 @@ void MessageQueue::postMessage(sp&& handler) { mLooper->sendMessage(handler, Message()); } -void MessageQueue::invalidate() { +void MessageQueue::scheduleCommit() { ATRACE_CALL(); { @@ -181,15 +189,14 @@ void MessageQueue::invalidate() { } std::lock_guard lock(mVsync.mutex); - mVsync.scheduled = true; - mVsync.expectedWakeupTime = + mVsync.scheduledFrameTime = mVsync.registration->schedule({.workDuration = mVsync.workDuration.get().count(), .readyDuration = 0, .earliestVsync = mVsync.lastCallbackTime.count()}); } -void MessageQueue::refresh() { - mHandler->dispatchRefresh(); +void MessageQueue::scheduleComposite() { + mHandler->dispatchComposite(); } void MessageQueue::injectorCallback() { @@ -198,24 +205,22 @@ void MessageQueue::injectorCallback() { while ((n = DisplayEventReceiver::getEvents(&mInjector.tube, buffer, 8)) > 0) { for (int i = 0; i < n; i++) { if (buffer[i].header.type == DisplayEventReceiver::DISPLAY_EVENT_VSYNC) { - mHandler->dispatchInvalidate(buffer[i].vsync.vsyncId, - buffer[i].vsync.expectedVSyncTimestamp); + mHandler->dispatchCommit(buffer[i].vsync.vsyncId, + buffer[i].vsync.expectedVSyncTimestamp); break; } } } } -std::optional MessageQueue::nextExpectedInvalidate() { - if (mHandler->invalidatePending()) { - return std::chrono::steady_clock::now(); +auto MessageQueue::getScheduledFrameTime() const -> std::optional { + if (mHandler->isFramePending()) { + return Clock::now(); } std::lock_guard lock(mVsync.mutex); - if (mVsync.scheduled) { - LOG_ALWAYS_FATAL_IF(!mVsync.expectedWakeupTime.has_value(), "callback was never scheduled"); - const auto expectedWakeupTime = std::chrono::nanoseconds(*mVsync.expectedWakeupTime); - return std::optional(expectedWakeupTime); + if (const auto time = mVsync.scheduledFrameTime) { + return Clock::time_point(std::chrono::nanoseconds(*time)); } return std::nullopt; diff --git a/services/surfaceflinger/Scheduler/MessageQueue.h b/services/surfaceflinger/Scheduler/MessageQueue.h index 58ce9b9a2f..2c908a6983 100644 --- a/services/surfaceflinger/Scheduler/MessageQueue.h +++ b/services/surfaceflinger/Scheduler/MessageQueue.h @@ -33,7 +33,14 @@ namespace android { -class SurfaceFlinger; +struct ICompositor { + virtual bool commit(nsecs_t frameTime, int64_t vsyncId, nsecs_t expectedVsyncTime) = 0; + virtual void composite(nsecs_t frameTime) = 0; + virtual void sample() = 0; + +protected: + ~ICompositor() = default; +}; template class Task : public MessageHandler { @@ -56,65 +63,65 @@ inline auto makeTask(F&& f) { class MessageQueue { public: - enum { - INVALIDATE = 0, - REFRESH = 1, - }; - virtual ~MessageQueue() = default; - virtual void init(const sp& flinger) = 0; virtual void initVsync(scheduler::VSyncDispatch&, frametimeline::TokenManager&, std::chrono::nanoseconds workDuration) = 0; virtual void setDuration(std::chrono::nanoseconds workDuration) = 0; virtual void setInjector(sp) = 0; virtual void waitMessage() = 0; virtual void postMessage(sp&&) = 0; - virtual void invalidate() = 0; - virtual void refresh() = 0; - virtual std::optional nextExpectedInvalidate() = 0; -}; + virtual void scheduleCommit() = 0; + virtual void scheduleComposite() = 0; -// --------------------------------------------------------------------------- + using Clock = std::chrono::steady_clock; + virtual std::optional getScheduledFrameTime() const = 0; +}; namespace impl { class MessageQueue : public android::MessageQueue { protected: class Handler : public MessageHandler { - enum : uint32_t { - eventMaskInvalidate = 0x1, - eventMaskRefresh = 0x2, - eventMaskTransaction = 0x4 - }; + static constexpr uint32_t kCommit = 0b1; + static constexpr uint32_t kComposite = 0b10; + MessageQueue& mQueue; - std::atomic mEventMask; - std::atomic mVsyncId; - std::atomic mExpectedVSyncTime; + std::atomic mEventMask = 0; + std::atomic mVsyncId = 0; + std::atomic mExpectedVsyncTime = 0; public: - explicit Handler(MessageQueue& queue) : mQueue(queue), mEventMask(0) {} + explicit Handler(MessageQueue& queue) : mQueue(queue) {} void handleMessage(const Message& message) override; - virtual void dispatchRefresh(); - virtual void dispatchInvalidate(int64_t vsyncId, nsecs_t expectedVSyncTimestamp); - virtual bool invalidatePending(); + + bool isFramePending() const; + + virtual void dispatchCommit(int64_t vsyncId, nsecs_t expectedVsyncTime); + void dispatchComposite(); }; friend class Handler; - sp mFlinger; - sp mLooper; + // For tests. + MessageQueue(ICompositor&, sp); + + void vsyncCallback(nsecs_t vsyncTime, nsecs_t targetWakeupTime, nsecs_t readyTime); + +private: + ICompositor& mCompositor; + const sp mLooper; + const sp mHandler; struct Vsync { frametimeline::TokenManager* tokenManager = nullptr; std::unique_ptr registration; - std::mutex mutex; + mutable std::mutex mutex; TracedOrdinal workDuration GUARDED_BY(mutex) = {"VsyncWorkDuration-sf", std::chrono::nanoseconds(0)}; std::chrono::nanoseconds lastCallbackTime GUARDED_BY(mutex) = std::chrono::nanoseconds{0}; - bool scheduled GUARDED_BY(mutex) = false; - std::optional expectedWakeupTime GUARDED_BY(mutex); + std::optional scheduledFrameTime GUARDED_BY(mutex); TracedOrdinal value = {"VSYNC-sf", 0}; }; @@ -127,14 +134,11 @@ protected: Vsync mVsync; Injector mInjector; - sp mHandler; - - void vsyncCallback(nsecs_t vsyncTime, nsecs_t targetWakeupTime, nsecs_t readyTime); void injectorCallback(); public: - ~MessageQueue() override = default; - void init(const sp& flinger) override; + explicit MessageQueue(ICompositor&); + void initVsync(scheduler::VSyncDispatch&, frametimeline::TokenManager&, std::chrono::nanoseconds workDuration) override; void setDuration(std::chrono::nanoseconds workDuration) override; @@ -143,13 +147,10 @@ public: void waitMessage() override; void postMessage(sp&&) override; - // sends INVALIDATE message at next VSYNC - void invalidate() override; - - // sends REFRESH message at next VSYNC - void refresh() override; + void scheduleCommit() override; + void scheduleComposite() override; - std::optional nextExpectedInvalidate() override; + std::optional getScheduledFrameTime() const override; }; } // namespace impl diff --git a/services/surfaceflinger/Scheduler/Scheduler.cpp b/services/surfaceflinger/Scheduler/Scheduler.cpp index 12e741bbc2..c6a19de9c6 100644 --- a/services/surfaceflinger/Scheduler/Scheduler.cpp +++ b/services/surfaceflinger/Scheduler/Scheduler.cpp @@ -870,7 +870,7 @@ DisplayModePtr Scheduler::getPreferredDisplayMode() { void Scheduler::onNewVsyncPeriodChangeTimeline(const hal::VsyncPeriodChangeTimeline& timeline) { if (timeline.refreshRequired) { - mSchedulerCallback.scheduleRefresh(FrameHint::kNone); + mSchedulerCallback.scheduleComposite(FrameHint::kNone); } std::lock_guard lock(mVsyncTimelineLock); @@ -882,12 +882,12 @@ void Scheduler::onNewVsyncPeriodChangeTimeline(const hal::VsyncPeriodChangeTimel } } -void Scheduler::onDisplayRefreshed(nsecs_t timestamp) { - const bool refresh = [=] { +void Scheduler::onPostComposition(nsecs_t presentTime) { + const bool recomposite = [=] { std::lock_guard lock(mVsyncTimelineLock); if (mLastVsyncPeriodChangeTimeline && mLastVsyncPeriodChangeTimeline->refreshRequired) { - if (timestamp < mLastVsyncPeriodChangeTimeline->refreshTimeNanos) { - // We need to schedule another refresh as refreshTimeNanos is still in the future. + if (presentTime < mLastVsyncPeriodChangeTimeline->refreshTimeNanos) { + // We need to composite again as refreshTimeNanos is still in the future. return true; } @@ -896,8 +896,8 @@ void Scheduler::onDisplayRefreshed(nsecs_t timestamp) { return false; }(); - if (refresh) { - mSchedulerCallback.scheduleRefresh(FrameHint::kNone); + if (recomposite) { + mSchedulerCallback.scheduleComposite(FrameHint::kNone); } } diff --git a/services/surfaceflinger/Scheduler/Scheduler.h b/services/surfaceflinger/Scheduler/Scheduler.h index 3f3debe33b..0a33dbbe92 100644 --- a/services/surfaceflinger/Scheduler/Scheduler.h +++ b/services/surfaceflinger/Scheduler/Scheduler.h @@ -59,7 +59,7 @@ struct ISchedulerCallback { // Indicates frame activity, i.e. whether commit and/or composite is taking place. enum class FrameHint { kNone, kActive }; - virtual void scheduleRefresh(FrameHint) = 0; + virtual void scheduleComposite(FrameHint) = 0; virtual void setVsyncEnabled(bool) = 0; virtual void changeRefreshRate(const scheduler::RefreshRateConfigs::RefreshRate&, scheduler::RefreshRateConfigEvent) = 0; @@ -162,8 +162,8 @@ public: // Notifies the scheduler about a refresh rate timeline change. void onNewVsyncPeriodChangeTimeline(const hal::VsyncPeriodChangeTimeline& timeline); - // Notifies the scheduler when the display was refreshed - void onDisplayRefreshed(nsecs_t timestamp); + // Notifies the scheduler post composition. + void onPostComposition(nsecs_t presentTime); // Notifies the scheduler when the display size has changed. Called from SF's main thread void onActiveDisplayAreaChanged(uint32_t displayArea); diff --git a/services/surfaceflinger/SurfaceFlinger.cpp b/services/surfaceflinger/SurfaceFlinger.cpp index e90af3a64a..bb65bae06b 100644 --- a/services/surfaceflinger/SurfaceFlinger.cpp +++ b/services/surfaceflinger/SurfaceFlinger.cpp @@ -371,7 +371,7 @@ SurfaceFlinger::SurfaceFlinger(Factory& factory, SkipInitializationTag) mTimeStats(std::make_shared()), mFrameTracer(mFactory.createFrameTracer()), mFrameTimeline(mFactory.createFrameTimeline(mTimeStats, getpid())), - mEventQueue(mFactory.createMessageQueue()), + mEventQueue(mFactory.createMessageQueue(*this)), mCompositionEngine(mFactory.createCompositionEngine()), mHwcServiceName(base::GetProperty("debug.sf.hwc_service_name"s, "default"s)), mTunnelModeEnabledReporter(new TunnelModeEnabledReporter()), @@ -506,10 +506,6 @@ SurfaceFlinger::SurfaceFlinger(Factory& factory) : SurfaceFlinger(factory, SkipI SurfaceFlinger::~SurfaceFlinger() = default; -void SurfaceFlinger::onFirstRef() { - mEventQueue->init(this); -} - void SurfaceFlinger::binderDied(const wp&) { // the window manager died on us. prepare its eulogy. mBootFinished = false; @@ -1104,7 +1100,7 @@ void SurfaceFlinger::setDesiredActiveMode(const ActiveModeInfo& info) { } if (display->setDesiredActiveMode(info)) { - scheduleRefresh(FrameHint::kNone); + scheduleComposite(FrameHint::kNone); // Start receiving vsync samples now, so that we can detect a period // switch. @@ -1704,31 +1700,26 @@ sp SurfaceFlinger::createDisplayEventConnection( return mScheduler->createDisplayEventConnection(handle, eventRegistration); } -void SurfaceFlinger::scheduleInvalidate(FrameHint hint) { +void SurfaceFlinger::scheduleCommit(FrameHint hint) { if (hint == FrameHint::kActive) { mScheduler->resetIdleTimer(); } mPowerAdvisor.notifyDisplayUpdateImminent(); - mEventQueue->invalidate(); + mEventQueue->scheduleCommit(); } -void SurfaceFlinger::scheduleRefresh(FrameHint hint) { - mForceRefresh = true; - scheduleInvalidate(hint); +void SurfaceFlinger::scheduleComposite(FrameHint hint) { + mMustComposite = true; + scheduleCommit(hint); } void SurfaceFlinger::scheduleRepaint() { mGeometryDirty = true; - scheduleRefresh(FrameHint::kActive); -} - -void SurfaceFlinger::signalLayerUpdate() { - scheduleInvalidate(FrameHint::kActive); + scheduleComposite(FrameHint::kActive); } -void SurfaceFlinger::signalRefresh() { - mRefreshPending = true; - mEventQueue->refresh(); +void SurfaceFlinger::scheduleSample() { + static_cast(schedule([this] { sample(); })); } nsecs_t SurfaceFlinger::getVsyncPeriodFromHWC() const { @@ -1834,7 +1825,7 @@ void SurfaceFlinger::onComposerHalSeamlessPossible(hal::HWDisplayId) { void SurfaceFlinger::onComposerHalRefresh(hal::HWDisplayId) { Mutex::Autolock lock(mStateLock); - scheduleRefresh(FrameHint::kNone); + scheduleComposite(FrameHint::kNone); } void SurfaceFlinger::setVsyncEnabled(bool enabled) { @@ -1889,40 +1880,26 @@ nsecs_t SurfaceFlinger::calculateExpectedPresentTime(DisplayStatInfo stats) cons : stats.vsyncTime + stats.vsyncPeriod; } -void SurfaceFlinger::onMessageReceived(int32_t what, int64_t vsyncId, nsecs_t expectedVSyncTime) { - switch (what) { - case MessageQueue::INVALIDATE: { - onMessageInvalidate(vsyncId, expectedVSyncTime); - break; - } - case MessageQueue::REFRESH: { - onMessageRefresh(); - break; - } - } -} - -void SurfaceFlinger::onMessageInvalidate(int64_t vsyncId, nsecs_t expectedVSyncTime) { - const nsecs_t frameStart = systemTime(); +bool SurfaceFlinger::commit(nsecs_t frameTime, int64_t vsyncId, nsecs_t expectedVsyncTime) { // calculate the expected present time once and use the cached // value throughout this frame to make sure all layers are // seeing this same value. - if (expectedVSyncTime >= frameStart) { - mExpectedPresentTime = expectedVSyncTime; + if (expectedVsyncTime >= frameTime) { + mExpectedPresentTime = expectedVsyncTime; } else { - const DisplayStatInfo stats = mScheduler->getDisplayStatInfo(frameStart); + const DisplayStatInfo stats = mScheduler->getDisplayStatInfo(frameTime); mExpectedPresentTime = calculateExpectedPresentTime(stats); } const nsecs_t lastScheduledPresentTime = mScheduledPresentTime; - mScheduledPresentTime = expectedVSyncTime; + mScheduledPresentTime = expectedVsyncTime; const auto vsyncIn = [&] { if (!ATRACE_ENABLED()) return 0.f; return (mExpectedPresentTime - systemTime()) / 1e6f; }(); - ATRACE_FORMAT("onMessageInvalidate %" PRId64 " vsyncIn %.2fms%s", vsyncId, vsyncIn, - mExpectedPresentTime == expectedVSyncTime ? "" : " (adjusted)"); + ATRACE_FORMAT("%s %" PRId64 " vsyncIn %.2fms%s", __func__, vsyncId, vsyncIn, + mExpectedPresentTime == expectedVsyncTime ? "" : " (adjusted)"); // When Backpressure propagation is enabled we want to give a small grace period // for the present fence to fire instead of just giving up on this frame to handle cases @@ -1969,11 +1946,11 @@ void SurfaceFlinger::onMessageInvalidate(int64_t vsyncId, nsecs_t expectedVSyncT } // If we are in the middle of a mode change and the fence hasn't - // fired yet just wait for the next invalidate + // fired yet just wait for the next commit. if (mSetActiveModePending) { if (framePending) { - mEventQueue->invalidate(); - return; + mEventQueue->scheduleCommit(); + return false; } // We received the present fence from the HWC, so we assume it successfully updated @@ -1984,8 +1961,8 @@ void SurfaceFlinger::onMessageInvalidate(int64_t vsyncId, nsecs_t expectedVSyncT if (framePending) { if ((hwcFrameMissed && !gpuFrameMissed) || mPropagateBackpressureClientComposition) { - signalLayerUpdate(); - return; + scheduleCommit(FrameHint::kNone); + return false; } } @@ -1997,11 +1974,12 @@ void SurfaceFlinger::onMessageInvalidate(int64_t vsyncId, nsecs_t expectedVSyncT if (mRefreshRateOverlaySpinner) { Mutex::Autolock lock(mStateLock); if (const auto display = getDefaultDisplayDeviceLocked()) { - display->onInvalidate(); + display->animateRefreshRateOverlay(); } } - bool refreshNeeded = mForceRefresh.exchange(false); + // Composite if transactions were committed, or if requested by HWC. + bool mustComposite = mMustComposite.exchange(false); { mTracePostComposition = mTracing.flagIsSet(SurfaceTracing::TRACE_COMPOSITION) || mTracing.flagIsSet(SurfaceTracing::TRACE_SYNC) || @@ -2009,10 +1987,12 @@ void SurfaceFlinger::onMessageInvalidate(int64_t vsyncId, nsecs_t expectedVSyncT const bool tracePreComposition = mTracingEnabled && !mTracePostComposition; ConditionalLockGuard lock(mTracingLock, tracePreComposition); - mFrameTimeline->setSfWakeUp(vsyncId, frameStart, Fps::fromPeriodNsecs(stats.vsyncPeriod)); + mFrameTimeline->setSfWakeUp(vsyncId, frameTime, Fps::fromPeriodNsecs(stats.vsyncPeriod)); + + mustComposite |= flushAndCommitTransactions(); + mustComposite |= latchBuffers(); - refreshNeeded |= flushAndCommitTransactions(); - refreshNeeded |= handleMessageInvalidate(); + updateLayerGeometry(); if (tracePreComposition) { if (mVisibleRegionsDirty) { @@ -2035,25 +2015,7 @@ void SurfaceFlinger::onMessageInvalidate(int64_t vsyncId, nsecs_t expectedVSyncT updateCursorAsync(); updateInputFlinger(); - if (refreshNeeded && CC_LIKELY(mBootStage != BootStage::BOOTLOADER)) { - // Signal a refresh if a transaction modified the window state, - // a new buffer was latched, or if HWC has requested a full - // repaint - if (mFrameStartTime <= 0) { - // We should only use the time of the first invalidate - // message that signals a refresh as the beginning of the - // frame. Otherwise the real frame time will be - // underestimated. - mFrameStartTime = frameStart; - } - - // Run the refresh immediately after invalidate as there is no point going thru the message - // queue again, and to ensure that we actually refresh the screen instead of handling - // other messages that were queued us already in the MessageQueue. - mRefreshPending = true; - onMessageRefresh(); - } - notifyRegionSamplingThread(); + return mustComposite && CC_LIKELY(mBootStage != BootStage::BOOTLOADER); } bool SurfaceFlinger::flushAndCommitTransactions() { @@ -2068,6 +2030,9 @@ bool SurfaceFlinger::flushAndCommitTransactions() { commitTransactions(); } + // Invoke OnCommit callbacks. + mTransactionCallbackInvoker.sendCallbacks(); + if (transactionFlushNeeded()) { setTransactionFlags(eTransactionFlushNeeded); } @@ -2075,11 +2040,9 @@ bool SurfaceFlinger::flushAndCommitTransactions() { return shouldCommit; } -void SurfaceFlinger::onMessageRefresh() { +void SurfaceFlinger::composite(nsecs_t frameTime) { ATRACE_CALL(); - mRefreshPending = false; - compositionengine::CompositionRefreshArgs refreshArgs; const auto& displays = ON_MAIN_THREAD(mDisplays); refreshArgs.outputs.reserve(displays.size()); @@ -2123,18 +2086,16 @@ void SurfaceFlinger::onMessageRefresh() { const auto hwcMinWorkDuration = mVsyncConfiguration->getCurrentConfigs().hwcMinWorkDuration; refreshArgs.earliestPresentTime = prevVsyncTime - hwcMinWorkDuration; refreshArgs.previousPresentFence = mPreviousPresentFences[0].fenceTime; - refreshArgs.nextInvalidateTime = mEventQueue->nextExpectedInvalidate(); + refreshArgs.scheduledFrameTime = mEventQueue->getScheduledFrameTime(); // Store the present time just before calling to the composition engine so we could notify // the scheduler. const auto presentTime = systemTime(); mCompositionEngine->present(refreshArgs); - mTimeStats->recordFrameDuration(mFrameStartTime, systemTime()); - // Reset the frame start time now that we've recorded this frame. - mFrameStartTime = 0; + mTimeStats->recordFrameDuration(frameTime, systemTime()); - mScheduler->onDisplayRefreshed(presentTime); + mScheduler->onPostComposition(presentTime); postFrame(); postComposition(); @@ -2177,17 +2138,12 @@ void SurfaceFlinger::onMessageRefresh() { mVisibleRegionsDirty = false; if (mCompositionEngine->needsAnotherUpdate()) { - signalLayerUpdate(); + scheduleCommit(FrameHint::kNone); } } -bool SurfaceFlinger::handleMessageInvalidate() { +void SurfaceFlinger::updateLayerGeometry() { ATRACE_CALL(); - // Send on commit callbacks - mTransactionCallbackInvoker.sendCallbacks(); - - bool refreshNeeded = handlePageFlip(); - if (mVisibleRegionsDirty) { computeLayerBounds(); @@ -2199,7 +2155,6 @@ bool SurfaceFlinger::handleMessageInvalidate() { invalidateLayerStack(layer, visibleReg); } mLayersPendingRefresh.clear(); - return refreshNeeded; } void SurfaceFlinger::updateCompositorTiming(const DisplayStatInfo& stats, nsecs_t compositeTime, @@ -3301,11 +3256,10 @@ void SurfaceFlinger::invalidateLayerStack(const sp& layer, const Re } } -bool SurfaceFlinger::handlePageFlip() { +bool SurfaceFlinger::latchBuffers() { ATRACE_CALL(); - ALOGV("handlePageFlip"); - nsecs_t latchTime = systemTime(); + const nsecs_t latchTime = systemTime(); bool visibleRegions = false; bool frameQueued = false; @@ -3374,7 +3328,7 @@ bool SurfaceFlinger::handlePageFlip() { // queued frame that shouldn't be displayed during this vsync period, wake // up during the next vsync period to check again. if (frameQueued && (mLayersWithQueuedFrames.empty() || !newDataLatched)) { - signalLayerUpdate(); + scheduleCommit(FrameHint::kNone); } // enter boot animation on first buffer latch @@ -3453,7 +3407,7 @@ uint32_t SurfaceFlinger::setTransactionFlags(uint32_t mask, TransactionSchedule const sp& applyToken) { const uint32_t old = mTransactionFlags.fetch_or(mask); modulateVsync(&VsyncModulator::setTransactionSchedule, schedule, applyToken); - if ((old & mask) == 0) scheduleInvalidate(FrameHint::kActive); + if ((old & mask) == 0) scheduleCommit(FrameHint::kActive); return old; } @@ -4572,7 +4526,7 @@ void SurfaceFlinger::setPowerModeInternal(const sp& display, hal: mVisibleRegionsDirty = true; mHasPoweredOff = true; - scheduleRefresh(FrameHint::kActive); + scheduleComposite(FrameHint::kActive); } else if (mode == hal::PowerMode::OFF) { // Turn off the display if (SurfaceFlinger::setSchedFifo(false) != NO_ERROR) { @@ -5430,8 +5384,8 @@ status_t SurfaceFlinger::onTransact(uint32_t code, const Parcel& data, Parcel* r } scheduleRepaint(); return NO_ERROR; - case 1004: // Force refresh ahead of next VSYNC. - scheduleRefresh(FrameHint::kActive); + case 1004: // Force composite ahead of next VSYNC. + scheduleComposite(FrameHint::kActive); return NO_ERROR; case 1005: { // Force commit ahead of next VSYNC. Mutex::Autolock lock(mStateLock); @@ -5439,8 +5393,8 @@ status_t SurfaceFlinger::onTransact(uint32_t code, const Parcel& data, Parcel* r eTraversalNeeded); return NO_ERROR; } - case 1006: // Force refresh immediately. - signalRefresh(); + case 1006: // Force composite immediately. + mEventQueue->scheduleComposite(); return NO_ERROR; case 1007: // Unused. return NAME_NOT_FOUND; @@ -5834,7 +5788,7 @@ void SurfaceFlinger::kernelTimerChanged(bool expired) { const bool timerExpired = mKernelIdleTimerEnabled && expired; if (display->onKernelTimerChanged(desiredModeId, timerExpired)) { - mEventQueue->invalidate(); + mEventQueue->scheduleCommit(); } })); } @@ -6265,12 +6219,6 @@ status_t SurfaceFlinger::captureScreenCommon( bool canCaptureBlackoutContent = hasCaptureBlackoutContentPermission(); static_cast(schedule([=, renderAreaFuture = std::move(renderAreaFuture)]() mutable { - if (mRefreshPending) { - ALOGW("Skipping screenshot for now"); - captureScreenCommon(std::move(renderAreaFuture), traverseLayers, buffer, regionSampling, - grayscale, captureListener); - return; - } ScreenCaptureResults captureResults; std::unique_ptr renderArea = renderAreaFuture.get(); if (!renderArea) { @@ -6617,6 +6565,10 @@ void SurfaceFlinger::onLayerDestroyed(Layer* layer) { } } +void SurfaceFlinger::onLayerUpdate() { + scheduleCommit(FrameHint::kActive); +} + // WARNING: ONLY CALL THIS FROM LAYER DTOR // Here we add children in the current state to offscreen layers and remove the // layer itself from the offscreen layer list. Since @@ -6941,16 +6893,12 @@ sp SurfaceFlinger::handleLayerCreatedLocked(const sp& handle) { return layer; } -void SurfaceFlinger::scheduleRegionSamplingThread() { - static_cast(schedule([&] { notifyRegionSamplingThread(); })); -} - -void SurfaceFlinger::notifyRegionSamplingThread() { +void SurfaceFlinger::sample() { if (!mLumaSampling || !mRegionSamplingThread) { return; } - mRegionSamplingThread->onCompositionComplete(mEventQueue->nextExpectedInvalidate()); + mRegionSamplingThread->onCompositionComplete(mEventQueue->getScheduledFrameTime()); } void SurfaceFlinger::onActiveDisplaySizeChanged(const sp& activeDisplay) { diff --git a/services/surfaceflinger/SurfaceFlinger.h b/services/surfaceflinger/SurfaceFlinger.h index 1217d6369b..43f7b36090 100644 --- a/services/surfaceflinger/SurfaceFlinger.h +++ b/services/surfaceflinger/SurfaceFlinger.h @@ -57,6 +57,7 @@ #include "Fps.h" #include "FrameTracker.h" #include "LayerVector.h" +#include "Scheduler/MessageQueue.h" #include "Scheduler/RefreshRateConfigs.h" #include "Scheduler/RefreshRateStats.h" #include "Scheduler/Scheduler.h" @@ -177,6 +178,7 @@ class SurfaceFlinger : public BnSurfaceComposer, public PriorityDumper, private IBinder::DeathRecipient, private HWC2::ComposerCallback, + private ICompositor, private ISchedulerCallback { public: struct SkipInitializationTag {}; @@ -287,11 +289,13 @@ public: [[nodiscard]] std::future schedule(F&&); // Schedule commit of transactions on the main thread ahead of the next VSYNC. - void scheduleInvalidate(FrameHint); - // As above, but also force refresh regardless if transactions were committed. - void scheduleRefresh(FrameHint) override; + void scheduleCommit(FrameHint); + // As above, but also force composite regardless if transactions were committed. + void scheduleComposite(FrameHint) override; // As above, but also force dirty geometry to repaint. void scheduleRepaint(); + // Schedule sampling independently from commit or composite. + void scheduleSample(); surfaceflinger::Factory& getFactory() { return mFactory; } @@ -305,11 +309,6 @@ public: // utility function to delete a texture on the main thread void deleteTextureAsync(uint32_t texture); - // called on the main thread by MessageQueue when an internal message - // is received - // TODO: this should be made accessible only to MessageQueue - void onMessageReceived(int32_t what, int64_t vsyncId, nsecs_t expectedVSyncTime); - renderengine::RenderEngine& getRenderEngine() const; bool authenticateSurfaceTextureLocked( @@ -317,6 +316,7 @@ public: void onLayerFirstRef(Layer*); void onLayerDestroyed(Layer*); + void onLayerUpdate(); void removeHierarchyFromOffscreenLayers(Layer* layer); void removeFromOffscreenLayers(Layer* layer); @@ -734,9 +734,6 @@ private: // Implements IBinder::DeathRecipient. void binderDied(const wp& who) override; - // Implements RefBase. - void onFirstRef() override; - // HWC2::ComposerCallback overrides: void onComposerHalVsync(hal::HWDisplayId, int64_t timestamp, std::optional) override; @@ -746,6 +743,19 @@ private: const hal::VsyncPeriodChangeTimeline&) override; void onComposerHalSeamlessPossible(hal::HWDisplayId) override; + // ICompositor overrides: + + // Commits transactions for layers and displays. Returns whether any state has been invalidated, + // i.e. whether a frame should be composited for each display. + bool commit(nsecs_t frameTime, int64_t vsyncId, nsecs_t expectedVsyncTime) override; + + // Composites a frame for each display. CompositionEngine performs GPU and/or HAL composition + // via RenderEngine and the Composer HAL, respectively. + void composite(nsecs_t frameTime) override; + + // Samples the composited frame via RegionSamplingThread. + void sample() override; + /* * ISchedulerCallback */ @@ -766,13 +776,6 @@ private: // Show spinner with refresh rate overlay bool mRefreshRateOverlaySpinner = false; - /* - * Message handling - */ - // Can only be called from the main thread or with mStateLock held - void signalLayerUpdate(); - void signalRefresh(); - // Called on the main thread in response to initializeDisplays() void onInitializeDisplays() REQUIRES(mStateLock); // Sets the desired active mode bit. It obtains the lock, and sets mDesiredActiveMode. @@ -797,10 +800,6 @@ private: const std::optional& policy, bool overridePolicy) EXCLUDES(mStateLock); - // Handle the INVALIDATE message queue event, latching new buffers and applying - // incoming transactions - void onMessageInvalidate(int64_t vsyncId, nsecs_t expectedVSyncTime); - // Returns whether transactions were committed. bool flushAndCommitTransactions() EXCLUDES(mStateLock); @@ -808,12 +807,10 @@ private: void commitTransactionsLocked(uint32_t transactionFlags) REQUIRES(mStateLock); void doCommitTransactions() REQUIRES(mStateLock); - // Handle the REFRESH message queue event, sending the current frame down to RenderEngine and - // the Composer HAL for presentation - void onMessageRefresh(); + // Returns whether a new buffer has been latched. + bool latchBuffers(); - // Returns whether a new buffer has been latched (see handlePageFlip()) - bool handleMessageInvalidate(); + void updateLayerGeometry(); void updateInputFlinger(); void notifyWindowInfos(); @@ -824,11 +821,6 @@ private: void updatePhaseConfiguration(const Fps&) REQUIRES(mStateLock); void setVsyncConfig(const VsyncModulator::VsyncConfig&, nsecs_t vsyncPeriod); - /* handlePageFlip - latch a new buffer if available and compute the dirty - * region. Returns whether a new buffer has been latched, i.e., whether it - * is necessary to perform a refresh during this vsync. - */ - bool handlePageFlip(); /* * Transactions @@ -1250,7 +1242,7 @@ private: bool mLayersRemoved = false; bool mLayersAdded = false; - std::atomic_bool mForceRefresh = false; + std::atomic_bool mMustComposite = false; std::atomic_bool mGeometryDirty = false; // constant members (no synchronization needed for access) @@ -1350,10 +1342,6 @@ private: mutable Mutex mDestroyedLayerLock; Vector mDestroyedLayers; - nsecs_t mRefreshStartTime = 0; - - std::atomic mRefreshPending = false; - // We maintain a pool of pre-generated texture names to hand out to avoid // layer creation needing to run on the main thread (which it would // otherwise need to do to access RenderEngine). @@ -1446,9 +1434,6 @@ private: Hwc2::impl::PowerAdvisor mPowerAdvisor; - // This should only be accessed on the main thread. - nsecs_t mFrameStartTime = 0; - void enableRefreshRateOverlay(bool enable) REQUIRES(mStateLock); // Flag used to set override desired display mode from backdoor @@ -1502,9 +1487,6 @@ private: std::atomic mActiveDisplayTransformHint; - void scheduleRegionSamplingThread(); - void notifyRegionSamplingThread(); - bool isRefreshRateOverlayEnabled() const REQUIRES(mStateLock) { return std::any_of(mDisplays.begin(), mDisplays.end(), [](std::pair, sp> display) { diff --git a/services/surfaceflinger/SurfaceFlingerDefaultFactory.cpp b/services/surfaceflinger/SurfaceFlingerDefaultFactory.cpp index 89d1c4d327..9a2f9107c3 100644 --- a/services/surfaceflinger/SurfaceFlingerDefaultFactory.cpp +++ b/services/surfaceflinger/SurfaceFlingerDefaultFactory.cpp @@ -51,8 +51,8 @@ std::unique_ptr DefaultFactory::createHWComposer(const std::string& return std::make_unique(serviceName); } -std::unique_ptr DefaultFactory::createMessageQueue() { - return std::make_unique(); +std::unique_ptr DefaultFactory::createMessageQueue(ICompositor& compositor) { + return std::make_unique(compositor); } std::unique_ptr DefaultFactory::createVsyncConfiguration( diff --git a/services/surfaceflinger/SurfaceFlingerDefaultFactory.h b/services/surfaceflinger/SurfaceFlingerDefaultFactory.h index b8bf2baa33..2be09ee788 100644 --- a/services/surfaceflinger/SurfaceFlingerDefaultFactory.h +++ b/services/surfaceflinger/SurfaceFlingerDefaultFactory.h @@ -27,7 +27,7 @@ public: virtual ~DefaultFactory(); std::unique_ptr createHWComposer(const std::string& serviceName) override; - std::unique_ptr createMessageQueue() override; + std::unique_ptr createMessageQueue(ICompositor&) override; std::unique_ptr createVsyncConfiguration( Fps currentRefreshRate) override; std::unique_ptr createScheduler( diff --git a/services/surfaceflinger/SurfaceFlingerFactory.h b/services/surfaceflinger/SurfaceFlingerFactory.h index 13c95ddd15..bca533b794 100644 --- a/services/surfaceflinger/SurfaceFlingerFactory.h +++ b/services/surfaceflinger/SurfaceFlingerFactory.h @@ -31,11 +31,11 @@ namespace android { typedef int32_t PixelFormat; class BufferQueueLayer; -class BufferStateLayer; class BufferLayerConsumer; -class EffectLayer; +class BufferStateLayer; class ContainerLayer; class DisplayDevice; +class EffectLayer; class FrameTracer; class GraphicBuffer; class HWComposer; @@ -50,6 +50,7 @@ class SurfaceInterceptor; class TimeStats; struct DisplayDeviceCreationArgs; +struct ICompositor; struct ISchedulerCallback; struct LayerCreationArgs; @@ -76,7 +77,7 @@ class NativeWindowSurface; class Factory { public: virtual std::unique_ptr createHWComposer(const std::string& serviceName) = 0; - virtual std::unique_ptr createMessageQueue() = 0; + virtual std::unique_ptr createMessageQueue(ICompositor&) = 0; virtual std::unique_ptr createVsyncConfiguration( Fps currentRefreshRate) = 0; virtual std::unique_ptr createScheduler( diff --git a/services/surfaceflinger/tests/unittests/CompositionTest.cpp b/services/surfaceflinger/tests/unittests/CompositionTest.cpp index 5135ff952f..a0812912d4 100644 --- a/services/surfaceflinger/tests/unittests/CompositionTest.cpp +++ b/services/surfaceflinger/tests/unittests/CompositionTest.cpp @@ -202,8 +202,7 @@ void CompositionTest::displayRefreshCompositionDirtyGeometry() { // -------------------------------------------------------------------- // Invocation - mFlinger.onMessageReceived(MessageQueue::INVALIDATE); - mFlinger.onMessageReceived(MessageQueue::REFRESH); + mFlinger.commitAndComposite(); LayerCase::cleanup(this); } @@ -215,8 +214,7 @@ void CompositionTest::displayRefreshCompositionDirtyFrame() { // -------------------------------------------------------------------- // Invocation - mFlinger.onMessageReceived(MessageQueue::INVALIDATE); - mFlinger.onMessageReceived(MessageQueue::REFRESH); + mFlinger.commitAndComposite(); LayerCase::cleanup(this); } @@ -537,7 +535,7 @@ struct BaseLayerProperties { ASSERT_EQ(NO_ERROR, err); Mock::VerifyAndClear(test->mRenderEngine); - EXPECT_CALL(*test->mMessageQueue, invalidate()).Times(1); + EXPECT_CALL(*test->mMessageQueue, scheduleCommit()).Times(1); enqueueBuffer(test, layer); Mock::VerifyAndClearExpectations(test->mMessageQueue); @@ -883,7 +881,7 @@ struct BaseLayerVariant { test->mFlinger.mutableDrawingState().layersSortedByZ.clear(); // Layer should be unregistered with scheduler. - test->mFlinger.onMessageReceived(MessageQueue::INVALIDATE); + test->mFlinger.commit(); EXPECT_EQ(0, test->mFlinger.scheduler()->layerHistorySize()); } }; diff --git a/services/surfaceflinger/tests/unittests/MessageQueueTest.cpp b/services/surfaceflinger/tests/unittests/MessageQueueTest.cpp index dbd51fed78..17d1dd6b09 100644 --- a/services/surfaceflinger/tests/unittests/MessageQueueTest.cpp +++ b/services/surfaceflinger/tests/unittests/MessageQueueTest.cpp @@ -31,62 +31,51 @@ using namespace testing; using CallbackToken = scheduler::VSyncDispatch::CallbackToken; +struct NoOpCompositor final : ICompositor { + bool commit(nsecs_t, int64_t, nsecs_t) override { return false; } + void composite(nsecs_t) override {} + void sample() override {} +} gNoOpCompositor; + class TestableMessageQueue : public impl::MessageQueue { -public: - class MockHandler : public MessageQueue::Handler { - public: - explicit MockHandler(MessageQueue& queue) : MessageQueue::Handler(queue) {} - ~MockHandler() override = default; - MOCK_METHOD2(dispatchInvalidate, void(int64_t vsyncId, nsecs_t expectedVSyncTimestamp)); + struct MockHandler : MessageQueue::Handler { + using MessageQueue::Handler::Handler; + + MOCK_METHOD(void, dispatchCommit, (int64_t, nsecs_t), (override)); }; - TestableMessageQueue() = default; - ~TestableMessageQueue() override = default; + explicit TestableMessageQueue(sp handler) + : impl::MessageQueue(gNoOpCompositor, handler), mHandler(std::move(handler)) {} - void initHandler(const sp& handler) { mHandler = handler; } +public: + TestableMessageQueue() : TestableMessageQueue(sp::make(*this)) {} - void triggerVsyncCallback(nsecs_t vsyncTime, nsecs_t targetWakeupTime, nsecs_t readyTime) { - vsyncCallback(vsyncTime, targetWakeupTime, readyTime); - } -}; + using impl::MessageQueue::vsyncCallback; -class MockVSyncDispatch : public scheduler::VSyncDispatch { -public: - MockVSyncDispatch() = default; - ~MockVSyncDispatch() override = default; + const sp mHandler; +}; +struct MockVSyncDispatch : scheduler::VSyncDispatch { MOCK_METHOD2(registerCallback, - CallbackToken(std::function const&, std::string)); + CallbackToken(const std::function&, std::string)); MOCK_METHOD1(unregisterCallback, void(CallbackToken)); MOCK_METHOD2(schedule, scheduler::ScheduleResult(CallbackToken, ScheduleTiming)); MOCK_METHOD1(cancel, scheduler::CancelResult(CallbackToken token)); MOCK_CONST_METHOD1(dump, void(std::string&)); }; -class MockTokenManager : public frametimeline::TokenManager { -public: - MockTokenManager() = default; - ~MockTokenManager() override = default; - +struct MockTokenManager : frametimeline::TokenManager { MOCK_METHOD1(generateTokenForPredictions, int64_t(frametimeline::TimelineItem&& prediction)); MOCK_CONST_METHOD1(getPredictionsForToken, std::optional(int64_t)); }; -class MessageQueueTest : public testing::Test { -public: - MessageQueueTest() = default; - ~MessageQueueTest() override = default; - +struct MessageQueueTest : testing::Test { void SetUp() override { - EXPECT_NO_FATAL_FAILURE(mEventQueue.initHandler(mHandler)); - EXPECT_CALL(mVSyncDispatch, registerCallback(_, "sf")).WillOnce(Return(mCallbackToken)); EXPECT_NO_FATAL_FAILURE(mEventQueue.initVsync(mVSyncDispatch, mTokenManager, mDuration)); EXPECT_CALL(mVSyncDispatch, unregisterCallback(mCallbackToken)).Times(1); } - sp mHandler = - new TestableMessageQueue::MockHandler(mEventQueue); MockVSyncDispatch mVSyncDispatch; MockTokenManager mTokenManager; TestableMessageQueue mEventQueue; @@ -100,45 +89,49 @@ namespace { /* ------------------------------------------------------------------------ * Test cases */ -TEST_F(MessageQueueTest, invalidate) { +TEST_F(MessageQueueTest, commit) { const auto timing = scheduler::VSyncDispatch::ScheduleTiming{.workDuration = mDuration.count(), .readyDuration = 0, .earliestVsync = 0}; - EXPECT_FALSE(mEventQueue.nextExpectedInvalidate().has_value()); + EXPECT_FALSE(mEventQueue.getScheduledFrameTime()); EXPECT_CALL(mVSyncDispatch, schedule(mCallbackToken, timing)).WillOnce(Return(1234)); - EXPECT_NO_FATAL_FAILURE(mEventQueue.invalidate()); - EXPECT_TRUE(mEventQueue.nextExpectedInvalidate().has_value()); - EXPECT_EQ(1234, mEventQueue.nextExpectedInvalidate().value().time_since_epoch().count()); + EXPECT_NO_FATAL_FAILURE(mEventQueue.scheduleCommit()); + + ASSERT_TRUE(mEventQueue.getScheduledFrameTime()); + EXPECT_EQ(1234, mEventQueue.getScheduledFrameTime()->time_since_epoch().count()); } -TEST_F(MessageQueueTest, invalidateTwice) { +TEST_F(MessageQueueTest, commitTwice) { InSequence s; const auto timing = scheduler::VSyncDispatch::ScheduleTiming{.workDuration = mDuration.count(), .readyDuration = 0, .earliestVsync = 0}; EXPECT_CALL(mVSyncDispatch, schedule(mCallbackToken, timing)).WillOnce(Return(1234)); - EXPECT_NO_FATAL_FAILURE(mEventQueue.invalidate()); - EXPECT_TRUE(mEventQueue.nextExpectedInvalidate().has_value()); - EXPECT_EQ(1234, mEventQueue.nextExpectedInvalidate().value().time_since_epoch().count()); + EXPECT_NO_FATAL_FAILURE(mEventQueue.scheduleCommit()); + + ASSERT_TRUE(mEventQueue.getScheduledFrameTime()); + EXPECT_EQ(1234, mEventQueue.getScheduledFrameTime()->time_since_epoch().count()); EXPECT_CALL(mVSyncDispatch, schedule(mCallbackToken, timing)).WillOnce(Return(4567)); - EXPECT_NO_FATAL_FAILURE(mEventQueue.invalidate()); - EXPECT_TRUE(mEventQueue.nextExpectedInvalidate().has_value()); - EXPECT_EQ(4567, mEventQueue.nextExpectedInvalidate().value().time_since_epoch().count()); + EXPECT_NO_FATAL_FAILURE(mEventQueue.scheduleCommit()); + + ASSERT_TRUE(mEventQueue.getScheduledFrameTime()); + EXPECT_EQ(4567, mEventQueue.getScheduledFrameTime()->time_since_epoch().count()); } -TEST_F(MessageQueueTest, invalidateTwiceWithCallback) { +TEST_F(MessageQueueTest, commitTwiceWithCallback) { InSequence s; const auto timing = scheduler::VSyncDispatch::ScheduleTiming{.workDuration = mDuration.count(), .readyDuration = 0, .earliestVsync = 0}; EXPECT_CALL(mVSyncDispatch, schedule(mCallbackToken, timing)).WillOnce(Return(1234)); - EXPECT_NO_FATAL_FAILURE(mEventQueue.invalidate()); - EXPECT_TRUE(mEventQueue.nextExpectedInvalidate().has_value()); - EXPECT_EQ(1234, mEventQueue.nextExpectedInvalidate().value().time_since_epoch().count()); + EXPECT_NO_FATAL_FAILURE(mEventQueue.scheduleCommit()); + + ASSERT_TRUE(mEventQueue.getScheduledFrameTime()); + EXPECT_EQ(1234, mEventQueue.getScheduledFrameTime()->time_since_epoch().count()); const auto startTime = 100; const auto endTime = startTime + mDuration.count(); @@ -148,10 +141,10 @@ TEST_F(MessageQueueTest, invalidateTwiceWithCallback) { generateTokenForPredictions( frametimeline::TimelineItem(startTime, endTime, presentTime))) .WillOnce(Return(vsyncId)); - EXPECT_CALL(*mHandler, dispatchInvalidate(vsyncId, presentTime)).Times(1); - EXPECT_NO_FATAL_FAILURE(mEventQueue.triggerVsyncCallback(presentTime, startTime, endTime)); + EXPECT_CALL(*mEventQueue.mHandler, dispatchCommit(vsyncId, presentTime)).Times(1); + EXPECT_NO_FATAL_FAILURE(mEventQueue.vsyncCallback(presentTime, startTime, endTime)); - EXPECT_FALSE(mEventQueue.nextExpectedInvalidate().has_value()); + EXPECT_FALSE(mEventQueue.getScheduledFrameTime()); const auto timingAfterCallback = scheduler::VSyncDispatch::ScheduleTiming{.workDuration = mDuration.count(), @@ -159,10 +152,10 @@ TEST_F(MessageQueueTest, invalidateTwiceWithCallback) { .earliestVsync = presentTime}; EXPECT_CALL(mVSyncDispatch, schedule(mCallbackToken, timingAfterCallback)).WillOnce(Return(0)); - EXPECT_NO_FATAL_FAILURE(mEventQueue.invalidate()); + EXPECT_NO_FATAL_FAILURE(mEventQueue.scheduleCommit()); } -TEST_F(MessageQueueTest, invalidateWithDurationChange) { +TEST_F(MessageQueueTest, commitWithDurationChange) { EXPECT_NO_FATAL_FAILURE(mEventQueue.setDuration(mDifferentDuration)); const auto timing = @@ -171,7 +164,7 @@ TEST_F(MessageQueueTest, invalidateWithDurationChange) { .earliestVsync = 0}; EXPECT_CALL(mVSyncDispatch, schedule(mCallbackToken, timing)).WillOnce(Return(0)); - EXPECT_NO_FATAL_FAILURE(mEventQueue.invalidate()); + EXPECT_NO_FATAL_FAILURE(mEventQueue.scheduleCommit()); } } // namespace diff --git a/services/surfaceflinger/tests/unittests/SetFrameRateTest.cpp b/services/surfaceflinger/tests/unittests/SetFrameRateTest.cpp index 84fa1e290a..6c3b2fdc6c 100644 --- a/services/surfaceflinger/tests/unittests/SetFrameRateTest.cpp +++ b/services/surfaceflinger/tests/unittests/SetFrameRateTest.cpp @@ -176,7 +176,7 @@ namespace { * Test cases */ TEST_P(SetFrameRateTest, SetAndGet) { - EXPECT_CALL(*mMessageQueue, invalidate()).Times(1); + EXPECT_CALL(*mMessageQueue, scheduleCommit()).Times(1); const auto& layerFactory = GetParam(); @@ -187,7 +187,7 @@ TEST_P(SetFrameRateTest, SetAndGet) { } TEST_P(SetFrameRateTest, SetAndGetParent) { - EXPECT_CALL(*mMessageQueue, invalidate()).Times(1); + EXPECT_CALL(*mMessageQueue, scheduleCommit()).Times(1); const auto& layerFactory = GetParam(); @@ -212,7 +212,7 @@ TEST_P(SetFrameRateTest, SetAndGetParent) { } TEST_P(SetFrameRateTest, SetAndGetParentAllVote) { - EXPECT_CALL(*mMessageQueue, invalidate()).Times(1); + EXPECT_CALL(*mMessageQueue, scheduleCommit()).Times(1); const auto& layerFactory = GetParam(); @@ -251,7 +251,7 @@ TEST_P(SetFrameRateTest, SetAndGetParentAllVote) { } TEST_P(SetFrameRateTest, SetAndGetChild) { - EXPECT_CALL(*mMessageQueue, invalidate()).Times(1); + EXPECT_CALL(*mMessageQueue, scheduleCommit()).Times(1); const auto& layerFactory = GetParam(); @@ -276,7 +276,7 @@ TEST_P(SetFrameRateTest, SetAndGetChild) { } TEST_P(SetFrameRateTest, SetAndGetChildAllVote) { - EXPECT_CALL(*mMessageQueue, invalidate()).Times(1); + EXPECT_CALL(*mMessageQueue, scheduleCommit()).Times(1); const auto& layerFactory = GetParam(); @@ -315,7 +315,7 @@ TEST_P(SetFrameRateTest, SetAndGetChildAllVote) { } TEST_P(SetFrameRateTest, SetAndGetChildAddAfterVote) { - EXPECT_CALL(*mMessageQueue, invalidate()).Times(1); + EXPECT_CALL(*mMessageQueue, scheduleCommit()).Times(1); const auto& layerFactory = GetParam(); @@ -345,7 +345,7 @@ TEST_P(SetFrameRateTest, SetAndGetChildAddAfterVote) { } TEST_P(SetFrameRateTest, SetAndGetChildRemoveAfterVote) { - EXPECT_CALL(*mMessageQueue, invalidate()).Times(1); + EXPECT_CALL(*mMessageQueue, scheduleCommit()).Times(1); const auto& layerFactory = GetParam(); @@ -376,7 +376,7 @@ TEST_P(SetFrameRateTest, SetAndGetChildRemoveAfterVote) { } TEST_P(SetFrameRateTest, SetAndGetParentNotInTree) { - EXPECT_CALL(*mMessageQueue, invalidate()).Times(1); + EXPECT_CALL(*mMessageQueue, scheduleCommit()).Times(1); const auto& layerFactory = GetParam(); @@ -475,7 +475,7 @@ TEST_P(SetFrameRateTest, SetOnParentActivatesTree) { } TEST_P(SetFrameRateTest, addChildForParentWithTreeVote) { - EXPECT_CALL(*mMessageQueue, invalidate()).Times(1); + EXPECT_CALL(*mMessageQueue, scheduleCommit()).Times(1); const auto& layerFactory = GetParam(); diff --git a/services/surfaceflinger/tests/unittests/SurfaceFlinger_CreateDisplayTest.cpp b/services/surfaceflinger/tests/unittests/SurfaceFlinger_CreateDisplayTest.cpp index 2362a31827..8c3034178f 100644 --- a/services/surfaceflinger/tests/unittests/SurfaceFlinger_CreateDisplayTest.cpp +++ b/services/surfaceflinger/tests/unittests/SurfaceFlinger_CreateDisplayTest.cpp @@ -51,8 +51,8 @@ TEST_F(CreateDisplayTest, createDisplaySetsCurrentStateForNonsecureDisplay) { // -------------------------------------------------------------------- // Cleanup conditions - // Destroying the display invalidates the display state. - EXPECT_CALL(*mMessageQueue, invalidate()).Times(1); + // Creating the display commits a display transaction. + EXPECT_CALL(*mMessageQueue, scheduleCommit()).Times(1); } TEST_F(CreateDisplayTest, createDisplaySetsCurrentStateForSecureDisplay) { @@ -86,9 +86,9 @@ TEST_F(CreateDisplayTest, createDisplaySetsCurrentStateForSecureDisplay) { // -------------------------------------------------------------------- // Cleanup conditions - // Destroying the display invalidates the display state. - EXPECT_CALL(*mMessageQueue, invalidate()).Times(1); + // Creating the display commits a display transaction. + EXPECT_CALL(*mMessageQueue, scheduleCommit()).Times(1); } } // namespace -} // namespace android \ No newline at end of file +} // namespace android diff --git a/services/surfaceflinger/tests/unittests/SurfaceFlinger_DestroyDisplayTest.cpp b/services/surfaceflinger/tests/unittests/SurfaceFlinger_DestroyDisplayTest.cpp index e2be074fc4..7087fb6568 100644 --- a/services/surfaceflinger/tests/unittests/SurfaceFlinger_DestroyDisplayTest.cpp +++ b/services/surfaceflinger/tests/unittests/SurfaceFlinger_DestroyDisplayTest.cpp @@ -40,8 +40,8 @@ TEST_F(DestroyDisplayTest, destroyDisplayClearsCurrentStateForDisplay) { // The call should notify the interceptor that a display was created. EXPECT_CALL(*mSurfaceInterceptor, saveDisplayDeletion(_)).Times(1); - // Destroying the display invalidates the display state. - EXPECT_CALL(*mMessageQueue, invalidate()).Times(1); + // Destroying the display commits a display transaction. + EXPECT_CALL(*mMessageQueue, scheduleCommit()).Times(1); // -------------------------------------------------------------------- // Invocation diff --git a/services/surfaceflinger/tests/unittests/SurfaceFlinger_HotplugTest.cpp b/services/surfaceflinger/tests/unittests/SurfaceFlinger_HotplugTest.cpp index bd89397ef6..29ff0cd90b 100644 --- a/services/surfaceflinger/tests/unittests/SurfaceFlinger_HotplugTest.cpp +++ b/services/surfaceflinger/tests/unittests/SurfaceFlinger_HotplugTest.cpp @@ -38,9 +38,8 @@ TEST_F(HotplugTest, enqueuesEventsForDisplayTransaction) { // -------------------------------------------------------------------- // Call Expectations - // We expect invalidate() to be invoked once to trigger display transaction - // processing. - EXPECT_CALL(*mMessageQueue, invalidate()).Times(1); + // We expect a scheduled commit for the display transaction. + EXPECT_CALL(*mMessageQueue, scheduleCommit()).Times(1); // -------------------------------------------------------------------- // Invocation @@ -86,9 +85,8 @@ TEST_F(HotplugTest, processesEnqueuedEventsIfCalledOnMainThread) { // -------------------------------------------------------------------- // Call Expectations - // We expect invalidate() to be invoked once to trigger display transaction - // processing. - EXPECT_CALL(*mMessageQueue, invalidate()).Times(1); + // We expect a scheduled commit for the display transaction. + EXPECT_CALL(*mMessageQueue, scheduleCommit()).Times(1); // -------------------------------------------------------------------- // Invocation diff --git a/services/surfaceflinger/tests/unittests/SurfaceFlinger_OnInitializeDisplaysTest.cpp b/services/surfaceflinger/tests/unittests/SurfaceFlinger_OnInitializeDisplaysTest.cpp index bafa910270..e1b44cf549 100644 --- a/services/surfaceflinger/tests/unittests/SurfaceFlinger_OnInitializeDisplaysTest.cpp +++ b/services/surfaceflinger/tests/unittests/SurfaceFlinger_OnInitializeDisplaysTest.cpp @@ -46,9 +46,8 @@ TEST_F(OnInitializeDisplaysTest, onInitializeDisplaysSetsUpPrimaryDisplay) { // We expect a call to get the active display config. Case::Display::setupHwcGetActiveConfigCallExpectations(this); - // We expect invalidate() to be invoked once to trigger display transaction - // processing. - EXPECT_CALL(*mMessageQueue, invalidate()).Times(1); + // We expect a scheduled commit for the display transaction. + EXPECT_CALL(*mMessageQueue, scheduleCommit()).Times(1); EXPECT_CALL(*mVSyncTracker, nextAnticipatedVSyncTimeFrom(_)).WillRepeatedly(Return(0)); diff --git a/services/surfaceflinger/tests/unittests/SurfaceFlinger_SetPowerModeInternalTest.cpp b/services/surfaceflinger/tests/unittests/SurfaceFlinger_SetPowerModeInternalTest.cpp index 65024202b8..e55721dd6e 100644 --- a/services/surfaceflinger/tests/unittests/SurfaceFlinger_SetPowerModeInternalTest.cpp +++ b/services/surfaceflinger/tests/unittests/SurfaceFlinger_SetPowerModeInternalTest.cpp @@ -268,7 +268,7 @@ struct DisplayPowerCase { } static void setupRepaintEverythingCallExpectations(DisplayTransactionTest* test) { - EXPECT_CALL(*test->mMessageQueue, invalidate()).Times(1); + EXPECT_CALL(*test->mMessageQueue, scheduleCommit()).Times(1); } static void setupSurfaceInterceptorCallExpectations(DisplayTransactionTest* test, diff --git a/services/surfaceflinger/tests/unittests/TestableSurfaceFlinger.h b/services/surfaceflinger/tests/unittests/TestableSurfaceFlinger.h index 7072439cea..de1caded50 100644 --- a/services/surfaceflinger/tests/unittests/TestableSurfaceFlinger.h +++ b/services/surfaceflinger/tests/unittests/TestableSurfaceFlinger.h @@ -73,8 +73,8 @@ public: return nullptr; } - std::unique_ptr createMessageQueue() override { - return std::make_unique(); + std::unique_ptr createMessageQueue(ICompositor& compositor) override { + return std::make_unique(compositor); } std::unique_ptr createVsyncConfiguration( @@ -296,6 +296,16 @@ public: * Forwarding for functions being tested */ + nsecs_t commit() { + constexpr int64_t kVsyncId = 123; + const nsecs_t now = systemTime(); + const nsecs_t expectedVsyncTime = now + 10'000'000; + mFlinger->commit(now, kVsyncId, expectedVsyncTime); + return now; + } + + void commitAndComposite() { mFlinger->composite(commit()); } + auto createDisplay(const String8& displayName, bool secure) { return mFlinger->createDisplay(displayName, secure); } @@ -343,10 +353,6 @@ public: return mFlinger->setPowerModeInternal(display, mode); } - auto onMessageReceived(int32_t what) { - return mFlinger->onMessageReceived(what, /*vsyncId=*/0, systemTime()); - } - auto renderScreenImplLocked(const RenderArea& renderArea, SurfaceFlinger::TraverseLayersFunction traverseLayers, const std::shared_ptr& buffer, @@ -761,7 +767,7 @@ public: }; private: - void scheduleRefresh(FrameHint) override {} + void scheduleComposite(FrameHint) override {} void setVsyncEnabled(bool) override {} void changeRefreshRate(const Scheduler::RefreshRate&, Scheduler::ModeEvent) override {} void kernelTimerChanged(bool) override {} diff --git a/services/surfaceflinger/tests/unittests/TransactionApplicationTest.cpp b/services/surfaceflinger/tests/unittests/TransactionApplicationTest.cpp index 1a50427b93..d8e68b8966 100644 --- a/services/surfaceflinger/tests/unittests/TransactionApplicationTest.cpp +++ b/services/surfaceflinger/tests/unittests/TransactionApplicationTest.cpp @@ -126,8 +126,7 @@ public: void NotPlacedOnTransactionQueue(uint32_t flags, bool syncInputWindows) { ASSERT_EQ(0u, mFlinger.getTransactionQueue().size()); - // called in SurfaceFlinger::signalTransaction - EXPECT_CALL(*mMessageQueue, invalidate()).Times(1); + EXPECT_CALL(*mMessageQueue, scheduleCommit()).Times(1); TransactionInfo transaction; setupSingle(transaction, flags, syncInputWindows, /*desiredPresentTime*/ systemTime(), /*isAutoTimestamp*/ true, @@ -157,8 +156,7 @@ public: void PlaceOnTransactionQueue(uint32_t flags, bool syncInputWindows) { ASSERT_EQ(0u, mFlinger.getTransactionQueue().size()); - // called in SurfaceFlinger::signalTransaction - EXPECT_CALL(*mMessageQueue, invalidate()).Times(1); + EXPECT_CALL(*mMessageQueue, scheduleCommit()).Times(1); // first check will see desired present time has not passed, // but afterwards it will look like the desired present time has passed @@ -187,12 +185,11 @@ public: void BlockedByPriorTransaction(uint32_t flags, bool syncInputWindows) { ASSERT_EQ(0u, mFlinger.getTransactionQueue().size()); - // called in SurfaceFlinger::signalTransaction nsecs_t time = systemTime(); if (!syncInputWindows) { - EXPECT_CALL(*mMessageQueue, invalidate()).Times(2); + EXPECT_CALL(*mMessageQueue, scheduleCommit()).Times(2); } else { - EXPECT_CALL(*mMessageQueue, invalidate()).Times(1); + EXPECT_CALL(*mMessageQueue, scheduleCommit()).Times(1); } // transaction that should go on the pending thread TransactionInfo transactionA; @@ -255,8 +252,7 @@ public: TEST_F(TransactionApplicationTest, Flush_RemovesFromQueue) { ASSERT_EQ(0u, mFlinger.getTransactionQueue().size()); - // called in SurfaceFlinger::signalTransaction - EXPECT_CALL(*mMessageQueue, invalidate()).Times(1); + EXPECT_CALL(*mMessageQueue, scheduleCommit()).Times(1); TransactionInfo transactionA; // transaction to go on pending queue setupSingle(transactionA, /*flags*/ 0, /*syncInputWindows*/ false, diff --git a/services/surfaceflinger/tests/unittests/mock/MockMessageQueue.h b/services/surfaceflinger/tests/unittests/mock/MockMessageQueue.h index 0e7b320787..d68433760d 100644 --- a/services/surfaceflinger/tests/unittests/mock/MockMessageQueue.h +++ b/services/surfaceflinger/tests/unittests/mock/MockMessageQueue.h @@ -29,17 +29,18 @@ public: MessageQueue(); ~MessageQueue() override; - MOCK_METHOD1(init, void(const sp&)); MOCK_METHOD1(setInjector, void(sp)); MOCK_METHOD0(waitMessage, void()); MOCK_METHOD1(postMessage, void(sp&&)); - MOCK_METHOD0(invalidate, void()); - MOCK_METHOD0(refresh, void()); MOCK_METHOD3(initVsync, void(scheduler::VSyncDispatch&, frametimeline::TokenManager&, std::chrono::nanoseconds)); MOCK_METHOD1(setDuration, void(std::chrono::nanoseconds workDuration)); - MOCK_METHOD0(nextExpectedInvalidate, std::optional()); + + MOCK_METHOD(void, scheduleCommit, (), (override)); + MOCK_METHOD(void, scheduleComposite, (), (override)); + + MOCK_METHOD(std::optional, getScheduledFrameTime, (), (const, override)); }; } // namespace android::mock diff --git a/services/surfaceflinger/tests/unittests/mock/MockSchedulerCallback.h b/services/surfaceflinger/tests/unittests/mock/MockSchedulerCallback.h index 291559f2f9..e241dc903f 100644 --- a/services/surfaceflinger/tests/unittests/mock/MockSchedulerCallback.h +++ b/services/surfaceflinger/tests/unittests/mock/MockSchedulerCallback.h @@ -23,7 +23,7 @@ namespace android::mock { struct SchedulerCallback final : ISchedulerCallback { - MOCK_METHOD(void, scheduleRefresh, (FrameHint), (override)); + MOCK_METHOD(void, scheduleComposite, (FrameHint), (override)); MOCK_METHOD1(setVsyncEnabled, void(bool)); MOCK_METHOD2(changeRefreshRate, void(const scheduler::RefreshRateConfigs::RefreshRate&, @@ -33,7 +33,7 @@ struct SchedulerCallback final : ISchedulerCallback { }; struct NoOpSchedulerCallback final : ISchedulerCallback { - void scheduleRefresh(FrameHint) override {} + void scheduleComposite(FrameHint) override {} void setVsyncEnabled(bool) override {} void changeRefreshRate(const scheduler::RefreshRateConfigs::RefreshRate&, scheduler::RefreshRateConfigEvent) override {} -- cgit v1.2.3-59-g8ed1b From 403a05bc88c5aa6671adcf4214c2a531f77ac2a4 Mon Sep 17 00:00:00 2001 From: Sally Qi Date: Fri, 20 Aug 2021 16:28:35 -0700 Subject: Second Patch for async RenderEngine - pass a vector of instead of a vector of pointers to drawLayers function to ensure lifecycle safety. - capture all local variables to call drawLayerInternals in the render engine thread to avoid of pointers being invalidated if it takes long time to pop mFunctions calls. - change renderScreenImplLocked return type as a shared_future object to unblock SF main thread for screen capture events. - block region sampling thread only when SF main thread hasn't completed capture screen event. Bug: 180657548 Test: SurfaceFlinger_test, android.hardware.graphics.composer@2.2-vts, libcompositionengine_test, librenderengine_test, libsurfaceflinger_unittest pass Change-Id: I615f2927d30524988fb12df22fe331e7217c3058 --- libs/renderengine/RenderEngine.cpp | 2 +- libs/renderengine/gl/GLESRenderEngine.cpp | 66 +++++------ libs/renderengine/gl/GLESRenderEngine.h | 2 +- .../include/renderengine/RenderEngine.h | 4 +- .../include/renderengine/mock/RenderEngine.h | 4 +- libs/renderengine/skia/Cache.cpp | 16 +-- libs/renderengine/skia/SkiaGLRenderEngine.cpp | 113 +++++++++--------- libs/renderengine/skia/SkiaGLRenderEngine.h | 7 +- libs/renderengine/skia/SkiaRenderEngine.h | 2 +- libs/renderengine/tests/RenderEngineTest.cpp | 125 +++++++++---------- .../tests/RenderEngineThreadedTest.cpp | 7 +- .../renderengine/threaded/RenderEngineThreaded.cpp | 11 +- libs/renderengine/threaded/RenderEngineThreaded.h | 4 +- services/surfaceflinger/BufferQueueLayer.cpp | 4 +- services/surfaceflinger/BufferQueueLayer.h | 3 +- services/surfaceflinger/BufferStateLayer.cpp | 88 +++----------- services/surfaceflinger/BufferStateLayer.h | 8 +- .../include/compositionengine/LayerFE.h | 4 +- .../include/compositionengine/mock/LayerFE.h | 2 +- .../CompositionEngine/src/Output.cpp | 23 ++-- .../CompositionEngine/src/planner/CachedSet.cpp | 17 +-- .../CompositionEngine/tests/OutputTest.cpp | 87 +++++++++----- .../tests/planner/CachedSetTest.cpp | 84 ++++++------- services/surfaceflinger/Layer.cpp | 3 +- services/surfaceflinger/Layer.h | 3 +- services/surfaceflinger/RegionSamplingThread.cpp | 11 +- services/surfaceflinger/SurfaceFlinger.cpp | 132 +++++++++++++-------- services/surfaceflinger/SurfaceFlinger.h | 22 ++-- .../surfaceflinger/TransactionCallbackInvoker.cpp | 32 +++++ .../surfaceflinger/TransactionCallbackInvoker.h | 6 +- .../tests/unittests/CompositionTest.cpp | 78 ++++++------ 31 files changed, 513 insertions(+), 457 deletions(-) (limited to 'services/surfaceflinger/BufferQueueLayer.cpp') diff --git a/libs/renderengine/RenderEngine.cpp b/libs/renderengine/RenderEngine.cpp index 2174df5515..a9ea690a7c 100644 --- a/libs/renderengine/RenderEngine.cpp +++ b/libs/renderengine/RenderEngine.cpp @@ -96,7 +96,7 @@ void RenderEngine::validateOutputBufferUsage(const sp& buffer) { } std::future RenderEngine::drawLayers( - const DisplaySettings& display, const std::vector& layers, + const DisplaySettings& display, const std::vector& layers, const std::shared_ptr& buffer, const bool useFramebufferCache, base::unique_fd&& bufferFence) { const auto resultPromise = std::make_shared>(); diff --git a/libs/renderengine/gl/GLESRenderEngine.cpp b/libs/renderengine/gl/GLESRenderEngine.cpp index 2375cb7bf1..22dd86698b 100644 --- a/libs/renderengine/gl/GLESRenderEngine.cpp +++ b/libs/renderengine/gl/GLESRenderEngine.cpp @@ -1080,7 +1080,7 @@ EGLImageKHR GLESRenderEngine::createFramebufferImageIfNeeded(ANativeWindowBuffer void GLESRenderEngine::drawLayersInternal( const std::shared_ptr>&& resultPromise, - const DisplaySettings& display, const std::vector& layers, + const DisplaySettings& display, const std::vector& layers, const std::shared_ptr& buffer, const bool useFramebufferCache, base::unique_fd&& bufferFence) { ATRACE_CALL(); @@ -1110,10 +1110,10 @@ void GLESRenderEngine::drawLayersInternal( std::unique_ptr fbo; // Gathering layers that requested blur, we'll need them to decide when to render to an // offscreen buffer, and when to render to the native buffer. - std::deque blurLayers; + std::deque blurLayers; if (CC_LIKELY(mBlurFilter != nullptr)) { - for (auto layer : layers) { - if (layer->backgroundBlurRadius > 0) { + for (const auto& layer : layers) { + if (layer.backgroundBlurRadius > 0) { blurLayers.push_back(layer); } } @@ -1137,7 +1137,7 @@ void GLESRenderEngine::drawLayersInternal( } else { setViewportAndProjection(display.physicalDisplay, display.clip); auto status = - mBlurFilter->setAsDrawTarget(display, blurLayers.front()->backgroundBlurRadius); + mBlurFilter->setAsDrawTarget(display, blurLayers.front().backgroundBlurRadius); if (status != NO_ERROR) { ALOGE("Failed to prepare blur filter! Aborting GPU composition for buffer (%p).", buffer->getBuffer()->handle); @@ -1167,7 +1167,7 @@ void GLESRenderEngine::drawLayersInternal( .setTexCoords(2 /* size */) .setCropCoords(2 /* size */) .build(); - for (auto const layer : layers) { + for (const auto& layer : layers) { if (blurLayers.size() > 0 && blurLayers.front() == layer) { blurLayers.pop_front(); @@ -1193,7 +1193,7 @@ void GLESRenderEngine::drawLayersInternal( // There's still something else to blur, so let's keep rendering to our FBO // instead of to the display. status = mBlurFilter->setAsDrawTarget(display, - blurLayers.front()->backgroundBlurRadius); + blurLayers.front().backgroundBlurRadius); } if (status != NO_ERROR) { ALOGE("Failed to bind framebuffer! Aborting GPU composition for buffer (%p).", @@ -1214,42 +1214,42 @@ void GLESRenderEngine::drawLayersInternal( } // Ensure luminance is at least 100 nits to avoid div-by-zero - const float maxLuminance = std::max(100.f, layer->source.buffer.maxLuminanceNits); + const float maxLuminance = std::max(100.f, layer.source.buffer.maxLuminanceNits); mState.maxMasteringLuminance = maxLuminance; mState.maxContentLuminance = maxLuminance; - mState.projectionMatrix = projectionMatrix * layer->geometry.positionTransform; + mState.projectionMatrix = projectionMatrix * layer.geometry.positionTransform; - const FloatRect bounds = layer->geometry.boundaries; + const FloatRect bounds = layer.geometry.boundaries; Mesh::VertexArray position(mesh.getPositionArray()); position[0] = vec2(bounds.left, bounds.top); position[1] = vec2(bounds.left, bounds.bottom); position[2] = vec2(bounds.right, bounds.bottom); position[3] = vec2(bounds.right, bounds.top); - setupLayerCropping(*layer, mesh); - setColorTransform(layer->colorTransform); + setupLayerCropping(layer, mesh); + setColorTransform(layer.colorTransform); bool usePremultipliedAlpha = true; bool disableTexture = true; bool isOpaque = false; - if (layer->source.buffer.buffer != nullptr) { + if (layer.source.buffer.buffer != nullptr) { disableTexture = false; - isOpaque = layer->source.buffer.isOpaque; + isOpaque = layer.source.buffer.isOpaque; - sp gBuf = layer->source.buffer.buffer->getBuffer(); + sp gBuf = layer.source.buffer.buffer->getBuffer(); validateInputBufferUsage(gBuf); - bindExternalTextureBuffer(layer->source.buffer.textureName, gBuf, - layer->source.buffer.fence); + bindExternalTextureBuffer(layer.source.buffer.textureName, gBuf, + layer.source.buffer.fence); - usePremultipliedAlpha = layer->source.buffer.usePremultipliedAlpha; - Texture texture(Texture::TEXTURE_EXTERNAL, layer->source.buffer.textureName); - mat4 texMatrix = layer->source.buffer.textureTransform; + usePremultipliedAlpha = layer.source.buffer.usePremultipliedAlpha; + Texture texture(Texture::TEXTURE_EXTERNAL, layer.source.buffer.textureName); + mat4 texMatrix = layer.source.buffer.textureTransform; texture.setMatrix(texMatrix.asArray()); - texture.setFiltering(layer->source.buffer.useTextureFiltering); + texture.setFiltering(layer.source.buffer.useTextureFiltering); texture.setDimensions(gBuf->getWidth(), gBuf->getHeight()); - setSourceY410BT2020(layer->source.buffer.isY410BT2020); + setSourceY410BT2020(layer.source.buffer.isY410BT2020); renderengine::Mesh::VertexArray texCoords(mesh.getTexCoordArray()); texCoords[0] = vec2(0.0, 0.0); @@ -1264,32 +1264,32 @@ void GLESRenderEngine::drawLayersInternal( } } - const half3 solidColor = layer->source.solidColor; - const half4 color = half4(solidColor.r, solidColor.g, solidColor.b, layer->alpha); + const half3 solidColor = layer.source.solidColor; + const half4 color = half4(solidColor.r, solidColor.g, solidColor.b, layer.alpha); // Buffer sources will have a black solid color ignored in the shader, // so in that scenario the solid color passed here is arbitrary. setupLayerBlending(usePremultipliedAlpha, isOpaque, disableTexture, color, - layer->geometry.roundedCornersRadius); - if (layer->disableBlending) { + layer.geometry.roundedCornersRadius); + if (layer.disableBlending) { glDisable(GL_BLEND); } - setSourceDataSpace(layer->sourceDataspace); + setSourceDataSpace(layer.sourceDataspace); - if (layer->shadow.length > 0.0f) { - handleShadow(layer->geometry.boundaries, layer->geometry.roundedCornersRadius, - layer->shadow); + if (layer.shadow.length > 0.0f) { + handleShadow(layer.geometry.boundaries, layer.geometry.roundedCornersRadius, + layer.shadow); } // We only want to do a special handling for rounded corners when having rounded corners // is the only reason it needs to turn on blending, otherwise, we handle it like the // usual way since it needs to turn on blending anyway. - else if (layer->geometry.roundedCornersRadius > 0.0 && color.a >= 1.0f && isOpaque) { - handleRoundedCorners(display, *layer, mesh); + else if (layer.geometry.roundedCornersRadius > 0.0 && color.a >= 1.0f && isOpaque) { + handleRoundedCorners(display, layer, mesh); } else { drawMesh(mesh); } // Cleanup if there's a buffer source - if (layer->source.buffer.buffer != nullptr) { + if (layer.source.buffer.buffer != nullptr) { disableBlending(); setSourceY410BT2020(false); disableTexturing(); diff --git a/libs/renderengine/gl/GLESRenderEngine.h b/libs/renderengine/gl/GLESRenderEngine.h index c4adfdf752..1d7c2cafb5 100644 --- a/libs/renderengine/gl/GLESRenderEngine.h +++ b/libs/renderengine/gl/GLESRenderEngine.h @@ -104,7 +104,7 @@ protected: bool canSkipPostRenderCleanup() const override; void drawLayersInternal(const std::shared_ptr>&& resultPromise, const DisplaySettings& display, - const std::vector& layers, + const std::vector& layers, const std::shared_ptr& buffer, const bool useFramebufferCache, base::unique_fd&& bufferFence) override; diff --git a/libs/renderengine/include/renderengine/RenderEngine.h b/libs/renderengine/include/renderengine/RenderEngine.h index 701c1f2071..b9cc6485e5 100644 --- a/libs/renderengine/include/renderengine/RenderEngine.h +++ b/libs/renderengine/include/renderengine/RenderEngine.h @@ -160,7 +160,7 @@ public: // @return A future object of RenderEngineResult struct indicating whether // drawing was successful in async mode. virtual std::future drawLayers( - const DisplaySettings& display, const std::vector& layers, + const DisplaySettings& display, const std::vector& layers, const std::shared_ptr& buffer, const bool useFramebufferCache, base::unique_fd&& bufferFence); @@ -231,7 +231,7 @@ protected: virtual void drawLayersInternal( const std::shared_ptr>&& resultPromise, - const DisplaySettings& display, const std::vector& layers, + const DisplaySettings& display, const std::vector& layers, const std::shared_ptr& buffer, const bool useFramebufferCache, base::unique_fd&& bufferFence) = 0; }; diff --git a/libs/renderengine/include/renderengine/mock/RenderEngine.h b/libs/renderengine/include/renderengine/mock/RenderEngine.h index a7e6809223..248bd652c0 100644 --- a/libs/renderengine/include/renderengine/mock/RenderEngine.h +++ b/libs/renderengine/include/renderengine/mock/RenderEngine.h @@ -49,12 +49,12 @@ public: MOCK_CONST_METHOD0(canSkipPostRenderCleanup, bool()); MOCK_METHOD5(drawLayers, std::future(const DisplaySettings&, - const std::vector&, + const std::vector&, const std::shared_ptr&, const bool, base::unique_fd&&)); MOCK_METHOD6(drawLayersInternal, void(const std::shared_ptr>&&, - const DisplaySettings&, const std::vector&, + const DisplaySettings&, const std::vector&, const std::shared_ptr&, const bool, base::unique_fd&&)); MOCK_METHOD0(cleanFramebufferCache, void()); MOCK_METHOD0(getContextPriority, int()); diff --git a/libs/renderengine/skia/Cache.cpp b/libs/renderengine/skia/Cache.cpp index c4fa1bb091..b18a872836 100644 --- a/libs/renderengine/skia/Cache.cpp +++ b/libs/renderengine/skia/Cache.cpp @@ -95,7 +95,7 @@ static void drawShadowLayers(SkiaRenderEngine* renderengine, const DisplaySettin .alpha = 1, }; - auto layers = std::vector{&layer, &caster}; + auto layers = std::vector{layer, caster}; // Four combinations of settings are used (two transforms here, and drawShadowLayers is // called with two different destination data spaces) They're all rounded rect. // Three of these are cache misses that generate new shaders. @@ -140,7 +140,7 @@ static void drawImageLayers(SkiaRenderEngine* renderengine, const DisplaySetting }}, }; - auto layers = std::vector{&layer}; + auto layers = std::vector{layer}; for (auto dataspace : {kDestDataSpace, kOtherDataSpace}) { layer.sourceDataspace = dataspace; // Cache shaders for both rects and round rects. @@ -176,7 +176,7 @@ static void drawSolidLayers(SkiaRenderEngine* renderengine, const DisplaySetting .alpha = 0.5, }; - auto layers = std::vector{&layer}; + auto layers = std::vector{layer}; for (auto transform : {mat4(), kScaleAndTranslate}) { layer.geometry.positionTransform = transform; for (float roundedCornersRadius : {0.0f, 50.f}) { @@ -201,7 +201,7 @@ static void drawBlurLayers(SkiaRenderEngine* renderengine, const DisplaySettings .skipContentDraw = true, }; - auto layers = std::vector{&layer}; + auto layers = std::vector{layer}; // Different blur code is invoked for radii less and greater than 30 pixels for (int radius : {9, 60}) { layer.backgroundBlurRadius = radius; @@ -242,7 +242,7 @@ static void drawClippedLayers(SkiaRenderEngine* renderengine, const DisplaySetti }, }; - auto layers = std::vector{&layer}; + auto layers = std::vector{layer}; for (auto pixelSource : {bufferSource, bufferOpaque, colorSource}) { layer.source = pixelSource; for (auto dataspace : {kDestDataSpace, kOtherDataSpace}) { @@ -289,7 +289,7 @@ static void drawPIPImageLayer(SkiaRenderEngine* renderengine, const DisplaySetti }; - auto layers = std::vector{&layer}; + auto layers = std::vector{layer}; renderengine->drawLayers(display, layers, dstTexture, kUseFrameBufferCache, base::unique_fd()); } @@ -317,7 +317,7 @@ static void drawHolePunchLayer(SkiaRenderEngine* renderengine, const DisplaySett }; - auto layers = std::vector{&layer}; + auto layers = std::vector{layer}; renderengine->drawLayers(display, layers, dstTexture, kUseFrameBufferCache, base::unique_fd()); } @@ -429,7 +429,7 @@ void Cache::primeShaderCache(SkiaRenderEngine* renderengine) { LayerSettings layer{ .source = PixelSource{.solidColor = half3(0.f, 0.f, 0.f)}, }; - auto layers = std::vector{&layer}; + auto layers = std::vector{layer}; // call get() to make it synchronous renderengine ->drawLayers(display, layers, dstTexture, kUseFrameBufferCache, base::unique_fd()) diff --git a/libs/renderengine/skia/SkiaGLRenderEngine.cpp b/libs/renderengine/skia/SkiaGLRenderEngine.cpp index cb686a643a..d5ec774e9c 100644 --- a/libs/renderengine/skia/SkiaGLRenderEngine.cpp +++ b/libs/renderengine/skia/SkiaGLRenderEngine.cpp @@ -610,17 +610,18 @@ private: AutoBackendTexture::CleanupManager& mMgr; }; -sk_sp SkiaGLRenderEngine::createRuntimeEffectShader( - sk_sp shader, - const LayerSettings* layer, const DisplaySettings& display, bool undoPremultipliedAlpha, - bool requiresLinearEffect) { - const auto stretchEffect = layer->stretchEffect; +sk_sp SkiaGLRenderEngine::createRuntimeEffectShader(sk_sp shader, + const LayerSettings& layer, + const DisplaySettings& display, + bool undoPremultipliedAlpha, + bool requiresLinearEffect) { + const auto stretchEffect = layer.stretchEffect; // The given surface will be stretched by HWUI via matrix transformation // which gets similar results for most surfaces // Determine later on if we need to leverage the stertch shader within // surface flinger if (stretchEffect.hasEffect()) { - const auto targetBuffer = layer->source.buffer.buffer; + const auto targetBuffer = layer.source.buffer.buffer; const auto graphicBuffer = targetBuffer ? targetBuffer->getBuffer() : nullptr; if (graphicBuffer && shader) { shader = mStretchShaderFactory.createSkShader(shader, stretchEffect); @@ -629,7 +630,7 @@ sk_sp SkiaGLRenderEngine::createRuntimeEffectShader( if (requiresLinearEffect) { const ui::Dataspace inputDataspace = - mUseColorManagement ? layer->sourceDataspace : ui::Dataspace::V0_SRGB_LINEAR; + mUseColorManagement ? layer.sourceDataspace : ui::Dataspace::V0_SRGB_LINEAR; const ui::Dataspace outputDataspace = mUseColorManagement ? display.outputDataspace : ui::Dataspace::V0_SRGB_LINEAR; @@ -645,13 +646,13 @@ sk_sp SkiaGLRenderEngine::createRuntimeEffectShader( } else { runtimeEffect = effectIter->second; } - float maxLuminance = layer->source.buffer.maxLuminanceNits; + float maxLuminance = layer.source.buffer.maxLuminanceNits; // If the buffer doesn't have a max luminance, treat it as SDR & use the display's SDR // white point if (maxLuminance <= 0.f) { maxLuminance = display.sdrWhitePointNits; } - return createLinearEffectShader(shader, effect, runtimeEffect, layer->colorTransform, + return createLinearEffectShader(shader, effect, runtimeEffect, layer.colorTransform, display.maxLuminance, maxLuminance); } return shader; @@ -729,7 +730,7 @@ static SkRRect getBlurRRect(const BlurRegion& region) { void SkiaGLRenderEngine::drawLayersInternal( const std::shared_ptr>&& resultPromise, - const DisplaySettings& display, const std::vector& layers, + const DisplaySettings& display, const std::vector& layers, const std::shared_ptr& buffer, const bool /*useFramebufferCache*/, base::unique_fd&& bufferFence) { ATRACE_NAME("SkiaGL::drawLayers"); @@ -801,11 +802,11 @@ void SkiaGLRenderEngine::drawLayersInternal( if (!layerHasBlur(layer, ctModifiesAlpha)) { continue; } - if (layer->backgroundBlurRadius > 0 && - layer->backgroundBlurRadius < BlurFilter::kMaxCrossFadeRadius) { + if (layer.backgroundBlurRadius > 0 && + layer.backgroundBlurRadius < BlurFilter::kMaxCrossFadeRadius) { requiresCompositionLayer = true; } - for (auto region : layer->blurRegions) { + for (auto region : layer.blurRegions) { if (region.blurRadius < BlurFilter::kMaxCrossFadeRadius) { requiresCompositionLayer = true; } @@ -813,7 +814,7 @@ void SkiaGLRenderEngine::drawLayersInternal( if (requiresCompositionLayer) { activeSurface = dstSurface->makeSurface(dstSurface->imageInfo()); canvas = mCapture->tryOffscreenCapture(activeSurface.get(), &offscreenCaptureState); - blurCompositionLayer = layer; + blurCompositionLayer = &layer; break; } } @@ -825,11 +826,11 @@ void SkiaGLRenderEngine::drawLayersInternal( initCanvas(canvas, display); for (const auto& layer : layers) { - ATRACE_FORMAT("DrawLayer: %s", layer->name.c_str()); + ATRACE_FORMAT("DrawLayer: %s", layer.name.c_str()); if (kPrintLayerSettings) { std::stringstream ls; - PrintTo(*layer, &ls); + PrintTo(layer, &ls); auto debugs = ls.str(); int pos = 0; while (pos < debugs.size()) { @@ -839,7 +840,7 @@ void SkiaGLRenderEngine::drawLayersInternal( } sk_sp blurInput; - if (blurCompositionLayer == layer) { + if (blurCompositionLayer == &layer) { LOG_ALWAYS_FATAL_IF(activeSurface == dstSurface); LOG_ALWAYS_FATAL_IF(canvas == dstCanvas); @@ -878,17 +879,17 @@ void SkiaGLRenderEngine::drawLayersInternal( if (CC_UNLIKELY(mCapture->isCaptureRunning())) { // Record the name of the layer if the capture is running. std::stringstream layerSettings; - PrintTo(*layer, &layerSettings); + PrintTo(layer, &layerSettings); // Store the LayerSettings in additional information. - canvas->drawAnnotation(SkRect::MakeEmpty(), layer->name.c_str(), + canvas->drawAnnotation(SkRect::MakeEmpty(), layer.name.c_str(), SkData::MakeWithCString(layerSettings.str().c_str())); } // Layers have a local transform that should be applied to them - canvas->concat(getSkM44(layer->geometry.positionTransform).asM33()); + canvas->concat(getSkM44(layer.geometry.positionTransform).asM33()); const auto [bounds, roundRectClip] = - getBoundsAndClip(layer->geometry.boundaries, layer->geometry.roundedCornersCrop, - layer->geometry.roundedCornersRadius); + getBoundsAndClip(layer.geometry.boundaries, layer.geometry.roundedCornersCrop, + layer.geometry.roundedCornersRadius); if (mBlurFilter && layerHasBlur(layer, ctModifiesAlpha)) { std::unordered_map> cachedBlurs; @@ -909,20 +910,19 @@ void SkiaGLRenderEngine::drawLayersInternal( // TODO(b/182216890): Filter out empty layers earlier if (blurRect.width() > 0 && blurRect.height() > 0) { - if (layer->backgroundBlurRadius > 0) { + if (layer.backgroundBlurRadius > 0) { ATRACE_NAME("BackgroundBlur"); - auto blurredImage = - mBlurFilter->generate(grContext, layer->backgroundBlurRadius, blurInput, - blurRect); + auto blurredImage = mBlurFilter->generate(grContext, layer.backgroundBlurRadius, + blurInput, blurRect); - cachedBlurs[layer->backgroundBlurRadius] = blurredImage; + cachedBlurs[layer.backgroundBlurRadius] = blurredImage; - mBlurFilter->drawBlurRegion(canvas, bounds, layer->backgroundBlurRadius, 1.0f, + mBlurFilter->drawBlurRegion(canvas, bounds, layer.backgroundBlurRadius, 1.0f, blurRect, blurredImage, blurInput); } - canvas->concat(getSkM44(layer->blurRegionTransform).asM33()); - for (auto region : layer->blurRegions) { + canvas->concat(getSkM44(layer.blurRegionTransform).asM33()); + for (auto region : layer.blurRegions) { if (cachedBlurs[region.blurRadius] == nullptr) { ATRACE_NAME("BlurRegion"); cachedBlurs[region.blurRadius] = @@ -937,19 +937,18 @@ void SkiaGLRenderEngine::drawLayersInternal( } } - if (layer->shadow.length > 0) { + if (layer.shadow.length > 0) { // This would require a new parameter/flag to SkShadowUtils::DrawShadow - LOG_ALWAYS_FATAL_IF(layer->disableBlending, "Cannot disableBlending with a shadow"); + LOG_ALWAYS_FATAL_IF(layer.disableBlending, "Cannot disableBlending with a shadow"); SkRRect shadowBounds, shadowClip; - if (layer->geometry.boundaries == layer->shadow.boundaries) { + if (layer.geometry.boundaries == layer.shadow.boundaries) { shadowBounds = bounds; shadowClip = roundRectClip; } else { std::tie(shadowBounds, shadowClip) = - getBoundsAndClip(layer->shadow.boundaries, - layer->geometry.roundedCornersCrop, - layer->geometry.roundedCornersRadius); + getBoundsAndClip(layer.shadow.boundaries, layer.geometry.roundedCornersCrop, + layer.geometry.roundedCornersRadius); } // Technically, if bounds is a rect and roundRectClip is not empty, @@ -960,18 +959,18 @@ void SkiaGLRenderEngine::drawLayersInternal( // looks more like the intent. const auto& rrect = shadowBounds.isRect() && !shadowClip.isEmpty() ? shadowClip : shadowBounds; - drawShadow(canvas, rrect, layer->shadow); + drawShadow(canvas, rrect, layer.shadow); } - const bool requiresLinearEffect = layer->colorTransform != mat4() || + const bool requiresLinearEffect = layer.colorTransform != mat4() || (mUseColorManagement && - needsToneMapping(layer->sourceDataspace, display.outputDataspace)) || + needsToneMapping(layer.sourceDataspace, display.outputDataspace)) || (display.sdrWhitePointNits > 0.f && display.sdrWhitePointNits != display.maxLuminance); // quick abort from drawing the remaining portion of the layer - if (layer->skipContentDraw || - (layer->alpha == 0 && !requiresLinearEffect && !layer->disableBlending && + if (layer.skipContentDraw || + (layer.alpha == 0 && !requiresLinearEffect && !layer.disableBlending && (!displayColorTransform || displayColorTransform->isAlphaUnchanged()))) { continue; } @@ -981,13 +980,13 @@ void SkiaGLRenderEngine::drawLayersInternal( // management is a no-op. const ui::Dataspace layerDataspace = (!mUseColorManagement || requiresLinearEffect) ? dstDataspace - : layer->sourceDataspace; + : layer.sourceDataspace; SkPaint paint; - if (layer->source.buffer.buffer) { + if (layer.source.buffer.buffer) { ATRACE_NAME("DrawImage"); - validateInputBufferUsage(layer->source.buffer.buffer->getBuffer()); - const auto& item = layer->source.buffer; + validateInputBufferUsage(layer.source.buffer.buffer->getBuffer()); + const auto& item = layer.source.buffer; std::shared_ptr imageTextureRef = nullptr; if (const auto& iter = cache.find(item.buffer->getBuffer()->getId()); @@ -1006,8 +1005,8 @@ void SkiaGLRenderEngine::drawLayersInternal( // if the layer's buffer has a fence, then we must must respect the fence prior to using // the buffer. - if (layer->source.buffer.fence != nullptr) { - waitFence(layer->source.buffer.fence->get()); + if (layer.source.buffer.fence != nullptr) { + waitFence(layer.source.buffer.fence->get()); } // isOpaque means we need to ignore the alpha in the image, @@ -1051,7 +1050,7 @@ void SkiaGLRenderEngine::drawLayersInternal( sk_sp shader; - if (layer->source.buffer.useTextureFiltering) { + if (layer.source.buffer.useTextureFiltering) { shader = image->makeShader(SkTileMode::kClamp, SkTileMode::kClamp, SkSamplingOptions( {SkFilterMode::kLinear, SkMipmapMode::kNone}), @@ -1069,21 +1068,21 @@ void SkiaGLRenderEngine::drawLayersInternal( paint.setShader(createRuntimeEffectShader(shader, layer, display, !item.isOpaque && item.usePremultipliedAlpha, requiresLinearEffect)); - paint.setAlphaf(layer->alpha); + paint.setAlphaf(layer.alpha); } else { ATRACE_NAME("DrawColor"); - const auto color = layer->source.solidColor; + const auto color = layer.source.solidColor; sk_sp shader = SkShaders::Color(SkColor4f{.fR = color.r, .fG = color.g, .fB = color.b, - .fA = layer->alpha}, + .fA = layer.alpha}, toSkColorSpace(layerDataspace)); paint.setShader(createRuntimeEffectShader(shader, layer, display, /* undoPremultipliedAlpha */ false, requiresLinearEffect)); } - if (layer->disableBlending) { + if (layer.disableBlending) { paint.setBlendMode(SkBlendMode::kSrc); } @@ -1251,13 +1250,13 @@ inline std::pair SkiaGLRenderEngine::getBoundsAndClip(const Fl return {SkRRect::MakeRect(bounds), clip}; } -inline bool SkiaGLRenderEngine::layerHasBlur(const LayerSettings* layer, +inline bool SkiaGLRenderEngine::layerHasBlur(const LayerSettings& layer, bool colorTransformModifiesAlpha) { - if (layer->backgroundBlurRadius > 0 || layer->blurRegions.size()) { + if (layer.backgroundBlurRadius > 0 || layer.blurRegions.size()) { // return false if the content is opaque and would therefore occlude the blur - const bool opaqueContent = !layer->source.buffer.buffer || layer->source.buffer.isOpaque; - const bool opaqueAlpha = layer->alpha == 1.0f && !colorTransformModifiesAlpha; - return layer->skipContentDraw || !(opaqueContent && opaqueAlpha); + const bool opaqueContent = !layer.source.buffer.buffer || layer.source.buffer.isOpaque; + const bool opaqueAlpha = layer.alpha == 1.0f && !colorTransformModifiesAlpha; + return layer.skipContentDraw || !(opaqueContent && opaqueAlpha); } return false; } diff --git a/libs/renderengine/skia/SkiaGLRenderEngine.h b/libs/renderengine/skia/SkiaGLRenderEngine.h index e010c35c13..74ce6513e9 100644 --- a/libs/renderengine/skia/SkiaGLRenderEngine.h +++ b/libs/renderengine/skia/SkiaGLRenderEngine.h @@ -74,7 +74,7 @@ protected: bool canSkipPostRenderCleanup() const override; void drawLayersInternal(const std::shared_ptr>&& resultPromise, const DisplaySettings& display, - const std::vector& layers, + const std::vector& layers, const std::shared_ptr& buffer, const bool useFramebufferCache, base::unique_fd&& bufferFence) override; @@ -92,7 +92,7 @@ private: inline SkRect getSkRect(const Rect& layer); inline std::pair getBoundsAndClip(const FloatRect& bounds, const FloatRect& crop, float cornerRadius); - inline bool layerHasBlur(const LayerSettings* layer, bool colorTransformModifiesAlpha); + inline bool layerHasBlur(const LayerSettings& layer, bool colorTransformModifiesAlpha); inline SkColor getSkColor(const vec4& color); inline SkM44 getSkM44(const mat4& matrix); inline SkPoint3 getSkPoint3(const vec3& vector); @@ -108,8 +108,7 @@ private: const ShadowSettings& shadowSettings); // If requiresLinearEffect is true or the layer has a stretchEffect a new shader is returned. // Otherwise it returns the input shader. - sk_sp createRuntimeEffectShader(sk_sp shader, - const LayerSettings* layer, + sk_sp createRuntimeEffectShader(sk_sp shader, const LayerSettings& layer, const DisplaySettings& display, bool undoPremultipliedAlpha, bool requiresLinearEffect); diff --git a/libs/renderengine/skia/SkiaRenderEngine.h b/libs/renderengine/skia/SkiaRenderEngine.h index f61653b940..eb65e83324 100644 --- a/libs/renderengine/skia/SkiaRenderEngine.h +++ b/libs/renderengine/skia/SkiaRenderEngine.h @@ -55,7 +55,7 @@ protected: virtual void drawLayersInternal( const std::shared_ptr>&& resultPromise, - const DisplaySettings& display, const std::vector& layers, + const DisplaySettings& display, const std::vector& layers, const std::shared_ptr& buffer, const bool useFramebufferCache, base::unique_fd&& bufferFence) override { resultPromise->set_value({NO_ERROR, base::unique_fd()}); diff --git a/libs/renderengine/tests/RenderEngineTest.cpp b/libs/renderengine/tests/RenderEngineTest.cpp index 694bda65d4..c2c05f41b7 100644 --- a/libs/renderengine/tests/RenderEngineTest.cpp +++ b/libs/renderengine/tests/RenderEngineTest.cpp @@ -417,10 +417,11 @@ public: DEFAULT_DISPLAY_HEIGHT - DEFAULT_DISPLAY_OFFSET); } - void invokeDraw(renderengine::DisplaySettings settings, - std::vector layers) { + void invokeDraw(const renderengine::DisplaySettings& settings, + const std::vector& layers) { std::future result = mRE->drawLayers(settings, layers, mBuffer, true, base::unique_fd()); + ASSERT_TRUE(result.valid()); auto [status, fence] = result.get(); @@ -436,7 +437,7 @@ public: void drawEmptyLayers() { renderengine::DisplaySettings settings; - std::vector layers; + std::vector layers; invokeDraw(settings, layers); } @@ -629,7 +630,7 @@ void RenderEngineTest::fillBuffer(half r, half g, half b, half a) { settings.clip = fullscreenRect(); settings.outputDataspace = ui::Dataspace::V0_SRGB_LINEAR; - std::vector layers; + std::vector layers; renderengine::LayerSettings layer; layer.sourceDataspace = ui::Dataspace::V0_SRGB_LINEAR; @@ -637,7 +638,7 @@ void RenderEngineTest::fillBuffer(half r, half g, half b, half a) { SourceVariant::fillColor(layer, r, g, b, this); layer.alpha = a; - layers.push_back(&layer); + layers.push_back(layer); invokeDraw(settings, layers); } @@ -673,7 +674,7 @@ void RenderEngineTest::fillRedOffsetBuffer() { settings.physicalDisplay = offsetRect(); settings.clip = offsetRectAtZero(); - std::vector layers; + std::vector layers; renderengine::LayerSettings layer; layer.sourceDataspace = ui::Dataspace::V0_SRGB_LINEAR; @@ -681,7 +682,7 @@ void RenderEngineTest::fillRedOffsetBuffer() { SourceVariant::fillColor(layer, 1.0f, 0.0f, 0.0f, this); layer.alpha = 1.0f; - layers.push_back(&layer); + layers.push_back(layer); invokeDraw(settings, layers); } @@ -708,7 +709,7 @@ void RenderEngineTest::fillBufferCheckers(uint32_t orientationFlag) { settings.clip = Rect(2, 2); settings.orientation = orientationFlag; - std::vector layers; + std::vector layers; renderengine::LayerSettings layerOne; layerOne.sourceDataspace = ui::Dataspace::V0_SRGB_LINEAR; @@ -731,9 +732,9 @@ void RenderEngineTest::fillBufferCheckers(uint32_t orientationFlag) { SourceVariant::fillColor(layerThree, 0.0f, 0.0f, 1.0f, this); layerThree.alpha = 1.0f; - layers.push_back(&layerOne); - layers.push_back(&layerTwo); - layers.push_back(&layerThree); + layers.push_back(layerOne); + layers.push_back(layerTwo); + layers.push_back(layerThree); invokeDraw(settings, layers); } @@ -810,7 +811,7 @@ void RenderEngineTest::fillBufferWithLayerTransform() { settings.clip = Rect(2, 2); settings.outputDataspace = ui::Dataspace::V0_SRGB_LINEAR; - std::vector layers; + std::vector layers; renderengine::LayerSettings layer; layer.sourceDataspace = ui::Dataspace::V0_SRGB_LINEAR; @@ -821,7 +822,7 @@ void RenderEngineTest::fillBufferWithLayerTransform() { layer.source.solidColor = half3(1.0f, 0.0f, 0.0f); layer.alpha = 1.0f; - layers.push_back(&layer); + layers.push_back(layer); invokeDraw(settings, layers); } @@ -843,7 +844,7 @@ void RenderEngineTest::fillBufferWithColorTransform() { settings.clip = Rect(1, 1); settings.outputDataspace = ui::Dataspace::V0_SRGB_LINEAR; - std::vector layers; + std::vector layers; renderengine::LayerSettings layer; layer.sourceDataspace = ui::Dataspace::V0_SRGB_LINEAR; @@ -860,7 +861,7 @@ void RenderEngineTest::fillBufferWithColorTransform() { layer.alpha = 1.0f; layer.geometry.boundaries = Rect(1, 1).toFloatRect(); - layers.push_back(&layer); + layers.push_back(layer); invokeDraw(settings, layers); } @@ -877,7 +878,7 @@ void RenderEngineTest::fillBufferWithColorTransformZeroLayerAlpha() { settings.physicalDisplay = fullscreenRect(); settings.clip = Rect(1, 1); - std::vector layers; + std::vector layers; renderengine::LayerSettings layer; layer.geometry.boundaries = Rect(1, 1).toFloatRect(); @@ -890,7 +891,7 @@ void RenderEngineTest::fillBufferWithColorTransformZeroLayerAlpha() { layer.geometry.boundaries = Rect(1, 1).toFloatRect(); - layers.push_back(&layer); + layers.push_back(layer); invokeDraw(settings, layers); } @@ -908,7 +909,7 @@ void RenderEngineTest::fillRedBufferWithRoundedCorners() { settings.clip = fullscreenRect(); settings.outputDataspace = ui::Dataspace::V0_SRGB_LINEAR; - std::vector layers; + std::vector layers; renderengine::LayerSettings layer; layer.sourceDataspace = ui::Dataspace::V0_SRGB_LINEAR; @@ -918,7 +919,7 @@ void RenderEngineTest::fillRedBufferWithRoundedCorners() { SourceVariant::fillColor(layer, 1.0f, 0.0f, 0.0f, this); layer.alpha = 1.0f; - layers.push_back(&layer); + layers.push_back(layer); invokeDraw(settings, layers); } @@ -949,14 +950,14 @@ void RenderEngineTest::fillBufferAndBlurBackground() { settings.physicalDisplay = fullscreenRect(); settings.clip = fullscreenRect(); - std::vector layers; + std::vector layers; renderengine::LayerSettings backgroundLayer; backgroundLayer.sourceDataspace = ui::Dataspace::V0_SRGB_LINEAR; backgroundLayer.geometry.boundaries = fullscreenRect().toFloatRect(); SourceVariant::fillColor(backgroundLayer, 0.0f, 1.0f, 0.0f, this); backgroundLayer.alpha = 1.0f; - layers.push_back(&backgroundLayer); + layers.emplace_back(backgroundLayer); renderengine::LayerSettings leftLayer; leftLayer.sourceDataspace = ui::Dataspace::V0_SRGB_LINEAR; @@ -964,7 +965,7 @@ void RenderEngineTest::fillBufferAndBlurBackground() { Rect(DEFAULT_DISPLAY_WIDTH / 2, DEFAULT_DISPLAY_HEIGHT).toFloatRect(); SourceVariant::fillColor(leftLayer, 1.0f, 0.0f, 0.0f, this); leftLayer.alpha = 1.0f; - layers.push_back(&leftLayer); + layers.emplace_back(leftLayer); renderengine::LayerSettings blurLayer; blurLayer.sourceDataspace = ui::Dataspace::V0_SRGB_LINEAR; @@ -972,7 +973,7 @@ void RenderEngineTest::fillBufferAndBlurBackground() { blurLayer.backgroundBlurRadius = blurRadius; SourceVariant::fillColor(blurLayer, 0.0f, 0.0f, 1.0f, this); blurLayer.alpha = 0; - layers.push_back(&blurLayer); + layers.emplace_back(blurLayer); invokeDraw(settings, layers); @@ -994,14 +995,14 @@ void RenderEngineTest::fillSmallLayerAndBlurBackground() { settings.physicalDisplay = fullscreenRect(); settings.clip = fullscreenRect(); - std::vector layers; + std::vector layers; renderengine::LayerSettings backgroundLayer; backgroundLayer.sourceDataspace = ui::Dataspace::V0_SRGB_LINEAR; backgroundLayer.geometry.boundaries = fullscreenRect().toFloatRect(); SourceVariant::fillColor(backgroundLayer, 1.0f, 0.0f, 0.0f, this); backgroundLayer.alpha = 1.0f; - layers.push_back(&backgroundLayer); + layers.push_back(backgroundLayer); renderengine::LayerSettings blurLayer; blurLayer.sourceDataspace = ui::Dataspace::V0_SRGB_LINEAR; @@ -1009,7 +1010,7 @@ void RenderEngineTest::fillSmallLayerAndBlurBackground() { blurLayer.backgroundBlurRadius = blurRadius; SourceVariant::fillColor(blurLayer, 0.0f, 0.0f, 1.0f, this); blurLayer.alpha = 0; - layers.push_back(&blurLayer); + layers.push_back(blurLayer); invokeDraw(settings, layers); @@ -1026,7 +1027,7 @@ void RenderEngineTest::overlayCorners() { settings.clip = fullscreenRect(); settings.outputDataspace = ui::Dataspace::V0_SRGB_LINEAR; - std::vector layersFirst; + std::vector layersFirst; renderengine::LayerSettings layerOne; layerOne.sourceDataspace = ui::Dataspace::V0_SRGB_LINEAR; @@ -1035,14 +1036,14 @@ void RenderEngineTest::overlayCorners() { SourceVariant::fillColor(layerOne, 1.0f, 0.0f, 0.0f, this); layerOne.alpha = 0.2; - layersFirst.push_back(&layerOne); + layersFirst.push_back(layerOne); invokeDraw(settings, layersFirst); expectBufferColor(Rect(DEFAULT_DISPLAY_WIDTH / 3, DEFAULT_DISPLAY_HEIGHT / 3), 51, 0, 0, 51); expectBufferColor(Rect(DEFAULT_DISPLAY_WIDTH / 3 + 1, DEFAULT_DISPLAY_HEIGHT / 3 + 1, DEFAULT_DISPLAY_WIDTH, DEFAULT_DISPLAY_HEIGHT), 0, 0, 0, 0); - std::vector layersSecond; + std::vector layersSecond; renderengine::LayerSettings layerTwo; layerTwo.sourceDataspace = ui::Dataspace::V0_SRGB_LINEAR; layerTwo.geometry.boundaries = @@ -1051,7 +1052,7 @@ void RenderEngineTest::overlayCorners() { SourceVariant::fillColor(layerTwo, 0.0f, 1.0f, 0.0f, this); layerTwo.alpha = 1.0f; - layersSecond.push_back(&layerTwo); + layersSecond.push_back(layerTwo); invokeDraw(settings, layersSecond); expectBufferColor(Rect(DEFAULT_DISPLAY_WIDTH / 3, DEFAULT_DISPLAY_HEIGHT / 3), 0, 0, 0, 0); @@ -1066,7 +1067,7 @@ void RenderEngineTest::fillRedBufferTextureTransform() { settings.clip = Rect(1, 1); settings.outputDataspace = ui::Dataspace::V0_SRGB_LINEAR; - std::vector layers; + std::vector layers; renderengine::LayerSettings layer; layer.sourceDataspace = ui::Dataspace::V0_SRGB_LINEAR; @@ -1102,7 +1103,7 @@ void RenderEngineTest::fillRedBufferTextureTransform() { layer.alpha = 1.0f; layer.geometry.boundaries = Rect(1, 1).toFloatRect(); - layers.push_back(&layer); + layers.push_back(layer); invokeDraw(settings, layers); } @@ -1118,7 +1119,7 @@ void RenderEngineTest::fillRedBufferWithPremultiplyAlpha() { // Here logical space is 1x1 settings.clip = Rect(1, 1); - std::vector layers; + std::vector layers; renderengine::LayerSettings layer; const auto buf = allocateSourceBuffer(1, 1); @@ -1141,7 +1142,7 @@ void RenderEngineTest::fillRedBufferWithPremultiplyAlpha() { layer.alpha = 0.5f; layer.geometry.boundaries = Rect(1, 1).toFloatRect(); - layers.push_back(&layer); + layers.push_back(layer); invokeDraw(settings, layers); } @@ -1157,7 +1158,7 @@ void RenderEngineTest::fillRedBufferWithoutPremultiplyAlpha() { // Here logical space is 1x1 settings.clip = Rect(1, 1); - std::vector layers; + std::vector layers; renderengine::LayerSettings layer; const auto buf = allocateSourceBuffer(1, 1); @@ -1180,7 +1181,7 @@ void RenderEngineTest::fillRedBufferWithoutPremultiplyAlpha() { layer.alpha = 0.5f; layer.geometry.boundaries = Rect(1, 1).toFloatRect(); - layers.push_back(&layer); + layers.push_back(layer); invokeDraw(settings, layers); } @@ -1199,7 +1200,7 @@ void RenderEngineTest::drawShadow(const renderengine::LayerSettings& castingLaye settings.physicalDisplay = fullscreenRect(); settings.clip = fullscreenRect(); - std::vector layers; + std::vector layers; // add background layer renderengine::LayerSettings bgLayer; @@ -1208,7 +1209,7 @@ void RenderEngineTest::drawShadow(const renderengine::LayerSettings& castingLaye ColorSourceVariant::fillColor(bgLayer, backgroundColor.r / 255.0f, backgroundColor.g / 255.0f, backgroundColor.b / 255.0f, this); bgLayer.alpha = backgroundColor.a / 255.0f; - layers.push_back(&bgLayer); + layers.push_back(bgLayer); // add shadow layer renderengine::LayerSettings shadowLayer; @@ -1216,14 +1217,14 @@ void RenderEngineTest::drawShadow(const renderengine::LayerSettings& castingLaye shadowLayer.geometry.boundaries = castingLayer.geometry.boundaries; shadowLayer.alpha = castingLayer.alpha; shadowLayer.shadow = shadow; - layers.push_back(&shadowLayer); + layers.push_back(shadowLayer); // add layer casting the shadow renderengine::LayerSettings layer = castingLayer; layer.sourceDataspace = ui::Dataspace::V0_SRGB_LINEAR; SourceVariant::fillColor(layer, casterColor.r / 255.0f, casterColor.g / 255.0f, casterColor.b / 255.0f, this); - layers.push_back(&layer); + layers.push_back(layer); invokeDraw(settings, layers); } @@ -1236,7 +1237,7 @@ void RenderEngineTest::drawShadowWithoutCaster(const FloatRect& castingBounds, settings.physicalDisplay = fullscreenRect(); settings.clip = fullscreenRect(); - std::vector layers; + std::vector layers; // add background layer renderengine::LayerSettings bgLayer; @@ -1245,7 +1246,7 @@ void RenderEngineTest::drawShadowWithoutCaster(const FloatRect& castingBounds, ColorSourceVariant::fillColor(bgLayer, backgroundColor.r / 255.0f, backgroundColor.g / 255.0f, backgroundColor.b / 255.0f, this); bgLayer.alpha = backgroundColor.a / 255.0f; - layers.push_back(&bgLayer); + layers.push_back(bgLayer); // add shadow layer renderengine::LayerSettings shadowLayer; @@ -1255,7 +1256,7 @@ void RenderEngineTest::drawShadowWithoutCaster(const FloatRect& castingBounds, shadowLayer.alpha = 1.0f; ColorSourceVariant::fillColor(shadowLayer, 0, 0, 0, this); shadowLayer.shadow = shadow; - layers.push_back(&shadowLayer); + layers.push_back(shadowLayer); invokeDraw(settings, layers); } @@ -1291,8 +1292,8 @@ TEST_P(RenderEngineTest, drawLayers_withoutBuffers_withColorTransform) { // Transform the red color. bgLayer.colorTransform = mat4(-1, 0, 0, 0, 0, 1, 0, 0, 0, 0, 1, 0, 0, 0, 0, 1); - std::vector layers; - layers.push_back(&bgLayer); + std::vector layers; + layers.push_back(bgLayer); invokeDraw(settings, layers); @@ -1306,11 +1307,11 @@ TEST_P(RenderEngineTest, drawLayers_nullOutputBuffer) { renderengine::DisplaySettings settings; settings.outputDataspace = ui::Dataspace::V0_SRGB_LINEAR; - std::vector layers; + std::vector layers; renderengine::LayerSettings layer; layer.geometry.boundaries = fullscreenRect().toFloatRect(); BufferSourceVariant::fillColor(layer, 1.0f, 0.0f, 0.0f, this); - layers.push_back(&layer); + layers.push_back(layer); std::future result = mRE->drawLayers(settings, layers, nullptr, true, base::unique_fd()); @@ -1335,12 +1336,12 @@ TEST_P(RenderEngineTest, drawLayers_doesNotCacheFramebuffer) { settings.physicalDisplay = fullscreenRect(); settings.clip = fullscreenRect(); - std::vector layers; + std::vector layers; renderengine::LayerSettings layer; layer.geometry.boundaries = fullscreenRect().toFloatRect(); BufferSourceVariant::fillColor(layer, 1.0f, 0.0f, 0.0f, this); layer.alpha = 1.0; - layers.push_back(&layer); + layers.push_back(layer); std::future result = mRE->drawLayers(settings, layers, mBuffer, false, base::unique_fd()); @@ -1743,12 +1744,12 @@ TEST_P(RenderEngineTest, cleanupPostRender_cleansUpOnce) { settings.clip = fullscreenRect(); settings.outputDataspace = ui::Dataspace::V0_SRGB_LINEAR; - std::vector layers; + std::vector layers; renderengine::LayerSettings layer; layer.geometry.boundaries = fullscreenRect().toFloatRect(); BufferSourceVariant::fillColor(layer, 1.0f, 0.0f, 0.0f, this); layer.alpha = 1.0; - layers.push_back(&layer); + layers.push_back(layer); std::future resultOne = mRE->drawLayers(settings, layers, mBuffer, true, base::unique_fd()); @@ -1779,7 +1780,7 @@ TEST_P(RenderEngineTest, testRoundedCornersCrop) { settings.clip = fullscreenRect(); settings.outputDataspace = ui::Dataspace::V0_SRGB_LINEAR; - std::vector layers; + std::vector layers; renderengine::LayerSettings redLayer; redLayer.sourceDataspace = ui::Dataspace::V0_SRGB_LINEAR; @@ -1790,7 +1791,7 @@ TEST_P(RenderEngineTest, testRoundedCornersCrop) { redLayer.source.solidColor = half3(1.0f, 0.0f, 0.0f); redLayer.alpha = 1.0f; - layers.push_back(&redLayer); + layers.push_back(redLayer); // Green layer with 1/3 size. renderengine::LayerSettings greenLayer; @@ -1805,7 +1806,7 @@ TEST_P(RenderEngineTest, testRoundedCornersCrop) { greenLayer.source.solidColor = half3(0.0f, 1.0f, 0.0f); greenLayer.alpha = 1.0f; - layers.push_back(&greenLayer); + layers.push_back(greenLayer); invokeDraw(settings, layers); @@ -1828,7 +1829,7 @@ TEST_P(RenderEngineTest, testRoundedCornersParentCrop) { settings.clip = fullscreenRect(); settings.outputDataspace = ui::Dataspace::V0_SRGB_LINEAR; - std::vector layers; + std::vector layers; renderengine::LayerSettings redLayer; redLayer.sourceDataspace = ui::Dataspace::V0_SRGB_LINEAR; @@ -1839,7 +1840,7 @@ TEST_P(RenderEngineTest, testRoundedCornersParentCrop) { redLayer.source.solidColor = half3(1.0f, 0.0f, 0.0f); redLayer.alpha = 1.0f; - layers.push_back(&redLayer); + layers.push_back(redLayer); // Green layer with 1/2 size with parent crop rect. renderengine::LayerSettings greenLayer = redLayer; @@ -1847,7 +1848,7 @@ TEST_P(RenderEngineTest, testRoundedCornersParentCrop) { FloatRect(0, 0, DEFAULT_DISPLAY_WIDTH, DEFAULT_DISPLAY_HEIGHT / 2); greenLayer.source.solidColor = half3(0.0f, 1.0f, 0.0f); - layers.push_back(&greenLayer); + layers.push_back(greenLayer); invokeDraw(settings, layers); @@ -1873,7 +1874,7 @@ TEST_P(RenderEngineTest, testRoundedCornersParentCropSmallBounds) { settings.clip = fullscreenRect(); settings.outputDataspace = ui::Dataspace::V0_SRGB_LINEAR; - std::vector layers; + std::vector layers; renderengine::LayerSettings redLayer; redLayer.sourceDataspace = ui::Dataspace::V0_SRGB_LINEAR; @@ -1884,7 +1885,7 @@ TEST_P(RenderEngineTest, testRoundedCornersParentCropSmallBounds) { redLayer.source.solidColor = half3(1.0f, 0.0f, 0.0f); redLayer.alpha = 1.0f; - layers.push_back(&redLayer); + layers.push_back(redLayer); invokeDraw(settings, layers); // Due to roundedCornersRadius, the top corners are untouched. @@ -1923,7 +1924,7 @@ TEST_P(RenderEngineTest, testClear) { .disableBlending = true, }; - std::vector layers{&redLayer, &clearLayer}; + std::vector layers{redLayer, clearLayer}; invokeDraw(display, layers); expectBufferColor(rect, 0, 0, 0, 0); } @@ -1971,7 +1972,7 @@ TEST_P(RenderEngineTest, testDisableBlendingBuffer) { .disableBlending = true, }; - std::vector layers{&redLayer, &greenLayer}; + std::vector layers{redLayer, greenLayer}; invokeDraw(display, layers); expectBufferColor(rect, 0, 128, 0, 128); } @@ -2017,7 +2018,7 @@ TEST_P(RenderEngineTest, test_isOpaque) { .alpha = 1.0f, }; - std::vector layers{&greenLayer}; + std::vector layers{greenLayer}; invokeDraw(display, layers); if (GetParam()->useColorManagement()) { diff --git a/libs/renderengine/tests/RenderEngineThreadedTest.cpp b/libs/renderengine/tests/RenderEngineThreadedTest.cpp index 99250c1412..db7e12b71b 100644 --- a/libs/renderengine/tests/RenderEngineThreadedTest.cpp +++ b/libs/renderengine/tests/RenderEngineThreadedTest.cpp @@ -172,20 +172,21 @@ TEST_F(RenderEngineThreadedTest, supportsBackgroundBlur_returnsTrue) { TEST_F(RenderEngineThreadedTest, drawLayers) { renderengine::DisplaySettings settings; - std::vector layers; + std::vector layers; std::shared_ptr buffer = std::make_shared< renderengine::ExternalTexture>(new GraphicBuffer(), *mRenderEngine, renderengine::ExternalTexture::Usage::READABLE | renderengine::ExternalTexture::Usage::WRITEABLE); + base::unique_fd bufferFence; EXPECT_CALL(*mRenderEngine, drawLayersInternal) .WillOnce([&](const std::shared_ptr>&& resultPromise, const renderengine::DisplaySettings&, - const std::vector&, + const std::vector&, const std::shared_ptr&, const bool, - base::unique_fd &&) -> void { + base::unique_fd&&) -> void { resultPromise->set_value({NO_ERROR, base::unique_fd()}); }); diff --git a/libs/renderengine/threaded/RenderEngineThreaded.cpp b/libs/renderengine/threaded/RenderEngineThreaded.cpp index a549672259..3d446e8e72 100644 --- a/libs/renderengine/threaded/RenderEngineThreaded.cpp +++ b/libs/renderengine/threaded/RenderEngineThreaded.cpp @@ -306,7 +306,7 @@ bool RenderEngineThreaded::canSkipPostRenderCleanup() const { void RenderEngineThreaded::drawLayersInternal( const std::shared_ptr>&& resultPromise, - const DisplaySettings& display, const std::vector& layers, + const DisplaySettings& display, const std::vector& layers, const std::shared_ptr& buffer, const bool useFramebufferCache, base::unique_fd&& bufferFence) { resultPromise->set_value({NO_ERROR, base::unique_fd()}); @@ -314,19 +314,20 @@ void RenderEngineThreaded::drawLayersInternal( } std::future RenderEngineThreaded::drawLayers( - const DisplaySettings& display, const std::vector& layers, + const DisplaySettings& display, const std::vector& layers, const std::shared_ptr& buffer, const bool useFramebufferCache, base::unique_fd&& bufferFence) { ATRACE_CALL(); const auto resultPromise = std::make_shared>(); std::future resultFuture = resultPromise->get_future(); + int fd = bufferFence.release(); { std::lock_guard lock(mThreadMutex); - mFunctionCalls.push([resultPromise, &display, &layers, &buffer, useFramebufferCache, - &bufferFence](renderengine::RenderEngine& instance) { + mFunctionCalls.push([resultPromise, display, layers, buffer, useFramebufferCache, + fd](renderengine::RenderEngine& instance) { ATRACE_NAME("REThreaded::drawLayers"); instance.drawLayersInternal(std::move(resultPromise), display, layers, buffer, - useFramebufferCache, std::move(bufferFence)); + useFramebufferCache, base::unique_fd(fd)); }); } mCondition.notify_one(); diff --git a/libs/renderengine/threaded/RenderEngineThreaded.h b/libs/renderengine/threaded/RenderEngineThreaded.h index 2303caa7eb..0159cfaece 100644 --- a/libs/renderengine/threaded/RenderEngineThreaded.h +++ b/libs/renderengine/threaded/RenderEngineThreaded.h @@ -57,7 +57,7 @@ public: void cleanupPostRender() override; std::future drawLayers(const DisplaySettings& display, - const std::vector& layers, + const std::vector& layers, const std::shared_ptr& buffer, const bool useFramebufferCache, base::unique_fd&& bufferFence) override; @@ -73,7 +73,7 @@ protected: bool canSkipPostRenderCleanup() const override; void drawLayersInternal(const std::shared_ptr>&& resultPromise, const DisplaySettings& display, - const std::vector& layers, + const std::vector& layers, const std::shared_ptr& buffer, const bool useFramebufferCache, base::unique_fd&& bufferFence) override; diff --git a/services/surfaceflinger/BufferQueueLayer.cpp b/services/surfaceflinger/BufferQueueLayer.cpp index f98681e1ce..6c60e53841 100644 --- a/services/surfaceflinger/BufferQueueLayer.cpp +++ b/services/surfaceflinger/BufferQueueLayer.cpp @@ -48,7 +48,9 @@ BufferQueueLayer::~BufferQueueLayer() { // Interface implementation for Layer // ----------------------------------------------------------------------- -void BufferQueueLayer::onLayerDisplayed(const sp& releaseFence) { +void BufferQueueLayer::onLayerDisplayed( + std::shared_future futureRenderEngineResult) { + sp releaseFence = new Fence(dup(futureRenderEngineResult.get().drawFence)); mConsumer->setReleaseFence(releaseFence); // Prevent tracing the same release multiple times. diff --git a/services/surfaceflinger/BufferQueueLayer.h b/services/surfaceflinger/BufferQueueLayer.h index a3bd725cfe..dfdb5c055d 100644 --- a/services/surfaceflinger/BufferQueueLayer.h +++ b/services/surfaceflinger/BufferQueueLayer.h @@ -42,7 +42,8 @@ public: // Implements Layer. const char* getType() const override { return "BufferQueueLayer"; } - void onLayerDisplayed(const sp& releaseFence) override; + void onLayerDisplayed( + std::shared_future futureRenderEngineResult) override; // If a buffer was replaced this frame, release the former buffer void releasePendingBuffer(nsecs_t dequeueReadyTime) override; diff --git a/services/surfaceflinger/BufferStateLayer.cpp b/services/surfaceflinger/BufferStateLayer.cpp index 132ee9d71b..454363ac3f 100644 --- a/services/surfaceflinger/BufferStateLayer.cpp +++ b/services/surfaceflinger/BufferStateLayer.cpp @@ -70,69 +70,11 @@ BufferStateLayer::~BufferStateLayer() { } } -status_t BufferStateLayer::addReleaseFence(const sp& ch, - const sp& fence) { - if (ch == nullptr) { - return OK; - } - ch->previousReleaseCallbackId = mPreviousReleaseCallbackId; - if (!ch->previousReleaseFence.get()) { - ch->previousReleaseFence = fence; - return OK; - } - - // Below logic is lifted from ConsumerBase.cpp: - // Check status of fences first because merging is expensive. - // Merging an invalid fence with any other fence results in an - // invalid fence. - auto currentStatus = ch->previousReleaseFence->getStatus(); - if (currentStatus == Fence::Status::Invalid) { - ALOGE("Existing fence has invalid state, layer: %s", mName.c_str()); - return BAD_VALUE; - } - - auto incomingStatus = fence->getStatus(); - if (incomingStatus == Fence::Status::Invalid) { - ALOGE("New fence has invalid state, layer: %s", mName.c_str()); - ch->previousReleaseFence = fence; - return BAD_VALUE; - } - - // If both fences are signaled or both are unsignaled, we need to merge - // them to get an accurate timestamp. - if (currentStatus == incomingStatus) { - char fenceName[32] = {}; - snprintf(fenceName, 32, "%.28s", mName.c_str()); - sp mergedFence = Fence::merge( - fenceName, ch->previousReleaseFence, fence); - if (!mergedFence.get()) { - ALOGE("failed to merge release fences, layer: %s", mName.c_str()); - // synchronization is broken, the best we can do is hope fences - // signal in order so the new fence will act like a union - ch->previousReleaseFence = fence; - return BAD_VALUE; - } - ch->previousReleaseFence = mergedFence; - } else if (incomingStatus == Fence::Status::Unsignaled) { - // If one fence has signaled and the other hasn't, the unsignaled - // fence will approximately correspond with the correct timestamp. - // There's a small race if both fences signal at about the same time - // and their statuses are retrieved with unfortunate timing. However, - // by this point, they will have both signaled and only the timestamp - // will be slightly off; any dependencies after this point will - // already have been met. - ch->previousReleaseFence = fence; - } - // else if (currentStatus == Fence::Status::Unsignaled) is a no-op. - - return OK; -} - // ----------------------------------------------------------------------- // Interface implementation for Layer // ----------------------------------------------------------------------- -void BufferStateLayer::onLayerDisplayed(const sp& releaseFence) { - +void BufferStateLayer::onLayerDisplayed( + std::shared_future futureRenderEngineResult) { // If a layer has been displayed again we may need to clear // the mLastClientComposition fence that we use for early release in setBuffer // (as we now have a new fence which won't pass through the client composition path in some cases @@ -146,9 +88,6 @@ void BufferStateLayer::onLayerDisplayed(const sp& releaseFence) { mLastClientCompositionDisplayed = true; } - if (!releaseFence->isValid()) { - return; - } // The previous release fence notifies the client that SurfaceFlinger is done with the previous // buffer that was presented on this layer. The first transaction that came in this frame that // replaced the previous buffer on this layer needs this release fence, because the fence will @@ -173,17 +112,19 @@ void BufferStateLayer::onLayerDisplayed(const sp& releaseFence) { break; } } - auto status = addReleaseFence(ch, releaseFence); - if (status != OK) { - ALOGE("Failed to add release fence for layer %s", getName().c_str()); - } - mPreviousReleaseFence = releaseFence; + mListPreviousReleaseFences.emplace_back(futureRenderEngineResult); // Prevent tracing the same release multiple times. if (mPreviousFrameNumber != mPreviousReleasedFrameNumber) { mPreviousReleasedFrameNumber = mPreviousFrameNumber; } + + if (ch != nullptr) { + ch->previousReleaseCallbackId = mPreviousReleaseCallbackId; + ch->previousReleaseFences.emplace_back(futureRenderEngineResult); + ch->name = mName; + } } void BufferStateLayer::onSurfaceFrameCreated( @@ -231,9 +172,18 @@ void BufferStateLayer::releasePendingBuffer(nsecs_t dequeueReadyTime) { mFlinger->getTransactionCallbackInvoker().addCallbackHandles( mDrawingState.callbackHandles, jankData); + sp releaseFence = Fence::NO_FENCE; + for (auto& handle : mDrawingState.callbackHandles) { + if (handle->releasePreviousBuffer && + mDrawingState.releaseBufferEndpoint == handle->listener) { + releaseFence = + handle->previousReleaseFence ? handle->previousReleaseFence : Fence::NO_FENCE; + break; + } + } + mDrawingState.callbackHandles = {}; - const sp& releaseFence(mPreviousReleaseFence); std::shared_ptr releaseFenceTime = std::make_shared(releaseFence); { Mutex::Autolock lock(mFrameEventHistoryMutex); diff --git a/services/surfaceflinger/BufferStateLayer.h b/services/surfaceflinger/BufferStateLayer.h index 87b68ea71b..6cb9b352f8 100644 --- a/services/surfaceflinger/BufferStateLayer.h +++ b/services/surfaceflinger/BufferStateLayer.h @@ -39,7 +39,9 @@ public: // Implements Layer. const char* getType() const override { return "BufferStateLayer"; } - void onLayerDisplayed(const sp& releaseFence) override; + void onLayerDisplayed( + std::shared_future futureRenderEngineResult) override; + void releasePendingBuffer(nsecs_t dequeueReadyTime) override; void finalizeFrameEventHistory(const std::shared_ptr& glDoneFence, @@ -115,8 +117,6 @@ private: bool updateFrameEventHistory(const sp& acquireFence, nsecs_t postedTime, nsecs_t requestedPresentTime); - status_t addReleaseFence(const sp& ch, const sp& releaseFence); - bool latchSidebandStream(bool& recomputeVisibleRegions) override; bool hasFrameUpdate() const override; @@ -139,7 +139,7 @@ private: std::shared_ptr getBufferFromBufferData( const BufferData& bufferData); - sp mPreviousReleaseFence; + std::vector> mListPreviousReleaseFences; ReleaseCallbackId mPreviousReleaseCallbackId = ReleaseCallbackId::INVALID_ID; uint64_t mPreviousReleasedFrameNumber = 0; diff --git a/services/surfaceflinger/CompositionEngine/include/compositionengine/LayerFE.h b/services/surfaceflinger/CompositionEngine/include/compositionengine/LayerFE.h index f7b71cf9fe..ac243c0a17 100644 --- a/services/surfaceflinger/CompositionEngine/include/compositionengine/LayerFE.h +++ b/services/surfaceflinger/CompositionEngine/include/compositionengine/LayerFE.h @@ -16,6 +16,7 @@ #pragma once +#include #include #include #include @@ -26,6 +27,7 @@ #pragma clang diagnostic ignored "-Wextra" #include +#include // TODO(b/129481165): remove the #pragma below and fix conversion issues #pragma clang diagnostic pop // ignored "-Wconversion -Wextra" @@ -151,7 +153,7 @@ public: ClientCompositionTargetSettings&) = 0; // Called after the layer is displayed to update the presentation fence - virtual void onLayerDisplayed(const sp&) = 0; + virtual void onLayerDisplayed(std::shared_future) = 0; // Gets some kind of identifier for the layer for debug purposes. virtual const char* getDebugName() const = 0; diff --git a/services/surfaceflinger/CompositionEngine/include/compositionengine/mock/LayerFE.h b/services/surfaceflinger/CompositionEngine/include/compositionengine/mock/LayerFE.h index d215bda891..16aebef9f3 100644 --- a/services/surfaceflinger/CompositionEngine/include/compositionengine/mock/LayerFE.h +++ b/services/surfaceflinger/CompositionEngine/include/compositionengine/mock/LayerFE.h @@ -39,7 +39,7 @@ public: std::vector( compositionengine::LayerFE::ClientCompositionTargetSettings&)); - MOCK_METHOD1(onLayerDisplayed, void(const sp&)); + MOCK_METHOD1(onLayerDisplayed, void(std::shared_future)); MOCK_CONST_METHOD0(getDebugName, const char*()); MOCK_CONST_METHOD0(getSequence, int32_t()); diff --git a/services/surfaceflinger/CompositionEngine/src/Output.cpp b/services/surfaceflinger/CompositionEngine/src/Output.cpp index 048d7c2b4a..7ea1aa2f92 100644 --- a/services/surfaceflinger/CompositionEngine/src/Output.cpp +++ b/services/surfaceflinger/CompositionEngine/src/Output.cpp @@ -27,6 +27,7 @@ #include #include #include +#include #include @@ -1097,12 +1098,12 @@ std::optional Output::composeSurfaces( setExpensiveRenderingExpected(true); } - std::vector clientCompositionLayerPointers; - clientCompositionLayerPointers.reserve(clientCompositionLayers.size()); + std::vector clientRenderEngineLayers; + clientRenderEngineLayers.reserve(clientCompositionLayers.size()); std::transform(clientCompositionLayers.begin(), clientCompositionLayers.end(), - std::back_inserter(clientCompositionLayerPointers), - [](LayerFE::LayerSettings& settings) -> renderengine::LayerSettings* { - return &settings; + std::back_inserter(clientRenderEngineLayers), + [](LayerFE::LayerSettings& settings) -> renderengine::LayerSettings { + return settings; }); const nsecs_t renderEngineStart = systemTime(); @@ -1115,7 +1116,7 @@ std::optional Output::composeSurfaces( const bool useFramebufferCache = outputState.layerFilter.toInternalDisplay; auto [status, drawFence] = renderEngine - .drawLayers(clientCompositionDisplay, clientCompositionLayerPointers, tex, + .drawLayers(clientCompositionDisplay, clientRenderEngineLayers, tex, useFramebufferCache, std::move(fd)) .get(); @@ -1295,8 +1296,10 @@ void Output::postFramebuffer() { releaseFence = Fence::merge("LayerRelease", releaseFence, frame.clientTargetAcquireFence); } - - layer->getLayerFE().onLayerDisplayed(releaseFence); + layer->getLayerFE().onLayerDisplayed( + ftl::yield( + {NO_ERROR, base::unique_fd(releaseFence->dup())}) + .share()); } // We've got a list of layers needing fences, that are disjoint with @@ -1304,7 +1307,9 @@ void Output::postFramebuffer() { // supply them with the present fence. for (auto& weakLayer : mReleasedLayers) { if (auto layer = weakLayer.promote(); layer != nullptr) { - layer->onLayerDisplayed(frame.presentFence); + layer->onLayerDisplayed(ftl::yield( + {NO_ERROR, base::unique_fd(frame.presentFence->dup())}) + .share()); } } diff --git a/services/surfaceflinger/CompositionEngine/src/planner/CachedSet.cpp b/services/surfaceflinger/CompositionEngine/src/planner/CachedSet.cpp index e6b716e8f2..ec52e59ab0 100644 --- a/services/surfaceflinger/CompositionEngine/src/planner/CachedSet.cpp +++ b/services/surfaceflinger/CompositionEngine/src/planner/CachedSet.cpp @@ -193,11 +193,6 @@ void CachedSet::render(renderengine::RenderEngine& renderEngine, TexturePool& te clientCompositionList.cend()); } - std::vector layerSettingsPointers; - std::transform(layerSettings.cbegin(), layerSettings.cend(), - std::back_inserter(layerSettingsPointers), - [](const renderengine::LayerSettings& settings) { return &settings; }); - renderengine::LayerSettings blurLayerSettings; if (mBlurLayer) { auto blurSettings = targetSettings; @@ -212,7 +207,7 @@ void CachedSet::render(renderengine::RenderEngine& renderEngine, TexturePool& te blurLayerSettings.name = std::string("blur layer"); // Clear out the shadow settings blurLayerSettings.shadow = {}; - layerSettingsPointers.push_back(&blurLayerSettings); + layerSettings.push_back(blurLayerSettings); } renderengine::LayerSettings holePunchSettings; @@ -230,7 +225,7 @@ void CachedSet::render(renderengine::RenderEngine& renderEngine, TexturePool& te holePunchSettings.disableBlending = true; holePunchSettings.alpha = 0.0f; holePunchSettings.name = std::string("hole punch layer"); - layerSettingsPointers.push_back(&holePunchSettings); + layerSettings.push_back(holePunchSettings); // Add a solid background as the first layer in case there is no opaque // buffer behind the punch hole @@ -239,7 +234,7 @@ void CachedSet::render(renderengine::RenderEngine& renderEngine, TexturePool& te holePunchBackgroundSettings.geometry.boundaries = holePunchSettings.geometry.boundaries; holePunchBackgroundSettings.geometry.positionTransform = holePunchSettings.geometry.positionTransform; - layerSettingsPointers.insert(layerSettingsPointers.begin(), &holePunchBackgroundSettings); + layerSettings.emplace(layerSettings.begin(), holePunchBackgroundSettings); } if (sDebugHighlighLayers) { @@ -257,7 +252,7 @@ void CachedSet::render(renderengine::RenderEngine& renderEngine, TexturePool& te .alpha = half(0.05f), }; - layerSettingsPointers.emplace_back(&highlight); + layerSettings.emplace_back(highlight); } auto texture = texturePool.borrowTexture(); @@ -273,8 +268,8 @@ void CachedSet::render(renderengine::RenderEngine& renderEngine, TexturePool& te } auto [status, drawFence] = renderEngine - .drawLayers(displaySettings, layerSettingsPointers, - texture->get(), false, std::move(bufferFence)) + .drawLayers(displaySettings, layerSettings, texture->get(), + false, std::move(bufferFence)) .get(); if (status == NO_ERROR) { diff --git a/services/surfaceflinger/CompositionEngine/tests/OutputTest.cpp b/services/surfaceflinger/CompositionEngine/tests/OutputTest.cpp index 8f0028c399..cf63ef5183 100644 --- a/services/surfaceflinger/CompositionEngine/tests/OutputTest.cpp +++ b/services/surfaceflinger/CompositionEngine/tests/OutputTest.cpp @@ -24,6 +24,7 @@ #include #include #include +#include #include #include #include @@ -2884,12 +2885,24 @@ TEST_F(OutputPostFramebufferTest, releaseFencesAreSentToLayerFE) { // are passed. This happens to work with the current implementation, but // would not survive certain calls like Fence::merge() which would return a // new instance. - EXPECT_CALL(*mLayer1.layerFE, - onLayerDisplayed(Property(&sp::get, Eq(layer1Fence.get())))); - EXPECT_CALL(*mLayer2.layerFE, - onLayerDisplayed(Property(&sp::get, Eq(layer2Fence.get())))); - EXPECT_CALL(*mLayer3.layerFE, - onLayerDisplayed(Property(&sp::get, Eq(layer3Fence.get())))); + base::unique_fd layer1FD(layer1Fence->dup()); + base::unique_fd layer2FD(layer2Fence->dup()); + base::unique_fd layer3FD(layer3Fence->dup()); + EXPECT_CALL(*mLayer1.layerFE, onLayerDisplayed(_)) + .WillOnce([&layer1FD](std::shared_future + futureRenderEngineResult) { + EXPECT_EQ(layer1FD, futureRenderEngineResult.get().drawFence); + }); + EXPECT_CALL(*mLayer2.layerFE, onLayerDisplayed(_)) + .WillOnce([&layer2FD](std::shared_future + futureRenderEngineResult) { + EXPECT_EQ(layer2FD, futureRenderEngineResult.get().drawFence); + }); + EXPECT_CALL(*mLayer3.layerFE, onLayerDisplayed(_)) + .WillOnce([&layer3FD](std::shared_future + futureRenderEngineResult) { + EXPECT_EQ(layer3FD, futureRenderEngineResult.get().drawFence); + }); mOutput.postFramebuffer(); } @@ -2915,9 +2928,9 @@ TEST_F(OutputPostFramebufferTest, releaseFencesIncludeClientTargetAcquireFence) // Fence::merge is called, and since none of the fences are actually valid, // Fence::NO_FENCE is returned and passed to each onLayerDisplayed() call. // This is the best we can do without creating a real kernel fence object. - EXPECT_CALL(*mLayer1.layerFE, onLayerDisplayed(Fence::NO_FENCE)); - EXPECT_CALL(*mLayer2.layerFE, onLayerDisplayed(Fence::NO_FENCE)); - EXPECT_CALL(*mLayer3.layerFE, onLayerDisplayed(Fence::NO_FENCE)); + EXPECT_CALL(*mLayer1.layerFE, onLayerDisplayed).WillOnce(Return()); + EXPECT_CALL(*mLayer2.layerFE, onLayerDisplayed).WillOnce(Return()); + EXPECT_CALL(*mLayer3.layerFE, onLayerDisplayed).WillOnce(Return()); mOutput.postFramebuffer(); } @@ -2949,12 +2962,22 @@ TEST_F(OutputPostFramebufferTest, releasedLayersSentPresentFence) { EXPECT_CALL(*mRenderSurface, onPresentDisplayCompleted()); // Each released layer should be given the presentFence. - EXPECT_CALL(*releasedLayer1, - onLayerDisplayed(Property(&sp::get, Eq(presentFence.get())))); - EXPECT_CALL(*releasedLayer2, - onLayerDisplayed(Property(&sp::get, Eq(presentFence.get())))); - EXPECT_CALL(*releasedLayer3, - onLayerDisplayed(Property(&sp::get, Eq(presentFence.get())))); + base::unique_fd layerFD(presentFence.get()->dup()); + EXPECT_CALL(*releasedLayer1, onLayerDisplayed(_)) + .WillOnce([&layerFD](std::shared_future + futureRenderEngineResult) { + EXPECT_EQ(layerFD, futureRenderEngineResult.get().drawFence); + }); + EXPECT_CALL(*releasedLayer2, onLayerDisplayed(_)) + .WillOnce([&layerFD](std::shared_future + futureRenderEngineResult) { + EXPECT_EQ(layerFD, futureRenderEngineResult.get().drawFence); + }); + EXPECT_CALL(*releasedLayer3, onLayerDisplayed(_)) + .WillOnce([&layerFD](std::shared_future + futureRenderEngineResult) { + EXPECT_EQ(layerFD, futureRenderEngineResult.get().drawFence); + }); mOutput.postFramebuffer(); @@ -3131,9 +3154,9 @@ TEST_F(OutputComposeSurfacesTest, handlesZeroCompositionRequests) { EXPECT_CALL(*mRenderSurface, dequeueBuffer(_)).WillRepeatedly(Return(mOutputBuffer)); EXPECT_CALL(mRenderEngine, drawLayers(_, IsEmpty(), _, false, _)) .WillRepeatedly([&](const renderengine::DisplaySettings&, - const std::vector&, + const std::vector&, const std::shared_ptr&, const bool, - base::unique_fd &&) + base::unique_fd&&) -> std::future { return futureOf({NO_ERROR, base::unique_fd()}); }); @@ -3161,11 +3184,11 @@ TEST_F(OutputComposeSurfacesTest, buildsAndRendersRequestList) { })); EXPECT_CALL(*mRenderSurface, dequeueBuffer(_)).WillRepeatedly(Return(mOutputBuffer)); - EXPECT_CALL(mRenderEngine, drawLayers(_, ElementsAre(Pointee(r1), Pointee(r2)), _, false, _)) + EXPECT_CALL(mRenderEngine, drawLayers(_, ElementsAre(r1, r2), _, false, _)) .WillRepeatedly([&](const renderengine::DisplaySettings&, - const std::vector&, + const std::vector&, const std::shared_ptr&, const bool, - base::unique_fd &&) + base::unique_fd&&) -> std::future { return futureOf({NO_ERROR, base::unique_fd()}); }); @@ -3196,11 +3219,11 @@ TEST_F(OutputComposeSurfacesTest, })); EXPECT_CALL(*mRenderSurface, dequeueBuffer(_)).WillRepeatedly(Return(mOutputBuffer)); - EXPECT_CALL(mRenderEngine, drawLayers(_, ElementsAre(Pointee(r1), Pointee(r2)), _, true, _)) + EXPECT_CALL(mRenderEngine, drawLayers(_, ElementsAre(r1, r2), _, true, _)) .WillRepeatedly([&](const renderengine::DisplaySettings&, - const std::vector&, + const std::vector&, const std::shared_ptr&, const bool, - base::unique_fd &&) + base::unique_fd&&) -> std::future { return futureOf({NO_ERROR, base::unique_fd()}); }); @@ -3226,7 +3249,7 @@ TEST_F(OutputComposeSurfacesTest, renderDuplicateClientCompositionRequestsWithou .WillRepeatedly(Return()); EXPECT_CALL(*mRenderSurface, dequeueBuffer(_)).WillRepeatedly(Return(mOutputBuffer)); - EXPECT_CALL(mRenderEngine, drawLayers(_, ElementsAre(Pointee(r1), Pointee(r2)), _, false, _)) + EXPECT_CALL(mRenderEngine, drawLayers(_, ElementsAre(r1, r2), _, false, _)) .Times(2) .WillOnce(Return(ByMove( futureOf({NO_ERROR, base::unique_fd()})))) @@ -3258,7 +3281,7 @@ TEST_F(OutputComposeSurfacesTest, skipDuplicateClientCompositionRequests) { .WillRepeatedly(Return()); EXPECT_CALL(*mRenderSurface, dequeueBuffer(_)).WillRepeatedly(Return(mOutputBuffer)); - EXPECT_CALL(mRenderEngine, drawLayers(_, ElementsAre(Pointee(r1), Pointee(r2)), _, false, _)) + EXPECT_CALL(mRenderEngine, drawLayers(_, ElementsAre(r1, r2), _, false, _)) .WillOnce(Return(ByMove( futureOf({NO_ERROR, base::unique_fd()})))); EXPECT_CALL(mOutput, setExpensiveRenderingExpected(false)); @@ -3294,11 +3317,11 @@ TEST_F(OutputComposeSurfacesTest, clientCompositionIfBufferChanges) { EXPECT_CALL(*mRenderSurface, dequeueBuffer(_)) .WillOnce(Return(mOutputBuffer)) .WillOnce(Return(otherOutputBuffer)); - EXPECT_CALL(mRenderEngine, drawLayers(_, ElementsAre(Pointee(r1), Pointee(r2)), _, false, _)) + EXPECT_CALL(mRenderEngine, drawLayers(_, ElementsAre(r1, r2), _, false, _)) .WillRepeatedly([&](const renderengine::DisplaySettings&, - const std::vector&, + const std::vector&, const std::shared_ptr&, const bool, - base::unique_fd &&) + base::unique_fd&&) -> std::future { return futureOf({NO_ERROR, base::unique_fd()}); }); @@ -3330,10 +3353,10 @@ TEST_F(OutputComposeSurfacesTest, clientCompositionIfRequestChanges) { .WillRepeatedly(Return()); EXPECT_CALL(*mRenderSurface, dequeueBuffer(_)).WillRepeatedly(Return(mOutputBuffer)); - EXPECT_CALL(mRenderEngine, drawLayers(_, ElementsAre(Pointee(r1), Pointee(r2)), _, false, _)) + EXPECT_CALL(mRenderEngine, drawLayers(_, ElementsAre(r1, r2), _, false, _)) .WillOnce(Return(ByMove( futureOf({NO_ERROR, base::unique_fd()})))); - EXPECT_CALL(mRenderEngine, drawLayers(_, ElementsAre(Pointee(r1), Pointee(r3)), _, false, _)) + EXPECT_CALL(mRenderEngine, drawLayers(_, ElementsAre(r1, r3), _, false, _)) .WillOnce(Return(ByMove( futureOf({NO_ERROR, base::unique_fd()})))); @@ -3487,9 +3510,9 @@ struct OutputComposeSurfacesTest_HandlesProtectedContent : public OutputComposeS EXPECT_CALL(mRenderEngine, drawLayers(_, _, _, false, _)) .WillRepeatedly( [&](const renderengine::DisplaySettings&, - const std::vector&, + const std::vector&, const std::shared_ptr&, const bool, - base::unique_fd &&) -> std::future { + base::unique_fd&&) -> std::future { return futureOf( {NO_ERROR, base::unique_fd()}); }); diff --git a/services/surfaceflinger/CompositionEngine/tests/planner/CachedSetTest.cpp b/services/surfaceflinger/CompositionEngine/tests/planner/CachedSetTest.cpp index ecb05f8e5f..42b3d972a8 100644 --- a/services/surfaceflinger/CompositionEngine/tests/planner/CachedSetTest.cpp +++ b/services/surfaceflinger/CompositionEngine/tests/planner/CachedSetTest.cpp @@ -346,15 +346,15 @@ TEST_F(CachedSetTest, renderUnsecureOutput) { const auto drawLayers = [&](const renderengine::DisplaySettings& displaySettings, - const std::vector& layers, + const std::vector& layers, const std::shared_ptr&, const bool, - base::unique_fd &&) -> std::future { + base::unique_fd&&) -> std::future { EXPECT_EQ(mOutputState.framebufferSpace.getContent(), displaySettings.physicalDisplay); EXPECT_EQ(mOutputState.layerStackSpace.getContent(), displaySettings.clip); EXPECT_EQ(ui::Transform::toRotationFlags(mOutputState.framebufferSpace.getOrientation()), displaySettings.orientation); - EXPECT_EQ(0.5f, layers[0]->alpha); - EXPECT_EQ(0.75f, layers[1]->alpha); + EXPECT_EQ(0.5f, layers[0].alpha); + EXPECT_EQ(0.75f, layers[1].alpha); EXPECT_EQ(ui::Dataspace::SRGB, displaySettings.outputDataspace); return futureOf({NO_ERROR, base::unique_fd()}); }; @@ -398,15 +398,15 @@ TEST_F(CachedSetTest, renderSecureOutput) { const auto drawLayers = [&](const renderengine::DisplaySettings& displaySettings, - const std::vector& layers, + const std::vector& layers, const std::shared_ptr&, const bool, - base::unique_fd &&) -> std::future { + base::unique_fd&&) -> std::future { EXPECT_EQ(mOutputState.framebufferSpace.getContent(), displaySettings.physicalDisplay); EXPECT_EQ(mOutputState.layerStackSpace.getContent(), displaySettings.clip); EXPECT_EQ(ui::Transform::toRotationFlags(mOutputState.framebufferSpace.getOrientation()), displaySettings.orientation); - EXPECT_EQ(0.5f, layers[0]->alpha); - EXPECT_EQ(0.75f, layers[1]->alpha); + EXPECT_EQ(0.5f, layers[0].alpha); + EXPECT_EQ(0.75f, layers[1].alpha); EXPECT_EQ(ui::Dataspace::SRGB, displaySettings.outputDataspace); return futureOf({NO_ERROR, base::unique_fd()}); @@ -453,15 +453,15 @@ TEST_F(CachedSetTest, rendersWithOffsetFramebufferContent) { const auto drawLayers = [&](const renderengine::DisplaySettings& displaySettings, - const std::vector& layers, + const std::vector& layers, const std::shared_ptr&, const bool, - base::unique_fd &&) -> std::future { + base::unique_fd&&) -> std::future { EXPECT_EQ(mOutputState.framebufferSpace.getContent(), displaySettings.physicalDisplay); EXPECT_EQ(mOutputState.layerStackSpace.getContent(), displaySettings.clip); EXPECT_EQ(ui::Transform::toRotationFlags(mOutputState.framebufferSpace.getOrientation()), displaySettings.orientation); - EXPECT_EQ(0.5f, layers[0]->alpha); - EXPECT_EQ(0.75f, layers[1]->alpha); + EXPECT_EQ(0.5f, layers[0].alpha); + EXPECT_EQ(0.75f, layers[1].alpha); EXPECT_EQ(ui::Dataspace::SRGB, displaySettings.outputDataspace); return futureOf({NO_ERROR, base::unique_fd()}); @@ -656,26 +656,26 @@ TEST_F(CachedSetTest, addHolePunch) { const auto drawLayers = [&](const renderengine::DisplaySettings&, - const std::vector& layers, + const std::vector& layers, const std::shared_ptr&, const bool, - base::unique_fd &&) -> std::future { + base::unique_fd&&) -> std::future { // If the highlight layer is enabled, it will increase the size by 1. // We're interested in the third layer either way. EXPECT_GE(layers.size(), 4u); { - const auto* holePunchSettings = layers[3]; - EXPECT_EQ(nullptr, holePunchSettings->source.buffer.buffer); - EXPECT_EQ(half3(0.0f, 0.0f, 0.0f), holePunchSettings->source.solidColor); - EXPECT_TRUE(holePunchSettings->disableBlending); - EXPECT_EQ(0.0f, holePunchSettings->alpha); + const auto holePunchSettings = layers[3]; + EXPECT_EQ(nullptr, holePunchSettings.source.buffer.buffer); + EXPECT_EQ(half3(0.0f, 0.0f, 0.0f), holePunchSettings.source.solidColor); + EXPECT_TRUE(holePunchSettings.disableBlending); + EXPECT_EQ(0.0f, holePunchSettings.alpha); } { - const auto* holePunchBackgroundSettings = layers[0]; - EXPECT_EQ(nullptr, holePunchBackgroundSettings->source.buffer.buffer); - EXPECT_EQ(half3(0.0f, 0.0f, 0.0f), holePunchBackgroundSettings->source.solidColor); - EXPECT_FALSE(holePunchBackgroundSettings->disableBlending); - EXPECT_EQ(1.0f, holePunchBackgroundSettings->alpha); + const auto holePunchBackgroundSettings = layers[0]; + EXPECT_EQ(nullptr, holePunchBackgroundSettings.source.buffer.buffer); + EXPECT_EQ(half3(0.0f, 0.0f, 0.0f), holePunchBackgroundSettings.source.solidColor); + EXPECT_FALSE(holePunchBackgroundSettings.disableBlending); + EXPECT_EQ(1.0f, holePunchBackgroundSettings.alpha); } return futureOf({NO_ERROR, base::unique_fd()}); @@ -717,27 +717,27 @@ TEST_F(CachedSetTest, addHolePunch_noBuffer) { const auto drawLayers = [&](const renderengine::DisplaySettings&, - const std::vector& layers, + const std::vector& layers, const std::shared_ptr&, const bool, - base::unique_fd &&) -> std::future { + base::unique_fd&&) -> std::future { // If the highlight layer is enabled, it will increase the size by 1. // We're interested in the third layer either way. EXPECT_GE(layers.size(), 4u); { - const auto* holePunchSettings = layers[3]; - EXPECT_EQ(nullptr, holePunchSettings->source.buffer.buffer); - EXPECT_EQ(half3(0.0f, 0.0f, 0.0f), holePunchSettings->source.solidColor); - EXPECT_TRUE(holePunchSettings->disableBlending); - EXPECT_EQ(0.0f, holePunchSettings->alpha); + const auto holePunchSettings = layers[3]; + EXPECT_EQ(nullptr, holePunchSettings.source.buffer.buffer); + EXPECT_EQ(half3(0.0f, 0.0f, 0.0f), holePunchSettings.source.solidColor); + EXPECT_TRUE(holePunchSettings.disableBlending); + EXPECT_EQ(0.0f, holePunchSettings.alpha); } { - const auto* holePunchBackgroundSettings = layers[0]; - EXPECT_EQ(nullptr, holePunchBackgroundSettings->source.buffer.buffer); - EXPECT_EQ(half3(0.0f, 0.0f, 0.0f), holePunchBackgroundSettings->source.solidColor); - EXPECT_FALSE(holePunchBackgroundSettings->disableBlending); - EXPECT_EQ(1.0f, holePunchBackgroundSettings->alpha); + const auto holePunchBackgroundSettings = layers[0]; + EXPECT_EQ(nullptr, holePunchBackgroundSettings.source.buffer.buffer); + EXPECT_EQ(half3(0.0f, 0.0f, 0.0f), holePunchBackgroundSettings.source.solidColor); + EXPECT_FALSE(holePunchBackgroundSettings.disableBlending); + EXPECT_EQ(1.0f, holePunchBackgroundSettings.alpha); } return futureOf({NO_ERROR, base::unique_fd()}); @@ -867,16 +867,16 @@ TEST_F(CachedSetTest, addBlur) { const auto drawLayers = [&](const renderengine::DisplaySettings&, - const std::vector& layers, + const std::vector& layers, const std::shared_ptr&, const bool, - base::unique_fd &&) -> std::future { + base::unique_fd&&) -> std::future { // If the highlight layer is enabled, it will increase the size by 1. // We're interested in the third layer either way. EXPECT_GE(layers.size(), 3u); - const auto* blurSettings = layers[2]; - EXPECT_TRUE(blurSettings->skipContentDraw); - EXPECT_EQ(half3(0.0f, 0.0f, 0.0f), blurSettings->source.solidColor); - EXPECT_EQ(0.0f, blurSettings->alpha); + const auto blurSettings = layers[2]; + EXPECT_TRUE(blurSettings.skipContentDraw); + EXPECT_EQ(half3(0.0f, 0.0f, 0.0f), blurSettings.source.solidColor); + EXPECT_EQ(0.0f, blurSettings.alpha); return futureOf({NO_ERROR, base::unique_fd()}); }; diff --git a/services/surfaceflinger/Layer.cpp b/services/surfaceflinger/Layer.cpp index 5707c67a56..d68cf9720f 100644 --- a/services/surfaceflinger/Layer.cpp +++ b/services/surfaceflinger/Layer.cpp @@ -221,7 +221,8 @@ LayerCreationArgs::LayerCreationArgs(SurfaceFlinger* flinger, sp client, * Layer. So, the implementation is done in BufferLayer. When called on a * EffectLayer object, it's essentially a NOP. */ -void Layer::onLayerDisplayed(const sp& /*releaseFence*/) {} +void Layer::onLayerDisplayed( + std::shared_future /*futureRenderEngineResult*/) {} void Layer::removeRelativeZ(const std::vector& layersInTree) { if (mDrawingState.zOrderRelativeOf == nullptr) { diff --git a/services/surfaceflinger/Layer.h b/services/surfaceflinger/Layer.h index 07b2eb5130..4569f9af23 100644 --- a/services/surfaceflinger/Layer.h +++ b/services/surfaceflinger/Layer.h @@ -616,7 +616,8 @@ public: void prepareCompositionState(compositionengine::LayerFE::StateSubset subset) override; std::vector prepareClientCompositionList( compositionengine::LayerFE::ClientCompositionTargetSettings&) override; - void onLayerDisplayed(const sp& releaseFence) override; + void onLayerDisplayed( + std::shared_future futureRenderEngineResult) override; void setWasClientComposed(const sp& fence) override { mLastClientCompositionFence = fence; diff --git a/services/surfaceflinger/RegionSamplingThread.cpp b/services/surfaceflinger/RegionSamplingThread.cpp index aa2fec56ad..d0f56b5bdd 100644 --- a/services/surfaceflinger/RegionSamplingThread.cpp +++ b/services/surfaceflinger/RegionSamplingThread.cpp @@ -356,10 +356,13 @@ void RegionSamplingThread::captureSample() { renderengine::ExternalTexture::Usage::WRITEABLE); } - const sp captureListener = new SyncScreenCaptureListener(); - mFlinger.captureScreenCommon(std::move(renderAreaFuture), traverseLayers, buffer, - true /* regionSampling */, false /* grayscale */, captureListener); - ScreenCaptureResults captureResults = captureListener->waitForResults(); + auto captureScreenResultFuture = + mFlinger.captureScreenCommon(std::move(renderAreaFuture), traverseLayers, buffer, + true /* regionSampling */, false /* grayscale */, nullptr); + auto& captureScreenResult = captureScreenResultFuture.get(); + if (captureScreenResult.drawFence.ok()) { + sync_wait(captureScreenResult.drawFence.get(), -1); + } std::vector activeDescriptors; for (const auto& descriptor : descriptors) { diff --git a/services/surfaceflinger/SurfaceFlinger.cpp b/services/surfaceflinger/SurfaceFlinger.cpp index acb81dc41c..638458cfd3 100644 --- a/services/surfaceflinger/SurfaceFlinger.cpp +++ b/services/surfaceflinger/SurfaceFlinger.cpp @@ -5972,9 +5972,10 @@ status_t SurfaceFlinger::captureDisplay(const DisplayCaptureArgs& args, traverseLayersInLayerStack(layerStack, args.uid, visitor); }; - return captureScreenCommon(std::move(renderAreaFuture), traverseLayers, reqSize, - args.pixelFormat, args.allowProtected, args.grayscale, - captureListener); + auto captureResultFuture = captureScreenCommon(std::move(renderAreaFuture), traverseLayers, + reqSize, args.pixelFormat, args.allowProtected, + args.grayscale, captureListener); + return captureResultFuture.get().status; } status_t SurfaceFlinger::captureDisplay(DisplayId displayId, @@ -6009,9 +6010,15 @@ status_t SurfaceFlinger::captureDisplay(DisplayId displayId, traverseLayersInLayerStack(layerStack, CaptureArgs::UNSET_UID, visitor); }; - return captureScreenCommon(std::move(renderAreaFuture), traverseLayers, size, - ui::PixelFormat::RGBA_8888, false /* allowProtected */, - false /* grayscale */, captureListener); + if (captureListener == nullptr) { + ALOGE("capture screen must provide a capture listener callback"); + return BAD_VALUE; + } + auto captureResultFuture = + captureScreenCommon(std::move(renderAreaFuture), traverseLayers, size, + ui::PixelFormat::RGBA_8888, false /* allowProtected */, + false /* grayscale */, captureListener); + return captureResultFuture.get().status; } status_t SurfaceFlinger::captureLayers(const LayerCaptureArgs& args, @@ -6138,23 +6145,28 @@ status_t SurfaceFlinger::captureLayers(const LayerCaptureArgs& args, }); }; - return captureScreenCommon(std::move(renderAreaFuture), traverseLayers, reqSize, - args.pixelFormat, args.allowProtected, args.grayscale, - captureListener); + if (captureListener == nullptr) { + ALOGE("capture screen must provide a capture listener callback"); + return BAD_VALUE; + } + + auto captureResultFuture = captureScreenCommon(std::move(renderAreaFuture), traverseLayers, + reqSize, args.pixelFormat, args.allowProtected, + args.grayscale, captureListener); + return captureResultFuture.get().status; } -status_t SurfaceFlinger::captureScreenCommon(RenderAreaFuture renderAreaFuture, - TraverseLayersFunction traverseLayers, - ui::Size bufferSize, ui::PixelFormat reqPixelFormat, - bool allowProtected, bool grayscale, - const sp& captureListener) { +std::shared_future SurfaceFlinger::captureScreenCommon( + RenderAreaFuture renderAreaFuture, TraverseLayersFunction traverseLayers, + ui::Size bufferSize, ui::PixelFormat reqPixelFormat, bool allowProtected, bool grayscale, + const sp& captureListener) { ATRACE_CALL(); if (exceedsMaxRenderTargetSize(bufferSize.getWidth(), bufferSize.getHeight())) { ALOGE("Attempted to capture screen with size (%" PRId32 ", %" PRId32 ") that exceeds render target size limit.", bufferSize.getWidth(), bufferSize.getHeight()); - return BAD_VALUE; + return ftl::yield({BAD_VALUE, base::unique_fd()}).share(); } // Loop over all visible layers to see whether there's any protected layer. A protected layer is @@ -6194,25 +6206,23 @@ status_t SurfaceFlinger::captureScreenCommon(RenderAreaFuture renderAreaFuture, false /* regionSampling */, grayscale, captureListener); } -status_t SurfaceFlinger::captureScreenCommon( +std::shared_future SurfaceFlinger::captureScreenCommon( RenderAreaFuture renderAreaFuture, TraverseLayersFunction traverseLayers, const std::shared_ptr& buffer, bool regionSampling, bool grayscale, const sp& captureListener) { ATRACE_CALL(); - if (captureListener == nullptr) { - ALOGE("capture screen must provide a capture listener callback"); - return BAD_VALUE; - } - bool canCaptureBlackoutContent = hasCaptureBlackoutContentPermission(); - static_cast(schedule([=, renderAreaFuture = std::move(renderAreaFuture)]() mutable { + auto scheduleResultFuture = schedule([=, + renderAreaFuture = std::move(renderAreaFuture)]() mutable + -> std::shared_future { if (mRefreshPending) { ALOGW("Skipping screenshot for now"); captureScreenCommon(std::move(renderAreaFuture), traverseLayers, buffer, regionSampling, grayscale, captureListener); - return; + return ftl::yield({NO_ERROR, base::unique_fd()}) + .share(); } ScreenCaptureResults captureResults; std::unique_ptr renderArea = renderAreaFuture.get(); @@ -6220,24 +6230,44 @@ status_t SurfaceFlinger::captureScreenCommon( ALOGW("Skipping screen capture because of invalid render area."); captureResults.result = NO_MEMORY; captureListener->onScreenCaptureCompleted(captureResults); - return; + return ftl::yield({NO_ERROR, base::unique_fd()}) + .share(); } - status_t result = NO_ERROR; + std::shared_future renderEngineResultFuture; + renderArea->render([&] { - result = renderScreenImplLocked(*renderArea, traverseLayers, buffer, - canCaptureBlackoutContent, regionSampling, grayscale, - captureResults); + renderEngineResultFuture = + renderScreenImplLocked(*renderArea, traverseLayers, buffer, + canCaptureBlackoutContent, regionSampling, grayscale, + captureResults); }); + // spring up a thread to unblock SF main thread and wait for + // RenderEngineResult to be available + if (captureListener != nullptr) { + std::async([=]() mutable { + ATRACE_NAME("captureListener is nonnull!"); + auto& [status, drawFence] = renderEngineResultFuture.get(); + captureResults.result = status; + captureResults.fence = new Fence(dup(drawFence)); + captureListener->onScreenCaptureCompleted(captureResults); + }); + } + return renderEngineResultFuture; + }); - captureResults.result = result; - captureListener->onScreenCaptureCompleted(captureResults); - })); - - return NO_ERROR; + // flatten scheduleResultFuture object to single shared_future object + std::future captureScreenResultFuture = + ftl::chain(std::move(scheduleResultFuture)) + .then([=](std::shared_future futureObject) + -> renderengine::RenderEngineResult { + auto& [status, drawFence] = futureObject.get(); + return {status, base::unique_fd(dup(drawFence))}; + }); + return captureScreenResultFuture.share(); } -status_t SurfaceFlinger::renderScreenImplLocked( +std::shared_future SurfaceFlinger::renderScreenImplLocked( const RenderArea& renderArea, TraverseLayersFunction traverseLayers, const std::shared_ptr& buffer, bool canCaptureBlackoutContent, bool regionSampling, bool grayscale, @@ -6256,7 +6286,8 @@ status_t SurfaceFlinger::renderScreenImplLocked( // the impetus on WindowManager to not persist them. if (captureResults.capturedSecureLayers && !canCaptureBlackoutContent) { ALOGW("FB is protected: PERMISSION_DENIED"); - return PERMISSION_DENIED; + return ftl::yield({PERMISSION_DENIED, base::unique_fd()}) + .share(); } captureResults.buffer = buffer->getBuffer(); @@ -6338,11 +6369,12 @@ status_t SurfaceFlinger::renderScreenImplLocked( }); - std::vector clientCompositionLayerPointers( - clientCompositionLayers.size()); + std::vector clientRenderEngineLayers; + clientRenderEngineLayers.reserve(clientCompositionLayers.size()); std::transform(clientCompositionLayers.begin(), clientCompositionLayers.end(), - clientCompositionLayerPointers.begin(), - std::pointer_traits::pointer_to); + std::back_inserter(clientRenderEngineLayers), + [](compositionengine::LayerFE::LayerSettings& settings) + -> renderengine::LayerSettings { return settings; }); // Use an empty fence for the buffer fence, since we just created the buffer so // there is no need for synchronization with the GPU. @@ -6350,24 +6382,22 @@ status_t SurfaceFlinger::renderScreenImplLocked( getRenderEngine().useProtectedContext(useProtected); const constexpr bool kUseFramebufferCache = false; - auto [status, drawFence] = - getRenderEngine() - .drawLayers(clientCompositionDisplay, clientCompositionLayerPointers, buffer, - kUseFramebufferCache, std::move(bufferFence)) - .get(); + std::future drawLayersResult = + getRenderEngine().drawLayers(clientCompositionDisplay, clientRenderEngineLayers, buffer, + kUseFramebufferCache, std::move(bufferFence)); - if (drawFence >= 0) { - sp releaseFence = new Fence(dup(drawFence)); - for (auto* layer : renderedLayers) { - layer->onLayerDisplayed(releaseFence); - } + std::shared_future drawLayersResultFuture = + drawLayersResult.share(); // drawLayersResult will be moved to shared one + + for (auto* layer : renderedLayers) { + // make a copy of shared_future object for each layer + layer->onLayerDisplayed(drawLayersResultFuture); } - captureResults.fence = new Fence(drawFence.release()); // Always switch back to unprotected context. getRenderEngine().useProtectedContext(false); - return status; + return drawLayersResultFuture; } void SurfaceFlinger::windowInfosReported() { diff --git a/services/surfaceflinger/SurfaceFlinger.h b/services/surfaceflinger/SurfaceFlinger.h index 1f0e42ddf3..45fd94e50c 100644 --- a/services/surfaceflinger/SurfaceFlinger.h +++ b/services/surfaceflinger/SurfaceFlinger.h @@ -906,17 +906,17 @@ private: // Boot animation, on/off animations and screen capture void startBootAnim(); - status_t captureScreenCommon(RenderAreaFuture, TraverseLayersFunction, ui::Size bufferSize, - ui::PixelFormat, bool allowProtected, bool grayscale, - const sp&); - status_t captureScreenCommon(RenderAreaFuture, TraverseLayersFunction, - const std::shared_ptr&, - bool regionSampling, bool grayscale, - const sp&); - status_t renderScreenImplLocked(const RenderArea&, TraverseLayersFunction, - const std::shared_ptr&, - bool canCaptureBlackoutContent, bool regionSampling, - bool grayscale, ScreenCaptureResults&); + std::shared_future captureScreenCommon( + RenderAreaFuture, TraverseLayersFunction, ui::Size bufferSize, ui::PixelFormat, + bool allowProtected, bool grayscale, const sp&); + std::shared_future captureScreenCommon( + RenderAreaFuture, TraverseLayersFunction, + const std::shared_ptr&, bool regionSampling, + bool grayscale, const sp&); + std::shared_future renderScreenImplLocked( + const RenderArea&, TraverseLayersFunction, + const std::shared_ptr&, bool canCaptureBlackoutContent, + bool regionSampling, bool grayscale, ScreenCaptureResults&); // If the uid provided is not UNSET_UID, the traverse will skip any layers that don't have a // matching ownerUid diff --git a/services/surfaceflinger/TransactionCallbackInvoker.cpp b/services/surfaceflinger/TransactionCallbackInvoker.cpp index c1eb8966d1..8fbf0b4d07 100644 --- a/services/surfaceflinger/TransactionCallbackInvoker.cpp +++ b/services/surfaceflinger/TransactionCallbackInvoker.cpp @@ -154,6 +154,38 @@ status_t TransactionCallbackInvoker::addCallbackHandle(const sp& // destroyed the client side is dead and there won't be anyone to send the callback to. sp surfaceControl = handle->surfaceControl.promote(); if (surfaceControl) { + sp prevFence = nullptr; + + for (const auto& futureStruct : handle->previousReleaseFences) { + sp currentFence = sp::make(dup(futureStruct.get().drawFence)); + if (prevFence == nullptr && currentFence->getStatus() != Fence::Status::Invalid) { + prevFence = currentFence; + handle->previousReleaseFence = prevFence; + } else if (prevFence != nullptr) { + // If both fences are signaled or both are unsignaled, we need to merge + // them to get an accurate timestamp. + if (prevFence->getStatus() != Fence::Status::Invalid && + prevFence->getStatus() == currentFence->getStatus()) { + char fenceName[32] = {}; + snprintf(fenceName, 32, "%.28s", handle->name.c_str()); + sp mergedFence = Fence::merge(fenceName, prevFence, currentFence); + if (mergedFence->isValid()) { + handle->previousReleaseFence = mergedFence; + prevFence = handle->previousReleaseFence; + } + } else if (currentFence->getStatus() == Fence::Status::Unsignaled) { + // If one fence has signaled and the other hasn't, the unsignaled + // fence will approximately correspond with the correct timestamp. + // There's a small race if both fences signal at about the same time + // and their statuses are retrieved with unfortunate timing. However, + // by this point, they will have both signaled and only the timestamp + // will be slightly off; any dependencies after this point will + // already have been met. + handle->previousReleaseFence = currentFence; + } + } + } + handle->previousReleaseFences = {}; FrameEventHistoryStats eventStats(handle->frameNumber, handle->gpuCompositionDoneFence->getSnapshot().fence, handle->compositorTiming, handle->refreshStartTime, diff --git a/services/surfaceflinger/TransactionCallbackInvoker.h b/services/surfaceflinger/TransactionCallbackInvoker.h index 7e879e119b..100dbfa8aa 100644 --- a/services/surfaceflinger/TransactionCallbackInvoker.h +++ b/services/surfaceflinger/TransactionCallbackInvoker.h @@ -18,8 +18,9 @@ #include #include -#include +#include #include +#include #include #include #include @@ -28,6 +29,7 @@ #include #include +#include #include namespace android { @@ -42,7 +44,9 @@ public: wp surfaceControl; bool releasePreviousBuffer = false; + std::string name; sp previousReleaseFence; + std::vector> previousReleaseFences; nsecs_t acquireTime = -1; nsecs_t latchTime = -1; uint32_t transformHint = 0; diff --git a/services/surfaceflinger/tests/unittests/CompositionTest.cpp b/services/surfaceflinger/tests/unittests/CompositionTest.cpp index 5135ff952f..61c7c398dd 100644 --- a/services/surfaceflinger/tests/unittests/CompositionTest.cpp +++ b/services/surfaceflinger/tests/unittests/CompositionTest.cpp @@ -247,10 +247,16 @@ void CompositionTest::captureScreenComposition() { "screenshot"), *mRenderEngine, true); - status_t result = - mFlinger.renderScreenImplLocked(*renderArea, traverseLayers, mCaptureScreenBuffer, - forSystem, regionSampling); - EXPECT_EQ(NO_ERROR, result); + auto result = mFlinger.renderScreenImplLocked(*renderArea, traverseLayers, mCaptureScreenBuffer, + forSystem, regionSampling); + EXPECT_TRUE(result.valid()); + + auto& [status, drawFence] = result.get(); + + EXPECT_EQ(NO_ERROR, status); + if (drawFence.ok()) { + sync_wait(drawFence.get(), -1); + } LayerCase::cleanup(this); } @@ -346,9 +352,9 @@ struct BaseDisplayVariant { static void setupCommonScreensCaptureCallExpectations(CompositionTest* test) { EXPECT_CALL(*test->mRenderEngine, drawLayers) .WillRepeatedly([&](const renderengine::DisplaySettings& displaySettings, - const std::vector&, + const std::vector&, const std::shared_ptr&, - const bool, base::unique_fd &&) + const bool, base::unique_fd&&) -> std::future { EXPECT_EQ(DEFAULT_DISPLAY_MAX_LUMINANCE, displaySettings.maxLuminance); EXPECT_EQ(Rect(DEFAULT_DISPLAY_WIDTH, DEFAULT_DISPLAY_HEIGHT), @@ -397,9 +403,9 @@ struct BaseDisplayVariant { Return(0))); EXPECT_CALL(*test->mRenderEngine, drawLayers) .WillRepeatedly([&](const renderengine::DisplaySettings& displaySettings, - const std::vector&, + const std::vector&, const std::shared_ptr&, - const bool, base::unique_fd &&) + const bool, base::unique_fd&&) -> std::future { EXPECT_EQ(DEFAULT_DISPLAY_MAX_LUMINANCE, displaySettings.maxLuminance); EXPECT_EQ(Rect(DEFAULT_DISPLAY_WIDTH, DEFAULT_DISPLAY_HEIGHT), @@ -633,9 +639,9 @@ struct BaseLayerProperties { static void setupREBufferCompositionCommonCallExpectations(CompositionTest* test) { EXPECT_CALL(*test->mRenderEngine, drawLayers) .WillOnce([&](const renderengine::DisplaySettings& displaySettings, - const std::vector& layerSettings, + const std::vector& layerSettings, const std::shared_ptr&, const bool, - base::unique_fd &&) -> std::future { + base::unique_fd&&) -> std::future { EXPECT_EQ(DEFAULT_DISPLAY_MAX_LUMINANCE, displaySettings.maxLuminance); EXPECT_EQ(Rect(DEFAULT_DISPLAY_WIDTH, DEFAULT_DISPLAY_HEIGHT), displaySettings.physicalDisplay); @@ -652,16 +658,16 @@ struct BaseLayerProperties { "verification lambda"; return resultFuture; } - const renderengine::LayerSettings* layer = layerSettings.back(); - EXPECT_THAT(layer->source.buffer.buffer, Not(IsNull())); - EXPECT_THAT(layer->source.buffer.fence, Not(IsNull())); - EXPECT_EQ(DEFAULT_TEXTURE_ID, layer->source.buffer.textureName); - EXPECT_EQ(false, layer->source.buffer.isY410BT2020); - EXPECT_EQ(true, layer->source.buffer.usePremultipliedAlpha); - EXPECT_EQ(false, layer->source.buffer.isOpaque); - EXPECT_EQ(0.0, layer->geometry.roundedCornersRadius); - EXPECT_EQ(ui::Dataspace::UNKNOWN, layer->sourceDataspace); - EXPECT_EQ(LayerProperties::COLOR[3], layer->alpha); + const renderengine::LayerSettings layer = layerSettings.back(); + EXPECT_THAT(layer.source.buffer.buffer, Not(IsNull())); + EXPECT_THAT(layer.source.buffer.fence, Not(IsNull())); + EXPECT_EQ(DEFAULT_TEXTURE_ID, layer.source.buffer.textureName); + EXPECT_EQ(false, layer.source.buffer.isY410BT2020); + EXPECT_EQ(true, layer.source.buffer.usePremultipliedAlpha); + EXPECT_EQ(false, layer.source.buffer.isOpaque); + EXPECT_EQ(0.0, layer.geometry.roundedCornersRadius); + EXPECT_EQ(ui::Dataspace::UNKNOWN, layer.sourceDataspace); + EXPECT_EQ(LayerProperties::COLOR[3], layer.alpha); return resultFuture; }); } @@ -685,9 +691,9 @@ struct BaseLayerProperties { static void setupREColorCompositionCallExpectations(CompositionTest* test) { EXPECT_CALL(*test->mRenderEngine, drawLayers) .WillOnce([&](const renderengine::DisplaySettings& displaySettings, - const std::vector& layerSettings, + const std::vector& layerSettings, const std::shared_ptr&, const bool, - base::unique_fd &&) -> std::future { + base::unique_fd&&) -> std::future { EXPECT_EQ(DEFAULT_DISPLAY_MAX_LUMINANCE, displaySettings.maxLuminance); EXPECT_EQ(Rect(DEFAULT_DISPLAY_WIDTH, DEFAULT_DISPLAY_HEIGHT), displaySettings.physicalDisplay); @@ -704,14 +710,14 @@ struct BaseLayerProperties { "setupREColorCompositionCallExpectations verification lambda"; return resultFuture; } - const renderengine::LayerSettings* layer = layerSettings.back(); - EXPECT_THAT(layer->source.buffer.buffer, IsNull()); + const renderengine::LayerSettings layer = layerSettings.back(); + EXPECT_THAT(layer.source.buffer.buffer, IsNull()); EXPECT_EQ(half3(LayerProperties::COLOR[0], LayerProperties::COLOR[1], LayerProperties::COLOR[2]), - layer->source.solidColor); - EXPECT_EQ(0.0, layer->geometry.roundedCornersRadius); - EXPECT_EQ(ui::Dataspace::UNKNOWN, layer->sourceDataspace); - EXPECT_EQ(LayerProperties::COLOR[3], layer->alpha); + layer.source.solidColor); + EXPECT_EQ(0.0, layer.geometry.roundedCornersRadius); + EXPECT_EQ(ui::Dataspace::UNKNOWN, layer.sourceDataspace); + EXPECT_EQ(LayerProperties::COLOR[3], layer.alpha); return resultFuture; }); } @@ -765,9 +771,9 @@ struct CommonSecureLayerProperties : public BaseLayerProperties static void setupInsecureREBufferCompositionCommonCallExpectations(CompositionTest* test) { EXPECT_CALL(*test->mRenderEngine, drawLayers) .WillOnce([&](const renderengine::DisplaySettings& displaySettings, - const std::vector& layerSettings, + const std::vector& layerSettings, const std::shared_ptr&, const bool, - base::unique_fd &&) -> std::future { + base::unique_fd&&) -> std::future { EXPECT_EQ(DEFAULT_DISPLAY_MAX_LUMINANCE, displaySettings.maxLuminance); EXPECT_EQ(Rect(DEFAULT_DISPLAY_WIDTH, DEFAULT_DISPLAY_HEIGHT), displaySettings.physicalDisplay); @@ -784,12 +790,12 @@ struct CommonSecureLayerProperties : public BaseLayerProperties "verification lambda"; return resultFuture; } - const renderengine::LayerSettings* layer = layerSettings.back(); - EXPECT_THAT(layer->source.buffer.buffer, IsNull()); - EXPECT_EQ(half3(0.0f, 0.0f, 0.0f), layer->source.solidColor); - EXPECT_EQ(0.0, layer->geometry.roundedCornersRadius); - EXPECT_EQ(ui::Dataspace::UNKNOWN, layer->sourceDataspace); - EXPECT_EQ(1.0f, layer->alpha); + const renderengine::LayerSettings layer = layerSettings.back(); + EXPECT_THAT(layer.source.buffer.buffer, IsNull()); + EXPECT_EQ(half3(0.0f, 0.0f, 0.0f), layer.source.solidColor); + EXPECT_EQ(0.0, layer.geometry.roundedCornersRadius); + EXPECT_EQ(ui::Dataspace::UNKNOWN, layer.sourceDataspace); + EXPECT_EQ(1.0f, layer.alpha); return resultFuture; }); } -- cgit v1.2.3-59-g8ed1b From 2109270e74a18585aceffc94d1758cee47bb4175 Mon Sep 17 00:00:00 2001 From: Vladimir Marko Date: Tue, 12 Oct 2021 12:43:47 +0000 Subject: Revert "Second Patch for async RenderEngine" Revert "Fix vender implementation due to second patch of async R..." Revert submission 15644535-asyncRenderEngineV2 Reason for revert: Broke multiple tests Reverted Changes: I772122750:Fix vts cases due to function change for async ren... I615f2927d:Second Patch for async RenderEngine I3f47b8b67:Fix vender implementation due to second patch of a... Bug: 202803359 Bug: 202808760 Change-Id: Ib8ef68747621b7114cf2d1dfb856292674729744 --- libs/renderengine/RenderEngine.cpp | 2 +- libs/renderengine/gl/GLESRenderEngine.cpp | 66 +++++------ libs/renderengine/gl/GLESRenderEngine.h | 2 +- .../include/renderengine/RenderEngine.h | 4 +- .../include/renderengine/mock/RenderEngine.h | 4 +- libs/renderengine/skia/Cache.cpp | 16 +-- libs/renderengine/skia/SkiaGLRenderEngine.cpp | 113 +++++++++--------- libs/renderengine/skia/SkiaGLRenderEngine.h | 7 +- libs/renderengine/skia/SkiaRenderEngine.h | 2 +- libs/renderengine/tests/RenderEngineTest.cpp | 125 ++++++++++--------- .../tests/RenderEngineThreadedTest.cpp | 7 +- .../renderengine/threaded/RenderEngineThreaded.cpp | 11 +- libs/renderengine/threaded/RenderEngineThreaded.h | 4 +- services/surfaceflinger/BufferQueueLayer.cpp | 4 +- services/surfaceflinger/BufferQueueLayer.h | 3 +- services/surfaceflinger/BufferStateLayer.cpp | 88 +++++++++++--- services/surfaceflinger/BufferStateLayer.h | 8 +- .../include/compositionengine/LayerFE.h | 4 +- .../include/compositionengine/mock/LayerFE.h | 2 +- .../CompositionEngine/src/Output.cpp | 23 ++-- .../CompositionEngine/src/planner/CachedSet.cpp | 17 ++- .../CompositionEngine/tests/OutputTest.cpp | 87 +++++--------- .../tests/planner/CachedSetTest.cpp | 84 ++++++------- services/surfaceflinger/Layer.cpp | 3 +- services/surfaceflinger/Layer.h | 3 +- services/surfaceflinger/RegionSamplingThread.cpp | 11 +- services/surfaceflinger/SurfaceFlinger.cpp | 132 ++++++++------------- services/surfaceflinger/SurfaceFlinger.h | 22 ++-- .../surfaceflinger/TransactionCallbackInvoker.cpp | 32 ----- .../surfaceflinger/TransactionCallbackInvoker.h | 6 +- .../tests/unittests/CompositionTest.cpp | 78 ++++++------ 31 files changed, 457 insertions(+), 513 deletions(-) (limited to 'services/surfaceflinger/BufferQueueLayer.cpp') diff --git a/libs/renderengine/RenderEngine.cpp b/libs/renderengine/RenderEngine.cpp index a9ea690a7c..2174df5515 100644 --- a/libs/renderengine/RenderEngine.cpp +++ b/libs/renderengine/RenderEngine.cpp @@ -96,7 +96,7 @@ void RenderEngine::validateOutputBufferUsage(const sp& buffer) { } std::future RenderEngine::drawLayers( - const DisplaySettings& display, const std::vector& layers, + const DisplaySettings& display, const std::vector& layers, const std::shared_ptr& buffer, const bool useFramebufferCache, base::unique_fd&& bufferFence) { const auto resultPromise = std::make_shared>(); diff --git a/libs/renderengine/gl/GLESRenderEngine.cpp b/libs/renderengine/gl/GLESRenderEngine.cpp index 22dd86698b..2375cb7bf1 100644 --- a/libs/renderengine/gl/GLESRenderEngine.cpp +++ b/libs/renderengine/gl/GLESRenderEngine.cpp @@ -1080,7 +1080,7 @@ EGLImageKHR GLESRenderEngine::createFramebufferImageIfNeeded(ANativeWindowBuffer void GLESRenderEngine::drawLayersInternal( const std::shared_ptr>&& resultPromise, - const DisplaySettings& display, const std::vector& layers, + const DisplaySettings& display, const std::vector& layers, const std::shared_ptr& buffer, const bool useFramebufferCache, base::unique_fd&& bufferFence) { ATRACE_CALL(); @@ -1110,10 +1110,10 @@ void GLESRenderEngine::drawLayersInternal( std::unique_ptr fbo; // Gathering layers that requested blur, we'll need them to decide when to render to an // offscreen buffer, and when to render to the native buffer. - std::deque blurLayers; + std::deque blurLayers; if (CC_LIKELY(mBlurFilter != nullptr)) { - for (const auto& layer : layers) { - if (layer.backgroundBlurRadius > 0) { + for (auto layer : layers) { + if (layer->backgroundBlurRadius > 0) { blurLayers.push_back(layer); } } @@ -1137,7 +1137,7 @@ void GLESRenderEngine::drawLayersInternal( } else { setViewportAndProjection(display.physicalDisplay, display.clip); auto status = - mBlurFilter->setAsDrawTarget(display, blurLayers.front().backgroundBlurRadius); + mBlurFilter->setAsDrawTarget(display, blurLayers.front()->backgroundBlurRadius); if (status != NO_ERROR) { ALOGE("Failed to prepare blur filter! Aborting GPU composition for buffer (%p).", buffer->getBuffer()->handle); @@ -1167,7 +1167,7 @@ void GLESRenderEngine::drawLayersInternal( .setTexCoords(2 /* size */) .setCropCoords(2 /* size */) .build(); - for (const auto& layer : layers) { + for (auto const layer : layers) { if (blurLayers.size() > 0 && blurLayers.front() == layer) { blurLayers.pop_front(); @@ -1193,7 +1193,7 @@ void GLESRenderEngine::drawLayersInternal( // There's still something else to blur, so let's keep rendering to our FBO // instead of to the display. status = mBlurFilter->setAsDrawTarget(display, - blurLayers.front().backgroundBlurRadius); + blurLayers.front()->backgroundBlurRadius); } if (status != NO_ERROR) { ALOGE("Failed to bind framebuffer! Aborting GPU composition for buffer (%p).", @@ -1214,42 +1214,42 @@ void GLESRenderEngine::drawLayersInternal( } // Ensure luminance is at least 100 nits to avoid div-by-zero - const float maxLuminance = std::max(100.f, layer.source.buffer.maxLuminanceNits); + const float maxLuminance = std::max(100.f, layer->source.buffer.maxLuminanceNits); mState.maxMasteringLuminance = maxLuminance; mState.maxContentLuminance = maxLuminance; - mState.projectionMatrix = projectionMatrix * layer.geometry.positionTransform; + mState.projectionMatrix = projectionMatrix * layer->geometry.positionTransform; - const FloatRect bounds = layer.geometry.boundaries; + const FloatRect bounds = layer->geometry.boundaries; Mesh::VertexArray position(mesh.getPositionArray()); position[0] = vec2(bounds.left, bounds.top); position[1] = vec2(bounds.left, bounds.bottom); position[2] = vec2(bounds.right, bounds.bottom); position[3] = vec2(bounds.right, bounds.top); - setupLayerCropping(layer, mesh); - setColorTransform(layer.colorTransform); + setupLayerCropping(*layer, mesh); + setColorTransform(layer->colorTransform); bool usePremultipliedAlpha = true; bool disableTexture = true; bool isOpaque = false; - if (layer.source.buffer.buffer != nullptr) { + if (layer->source.buffer.buffer != nullptr) { disableTexture = false; - isOpaque = layer.source.buffer.isOpaque; + isOpaque = layer->source.buffer.isOpaque; - sp gBuf = layer.source.buffer.buffer->getBuffer(); + sp gBuf = layer->source.buffer.buffer->getBuffer(); validateInputBufferUsage(gBuf); - bindExternalTextureBuffer(layer.source.buffer.textureName, gBuf, - layer.source.buffer.fence); + bindExternalTextureBuffer(layer->source.buffer.textureName, gBuf, + layer->source.buffer.fence); - usePremultipliedAlpha = layer.source.buffer.usePremultipliedAlpha; - Texture texture(Texture::TEXTURE_EXTERNAL, layer.source.buffer.textureName); - mat4 texMatrix = layer.source.buffer.textureTransform; + usePremultipliedAlpha = layer->source.buffer.usePremultipliedAlpha; + Texture texture(Texture::TEXTURE_EXTERNAL, layer->source.buffer.textureName); + mat4 texMatrix = layer->source.buffer.textureTransform; texture.setMatrix(texMatrix.asArray()); - texture.setFiltering(layer.source.buffer.useTextureFiltering); + texture.setFiltering(layer->source.buffer.useTextureFiltering); texture.setDimensions(gBuf->getWidth(), gBuf->getHeight()); - setSourceY410BT2020(layer.source.buffer.isY410BT2020); + setSourceY410BT2020(layer->source.buffer.isY410BT2020); renderengine::Mesh::VertexArray texCoords(mesh.getTexCoordArray()); texCoords[0] = vec2(0.0, 0.0); @@ -1264,32 +1264,32 @@ void GLESRenderEngine::drawLayersInternal( } } - const half3 solidColor = layer.source.solidColor; - const half4 color = half4(solidColor.r, solidColor.g, solidColor.b, layer.alpha); + const half3 solidColor = layer->source.solidColor; + const half4 color = half4(solidColor.r, solidColor.g, solidColor.b, layer->alpha); // Buffer sources will have a black solid color ignored in the shader, // so in that scenario the solid color passed here is arbitrary. setupLayerBlending(usePremultipliedAlpha, isOpaque, disableTexture, color, - layer.geometry.roundedCornersRadius); - if (layer.disableBlending) { + layer->geometry.roundedCornersRadius); + if (layer->disableBlending) { glDisable(GL_BLEND); } - setSourceDataSpace(layer.sourceDataspace); + setSourceDataSpace(layer->sourceDataspace); - if (layer.shadow.length > 0.0f) { - handleShadow(layer.geometry.boundaries, layer.geometry.roundedCornersRadius, - layer.shadow); + if (layer->shadow.length > 0.0f) { + handleShadow(layer->geometry.boundaries, layer->geometry.roundedCornersRadius, + layer->shadow); } // We only want to do a special handling for rounded corners when having rounded corners // is the only reason it needs to turn on blending, otherwise, we handle it like the // usual way since it needs to turn on blending anyway. - else if (layer.geometry.roundedCornersRadius > 0.0 && color.a >= 1.0f && isOpaque) { - handleRoundedCorners(display, layer, mesh); + else if (layer->geometry.roundedCornersRadius > 0.0 && color.a >= 1.0f && isOpaque) { + handleRoundedCorners(display, *layer, mesh); } else { drawMesh(mesh); } // Cleanup if there's a buffer source - if (layer.source.buffer.buffer != nullptr) { + if (layer->source.buffer.buffer != nullptr) { disableBlending(); setSourceY410BT2020(false); disableTexturing(); diff --git a/libs/renderengine/gl/GLESRenderEngine.h b/libs/renderengine/gl/GLESRenderEngine.h index 1d7c2cafb5..c4adfdf752 100644 --- a/libs/renderengine/gl/GLESRenderEngine.h +++ b/libs/renderengine/gl/GLESRenderEngine.h @@ -104,7 +104,7 @@ protected: bool canSkipPostRenderCleanup() const override; void drawLayersInternal(const std::shared_ptr>&& resultPromise, const DisplaySettings& display, - const std::vector& layers, + const std::vector& layers, const std::shared_ptr& buffer, const bool useFramebufferCache, base::unique_fd&& bufferFence) override; diff --git a/libs/renderengine/include/renderengine/RenderEngine.h b/libs/renderengine/include/renderengine/RenderEngine.h index b9cc6485e5..701c1f2071 100644 --- a/libs/renderengine/include/renderengine/RenderEngine.h +++ b/libs/renderengine/include/renderengine/RenderEngine.h @@ -160,7 +160,7 @@ public: // @return A future object of RenderEngineResult struct indicating whether // drawing was successful in async mode. virtual std::future drawLayers( - const DisplaySettings& display, const std::vector& layers, + const DisplaySettings& display, const std::vector& layers, const std::shared_ptr& buffer, const bool useFramebufferCache, base::unique_fd&& bufferFence); @@ -231,7 +231,7 @@ protected: virtual void drawLayersInternal( const std::shared_ptr>&& resultPromise, - const DisplaySettings& display, const std::vector& layers, + const DisplaySettings& display, const std::vector& layers, const std::shared_ptr& buffer, const bool useFramebufferCache, base::unique_fd&& bufferFence) = 0; }; diff --git a/libs/renderengine/include/renderengine/mock/RenderEngine.h b/libs/renderengine/include/renderengine/mock/RenderEngine.h index 248bd652c0..a7e6809223 100644 --- a/libs/renderengine/include/renderengine/mock/RenderEngine.h +++ b/libs/renderengine/include/renderengine/mock/RenderEngine.h @@ -49,12 +49,12 @@ public: MOCK_CONST_METHOD0(canSkipPostRenderCleanup, bool()); MOCK_METHOD5(drawLayers, std::future(const DisplaySettings&, - const std::vector&, + const std::vector&, const std::shared_ptr&, const bool, base::unique_fd&&)); MOCK_METHOD6(drawLayersInternal, void(const std::shared_ptr>&&, - const DisplaySettings&, const std::vector&, + const DisplaySettings&, const std::vector&, const std::shared_ptr&, const bool, base::unique_fd&&)); MOCK_METHOD0(cleanFramebufferCache, void()); MOCK_METHOD0(getContextPriority, int()); diff --git a/libs/renderengine/skia/Cache.cpp b/libs/renderengine/skia/Cache.cpp index b18a872836..c4fa1bb091 100644 --- a/libs/renderengine/skia/Cache.cpp +++ b/libs/renderengine/skia/Cache.cpp @@ -95,7 +95,7 @@ static void drawShadowLayers(SkiaRenderEngine* renderengine, const DisplaySettin .alpha = 1, }; - auto layers = std::vector{layer, caster}; + auto layers = std::vector{&layer, &caster}; // Four combinations of settings are used (two transforms here, and drawShadowLayers is // called with two different destination data spaces) They're all rounded rect. // Three of these are cache misses that generate new shaders. @@ -140,7 +140,7 @@ static void drawImageLayers(SkiaRenderEngine* renderengine, const DisplaySetting }}, }; - auto layers = std::vector{layer}; + auto layers = std::vector{&layer}; for (auto dataspace : {kDestDataSpace, kOtherDataSpace}) { layer.sourceDataspace = dataspace; // Cache shaders for both rects and round rects. @@ -176,7 +176,7 @@ static void drawSolidLayers(SkiaRenderEngine* renderengine, const DisplaySetting .alpha = 0.5, }; - auto layers = std::vector{layer}; + auto layers = std::vector{&layer}; for (auto transform : {mat4(), kScaleAndTranslate}) { layer.geometry.positionTransform = transform; for (float roundedCornersRadius : {0.0f, 50.f}) { @@ -201,7 +201,7 @@ static void drawBlurLayers(SkiaRenderEngine* renderengine, const DisplaySettings .skipContentDraw = true, }; - auto layers = std::vector{layer}; + auto layers = std::vector{&layer}; // Different blur code is invoked for radii less and greater than 30 pixels for (int radius : {9, 60}) { layer.backgroundBlurRadius = radius; @@ -242,7 +242,7 @@ static void drawClippedLayers(SkiaRenderEngine* renderengine, const DisplaySetti }, }; - auto layers = std::vector{layer}; + auto layers = std::vector{&layer}; for (auto pixelSource : {bufferSource, bufferOpaque, colorSource}) { layer.source = pixelSource; for (auto dataspace : {kDestDataSpace, kOtherDataSpace}) { @@ -289,7 +289,7 @@ static void drawPIPImageLayer(SkiaRenderEngine* renderengine, const DisplaySetti }; - auto layers = std::vector{layer}; + auto layers = std::vector{&layer}; renderengine->drawLayers(display, layers, dstTexture, kUseFrameBufferCache, base::unique_fd()); } @@ -317,7 +317,7 @@ static void drawHolePunchLayer(SkiaRenderEngine* renderengine, const DisplaySett }; - auto layers = std::vector{layer}; + auto layers = std::vector{&layer}; renderengine->drawLayers(display, layers, dstTexture, kUseFrameBufferCache, base::unique_fd()); } @@ -429,7 +429,7 @@ void Cache::primeShaderCache(SkiaRenderEngine* renderengine) { LayerSettings layer{ .source = PixelSource{.solidColor = half3(0.f, 0.f, 0.f)}, }; - auto layers = std::vector{layer}; + auto layers = std::vector{&layer}; // call get() to make it synchronous renderengine ->drawLayers(display, layers, dstTexture, kUseFrameBufferCache, base::unique_fd()) diff --git a/libs/renderengine/skia/SkiaGLRenderEngine.cpp b/libs/renderengine/skia/SkiaGLRenderEngine.cpp index d5ec774e9c..cb686a643a 100644 --- a/libs/renderengine/skia/SkiaGLRenderEngine.cpp +++ b/libs/renderengine/skia/SkiaGLRenderEngine.cpp @@ -610,18 +610,17 @@ private: AutoBackendTexture::CleanupManager& mMgr; }; -sk_sp SkiaGLRenderEngine::createRuntimeEffectShader(sk_sp shader, - const LayerSettings& layer, - const DisplaySettings& display, - bool undoPremultipliedAlpha, - bool requiresLinearEffect) { - const auto stretchEffect = layer.stretchEffect; +sk_sp SkiaGLRenderEngine::createRuntimeEffectShader( + sk_sp shader, + const LayerSettings* layer, const DisplaySettings& display, bool undoPremultipliedAlpha, + bool requiresLinearEffect) { + const auto stretchEffect = layer->stretchEffect; // The given surface will be stretched by HWUI via matrix transformation // which gets similar results for most surfaces // Determine later on if we need to leverage the stertch shader within // surface flinger if (stretchEffect.hasEffect()) { - const auto targetBuffer = layer.source.buffer.buffer; + const auto targetBuffer = layer->source.buffer.buffer; const auto graphicBuffer = targetBuffer ? targetBuffer->getBuffer() : nullptr; if (graphicBuffer && shader) { shader = mStretchShaderFactory.createSkShader(shader, stretchEffect); @@ -630,7 +629,7 @@ sk_sp SkiaGLRenderEngine::createRuntimeEffectShader(sk_sp sh if (requiresLinearEffect) { const ui::Dataspace inputDataspace = - mUseColorManagement ? layer.sourceDataspace : ui::Dataspace::V0_SRGB_LINEAR; + mUseColorManagement ? layer->sourceDataspace : ui::Dataspace::V0_SRGB_LINEAR; const ui::Dataspace outputDataspace = mUseColorManagement ? display.outputDataspace : ui::Dataspace::V0_SRGB_LINEAR; @@ -646,13 +645,13 @@ sk_sp SkiaGLRenderEngine::createRuntimeEffectShader(sk_sp sh } else { runtimeEffect = effectIter->second; } - float maxLuminance = layer.source.buffer.maxLuminanceNits; + float maxLuminance = layer->source.buffer.maxLuminanceNits; // If the buffer doesn't have a max luminance, treat it as SDR & use the display's SDR // white point if (maxLuminance <= 0.f) { maxLuminance = display.sdrWhitePointNits; } - return createLinearEffectShader(shader, effect, runtimeEffect, layer.colorTransform, + return createLinearEffectShader(shader, effect, runtimeEffect, layer->colorTransform, display.maxLuminance, maxLuminance); } return shader; @@ -730,7 +729,7 @@ static SkRRect getBlurRRect(const BlurRegion& region) { void SkiaGLRenderEngine::drawLayersInternal( const std::shared_ptr>&& resultPromise, - const DisplaySettings& display, const std::vector& layers, + const DisplaySettings& display, const std::vector& layers, const std::shared_ptr& buffer, const bool /*useFramebufferCache*/, base::unique_fd&& bufferFence) { ATRACE_NAME("SkiaGL::drawLayers"); @@ -802,11 +801,11 @@ void SkiaGLRenderEngine::drawLayersInternal( if (!layerHasBlur(layer, ctModifiesAlpha)) { continue; } - if (layer.backgroundBlurRadius > 0 && - layer.backgroundBlurRadius < BlurFilter::kMaxCrossFadeRadius) { + if (layer->backgroundBlurRadius > 0 && + layer->backgroundBlurRadius < BlurFilter::kMaxCrossFadeRadius) { requiresCompositionLayer = true; } - for (auto region : layer.blurRegions) { + for (auto region : layer->blurRegions) { if (region.blurRadius < BlurFilter::kMaxCrossFadeRadius) { requiresCompositionLayer = true; } @@ -814,7 +813,7 @@ void SkiaGLRenderEngine::drawLayersInternal( if (requiresCompositionLayer) { activeSurface = dstSurface->makeSurface(dstSurface->imageInfo()); canvas = mCapture->tryOffscreenCapture(activeSurface.get(), &offscreenCaptureState); - blurCompositionLayer = &layer; + blurCompositionLayer = layer; break; } } @@ -826,11 +825,11 @@ void SkiaGLRenderEngine::drawLayersInternal( initCanvas(canvas, display); for (const auto& layer : layers) { - ATRACE_FORMAT("DrawLayer: %s", layer.name.c_str()); + ATRACE_FORMAT("DrawLayer: %s", layer->name.c_str()); if (kPrintLayerSettings) { std::stringstream ls; - PrintTo(layer, &ls); + PrintTo(*layer, &ls); auto debugs = ls.str(); int pos = 0; while (pos < debugs.size()) { @@ -840,7 +839,7 @@ void SkiaGLRenderEngine::drawLayersInternal( } sk_sp blurInput; - if (blurCompositionLayer == &layer) { + if (blurCompositionLayer == layer) { LOG_ALWAYS_FATAL_IF(activeSurface == dstSurface); LOG_ALWAYS_FATAL_IF(canvas == dstCanvas); @@ -879,17 +878,17 @@ void SkiaGLRenderEngine::drawLayersInternal( if (CC_UNLIKELY(mCapture->isCaptureRunning())) { // Record the name of the layer if the capture is running. std::stringstream layerSettings; - PrintTo(layer, &layerSettings); + PrintTo(*layer, &layerSettings); // Store the LayerSettings in additional information. - canvas->drawAnnotation(SkRect::MakeEmpty(), layer.name.c_str(), + canvas->drawAnnotation(SkRect::MakeEmpty(), layer->name.c_str(), SkData::MakeWithCString(layerSettings.str().c_str())); } // Layers have a local transform that should be applied to them - canvas->concat(getSkM44(layer.geometry.positionTransform).asM33()); + canvas->concat(getSkM44(layer->geometry.positionTransform).asM33()); const auto [bounds, roundRectClip] = - getBoundsAndClip(layer.geometry.boundaries, layer.geometry.roundedCornersCrop, - layer.geometry.roundedCornersRadius); + getBoundsAndClip(layer->geometry.boundaries, layer->geometry.roundedCornersCrop, + layer->geometry.roundedCornersRadius); if (mBlurFilter && layerHasBlur(layer, ctModifiesAlpha)) { std::unordered_map> cachedBlurs; @@ -910,19 +909,20 @@ void SkiaGLRenderEngine::drawLayersInternal( // TODO(b/182216890): Filter out empty layers earlier if (blurRect.width() > 0 && blurRect.height() > 0) { - if (layer.backgroundBlurRadius > 0) { + if (layer->backgroundBlurRadius > 0) { ATRACE_NAME("BackgroundBlur"); - auto blurredImage = mBlurFilter->generate(grContext, layer.backgroundBlurRadius, - blurInput, blurRect); + auto blurredImage = + mBlurFilter->generate(grContext, layer->backgroundBlurRadius, blurInput, + blurRect); - cachedBlurs[layer.backgroundBlurRadius] = blurredImage; + cachedBlurs[layer->backgroundBlurRadius] = blurredImage; - mBlurFilter->drawBlurRegion(canvas, bounds, layer.backgroundBlurRadius, 1.0f, + mBlurFilter->drawBlurRegion(canvas, bounds, layer->backgroundBlurRadius, 1.0f, blurRect, blurredImage, blurInput); } - canvas->concat(getSkM44(layer.blurRegionTransform).asM33()); - for (auto region : layer.blurRegions) { + canvas->concat(getSkM44(layer->blurRegionTransform).asM33()); + for (auto region : layer->blurRegions) { if (cachedBlurs[region.blurRadius] == nullptr) { ATRACE_NAME("BlurRegion"); cachedBlurs[region.blurRadius] = @@ -937,18 +937,19 @@ void SkiaGLRenderEngine::drawLayersInternal( } } - if (layer.shadow.length > 0) { + if (layer->shadow.length > 0) { // This would require a new parameter/flag to SkShadowUtils::DrawShadow - LOG_ALWAYS_FATAL_IF(layer.disableBlending, "Cannot disableBlending with a shadow"); + LOG_ALWAYS_FATAL_IF(layer->disableBlending, "Cannot disableBlending with a shadow"); SkRRect shadowBounds, shadowClip; - if (layer.geometry.boundaries == layer.shadow.boundaries) { + if (layer->geometry.boundaries == layer->shadow.boundaries) { shadowBounds = bounds; shadowClip = roundRectClip; } else { std::tie(shadowBounds, shadowClip) = - getBoundsAndClip(layer.shadow.boundaries, layer.geometry.roundedCornersCrop, - layer.geometry.roundedCornersRadius); + getBoundsAndClip(layer->shadow.boundaries, + layer->geometry.roundedCornersCrop, + layer->geometry.roundedCornersRadius); } // Technically, if bounds is a rect and roundRectClip is not empty, @@ -959,18 +960,18 @@ void SkiaGLRenderEngine::drawLayersInternal( // looks more like the intent. const auto& rrect = shadowBounds.isRect() && !shadowClip.isEmpty() ? shadowClip : shadowBounds; - drawShadow(canvas, rrect, layer.shadow); + drawShadow(canvas, rrect, layer->shadow); } - const bool requiresLinearEffect = layer.colorTransform != mat4() || + const bool requiresLinearEffect = layer->colorTransform != mat4() || (mUseColorManagement && - needsToneMapping(layer.sourceDataspace, display.outputDataspace)) || + needsToneMapping(layer->sourceDataspace, display.outputDataspace)) || (display.sdrWhitePointNits > 0.f && display.sdrWhitePointNits != display.maxLuminance); // quick abort from drawing the remaining portion of the layer - if (layer.skipContentDraw || - (layer.alpha == 0 && !requiresLinearEffect && !layer.disableBlending && + if (layer->skipContentDraw || + (layer->alpha == 0 && !requiresLinearEffect && !layer->disableBlending && (!displayColorTransform || displayColorTransform->isAlphaUnchanged()))) { continue; } @@ -980,13 +981,13 @@ void SkiaGLRenderEngine::drawLayersInternal( // management is a no-op. const ui::Dataspace layerDataspace = (!mUseColorManagement || requiresLinearEffect) ? dstDataspace - : layer.sourceDataspace; + : layer->sourceDataspace; SkPaint paint; - if (layer.source.buffer.buffer) { + if (layer->source.buffer.buffer) { ATRACE_NAME("DrawImage"); - validateInputBufferUsage(layer.source.buffer.buffer->getBuffer()); - const auto& item = layer.source.buffer; + validateInputBufferUsage(layer->source.buffer.buffer->getBuffer()); + const auto& item = layer->source.buffer; std::shared_ptr imageTextureRef = nullptr; if (const auto& iter = cache.find(item.buffer->getBuffer()->getId()); @@ -1005,8 +1006,8 @@ void SkiaGLRenderEngine::drawLayersInternal( // if the layer's buffer has a fence, then we must must respect the fence prior to using // the buffer. - if (layer.source.buffer.fence != nullptr) { - waitFence(layer.source.buffer.fence->get()); + if (layer->source.buffer.fence != nullptr) { + waitFence(layer->source.buffer.fence->get()); } // isOpaque means we need to ignore the alpha in the image, @@ -1050,7 +1051,7 @@ void SkiaGLRenderEngine::drawLayersInternal( sk_sp shader; - if (layer.source.buffer.useTextureFiltering) { + if (layer->source.buffer.useTextureFiltering) { shader = image->makeShader(SkTileMode::kClamp, SkTileMode::kClamp, SkSamplingOptions( {SkFilterMode::kLinear, SkMipmapMode::kNone}), @@ -1068,21 +1069,21 @@ void SkiaGLRenderEngine::drawLayersInternal( paint.setShader(createRuntimeEffectShader(shader, layer, display, !item.isOpaque && item.usePremultipliedAlpha, requiresLinearEffect)); - paint.setAlphaf(layer.alpha); + paint.setAlphaf(layer->alpha); } else { ATRACE_NAME("DrawColor"); - const auto color = layer.source.solidColor; + const auto color = layer->source.solidColor; sk_sp shader = SkShaders::Color(SkColor4f{.fR = color.r, .fG = color.g, .fB = color.b, - .fA = layer.alpha}, + .fA = layer->alpha}, toSkColorSpace(layerDataspace)); paint.setShader(createRuntimeEffectShader(shader, layer, display, /* undoPremultipliedAlpha */ false, requiresLinearEffect)); } - if (layer.disableBlending) { + if (layer->disableBlending) { paint.setBlendMode(SkBlendMode::kSrc); } @@ -1250,13 +1251,13 @@ inline std::pair SkiaGLRenderEngine::getBoundsAndClip(const Fl return {SkRRect::MakeRect(bounds), clip}; } -inline bool SkiaGLRenderEngine::layerHasBlur(const LayerSettings& layer, +inline bool SkiaGLRenderEngine::layerHasBlur(const LayerSettings* layer, bool colorTransformModifiesAlpha) { - if (layer.backgroundBlurRadius > 0 || layer.blurRegions.size()) { + if (layer->backgroundBlurRadius > 0 || layer->blurRegions.size()) { // return false if the content is opaque and would therefore occlude the blur - const bool opaqueContent = !layer.source.buffer.buffer || layer.source.buffer.isOpaque; - const bool opaqueAlpha = layer.alpha == 1.0f && !colorTransformModifiesAlpha; - return layer.skipContentDraw || !(opaqueContent && opaqueAlpha); + const bool opaqueContent = !layer->source.buffer.buffer || layer->source.buffer.isOpaque; + const bool opaqueAlpha = layer->alpha == 1.0f && !colorTransformModifiesAlpha; + return layer->skipContentDraw || !(opaqueContent && opaqueAlpha); } return false; } diff --git a/libs/renderengine/skia/SkiaGLRenderEngine.h b/libs/renderengine/skia/SkiaGLRenderEngine.h index 74ce6513e9..e010c35c13 100644 --- a/libs/renderengine/skia/SkiaGLRenderEngine.h +++ b/libs/renderengine/skia/SkiaGLRenderEngine.h @@ -74,7 +74,7 @@ protected: bool canSkipPostRenderCleanup() const override; void drawLayersInternal(const std::shared_ptr>&& resultPromise, const DisplaySettings& display, - const std::vector& layers, + const std::vector& layers, const std::shared_ptr& buffer, const bool useFramebufferCache, base::unique_fd&& bufferFence) override; @@ -92,7 +92,7 @@ private: inline SkRect getSkRect(const Rect& layer); inline std::pair getBoundsAndClip(const FloatRect& bounds, const FloatRect& crop, float cornerRadius); - inline bool layerHasBlur(const LayerSettings& layer, bool colorTransformModifiesAlpha); + inline bool layerHasBlur(const LayerSettings* layer, bool colorTransformModifiesAlpha); inline SkColor getSkColor(const vec4& color); inline SkM44 getSkM44(const mat4& matrix); inline SkPoint3 getSkPoint3(const vec3& vector); @@ -108,7 +108,8 @@ private: const ShadowSettings& shadowSettings); // If requiresLinearEffect is true or the layer has a stretchEffect a new shader is returned. // Otherwise it returns the input shader. - sk_sp createRuntimeEffectShader(sk_sp shader, const LayerSettings& layer, + sk_sp createRuntimeEffectShader(sk_sp shader, + const LayerSettings* layer, const DisplaySettings& display, bool undoPremultipliedAlpha, bool requiresLinearEffect); diff --git a/libs/renderengine/skia/SkiaRenderEngine.h b/libs/renderengine/skia/SkiaRenderEngine.h index eb65e83324..f61653b940 100644 --- a/libs/renderengine/skia/SkiaRenderEngine.h +++ b/libs/renderengine/skia/SkiaRenderEngine.h @@ -55,7 +55,7 @@ protected: virtual void drawLayersInternal( const std::shared_ptr>&& resultPromise, - const DisplaySettings& display, const std::vector& layers, + const DisplaySettings& display, const std::vector& layers, const std::shared_ptr& buffer, const bool useFramebufferCache, base::unique_fd&& bufferFence) override { resultPromise->set_value({NO_ERROR, base::unique_fd()}); diff --git a/libs/renderengine/tests/RenderEngineTest.cpp b/libs/renderengine/tests/RenderEngineTest.cpp index c2c05f41b7..694bda65d4 100644 --- a/libs/renderengine/tests/RenderEngineTest.cpp +++ b/libs/renderengine/tests/RenderEngineTest.cpp @@ -417,11 +417,10 @@ public: DEFAULT_DISPLAY_HEIGHT - DEFAULT_DISPLAY_OFFSET); } - void invokeDraw(const renderengine::DisplaySettings& settings, - const std::vector& layers) { + void invokeDraw(renderengine::DisplaySettings settings, + std::vector layers) { std::future result = mRE->drawLayers(settings, layers, mBuffer, true, base::unique_fd()); - ASSERT_TRUE(result.valid()); auto [status, fence] = result.get(); @@ -437,7 +436,7 @@ public: void drawEmptyLayers() { renderengine::DisplaySettings settings; - std::vector layers; + std::vector layers; invokeDraw(settings, layers); } @@ -630,7 +629,7 @@ void RenderEngineTest::fillBuffer(half r, half g, half b, half a) { settings.clip = fullscreenRect(); settings.outputDataspace = ui::Dataspace::V0_SRGB_LINEAR; - std::vector layers; + std::vector layers; renderengine::LayerSettings layer; layer.sourceDataspace = ui::Dataspace::V0_SRGB_LINEAR; @@ -638,7 +637,7 @@ void RenderEngineTest::fillBuffer(half r, half g, half b, half a) { SourceVariant::fillColor(layer, r, g, b, this); layer.alpha = a; - layers.push_back(layer); + layers.push_back(&layer); invokeDraw(settings, layers); } @@ -674,7 +673,7 @@ void RenderEngineTest::fillRedOffsetBuffer() { settings.physicalDisplay = offsetRect(); settings.clip = offsetRectAtZero(); - std::vector layers; + std::vector layers; renderengine::LayerSettings layer; layer.sourceDataspace = ui::Dataspace::V0_SRGB_LINEAR; @@ -682,7 +681,7 @@ void RenderEngineTest::fillRedOffsetBuffer() { SourceVariant::fillColor(layer, 1.0f, 0.0f, 0.0f, this); layer.alpha = 1.0f; - layers.push_back(layer); + layers.push_back(&layer); invokeDraw(settings, layers); } @@ -709,7 +708,7 @@ void RenderEngineTest::fillBufferCheckers(uint32_t orientationFlag) { settings.clip = Rect(2, 2); settings.orientation = orientationFlag; - std::vector layers; + std::vector layers; renderengine::LayerSettings layerOne; layerOne.sourceDataspace = ui::Dataspace::V0_SRGB_LINEAR; @@ -732,9 +731,9 @@ void RenderEngineTest::fillBufferCheckers(uint32_t orientationFlag) { SourceVariant::fillColor(layerThree, 0.0f, 0.0f, 1.0f, this); layerThree.alpha = 1.0f; - layers.push_back(layerOne); - layers.push_back(layerTwo); - layers.push_back(layerThree); + layers.push_back(&layerOne); + layers.push_back(&layerTwo); + layers.push_back(&layerThree); invokeDraw(settings, layers); } @@ -811,7 +810,7 @@ void RenderEngineTest::fillBufferWithLayerTransform() { settings.clip = Rect(2, 2); settings.outputDataspace = ui::Dataspace::V0_SRGB_LINEAR; - std::vector layers; + std::vector layers; renderengine::LayerSettings layer; layer.sourceDataspace = ui::Dataspace::V0_SRGB_LINEAR; @@ -822,7 +821,7 @@ void RenderEngineTest::fillBufferWithLayerTransform() { layer.source.solidColor = half3(1.0f, 0.0f, 0.0f); layer.alpha = 1.0f; - layers.push_back(layer); + layers.push_back(&layer); invokeDraw(settings, layers); } @@ -844,7 +843,7 @@ void RenderEngineTest::fillBufferWithColorTransform() { settings.clip = Rect(1, 1); settings.outputDataspace = ui::Dataspace::V0_SRGB_LINEAR; - std::vector layers; + std::vector layers; renderengine::LayerSettings layer; layer.sourceDataspace = ui::Dataspace::V0_SRGB_LINEAR; @@ -861,7 +860,7 @@ void RenderEngineTest::fillBufferWithColorTransform() { layer.alpha = 1.0f; layer.geometry.boundaries = Rect(1, 1).toFloatRect(); - layers.push_back(layer); + layers.push_back(&layer); invokeDraw(settings, layers); } @@ -878,7 +877,7 @@ void RenderEngineTest::fillBufferWithColorTransformZeroLayerAlpha() { settings.physicalDisplay = fullscreenRect(); settings.clip = Rect(1, 1); - std::vector layers; + std::vector layers; renderengine::LayerSettings layer; layer.geometry.boundaries = Rect(1, 1).toFloatRect(); @@ -891,7 +890,7 @@ void RenderEngineTest::fillBufferWithColorTransformZeroLayerAlpha() { layer.geometry.boundaries = Rect(1, 1).toFloatRect(); - layers.push_back(layer); + layers.push_back(&layer); invokeDraw(settings, layers); } @@ -909,7 +908,7 @@ void RenderEngineTest::fillRedBufferWithRoundedCorners() { settings.clip = fullscreenRect(); settings.outputDataspace = ui::Dataspace::V0_SRGB_LINEAR; - std::vector layers; + std::vector layers; renderengine::LayerSettings layer; layer.sourceDataspace = ui::Dataspace::V0_SRGB_LINEAR; @@ -919,7 +918,7 @@ void RenderEngineTest::fillRedBufferWithRoundedCorners() { SourceVariant::fillColor(layer, 1.0f, 0.0f, 0.0f, this); layer.alpha = 1.0f; - layers.push_back(layer); + layers.push_back(&layer); invokeDraw(settings, layers); } @@ -950,14 +949,14 @@ void RenderEngineTest::fillBufferAndBlurBackground() { settings.physicalDisplay = fullscreenRect(); settings.clip = fullscreenRect(); - std::vector layers; + std::vector layers; renderengine::LayerSettings backgroundLayer; backgroundLayer.sourceDataspace = ui::Dataspace::V0_SRGB_LINEAR; backgroundLayer.geometry.boundaries = fullscreenRect().toFloatRect(); SourceVariant::fillColor(backgroundLayer, 0.0f, 1.0f, 0.0f, this); backgroundLayer.alpha = 1.0f; - layers.emplace_back(backgroundLayer); + layers.push_back(&backgroundLayer); renderengine::LayerSettings leftLayer; leftLayer.sourceDataspace = ui::Dataspace::V0_SRGB_LINEAR; @@ -965,7 +964,7 @@ void RenderEngineTest::fillBufferAndBlurBackground() { Rect(DEFAULT_DISPLAY_WIDTH / 2, DEFAULT_DISPLAY_HEIGHT).toFloatRect(); SourceVariant::fillColor(leftLayer, 1.0f, 0.0f, 0.0f, this); leftLayer.alpha = 1.0f; - layers.emplace_back(leftLayer); + layers.push_back(&leftLayer); renderengine::LayerSettings blurLayer; blurLayer.sourceDataspace = ui::Dataspace::V0_SRGB_LINEAR; @@ -973,7 +972,7 @@ void RenderEngineTest::fillBufferAndBlurBackground() { blurLayer.backgroundBlurRadius = blurRadius; SourceVariant::fillColor(blurLayer, 0.0f, 0.0f, 1.0f, this); blurLayer.alpha = 0; - layers.emplace_back(blurLayer); + layers.push_back(&blurLayer); invokeDraw(settings, layers); @@ -995,14 +994,14 @@ void RenderEngineTest::fillSmallLayerAndBlurBackground() { settings.physicalDisplay = fullscreenRect(); settings.clip = fullscreenRect(); - std::vector layers; + std::vector layers; renderengine::LayerSettings backgroundLayer; backgroundLayer.sourceDataspace = ui::Dataspace::V0_SRGB_LINEAR; backgroundLayer.geometry.boundaries = fullscreenRect().toFloatRect(); SourceVariant::fillColor(backgroundLayer, 1.0f, 0.0f, 0.0f, this); backgroundLayer.alpha = 1.0f; - layers.push_back(backgroundLayer); + layers.push_back(&backgroundLayer); renderengine::LayerSettings blurLayer; blurLayer.sourceDataspace = ui::Dataspace::V0_SRGB_LINEAR; @@ -1010,7 +1009,7 @@ void RenderEngineTest::fillSmallLayerAndBlurBackground() { blurLayer.backgroundBlurRadius = blurRadius; SourceVariant::fillColor(blurLayer, 0.0f, 0.0f, 1.0f, this); blurLayer.alpha = 0; - layers.push_back(blurLayer); + layers.push_back(&blurLayer); invokeDraw(settings, layers); @@ -1027,7 +1026,7 @@ void RenderEngineTest::overlayCorners() { settings.clip = fullscreenRect(); settings.outputDataspace = ui::Dataspace::V0_SRGB_LINEAR; - std::vector layersFirst; + std::vector layersFirst; renderengine::LayerSettings layerOne; layerOne.sourceDataspace = ui::Dataspace::V0_SRGB_LINEAR; @@ -1036,14 +1035,14 @@ void RenderEngineTest::overlayCorners() { SourceVariant::fillColor(layerOne, 1.0f, 0.0f, 0.0f, this); layerOne.alpha = 0.2; - layersFirst.push_back(layerOne); + layersFirst.push_back(&layerOne); invokeDraw(settings, layersFirst); expectBufferColor(Rect(DEFAULT_DISPLAY_WIDTH / 3, DEFAULT_DISPLAY_HEIGHT / 3), 51, 0, 0, 51); expectBufferColor(Rect(DEFAULT_DISPLAY_WIDTH / 3 + 1, DEFAULT_DISPLAY_HEIGHT / 3 + 1, DEFAULT_DISPLAY_WIDTH, DEFAULT_DISPLAY_HEIGHT), 0, 0, 0, 0); - std::vector layersSecond; + std::vector layersSecond; renderengine::LayerSettings layerTwo; layerTwo.sourceDataspace = ui::Dataspace::V0_SRGB_LINEAR; layerTwo.geometry.boundaries = @@ -1052,7 +1051,7 @@ void RenderEngineTest::overlayCorners() { SourceVariant::fillColor(layerTwo, 0.0f, 1.0f, 0.0f, this); layerTwo.alpha = 1.0f; - layersSecond.push_back(layerTwo); + layersSecond.push_back(&layerTwo); invokeDraw(settings, layersSecond); expectBufferColor(Rect(DEFAULT_DISPLAY_WIDTH / 3, DEFAULT_DISPLAY_HEIGHT / 3), 0, 0, 0, 0); @@ -1067,7 +1066,7 @@ void RenderEngineTest::fillRedBufferTextureTransform() { settings.clip = Rect(1, 1); settings.outputDataspace = ui::Dataspace::V0_SRGB_LINEAR; - std::vector layers; + std::vector layers; renderengine::LayerSettings layer; layer.sourceDataspace = ui::Dataspace::V0_SRGB_LINEAR; @@ -1103,7 +1102,7 @@ void RenderEngineTest::fillRedBufferTextureTransform() { layer.alpha = 1.0f; layer.geometry.boundaries = Rect(1, 1).toFloatRect(); - layers.push_back(layer); + layers.push_back(&layer); invokeDraw(settings, layers); } @@ -1119,7 +1118,7 @@ void RenderEngineTest::fillRedBufferWithPremultiplyAlpha() { // Here logical space is 1x1 settings.clip = Rect(1, 1); - std::vector layers; + std::vector layers; renderengine::LayerSettings layer; const auto buf = allocateSourceBuffer(1, 1); @@ -1142,7 +1141,7 @@ void RenderEngineTest::fillRedBufferWithPremultiplyAlpha() { layer.alpha = 0.5f; layer.geometry.boundaries = Rect(1, 1).toFloatRect(); - layers.push_back(layer); + layers.push_back(&layer); invokeDraw(settings, layers); } @@ -1158,7 +1157,7 @@ void RenderEngineTest::fillRedBufferWithoutPremultiplyAlpha() { // Here logical space is 1x1 settings.clip = Rect(1, 1); - std::vector layers; + std::vector layers; renderengine::LayerSettings layer; const auto buf = allocateSourceBuffer(1, 1); @@ -1181,7 +1180,7 @@ void RenderEngineTest::fillRedBufferWithoutPremultiplyAlpha() { layer.alpha = 0.5f; layer.geometry.boundaries = Rect(1, 1).toFloatRect(); - layers.push_back(layer); + layers.push_back(&layer); invokeDraw(settings, layers); } @@ -1200,7 +1199,7 @@ void RenderEngineTest::drawShadow(const renderengine::LayerSettings& castingLaye settings.physicalDisplay = fullscreenRect(); settings.clip = fullscreenRect(); - std::vector layers; + std::vector layers; // add background layer renderengine::LayerSettings bgLayer; @@ -1209,7 +1208,7 @@ void RenderEngineTest::drawShadow(const renderengine::LayerSettings& castingLaye ColorSourceVariant::fillColor(bgLayer, backgroundColor.r / 255.0f, backgroundColor.g / 255.0f, backgroundColor.b / 255.0f, this); bgLayer.alpha = backgroundColor.a / 255.0f; - layers.push_back(bgLayer); + layers.push_back(&bgLayer); // add shadow layer renderengine::LayerSettings shadowLayer; @@ -1217,14 +1216,14 @@ void RenderEngineTest::drawShadow(const renderengine::LayerSettings& castingLaye shadowLayer.geometry.boundaries = castingLayer.geometry.boundaries; shadowLayer.alpha = castingLayer.alpha; shadowLayer.shadow = shadow; - layers.push_back(shadowLayer); + layers.push_back(&shadowLayer); // add layer casting the shadow renderengine::LayerSettings layer = castingLayer; layer.sourceDataspace = ui::Dataspace::V0_SRGB_LINEAR; SourceVariant::fillColor(layer, casterColor.r / 255.0f, casterColor.g / 255.0f, casterColor.b / 255.0f, this); - layers.push_back(layer); + layers.push_back(&layer); invokeDraw(settings, layers); } @@ -1237,7 +1236,7 @@ void RenderEngineTest::drawShadowWithoutCaster(const FloatRect& castingBounds, settings.physicalDisplay = fullscreenRect(); settings.clip = fullscreenRect(); - std::vector layers; + std::vector layers; // add background layer renderengine::LayerSettings bgLayer; @@ -1246,7 +1245,7 @@ void RenderEngineTest::drawShadowWithoutCaster(const FloatRect& castingBounds, ColorSourceVariant::fillColor(bgLayer, backgroundColor.r / 255.0f, backgroundColor.g / 255.0f, backgroundColor.b / 255.0f, this); bgLayer.alpha = backgroundColor.a / 255.0f; - layers.push_back(bgLayer); + layers.push_back(&bgLayer); // add shadow layer renderengine::LayerSettings shadowLayer; @@ -1256,7 +1255,7 @@ void RenderEngineTest::drawShadowWithoutCaster(const FloatRect& castingBounds, shadowLayer.alpha = 1.0f; ColorSourceVariant::fillColor(shadowLayer, 0, 0, 0, this); shadowLayer.shadow = shadow; - layers.push_back(shadowLayer); + layers.push_back(&shadowLayer); invokeDraw(settings, layers); } @@ -1292,8 +1291,8 @@ TEST_P(RenderEngineTest, drawLayers_withoutBuffers_withColorTransform) { // Transform the red color. bgLayer.colorTransform = mat4(-1, 0, 0, 0, 0, 1, 0, 0, 0, 0, 1, 0, 0, 0, 0, 1); - std::vector layers; - layers.push_back(bgLayer); + std::vector layers; + layers.push_back(&bgLayer); invokeDraw(settings, layers); @@ -1307,11 +1306,11 @@ TEST_P(RenderEngineTest, drawLayers_nullOutputBuffer) { renderengine::DisplaySettings settings; settings.outputDataspace = ui::Dataspace::V0_SRGB_LINEAR; - std::vector layers; + std::vector layers; renderengine::LayerSettings layer; layer.geometry.boundaries = fullscreenRect().toFloatRect(); BufferSourceVariant::fillColor(layer, 1.0f, 0.0f, 0.0f, this); - layers.push_back(layer); + layers.push_back(&layer); std::future result = mRE->drawLayers(settings, layers, nullptr, true, base::unique_fd()); @@ -1336,12 +1335,12 @@ TEST_P(RenderEngineTest, drawLayers_doesNotCacheFramebuffer) { settings.physicalDisplay = fullscreenRect(); settings.clip = fullscreenRect(); - std::vector layers; + std::vector layers; renderengine::LayerSettings layer; layer.geometry.boundaries = fullscreenRect().toFloatRect(); BufferSourceVariant::fillColor(layer, 1.0f, 0.0f, 0.0f, this); layer.alpha = 1.0; - layers.push_back(layer); + layers.push_back(&layer); std::future result = mRE->drawLayers(settings, layers, mBuffer, false, base::unique_fd()); @@ -1744,12 +1743,12 @@ TEST_P(RenderEngineTest, cleanupPostRender_cleansUpOnce) { settings.clip = fullscreenRect(); settings.outputDataspace = ui::Dataspace::V0_SRGB_LINEAR; - std::vector layers; + std::vector layers; renderengine::LayerSettings layer; layer.geometry.boundaries = fullscreenRect().toFloatRect(); BufferSourceVariant::fillColor(layer, 1.0f, 0.0f, 0.0f, this); layer.alpha = 1.0; - layers.push_back(layer); + layers.push_back(&layer); std::future resultOne = mRE->drawLayers(settings, layers, mBuffer, true, base::unique_fd()); @@ -1780,7 +1779,7 @@ TEST_P(RenderEngineTest, testRoundedCornersCrop) { settings.clip = fullscreenRect(); settings.outputDataspace = ui::Dataspace::V0_SRGB_LINEAR; - std::vector layers; + std::vector layers; renderengine::LayerSettings redLayer; redLayer.sourceDataspace = ui::Dataspace::V0_SRGB_LINEAR; @@ -1791,7 +1790,7 @@ TEST_P(RenderEngineTest, testRoundedCornersCrop) { redLayer.source.solidColor = half3(1.0f, 0.0f, 0.0f); redLayer.alpha = 1.0f; - layers.push_back(redLayer); + layers.push_back(&redLayer); // Green layer with 1/3 size. renderengine::LayerSettings greenLayer; @@ -1806,7 +1805,7 @@ TEST_P(RenderEngineTest, testRoundedCornersCrop) { greenLayer.source.solidColor = half3(0.0f, 1.0f, 0.0f); greenLayer.alpha = 1.0f; - layers.push_back(greenLayer); + layers.push_back(&greenLayer); invokeDraw(settings, layers); @@ -1829,7 +1828,7 @@ TEST_P(RenderEngineTest, testRoundedCornersParentCrop) { settings.clip = fullscreenRect(); settings.outputDataspace = ui::Dataspace::V0_SRGB_LINEAR; - std::vector layers; + std::vector layers; renderengine::LayerSettings redLayer; redLayer.sourceDataspace = ui::Dataspace::V0_SRGB_LINEAR; @@ -1840,7 +1839,7 @@ TEST_P(RenderEngineTest, testRoundedCornersParentCrop) { redLayer.source.solidColor = half3(1.0f, 0.0f, 0.0f); redLayer.alpha = 1.0f; - layers.push_back(redLayer); + layers.push_back(&redLayer); // Green layer with 1/2 size with parent crop rect. renderengine::LayerSettings greenLayer = redLayer; @@ -1848,7 +1847,7 @@ TEST_P(RenderEngineTest, testRoundedCornersParentCrop) { FloatRect(0, 0, DEFAULT_DISPLAY_WIDTH, DEFAULT_DISPLAY_HEIGHT / 2); greenLayer.source.solidColor = half3(0.0f, 1.0f, 0.0f); - layers.push_back(greenLayer); + layers.push_back(&greenLayer); invokeDraw(settings, layers); @@ -1874,7 +1873,7 @@ TEST_P(RenderEngineTest, testRoundedCornersParentCropSmallBounds) { settings.clip = fullscreenRect(); settings.outputDataspace = ui::Dataspace::V0_SRGB_LINEAR; - std::vector layers; + std::vector layers; renderengine::LayerSettings redLayer; redLayer.sourceDataspace = ui::Dataspace::V0_SRGB_LINEAR; @@ -1885,7 +1884,7 @@ TEST_P(RenderEngineTest, testRoundedCornersParentCropSmallBounds) { redLayer.source.solidColor = half3(1.0f, 0.0f, 0.0f); redLayer.alpha = 1.0f; - layers.push_back(redLayer); + layers.push_back(&redLayer); invokeDraw(settings, layers); // Due to roundedCornersRadius, the top corners are untouched. @@ -1924,7 +1923,7 @@ TEST_P(RenderEngineTest, testClear) { .disableBlending = true, }; - std::vector layers{redLayer, clearLayer}; + std::vector layers{&redLayer, &clearLayer}; invokeDraw(display, layers); expectBufferColor(rect, 0, 0, 0, 0); } @@ -1972,7 +1971,7 @@ TEST_P(RenderEngineTest, testDisableBlendingBuffer) { .disableBlending = true, }; - std::vector layers{redLayer, greenLayer}; + std::vector layers{&redLayer, &greenLayer}; invokeDraw(display, layers); expectBufferColor(rect, 0, 128, 0, 128); } @@ -2018,7 +2017,7 @@ TEST_P(RenderEngineTest, test_isOpaque) { .alpha = 1.0f, }; - std::vector layers{greenLayer}; + std::vector layers{&greenLayer}; invokeDraw(display, layers); if (GetParam()->useColorManagement()) { diff --git a/libs/renderengine/tests/RenderEngineThreadedTest.cpp b/libs/renderengine/tests/RenderEngineThreadedTest.cpp index db7e12b71b..99250c1412 100644 --- a/libs/renderengine/tests/RenderEngineThreadedTest.cpp +++ b/libs/renderengine/tests/RenderEngineThreadedTest.cpp @@ -172,21 +172,20 @@ TEST_F(RenderEngineThreadedTest, supportsBackgroundBlur_returnsTrue) { TEST_F(RenderEngineThreadedTest, drawLayers) { renderengine::DisplaySettings settings; - std::vector layers; + std::vector layers; std::shared_ptr buffer = std::make_shared< renderengine::ExternalTexture>(new GraphicBuffer(), *mRenderEngine, renderengine::ExternalTexture::Usage::READABLE | renderengine::ExternalTexture::Usage::WRITEABLE); - base::unique_fd bufferFence; EXPECT_CALL(*mRenderEngine, drawLayersInternal) .WillOnce([&](const std::shared_ptr>&& resultPromise, const renderengine::DisplaySettings&, - const std::vector&, + const std::vector&, const std::shared_ptr&, const bool, - base::unique_fd&&) -> void { + base::unique_fd &&) -> void { resultPromise->set_value({NO_ERROR, base::unique_fd()}); }); diff --git a/libs/renderengine/threaded/RenderEngineThreaded.cpp b/libs/renderengine/threaded/RenderEngineThreaded.cpp index 3d446e8e72..a549672259 100644 --- a/libs/renderengine/threaded/RenderEngineThreaded.cpp +++ b/libs/renderengine/threaded/RenderEngineThreaded.cpp @@ -306,7 +306,7 @@ bool RenderEngineThreaded::canSkipPostRenderCleanup() const { void RenderEngineThreaded::drawLayersInternal( const std::shared_ptr>&& resultPromise, - const DisplaySettings& display, const std::vector& layers, + const DisplaySettings& display, const std::vector& layers, const std::shared_ptr& buffer, const bool useFramebufferCache, base::unique_fd&& bufferFence) { resultPromise->set_value({NO_ERROR, base::unique_fd()}); @@ -314,20 +314,19 @@ void RenderEngineThreaded::drawLayersInternal( } std::future RenderEngineThreaded::drawLayers( - const DisplaySettings& display, const std::vector& layers, + const DisplaySettings& display, const std::vector& layers, const std::shared_ptr& buffer, const bool useFramebufferCache, base::unique_fd&& bufferFence) { ATRACE_CALL(); const auto resultPromise = std::make_shared>(); std::future resultFuture = resultPromise->get_future(); - int fd = bufferFence.release(); { std::lock_guard lock(mThreadMutex); - mFunctionCalls.push([resultPromise, display, layers, buffer, useFramebufferCache, - fd](renderengine::RenderEngine& instance) { + mFunctionCalls.push([resultPromise, &display, &layers, &buffer, useFramebufferCache, + &bufferFence](renderengine::RenderEngine& instance) { ATRACE_NAME("REThreaded::drawLayers"); instance.drawLayersInternal(std::move(resultPromise), display, layers, buffer, - useFramebufferCache, base::unique_fd(fd)); + useFramebufferCache, std::move(bufferFence)); }); } mCondition.notify_one(); diff --git a/libs/renderengine/threaded/RenderEngineThreaded.h b/libs/renderengine/threaded/RenderEngineThreaded.h index 0159cfaece..2303caa7eb 100644 --- a/libs/renderengine/threaded/RenderEngineThreaded.h +++ b/libs/renderengine/threaded/RenderEngineThreaded.h @@ -57,7 +57,7 @@ public: void cleanupPostRender() override; std::future drawLayers(const DisplaySettings& display, - const std::vector& layers, + const std::vector& layers, const std::shared_ptr& buffer, const bool useFramebufferCache, base::unique_fd&& bufferFence) override; @@ -73,7 +73,7 @@ protected: bool canSkipPostRenderCleanup() const override; void drawLayersInternal(const std::shared_ptr>&& resultPromise, const DisplaySettings& display, - const std::vector& layers, + const std::vector& layers, const std::shared_ptr& buffer, const bool useFramebufferCache, base::unique_fd&& bufferFence) override; diff --git a/services/surfaceflinger/BufferQueueLayer.cpp b/services/surfaceflinger/BufferQueueLayer.cpp index 6c60e53841..f98681e1ce 100644 --- a/services/surfaceflinger/BufferQueueLayer.cpp +++ b/services/surfaceflinger/BufferQueueLayer.cpp @@ -48,9 +48,7 @@ BufferQueueLayer::~BufferQueueLayer() { // Interface implementation for Layer // ----------------------------------------------------------------------- -void BufferQueueLayer::onLayerDisplayed( - std::shared_future futureRenderEngineResult) { - sp releaseFence = new Fence(dup(futureRenderEngineResult.get().drawFence)); +void BufferQueueLayer::onLayerDisplayed(const sp& releaseFence) { mConsumer->setReleaseFence(releaseFence); // Prevent tracing the same release multiple times. diff --git a/services/surfaceflinger/BufferQueueLayer.h b/services/surfaceflinger/BufferQueueLayer.h index dfdb5c055d..a3bd725cfe 100644 --- a/services/surfaceflinger/BufferQueueLayer.h +++ b/services/surfaceflinger/BufferQueueLayer.h @@ -42,8 +42,7 @@ public: // Implements Layer. const char* getType() const override { return "BufferQueueLayer"; } - void onLayerDisplayed( - std::shared_future futureRenderEngineResult) override; + void onLayerDisplayed(const sp& releaseFence) override; // If a buffer was replaced this frame, release the former buffer void releasePendingBuffer(nsecs_t dequeueReadyTime) override; diff --git a/services/surfaceflinger/BufferStateLayer.cpp b/services/surfaceflinger/BufferStateLayer.cpp index 454363ac3f..132ee9d71b 100644 --- a/services/surfaceflinger/BufferStateLayer.cpp +++ b/services/surfaceflinger/BufferStateLayer.cpp @@ -70,11 +70,69 @@ BufferStateLayer::~BufferStateLayer() { } } +status_t BufferStateLayer::addReleaseFence(const sp& ch, + const sp& fence) { + if (ch == nullptr) { + return OK; + } + ch->previousReleaseCallbackId = mPreviousReleaseCallbackId; + if (!ch->previousReleaseFence.get()) { + ch->previousReleaseFence = fence; + return OK; + } + + // Below logic is lifted from ConsumerBase.cpp: + // Check status of fences first because merging is expensive. + // Merging an invalid fence with any other fence results in an + // invalid fence. + auto currentStatus = ch->previousReleaseFence->getStatus(); + if (currentStatus == Fence::Status::Invalid) { + ALOGE("Existing fence has invalid state, layer: %s", mName.c_str()); + return BAD_VALUE; + } + + auto incomingStatus = fence->getStatus(); + if (incomingStatus == Fence::Status::Invalid) { + ALOGE("New fence has invalid state, layer: %s", mName.c_str()); + ch->previousReleaseFence = fence; + return BAD_VALUE; + } + + // If both fences are signaled or both are unsignaled, we need to merge + // them to get an accurate timestamp. + if (currentStatus == incomingStatus) { + char fenceName[32] = {}; + snprintf(fenceName, 32, "%.28s", mName.c_str()); + sp mergedFence = Fence::merge( + fenceName, ch->previousReleaseFence, fence); + if (!mergedFence.get()) { + ALOGE("failed to merge release fences, layer: %s", mName.c_str()); + // synchronization is broken, the best we can do is hope fences + // signal in order so the new fence will act like a union + ch->previousReleaseFence = fence; + return BAD_VALUE; + } + ch->previousReleaseFence = mergedFence; + } else if (incomingStatus == Fence::Status::Unsignaled) { + // If one fence has signaled and the other hasn't, the unsignaled + // fence will approximately correspond with the correct timestamp. + // There's a small race if both fences signal at about the same time + // and their statuses are retrieved with unfortunate timing. However, + // by this point, they will have both signaled and only the timestamp + // will be slightly off; any dependencies after this point will + // already have been met. + ch->previousReleaseFence = fence; + } + // else if (currentStatus == Fence::Status::Unsignaled) is a no-op. + + return OK; +} + // ----------------------------------------------------------------------- // Interface implementation for Layer // ----------------------------------------------------------------------- -void BufferStateLayer::onLayerDisplayed( - std::shared_future futureRenderEngineResult) { +void BufferStateLayer::onLayerDisplayed(const sp& releaseFence) { + // If a layer has been displayed again we may need to clear // the mLastClientComposition fence that we use for early release in setBuffer // (as we now have a new fence which won't pass through the client composition path in some cases @@ -88,6 +146,9 @@ void BufferStateLayer::onLayerDisplayed( mLastClientCompositionDisplayed = true; } + if (!releaseFence->isValid()) { + return; + } // The previous release fence notifies the client that SurfaceFlinger is done with the previous // buffer that was presented on this layer. The first transaction that came in this frame that // replaced the previous buffer on this layer needs this release fence, because the fence will @@ -112,19 +173,17 @@ void BufferStateLayer::onLayerDisplayed( break; } } + auto status = addReleaseFence(ch, releaseFence); + if (status != OK) { + ALOGE("Failed to add release fence for layer %s", getName().c_str()); + } - mListPreviousReleaseFences.emplace_back(futureRenderEngineResult); + mPreviousReleaseFence = releaseFence; // Prevent tracing the same release multiple times. if (mPreviousFrameNumber != mPreviousReleasedFrameNumber) { mPreviousReleasedFrameNumber = mPreviousFrameNumber; } - - if (ch != nullptr) { - ch->previousReleaseCallbackId = mPreviousReleaseCallbackId; - ch->previousReleaseFences.emplace_back(futureRenderEngineResult); - ch->name = mName; - } } void BufferStateLayer::onSurfaceFrameCreated( @@ -172,18 +231,9 @@ void BufferStateLayer::releasePendingBuffer(nsecs_t dequeueReadyTime) { mFlinger->getTransactionCallbackInvoker().addCallbackHandles( mDrawingState.callbackHandles, jankData); - sp releaseFence = Fence::NO_FENCE; - for (auto& handle : mDrawingState.callbackHandles) { - if (handle->releasePreviousBuffer && - mDrawingState.releaseBufferEndpoint == handle->listener) { - releaseFence = - handle->previousReleaseFence ? handle->previousReleaseFence : Fence::NO_FENCE; - break; - } - } - mDrawingState.callbackHandles = {}; + const sp& releaseFence(mPreviousReleaseFence); std::shared_ptr releaseFenceTime = std::make_shared(releaseFence); { Mutex::Autolock lock(mFrameEventHistoryMutex); diff --git a/services/surfaceflinger/BufferStateLayer.h b/services/surfaceflinger/BufferStateLayer.h index 6cb9b352f8..87b68ea71b 100644 --- a/services/surfaceflinger/BufferStateLayer.h +++ b/services/surfaceflinger/BufferStateLayer.h @@ -39,9 +39,7 @@ public: // Implements Layer. const char* getType() const override { return "BufferStateLayer"; } - void onLayerDisplayed( - std::shared_future futureRenderEngineResult) override; - + void onLayerDisplayed(const sp& releaseFence) override; void releasePendingBuffer(nsecs_t dequeueReadyTime) override; void finalizeFrameEventHistory(const std::shared_ptr& glDoneFence, @@ -117,6 +115,8 @@ private: bool updateFrameEventHistory(const sp& acquireFence, nsecs_t postedTime, nsecs_t requestedPresentTime); + status_t addReleaseFence(const sp& ch, const sp& releaseFence); + bool latchSidebandStream(bool& recomputeVisibleRegions) override; bool hasFrameUpdate() const override; @@ -139,7 +139,7 @@ private: std::shared_ptr getBufferFromBufferData( const BufferData& bufferData); - std::vector> mListPreviousReleaseFences; + sp mPreviousReleaseFence; ReleaseCallbackId mPreviousReleaseCallbackId = ReleaseCallbackId::INVALID_ID; uint64_t mPreviousReleasedFrameNumber = 0; diff --git a/services/surfaceflinger/CompositionEngine/include/compositionengine/LayerFE.h b/services/surfaceflinger/CompositionEngine/include/compositionengine/LayerFE.h index ac243c0a17..f7b71cf9fe 100644 --- a/services/surfaceflinger/CompositionEngine/include/compositionengine/LayerFE.h +++ b/services/surfaceflinger/CompositionEngine/include/compositionengine/LayerFE.h @@ -16,7 +16,6 @@ #pragma once -#include #include #include #include @@ -27,7 +26,6 @@ #pragma clang diagnostic ignored "-Wextra" #include -#include // TODO(b/129481165): remove the #pragma below and fix conversion issues #pragma clang diagnostic pop // ignored "-Wconversion -Wextra" @@ -153,7 +151,7 @@ public: ClientCompositionTargetSettings&) = 0; // Called after the layer is displayed to update the presentation fence - virtual void onLayerDisplayed(std::shared_future) = 0; + virtual void onLayerDisplayed(const sp&) = 0; // Gets some kind of identifier for the layer for debug purposes. virtual const char* getDebugName() const = 0; diff --git a/services/surfaceflinger/CompositionEngine/include/compositionengine/mock/LayerFE.h b/services/surfaceflinger/CompositionEngine/include/compositionengine/mock/LayerFE.h index 16aebef9f3..d215bda891 100644 --- a/services/surfaceflinger/CompositionEngine/include/compositionengine/mock/LayerFE.h +++ b/services/surfaceflinger/CompositionEngine/include/compositionengine/mock/LayerFE.h @@ -39,7 +39,7 @@ public: std::vector( compositionengine::LayerFE::ClientCompositionTargetSettings&)); - MOCK_METHOD1(onLayerDisplayed, void(std::shared_future)); + MOCK_METHOD1(onLayerDisplayed, void(const sp&)); MOCK_CONST_METHOD0(getDebugName, const char*()); MOCK_CONST_METHOD0(getSequence, int32_t()); diff --git a/services/surfaceflinger/CompositionEngine/src/Output.cpp b/services/surfaceflinger/CompositionEngine/src/Output.cpp index 7ea1aa2f92..048d7c2b4a 100644 --- a/services/surfaceflinger/CompositionEngine/src/Output.cpp +++ b/services/surfaceflinger/CompositionEngine/src/Output.cpp @@ -27,7 +27,6 @@ #include #include #include -#include #include @@ -1098,12 +1097,12 @@ std::optional Output::composeSurfaces( setExpensiveRenderingExpected(true); } - std::vector clientRenderEngineLayers; - clientRenderEngineLayers.reserve(clientCompositionLayers.size()); + std::vector clientCompositionLayerPointers; + clientCompositionLayerPointers.reserve(clientCompositionLayers.size()); std::transform(clientCompositionLayers.begin(), clientCompositionLayers.end(), - std::back_inserter(clientRenderEngineLayers), - [](LayerFE::LayerSettings& settings) -> renderengine::LayerSettings { - return settings; + std::back_inserter(clientCompositionLayerPointers), + [](LayerFE::LayerSettings& settings) -> renderengine::LayerSettings* { + return &settings; }); const nsecs_t renderEngineStart = systemTime(); @@ -1116,7 +1115,7 @@ std::optional Output::composeSurfaces( const bool useFramebufferCache = outputState.layerFilter.toInternalDisplay; auto [status, drawFence] = renderEngine - .drawLayers(clientCompositionDisplay, clientRenderEngineLayers, tex, + .drawLayers(clientCompositionDisplay, clientCompositionLayerPointers, tex, useFramebufferCache, std::move(fd)) .get(); @@ -1296,10 +1295,8 @@ void Output::postFramebuffer() { releaseFence = Fence::merge("LayerRelease", releaseFence, frame.clientTargetAcquireFence); } - layer->getLayerFE().onLayerDisplayed( - ftl::yield( - {NO_ERROR, base::unique_fd(releaseFence->dup())}) - .share()); + + layer->getLayerFE().onLayerDisplayed(releaseFence); } // We've got a list of layers needing fences, that are disjoint with @@ -1307,9 +1304,7 @@ void Output::postFramebuffer() { // supply them with the present fence. for (auto& weakLayer : mReleasedLayers) { if (auto layer = weakLayer.promote(); layer != nullptr) { - layer->onLayerDisplayed(ftl::yield( - {NO_ERROR, base::unique_fd(frame.presentFence->dup())}) - .share()); + layer->onLayerDisplayed(frame.presentFence); } } diff --git a/services/surfaceflinger/CompositionEngine/src/planner/CachedSet.cpp b/services/surfaceflinger/CompositionEngine/src/planner/CachedSet.cpp index ec52e59ab0..e6b716e8f2 100644 --- a/services/surfaceflinger/CompositionEngine/src/planner/CachedSet.cpp +++ b/services/surfaceflinger/CompositionEngine/src/planner/CachedSet.cpp @@ -193,6 +193,11 @@ void CachedSet::render(renderengine::RenderEngine& renderEngine, TexturePool& te clientCompositionList.cend()); } + std::vector layerSettingsPointers; + std::transform(layerSettings.cbegin(), layerSettings.cend(), + std::back_inserter(layerSettingsPointers), + [](const renderengine::LayerSettings& settings) { return &settings; }); + renderengine::LayerSettings blurLayerSettings; if (mBlurLayer) { auto blurSettings = targetSettings; @@ -207,7 +212,7 @@ void CachedSet::render(renderengine::RenderEngine& renderEngine, TexturePool& te blurLayerSettings.name = std::string("blur layer"); // Clear out the shadow settings blurLayerSettings.shadow = {}; - layerSettings.push_back(blurLayerSettings); + layerSettingsPointers.push_back(&blurLayerSettings); } renderengine::LayerSettings holePunchSettings; @@ -225,7 +230,7 @@ void CachedSet::render(renderengine::RenderEngine& renderEngine, TexturePool& te holePunchSettings.disableBlending = true; holePunchSettings.alpha = 0.0f; holePunchSettings.name = std::string("hole punch layer"); - layerSettings.push_back(holePunchSettings); + layerSettingsPointers.push_back(&holePunchSettings); // Add a solid background as the first layer in case there is no opaque // buffer behind the punch hole @@ -234,7 +239,7 @@ void CachedSet::render(renderengine::RenderEngine& renderEngine, TexturePool& te holePunchBackgroundSettings.geometry.boundaries = holePunchSettings.geometry.boundaries; holePunchBackgroundSettings.geometry.positionTransform = holePunchSettings.geometry.positionTransform; - layerSettings.emplace(layerSettings.begin(), holePunchBackgroundSettings); + layerSettingsPointers.insert(layerSettingsPointers.begin(), &holePunchBackgroundSettings); } if (sDebugHighlighLayers) { @@ -252,7 +257,7 @@ void CachedSet::render(renderengine::RenderEngine& renderEngine, TexturePool& te .alpha = half(0.05f), }; - layerSettings.emplace_back(highlight); + layerSettingsPointers.emplace_back(&highlight); } auto texture = texturePool.borrowTexture(); @@ -268,8 +273,8 @@ void CachedSet::render(renderengine::RenderEngine& renderEngine, TexturePool& te } auto [status, drawFence] = renderEngine - .drawLayers(displaySettings, layerSettings, texture->get(), - false, std::move(bufferFence)) + .drawLayers(displaySettings, layerSettingsPointers, + texture->get(), false, std::move(bufferFence)) .get(); if (status == NO_ERROR) { diff --git a/services/surfaceflinger/CompositionEngine/tests/OutputTest.cpp b/services/surfaceflinger/CompositionEngine/tests/OutputTest.cpp index cf63ef5183..8f0028c399 100644 --- a/services/surfaceflinger/CompositionEngine/tests/OutputTest.cpp +++ b/services/surfaceflinger/CompositionEngine/tests/OutputTest.cpp @@ -24,7 +24,6 @@ #include #include #include -#include #include #include #include @@ -2885,24 +2884,12 @@ TEST_F(OutputPostFramebufferTest, releaseFencesAreSentToLayerFE) { // are passed. This happens to work with the current implementation, but // would not survive certain calls like Fence::merge() which would return a // new instance. - base::unique_fd layer1FD(layer1Fence->dup()); - base::unique_fd layer2FD(layer2Fence->dup()); - base::unique_fd layer3FD(layer3Fence->dup()); - EXPECT_CALL(*mLayer1.layerFE, onLayerDisplayed(_)) - .WillOnce([&layer1FD](std::shared_future - futureRenderEngineResult) { - EXPECT_EQ(layer1FD, futureRenderEngineResult.get().drawFence); - }); - EXPECT_CALL(*mLayer2.layerFE, onLayerDisplayed(_)) - .WillOnce([&layer2FD](std::shared_future - futureRenderEngineResult) { - EXPECT_EQ(layer2FD, futureRenderEngineResult.get().drawFence); - }); - EXPECT_CALL(*mLayer3.layerFE, onLayerDisplayed(_)) - .WillOnce([&layer3FD](std::shared_future - futureRenderEngineResult) { - EXPECT_EQ(layer3FD, futureRenderEngineResult.get().drawFence); - }); + EXPECT_CALL(*mLayer1.layerFE, + onLayerDisplayed(Property(&sp::get, Eq(layer1Fence.get())))); + EXPECT_CALL(*mLayer2.layerFE, + onLayerDisplayed(Property(&sp::get, Eq(layer2Fence.get())))); + EXPECT_CALL(*mLayer3.layerFE, + onLayerDisplayed(Property(&sp::get, Eq(layer3Fence.get())))); mOutput.postFramebuffer(); } @@ -2928,9 +2915,9 @@ TEST_F(OutputPostFramebufferTest, releaseFencesIncludeClientTargetAcquireFence) // Fence::merge is called, and since none of the fences are actually valid, // Fence::NO_FENCE is returned and passed to each onLayerDisplayed() call. // This is the best we can do without creating a real kernel fence object. - EXPECT_CALL(*mLayer1.layerFE, onLayerDisplayed).WillOnce(Return()); - EXPECT_CALL(*mLayer2.layerFE, onLayerDisplayed).WillOnce(Return()); - EXPECT_CALL(*mLayer3.layerFE, onLayerDisplayed).WillOnce(Return()); + EXPECT_CALL(*mLayer1.layerFE, onLayerDisplayed(Fence::NO_FENCE)); + EXPECT_CALL(*mLayer2.layerFE, onLayerDisplayed(Fence::NO_FENCE)); + EXPECT_CALL(*mLayer3.layerFE, onLayerDisplayed(Fence::NO_FENCE)); mOutput.postFramebuffer(); } @@ -2962,22 +2949,12 @@ TEST_F(OutputPostFramebufferTest, releasedLayersSentPresentFence) { EXPECT_CALL(*mRenderSurface, onPresentDisplayCompleted()); // Each released layer should be given the presentFence. - base::unique_fd layerFD(presentFence.get()->dup()); - EXPECT_CALL(*releasedLayer1, onLayerDisplayed(_)) - .WillOnce([&layerFD](std::shared_future - futureRenderEngineResult) { - EXPECT_EQ(layerFD, futureRenderEngineResult.get().drawFence); - }); - EXPECT_CALL(*releasedLayer2, onLayerDisplayed(_)) - .WillOnce([&layerFD](std::shared_future - futureRenderEngineResult) { - EXPECT_EQ(layerFD, futureRenderEngineResult.get().drawFence); - }); - EXPECT_CALL(*releasedLayer3, onLayerDisplayed(_)) - .WillOnce([&layerFD](std::shared_future - futureRenderEngineResult) { - EXPECT_EQ(layerFD, futureRenderEngineResult.get().drawFence); - }); + EXPECT_CALL(*releasedLayer1, + onLayerDisplayed(Property(&sp::get, Eq(presentFence.get())))); + EXPECT_CALL(*releasedLayer2, + onLayerDisplayed(Property(&sp::get, Eq(presentFence.get())))); + EXPECT_CALL(*releasedLayer3, + onLayerDisplayed(Property(&sp::get, Eq(presentFence.get())))); mOutput.postFramebuffer(); @@ -3154,9 +3131,9 @@ TEST_F(OutputComposeSurfacesTest, handlesZeroCompositionRequests) { EXPECT_CALL(*mRenderSurface, dequeueBuffer(_)).WillRepeatedly(Return(mOutputBuffer)); EXPECT_CALL(mRenderEngine, drawLayers(_, IsEmpty(), _, false, _)) .WillRepeatedly([&](const renderengine::DisplaySettings&, - const std::vector&, + const std::vector&, const std::shared_ptr&, const bool, - base::unique_fd&&) + base::unique_fd &&) -> std::future { return futureOf({NO_ERROR, base::unique_fd()}); }); @@ -3184,11 +3161,11 @@ TEST_F(OutputComposeSurfacesTest, buildsAndRendersRequestList) { })); EXPECT_CALL(*mRenderSurface, dequeueBuffer(_)).WillRepeatedly(Return(mOutputBuffer)); - EXPECT_CALL(mRenderEngine, drawLayers(_, ElementsAre(r1, r2), _, false, _)) + EXPECT_CALL(mRenderEngine, drawLayers(_, ElementsAre(Pointee(r1), Pointee(r2)), _, false, _)) .WillRepeatedly([&](const renderengine::DisplaySettings&, - const std::vector&, + const std::vector&, const std::shared_ptr&, const bool, - base::unique_fd&&) + base::unique_fd &&) -> std::future { return futureOf({NO_ERROR, base::unique_fd()}); }); @@ -3219,11 +3196,11 @@ TEST_F(OutputComposeSurfacesTest, })); EXPECT_CALL(*mRenderSurface, dequeueBuffer(_)).WillRepeatedly(Return(mOutputBuffer)); - EXPECT_CALL(mRenderEngine, drawLayers(_, ElementsAre(r1, r2), _, true, _)) + EXPECT_CALL(mRenderEngine, drawLayers(_, ElementsAre(Pointee(r1), Pointee(r2)), _, true, _)) .WillRepeatedly([&](const renderengine::DisplaySettings&, - const std::vector&, + const std::vector&, const std::shared_ptr&, const bool, - base::unique_fd&&) + base::unique_fd &&) -> std::future { return futureOf({NO_ERROR, base::unique_fd()}); }); @@ -3249,7 +3226,7 @@ TEST_F(OutputComposeSurfacesTest, renderDuplicateClientCompositionRequestsWithou .WillRepeatedly(Return()); EXPECT_CALL(*mRenderSurface, dequeueBuffer(_)).WillRepeatedly(Return(mOutputBuffer)); - EXPECT_CALL(mRenderEngine, drawLayers(_, ElementsAre(r1, r2), _, false, _)) + EXPECT_CALL(mRenderEngine, drawLayers(_, ElementsAre(Pointee(r1), Pointee(r2)), _, false, _)) .Times(2) .WillOnce(Return(ByMove( futureOf({NO_ERROR, base::unique_fd()})))) @@ -3281,7 +3258,7 @@ TEST_F(OutputComposeSurfacesTest, skipDuplicateClientCompositionRequests) { .WillRepeatedly(Return()); EXPECT_CALL(*mRenderSurface, dequeueBuffer(_)).WillRepeatedly(Return(mOutputBuffer)); - EXPECT_CALL(mRenderEngine, drawLayers(_, ElementsAre(r1, r2), _, false, _)) + EXPECT_CALL(mRenderEngine, drawLayers(_, ElementsAre(Pointee(r1), Pointee(r2)), _, false, _)) .WillOnce(Return(ByMove( futureOf({NO_ERROR, base::unique_fd()})))); EXPECT_CALL(mOutput, setExpensiveRenderingExpected(false)); @@ -3317,11 +3294,11 @@ TEST_F(OutputComposeSurfacesTest, clientCompositionIfBufferChanges) { EXPECT_CALL(*mRenderSurface, dequeueBuffer(_)) .WillOnce(Return(mOutputBuffer)) .WillOnce(Return(otherOutputBuffer)); - EXPECT_CALL(mRenderEngine, drawLayers(_, ElementsAre(r1, r2), _, false, _)) + EXPECT_CALL(mRenderEngine, drawLayers(_, ElementsAre(Pointee(r1), Pointee(r2)), _, false, _)) .WillRepeatedly([&](const renderengine::DisplaySettings&, - const std::vector&, + const std::vector&, const std::shared_ptr&, const bool, - base::unique_fd&&) + base::unique_fd &&) -> std::future { return futureOf({NO_ERROR, base::unique_fd()}); }); @@ -3353,10 +3330,10 @@ TEST_F(OutputComposeSurfacesTest, clientCompositionIfRequestChanges) { .WillRepeatedly(Return()); EXPECT_CALL(*mRenderSurface, dequeueBuffer(_)).WillRepeatedly(Return(mOutputBuffer)); - EXPECT_CALL(mRenderEngine, drawLayers(_, ElementsAre(r1, r2), _, false, _)) + EXPECT_CALL(mRenderEngine, drawLayers(_, ElementsAre(Pointee(r1), Pointee(r2)), _, false, _)) .WillOnce(Return(ByMove( futureOf({NO_ERROR, base::unique_fd()})))); - EXPECT_CALL(mRenderEngine, drawLayers(_, ElementsAre(r1, r3), _, false, _)) + EXPECT_CALL(mRenderEngine, drawLayers(_, ElementsAre(Pointee(r1), Pointee(r3)), _, false, _)) .WillOnce(Return(ByMove( futureOf({NO_ERROR, base::unique_fd()})))); @@ -3510,9 +3487,9 @@ struct OutputComposeSurfacesTest_HandlesProtectedContent : public OutputComposeS EXPECT_CALL(mRenderEngine, drawLayers(_, _, _, false, _)) .WillRepeatedly( [&](const renderengine::DisplaySettings&, - const std::vector&, + const std::vector&, const std::shared_ptr&, const bool, - base::unique_fd&&) -> std::future { + base::unique_fd &&) -> std::future { return futureOf( {NO_ERROR, base::unique_fd()}); }); diff --git a/services/surfaceflinger/CompositionEngine/tests/planner/CachedSetTest.cpp b/services/surfaceflinger/CompositionEngine/tests/planner/CachedSetTest.cpp index 42b3d972a8..ecb05f8e5f 100644 --- a/services/surfaceflinger/CompositionEngine/tests/planner/CachedSetTest.cpp +++ b/services/surfaceflinger/CompositionEngine/tests/planner/CachedSetTest.cpp @@ -346,15 +346,15 @@ TEST_F(CachedSetTest, renderUnsecureOutput) { const auto drawLayers = [&](const renderengine::DisplaySettings& displaySettings, - const std::vector& layers, + const std::vector& layers, const std::shared_ptr&, const bool, - base::unique_fd&&) -> std::future { + base::unique_fd &&) -> std::future { EXPECT_EQ(mOutputState.framebufferSpace.getContent(), displaySettings.physicalDisplay); EXPECT_EQ(mOutputState.layerStackSpace.getContent(), displaySettings.clip); EXPECT_EQ(ui::Transform::toRotationFlags(mOutputState.framebufferSpace.getOrientation()), displaySettings.orientation); - EXPECT_EQ(0.5f, layers[0].alpha); - EXPECT_EQ(0.75f, layers[1].alpha); + EXPECT_EQ(0.5f, layers[0]->alpha); + EXPECT_EQ(0.75f, layers[1]->alpha); EXPECT_EQ(ui::Dataspace::SRGB, displaySettings.outputDataspace); return futureOf({NO_ERROR, base::unique_fd()}); }; @@ -398,15 +398,15 @@ TEST_F(CachedSetTest, renderSecureOutput) { const auto drawLayers = [&](const renderengine::DisplaySettings& displaySettings, - const std::vector& layers, + const std::vector& layers, const std::shared_ptr&, const bool, - base::unique_fd&&) -> std::future { + base::unique_fd &&) -> std::future { EXPECT_EQ(mOutputState.framebufferSpace.getContent(), displaySettings.physicalDisplay); EXPECT_EQ(mOutputState.layerStackSpace.getContent(), displaySettings.clip); EXPECT_EQ(ui::Transform::toRotationFlags(mOutputState.framebufferSpace.getOrientation()), displaySettings.orientation); - EXPECT_EQ(0.5f, layers[0].alpha); - EXPECT_EQ(0.75f, layers[1].alpha); + EXPECT_EQ(0.5f, layers[0]->alpha); + EXPECT_EQ(0.75f, layers[1]->alpha); EXPECT_EQ(ui::Dataspace::SRGB, displaySettings.outputDataspace); return futureOf({NO_ERROR, base::unique_fd()}); @@ -453,15 +453,15 @@ TEST_F(CachedSetTest, rendersWithOffsetFramebufferContent) { const auto drawLayers = [&](const renderengine::DisplaySettings& displaySettings, - const std::vector& layers, + const std::vector& layers, const std::shared_ptr&, const bool, - base::unique_fd&&) -> std::future { + base::unique_fd &&) -> std::future { EXPECT_EQ(mOutputState.framebufferSpace.getContent(), displaySettings.physicalDisplay); EXPECT_EQ(mOutputState.layerStackSpace.getContent(), displaySettings.clip); EXPECT_EQ(ui::Transform::toRotationFlags(mOutputState.framebufferSpace.getOrientation()), displaySettings.orientation); - EXPECT_EQ(0.5f, layers[0].alpha); - EXPECT_EQ(0.75f, layers[1].alpha); + EXPECT_EQ(0.5f, layers[0]->alpha); + EXPECT_EQ(0.75f, layers[1]->alpha); EXPECT_EQ(ui::Dataspace::SRGB, displaySettings.outputDataspace); return futureOf({NO_ERROR, base::unique_fd()}); @@ -656,26 +656,26 @@ TEST_F(CachedSetTest, addHolePunch) { const auto drawLayers = [&](const renderengine::DisplaySettings&, - const std::vector& layers, + const std::vector& layers, const std::shared_ptr&, const bool, - base::unique_fd&&) -> std::future { + base::unique_fd &&) -> std::future { // If the highlight layer is enabled, it will increase the size by 1. // We're interested in the third layer either way. EXPECT_GE(layers.size(), 4u); { - const auto holePunchSettings = layers[3]; - EXPECT_EQ(nullptr, holePunchSettings.source.buffer.buffer); - EXPECT_EQ(half3(0.0f, 0.0f, 0.0f), holePunchSettings.source.solidColor); - EXPECT_TRUE(holePunchSettings.disableBlending); - EXPECT_EQ(0.0f, holePunchSettings.alpha); + const auto* holePunchSettings = layers[3]; + EXPECT_EQ(nullptr, holePunchSettings->source.buffer.buffer); + EXPECT_EQ(half3(0.0f, 0.0f, 0.0f), holePunchSettings->source.solidColor); + EXPECT_TRUE(holePunchSettings->disableBlending); + EXPECT_EQ(0.0f, holePunchSettings->alpha); } { - const auto holePunchBackgroundSettings = layers[0]; - EXPECT_EQ(nullptr, holePunchBackgroundSettings.source.buffer.buffer); - EXPECT_EQ(half3(0.0f, 0.0f, 0.0f), holePunchBackgroundSettings.source.solidColor); - EXPECT_FALSE(holePunchBackgroundSettings.disableBlending); - EXPECT_EQ(1.0f, holePunchBackgroundSettings.alpha); + const auto* holePunchBackgroundSettings = layers[0]; + EXPECT_EQ(nullptr, holePunchBackgroundSettings->source.buffer.buffer); + EXPECT_EQ(half3(0.0f, 0.0f, 0.0f), holePunchBackgroundSettings->source.solidColor); + EXPECT_FALSE(holePunchBackgroundSettings->disableBlending); + EXPECT_EQ(1.0f, holePunchBackgroundSettings->alpha); } return futureOf({NO_ERROR, base::unique_fd()}); @@ -717,27 +717,27 @@ TEST_F(CachedSetTest, addHolePunch_noBuffer) { const auto drawLayers = [&](const renderengine::DisplaySettings&, - const std::vector& layers, + const std::vector& layers, const std::shared_ptr&, const bool, - base::unique_fd&&) -> std::future { + base::unique_fd &&) -> std::future { // If the highlight layer is enabled, it will increase the size by 1. // We're interested in the third layer either way. EXPECT_GE(layers.size(), 4u); { - const auto holePunchSettings = layers[3]; - EXPECT_EQ(nullptr, holePunchSettings.source.buffer.buffer); - EXPECT_EQ(half3(0.0f, 0.0f, 0.0f), holePunchSettings.source.solidColor); - EXPECT_TRUE(holePunchSettings.disableBlending); - EXPECT_EQ(0.0f, holePunchSettings.alpha); + const auto* holePunchSettings = layers[3]; + EXPECT_EQ(nullptr, holePunchSettings->source.buffer.buffer); + EXPECT_EQ(half3(0.0f, 0.0f, 0.0f), holePunchSettings->source.solidColor); + EXPECT_TRUE(holePunchSettings->disableBlending); + EXPECT_EQ(0.0f, holePunchSettings->alpha); } { - const auto holePunchBackgroundSettings = layers[0]; - EXPECT_EQ(nullptr, holePunchBackgroundSettings.source.buffer.buffer); - EXPECT_EQ(half3(0.0f, 0.0f, 0.0f), holePunchBackgroundSettings.source.solidColor); - EXPECT_FALSE(holePunchBackgroundSettings.disableBlending); - EXPECT_EQ(1.0f, holePunchBackgroundSettings.alpha); + const auto* holePunchBackgroundSettings = layers[0]; + EXPECT_EQ(nullptr, holePunchBackgroundSettings->source.buffer.buffer); + EXPECT_EQ(half3(0.0f, 0.0f, 0.0f), holePunchBackgroundSettings->source.solidColor); + EXPECT_FALSE(holePunchBackgroundSettings->disableBlending); + EXPECT_EQ(1.0f, holePunchBackgroundSettings->alpha); } return futureOf({NO_ERROR, base::unique_fd()}); @@ -867,16 +867,16 @@ TEST_F(CachedSetTest, addBlur) { const auto drawLayers = [&](const renderengine::DisplaySettings&, - const std::vector& layers, + const std::vector& layers, const std::shared_ptr&, const bool, - base::unique_fd&&) -> std::future { + base::unique_fd &&) -> std::future { // If the highlight layer is enabled, it will increase the size by 1. // We're interested in the third layer either way. EXPECT_GE(layers.size(), 3u); - const auto blurSettings = layers[2]; - EXPECT_TRUE(blurSettings.skipContentDraw); - EXPECT_EQ(half3(0.0f, 0.0f, 0.0f), blurSettings.source.solidColor); - EXPECT_EQ(0.0f, blurSettings.alpha); + const auto* blurSettings = layers[2]; + EXPECT_TRUE(blurSettings->skipContentDraw); + EXPECT_EQ(half3(0.0f, 0.0f, 0.0f), blurSettings->source.solidColor); + EXPECT_EQ(0.0f, blurSettings->alpha); return futureOf({NO_ERROR, base::unique_fd()}); }; diff --git a/services/surfaceflinger/Layer.cpp b/services/surfaceflinger/Layer.cpp index d68cf9720f..5707c67a56 100644 --- a/services/surfaceflinger/Layer.cpp +++ b/services/surfaceflinger/Layer.cpp @@ -221,8 +221,7 @@ LayerCreationArgs::LayerCreationArgs(SurfaceFlinger* flinger, sp client, * Layer. So, the implementation is done in BufferLayer. When called on a * EffectLayer object, it's essentially a NOP. */ -void Layer::onLayerDisplayed( - std::shared_future /*futureRenderEngineResult*/) {} +void Layer::onLayerDisplayed(const sp& /*releaseFence*/) {} void Layer::removeRelativeZ(const std::vector& layersInTree) { if (mDrawingState.zOrderRelativeOf == nullptr) { diff --git a/services/surfaceflinger/Layer.h b/services/surfaceflinger/Layer.h index 4569f9af23..07b2eb5130 100644 --- a/services/surfaceflinger/Layer.h +++ b/services/surfaceflinger/Layer.h @@ -616,8 +616,7 @@ public: void prepareCompositionState(compositionengine::LayerFE::StateSubset subset) override; std::vector prepareClientCompositionList( compositionengine::LayerFE::ClientCompositionTargetSettings&) override; - void onLayerDisplayed( - std::shared_future futureRenderEngineResult) override; + void onLayerDisplayed(const sp& releaseFence) override; void setWasClientComposed(const sp& fence) override { mLastClientCompositionFence = fence; diff --git a/services/surfaceflinger/RegionSamplingThread.cpp b/services/surfaceflinger/RegionSamplingThread.cpp index d0f56b5bdd..aa2fec56ad 100644 --- a/services/surfaceflinger/RegionSamplingThread.cpp +++ b/services/surfaceflinger/RegionSamplingThread.cpp @@ -356,13 +356,10 @@ void RegionSamplingThread::captureSample() { renderengine::ExternalTexture::Usage::WRITEABLE); } - auto captureScreenResultFuture = - mFlinger.captureScreenCommon(std::move(renderAreaFuture), traverseLayers, buffer, - true /* regionSampling */, false /* grayscale */, nullptr); - auto& captureScreenResult = captureScreenResultFuture.get(); - if (captureScreenResult.drawFence.ok()) { - sync_wait(captureScreenResult.drawFence.get(), -1); - } + const sp captureListener = new SyncScreenCaptureListener(); + mFlinger.captureScreenCommon(std::move(renderAreaFuture), traverseLayers, buffer, + true /* regionSampling */, false /* grayscale */, captureListener); + ScreenCaptureResults captureResults = captureListener->waitForResults(); std::vector activeDescriptors; for (const auto& descriptor : descriptors) { diff --git a/services/surfaceflinger/SurfaceFlinger.cpp b/services/surfaceflinger/SurfaceFlinger.cpp index 638458cfd3..acb81dc41c 100644 --- a/services/surfaceflinger/SurfaceFlinger.cpp +++ b/services/surfaceflinger/SurfaceFlinger.cpp @@ -5972,10 +5972,9 @@ status_t SurfaceFlinger::captureDisplay(const DisplayCaptureArgs& args, traverseLayersInLayerStack(layerStack, args.uid, visitor); }; - auto captureResultFuture = captureScreenCommon(std::move(renderAreaFuture), traverseLayers, - reqSize, args.pixelFormat, args.allowProtected, - args.grayscale, captureListener); - return captureResultFuture.get().status; + return captureScreenCommon(std::move(renderAreaFuture), traverseLayers, reqSize, + args.pixelFormat, args.allowProtected, args.grayscale, + captureListener); } status_t SurfaceFlinger::captureDisplay(DisplayId displayId, @@ -6010,15 +6009,9 @@ status_t SurfaceFlinger::captureDisplay(DisplayId displayId, traverseLayersInLayerStack(layerStack, CaptureArgs::UNSET_UID, visitor); }; - if (captureListener == nullptr) { - ALOGE("capture screen must provide a capture listener callback"); - return BAD_VALUE; - } - auto captureResultFuture = - captureScreenCommon(std::move(renderAreaFuture), traverseLayers, size, - ui::PixelFormat::RGBA_8888, false /* allowProtected */, - false /* grayscale */, captureListener); - return captureResultFuture.get().status; + return captureScreenCommon(std::move(renderAreaFuture), traverseLayers, size, + ui::PixelFormat::RGBA_8888, false /* allowProtected */, + false /* grayscale */, captureListener); } status_t SurfaceFlinger::captureLayers(const LayerCaptureArgs& args, @@ -6145,28 +6138,23 @@ status_t SurfaceFlinger::captureLayers(const LayerCaptureArgs& args, }); }; - if (captureListener == nullptr) { - ALOGE("capture screen must provide a capture listener callback"); - return BAD_VALUE; - } - - auto captureResultFuture = captureScreenCommon(std::move(renderAreaFuture), traverseLayers, - reqSize, args.pixelFormat, args.allowProtected, - args.grayscale, captureListener); - return captureResultFuture.get().status; + return captureScreenCommon(std::move(renderAreaFuture), traverseLayers, reqSize, + args.pixelFormat, args.allowProtected, args.grayscale, + captureListener); } -std::shared_future SurfaceFlinger::captureScreenCommon( - RenderAreaFuture renderAreaFuture, TraverseLayersFunction traverseLayers, - ui::Size bufferSize, ui::PixelFormat reqPixelFormat, bool allowProtected, bool grayscale, - const sp& captureListener) { +status_t SurfaceFlinger::captureScreenCommon(RenderAreaFuture renderAreaFuture, + TraverseLayersFunction traverseLayers, + ui::Size bufferSize, ui::PixelFormat reqPixelFormat, + bool allowProtected, bool grayscale, + const sp& captureListener) { ATRACE_CALL(); if (exceedsMaxRenderTargetSize(bufferSize.getWidth(), bufferSize.getHeight())) { ALOGE("Attempted to capture screen with size (%" PRId32 ", %" PRId32 ") that exceeds render target size limit.", bufferSize.getWidth(), bufferSize.getHeight()); - return ftl::yield({BAD_VALUE, base::unique_fd()}).share(); + return BAD_VALUE; } // Loop over all visible layers to see whether there's any protected layer. A protected layer is @@ -6206,23 +6194,25 @@ std::shared_future SurfaceFlinger::captureScre false /* regionSampling */, grayscale, captureListener); } -std::shared_future SurfaceFlinger::captureScreenCommon( +status_t SurfaceFlinger::captureScreenCommon( RenderAreaFuture renderAreaFuture, TraverseLayersFunction traverseLayers, const std::shared_ptr& buffer, bool regionSampling, bool grayscale, const sp& captureListener) { ATRACE_CALL(); + if (captureListener == nullptr) { + ALOGE("capture screen must provide a capture listener callback"); + return BAD_VALUE; + } + bool canCaptureBlackoutContent = hasCaptureBlackoutContentPermission(); - auto scheduleResultFuture = schedule([=, - renderAreaFuture = std::move(renderAreaFuture)]() mutable - -> std::shared_future { + static_cast(schedule([=, renderAreaFuture = std::move(renderAreaFuture)]() mutable { if (mRefreshPending) { ALOGW("Skipping screenshot for now"); captureScreenCommon(std::move(renderAreaFuture), traverseLayers, buffer, regionSampling, grayscale, captureListener); - return ftl::yield({NO_ERROR, base::unique_fd()}) - .share(); + return; } ScreenCaptureResults captureResults; std::unique_ptr renderArea = renderAreaFuture.get(); @@ -6230,44 +6220,24 @@ std::shared_future SurfaceFlinger::captureScre ALOGW("Skipping screen capture because of invalid render area."); captureResults.result = NO_MEMORY; captureListener->onScreenCaptureCompleted(captureResults); - return ftl::yield({NO_ERROR, base::unique_fd()}) - .share(); + return; } - std::shared_future renderEngineResultFuture; - + status_t result = NO_ERROR; renderArea->render([&] { - renderEngineResultFuture = - renderScreenImplLocked(*renderArea, traverseLayers, buffer, - canCaptureBlackoutContent, regionSampling, grayscale, - captureResults); + result = renderScreenImplLocked(*renderArea, traverseLayers, buffer, + canCaptureBlackoutContent, regionSampling, grayscale, + captureResults); }); - // spring up a thread to unblock SF main thread and wait for - // RenderEngineResult to be available - if (captureListener != nullptr) { - std::async([=]() mutable { - ATRACE_NAME("captureListener is nonnull!"); - auto& [status, drawFence] = renderEngineResultFuture.get(); - captureResults.result = status; - captureResults.fence = new Fence(dup(drawFence)); - captureListener->onScreenCaptureCompleted(captureResults); - }); - } - return renderEngineResultFuture; - }); - // flatten scheduleResultFuture object to single shared_future object - std::future captureScreenResultFuture = - ftl::chain(std::move(scheduleResultFuture)) - .then([=](std::shared_future futureObject) - -> renderengine::RenderEngineResult { - auto& [status, drawFence] = futureObject.get(); - return {status, base::unique_fd(dup(drawFence))}; - }); - return captureScreenResultFuture.share(); + captureResults.result = result; + captureListener->onScreenCaptureCompleted(captureResults); + })); + + return NO_ERROR; } -std::shared_future SurfaceFlinger::renderScreenImplLocked( +status_t SurfaceFlinger::renderScreenImplLocked( const RenderArea& renderArea, TraverseLayersFunction traverseLayers, const std::shared_ptr& buffer, bool canCaptureBlackoutContent, bool regionSampling, bool grayscale, @@ -6286,8 +6256,7 @@ std::shared_future SurfaceFlinger::renderScree // the impetus on WindowManager to not persist them. if (captureResults.capturedSecureLayers && !canCaptureBlackoutContent) { ALOGW("FB is protected: PERMISSION_DENIED"); - return ftl::yield({PERMISSION_DENIED, base::unique_fd()}) - .share(); + return PERMISSION_DENIED; } captureResults.buffer = buffer->getBuffer(); @@ -6369,12 +6338,11 @@ std::shared_future SurfaceFlinger::renderScree }); - std::vector clientRenderEngineLayers; - clientRenderEngineLayers.reserve(clientCompositionLayers.size()); + std::vector clientCompositionLayerPointers( + clientCompositionLayers.size()); std::transform(clientCompositionLayers.begin(), clientCompositionLayers.end(), - std::back_inserter(clientRenderEngineLayers), - [](compositionengine::LayerFE::LayerSettings& settings) - -> renderengine::LayerSettings { return settings; }); + clientCompositionLayerPointers.begin(), + std::pointer_traits::pointer_to); // Use an empty fence for the buffer fence, since we just created the buffer so // there is no need for synchronization with the GPU. @@ -6382,22 +6350,24 @@ std::shared_future SurfaceFlinger::renderScree getRenderEngine().useProtectedContext(useProtected); const constexpr bool kUseFramebufferCache = false; - std::future drawLayersResult = - getRenderEngine().drawLayers(clientCompositionDisplay, clientRenderEngineLayers, buffer, - kUseFramebufferCache, std::move(bufferFence)); - - std::shared_future drawLayersResultFuture = - drawLayersResult.share(); // drawLayersResult will be moved to shared one + auto [status, drawFence] = + getRenderEngine() + .drawLayers(clientCompositionDisplay, clientCompositionLayerPointers, buffer, + kUseFramebufferCache, std::move(bufferFence)) + .get(); - for (auto* layer : renderedLayers) { - // make a copy of shared_future object for each layer - layer->onLayerDisplayed(drawLayersResultFuture); + if (drawFence >= 0) { + sp releaseFence = new Fence(dup(drawFence)); + for (auto* layer : renderedLayers) { + layer->onLayerDisplayed(releaseFence); + } } + captureResults.fence = new Fence(drawFence.release()); // Always switch back to unprotected context. getRenderEngine().useProtectedContext(false); - return drawLayersResultFuture; + return status; } void SurfaceFlinger::windowInfosReported() { diff --git a/services/surfaceflinger/SurfaceFlinger.h b/services/surfaceflinger/SurfaceFlinger.h index 45fd94e50c..1f0e42ddf3 100644 --- a/services/surfaceflinger/SurfaceFlinger.h +++ b/services/surfaceflinger/SurfaceFlinger.h @@ -906,17 +906,17 @@ private: // Boot animation, on/off animations and screen capture void startBootAnim(); - std::shared_future captureScreenCommon( - RenderAreaFuture, TraverseLayersFunction, ui::Size bufferSize, ui::PixelFormat, - bool allowProtected, bool grayscale, const sp&); - std::shared_future captureScreenCommon( - RenderAreaFuture, TraverseLayersFunction, - const std::shared_ptr&, bool regionSampling, - bool grayscale, const sp&); - std::shared_future renderScreenImplLocked( - const RenderArea&, TraverseLayersFunction, - const std::shared_ptr&, bool canCaptureBlackoutContent, - bool regionSampling, bool grayscale, ScreenCaptureResults&); + status_t captureScreenCommon(RenderAreaFuture, TraverseLayersFunction, ui::Size bufferSize, + ui::PixelFormat, bool allowProtected, bool grayscale, + const sp&); + status_t captureScreenCommon(RenderAreaFuture, TraverseLayersFunction, + const std::shared_ptr&, + bool regionSampling, bool grayscale, + const sp&); + status_t renderScreenImplLocked(const RenderArea&, TraverseLayersFunction, + const std::shared_ptr&, + bool canCaptureBlackoutContent, bool regionSampling, + bool grayscale, ScreenCaptureResults&); // If the uid provided is not UNSET_UID, the traverse will skip any layers that don't have a // matching ownerUid diff --git a/services/surfaceflinger/TransactionCallbackInvoker.cpp b/services/surfaceflinger/TransactionCallbackInvoker.cpp index 8fbf0b4d07..c1eb8966d1 100644 --- a/services/surfaceflinger/TransactionCallbackInvoker.cpp +++ b/services/surfaceflinger/TransactionCallbackInvoker.cpp @@ -154,38 +154,6 @@ status_t TransactionCallbackInvoker::addCallbackHandle(const sp& // destroyed the client side is dead and there won't be anyone to send the callback to. sp surfaceControl = handle->surfaceControl.promote(); if (surfaceControl) { - sp prevFence = nullptr; - - for (const auto& futureStruct : handle->previousReleaseFences) { - sp currentFence = sp::make(dup(futureStruct.get().drawFence)); - if (prevFence == nullptr && currentFence->getStatus() != Fence::Status::Invalid) { - prevFence = currentFence; - handle->previousReleaseFence = prevFence; - } else if (prevFence != nullptr) { - // If both fences are signaled or both are unsignaled, we need to merge - // them to get an accurate timestamp. - if (prevFence->getStatus() != Fence::Status::Invalid && - prevFence->getStatus() == currentFence->getStatus()) { - char fenceName[32] = {}; - snprintf(fenceName, 32, "%.28s", handle->name.c_str()); - sp mergedFence = Fence::merge(fenceName, prevFence, currentFence); - if (mergedFence->isValid()) { - handle->previousReleaseFence = mergedFence; - prevFence = handle->previousReleaseFence; - } - } else if (currentFence->getStatus() == Fence::Status::Unsignaled) { - // If one fence has signaled and the other hasn't, the unsignaled - // fence will approximately correspond with the correct timestamp. - // There's a small race if both fences signal at about the same time - // and their statuses are retrieved with unfortunate timing. However, - // by this point, they will have both signaled and only the timestamp - // will be slightly off; any dependencies after this point will - // already have been met. - handle->previousReleaseFence = currentFence; - } - } - } - handle->previousReleaseFences = {}; FrameEventHistoryStats eventStats(handle->frameNumber, handle->gpuCompositionDoneFence->getSnapshot().fence, handle->compositorTiming, handle->refreshStartTime, diff --git a/services/surfaceflinger/TransactionCallbackInvoker.h b/services/surfaceflinger/TransactionCallbackInvoker.h index 100dbfa8aa..7e879e119b 100644 --- a/services/surfaceflinger/TransactionCallbackInvoker.h +++ b/services/surfaceflinger/TransactionCallbackInvoker.h @@ -18,9 +18,8 @@ #include #include -#include -#include #include +#include #include #include #include @@ -29,7 +28,6 @@ #include #include -#include #include namespace android { @@ -44,9 +42,7 @@ public: wp surfaceControl; bool releasePreviousBuffer = false; - std::string name; sp previousReleaseFence; - std::vector> previousReleaseFences; nsecs_t acquireTime = -1; nsecs_t latchTime = -1; uint32_t transformHint = 0; diff --git a/services/surfaceflinger/tests/unittests/CompositionTest.cpp b/services/surfaceflinger/tests/unittests/CompositionTest.cpp index 61c7c398dd..5135ff952f 100644 --- a/services/surfaceflinger/tests/unittests/CompositionTest.cpp +++ b/services/surfaceflinger/tests/unittests/CompositionTest.cpp @@ -247,16 +247,10 @@ void CompositionTest::captureScreenComposition() { "screenshot"), *mRenderEngine, true); - auto result = mFlinger.renderScreenImplLocked(*renderArea, traverseLayers, mCaptureScreenBuffer, - forSystem, regionSampling); - EXPECT_TRUE(result.valid()); - - auto& [status, drawFence] = result.get(); - - EXPECT_EQ(NO_ERROR, status); - if (drawFence.ok()) { - sync_wait(drawFence.get(), -1); - } + status_t result = + mFlinger.renderScreenImplLocked(*renderArea, traverseLayers, mCaptureScreenBuffer, + forSystem, regionSampling); + EXPECT_EQ(NO_ERROR, result); LayerCase::cleanup(this); } @@ -352,9 +346,9 @@ struct BaseDisplayVariant { static void setupCommonScreensCaptureCallExpectations(CompositionTest* test) { EXPECT_CALL(*test->mRenderEngine, drawLayers) .WillRepeatedly([&](const renderengine::DisplaySettings& displaySettings, - const std::vector&, + const std::vector&, const std::shared_ptr&, - const bool, base::unique_fd&&) + const bool, base::unique_fd &&) -> std::future { EXPECT_EQ(DEFAULT_DISPLAY_MAX_LUMINANCE, displaySettings.maxLuminance); EXPECT_EQ(Rect(DEFAULT_DISPLAY_WIDTH, DEFAULT_DISPLAY_HEIGHT), @@ -403,9 +397,9 @@ struct BaseDisplayVariant { Return(0))); EXPECT_CALL(*test->mRenderEngine, drawLayers) .WillRepeatedly([&](const renderengine::DisplaySettings& displaySettings, - const std::vector&, + const std::vector&, const std::shared_ptr&, - const bool, base::unique_fd&&) + const bool, base::unique_fd &&) -> std::future { EXPECT_EQ(DEFAULT_DISPLAY_MAX_LUMINANCE, displaySettings.maxLuminance); EXPECT_EQ(Rect(DEFAULT_DISPLAY_WIDTH, DEFAULT_DISPLAY_HEIGHT), @@ -639,9 +633,9 @@ struct BaseLayerProperties { static void setupREBufferCompositionCommonCallExpectations(CompositionTest* test) { EXPECT_CALL(*test->mRenderEngine, drawLayers) .WillOnce([&](const renderengine::DisplaySettings& displaySettings, - const std::vector& layerSettings, + const std::vector& layerSettings, const std::shared_ptr&, const bool, - base::unique_fd&&) -> std::future { + base::unique_fd &&) -> std::future { EXPECT_EQ(DEFAULT_DISPLAY_MAX_LUMINANCE, displaySettings.maxLuminance); EXPECT_EQ(Rect(DEFAULT_DISPLAY_WIDTH, DEFAULT_DISPLAY_HEIGHT), displaySettings.physicalDisplay); @@ -658,16 +652,16 @@ struct BaseLayerProperties { "verification lambda"; return resultFuture; } - const renderengine::LayerSettings layer = layerSettings.back(); - EXPECT_THAT(layer.source.buffer.buffer, Not(IsNull())); - EXPECT_THAT(layer.source.buffer.fence, Not(IsNull())); - EXPECT_EQ(DEFAULT_TEXTURE_ID, layer.source.buffer.textureName); - EXPECT_EQ(false, layer.source.buffer.isY410BT2020); - EXPECT_EQ(true, layer.source.buffer.usePremultipliedAlpha); - EXPECT_EQ(false, layer.source.buffer.isOpaque); - EXPECT_EQ(0.0, layer.geometry.roundedCornersRadius); - EXPECT_EQ(ui::Dataspace::UNKNOWN, layer.sourceDataspace); - EXPECT_EQ(LayerProperties::COLOR[3], layer.alpha); + const renderengine::LayerSettings* layer = layerSettings.back(); + EXPECT_THAT(layer->source.buffer.buffer, Not(IsNull())); + EXPECT_THAT(layer->source.buffer.fence, Not(IsNull())); + EXPECT_EQ(DEFAULT_TEXTURE_ID, layer->source.buffer.textureName); + EXPECT_EQ(false, layer->source.buffer.isY410BT2020); + EXPECT_EQ(true, layer->source.buffer.usePremultipliedAlpha); + EXPECT_EQ(false, layer->source.buffer.isOpaque); + EXPECT_EQ(0.0, layer->geometry.roundedCornersRadius); + EXPECT_EQ(ui::Dataspace::UNKNOWN, layer->sourceDataspace); + EXPECT_EQ(LayerProperties::COLOR[3], layer->alpha); return resultFuture; }); } @@ -691,9 +685,9 @@ struct BaseLayerProperties { static void setupREColorCompositionCallExpectations(CompositionTest* test) { EXPECT_CALL(*test->mRenderEngine, drawLayers) .WillOnce([&](const renderengine::DisplaySettings& displaySettings, - const std::vector& layerSettings, + const std::vector& layerSettings, const std::shared_ptr&, const bool, - base::unique_fd&&) -> std::future { + base::unique_fd &&) -> std::future { EXPECT_EQ(DEFAULT_DISPLAY_MAX_LUMINANCE, displaySettings.maxLuminance); EXPECT_EQ(Rect(DEFAULT_DISPLAY_WIDTH, DEFAULT_DISPLAY_HEIGHT), displaySettings.physicalDisplay); @@ -710,14 +704,14 @@ struct BaseLayerProperties { "setupREColorCompositionCallExpectations verification lambda"; return resultFuture; } - const renderengine::LayerSettings layer = layerSettings.back(); - EXPECT_THAT(layer.source.buffer.buffer, IsNull()); + const renderengine::LayerSettings* layer = layerSettings.back(); + EXPECT_THAT(layer->source.buffer.buffer, IsNull()); EXPECT_EQ(half3(LayerProperties::COLOR[0], LayerProperties::COLOR[1], LayerProperties::COLOR[2]), - layer.source.solidColor); - EXPECT_EQ(0.0, layer.geometry.roundedCornersRadius); - EXPECT_EQ(ui::Dataspace::UNKNOWN, layer.sourceDataspace); - EXPECT_EQ(LayerProperties::COLOR[3], layer.alpha); + layer->source.solidColor); + EXPECT_EQ(0.0, layer->geometry.roundedCornersRadius); + EXPECT_EQ(ui::Dataspace::UNKNOWN, layer->sourceDataspace); + EXPECT_EQ(LayerProperties::COLOR[3], layer->alpha); return resultFuture; }); } @@ -771,9 +765,9 @@ struct CommonSecureLayerProperties : public BaseLayerProperties static void setupInsecureREBufferCompositionCommonCallExpectations(CompositionTest* test) { EXPECT_CALL(*test->mRenderEngine, drawLayers) .WillOnce([&](const renderengine::DisplaySettings& displaySettings, - const std::vector& layerSettings, + const std::vector& layerSettings, const std::shared_ptr&, const bool, - base::unique_fd&&) -> std::future { + base::unique_fd &&) -> std::future { EXPECT_EQ(DEFAULT_DISPLAY_MAX_LUMINANCE, displaySettings.maxLuminance); EXPECT_EQ(Rect(DEFAULT_DISPLAY_WIDTH, DEFAULT_DISPLAY_HEIGHT), displaySettings.physicalDisplay); @@ -790,12 +784,12 @@ struct CommonSecureLayerProperties : public BaseLayerProperties "verification lambda"; return resultFuture; } - const renderengine::LayerSettings layer = layerSettings.back(); - EXPECT_THAT(layer.source.buffer.buffer, IsNull()); - EXPECT_EQ(half3(0.0f, 0.0f, 0.0f), layer.source.solidColor); - EXPECT_EQ(0.0, layer.geometry.roundedCornersRadius); - EXPECT_EQ(ui::Dataspace::UNKNOWN, layer.sourceDataspace); - EXPECT_EQ(1.0f, layer.alpha); + const renderengine::LayerSettings* layer = layerSettings.back(); + EXPECT_THAT(layer->source.buffer.buffer, IsNull()); + EXPECT_EQ(half3(0.0f, 0.0f, 0.0f), layer->source.solidColor); + EXPECT_EQ(0.0, layer->geometry.roundedCornersRadius); + EXPECT_EQ(ui::Dataspace::UNKNOWN, layer->sourceDataspace); + EXPECT_EQ(1.0f, layer->alpha); return resultFuture; }); } -- cgit v1.2.3-59-g8ed1b From 59a9f506c7293fdee01482a4bb532df953600d4c Mon Sep 17 00:00:00 2001 From: Sally Qi Date: Tue, 12 Oct 2021 18:53:23 +0000 Subject: Revert^2 "Second Patch for async RenderEngine" Keep the change of Second Patch for async RenderEngine and fix the regression - remove the vector variables which is to store futureFence locally in BufferStateLayer to get avoid fd leaking - screenshots initiated from the app don't wait on the SF main thread. 2109270e74a18585aceffc94d1758cee47bb4175 Bug: 202843200 Bug: 202833127 Bug: 202808760 Test: Wembley PIN setting test, NexusLauncherOutOfProcTests Change-Id: I87847d01e2e330ddec88272cd8608f0b78c0a2cd --- libs/renderengine/RenderEngine.cpp | 2 +- libs/renderengine/gl/GLESRenderEngine.cpp | 66 +++++----- libs/renderengine/gl/GLESRenderEngine.h | 2 +- .../include/renderengine/RenderEngine.h | 4 +- .../include/renderengine/mock/RenderEngine.h | 4 +- libs/renderengine/skia/Cache.cpp | 16 +-- libs/renderengine/skia/SkiaGLRenderEngine.cpp | 113 +++++++++-------- libs/renderengine/skia/SkiaGLRenderEngine.h | 7 +- libs/renderengine/skia/SkiaRenderEngine.h | 2 +- libs/renderengine/tests/RenderEngineTest.cpp | 125 +++++++++---------- .../tests/RenderEngineThreadedTest.cpp | 7 +- .../renderengine/threaded/RenderEngineThreaded.cpp | 11 +- libs/renderengine/threaded/RenderEngineThreaded.h | 4 +- services/surfaceflinger/BufferQueueLayer.cpp | 4 +- services/surfaceflinger/BufferQueueLayer.h | 3 +- services/surfaceflinger/BufferStateLayer.cpp | 88 +++----------- services/surfaceflinger/BufferStateLayer.h | 7 +- .../include/compositionengine/LayerFE.h | 4 +- .../include/compositionengine/mock/LayerFE.h | 2 +- .../CompositionEngine/src/Output.cpp | 23 ++-- .../CompositionEngine/src/planner/CachedSet.cpp | 17 +-- .../CompositionEngine/tests/OutputTest.cpp | 87 +++++++++----- .../tests/planner/CachedSetTest.cpp | 84 ++++++------- services/surfaceflinger/Layer.cpp | 3 +- services/surfaceflinger/Layer.h | 3 +- services/surfaceflinger/RegionSamplingThread.cpp | 11 +- services/surfaceflinger/SurfaceFlinger.cpp | 133 +++++++++++++-------- services/surfaceflinger/SurfaceFlinger.h | 22 ++-- .../surfaceflinger/TransactionCallbackInvoker.cpp | 32 +++++ .../surfaceflinger/TransactionCallbackInvoker.h | 6 +- .../tests/unittests/CompositionTest.cpp | 78 ++++++------ 31 files changed, 513 insertions(+), 457 deletions(-) (limited to 'services/surfaceflinger/BufferQueueLayer.cpp') diff --git a/libs/renderengine/RenderEngine.cpp b/libs/renderengine/RenderEngine.cpp index 2174df5515..a9ea690a7c 100644 --- a/libs/renderengine/RenderEngine.cpp +++ b/libs/renderengine/RenderEngine.cpp @@ -96,7 +96,7 @@ void RenderEngine::validateOutputBufferUsage(const sp& buffer) { } std::future RenderEngine::drawLayers( - const DisplaySettings& display, const std::vector& layers, + const DisplaySettings& display, const std::vector& layers, const std::shared_ptr& buffer, const bool useFramebufferCache, base::unique_fd&& bufferFence) { const auto resultPromise = std::make_shared>(); diff --git a/libs/renderengine/gl/GLESRenderEngine.cpp b/libs/renderengine/gl/GLESRenderEngine.cpp index 2375cb7bf1..22dd86698b 100644 --- a/libs/renderengine/gl/GLESRenderEngine.cpp +++ b/libs/renderengine/gl/GLESRenderEngine.cpp @@ -1080,7 +1080,7 @@ EGLImageKHR GLESRenderEngine::createFramebufferImageIfNeeded(ANativeWindowBuffer void GLESRenderEngine::drawLayersInternal( const std::shared_ptr>&& resultPromise, - const DisplaySettings& display, const std::vector& layers, + const DisplaySettings& display, const std::vector& layers, const std::shared_ptr& buffer, const bool useFramebufferCache, base::unique_fd&& bufferFence) { ATRACE_CALL(); @@ -1110,10 +1110,10 @@ void GLESRenderEngine::drawLayersInternal( std::unique_ptr fbo; // Gathering layers that requested blur, we'll need them to decide when to render to an // offscreen buffer, and when to render to the native buffer. - std::deque blurLayers; + std::deque blurLayers; if (CC_LIKELY(mBlurFilter != nullptr)) { - for (auto layer : layers) { - if (layer->backgroundBlurRadius > 0) { + for (const auto& layer : layers) { + if (layer.backgroundBlurRadius > 0) { blurLayers.push_back(layer); } } @@ -1137,7 +1137,7 @@ void GLESRenderEngine::drawLayersInternal( } else { setViewportAndProjection(display.physicalDisplay, display.clip); auto status = - mBlurFilter->setAsDrawTarget(display, blurLayers.front()->backgroundBlurRadius); + mBlurFilter->setAsDrawTarget(display, blurLayers.front().backgroundBlurRadius); if (status != NO_ERROR) { ALOGE("Failed to prepare blur filter! Aborting GPU composition for buffer (%p).", buffer->getBuffer()->handle); @@ -1167,7 +1167,7 @@ void GLESRenderEngine::drawLayersInternal( .setTexCoords(2 /* size */) .setCropCoords(2 /* size */) .build(); - for (auto const layer : layers) { + for (const auto& layer : layers) { if (blurLayers.size() > 0 && blurLayers.front() == layer) { blurLayers.pop_front(); @@ -1193,7 +1193,7 @@ void GLESRenderEngine::drawLayersInternal( // There's still something else to blur, so let's keep rendering to our FBO // instead of to the display. status = mBlurFilter->setAsDrawTarget(display, - blurLayers.front()->backgroundBlurRadius); + blurLayers.front().backgroundBlurRadius); } if (status != NO_ERROR) { ALOGE("Failed to bind framebuffer! Aborting GPU composition for buffer (%p).", @@ -1214,42 +1214,42 @@ void GLESRenderEngine::drawLayersInternal( } // Ensure luminance is at least 100 nits to avoid div-by-zero - const float maxLuminance = std::max(100.f, layer->source.buffer.maxLuminanceNits); + const float maxLuminance = std::max(100.f, layer.source.buffer.maxLuminanceNits); mState.maxMasteringLuminance = maxLuminance; mState.maxContentLuminance = maxLuminance; - mState.projectionMatrix = projectionMatrix * layer->geometry.positionTransform; + mState.projectionMatrix = projectionMatrix * layer.geometry.positionTransform; - const FloatRect bounds = layer->geometry.boundaries; + const FloatRect bounds = layer.geometry.boundaries; Mesh::VertexArray position(mesh.getPositionArray()); position[0] = vec2(bounds.left, bounds.top); position[1] = vec2(bounds.left, bounds.bottom); position[2] = vec2(bounds.right, bounds.bottom); position[3] = vec2(bounds.right, bounds.top); - setupLayerCropping(*layer, mesh); - setColorTransform(layer->colorTransform); + setupLayerCropping(layer, mesh); + setColorTransform(layer.colorTransform); bool usePremultipliedAlpha = true; bool disableTexture = true; bool isOpaque = false; - if (layer->source.buffer.buffer != nullptr) { + if (layer.source.buffer.buffer != nullptr) { disableTexture = false; - isOpaque = layer->source.buffer.isOpaque; + isOpaque = layer.source.buffer.isOpaque; - sp gBuf = layer->source.buffer.buffer->getBuffer(); + sp gBuf = layer.source.buffer.buffer->getBuffer(); validateInputBufferUsage(gBuf); - bindExternalTextureBuffer(layer->source.buffer.textureName, gBuf, - layer->source.buffer.fence); + bindExternalTextureBuffer(layer.source.buffer.textureName, gBuf, + layer.source.buffer.fence); - usePremultipliedAlpha = layer->source.buffer.usePremultipliedAlpha; - Texture texture(Texture::TEXTURE_EXTERNAL, layer->source.buffer.textureName); - mat4 texMatrix = layer->source.buffer.textureTransform; + usePremultipliedAlpha = layer.source.buffer.usePremultipliedAlpha; + Texture texture(Texture::TEXTURE_EXTERNAL, layer.source.buffer.textureName); + mat4 texMatrix = layer.source.buffer.textureTransform; texture.setMatrix(texMatrix.asArray()); - texture.setFiltering(layer->source.buffer.useTextureFiltering); + texture.setFiltering(layer.source.buffer.useTextureFiltering); texture.setDimensions(gBuf->getWidth(), gBuf->getHeight()); - setSourceY410BT2020(layer->source.buffer.isY410BT2020); + setSourceY410BT2020(layer.source.buffer.isY410BT2020); renderengine::Mesh::VertexArray texCoords(mesh.getTexCoordArray()); texCoords[0] = vec2(0.0, 0.0); @@ -1264,32 +1264,32 @@ void GLESRenderEngine::drawLayersInternal( } } - const half3 solidColor = layer->source.solidColor; - const half4 color = half4(solidColor.r, solidColor.g, solidColor.b, layer->alpha); + const half3 solidColor = layer.source.solidColor; + const half4 color = half4(solidColor.r, solidColor.g, solidColor.b, layer.alpha); // Buffer sources will have a black solid color ignored in the shader, // so in that scenario the solid color passed here is arbitrary. setupLayerBlending(usePremultipliedAlpha, isOpaque, disableTexture, color, - layer->geometry.roundedCornersRadius); - if (layer->disableBlending) { + layer.geometry.roundedCornersRadius); + if (layer.disableBlending) { glDisable(GL_BLEND); } - setSourceDataSpace(layer->sourceDataspace); + setSourceDataSpace(layer.sourceDataspace); - if (layer->shadow.length > 0.0f) { - handleShadow(layer->geometry.boundaries, layer->geometry.roundedCornersRadius, - layer->shadow); + if (layer.shadow.length > 0.0f) { + handleShadow(layer.geometry.boundaries, layer.geometry.roundedCornersRadius, + layer.shadow); } // We only want to do a special handling for rounded corners when having rounded corners // is the only reason it needs to turn on blending, otherwise, we handle it like the // usual way since it needs to turn on blending anyway. - else if (layer->geometry.roundedCornersRadius > 0.0 && color.a >= 1.0f && isOpaque) { - handleRoundedCorners(display, *layer, mesh); + else if (layer.geometry.roundedCornersRadius > 0.0 && color.a >= 1.0f && isOpaque) { + handleRoundedCorners(display, layer, mesh); } else { drawMesh(mesh); } // Cleanup if there's a buffer source - if (layer->source.buffer.buffer != nullptr) { + if (layer.source.buffer.buffer != nullptr) { disableBlending(); setSourceY410BT2020(false); disableTexturing(); diff --git a/libs/renderengine/gl/GLESRenderEngine.h b/libs/renderengine/gl/GLESRenderEngine.h index c4adfdf752..1d7c2cafb5 100644 --- a/libs/renderengine/gl/GLESRenderEngine.h +++ b/libs/renderengine/gl/GLESRenderEngine.h @@ -104,7 +104,7 @@ protected: bool canSkipPostRenderCleanup() const override; void drawLayersInternal(const std::shared_ptr>&& resultPromise, const DisplaySettings& display, - const std::vector& layers, + const std::vector& layers, const std::shared_ptr& buffer, const bool useFramebufferCache, base::unique_fd&& bufferFence) override; diff --git a/libs/renderengine/include/renderengine/RenderEngine.h b/libs/renderengine/include/renderengine/RenderEngine.h index 701c1f2071..b9cc6485e5 100644 --- a/libs/renderengine/include/renderengine/RenderEngine.h +++ b/libs/renderengine/include/renderengine/RenderEngine.h @@ -160,7 +160,7 @@ public: // @return A future object of RenderEngineResult struct indicating whether // drawing was successful in async mode. virtual std::future drawLayers( - const DisplaySettings& display, const std::vector& layers, + const DisplaySettings& display, const std::vector& layers, const std::shared_ptr& buffer, const bool useFramebufferCache, base::unique_fd&& bufferFence); @@ -231,7 +231,7 @@ protected: virtual void drawLayersInternal( const std::shared_ptr>&& resultPromise, - const DisplaySettings& display, const std::vector& layers, + const DisplaySettings& display, const std::vector& layers, const std::shared_ptr& buffer, const bool useFramebufferCache, base::unique_fd&& bufferFence) = 0; }; diff --git a/libs/renderengine/include/renderengine/mock/RenderEngine.h b/libs/renderengine/include/renderengine/mock/RenderEngine.h index a7e6809223..248bd652c0 100644 --- a/libs/renderengine/include/renderengine/mock/RenderEngine.h +++ b/libs/renderengine/include/renderengine/mock/RenderEngine.h @@ -49,12 +49,12 @@ public: MOCK_CONST_METHOD0(canSkipPostRenderCleanup, bool()); MOCK_METHOD5(drawLayers, std::future(const DisplaySettings&, - const std::vector&, + const std::vector&, const std::shared_ptr&, const bool, base::unique_fd&&)); MOCK_METHOD6(drawLayersInternal, void(const std::shared_ptr>&&, - const DisplaySettings&, const std::vector&, + const DisplaySettings&, const std::vector&, const std::shared_ptr&, const bool, base::unique_fd&&)); MOCK_METHOD0(cleanFramebufferCache, void()); MOCK_METHOD0(getContextPriority, int()); diff --git a/libs/renderengine/skia/Cache.cpp b/libs/renderengine/skia/Cache.cpp index c4fa1bb091..b18a872836 100644 --- a/libs/renderengine/skia/Cache.cpp +++ b/libs/renderengine/skia/Cache.cpp @@ -95,7 +95,7 @@ static void drawShadowLayers(SkiaRenderEngine* renderengine, const DisplaySettin .alpha = 1, }; - auto layers = std::vector{&layer, &caster}; + auto layers = std::vector{layer, caster}; // Four combinations of settings are used (two transforms here, and drawShadowLayers is // called with two different destination data spaces) They're all rounded rect. // Three of these are cache misses that generate new shaders. @@ -140,7 +140,7 @@ static void drawImageLayers(SkiaRenderEngine* renderengine, const DisplaySetting }}, }; - auto layers = std::vector{&layer}; + auto layers = std::vector{layer}; for (auto dataspace : {kDestDataSpace, kOtherDataSpace}) { layer.sourceDataspace = dataspace; // Cache shaders for both rects and round rects. @@ -176,7 +176,7 @@ static void drawSolidLayers(SkiaRenderEngine* renderengine, const DisplaySetting .alpha = 0.5, }; - auto layers = std::vector{&layer}; + auto layers = std::vector{layer}; for (auto transform : {mat4(), kScaleAndTranslate}) { layer.geometry.positionTransform = transform; for (float roundedCornersRadius : {0.0f, 50.f}) { @@ -201,7 +201,7 @@ static void drawBlurLayers(SkiaRenderEngine* renderengine, const DisplaySettings .skipContentDraw = true, }; - auto layers = std::vector{&layer}; + auto layers = std::vector{layer}; // Different blur code is invoked for radii less and greater than 30 pixels for (int radius : {9, 60}) { layer.backgroundBlurRadius = radius; @@ -242,7 +242,7 @@ static void drawClippedLayers(SkiaRenderEngine* renderengine, const DisplaySetti }, }; - auto layers = std::vector{&layer}; + auto layers = std::vector{layer}; for (auto pixelSource : {bufferSource, bufferOpaque, colorSource}) { layer.source = pixelSource; for (auto dataspace : {kDestDataSpace, kOtherDataSpace}) { @@ -289,7 +289,7 @@ static void drawPIPImageLayer(SkiaRenderEngine* renderengine, const DisplaySetti }; - auto layers = std::vector{&layer}; + auto layers = std::vector{layer}; renderengine->drawLayers(display, layers, dstTexture, kUseFrameBufferCache, base::unique_fd()); } @@ -317,7 +317,7 @@ static void drawHolePunchLayer(SkiaRenderEngine* renderengine, const DisplaySett }; - auto layers = std::vector{&layer}; + auto layers = std::vector{layer}; renderengine->drawLayers(display, layers, dstTexture, kUseFrameBufferCache, base::unique_fd()); } @@ -429,7 +429,7 @@ void Cache::primeShaderCache(SkiaRenderEngine* renderengine) { LayerSettings layer{ .source = PixelSource{.solidColor = half3(0.f, 0.f, 0.f)}, }; - auto layers = std::vector{&layer}; + auto layers = std::vector{layer}; // call get() to make it synchronous renderengine ->drawLayers(display, layers, dstTexture, kUseFrameBufferCache, base::unique_fd()) diff --git a/libs/renderengine/skia/SkiaGLRenderEngine.cpp b/libs/renderengine/skia/SkiaGLRenderEngine.cpp index cb686a643a..d5ec774e9c 100644 --- a/libs/renderengine/skia/SkiaGLRenderEngine.cpp +++ b/libs/renderengine/skia/SkiaGLRenderEngine.cpp @@ -610,17 +610,18 @@ private: AutoBackendTexture::CleanupManager& mMgr; }; -sk_sp SkiaGLRenderEngine::createRuntimeEffectShader( - sk_sp shader, - const LayerSettings* layer, const DisplaySettings& display, bool undoPremultipliedAlpha, - bool requiresLinearEffect) { - const auto stretchEffect = layer->stretchEffect; +sk_sp SkiaGLRenderEngine::createRuntimeEffectShader(sk_sp shader, + const LayerSettings& layer, + const DisplaySettings& display, + bool undoPremultipliedAlpha, + bool requiresLinearEffect) { + const auto stretchEffect = layer.stretchEffect; // The given surface will be stretched by HWUI via matrix transformation // which gets similar results for most surfaces // Determine later on if we need to leverage the stertch shader within // surface flinger if (stretchEffect.hasEffect()) { - const auto targetBuffer = layer->source.buffer.buffer; + const auto targetBuffer = layer.source.buffer.buffer; const auto graphicBuffer = targetBuffer ? targetBuffer->getBuffer() : nullptr; if (graphicBuffer && shader) { shader = mStretchShaderFactory.createSkShader(shader, stretchEffect); @@ -629,7 +630,7 @@ sk_sp SkiaGLRenderEngine::createRuntimeEffectShader( if (requiresLinearEffect) { const ui::Dataspace inputDataspace = - mUseColorManagement ? layer->sourceDataspace : ui::Dataspace::V0_SRGB_LINEAR; + mUseColorManagement ? layer.sourceDataspace : ui::Dataspace::V0_SRGB_LINEAR; const ui::Dataspace outputDataspace = mUseColorManagement ? display.outputDataspace : ui::Dataspace::V0_SRGB_LINEAR; @@ -645,13 +646,13 @@ sk_sp SkiaGLRenderEngine::createRuntimeEffectShader( } else { runtimeEffect = effectIter->second; } - float maxLuminance = layer->source.buffer.maxLuminanceNits; + float maxLuminance = layer.source.buffer.maxLuminanceNits; // If the buffer doesn't have a max luminance, treat it as SDR & use the display's SDR // white point if (maxLuminance <= 0.f) { maxLuminance = display.sdrWhitePointNits; } - return createLinearEffectShader(shader, effect, runtimeEffect, layer->colorTransform, + return createLinearEffectShader(shader, effect, runtimeEffect, layer.colorTransform, display.maxLuminance, maxLuminance); } return shader; @@ -729,7 +730,7 @@ static SkRRect getBlurRRect(const BlurRegion& region) { void SkiaGLRenderEngine::drawLayersInternal( const std::shared_ptr>&& resultPromise, - const DisplaySettings& display, const std::vector& layers, + const DisplaySettings& display, const std::vector& layers, const std::shared_ptr& buffer, const bool /*useFramebufferCache*/, base::unique_fd&& bufferFence) { ATRACE_NAME("SkiaGL::drawLayers"); @@ -801,11 +802,11 @@ void SkiaGLRenderEngine::drawLayersInternal( if (!layerHasBlur(layer, ctModifiesAlpha)) { continue; } - if (layer->backgroundBlurRadius > 0 && - layer->backgroundBlurRadius < BlurFilter::kMaxCrossFadeRadius) { + if (layer.backgroundBlurRadius > 0 && + layer.backgroundBlurRadius < BlurFilter::kMaxCrossFadeRadius) { requiresCompositionLayer = true; } - for (auto region : layer->blurRegions) { + for (auto region : layer.blurRegions) { if (region.blurRadius < BlurFilter::kMaxCrossFadeRadius) { requiresCompositionLayer = true; } @@ -813,7 +814,7 @@ void SkiaGLRenderEngine::drawLayersInternal( if (requiresCompositionLayer) { activeSurface = dstSurface->makeSurface(dstSurface->imageInfo()); canvas = mCapture->tryOffscreenCapture(activeSurface.get(), &offscreenCaptureState); - blurCompositionLayer = layer; + blurCompositionLayer = &layer; break; } } @@ -825,11 +826,11 @@ void SkiaGLRenderEngine::drawLayersInternal( initCanvas(canvas, display); for (const auto& layer : layers) { - ATRACE_FORMAT("DrawLayer: %s", layer->name.c_str()); + ATRACE_FORMAT("DrawLayer: %s", layer.name.c_str()); if (kPrintLayerSettings) { std::stringstream ls; - PrintTo(*layer, &ls); + PrintTo(layer, &ls); auto debugs = ls.str(); int pos = 0; while (pos < debugs.size()) { @@ -839,7 +840,7 @@ void SkiaGLRenderEngine::drawLayersInternal( } sk_sp blurInput; - if (blurCompositionLayer == layer) { + if (blurCompositionLayer == &layer) { LOG_ALWAYS_FATAL_IF(activeSurface == dstSurface); LOG_ALWAYS_FATAL_IF(canvas == dstCanvas); @@ -878,17 +879,17 @@ void SkiaGLRenderEngine::drawLayersInternal( if (CC_UNLIKELY(mCapture->isCaptureRunning())) { // Record the name of the layer if the capture is running. std::stringstream layerSettings; - PrintTo(*layer, &layerSettings); + PrintTo(layer, &layerSettings); // Store the LayerSettings in additional information. - canvas->drawAnnotation(SkRect::MakeEmpty(), layer->name.c_str(), + canvas->drawAnnotation(SkRect::MakeEmpty(), layer.name.c_str(), SkData::MakeWithCString(layerSettings.str().c_str())); } // Layers have a local transform that should be applied to them - canvas->concat(getSkM44(layer->geometry.positionTransform).asM33()); + canvas->concat(getSkM44(layer.geometry.positionTransform).asM33()); const auto [bounds, roundRectClip] = - getBoundsAndClip(layer->geometry.boundaries, layer->geometry.roundedCornersCrop, - layer->geometry.roundedCornersRadius); + getBoundsAndClip(layer.geometry.boundaries, layer.geometry.roundedCornersCrop, + layer.geometry.roundedCornersRadius); if (mBlurFilter && layerHasBlur(layer, ctModifiesAlpha)) { std::unordered_map> cachedBlurs; @@ -909,20 +910,19 @@ void SkiaGLRenderEngine::drawLayersInternal( // TODO(b/182216890): Filter out empty layers earlier if (blurRect.width() > 0 && blurRect.height() > 0) { - if (layer->backgroundBlurRadius > 0) { + if (layer.backgroundBlurRadius > 0) { ATRACE_NAME("BackgroundBlur"); - auto blurredImage = - mBlurFilter->generate(grContext, layer->backgroundBlurRadius, blurInput, - blurRect); + auto blurredImage = mBlurFilter->generate(grContext, layer.backgroundBlurRadius, + blurInput, blurRect); - cachedBlurs[layer->backgroundBlurRadius] = blurredImage; + cachedBlurs[layer.backgroundBlurRadius] = blurredImage; - mBlurFilter->drawBlurRegion(canvas, bounds, layer->backgroundBlurRadius, 1.0f, + mBlurFilter->drawBlurRegion(canvas, bounds, layer.backgroundBlurRadius, 1.0f, blurRect, blurredImage, blurInput); } - canvas->concat(getSkM44(layer->blurRegionTransform).asM33()); - for (auto region : layer->blurRegions) { + canvas->concat(getSkM44(layer.blurRegionTransform).asM33()); + for (auto region : layer.blurRegions) { if (cachedBlurs[region.blurRadius] == nullptr) { ATRACE_NAME("BlurRegion"); cachedBlurs[region.blurRadius] = @@ -937,19 +937,18 @@ void SkiaGLRenderEngine::drawLayersInternal( } } - if (layer->shadow.length > 0) { + if (layer.shadow.length > 0) { // This would require a new parameter/flag to SkShadowUtils::DrawShadow - LOG_ALWAYS_FATAL_IF(layer->disableBlending, "Cannot disableBlending with a shadow"); + LOG_ALWAYS_FATAL_IF(layer.disableBlending, "Cannot disableBlending with a shadow"); SkRRect shadowBounds, shadowClip; - if (layer->geometry.boundaries == layer->shadow.boundaries) { + if (layer.geometry.boundaries == layer.shadow.boundaries) { shadowBounds = bounds; shadowClip = roundRectClip; } else { std::tie(shadowBounds, shadowClip) = - getBoundsAndClip(layer->shadow.boundaries, - layer->geometry.roundedCornersCrop, - layer->geometry.roundedCornersRadius); + getBoundsAndClip(layer.shadow.boundaries, layer.geometry.roundedCornersCrop, + layer.geometry.roundedCornersRadius); } // Technically, if bounds is a rect and roundRectClip is not empty, @@ -960,18 +959,18 @@ void SkiaGLRenderEngine::drawLayersInternal( // looks more like the intent. const auto& rrect = shadowBounds.isRect() && !shadowClip.isEmpty() ? shadowClip : shadowBounds; - drawShadow(canvas, rrect, layer->shadow); + drawShadow(canvas, rrect, layer.shadow); } - const bool requiresLinearEffect = layer->colorTransform != mat4() || + const bool requiresLinearEffect = layer.colorTransform != mat4() || (mUseColorManagement && - needsToneMapping(layer->sourceDataspace, display.outputDataspace)) || + needsToneMapping(layer.sourceDataspace, display.outputDataspace)) || (display.sdrWhitePointNits > 0.f && display.sdrWhitePointNits != display.maxLuminance); // quick abort from drawing the remaining portion of the layer - if (layer->skipContentDraw || - (layer->alpha == 0 && !requiresLinearEffect && !layer->disableBlending && + if (layer.skipContentDraw || + (layer.alpha == 0 && !requiresLinearEffect && !layer.disableBlending && (!displayColorTransform || displayColorTransform->isAlphaUnchanged()))) { continue; } @@ -981,13 +980,13 @@ void SkiaGLRenderEngine::drawLayersInternal( // management is a no-op. const ui::Dataspace layerDataspace = (!mUseColorManagement || requiresLinearEffect) ? dstDataspace - : layer->sourceDataspace; + : layer.sourceDataspace; SkPaint paint; - if (layer->source.buffer.buffer) { + if (layer.source.buffer.buffer) { ATRACE_NAME("DrawImage"); - validateInputBufferUsage(layer->source.buffer.buffer->getBuffer()); - const auto& item = layer->source.buffer; + validateInputBufferUsage(layer.source.buffer.buffer->getBuffer()); + const auto& item = layer.source.buffer; std::shared_ptr imageTextureRef = nullptr; if (const auto& iter = cache.find(item.buffer->getBuffer()->getId()); @@ -1006,8 +1005,8 @@ void SkiaGLRenderEngine::drawLayersInternal( // if the layer's buffer has a fence, then we must must respect the fence prior to using // the buffer. - if (layer->source.buffer.fence != nullptr) { - waitFence(layer->source.buffer.fence->get()); + if (layer.source.buffer.fence != nullptr) { + waitFence(layer.source.buffer.fence->get()); } // isOpaque means we need to ignore the alpha in the image, @@ -1051,7 +1050,7 @@ void SkiaGLRenderEngine::drawLayersInternal( sk_sp shader; - if (layer->source.buffer.useTextureFiltering) { + if (layer.source.buffer.useTextureFiltering) { shader = image->makeShader(SkTileMode::kClamp, SkTileMode::kClamp, SkSamplingOptions( {SkFilterMode::kLinear, SkMipmapMode::kNone}), @@ -1069,21 +1068,21 @@ void SkiaGLRenderEngine::drawLayersInternal( paint.setShader(createRuntimeEffectShader(shader, layer, display, !item.isOpaque && item.usePremultipliedAlpha, requiresLinearEffect)); - paint.setAlphaf(layer->alpha); + paint.setAlphaf(layer.alpha); } else { ATRACE_NAME("DrawColor"); - const auto color = layer->source.solidColor; + const auto color = layer.source.solidColor; sk_sp shader = SkShaders::Color(SkColor4f{.fR = color.r, .fG = color.g, .fB = color.b, - .fA = layer->alpha}, + .fA = layer.alpha}, toSkColorSpace(layerDataspace)); paint.setShader(createRuntimeEffectShader(shader, layer, display, /* undoPremultipliedAlpha */ false, requiresLinearEffect)); } - if (layer->disableBlending) { + if (layer.disableBlending) { paint.setBlendMode(SkBlendMode::kSrc); } @@ -1251,13 +1250,13 @@ inline std::pair SkiaGLRenderEngine::getBoundsAndClip(const Fl return {SkRRect::MakeRect(bounds), clip}; } -inline bool SkiaGLRenderEngine::layerHasBlur(const LayerSettings* layer, +inline bool SkiaGLRenderEngine::layerHasBlur(const LayerSettings& layer, bool colorTransformModifiesAlpha) { - if (layer->backgroundBlurRadius > 0 || layer->blurRegions.size()) { + if (layer.backgroundBlurRadius > 0 || layer.blurRegions.size()) { // return false if the content is opaque and would therefore occlude the blur - const bool opaqueContent = !layer->source.buffer.buffer || layer->source.buffer.isOpaque; - const bool opaqueAlpha = layer->alpha == 1.0f && !colorTransformModifiesAlpha; - return layer->skipContentDraw || !(opaqueContent && opaqueAlpha); + const bool opaqueContent = !layer.source.buffer.buffer || layer.source.buffer.isOpaque; + const bool opaqueAlpha = layer.alpha == 1.0f && !colorTransformModifiesAlpha; + return layer.skipContentDraw || !(opaqueContent && opaqueAlpha); } return false; } diff --git a/libs/renderengine/skia/SkiaGLRenderEngine.h b/libs/renderengine/skia/SkiaGLRenderEngine.h index e010c35c13..74ce6513e9 100644 --- a/libs/renderengine/skia/SkiaGLRenderEngine.h +++ b/libs/renderengine/skia/SkiaGLRenderEngine.h @@ -74,7 +74,7 @@ protected: bool canSkipPostRenderCleanup() const override; void drawLayersInternal(const std::shared_ptr>&& resultPromise, const DisplaySettings& display, - const std::vector& layers, + const std::vector& layers, const std::shared_ptr& buffer, const bool useFramebufferCache, base::unique_fd&& bufferFence) override; @@ -92,7 +92,7 @@ private: inline SkRect getSkRect(const Rect& layer); inline std::pair getBoundsAndClip(const FloatRect& bounds, const FloatRect& crop, float cornerRadius); - inline bool layerHasBlur(const LayerSettings* layer, bool colorTransformModifiesAlpha); + inline bool layerHasBlur(const LayerSettings& layer, bool colorTransformModifiesAlpha); inline SkColor getSkColor(const vec4& color); inline SkM44 getSkM44(const mat4& matrix); inline SkPoint3 getSkPoint3(const vec3& vector); @@ -108,8 +108,7 @@ private: const ShadowSettings& shadowSettings); // If requiresLinearEffect is true or the layer has a stretchEffect a new shader is returned. // Otherwise it returns the input shader. - sk_sp createRuntimeEffectShader(sk_sp shader, - const LayerSettings* layer, + sk_sp createRuntimeEffectShader(sk_sp shader, const LayerSettings& layer, const DisplaySettings& display, bool undoPremultipliedAlpha, bool requiresLinearEffect); diff --git a/libs/renderengine/skia/SkiaRenderEngine.h b/libs/renderengine/skia/SkiaRenderEngine.h index f61653b940..eb65e83324 100644 --- a/libs/renderengine/skia/SkiaRenderEngine.h +++ b/libs/renderengine/skia/SkiaRenderEngine.h @@ -55,7 +55,7 @@ protected: virtual void drawLayersInternal( const std::shared_ptr>&& resultPromise, - const DisplaySettings& display, const std::vector& layers, + const DisplaySettings& display, const std::vector& layers, const std::shared_ptr& buffer, const bool useFramebufferCache, base::unique_fd&& bufferFence) override { resultPromise->set_value({NO_ERROR, base::unique_fd()}); diff --git a/libs/renderengine/tests/RenderEngineTest.cpp b/libs/renderengine/tests/RenderEngineTest.cpp index 694bda65d4..c2c05f41b7 100644 --- a/libs/renderengine/tests/RenderEngineTest.cpp +++ b/libs/renderengine/tests/RenderEngineTest.cpp @@ -417,10 +417,11 @@ public: DEFAULT_DISPLAY_HEIGHT - DEFAULT_DISPLAY_OFFSET); } - void invokeDraw(renderengine::DisplaySettings settings, - std::vector layers) { + void invokeDraw(const renderengine::DisplaySettings& settings, + const std::vector& layers) { std::future result = mRE->drawLayers(settings, layers, mBuffer, true, base::unique_fd()); + ASSERT_TRUE(result.valid()); auto [status, fence] = result.get(); @@ -436,7 +437,7 @@ public: void drawEmptyLayers() { renderengine::DisplaySettings settings; - std::vector layers; + std::vector layers; invokeDraw(settings, layers); } @@ -629,7 +630,7 @@ void RenderEngineTest::fillBuffer(half r, half g, half b, half a) { settings.clip = fullscreenRect(); settings.outputDataspace = ui::Dataspace::V0_SRGB_LINEAR; - std::vector layers; + std::vector layers; renderengine::LayerSettings layer; layer.sourceDataspace = ui::Dataspace::V0_SRGB_LINEAR; @@ -637,7 +638,7 @@ void RenderEngineTest::fillBuffer(half r, half g, half b, half a) { SourceVariant::fillColor(layer, r, g, b, this); layer.alpha = a; - layers.push_back(&layer); + layers.push_back(layer); invokeDraw(settings, layers); } @@ -673,7 +674,7 @@ void RenderEngineTest::fillRedOffsetBuffer() { settings.physicalDisplay = offsetRect(); settings.clip = offsetRectAtZero(); - std::vector layers; + std::vector layers; renderengine::LayerSettings layer; layer.sourceDataspace = ui::Dataspace::V0_SRGB_LINEAR; @@ -681,7 +682,7 @@ void RenderEngineTest::fillRedOffsetBuffer() { SourceVariant::fillColor(layer, 1.0f, 0.0f, 0.0f, this); layer.alpha = 1.0f; - layers.push_back(&layer); + layers.push_back(layer); invokeDraw(settings, layers); } @@ -708,7 +709,7 @@ void RenderEngineTest::fillBufferCheckers(uint32_t orientationFlag) { settings.clip = Rect(2, 2); settings.orientation = orientationFlag; - std::vector layers; + std::vector layers; renderengine::LayerSettings layerOne; layerOne.sourceDataspace = ui::Dataspace::V0_SRGB_LINEAR; @@ -731,9 +732,9 @@ void RenderEngineTest::fillBufferCheckers(uint32_t orientationFlag) { SourceVariant::fillColor(layerThree, 0.0f, 0.0f, 1.0f, this); layerThree.alpha = 1.0f; - layers.push_back(&layerOne); - layers.push_back(&layerTwo); - layers.push_back(&layerThree); + layers.push_back(layerOne); + layers.push_back(layerTwo); + layers.push_back(layerThree); invokeDraw(settings, layers); } @@ -810,7 +811,7 @@ void RenderEngineTest::fillBufferWithLayerTransform() { settings.clip = Rect(2, 2); settings.outputDataspace = ui::Dataspace::V0_SRGB_LINEAR; - std::vector layers; + std::vector layers; renderengine::LayerSettings layer; layer.sourceDataspace = ui::Dataspace::V0_SRGB_LINEAR; @@ -821,7 +822,7 @@ void RenderEngineTest::fillBufferWithLayerTransform() { layer.source.solidColor = half3(1.0f, 0.0f, 0.0f); layer.alpha = 1.0f; - layers.push_back(&layer); + layers.push_back(layer); invokeDraw(settings, layers); } @@ -843,7 +844,7 @@ void RenderEngineTest::fillBufferWithColorTransform() { settings.clip = Rect(1, 1); settings.outputDataspace = ui::Dataspace::V0_SRGB_LINEAR; - std::vector layers; + std::vector layers; renderengine::LayerSettings layer; layer.sourceDataspace = ui::Dataspace::V0_SRGB_LINEAR; @@ -860,7 +861,7 @@ void RenderEngineTest::fillBufferWithColorTransform() { layer.alpha = 1.0f; layer.geometry.boundaries = Rect(1, 1).toFloatRect(); - layers.push_back(&layer); + layers.push_back(layer); invokeDraw(settings, layers); } @@ -877,7 +878,7 @@ void RenderEngineTest::fillBufferWithColorTransformZeroLayerAlpha() { settings.physicalDisplay = fullscreenRect(); settings.clip = Rect(1, 1); - std::vector layers; + std::vector layers; renderengine::LayerSettings layer; layer.geometry.boundaries = Rect(1, 1).toFloatRect(); @@ -890,7 +891,7 @@ void RenderEngineTest::fillBufferWithColorTransformZeroLayerAlpha() { layer.geometry.boundaries = Rect(1, 1).toFloatRect(); - layers.push_back(&layer); + layers.push_back(layer); invokeDraw(settings, layers); } @@ -908,7 +909,7 @@ void RenderEngineTest::fillRedBufferWithRoundedCorners() { settings.clip = fullscreenRect(); settings.outputDataspace = ui::Dataspace::V0_SRGB_LINEAR; - std::vector layers; + std::vector layers; renderengine::LayerSettings layer; layer.sourceDataspace = ui::Dataspace::V0_SRGB_LINEAR; @@ -918,7 +919,7 @@ void RenderEngineTest::fillRedBufferWithRoundedCorners() { SourceVariant::fillColor(layer, 1.0f, 0.0f, 0.0f, this); layer.alpha = 1.0f; - layers.push_back(&layer); + layers.push_back(layer); invokeDraw(settings, layers); } @@ -949,14 +950,14 @@ void RenderEngineTest::fillBufferAndBlurBackground() { settings.physicalDisplay = fullscreenRect(); settings.clip = fullscreenRect(); - std::vector layers; + std::vector layers; renderengine::LayerSettings backgroundLayer; backgroundLayer.sourceDataspace = ui::Dataspace::V0_SRGB_LINEAR; backgroundLayer.geometry.boundaries = fullscreenRect().toFloatRect(); SourceVariant::fillColor(backgroundLayer, 0.0f, 1.0f, 0.0f, this); backgroundLayer.alpha = 1.0f; - layers.push_back(&backgroundLayer); + layers.emplace_back(backgroundLayer); renderengine::LayerSettings leftLayer; leftLayer.sourceDataspace = ui::Dataspace::V0_SRGB_LINEAR; @@ -964,7 +965,7 @@ void RenderEngineTest::fillBufferAndBlurBackground() { Rect(DEFAULT_DISPLAY_WIDTH / 2, DEFAULT_DISPLAY_HEIGHT).toFloatRect(); SourceVariant::fillColor(leftLayer, 1.0f, 0.0f, 0.0f, this); leftLayer.alpha = 1.0f; - layers.push_back(&leftLayer); + layers.emplace_back(leftLayer); renderengine::LayerSettings blurLayer; blurLayer.sourceDataspace = ui::Dataspace::V0_SRGB_LINEAR; @@ -972,7 +973,7 @@ void RenderEngineTest::fillBufferAndBlurBackground() { blurLayer.backgroundBlurRadius = blurRadius; SourceVariant::fillColor(blurLayer, 0.0f, 0.0f, 1.0f, this); blurLayer.alpha = 0; - layers.push_back(&blurLayer); + layers.emplace_back(blurLayer); invokeDraw(settings, layers); @@ -994,14 +995,14 @@ void RenderEngineTest::fillSmallLayerAndBlurBackground() { settings.physicalDisplay = fullscreenRect(); settings.clip = fullscreenRect(); - std::vector layers; + std::vector layers; renderengine::LayerSettings backgroundLayer; backgroundLayer.sourceDataspace = ui::Dataspace::V0_SRGB_LINEAR; backgroundLayer.geometry.boundaries = fullscreenRect().toFloatRect(); SourceVariant::fillColor(backgroundLayer, 1.0f, 0.0f, 0.0f, this); backgroundLayer.alpha = 1.0f; - layers.push_back(&backgroundLayer); + layers.push_back(backgroundLayer); renderengine::LayerSettings blurLayer; blurLayer.sourceDataspace = ui::Dataspace::V0_SRGB_LINEAR; @@ -1009,7 +1010,7 @@ void RenderEngineTest::fillSmallLayerAndBlurBackground() { blurLayer.backgroundBlurRadius = blurRadius; SourceVariant::fillColor(blurLayer, 0.0f, 0.0f, 1.0f, this); blurLayer.alpha = 0; - layers.push_back(&blurLayer); + layers.push_back(blurLayer); invokeDraw(settings, layers); @@ -1026,7 +1027,7 @@ void RenderEngineTest::overlayCorners() { settings.clip = fullscreenRect(); settings.outputDataspace = ui::Dataspace::V0_SRGB_LINEAR; - std::vector layersFirst; + std::vector layersFirst; renderengine::LayerSettings layerOne; layerOne.sourceDataspace = ui::Dataspace::V0_SRGB_LINEAR; @@ -1035,14 +1036,14 @@ void RenderEngineTest::overlayCorners() { SourceVariant::fillColor(layerOne, 1.0f, 0.0f, 0.0f, this); layerOne.alpha = 0.2; - layersFirst.push_back(&layerOne); + layersFirst.push_back(layerOne); invokeDraw(settings, layersFirst); expectBufferColor(Rect(DEFAULT_DISPLAY_WIDTH / 3, DEFAULT_DISPLAY_HEIGHT / 3), 51, 0, 0, 51); expectBufferColor(Rect(DEFAULT_DISPLAY_WIDTH / 3 + 1, DEFAULT_DISPLAY_HEIGHT / 3 + 1, DEFAULT_DISPLAY_WIDTH, DEFAULT_DISPLAY_HEIGHT), 0, 0, 0, 0); - std::vector layersSecond; + std::vector layersSecond; renderengine::LayerSettings layerTwo; layerTwo.sourceDataspace = ui::Dataspace::V0_SRGB_LINEAR; layerTwo.geometry.boundaries = @@ -1051,7 +1052,7 @@ void RenderEngineTest::overlayCorners() { SourceVariant::fillColor(layerTwo, 0.0f, 1.0f, 0.0f, this); layerTwo.alpha = 1.0f; - layersSecond.push_back(&layerTwo); + layersSecond.push_back(layerTwo); invokeDraw(settings, layersSecond); expectBufferColor(Rect(DEFAULT_DISPLAY_WIDTH / 3, DEFAULT_DISPLAY_HEIGHT / 3), 0, 0, 0, 0); @@ -1066,7 +1067,7 @@ void RenderEngineTest::fillRedBufferTextureTransform() { settings.clip = Rect(1, 1); settings.outputDataspace = ui::Dataspace::V0_SRGB_LINEAR; - std::vector layers; + std::vector layers; renderengine::LayerSettings layer; layer.sourceDataspace = ui::Dataspace::V0_SRGB_LINEAR; @@ -1102,7 +1103,7 @@ void RenderEngineTest::fillRedBufferTextureTransform() { layer.alpha = 1.0f; layer.geometry.boundaries = Rect(1, 1).toFloatRect(); - layers.push_back(&layer); + layers.push_back(layer); invokeDraw(settings, layers); } @@ -1118,7 +1119,7 @@ void RenderEngineTest::fillRedBufferWithPremultiplyAlpha() { // Here logical space is 1x1 settings.clip = Rect(1, 1); - std::vector layers; + std::vector layers; renderengine::LayerSettings layer; const auto buf = allocateSourceBuffer(1, 1); @@ -1141,7 +1142,7 @@ void RenderEngineTest::fillRedBufferWithPremultiplyAlpha() { layer.alpha = 0.5f; layer.geometry.boundaries = Rect(1, 1).toFloatRect(); - layers.push_back(&layer); + layers.push_back(layer); invokeDraw(settings, layers); } @@ -1157,7 +1158,7 @@ void RenderEngineTest::fillRedBufferWithoutPremultiplyAlpha() { // Here logical space is 1x1 settings.clip = Rect(1, 1); - std::vector layers; + std::vector layers; renderengine::LayerSettings layer; const auto buf = allocateSourceBuffer(1, 1); @@ -1180,7 +1181,7 @@ void RenderEngineTest::fillRedBufferWithoutPremultiplyAlpha() { layer.alpha = 0.5f; layer.geometry.boundaries = Rect(1, 1).toFloatRect(); - layers.push_back(&layer); + layers.push_back(layer); invokeDraw(settings, layers); } @@ -1199,7 +1200,7 @@ void RenderEngineTest::drawShadow(const renderengine::LayerSettings& castingLaye settings.physicalDisplay = fullscreenRect(); settings.clip = fullscreenRect(); - std::vector layers; + std::vector layers; // add background layer renderengine::LayerSettings bgLayer; @@ -1208,7 +1209,7 @@ void RenderEngineTest::drawShadow(const renderengine::LayerSettings& castingLaye ColorSourceVariant::fillColor(bgLayer, backgroundColor.r / 255.0f, backgroundColor.g / 255.0f, backgroundColor.b / 255.0f, this); bgLayer.alpha = backgroundColor.a / 255.0f; - layers.push_back(&bgLayer); + layers.push_back(bgLayer); // add shadow layer renderengine::LayerSettings shadowLayer; @@ -1216,14 +1217,14 @@ void RenderEngineTest::drawShadow(const renderengine::LayerSettings& castingLaye shadowLayer.geometry.boundaries = castingLayer.geometry.boundaries; shadowLayer.alpha = castingLayer.alpha; shadowLayer.shadow = shadow; - layers.push_back(&shadowLayer); + layers.push_back(shadowLayer); // add layer casting the shadow renderengine::LayerSettings layer = castingLayer; layer.sourceDataspace = ui::Dataspace::V0_SRGB_LINEAR; SourceVariant::fillColor(layer, casterColor.r / 255.0f, casterColor.g / 255.0f, casterColor.b / 255.0f, this); - layers.push_back(&layer); + layers.push_back(layer); invokeDraw(settings, layers); } @@ -1236,7 +1237,7 @@ void RenderEngineTest::drawShadowWithoutCaster(const FloatRect& castingBounds, settings.physicalDisplay = fullscreenRect(); settings.clip = fullscreenRect(); - std::vector layers; + std::vector layers; // add background layer renderengine::LayerSettings bgLayer; @@ -1245,7 +1246,7 @@ void RenderEngineTest::drawShadowWithoutCaster(const FloatRect& castingBounds, ColorSourceVariant::fillColor(bgLayer, backgroundColor.r / 255.0f, backgroundColor.g / 255.0f, backgroundColor.b / 255.0f, this); bgLayer.alpha = backgroundColor.a / 255.0f; - layers.push_back(&bgLayer); + layers.push_back(bgLayer); // add shadow layer renderengine::LayerSettings shadowLayer; @@ -1255,7 +1256,7 @@ void RenderEngineTest::drawShadowWithoutCaster(const FloatRect& castingBounds, shadowLayer.alpha = 1.0f; ColorSourceVariant::fillColor(shadowLayer, 0, 0, 0, this); shadowLayer.shadow = shadow; - layers.push_back(&shadowLayer); + layers.push_back(shadowLayer); invokeDraw(settings, layers); } @@ -1291,8 +1292,8 @@ TEST_P(RenderEngineTest, drawLayers_withoutBuffers_withColorTransform) { // Transform the red color. bgLayer.colorTransform = mat4(-1, 0, 0, 0, 0, 1, 0, 0, 0, 0, 1, 0, 0, 0, 0, 1); - std::vector layers; - layers.push_back(&bgLayer); + std::vector layers; + layers.push_back(bgLayer); invokeDraw(settings, layers); @@ -1306,11 +1307,11 @@ TEST_P(RenderEngineTest, drawLayers_nullOutputBuffer) { renderengine::DisplaySettings settings; settings.outputDataspace = ui::Dataspace::V0_SRGB_LINEAR; - std::vector layers; + std::vector layers; renderengine::LayerSettings layer; layer.geometry.boundaries = fullscreenRect().toFloatRect(); BufferSourceVariant::fillColor(layer, 1.0f, 0.0f, 0.0f, this); - layers.push_back(&layer); + layers.push_back(layer); std::future result = mRE->drawLayers(settings, layers, nullptr, true, base::unique_fd()); @@ -1335,12 +1336,12 @@ TEST_P(RenderEngineTest, drawLayers_doesNotCacheFramebuffer) { settings.physicalDisplay = fullscreenRect(); settings.clip = fullscreenRect(); - std::vector layers; + std::vector layers; renderengine::LayerSettings layer; layer.geometry.boundaries = fullscreenRect().toFloatRect(); BufferSourceVariant::fillColor(layer, 1.0f, 0.0f, 0.0f, this); layer.alpha = 1.0; - layers.push_back(&layer); + layers.push_back(layer); std::future result = mRE->drawLayers(settings, layers, mBuffer, false, base::unique_fd()); @@ -1743,12 +1744,12 @@ TEST_P(RenderEngineTest, cleanupPostRender_cleansUpOnce) { settings.clip = fullscreenRect(); settings.outputDataspace = ui::Dataspace::V0_SRGB_LINEAR; - std::vector layers; + std::vector layers; renderengine::LayerSettings layer; layer.geometry.boundaries = fullscreenRect().toFloatRect(); BufferSourceVariant::fillColor(layer, 1.0f, 0.0f, 0.0f, this); layer.alpha = 1.0; - layers.push_back(&layer); + layers.push_back(layer); std::future resultOne = mRE->drawLayers(settings, layers, mBuffer, true, base::unique_fd()); @@ -1779,7 +1780,7 @@ TEST_P(RenderEngineTest, testRoundedCornersCrop) { settings.clip = fullscreenRect(); settings.outputDataspace = ui::Dataspace::V0_SRGB_LINEAR; - std::vector layers; + std::vector layers; renderengine::LayerSettings redLayer; redLayer.sourceDataspace = ui::Dataspace::V0_SRGB_LINEAR; @@ -1790,7 +1791,7 @@ TEST_P(RenderEngineTest, testRoundedCornersCrop) { redLayer.source.solidColor = half3(1.0f, 0.0f, 0.0f); redLayer.alpha = 1.0f; - layers.push_back(&redLayer); + layers.push_back(redLayer); // Green layer with 1/3 size. renderengine::LayerSettings greenLayer; @@ -1805,7 +1806,7 @@ TEST_P(RenderEngineTest, testRoundedCornersCrop) { greenLayer.source.solidColor = half3(0.0f, 1.0f, 0.0f); greenLayer.alpha = 1.0f; - layers.push_back(&greenLayer); + layers.push_back(greenLayer); invokeDraw(settings, layers); @@ -1828,7 +1829,7 @@ TEST_P(RenderEngineTest, testRoundedCornersParentCrop) { settings.clip = fullscreenRect(); settings.outputDataspace = ui::Dataspace::V0_SRGB_LINEAR; - std::vector layers; + std::vector layers; renderengine::LayerSettings redLayer; redLayer.sourceDataspace = ui::Dataspace::V0_SRGB_LINEAR; @@ -1839,7 +1840,7 @@ TEST_P(RenderEngineTest, testRoundedCornersParentCrop) { redLayer.source.solidColor = half3(1.0f, 0.0f, 0.0f); redLayer.alpha = 1.0f; - layers.push_back(&redLayer); + layers.push_back(redLayer); // Green layer with 1/2 size with parent crop rect. renderengine::LayerSettings greenLayer = redLayer; @@ -1847,7 +1848,7 @@ TEST_P(RenderEngineTest, testRoundedCornersParentCrop) { FloatRect(0, 0, DEFAULT_DISPLAY_WIDTH, DEFAULT_DISPLAY_HEIGHT / 2); greenLayer.source.solidColor = half3(0.0f, 1.0f, 0.0f); - layers.push_back(&greenLayer); + layers.push_back(greenLayer); invokeDraw(settings, layers); @@ -1873,7 +1874,7 @@ TEST_P(RenderEngineTest, testRoundedCornersParentCropSmallBounds) { settings.clip = fullscreenRect(); settings.outputDataspace = ui::Dataspace::V0_SRGB_LINEAR; - std::vector layers; + std::vector layers; renderengine::LayerSettings redLayer; redLayer.sourceDataspace = ui::Dataspace::V0_SRGB_LINEAR; @@ -1884,7 +1885,7 @@ TEST_P(RenderEngineTest, testRoundedCornersParentCropSmallBounds) { redLayer.source.solidColor = half3(1.0f, 0.0f, 0.0f); redLayer.alpha = 1.0f; - layers.push_back(&redLayer); + layers.push_back(redLayer); invokeDraw(settings, layers); // Due to roundedCornersRadius, the top corners are untouched. @@ -1923,7 +1924,7 @@ TEST_P(RenderEngineTest, testClear) { .disableBlending = true, }; - std::vector layers{&redLayer, &clearLayer}; + std::vector layers{redLayer, clearLayer}; invokeDraw(display, layers); expectBufferColor(rect, 0, 0, 0, 0); } @@ -1971,7 +1972,7 @@ TEST_P(RenderEngineTest, testDisableBlendingBuffer) { .disableBlending = true, }; - std::vector layers{&redLayer, &greenLayer}; + std::vector layers{redLayer, greenLayer}; invokeDraw(display, layers); expectBufferColor(rect, 0, 128, 0, 128); } @@ -2017,7 +2018,7 @@ TEST_P(RenderEngineTest, test_isOpaque) { .alpha = 1.0f, }; - std::vector layers{&greenLayer}; + std::vector layers{greenLayer}; invokeDraw(display, layers); if (GetParam()->useColorManagement()) { diff --git a/libs/renderengine/tests/RenderEngineThreadedTest.cpp b/libs/renderengine/tests/RenderEngineThreadedTest.cpp index 99250c1412..db7e12b71b 100644 --- a/libs/renderengine/tests/RenderEngineThreadedTest.cpp +++ b/libs/renderengine/tests/RenderEngineThreadedTest.cpp @@ -172,20 +172,21 @@ TEST_F(RenderEngineThreadedTest, supportsBackgroundBlur_returnsTrue) { TEST_F(RenderEngineThreadedTest, drawLayers) { renderengine::DisplaySettings settings; - std::vector layers; + std::vector layers; std::shared_ptr buffer = std::make_shared< renderengine::ExternalTexture>(new GraphicBuffer(), *mRenderEngine, renderengine::ExternalTexture::Usage::READABLE | renderengine::ExternalTexture::Usage::WRITEABLE); + base::unique_fd bufferFence; EXPECT_CALL(*mRenderEngine, drawLayersInternal) .WillOnce([&](const std::shared_ptr>&& resultPromise, const renderengine::DisplaySettings&, - const std::vector&, + const std::vector&, const std::shared_ptr&, const bool, - base::unique_fd &&) -> void { + base::unique_fd&&) -> void { resultPromise->set_value({NO_ERROR, base::unique_fd()}); }); diff --git a/libs/renderengine/threaded/RenderEngineThreaded.cpp b/libs/renderengine/threaded/RenderEngineThreaded.cpp index a549672259..3d446e8e72 100644 --- a/libs/renderengine/threaded/RenderEngineThreaded.cpp +++ b/libs/renderengine/threaded/RenderEngineThreaded.cpp @@ -306,7 +306,7 @@ bool RenderEngineThreaded::canSkipPostRenderCleanup() const { void RenderEngineThreaded::drawLayersInternal( const std::shared_ptr>&& resultPromise, - const DisplaySettings& display, const std::vector& layers, + const DisplaySettings& display, const std::vector& layers, const std::shared_ptr& buffer, const bool useFramebufferCache, base::unique_fd&& bufferFence) { resultPromise->set_value({NO_ERROR, base::unique_fd()}); @@ -314,19 +314,20 @@ void RenderEngineThreaded::drawLayersInternal( } std::future RenderEngineThreaded::drawLayers( - const DisplaySettings& display, const std::vector& layers, + const DisplaySettings& display, const std::vector& layers, const std::shared_ptr& buffer, const bool useFramebufferCache, base::unique_fd&& bufferFence) { ATRACE_CALL(); const auto resultPromise = std::make_shared>(); std::future resultFuture = resultPromise->get_future(); + int fd = bufferFence.release(); { std::lock_guard lock(mThreadMutex); - mFunctionCalls.push([resultPromise, &display, &layers, &buffer, useFramebufferCache, - &bufferFence](renderengine::RenderEngine& instance) { + mFunctionCalls.push([resultPromise, display, layers, buffer, useFramebufferCache, + fd](renderengine::RenderEngine& instance) { ATRACE_NAME("REThreaded::drawLayers"); instance.drawLayersInternal(std::move(resultPromise), display, layers, buffer, - useFramebufferCache, std::move(bufferFence)); + useFramebufferCache, base::unique_fd(fd)); }); } mCondition.notify_one(); diff --git a/libs/renderengine/threaded/RenderEngineThreaded.h b/libs/renderengine/threaded/RenderEngineThreaded.h index 2303caa7eb..0159cfaece 100644 --- a/libs/renderengine/threaded/RenderEngineThreaded.h +++ b/libs/renderengine/threaded/RenderEngineThreaded.h @@ -57,7 +57,7 @@ public: void cleanupPostRender() override; std::future drawLayers(const DisplaySettings& display, - const std::vector& layers, + const std::vector& layers, const std::shared_ptr& buffer, const bool useFramebufferCache, base::unique_fd&& bufferFence) override; @@ -73,7 +73,7 @@ protected: bool canSkipPostRenderCleanup() const override; void drawLayersInternal(const std::shared_ptr>&& resultPromise, const DisplaySettings& display, - const std::vector& layers, + const std::vector& layers, const std::shared_ptr& buffer, const bool useFramebufferCache, base::unique_fd&& bufferFence) override; diff --git a/services/surfaceflinger/BufferQueueLayer.cpp b/services/surfaceflinger/BufferQueueLayer.cpp index 52bd420d91..4e5d2d03b0 100644 --- a/services/surfaceflinger/BufferQueueLayer.cpp +++ b/services/surfaceflinger/BufferQueueLayer.cpp @@ -48,7 +48,9 @@ BufferQueueLayer::~BufferQueueLayer() { // Interface implementation for Layer // ----------------------------------------------------------------------- -void BufferQueueLayer::onLayerDisplayed(const sp& releaseFence) { +void BufferQueueLayer::onLayerDisplayed( + std::shared_future futureRenderEngineResult) { + sp releaseFence = new Fence(dup(futureRenderEngineResult.get().drawFence)); mConsumer->setReleaseFence(releaseFence); // Prevent tracing the same release multiple times. diff --git a/services/surfaceflinger/BufferQueueLayer.h b/services/surfaceflinger/BufferQueueLayer.h index a3bd725cfe..dfdb5c055d 100644 --- a/services/surfaceflinger/BufferQueueLayer.h +++ b/services/surfaceflinger/BufferQueueLayer.h @@ -42,7 +42,8 @@ public: // Implements Layer. const char* getType() const override { return "BufferQueueLayer"; } - void onLayerDisplayed(const sp& releaseFence) override; + void onLayerDisplayed( + std::shared_future futureRenderEngineResult) override; // If a buffer was replaced this frame, release the former buffer void releasePendingBuffer(nsecs_t dequeueReadyTime) override; diff --git a/services/surfaceflinger/BufferStateLayer.cpp b/services/surfaceflinger/BufferStateLayer.cpp index fda7a928a1..c213570c7f 100644 --- a/services/surfaceflinger/BufferStateLayer.cpp +++ b/services/surfaceflinger/BufferStateLayer.cpp @@ -70,69 +70,11 @@ BufferStateLayer::~BufferStateLayer() { } } -status_t BufferStateLayer::addReleaseFence(const sp& ch, - const sp& fence) { - if (ch == nullptr) { - return OK; - } - ch->previousReleaseCallbackId = mPreviousReleaseCallbackId; - if (!ch->previousReleaseFence.get()) { - ch->previousReleaseFence = fence; - return OK; - } - - // Below logic is lifted from ConsumerBase.cpp: - // Check status of fences first because merging is expensive. - // Merging an invalid fence with any other fence results in an - // invalid fence. - auto currentStatus = ch->previousReleaseFence->getStatus(); - if (currentStatus == Fence::Status::Invalid) { - ALOGE("Existing fence has invalid state, layer: %s", mName.c_str()); - return BAD_VALUE; - } - - auto incomingStatus = fence->getStatus(); - if (incomingStatus == Fence::Status::Invalid) { - ALOGE("New fence has invalid state, layer: %s", mName.c_str()); - ch->previousReleaseFence = fence; - return BAD_VALUE; - } - - // If both fences are signaled or both are unsignaled, we need to merge - // them to get an accurate timestamp. - if (currentStatus == incomingStatus) { - char fenceName[32] = {}; - snprintf(fenceName, 32, "%.28s", mName.c_str()); - sp mergedFence = Fence::merge( - fenceName, ch->previousReleaseFence, fence); - if (!mergedFence.get()) { - ALOGE("failed to merge release fences, layer: %s", mName.c_str()); - // synchronization is broken, the best we can do is hope fences - // signal in order so the new fence will act like a union - ch->previousReleaseFence = fence; - return BAD_VALUE; - } - ch->previousReleaseFence = mergedFence; - } else if (incomingStatus == Fence::Status::Unsignaled) { - // If one fence has signaled and the other hasn't, the unsignaled - // fence will approximately correspond with the correct timestamp. - // There's a small race if both fences signal at about the same time - // and their statuses are retrieved with unfortunate timing. However, - // by this point, they will have both signaled and only the timestamp - // will be slightly off; any dependencies after this point will - // already have been met. - ch->previousReleaseFence = fence; - } - // else if (currentStatus == Fence::Status::Unsignaled) is a no-op. - - return OK; -} - // ----------------------------------------------------------------------- // Interface implementation for Layer // ----------------------------------------------------------------------- -void BufferStateLayer::onLayerDisplayed(const sp& releaseFence) { - +void BufferStateLayer::onLayerDisplayed( + std::shared_future futureRenderEngineResult) { // If a layer has been displayed again we may need to clear // the mLastClientComposition fence that we use for early release in setBuffer // (as we now have a new fence which won't pass through the client composition path in some cases @@ -146,9 +88,6 @@ void BufferStateLayer::onLayerDisplayed(const sp& releaseFence) { mLastClientCompositionDisplayed = true; } - if (!releaseFence->isValid()) { - return; - } // The previous release fence notifies the client that SurfaceFlinger is done with the previous // buffer that was presented on this layer. The first transaction that came in this frame that // replaced the previous buffer on this layer needs this release fence, because the fence will @@ -173,17 +112,17 @@ void BufferStateLayer::onLayerDisplayed(const sp& releaseFence) { break; } } - auto status = addReleaseFence(ch, releaseFence); - if (status != OK) { - ALOGE("Failed to add release fence for layer %s", getName().c_str()); - } - - mPreviousReleaseFence = releaseFence; // Prevent tracing the same release multiple times. if (mPreviousFrameNumber != mPreviousReleasedFrameNumber) { mPreviousReleasedFrameNumber = mPreviousFrameNumber; } + + if (ch != nullptr) { + ch->previousReleaseCallbackId = mPreviousReleaseCallbackId; + ch->previousReleaseFences.emplace_back(futureRenderEngineResult); + ch->name = mName; + } } void BufferStateLayer::onSurfaceFrameCreated( @@ -231,9 +170,18 @@ void BufferStateLayer::releasePendingBuffer(nsecs_t dequeueReadyTime) { mFlinger->getTransactionCallbackInvoker().addCallbackHandles( mDrawingState.callbackHandles, jankData); + sp releaseFence = Fence::NO_FENCE; + for (auto& handle : mDrawingState.callbackHandles) { + if (handle->releasePreviousBuffer && + mDrawingState.releaseBufferEndpoint == handle->listener) { + releaseFence = + handle->previousReleaseFence ? handle->previousReleaseFence : Fence::NO_FENCE; + break; + } + } + mDrawingState.callbackHandles = {}; - const sp& releaseFence(mPreviousReleaseFence); std::shared_ptr releaseFenceTime = std::make_shared(releaseFence); { Mutex::Autolock lock(mFrameEventHistoryMutex); diff --git a/services/surfaceflinger/BufferStateLayer.h b/services/surfaceflinger/BufferStateLayer.h index 87b68ea71b..eea700cf7b 100644 --- a/services/surfaceflinger/BufferStateLayer.h +++ b/services/surfaceflinger/BufferStateLayer.h @@ -39,7 +39,9 @@ public: // Implements Layer. const char* getType() const override { return "BufferStateLayer"; } - void onLayerDisplayed(const sp& releaseFence) override; + void onLayerDisplayed( + std::shared_future futureRenderEngineResult) override; + void releasePendingBuffer(nsecs_t dequeueReadyTime) override; void finalizeFrameEventHistory(const std::shared_ptr& glDoneFence, @@ -115,8 +117,6 @@ private: bool updateFrameEventHistory(const sp& acquireFence, nsecs_t postedTime, nsecs_t requestedPresentTime); - status_t addReleaseFence(const sp& ch, const sp& releaseFence); - bool latchSidebandStream(bool& recomputeVisibleRegions) override; bool hasFrameUpdate() const override; @@ -139,7 +139,6 @@ private: std::shared_ptr getBufferFromBufferData( const BufferData& bufferData); - sp mPreviousReleaseFence; ReleaseCallbackId mPreviousReleaseCallbackId = ReleaseCallbackId::INVALID_ID; uint64_t mPreviousReleasedFrameNumber = 0; diff --git a/services/surfaceflinger/CompositionEngine/include/compositionengine/LayerFE.h b/services/surfaceflinger/CompositionEngine/include/compositionengine/LayerFE.h index f7b71cf9fe..ac243c0a17 100644 --- a/services/surfaceflinger/CompositionEngine/include/compositionengine/LayerFE.h +++ b/services/surfaceflinger/CompositionEngine/include/compositionengine/LayerFE.h @@ -16,6 +16,7 @@ #pragma once +#include #include #include #include @@ -26,6 +27,7 @@ #pragma clang diagnostic ignored "-Wextra" #include +#include // TODO(b/129481165): remove the #pragma below and fix conversion issues #pragma clang diagnostic pop // ignored "-Wconversion -Wextra" @@ -151,7 +153,7 @@ public: ClientCompositionTargetSettings&) = 0; // Called after the layer is displayed to update the presentation fence - virtual void onLayerDisplayed(const sp&) = 0; + virtual void onLayerDisplayed(std::shared_future) = 0; // Gets some kind of identifier for the layer for debug purposes. virtual const char* getDebugName() const = 0; diff --git a/services/surfaceflinger/CompositionEngine/include/compositionengine/mock/LayerFE.h b/services/surfaceflinger/CompositionEngine/include/compositionengine/mock/LayerFE.h index d215bda891..16aebef9f3 100644 --- a/services/surfaceflinger/CompositionEngine/include/compositionengine/mock/LayerFE.h +++ b/services/surfaceflinger/CompositionEngine/include/compositionengine/mock/LayerFE.h @@ -39,7 +39,7 @@ public: std::vector( compositionengine::LayerFE::ClientCompositionTargetSettings&)); - MOCK_METHOD1(onLayerDisplayed, void(const sp&)); + MOCK_METHOD1(onLayerDisplayed, void(std::shared_future)); MOCK_CONST_METHOD0(getDebugName, const char*()); MOCK_CONST_METHOD0(getSequence, int32_t()); diff --git a/services/surfaceflinger/CompositionEngine/src/Output.cpp b/services/surfaceflinger/CompositionEngine/src/Output.cpp index fad1fa74dd..6800004a90 100644 --- a/services/surfaceflinger/CompositionEngine/src/Output.cpp +++ b/services/surfaceflinger/CompositionEngine/src/Output.cpp @@ -27,6 +27,7 @@ #include #include #include +#include #include @@ -1097,12 +1098,12 @@ std::optional Output::composeSurfaces( setExpensiveRenderingExpected(true); } - std::vector clientCompositionLayerPointers; - clientCompositionLayerPointers.reserve(clientCompositionLayers.size()); + std::vector clientRenderEngineLayers; + clientRenderEngineLayers.reserve(clientCompositionLayers.size()); std::transform(clientCompositionLayers.begin(), clientCompositionLayers.end(), - std::back_inserter(clientCompositionLayerPointers), - [](LayerFE::LayerSettings& settings) -> renderengine::LayerSettings* { - return &settings; + std::back_inserter(clientRenderEngineLayers), + [](LayerFE::LayerSettings& settings) -> renderengine::LayerSettings { + return settings; }); const nsecs_t renderEngineStart = systemTime(); @@ -1115,7 +1116,7 @@ std::optional Output::composeSurfaces( const bool useFramebufferCache = outputState.layerFilter.toInternalDisplay; auto [status, drawFence] = renderEngine - .drawLayers(clientCompositionDisplay, clientCompositionLayerPointers, tex, + .drawLayers(clientCompositionDisplay, clientRenderEngineLayers, tex, useFramebufferCache, std::move(fd)) .get(); @@ -1295,8 +1296,10 @@ void Output::postFramebuffer() { releaseFence = Fence::merge("LayerRelease", releaseFence, frame.clientTargetAcquireFence); } - - layer->getLayerFE().onLayerDisplayed(releaseFence); + layer->getLayerFE().onLayerDisplayed( + ftl::yield( + {NO_ERROR, base::unique_fd(releaseFence->dup())}) + .share()); } // We've got a list of layers needing fences, that are disjoint with @@ -1304,7 +1307,9 @@ void Output::postFramebuffer() { // supply them with the present fence. for (auto& weakLayer : mReleasedLayers) { if (auto layer = weakLayer.promote(); layer != nullptr) { - layer->onLayerDisplayed(frame.presentFence); + layer->onLayerDisplayed(ftl::yield( + {NO_ERROR, base::unique_fd(frame.presentFence->dup())}) + .share()); } } diff --git a/services/surfaceflinger/CompositionEngine/src/planner/CachedSet.cpp b/services/surfaceflinger/CompositionEngine/src/planner/CachedSet.cpp index e6b716e8f2..ec52e59ab0 100644 --- a/services/surfaceflinger/CompositionEngine/src/planner/CachedSet.cpp +++ b/services/surfaceflinger/CompositionEngine/src/planner/CachedSet.cpp @@ -193,11 +193,6 @@ void CachedSet::render(renderengine::RenderEngine& renderEngine, TexturePool& te clientCompositionList.cend()); } - std::vector layerSettingsPointers; - std::transform(layerSettings.cbegin(), layerSettings.cend(), - std::back_inserter(layerSettingsPointers), - [](const renderengine::LayerSettings& settings) { return &settings; }); - renderengine::LayerSettings blurLayerSettings; if (mBlurLayer) { auto blurSettings = targetSettings; @@ -212,7 +207,7 @@ void CachedSet::render(renderengine::RenderEngine& renderEngine, TexturePool& te blurLayerSettings.name = std::string("blur layer"); // Clear out the shadow settings blurLayerSettings.shadow = {}; - layerSettingsPointers.push_back(&blurLayerSettings); + layerSettings.push_back(blurLayerSettings); } renderengine::LayerSettings holePunchSettings; @@ -230,7 +225,7 @@ void CachedSet::render(renderengine::RenderEngine& renderEngine, TexturePool& te holePunchSettings.disableBlending = true; holePunchSettings.alpha = 0.0f; holePunchSettings.name = std::string("hole punch layer"); - layerSettingsPointers.push_back(&holePunchSettings); + layerSettings.push_back(holePunchSettings); // Add a solid background as the first layer in case there is no opaque // buffer behind the punch hole @@ -239,7 +234,7 @@ void CachedSet::render(renderengine::RenderEngine& renderEngine, TexturePool& te holePunchBackgroundSettings.geometry.boundaries = holePunchSettings.geometry.boundaries; holePunchBackgroundSettings.geometry.positionTransform = holePunchSettings.geometry.positionTransform; - layerSettingsPointers.insert(layerSettingsPointers.begin(), &holePunchBackgroundSettings); + layerSettings.emplace(layerSettings.begin(), holePunchBackgroundSettings); } if (sDebugHighlighLayers) { @@ -257,7 +252,7 @@ void CachedSet::render(renderengine::RenderEngine& renderEngine, TexturePool& te .alpha = half(0.05f), }; - layerSettingsPointers.emplace_back(&highlight); + layerSettings.emplace_back(highlight); } auto texture = texturePool.borrowTexture(); @@ -273,8 +268,8 @@ void CachedSet::render(renderengine::RenderEngine& renderEngine, TexturePool& te } auto [status, drawFence] = renderEngine - .drawLayers(displaySettings, layerSettingsPointers, - texture->get(), false, std::move(bufferFence)) + .drawLayers(displaySettings, layerSettings, texture->get(), + false, std::move(bufferFence)) .get(); if (status == NO_ERROR) { diff --git a/services/surfaceflinger/CompositionEngine/tests/OutputTest.cpp b/services/surfaceflinger/CompositionEngine/tests/OutputTest.cpp index 8f0028c399..cf63ef5183 100644 --- a/services/surfaceflinger/CompositionEngine/tests/OutputTest.cpp +++ b/services/surfaceflinger/CompositionEngine/tests/OutputTest.cpp @@ -24,6 +24,7 @@ #include #include #include +#include #include #include #include @@ -2884,12 +2885,24 @@ TEST_F(OutputPostFramebufferTest, releaseFencesAreSentToLayerFE) { // are passed. This happens to work with the current implementation, but // would not survive certain calls like Fence::merge() which would return a // new instance. - EXPECT_CALL(*mLayer1.layerFE, - onLayerDisplayed(Property(&sp::get, Eq(layer1Fence.get())))); - EXPECT_CALL(*mLayer2.layerFE, - onLayerDisplayed(Property(&sp::get, Eq(layer2Fence.get())))); - EXPECT_CALL(*mLayer3.layerFE, - onLayerDisplayed(Property(&sp::get, Eq(layer3Fence.get())))); + base::unique_fd layer1FD(layer1Fence->dup()); + base::unique_fd layer2FD(layer2Fence->dup()); + base::unique_fd layer3FD(layer3Fence->dup()); + EXPECT_CALL(*mLayer1.layerFE, onLayerDisplayed(_)) + .WillOnce([&layer1FD](std::shared_future + futureRenderEngineResult) { + EXPECT_EQ(layer1FD, futureRenderEngineResult.get().drawFence); + }); + EXPECT_CALL(*mLayer2.layerFE, onLayerDisplayed(_)) + .WillOnce([&layer2FD](std::shared_future + futureRenderEngineResult) { + EXPECT_EQ(layer2FD, futureRenderEngineResult.get().drawFence); + }); + EXPECT_CALL(*mLayer3.layerFE, onLayerDisplayed(_)) + .WillOnce([&layer3FD](std::shared_future + futureRenderEngineResult) { + EXPECT_EQ(layer3FD, futureRenderEngineResult.get().drawFence); + }); mOutput.postFramebuffer(); } @@ -2915,9 +2928,9 @@ TEST_F(OutputPostFramebufferTest, releaseFencesIncludeClientTargetAcquireFence) // Fence::merge is called, and since none of the fences are actually valid, // Fence::NO_FENCE is returned and passed to each onLayerDisplayed() call. // This is the best we can do without creating a real kernel fence object. - EXPECT_CALL(*mLayer1.layerFE, onLayerDisplayed(Fence::NO_FENCE)); - EXPECT_CALL(*mLayer2.layerFE, onLayerDisplayed(Fence::NO_FENCE)); - EXPECT_CALL(*mLayer3.layerFE, onLayerDisplayed(Fence::NO_FENCE)); + EXPECT_CALL(*mLayer1.layerFE, onLayerDisplayed).WillOnce(Return()); + EXPECT_CALL(*mLayer2.layerFE, onLayerDisplayed).WillOnce(Return()); + EXPECT_CALL(*mLayer3.layerFE, onLayerDisplayed).WillOnce(Return()); mOutput.postFramebuffer(); } @@ -2949,12 +2962,22 @@ TEST_F(OutputPostFramebufferTest, releasedLayersSentPresentFence) { EXPECT_CALL(*mRenderSurface, onPresentDisplayCompleted()); // Each released layer should be given the presentFence. - EXPECT_CALL(*releasedLayer1, - onLayerDisplayed(Property(&sp::get, Eq(presentFence.get())))); - EXPECT_CALL(*releasedLayer2, - onLayerDisplayed(Property(&sp::get, Eq(presentFence.get())))); - EXPECT_CALL(*releasedLayer3, - onLayerDisplayed(Property(&sp::get, Eq(presentFence.get())))); + base::unique_fd layerFD(presentFence.get()->dup()); + EXPECT_CALL(*releasedLayer1, onLayerDisplayed(_)) + .WillOnce([&layerFD](std::shared_future + futureRenderEngineResult) { + EXPECT_EQ(layerFD, futureRenderEngineResult.get().drawFence); + }); + EXPECT_CALL(*releasedLayer2, onLayerDisplayed(_)) + .WillOnce([&layerFD](std::shared_future + futureRenderEngineResult) { + EXPECT_EQ(layerFD, futureRenderEngineResult.get().drawFence); + }); + EXPECT_CALL(*releasedLayer3, onLayerDisplayed(_)) + .WillOnce([&layerFD](std::shared_future + futureRenderEngineResult) { + EXPECT_EQ(layerFD, futureRenderEngineResult.get().drawFence); + }); mOutput.postFramebuffer(); @@ -3131,9 +3154,9 @@ TEST_F(OutputComposeSurfacesTest, handlesZeroCompositionRequests) { EXPECT_CALL(*mRenderSurface, dequeueBuffer(_)).WillRepeatedly(Return(mOutputBuffer)); EXPECT_CALL(mRenderEngine, drawLayers(_, IsEmpty(), _, false, _)) .WillRepeatedly([&](const renderengine::DisplaySettings&, - const std::vector&, + const std::vector&, const std::shared_ptr&, const bool, - base::unique_fd &&) + base::unique_fd&&) -> std::future { return futureOf({NO_ERROR, base::unique_fd()}); }); @@ -3161,11 +3184,11 @@ TEST_F(OutputComposeSurfacesTest, buildsAndRendersRequestList) { })); EXPECT_CALL(*mRenderSurface, dequeueBuffer(_)).WillRepeatedly(Return(mOutputBuffer)); - EXPECT_CALL(mRenderEngine, drawLayers(_, ElementsAre(Pointee(r1), Pointee(r2)), _, false, _)) + EXPECT_CALL(mRenderEngine, drawLayers(_, ElementsAre(r1, r2), _, false, _)) .WillRepeatedly([&](const renderengine::DisplaySettings&, - const std::vector&, + const std::vector&, const std::shared_ptr&, const bool, - base::unique_fd &&) + base::unique_fd&&) -> std::future { return futureOf({NO_ERROR, base::unique_fd()}); }); @@ -3196,11 +3219,11 @@ TEST_F(OutputComposeSurfacesTest, })); EXPECT_CALL(*mRenderSurface, dequeueBuffer(_)).WillRepeatedly(Return(mOutputBuffer)); - EXPECT_CALL(mRenderEngine, drawLayers(_, ElementsAre(Pointee(r1), Pointee(r2)), _, true, _)) + EXPECT_CALL(mRenderEngine, drawLayers(_, ElementsAre(r1, r2), _, true, _)) .WillRepeatedly([&](const renderengine::DisplaySettings&, - const std::vector&, + const std::vector&, const std::shared_ptr&, const bool, - base::unique_fd &&) + base::unique_fd&&) -> std::future { return futureOf({NO_ERROR, base::unique_fd()}); }); @@ -3226,7 +3249,7 @@ TEST_F(OutputComposeSurfacesTest, renderDuplicateClientCompositionRequestsWithou .WillRepeatedly(Return()); EXPECT_CALL(*mRenderSurface, dequeueBuffer(_)).WillRepeatedly(Return(mOutputBuffer)); - EXPECT_CALL(mRenderEngine, drawLayers(_, ElementsAre(Pointee(r1), Pointee(r2)), _, false, _)) + EXPECT_CALL(mRenderEngine, drawLayers(_, ElementsAre(r1, r2), _, false, _)) .Times(2) .WillOnce(Return(ByMove( futureOf({NO_ERROR, base::unique_fd()})))) @@ -3258,7 +3281,7 @@ TEST_F(OutputComposeSurfacesTest, skipDuplicateClientCompositionRequests) { .WillRepeatedly(Return()); EXPECT_CALL(*mRenderSurface, dequeueBuffer(_)).WillRepeatedly(Return(mOutputBuffer)); - EXPECT_CALL(mRenderEngine, drawLayers(_, ElementsAre(Pointee(r1), Pointee(r2)), _, false, _)) + EXPECT_CALL(mRenderEngine, drawLayers(_, ElementsAre(r1, r2), _, false, _)) .WillOnce(Return(ByMove( futureOf({NO_ERROR, base::unique_fd()})))); EXPECT_CALL(mOutput, setExpensiveRenderingExpected(false)); @@ -3294,11 +3317,11 @@ TEST_F(OutputComposeSurfacesTest, clientCompositionIfBufferChanges) { EXPECT_CALL(*mRenderSurface, dequeueBuffer(_)) .WillOnce(Return(mOutputBuffer)) .WillOnce(Return(otherOutputBuffer)); - EXPECT_CALL(mRenderEngine, drawLayers(_, ElementsAre(Pointee(r1), Pointee(r2)), _, false, _)) + EXPECT_CALL(mRenderEngine, drawLayers(_, ElementsAre(r1, r2), _, false, _)) .WillRepeatedly([&](const renderengine::DisplaySettings&, - const std::vector&, + const std::vector&, const std::shared_ptr&, const bool, - base::unique_fd &&) + base::unique_fd&&) -> std::future { return futureOf({NO_ERROR, base::unique_fd()}); }); @@ -3330,10 +3353,10 @@ TEST_F(OutputComposeSurfacesTest, clientCompositionIfRequestChanges) { .WillRepeatedly(Return()); EXPECT_CALL(*mRenderSurface, dequeueBuffer(_)).WillRepeatedly(Return(mOutputBuffer)); - EXPECT_CALL(mRenderEngine, drawLayers(_, ElementsAre(Pointee(r1), Pointee(r2)), _, false, _)) + EXPECT_CALL(mRenderEngine, drawLayers(_, ElementsAre(r1, r2), _, false, _)) .WillOnce(Return(ByMove( futureOf({NO_ERROR, base::unique_fd()})))); - EXPECT_CALL(mRenderEngine, drawLayers(_, ElementsAre(Pointee(r1), Pointee(r3)), _, false, _)) + EXPECT_CALL(mRenderEngine, drawLayers(_, ElementsAre(r1, r3), _, false, _)) .WillOnce(Return(ByMove( futureOf({NO_ERROR, base::unique_fd()})))); @@ -3487,9 +3510,9 @@ struct OutputComposeSurfacesTest_HandlesProtectedContent : public OutputComposeS EXPECT_CALL(mRenderEngine, drawLayers(_, _, _, false, _)) .WillRepeatedly( [&](const renderengine::DisplaySettings&, - const std::vector&, + const std::vector&, const std::shared_ptr&, const bool, - base::unique_fd &&) -> std::future { + base::unique_fd&&) -> std::future { return futureOf( {NO_ERROR, base::unique_fd()}); }); diff --git a/services/surfaceflinger/CompositionEngine/tests/planner/CachedSetTest.cpp b/services/surfaceflinger/CompositionEngine/tests/planner/CachedSetTest.cpp index ecb05f8e5f..42b3d972a8 100644 --- a/services/surfaceflinger/CompositionEngine/tests/planner/CachedSetTest.cpp +++ b/services/surfaceflinger/CompositionEngine/tests/planner/CachedSetTest.cpp @@ -346,15 +346,15 @@ TEST_F(CachedSetTest, renderUnsecureOutput) { const auto drawLayers = [&](const renderengine::DisplaySettings& displaySettings, - const std::vector& layers, + const std::vector& layers, const std::shared_ptr&, const bool, - base::unique_fd &&) -> std::future { + base::unique_fd&&) -> std::future { EXPECT_EQ(mOutputState.framebufferSpace.getContent(), displaySettings.physicalDisplay); EXPECT_EQ(mOutputState.layerStackSpace.getContent(), displaySettings.clip); EXPECT_EQ(ui::Transform::toRotationFlags(mOutputState.framebufferSpace.getOrientation()), displaySettings.orientation); - EXPECT_EQ(0.5f, layers[0]->alpha); - EXPECT_EQ(0.75f, layers[1]->alpha); + EXPECT_EQ(0.5f, layers[0].alpha); + EXPECT_EQ(0.75f, layers[1].alpha); EXPECT_EQ(ui::Dataspace::SRGB, displaySettings.outputDataspace); return futureOf({NO_ERROR, base::unique_fd()}); }; @@ -398,15 +398,15 @@ TEST_F(CachedSetTest, renderSecureOutput) { const auto drawLayers = [&](const renderengine::DisplaySettings& displaySettings, - const std::vector& layers, + const std::vector& layers, const std::shared_ptr&, const bool, - base::unique_fd &&) -> std::future { + base::unique_fd&&) -> std::future { EXPECT_EQ(mOutputState.framebufferSpace.getContent(), displaySettings.physicalDisplay); EXPECT_EQ(mOutputState.layerStackSpace.getContent(), displaySettings.clip); EXPECT_EQ(ui::Transform::toRotationFlags(mOutputState.framebufferSpace.getOrientation()), displaySettings.orientation); - EXPECT_EQ(0.5f, layers[0]->alpha); - EXPECT_EQ(0.75f, layers[1]->alpha); + EXPECT_EQ(0.5f, layers[0].alpha); + EXPECT_EQ(0.75f, layers[1].alpha); EXPECT_EQ(ui::Dataspace::SRGB, displaySettings.outputDataspace); return futureOf({NO_ERROR, base::unique_fd()}); @@ -453,15 +453,15 @@ TEST_F(CachedSetTest, rendersWithOffsetFramebufferContent) { const auto drawLayers = [&](const renderengine::DisplaySettings& displaySettings, - const std::vector& layers, + const std::vector& layers, const std::shared_ptr&, const bool, - base::unique_fd &&) -> std::future { + base::unique_fd&&) -> std::future { EXPECT_EQ(mOutputState.framebufferSpace.getContent(), displaySettings.physicalDisplay); EXPECT_EQ(mOutputState.layerStackSpace.getContent(), displaySettings.clip); EXPECT_EQ(ui::Transform::toRotationFlags(mOutputState.framebufferSpace.getOrientation()), displaySettings.orientation); - EXPECT_EQ(0.5f, layers[0]->alpha); - EXPECT_EQ(0.75f, layers[1]->alpha); + EXPECT_EQ(0.5f, layers[0].alpha); + EXPECT_EQ(0.75f, layers[1].alpha); EXPECT_EQ(ui::Dataspace::SRGB, displaySettings.outputDataspace); return futureOf({NO_ERROR, base::unique_fd()}); @@ -656,26 +656,26 @@ TEST_F(CachedSetTest, addHolePunch) { const auto drawLayers = [&](const renderengine::DisplaySettings&, - const std::vector& layers, + const std::vector& layers, const std::shared_ptr&, const bool, - base::unique_fd &&) -> std::future { + base::unique_fd&&) -> std::future { // If the highlight layer is enabled, it will increase the size by 1. // We're interested in the third layer either way. EXPECT_GE(layers.size(), 4u); { - const auto* holePunchSettings = layers[3]; - EXPECT_EQ(nullptr, holePunchSettings->source.buffer.buffer); - EXPECT_EQ(half3(0.0f, 0.0f, 0.0f), holePunchSettings->source.solidColor); - EXPECT_TRUE(holePunchSettings->disableBlending); - EXPECT_EQ(0.0f, holePunchSettings->alpha); + const auto holePunchSettings = layers[3]; + EXPECT_EQ(nullptr, holePunchSettings.source.buffer.buffer); + EXPECT_EQ(half3(0.0f, 0.0f, 0.0f), holePunchSettings.source.solidColor); + EXPECT_TRUE(holePunchSettings.disableBlending); + EXPECT_EQ(0.0f, holePunchSettings.alpha); } { - const auto* holePunchBackgroundSettings = layers[0]; - EXPECT_EQ(nullptr, holePunchBackgroundSettings->source.buffer.buffer); - EXPECT_EQ(half3(0.0f, 0.0f, 0.0f), holePunchBackgroundSettings->source.solidColor); - EXPECT_FALSE(holePunchBackgroundSettings->disableBlending); - EXPECT_EQ(1.0f, holePunchBackgroundSettings->alpha); + const auto holePunchBackgroundSettings = layers[0]; + EXPECT_EQ(nullptr, holePunchBackgroundSettings.source.buffer.buffer); + EXPECT_EQ(half3(0.0f, 0.0f, 0.0f), holePunchBackgroundSettings.source.solidColor); + EXPECT_FALSE(holePunchBackgroundSettings.disableBlending); + EXPECT_EQ(1.0f, holePunchBackgroundSettings.alpha); } return futureOf({NO_ERROR, base::unique_fd()}); @@ -717,27 +717,27 @@ TEST_F(CachedSetTest, addHolePunch_noBuffer) { const auto drawLayers = [&](const renderengine::DisplaySettings&, - const std::vector& layers, + const std::vector& layers, const std::shared_ptr&, const bool, - base::unique_fd &&) -> std::future { + base::unique_fd&&) -> std::future { // If the highlight layer is enabled, it will increase the size by 1. // We're interested in the third layer either way. EXPECT_GE(layers.size(), 4u); { - const auto* holePunchSettings = layers[3]; - EXPECT_EQ(nullptr, holePunchSettings->source.buffer.buffer); - EXPECT_EQ(half3(0.0f, 0.0f, 0.0f), holePunchSettings->source.solidColor); - EXPECT_TRUE(holePunchSettings->disableBlending); - EXPECT_EQ(0.0f, holePunchSettings->alpha); + const auto holePunchSettings = layers[3]; + EXPECT_EQ(nullptr, holePunchSettings.source.buffer.buffer); + EXPECT_EQ(half3(0.0f, 0.0f, 0.0f), holePunchSettings.source.solidColor); + EXPECT_TRUE(holePunchSettings.disableBlending); + EXPECT_EQ(0.0f, holePunchSettings.alpha); } { - const auto* holePunchBackgroundSettings = layers[0]; - EXPECT_EQ(nullptr, holePunchBackgroundSettings->source.buffer.buffer); - EXPECT_EQ(half3(0.0f, 0.0f, 0.0f), holePunchBackgroundSettings->source.solidColor); - EXPECT_FALSE(holePunchBackgroundSettings->disableBlending); - EXPECT_EQ(1.0f, holePunchBackgroundSettings->alpha); + const auto holePunchBackgroundSettings = layers[0]; + EXPECT_EQ(nullptr, holePunchBackgroundSettings.source.buffer.buffer); + EXPECT_EQ(half3(0.0f, 0.0f, 0.0f), holePunchBackgroundSettings.source.solidColor); + EXPECT_FALSE(holePunchBackgroundSettings.disableBlending); + EXPECT_EQ(1.0f, holePunchBackgroundSettings.alpha); } return futureOf({NO_ERROR, base::unique_fd()}); @@ -867,16 +867,16 @@ TEST_F(CachedSetTest, addBlur) { const auto drawLayers = [&](const renderengine::DisplaySettings&, - const std::vector& layers, + const std::vector& layers, const std::shared_ptr&, const bool, - base::unique_fd &&) -> std::future { + base::unique_fd&&) -> std::future { // If the highlight layer is enabled, it will increase the size by 1. // We're interested in the third layer either way. EXPECT_GE(layers.size(), 3u); - const auto* blurSettings = layers[2]; - EXPECT_TRUE(blurSettings->skipContentDraw); - EXPECT_EQ(half3(0.0f, 0.0f, 0.0f), blurSettings->source.solidColor); - EXPECT_EQ(0.0f, blurSettings->alpha); + const auto blurSettings = layers[2]; + EXPECT_TRUE(blurSettings.skipContentDraw); + EXPECT_EQ(half3(0.0f, 0.0f, 0.0f), blurSettings.source.solidColor); + EXPECT_EQ(0.0f, blurSettings.alpha); return futureOf({NO_ERROR, base::unique_fd()}); }; diff --git a/services/surfaceflinger/Layer.cpp b/services/surfaceflinger/Layer.cpp index 5707c67a56..d68cf9720f 100644 --- a/services/surfaceflinger/Layer.cpp +++ b/services/surfaceflinger/Layer.cpp @@ -221,7 +221,8 @@ LayerCreationArgs::LayerCreationArgs(SurfaceFlinger* flinger, sp client, * Layer. So, the implementation is done in BufferLayer. When called on a * EffectLayer object, it's essentially a NOP. */ -void Layer::onLayerDisplayed(const sp& /*releaseFence*/) {} +void Layer::onLayerDisplayed( + std::shared_future /*futureRenderEngineResult*/) {} void Layer::removeRelativeZ(const std::vector& layersInTree) { if (mDrawingState.zOrderRelativeOf == nullptr) { diff --git a/services/surfaceflinger/Layer.h b/services/surfaceflinger/Layer.h index 07b2eb5130..4569f9af23 100644 --- a/services/surfaceflinger/Layer.h +++ b/services/surfaceflinger/Layer.h @@ -616,7 +616,8 @@ public: void prepareCompositionState(compositionengine::LayerFE::StateSubset subset) override; std::vector prepareClientCompositionList( compositionengine::LayerFE::ClientCompositionTargetSettings&) override; - void onLayerDisplayed(const sp& releaseFence) override; + void onLayerDisplayed( + std::shared_future futureRenderEngineResult) override; void setWasClientComposed(const sp& fence) override { mLastClientCompositionFence = fence; diff --git a/services/surfaceflinger/RegionSamplingThread.cpp b/services/surfaceflinger/RegionSamplingThread.cpp index 9465b197b2..32585dd9ac 100644 --- a/services/surfaceflinger/RegionSamplingThread.cpp +++ b/services/surfaceflinger/RegionSamplingThread.cpp @@ -356,10 +356,13 @@ void RegionSamplingThread::captureSample() { renderengine::ExternalTexture::Usage::WRITEABLE); } - const sp captureListener = new SyncScreenCaptureListener(); - mFlinger.captureScreenCommon(std::move(renderAreaFuture), traverseLayers, buffer, - true /* regionSampling */, false /* grayscale */, captureListener); - ScreenCaptureResults captureResults = captureListener->waitForResults(); + auto captureScreenResultFuture = + mFlinger.captureScreenCommon(std::move(renderAreaFuture), traverseLayers, buffer, + true /* regionSampling */, false /* grayscale */, nullptr); + auto& captureScreenResult = captureScreenResultFuture.get(); + if (captureScreenResult.drawFence.ok()) { + sync_wait(captureScreenResult.drawFence.get(), -1); + } std::vector activeDescriptors; for (const auto& descriptor : descriptors) { diff --git a/services/surfaceflinger/SurfaceFlinger.cpp b/services/surfaceflinger/SurfaceFlinger.cpp index e9665bdec8..da5fefda94 100644 --- a/services/surfaceflinger/SurfaceFlinger.cpp +++ b/services/surfaceflinger/SurfaceFlinger.cpp @@ -5923,9 +5923,10 @@ status_t SurfaceFlinger::captureDisplay(const DisplayCaptureArgs& args, traverseLayersInLayerStack(layerStack, args.uid, visitor); }; - return captureScreenCommon(std::move(renderAreaFuture), traverseLayers, reqSize, - args.pixelFormat, args.allowProtected, args.grayscale, - captureListener); + auto captureResultFuture = captureScreenCommon(std::move(renderAreaFuture), traverseLayers, + reqSize, args.pixelFormat, args.allowProtected, + args.grayscale, captureListener); + return captureResultFuture.get().status; } status_t SurfaceFlinger::captureDisplay(DisplayId displayId, @@ -5960,9 +5961,15 @@ status_t SurfaceFlinger::captureDisplay(DisplayId displayId, traverseLayersInLayerStack(layerStack, CaptureArgs::UNSET_UID, visitor); }; - return captureScreenCommon(std::move(renderAreaFuture), traverseLayers, size, - ui::PixelFormat::RGBA_8888, false /* allowProtected */, - false /* grayscale */, captureListener); + if (captureListener == nullptr) { + ALOGE("capture screen must provide a capture listener callback"); + return BAD_VALUE; + } + auto captureResultFuture = + captureScreenCommon(std::move(renderAreaFuture), traverseLayers, size, + ui::PixelFormat::RGBA_8888, false /* allowProtected */, + false /* grayscale */, captureListener); + return captureResultFuture.get().status; } status_t SurfaceFlinger::captureLayers(const LayerCaptureArgs& args, @@ -6089,23 +6096,28 @@ status_t SurfaceFlinger::captureLayers(const LayerCaptureArgs& args, }); }; - return captureScreenCommon(std::move(renderAreaFuture), traverseLayers, reqSize, - args.pixelFormat, args.allowProtected, args.grayscale, - captureListener); + if (captureListener == nullptr) { + ALOGE("capture screen must provide a capture listener callback"); + return BAD_VALUE; + } + + auto captureResultFuture = captureScreenCommon(std::move(renderAreaFuture), traverseLayers, + reqSize, args.pixelFormat, args.allowProtected, + args.grayscale, captureListener); + return captureResultFuture.get().status; } -status_t SurfaceFlinger::captureScreenCommon(RenderAreaFuture renderAreaFuture, - TraverseLayersFunction traverseLayers, - ui::Size bufferSize, ui::PixelFormat reqPixelFormat, - bool allowProtected, bool grayscale, - const sp& captureListener) { +std::shared_future SurfaceFlinger::captureScreenCommon( + RenderAreaFuture renderAreaFuture, TraverseLayersFunction traverseLayers, + ui::Size bufferSize, ui::PixelFormat reqPixelFormat, bool allowProtected, bool grayscale, + const sp& captureListener) { ATRACE_CALL(); if (exceedsMaxRenderTargetSize(bufferSize.getWidth(), bufferSize.getHeight())) { ALOGE("Attempted to capture screen with size (%" PRId32 ", %" PRId32 ") that exceeds render target size limit.", bufferSize.getWidth(), bufferSize.getHeight()); - return BAD_VALUE; + return ftl::yield({BAD_VALUE, base::unique_fd()}).share(); } // Loop over all visible layers to see whether there's any protected layer. A protected layer is @@ -6145,44 +6157,65 @@ status_t SurfaceFlinger::captureScreenCommon(RenderAreaFuture renderAreaFuture, false /* regionSampling */, grayscale, captureListener); } -status_t SurfaceFlinger::captureScreenCommon( +std::shared_future SurfaceFlinger::captureScreenCommon( RenderAreaFuture renderAreaFuture, TraverseLayersFunction traverseLayers, const std::shared_ptr& buffer, bool regionSampling, bool grayscale, const sp& captureListener) { ATRACE_CALL(); - if (captureListener == nullptr) { - ALOGE("capture screen must provide a capture listener callback"); - return BAD_VALUE; - } - bool canCaptureBlackoutContent = hasCaptureBlackoutContentPermission(); - static_cast(schedule([=, renderAreaFuture = std::move(renderAreaFuture)]() mutable { + auto scheduleResultFuture = schedule([=, + renderAreaFuture = std::move(renderAreaFuture)]() mutable + -> std::shared_future { ScreenCaptureResults captureResults; std::unique_ptr renderArea = renderAreaFuture.get(); if (!renderArea) { ALOGW("Skipping screen capture because of invalid render area."); captureResults.result = NO_MEMORY; captureListener->onScreenCaptureCompleted(captureResults); - return; + return ftl::yield({NO_ERROR, base::unique_fd()}) + .share(); } - status_t result = NO_ERROR; + std::shared_future renderEngineResultFuture; + renderArea->render([&] { - result = renderScreenImplLocked(*renderArea, traverseLayers, buffer, - canCaptureBlackoutContent, regionSampling, grayscale, - captureResults); + renderEngineResultFuture = + renderScreenImplLocked(*renderArea, traverseLayers, buffer, + canCaptureBlackoutContent, regionSampling, grayscale, + captureResults); }); + // spring up a thread to unblock SF main thread and wait for + // RenderEngineResult to be available + if (captureListener != nullptr) { + std::async([=]() mutable { + ATRACE_NAME("captureListener is nonnull!"); + auto& [status, drawFence] = renderEngineResultFuture.get(); + captureResults.result = status; + captureResults.fence = new Fence(dup(drawFence)); + captureListener->onScreenCaptureCompleted(captureResults); + }); + } + return renderEngineResultFuture; + }); - captureResults.result = result; - captureListener->onScreenCaptureCompleted(captureResults); - })); - - return NO_ERROR; + // flatten scheduleResultFuture object to single shared_future object + if (captureListener == nullptr) { + std::future captureScreenResultFuture = + ftl::chain(std::move(scheduleResultFuture)) + .then([=](std::shared_future futureObject) + -> renderengine::RenderEngineResult { + auto& [status, drawFence] = futureObject.get(); + return {status, base::unique_fd(dup(drawFence))}; + }); + return captureScreenResultFuture.share(); + } else { + return ftl::yield({NO_ERROR, base::unique_fd()}).share(); + } } -status_t SurfaceFlinger::renderScreenImplLocked( +std::shared_future SurfaceFlinger::renderScreenImplLocked( const RenderArea& renderArea, TraverseLayersFunction traverseLayers, const std::shared_ptr& buffer, bool canCaptureBlackoutContent, bool regionSampling, bool grayscale, @@ -6201,7 +6234,8 @@ status_t SurfaceFlinger::renderScreenImplLocked( // the impetus on WindowManager to not persist them. if (captureResults.capturedSecureLayers && !canCaptureBlackoutContent) { ALOGW("FB is protected: PERMISSION_DENIED"); - return PERMISSION_DENIED; + return ftl::yield({PERMISSION_DENIED, base::unique_fd()}) + .share(); } captureResults.buffer = buffer->getBuffer(); @@ -6283,11 +6317,12 @@ status_t SurfaceFlinger::renderScreenImplLocked( }); - std::vector clientCompositionLayerPointers( - clientCompositionLayers.size()); + std::vector clientRenderEngineLayers; + clientRenderEngineLayers.reserve(clientCompositionLayers.size()); std::transform(clientCompositionLayers.begin(), clientCompositionLayers.end(), - clientCompositionLayerPointers.begin(), - std::pointer_traits::pointer_to); + std::back_inserter(clientRenderEngineLayers), + [](compositionengine::LayerFE::LayerSettings& settings) + -> renderengine::LayerSettings { return settings; }); // Use an empty fence for the buffer fence, since we just created the buffer so // there is no need for synchronization with the GPU. @@ -6295,24 +6330,22 @@ status_t SurfaceFlinger::renderScreenImplLocked( getRenderEngine().useProtectedContext(useProtected); const constexpr bool kUseFramebufferCache = false; - auto [status, drawFence] = - getRenderEngine() - .drawLayers(clientCompositionDisplay, clientCompositionLayerPointers, buffer, - kUseFramebufferCache, std::move(bufferFence)) - .get(); + std::future drawLayersResult = + getRenderEngine().drawLayers(clientCompositionDisplay, clientRenderEngineLayers, buffer, + kUseFramebufferCache, std::move(bufferFence)); - if (drawFence >= 0) { - sp releaseFence = new Fence(dup(drawFence)); - for (auto* layer : renderedLayers) { - layer->onLayerDisplayed(releaseFence); - } + std::shared_future drawLayersResultFuture = + drawLayersResult.share(); // drawLayersResult will be moved to shared one + + for (auto* layer : renderedLayers) { + // make a copy of shared_future object for each layer + layer->onLayerDisplayed(drawLayersResultFuture); } - captureResults.fence = new Fence(drawFence.release()); // Always switch back to unprotected context. getRenderEngine().useProtectedContext(false); - return status; + return drawLayersResultFuture; } void SurfaceFlinger::windowInfosReported() { diff --git a/services/surfaceflinger/SurfaceFlinger.h b/services/surfaceflinger/SurfaceFlinger.h index cb1611097a..3dda9f0607 100644 --- a/services/surfaceflinger/SurfaceFlinger.h +++ b/services/surfaceflinger/SurfaceFlinger.h @@ -809,17 +809,17 @@ private: // Boot animation, on/off animations and screen capture void startBootAnim(); - status_t captureScreenCommon(RenderAreaFuture, TraverseLayersFunction, ui::Size bufferSize, - ui::PixelFormat, bool allowProtected, bool grayscale, - const sp&); - status_t captureScreenCommon(RenderAreaFuture, TraverseLayersFunction, - const std::shared_ptr&, - bool regionSampling, bool grayscale, - const sp&); - status_t renderScreenImplLocked(const RenderArea&, TraverseLayersFunction, - const std::shared_ptr&, - bool canCaptureBlackoutContent, bool regionSampling, - bool grayscale, ScreenCaptureResults&); + std::shared_future captureScreenCommon( + RenderAreaFuture, TraverseLayersFunction, ui::Size bufferSize, ui::PixelFormat, + bool allowProtected, bool grayscale, const sp&); + std::shared_future captureScreenCommon( + RenderAreaFuture, TraverseLayersFunction, + const std::shared_ptr&, bool regionSampling, + bool grayscale, const sp&); + std::shared_future renderScreenImplLocked( + const RenderArea&, TraverseLayersFunction, + const std::shared_ptr&, bool canCaptureBlackoutContent, + bool regionSampling, bool grayscale, ScreenCaptureResults&); // If the uid provided is not UNSET_UID, the traverse will skip any layers that don't have a // matching ownerUid diff --git a/services/surfaceflinger/TransactionCallbackInvoker.cpp b/services/surfaceflinger/TransactionCallbackInvoker.cpp index c1eb8966d1..8fbf0b4d07 100644 --- a/services/surfaceflinger/TransactionCallbackInvoker.cpp +++ b/services/surfaceflinger/TransactionCallbackInvoker.cpp @@ -154,6 +154,38 @@ status_t TransactionCallbackInvoker::addCallbackHandle(const sp& // destroyed the client side is dead and there won't be anyone to send the callback to. sp surfaceControl = handle->surfaceControl.promote(); if (surfaceControl) { + sp prevFence = nullptr; + + for (const auto& futureStruct : handle->previousReleaseFences) { + sp currentFence = sp::make(dup(futureStruct.get().drawFence)); + if (prevFence == nullptr && currentFence->getStatus() != Fence::Status::Invalid) { + prevFence = currentFence; + handle->previousReleaseFence = prevFence; + } else if (prevFence != nullptr) { + // If both fences are signaled or both are unsignaled, we need to merge + // them to get an accurate timestamp. + if (prevFence->getStatus() != Fence::Status::Invalid && + prevFence->getStatus() == currentFence->getStatus()) { + char fenceName[32] = {}; + snprintf(fenceName, 32, "%.28s", handle->name.c_str()); + sp mergedFence = Fence::merge(fenceName, prevFence, currentFence); + if (mergedFence->isValid()) { + handle->previousReleaseFence = mergedFence; + prevFence = handle->previousReleaseFence; + } + } else if (currentFence->getStatus() == Fence::Status::Unsignaled) { + // If one fence has signaled and the other hasn't, the unsignaled + // fence will approximately correspond with the correct timestamp. + // There's a small race if both fences signal at about the same time + // and their statuses are retrieved with unfortunate timing. However, + // by this point, they will have both signaled and only the timestamp + // will be slightly off; any dependencies after this point will + // already have been met. + handle->previousReleaseFence = currentFence; + } + } + } + handle->previousReleaseFences = {}; FrameEventHistoryStats eventStats(handle->frameNumber, handle->gpuCompositionDoneFence->getSnapshot().fence, handle->compositorTiming, handle->refreshStartTime, diff --git a/services/surfaceflinger/TransactionCallbackInvoker.h b/services/surfaceflinger/TransactionCallbackInvoker.h index 7e879e119b..100dbfa8aa 100644 --- a/services/surfaceflinger/TransactionCallbackInvoker.h +++ b/services/surfaceflinger/TransactionCallbackInvoker.h @@ -18,8 +18,9 @@ #include #include -#include +#include #include +#include #include #include #include @@ -28,6 +29,7 @@ #include #include +#include #include namespace android { @@ -42,7 +44,9 @@ public: wp surfaceControl; bool releasePreviousBuffer = false; + std::string name; sp previousReleaseFence; + std::vector> previousReleaseFences; nsecs_t acquireTime = -1; nsecs_t latchTime = -1; uint32_t transformHint = 0; diff --git a/services/surfaceflinger/tests/unittests/CompositionTest.cpp b/services/surfaceflinger/tests/unittests/CompositionTest.cpp index a0812912d4..40ef6e702d 100644 --- a/services/surfaceflinger/tests/unittests/CompositionTest.cpp +++ b/services/surfaceflinger/tests/unittests/CompositionTest.cpp @@ -245,10 +245,16 @@ void CompositionTest::captureScreenComposition() { "screenshot"), *mRenderEngine, true); - status_t result = - mFlinger.renderScreenImplLocked(*renderArea, traverseLayers, mCaptureScreenBuffer, - forSystem, regionSampling); - EXPECT_EQ(NO_ERROR, result); + auto result = mFlinger.renderScreenImplLocked(*renderArea, traverseLayers, mCaptureScreenBuffer, + forSystem, regionSampling); + EXPECT_TRUE(result.valid()); + + auto& [status, drawFence] = result.get(); + + EXPECT_EQ(NO_ERROR, status); + if (drawFence.ok()) { + sync_wait(drawFence.get(), -1); + } LayerCase::cleanup(this); } @@ -344,9 +350,9 @@ struct BaseDisplayVariant { static void setupCommonScreensCaptureCallExpectations(CompositionTest* test) { EXPECT_CALL(*test->mRenderEngine, drawLayers) .WillRepeatedly([&](const renderengine::DisplaySettings& displaySettings, - const std::vector&, + const std::vector&, const std::shared_ptr&, - const bool, base::unique_fd &&) + const bool, base::unique_fd&&) -> std::future { EXPECT_EQ(DEFAULT_DISPLAY_MAX_LUMINANCE, displaySettings.maxLuminance); EXPECT_EQ(Rect(DEFAULT_DISPLAY_WIDTH, DEFAULT_DISPLAY_HEIGHT), @@ -395,9 +401,9 @@ struct BaseDisplayVariant { Return(0))); EXPECT_CALL(*test->mRenderEngine, drawLayers) .WillRepeatedly([&](const renderengine::DisplaySettings& displaySettings, - const std::vector&, + const std::vector&, const std::shared_ptr&, - const bool, base::unique_fd &&) + const bool, base::unique_fd&&) -> std::future { EXPECT_EQ(DEFAULT_DISPLAY_MAX_LUMINANCE, displaySettings.maxLuminance); EXPECT_EQ(Rect(DEFAULT_DISPLAY_WIDTH, DEFAULT_DISPLAY_HEIGHT), @@ -631,9 +637,9 @@ struct BaseLayerProperties { static void setupREBufferCompositionCommonCallExpectations(CompositionTest* test) { EXPECT_CALL(*test->mRenderEngine, drawLayers) .WillOnce([&](const renderengine::DisplaySettings& displaySettings, - const std::vector& layerSettings, + const std::vector& layerSettings, const std::shared_ptr&, const bool, - base::unique_fd &&) -> std::future { + base::unique_fd&&) -> std::future { EXPECT_EQ(DEFAULT_DISPLAY_MAX_LUMINANCE, displaySettings.maxLuminance); EXPECT_EQ(Rect(DEFAULT_DISPLAY_WIDTH, DEFAULT_DISPLAY_HEIGHT), displaySettings.physicalDisplay); @@ -650,16 +656,16 @@ struct BaseLayerProperties { "verification lambda"; return resultFuture; } - const renderengine::LayerSettings* layer = layerSettings.back(); - EXPECT_THAT(layer->source.buffer.buffer, Not(IsNull())); - EXPECT_THAT(layer->source.buffer.fence, Not(IsNull())); - EXPECT_EQ(DEFAULT_TEXTURE_ID, layer->source.buffer.textureName); - EXPECT_EQ(false, layer->source.buffer.isY410BT2020); - EXPECT_EQ(true, layer->source.buffer.usePremultipliedAlpha); - EXPECT_EQ(false, layer->source.buffer.isOpaque); - EXPECT_EQ(0.0, layer->geometry.roundedCornersRadius); - EXPECT_EQ(ui::Dataspace::UNKNOWN, layer->sourceDataspace); - EXPECT_EQ(LayerProperties::COLOR[3], layer->alpha); + const renderengine::LayerSettings layer = layerSettings.back(); + EXPECT_THAT(layer.source.buffer.buffer, Not(IsNull())); + EXPECT_THAT(layer.source.buffer.fence, Not(IsNull())); + EXPECT_EQ(DEFAULT_TEXTURE_ID, layer.source.buffer.textureName); + EXPECT_EQ(false, layer.source.buffer.isY410BT2020); + EXPECT_EQ(true, layer.source.buffer.usePremultipliedAlpha); + EXPECT_EQ(false, layer.source.buffer.isOpaque); + EXPECT_EQ(0.0, layer.geometry.roundedCornersRadius); + EXPECT_EQ(ui::Dataspace::UNKNOWN, layer.sourceDataspace); + EXPECT_EQ(LayerProperties::COLOR[3], layer.alpha); return resultFuture; }); } @@ -683,9 +689,9 @@ struct BaseLayerProperties { static void setupREColorCompositionCallExpectations(CompositionTest* test) { EXPECT_CALL(*test->mRenderEngine, drawLayers) .WillOnce([&](const renderengine::DisplaySettings& displaySettings, - const std::vector& layerSettings, + const std::vector& layerSettings, const std::shared_ptr&, const bool, - base::unique_fd &&) -> std::future { + base::unique_fd&&) -> std::future { EXPECT_EQ(DEFAULT_DISPLAY_MAX_LUMINANCE, displaySettings.maxLuminance); EXPECT_EQ(Rect(DEFAULT_DISPLAY_WIDTH, DEFAULT_DISPLAY_HEIGHT), displaySettings.physicalDisplay); @@ -702,14 +708,14 @@ struct BaseLayerProperties { "setupREColorCompositionCallExpectations verification lambda"; return resultFuture; } - const renderengine::LayerSettings* layer = layerSettings.back(); - EXPECT_THAT(layer->source.buffer.buffer, IsNull()); + const renderengine::LayerSettings layer = layerSettings.back(); + EXPECT_THAT(layer.source.buffer.buffer, IsNull()); EXPECT_EQ(half3(LayerProperties::COLOR[0], LayerProperties::COLOR[1], LayerProperties::COLOR[2]), - layer->source.solidColor); - EXPECT_EQ(0.0, layer->geometry.roundedCornersRadius); - EXPECT_EQ(ui::Dataspace::UNKNOWN, layer->sourceDataspace); - EXPECT_EQ(LayerProperties::COLOR[3], layer->alpha); + layer.source.solidColor); + EXPECT_EQ(0.0, layer.geometry.roundedCornersRadius); + EXPECT_EQ(ui::Dataspace::UNKNOWN, layer.sourceDataspace); + EXPECT_EQ(LayerProperties::COLOR[3], layer.alpha); return resultFuture; }); } @@ -763,9 +769,9 @@ struct CommonSecureLayerProperties : public BaseLayerProperties static void setupInsecureREBufferCompositionCommonCallExpectations(CompositionTest* test) { EXPECT_CALL(*test->mRenderEngine, drawLayers) .WillOnce([&](const renderengine::DisplaySettings& displaySettings, - const std::vector& layerSettings, + const std::vector& layerSettings, const std::shared_ptr&, const bool, - base::unique_fd &&) -> std::future { + base::unique_fd&&) -> std::future { EXPECT_EQ(DEFAULT_DISPLAY_MAX_LUMINANCE, displaySettings.maxLuminance); EXPECT_EQ(Rect(DEFAULT_DISPLAY_WIDTH, DEFAULT_DISPLAY_HEIGHT), displaySettings.physicalDisplay); @@ -782,12 +788,12 @@ struct CommonSecureLayerProperties : public BaseLayerProperties "verification lambda"; return resultFuture; } - const renderengine::LayerSettings* layer = layerSettings.back(); - EXPECT_THAT(layer->source.buffer.buffer, IsNull()); - EXPECT_EQ(half3(0.0f, 0.0f, 0.0f), layer->source.solidColor); - EXPECT_EQ(0.0, layer->geometry.roundedCornersRadius); - EXPECT_EQ(ui::Dataspace::UNKNOWN, layer->sourceDataspace); - EXPECT_EQ(1.0f, layer->alpha); + const renderengine::LayerSettings layer = layerSettings.back(); + EXPECT_THAT(layer.source.buffer.buffer, IsNull()); + EXPECT_EQ(half3(0.0f, 0.0f, 0.0f), layer.source.solidColor); + EXPECT_EQ(0.0, layer.geometry.roundedCornersRadius); + EXPECT_EQ(ui::Dataspace::UNKNOWN, layer.sourceDataspace); + EXPECT_EQ(1.0f, layer.alpha); return resultFuture; }); } -- cgit v1.2.3-59-g8ed1b From 4d48f9092b1209ad871969613e37ae19cb506d3c Mon Sep 17 00:00:00 2001 From: ramindani Date: Mon, 20 Sep 2021 21:07:45 +0000 Subject: Latch Unsignaled when only a single layer is being updated. Three conditions are introduced. DISABLED (Default for now): This is when latch unsignaled is completely disabled. AUTO: This is when we will latch for the single layer update. Further refinements will be done in b/200284381 ALWAYS: This will latch unsignaled no matter what the change is. BUG: 198189193 Test: Did the manual test and atest libsurfaceflinger_unittest atest MockFence_test atest libgui_test Change-Id: I0c0b475ba4a093275fac23a986fc610ea462f73e --- libs/ui/include/ui/Fence.h | 2 +- libs/ui/include_mock/ui/MockFence.h | 1 + libs/ui/tests/MockFence_test.cpp | 12 + services/surfaceflinger/BufferQueueLayer.cpp | 2 +- services/surfaceflinger/BufferStateLayer.cpp | 2 +- services/surfaceflinger/SurfaceFlinger.cpp | 149 ++++++-- services/surfaceflinger/SurfaceFlinger.h | 15 +- .../tests/unittests/TestableSurfaceFlinger.h | 1 + .../tests/unittests/TransactionApplicationTest.cpp | 416 ++++++++++++++++++++- 9 files changed, 562 insertions(+), 38 deletions(-) (limited to 'services/surfaceflinger/BufferQueueLayer.cpp') diff --git a/libs/ui/include/ui/Fence.h b/libs/ui/include/ui/Fence.h index 7634007771..9aae145c04 100644 --- a/libs/ui/include/ui/Fence.h +++ b/libs/ui/include/ui/Fence.h @@ -124,7 +124,7 @@ public: // getStatus() returns whether the fence has signaled yet. Prefer this to // getSignalTime() or wait() if all you care about is whether the fence has // signaled. - inline Status getStatus() { + virtual inline Status getStatus() { // The sync_wait call underlying wait() has been measured to be // significantly faster than the sync_fence_info call underlying // getSignalTime(), which might otherwise appear to be the more obvious diff --git a/libs/ui/include_mock/ui/MockFence.h b/libs/ui/include_mock/ui/MockFence.h index 162ec02455..71adee4fbc 100644 --- a/libs/ui/include_mock/ui/MockFence.h +++ b/libs/ui/include_mock/ui/MockFence.h @@ -27,6 +27,7 @@ public: virtual ~MockFence() = default; MOCK_METHOD(nsecs_t, getSignalTime, (), (const, override)); + MOCK_METHOD(Status, getStatus, (), (override)); }; }; // namespace android::mock diff --git a/libs/ui/tests/MockFence_test.cpp b/libs/ui/tests/MockFence_test.cpp index 6e520b1aee..40dddc3cf2 100644 --- a/libs/ui/tests/MockFence_test.cpp +++ b/libs/ui/tests/MockFence_test.cpp @@ -42,4 +42,16 @@ TEST_F(MockFenceTest, getSignalTime) { EXPECT_EQ(1234, fence->getSignalTime()); } +TEST_F(MockFenceTest, getStatus) { + sp fence = getFenceForTesting(); + + EXPECT_CALL(getMockFence(), getStatus).WillOnce(Return(Fence::Status::Unsignaled)); + EXPECT_EQ(Fence::Status::Unsignaled, fence->getStatus()); + + EXPECT_CALL(getMockFence(), getStatus).WillOnce(Return(Fence::Status::Signaled)); + EXPECT_EQ(Fence::Status::Signaled, fence->getStatus()); + + EXPECT_CALL(getMockFence(), getStatus).WillOnce(Return(Fence::Status::Invalid)); + EXPECT_EQ(Fence::Status::Invalid, fence->getStatus()); +} } // namespace android::ui diff --git a/services/surfaceflinger/BufferQueueLayer.cpp b/services/surfaceflinger/BufferQueueLayer.cpp index 4e5d2d03b0..8aecec131f 100644 --- a/services/surfaceflinger/BufferQueueLayer.cpp +++ b/services/surfaceflinger/BufferQueueLayer.cpp @@ -118,7 +118,7 @@ bool BufferQueueLayer::isBufferDue(nsecs_t expectedPresentTime) const { bool BufferQueueLayer::fenceHasSignaled() const { Mutex::Autolock lock(mQueueItemLock); - if (SurfaceFlinger::enableLatchUnsignaled) { + if (SurfaceFlinger::enableLatchUnsignaledConfig != LatchUnsignaledConfig::Disabled) { return true; } diff --git a/services/surfaceflinger/BufferStateLayer.cpp b/services/surfaceflinger/BufferStateLayer.cpp index c0753f9d47..f7f96ab1b1 100644 --- a/services/surfaceflinger/BufferStateLayer.cpp +++ b/services/surfaceflinger/BufferStateLayer.cpp @@ -630,7 +630,7 @@ FloatRect BufferStateLayer::computeSourceBounds(const FloatRect& parentBounds) c // Interface implementation for BufferLayer // ----------------------------------------------------------------------- bool BufferStateLayer::fenceHasSignaled() const { - if (SurfaceFlinger::enableLatchUnsignaled) { + if (SurfaceFlinger::enableLatchUnsignaledConfig != LatchUnsignaledConfig::Disabled) { return true; } diff --git a/services/surfaceflinger/SurfaceFlinger.cpp b/services/surfaceflinger/SurfaceFlinger.cpp index 8d7221c1dc..9b1677478d 100644 --- a/services/surfaceflinger/SurfaceFlinger.cpp +++ b/services/surfaceflinger/SurfaceFlinger.cpp @@ -341,7 +341,7 @@ Dataspace SurfaceFlinger::wideColorGamutCompositionDataspace = Dataspace::V0_SRG ui::PixelFormat SurfaceFlinger::wideColorGamutCompositionPixelFormat = ui::PixelFormat::RGBA_8888; bool SurfaceFlinger::useFrameRateApi; bool SurfaceFlinger::enableSdrDimming; -bool SurfaceFlinger::enableLatchUnsignaled; +LatchUnsignaledConfig SurfaceFlinger::enableLatchUnsignaledConfig; std::string decodeDisplayColorSetting(DisplayColorSetting displayColorSetting) { switch(displayColorSetting) { @@ -501,7 +501,17 @@ SurfaceFlinger::SurfaceFlinger(Factory& factory) : SurfaceFlinger(factory, SkipI // Debug property overrides ro. property enableSdrDimming = property_get_bool("debug.sf.enable_sdr_dimming", enable_sdr_dimming(false)); - enableLatchUnsignaled = base::GetBoolProperty("debug.sf.latch_unsignaled"s, false); + enableLatchUnsignaledConfig = getLatchUnsignaledConfig(); +} + +LatchUnsignaledConfig SurfaceFlinger::getLatchUnsignaledConfig() { + if (base::GetBoolProperty("debug.sf.latch_unsignaled"s, false)) { + return LatchUnsignaledConfig::Always; + } else if (base::GetBoolProperty("debug.sf.auto_latch_unsignaled"s, false)) { + return LatchUnsignaledConfig::Auto; + } else { + return LatchUnsignaledConfig::Disabled; + } } SurfaceFlinger::~SurfaceFlinger() = default; @@ -3421,29 +3431,34 @@ uint32_t SurfaceFlinger::setTransactionFlags(uint32_t mask, TransactionSchedule } bool SurfaceFlinger::flushTransactionQueues() { - bool needsTraversal = false; // to prevent onHandleDestroyed from being called while the lock is held, // we must keep a copy of the transactions (specifically the composer // states) around outside the scope of the lock - std::vector transactions; + std::vector transactions; // Layer handles that have transactions with buffers that are ready to be applied. std::unordered_set, ISurfaceComposer::SpHash> bufferLayersReadyToPresent; { Mutex::Autolock _l(mStateLock); { Mutex::Autolock _l(mQueueLock); + // allowLatchUnsignaled acts as a filter condition when latch unsignaled is either auto + // or always. auto: in this case we let buffer latch unsignaled if we have only one + // applyToken and if only first transaction is latch unsignaled. If more than one + // applyToken we don't latch unsignaled. + bool allowLatchUnsignaled = allowedLatchUnsignaled(); + bool isFirstUnsignaledTransactionApplied = false; // Collect transactions from pending transaction queue. auto it = mPendingTransactionQueues.begin(); while (it != mPendingTransactionQueues.end()) { auto& [applyToken, transactionQueue] = *it; - while (!transactionQueue.empty()) { auto& transaction = transactionQueue.front(); if (!transactionIsReadyToBeApplied(transaction.frameTimelineInfo, transaction.isAutoTimestamp, transaction.desiredPresentTime, transaction.originUid, transaction.states, - bufferLayersReadyToPresent)) { + bufferLayersReadyToPresent, + allowLatchUnsignaled)) { setTransactionFlags(eTransactionFlushNeeded); break; } @@ -3452,6 +3467,14 @@ bool SurfaceFlinger::flushTransactionQueues() { }); transactions.emplace_back(std::move(transaction)); transactionQueue.pop(); + if (allowLatchUnsignaled && + enableLatchUnsignaledConfig == LatchUnsignaledConfig::Auto) { + // if allowLatchUnsignaled && we are in LatchUnsignaledConfig::Auto + // then we should have only one applyToken for processing. + // so we can stop further transactions on this applyToken. + isFirstUnsignaledTransactionApplied = true; + break; + } } if (transactionQueue.empty()) { @@ -3463,52 +3486,115 @@ bool SurfaceFlinger::flushTransactionQueues() { } // Collect transactions from current transaction queue or queue to pending transactions. - // Case 1: push to pending when transactionIsReadyToBeApplied is false. + // Case 1: push to pending when transactionIsReadyToBeApplied is false + // or the first transaction was unsignaled. // Case 2: push to pending when there exist a pending queue. - // Case 3: others are ready to apply. + // Case 3: others are the transactions that are ready to apply. while (!mTransactionQueue.empty()) { auto& transaction = mTransactionQueue.front(); bool pendingTransactions = mPendingTransactionQueues.find(transaction.applyToken) != mPendingTransactionQueues.end(); - if (pendingTransactions || + if (isFirstUnsignaledTransactionApplied || pendingTransactions || !transactionIsReadyToBeApplied(transaction.frameTimelineInfo, transaction.isAutoTimestamp, transaction.desiredPresentTime, transaction.originUid, transaction.states, - bufferLayersReadyToPresent)) { + bufferLayersReadyToPresent, + allowLatchUnsignaled)) { mPendingTransactionQueues[transaction.applyToken].push(std::move(transaction)); } else { transaction.traverseStatesWithBuffers([&](const layer_state_t& state) { bufferLayersReadyToPresent.insert(state.surface); }); transactions.emplace_back(std::move(transaction)); + if (allowLatchUnsignaled && + enableLatchUnsignaledConfig == LatchUnsignaledConfig::Auto) { + isFirstUnsignaledTransactionApplied = true; + } } - mTransactionQueue.pop(); + mTransactionQueue.pop_front(); ATRACE_INT("TransactionQueue", mTransactionQueue.size()); } + + return applyTransactions(transactions); } + } +} - // Now apply all transactions. - for (const auto& transaction : transactions) { - needsTraversal |= - applyTransactionState(transaction.frameTimelineInfo, transaction.states, - transaction.displays, transaction.flags, - transaction.inputWindowCommands, - transaction.desiredPresentTime, - transaction.isAutoTimestamp, transaction.buffer, - transaction.postTime, transaction.permissions, - transaction.hasListenerCallbacks, - transaction.listenerCallbacks, transaction.originPid, - transaction.originUid, transaction.id); - if (transaction.transactionCommittedSignal) { - mTransactionCommittedSignals.emplace_back( - std::move(transaction.transactionCommittedSignal)); - } +bool SurfaceFlinger::applyTransactions(std::vector& transactions) { + bool needsTraversal = false; + // Now apply all transactions. + for (const auto& transaction : transactions) { + needsTraversal |= + applyTransactionState(transaction.frameTimelineInfo, transaction.states, + transaction.displays, transaction.flags, + transaction.inputWindowCommands, + transaction.desiredPresentTime, transaction.isAutoTimestamp, + transaction.buffer, transaction.postTime, + transaction.permissions, transaction.hasListenerCallbacks, + transaction.listenerCallbacks, transaction.originPid, + transaction.originUid, transaction.id); + if (transaction.transactionCommittedSignal) { + mTransactionCommittedSignals.emplace_back( + std::move(transaction.transactionCommittedSignal)); } - } // unlock mStateLock + } return needsTraversal; } +bool SurfaceFlinger::allowedLatchUnsignaled() { + if (enableLatchUnsignaledConfig == LatchUnsignaledConfig::Disabled) { + return false; + } + // Always mode matches the current latch unsignaled behavior. + // This behavior is currently used by the partners and we would like + // to keep it until we are completely migrated to Auto mode successfully + // and we we have our fallback based implementation in place. + if (enableLatchUnsignaledConfig == LatchUnsignaledConfig::Always) { + return true; + } + + // if enableLatchUnsignaledConfig == LatchUnsignaledConfig::Auto + // we don't latch unsignaled if more than one applyToken, as it can backpressure + // the other transactions. + if (mPendingTransactionQueues.size() > 1) { + return false; + } + std::optional> applyToken = std::nullopt; + bool isPendingTransactionQueuesItem = false; + if (!mPendingTransactionQueues.empty()) { + applyToken = mPendingTransactionQueues.begin()->first; + isPendingTransactionQueuesItem = true; + } + + for (const auto& item : mTransactionQueue) { + if (!applyToken.has_value()) { + applyToken = item.applyToken; + } else if (applyToken.has_value() && applyToken != item.applyToken) { + return false; + } + } + + if (isPendingTransactionQueuesItem) { + return checkTransactionCanLatchUnsignaled( + mPendingTransactionQueues.begin()->second.front()); + } else if (applyToken.has_value()) { + return checkTransactionCanLatchUnsignaled((mTransactionQueue.front())); + } + return false; +} + +bool SurfaceFlinger::checkTransactionCanLatchUnsignaled(const TransactionState& transaction) { + if (transaction.states.size() == 1) { + const auto& state = transaction.states.begin()->state; + return (state.flags & ~layer_state_t::eBufferChanged) == 0 && + state.bufferData.flags.test(BufferData::BufferDataChange::fenceChanged) && + state.bufferData.acquireFence && + state.bufferData.acquireFence->getStatus() == Fence::Status::Unsignaled; + } + return false; +} + bool SurfaceFlinger::transactionFlushNeeded() { Mutex::Autolock _l(mQueueLock); return !mPendingTransactionQueues.empty() || !mTransactionQueue.empty(); @@ -3540,7 +3626,8 @@ bool SurfaceFlinger::transactionIsReadyToBeApplied( const FrameTimelineInfo& info, bool isAutoTimestamp, int64_t desiredPresentTime, uid_t originUid, const Vector& states, const std::unordered_set, ISurfaceComposer::SpHash>& - bufferLayersReadyToPresent) const { + bufferLayersReadyToPresent, + bool allowLatchUnsignaled) const { ATRACE_CALL(); const nsecs_t expectedPresentTime = mExpectedPresentTime.load(); // Do not present if the desiredPresentTime has not passed unless it is more than one second @@ -3567,7 +3654,7 @@ bool SurfaceFlinger::transactionIsReadyToBeApplied( const layer_state_t& s = state.state; const bool acquireFenceChanged = s.bufferData.flags.test(BufferData::BufferDataChange::fenceChanged); - if (acquireFenceChanged && s.bufferData.acquireFence && !enableLatchUnsignaled && + if (acquireFenceChanged && s.bufferData.acquireFence && !allowLatchUnsignaled && s.bufferData.acquireFence->getStatus() == Fence::Status::Unsignaled) { ATRACE_NAME("fence unsignaled"); return false; @@ -3628,7 +3715,7 @@ void SurfaceFlinger::queueTransaction(TransactionState& state) { : CountDownLatch::eSyncTransaction)); } - mTransactionQueue.emplace(state); + mTransactionQueue.emplace_back(state); ATRACE_INT("TransactionQueue", mTransactionQueue.size()); const auto schedule = [](uint32_t flags) { diff --git a/services/surfaceflinger/SurfaceFlinger.h b/services/surfaceflinger/SurfaceFlinger.h index 276c7f6bfe..97fddf2930 100644 --- a/services/surfaceflinger/SurfaceFlinger.h +++ b/services/surfaceflinger/SurfaceFlinger.h @@ -135,6 +135,8 @@ enum { eTransactionMask = 0x1f, }; +enum class LatchUnsignaledConfig { Always, Auto, Disabled }; + using DisplayColorSetting = compositionengine::OutputColorSetting; struct SurfaceFlingerBE { @@ -257,7 +259,7 @@ public: // being treated as native display brightness static bool enableSdrDimming; - static bool enableLatchUnsignaled; + static LatchUnsignaledConfig enableLatchUnsignaledConfig; // must be called before clients can connect void init() ANDROID_API; @@ -751,7 +753,14 @@ private: const FrameTimelineInfo& info, bool isAutoTimestamp, int64_t desiredPresentTime, uid_t originUid, const Vector& states, const std::unordered_set, ISurfaceComposer::SpHash>& - bufferLayersReadyToPresent) const REQUIRES(mStateLock); + bufferLayersReadyToPresent, + bool allowLatchUnsignaled) const REQUIRES(mStateLock); + static LatchUnsignaledConfig getLatchUnsignaledConfig(); + bool latchUnsignaledIsAllowed(std::vector& transactions) REQUIRES(mStateLock); + bool allowedLatchUnsignaled() REQUIRES(mQueueLock, mStateLock); + bool checkTransactionCanLatchUnsignaled(const TransactionState& transaction) + REQUIRES(mStateLock); + bool applyTransactions(std::vector& transactions) REQUIRES(mStateLock); uint32_t setDisplayStateLocked(const DisplayState& s) REQUIRES(mStateLock); uint32_t addInputWindowCommands(const InputWindowCommands& inputWindowCommands) REQUIRES(mStateLock); @@ -1242,7 +1251,7 @@ private: Condition mTransactionQueueCV; std::unordered_map, std::queue, IListenerHash> mPendingTransactionQueues GUARDED_BY(mQueueLock); - std::queue mTransactionQueue GUARDED_BY(mQueueLock); + std::deque mTransactionQueue GUARDED_BY(mQueueLock); /* * Feature prototyping */ diff --git a/services/surfaceflinger/tests/unittests/TestableSurfaceFlinger.h b/services/surfaceflinger/tests/unittests/TestableSurfaceFlinger.h index c23fcc7d58..9832372a86 100644 --- a/services/surfaceflinger/tests/unittests/TestableSurfaceFlinger.h +++ b/services/surfaceflinger/tests/unittests/TestableSurfaceFlinger.h @@ -375,6 +375,7 @@ public: auto& getTransactionQueue() { return mFlinger->mTransactionQueue; } auto& getPendingTransactionQueue() { return mFlinger->mPendingTransactionQueues; } + auto& getTransactionCommittedSignals() { return mFlinger->mTransactionCommittedSignals; } auto setTransactionState( const FrameTimelineInfo& frameTimelineInfo, const Vector& states, diff --git a/services/surfaceflinger/tests/unittests/TransactionApplicationTest.cpp b/services/surfaceflinger/tests/unittests/TransactionApplicationTest.cpp index 05551b4701..8caadfbf85 100644 --- a/services/surfaceflinger/tests/unittests/TransactionApplicationTest.cpp +++ b/services/surfaceflinger/tests/unittests/TransactionApplicationTest.cpp @@ -24,8 +24,8 @@ #include #include #include +#include #include - #include "TestableScheduler.h" #include "TestableSurfaceFlinger.h" #include "mock/MockEventThread.h" @@ -74,6 +74,13 @@ public: EXPECT_CALL(*mVSyncTracker, currentPeriod()) .WillRepeatedly(Return(FakeHwcDisplayInjector::DEFAULT_VSYNC_PERIOD)); + EXPECT_CALL(*mFenceUnsignaled, getStatus()) + .WillRepeatedly(Return(Fence::Status::Unsignaled)); + EXPECT_CALL(*mFenceUnsignaled2, getStatus()) + .WillRepeatedly(Return(Fence::Status::Unsignaled)); + EXPECT_CALL(*mFenceSignaled, getStatus()).WillRepeatedly(Return(Fence::Status::Signaled)); + EXPECT_CALL(*mFenceSignaled2, getStatus()).WillRepeatedly(Return(Fence::Status::Signaled)); + mFlinger.setupComposer(std::make_unique()); mFlinger.setupScheduler(std::unique_ptr(mVsyncController), std::unique_ptr(mVSyncTracker), @@ -88,6 +95,10 @@ public: mock::MessageQueue* mMessageQueue = new mock::MessageQueue(); mock::VsyncController* mVsyncController = new mock::VsyncController(); mock::VSyncTracker* mVSyncTracker = new mock::VSyncTracker(); + mock::MockFence* mFenceUnsignaled = new mock::MockFence(); + mock::MockFence* mFenceSignaled = new mock::MockFence(); + mock::MockFence* mFenceUnsignaled2 = new mock::MockFence(); + mock::MockFence* mFenceSignaled2 = new mock::MockFence(); struct TransactionInfo { Vector states; @@ -124,6 +135,15 @@ public: transaction.frameTimelineInfo = frameTimelineInfo; } + void setupSingleWithComposer(TransactionInfo& transaction, uint32_t flags, + bool syncInputWindows, int64_t desiredPresentTime, + bool isAutoTimestamp, const FrameTimelineInfo& frameTimelineInfo, + const Vector* states) { + setupSingle(transaction, flags, syncInputWindows, desiredPresentTime, isAutoTimestamp, + frameTimelineInfo); + transaction.states = *states; + } + void NotPlacedOnTransactionQueue(uint32_t flags, bool syncInputWindows) { ASSERT_EQ(0u, mFlinger.getTransactionQueue().size()); EXPECT_CALL(*mMessageQueue, scheduleCommit()).Times(1); @@ -245,6 +265,188 @@ public: EXPECT_EQ(0u, transactionQueue.size()); } + void Flush_removesUnsignaledFromTheQueue(Vector state1, + Vector state2, + bool updateApplyToken = true) { + ASSERT_EQ(0u, mFlinger.getTransactionQueue().size()); + + TransactionInfo transactionA; + setupSingleWithComposer(transactionA, ISurfaceComposer::eSynchronous, + /*syncInputWindows*/ false, + /*desiredPresentTime*/ systemTime(), /*isAutoTimestamp*/ true, + FrameTimelineInfo{}, &state1); + + mFlinger.setTransactionState(transactionA.frameTimelineInfo, transactionA.states, + transactionA.displays, transactionA.flags, + transactionA.applyToken, transactionA.inputWindowCommands, + transactionA.desiredPresentTime, transactionA.isAutoTimestamp, + transactionA.uncacheBuffer, mHasListenerCallbacks, mCallbacks, + transactionA.id); + + TransactionInfo transactionB; + if (updateApplyToken) { + transactionB.applyToken = sp(); + } + setupSingleWithComposer(transactionB, ISurfaceComposer::eSynchronous, + /*syncInputWindows*/ false, + /*desiredPresentTime*/ systemTime(), /*isAutoTimestamp*/ true, + FrameTimelineInfo{}, &state2); + mFlinger.setTransactionState(transactionB.frameTimelineInfo, transactionB.states, + transactionB.displays, transactionB.flags, + transactionB.applyToken, transactionB.inputWindowCommands, + transactionB.desiredPresentTime, transactionB.isAutoTimestamp, + transactionB.uncacheBuffer, mHasListenerCallbacks, mCallbacks, + transactionB.id); + + mFlinger.flushTransactionQueues(); + EXPECT_EQ(0u, mFlinger.getPendingTransactionQueue().size()); + EXPECT_EQ(0u, mFlinger.getTransactionQueue().size()); + EXPECT_EQ(2ul, mFlinger.getTransactionCommittedSignals().size()); + } + + void Flush_removesFromTheQueue(const Vector& state) { + ASSERT_EQ(0u, mFlinger.getTransactionQueue().size()); + EXPECT_EQ(0u, mFlinger.getPendingTransactionQueue().size()); + + TransactionInfo transaction; + setupSingleWithComposer(transaction, ISurfaceComposer::eSynchronous, + /*syncInputWindows*/ false, + /*desiredPresentTime*/ systemTime(), /*isAutoTimestamp*/ true, + FrameTimelineInfo{}, &state); + + mFlinger.setTransactionState(transaction.frameTimelineInfo, transaction.states, + transaction.displays, transaction.flags, + transaction.applyToken, transaction.inputWindowCommands, + transaction.desiredPresentTime, transaction.isAutoTimestamp, + transaction.uncacheBuffer, mHasListenerCallbacks, mCallbacks, + transaction.id); + + mFlinger.flushTransactionQueues(); + EXPECT_EQ(0u, mFlinger.getPendingTransactionQueue().size()); + EXPECT_EQ(0u, mFlinger.getTransactionQueue().size()); + EXPECT_EQ(1u, mFlinger.getTransactionCommittedSignals().size()); + } + + void Flush_keepsInTheQueue(const Vector& state) { + ASSERT_EQ(0u, mFlinger.getTransactionQueue().size()); + EXPECT_EQ(0u, mFlinger.getPendingTransactionQueue().size()); + + TransactionInfo transaction; + setupSingleWithComposer(transaction, ISurfaceComposer::eSynchronous, + /*syncInputWindows*/ false, + /*desiredPresentTime*/ systemTime(), /*isAutoTimestamp*/ true, + FrameTimelineInfo{}, &state); + + mFlinger.setTransactionState(transaction.frameTimelineInfo, transaction.states, + transaction.displays, transaction.flags, + transaction.applyToken, transaction.inputWindowCommands, + transaction.desiredPresentTime, transaction.isAutoTimestamp, + transaction.uncacheBuffer, mHasListenerCallbacks, mCallbacks, + transaction.id); + + mFlinger.flushTransactionQueues(); + EXPECT_EQ(1u, mFlinger.getPendingTransactionQueue().size()); + EXPECT_EQ(0u, mFlinger.getTransactionQueue().size()); + EXPECT_EQ(0ul, mFlinger.getTransactionCommittedSignals().size()); + } + + void Flush_KeepsUnsignaledInTheQueue(const Vector& state1, + const Vector& state2, + bool updateApplyToken = true, + uint32_t pendingTransactionQueueSize = 1u) { + EXPECT_EQ(0u, mFlinger.getPendingTransactionQueue().size()); + ASSERT_EQ(0u, mFlinger.getTransactionQueue().size()); + auto time = systemTime(); + TransactionInfo transactionA; + TransactionInfo transactionB; + setupSingleWithComposer(transactionA, ISurfaceComposer::eSynchronous, + /*syncInputWindows*/ false, + /*desiredPresentTime*/ time, /*isAutoTimestamp*/ true, + FrameTimelineInfo{}, &state1); + setupSingleWithComposer(transactionB, ISurfaceComposer::eSynchronous, + /*syncInputWindows*/ false, + /*desiredPresentTime*/ time, /*isAutoTimestamp*/ true, + FrameTimelineInfo{}, &state2); + mFlinger.setTransactionState(transactionA.frameTimelineInfo, transactionA.states, + transactionA.displays, transactionA.flags, + transactionA.applyToken, transactionA.inputWindowCommands, + transactionA.desiredPresentTime, transactionA.isAutoTimestamp, + transactionA.uncacheBuffer, mHasListenerCallbacks, mCallbacks, + transactionA.id); + if (updateApplyToken) { + transactionB.applyToken = sp(); + } + mFlinger.setTransactionState(transactionB.frameTimelineInfo, transactionB.states, + transactionB.displays, transactionB.flags, + transactionB.applyToken, transactionB.inputWindowCommands, + transactionB.desiredPresentTime, transactionB.isAutoTimestamp, + transactionB.uncacheBuffer, mHasListenerCallbacks, mCallbacks, + transactionB.id); + + mFlinger.flushTransactionQueues(); + EXPECT_EQ(pendingTransactionQueueSize, mFlinger.getPendingTransactionQueue().size()); + EXPECT_EQ(0u, mFlinger.getTransactionQueue().size()); + } + + void Flush_removesSignaledFromTheQueue(const Vector& state1, + const Vector& state2) { + ASSERT_EQ(0u, mFlinger.getTransactionQueue().size()); + EXPECT_EQ(0u, mFlinger.getPendingTransactionQueue().size()); + + auto time = systemTime(); + TransactionInfo transactionA; + TransactionInfo transactionB; + setupSingleWithComposer(transactionA, ISurfaceComposer::eSynchronous, + /*syncInputWindows*/ false, + /*desiredPresentTime*/ time, /*isAutoTimestamp*/ true, + FrameTimelineInfo{}, &state1); + setupSingleWithComposer(transactionB, ISurfaceComposer::eSynchronous, + /*syncInputWindows*/ false, + /*desiredPresentTime*/ time, /*isAutoTimestamp*/ true, + FrameTimelineInfo{}, &state2); + mFlinger.setTransactionState(transactionA.frameTimelineInfo, transactionA.states, + transactionA.displays, transactionA.flags, + transactionA.applyToken, transactionA.inputWindowCommands, + transactionA.desiredPresentTime, transactionA.isAutoTimestamp, + transactionA.uncacheBuffer, mHasListenerCallbacks, mCallbacks, + transactionA.id); + mFlinger.setTransactionState(transactionB.frameTimelineInfo, transactionB.states, + transactionB.displays, transactionB.flags, + transactionB.applyToken, transactionB.inputWindowCommands, + transactionB.desiredPresentTime, transactionB.isAutoTimestamp, + transactionB.uncacheBuffer, mHasListenerCallbacks, mCallbacks, + transactionB.id); + + mFlinger.flushTransactionQueues(); + EXPECT_EQ(0u, mFlinger.getPendingTransactionQueue().size()); + EXPECT_EQ(0u, mFlinger.getTransactionQueue().size()); + EXPECT_EQ(2ul, mFlinger.getTransactionCommittedSignals().size()); + } + + static Vector createComposerStateVector(const ComposerState& state1, + const ComposerState& state2) { + Vector states; + states.push_back(state1); + states.push_back(state2); + return states; + } + + static Vector createComposerStateVector(const ComposerState& state) { + Vector states; + states.push_back(state); + return states; + } + + static ComposerState createComposerState(int layerId, sp fence, + uint32_t stateFlags = layer_state_t::eBufferChanged) { + ComposerState composer_state; + composer_state.state.bufferData.acquireFence = std::move(fence); + composer_state.state.layerId = layerId; + composer_state.state.bufferData.flags = BufferData::BufferDataChange::fenceChanged; + composer_state.state.flags = stateFlags; + return composer_state; + } + bool mHasListenerCallbacks = false; std::vector mCallbacks; int mTransactionNumber = 0; @@ -327,4 +529,216 @@ TEST_F(TransactionApplicationTest, FromHandle) { auto ret = mFlinger.fromHandle(badHandle); EXPECT_EQ(nullptr, ret.promote().get()); } + +TEST_F(TransactionApplicationTest, Flush_RemovesSingleSignaledFromTheQueue_LatchUnsignaled_Auto) { + SurfaceFlinger::enableLatchUnsignaledConfig = LatchUnsignaledConfig::Auto; + Flush_removesFromTheQueue( + createComposerStateVector(createComposerState(/*layerId*/ 1, mFenceSignaled))); +} + +TEST_F(TransactionApplicationTest, Flush_RemovesSingleUnSignaledFromTheQueue_LatchUnsignaled_Auto) { + SurfaceFlinger::enableLatchUnsignaledConfig = LatchUnsignaledConfig::Auto; + Flush_removesFromTheQueue( + createComposerStateVector(createComposerState(/*layerId*/ 1, mFenceUnsignaled))); +} + +TEST_F(TransactionApplicationTest, + Flush_KeepsUnSignaledInTheQueue_NonBufferCropChange_LatchUnsignaled_Auto) { + SurfaceFlinger::enableLatchUnsignaledConfig = LatchUnsignaledConfig::Auto; + Flush_keepsInTheQueue(createComposerStateVector( + createComposerState(/*layerId*/ 1, mFenceUnsignaled, layer_state_t::eCropChanged))); +} + +TEST_F(TransactionApplicationTest, + Flush_KeepsUnSignaledInTheQueue_NonBufferChangeClubed_LatchUnsignaled_Auto) { + SurfaceFlinger::enableLatchUnsignaledConfig = LatchUnsignaledConfig::Auto; + Flush_keepsInTheQueue(createComposerStateVector( + createComposerState(/*layerId*/ 1, mFenceUnsignaled, + layer_state_t::eCropChanged | layer_state_t::eBufferChanged))); +} + +TEST_F(TransactionApplicationTest, + Flush_KeepsInTheQueueSameApplyTokenMultiState_LatchUnsignaled_Auto) { + SurfaceFlinger::enableLatchUnsignaledConfig = LatchUnsignaledConfig::Auto; + Flush_keepsInTheQueue( + createComposerStateVector(createComposerState(/*layerId*/ 1, mFenceUnsignaled), + createComposerState(/*layerId*/ 1, mFenceSignaled))); +} + +TEST_F(TransactionApplicationTest, Flush_KeepsInTheQueue_MultipleStateTransaction_Auto) { + SurfaceFlinger::enableLatchUnsignaledConfig = LatchUnsignaledConfig::Auto; + Flush_keepsInTheQueue( + createComposerStateVector(createComposerState(/*layerId*/ 1, mFenceUnsignaled), + createComposerState(/*layerId*/ 2, mFenceSignaled))); +} + +TEST_F(TransactionApplicationTest, Flush_RemovesSignaledFromTheQueue_LatchUnsignaled_Auto) { + SurfaceFlinger::enableLatchUnsignaledConfig = LatchUnsignaledConfig::Auto; + Flush_removesSignaledFromTheQueue(createComposerStateVector( + createComposerState(/*layerId*/ 1, mFenceSignaled)), + createComposerStateVector( + createComposerState(/*layerId*/ 2, mFenceSignaled2))); +} + +TEST_F(TransactionApplicationTest, Flush_RemoveSignaledWithUnsignaledIntact_LatchUnsignaled_Auto) { + SurfaceFlinger::enableLatchUnsignaledConfig = LatchUnsignaledConfig::Auto; + Flush_KeepsUnsignaledInTheQueue(createComposerStateVector( + createComposerState(/*layerId*/ 1, mFenceSignaled)), + createComposerStateVector( + createComposerState(/*layerId*/ 2, mFenceUnsignaled))); + EXPECT_EQ(1ul, mFlinger.getTransactionCommittedSignals().size()); +} + +TEST_F(TransactionApplicationTest, + Flush_KeepsTransactionInTheQueueSameApplyToken_LatchUnsignaled_Auto) { + SurfaceFlinger::enableLatchUnsignaledConfig = LatchUnsignaledConfig::Auto; + Flush_KeepsUnsignaledInTheQueue(createComposerStateVector( + createComposerState(/*layerId*/ 1, mFenceUnsignaled)), + createComposerStateVector( + createComposerState(/*layerId*/ 2, mFenceSignaled)), + /*updateApplyToken*/ false); + EXPECT_EQ(1ul, mFlinger.getTransactionCommittedSignals().size()); +} + +TEST_F(TransactionApplicationTest, Flush_KeepsTransactionInTheQueue_LatchUnsignaled_Auto) { + SurfaceFlinger::enableLatchUnsignaledConfig = LatchUnsignaledConfig::Auto; + Flush_KeepsUnsignaledInTheQueue(createComposerStateVector( + createComposerState(/*layerId*/ 1, mFenceUnsignaled)), + createComposerStateVector( + createComposerState(/*layerId*/ 2, mFenceUnsignaled)), + /*updateApplyToken*/ true, + /*pendingTransactionQueueSize*/ 2u); + EXPECT_EQ(0ul, mFlinger.getTransactionCommittedSignals().size()); +} + +TEST_F(TransactionApplicationTest, Flush_RemovesSignaledFromTheQueue_LatchUnsignaled_Disabled) { + SurfaceFlinger::enableLatchUnsignaledConfig = LatchUnsignaledConfig::Disabled; + Flush_removesFromTheQueue( + createComposerStateVector(createComposerState(/*layerId*/ 1, mFenceSignaled))); +} + +TEST_F(TransactionApplicationTest, Flush_KeepsInTheQueue_LatchUnsignaled_Disabled) { + SurfaceFlinger::enableLatchUnsignaledConfig = LatchUnsignaledConfig::Disabled; + Flush_keepsInTheQueue( + createComposerStateVector(createComposerState(/*layerId*/ 1, mFenceUnsignaled))); +} + +TEST_F(TransactionApplicationTest, Flush_KeepsInTheQueueSameLayerId_LatchUnsignaled_Disabled) { + SurfaceFlinger::enableLatchUnsignaledConfig = LatchUnsignaledConfig::Disabled; + Flush_keepsInTheQueue( + createComposerStateVector(createComposerState(/*layerId*/ 1, mFenceUnsignaled), + createComposerState(/*layerId*/ 1, mFenceUnsignaled))); +} + +TEST_F(TransactionApplicationTest, Flush_KeepsInTheQueueDifferentLayerId_LatchUnsignaled_Disabled) { + SurfaceFlinger::enableLatchUnsignaledConfig = LatchUnsignaledConfig::Disabled; + Flush_keepsInTheQueue( + createComposerStateVector(createComposerState(/*layerId*/ 1, mFenceUnsignaled), + createComposerState(/*layerId*/ 2, mFenceUnsignaled))); +} + +TEST_F(TransactionApplicationTest, Flush_RemovesSignaledFromTheQueue_LatchUnSignaled_Disabled) { + SurfaceFlinger::enableLatchUnsignaledConfig = LatchUnsignaledConfig::Disabled; + Flush_removesSignaledFromTheQueue(createComposerStateVector( + createComposerState(/*layerId*/ 1, mFenceSignaled)), + createComposerStateVector( + createComposerState(/*layerId*/ 2, mFenceSignaled2))); +} + +TEST_F(TransactionApplicationTest, + Flush_KeepInTheQueueDifferentApplyToken_LatchUnsignaled_Disabled) { + SurfaceFlinger::enableLatchUnsignaledConfig = LatchUnsignaledConfig::Disabled; + Flush_KeepsUnsignaledInTheQueue(createComposerStateVector( + createComposerState(/*layerId*/ 1, mFenceUnsignaled)), + createComposerStateVector( + createComposerState(/*layerId*/ 2, mFenceSignaled))); + EXPECT_EQ(1ul, mFlinger.getTransactionCommittedSignals().size()); +} + +TEST_F(TransactionApplicationTest, Flush_KeepInTheQueueSameApplyToken_LatchUnsignaled_Disabled) { + SurfaceFlinger::enableLatchUnsignaledConfig = LatchUnsignaledConfig::Disabled; + Flush_KeepsUnsignaledInTheQueue(createComposerStateVector( + createComposerState(/*layerId*/ 1, mFenceSignaled)), + createComposerStateVector( + createComposerState(/*layerId*/ 2, mFenceUnsignaled)), + /*updateApplyToken*/ false); + EXPECT_EQ(1ul, mFlinger.getTransactionCommittedSignals().size()); +} + +TEST_F(TransactionApplicationTest, Flush_KeepInTheUnsignaledTheQueue_LatchUnsignaled_Disabled) { + SurfaceFlinger::enableLatchUnsignaledConfig = LatchUnsignaledConfig::Disabled; + Flush_KeepsUnsignaledInTheQueue(createComposerStateVector( + createComposerState(/*layerId*/ 1, mFenceUnsignaled)), + createComposerStateVector( + createComposerState(/*layerId*/ 2, mFenceUnsignaled)), + /*updateApplyToken*/ false); + EXPECT_EQ(0ul, mFlinger.getTransactionCommittedSignals().size()); +} + +TEST_F(TransactionApplicationTest, Flush_RemovesSignaledFromTheQueue_LatchUnsignaled_Always) { + SurfaceFlinger::enableLatchUnsignaledConfig = LatchUnsignaledConfig::Always; + Flush_removesFromTheQueue( + createComposerStateVector(createComposerState(/*layerId*/ 1, mFenceSignaled))); +} + +TEST_F(TransactionApplicationTest, Flush_RemovesFromTheQueue_LatchUnsignaled_Always) { + SurfaceFlinger::enableLatchUnsignaledConfig = LatchUnsignaledConfig::Always; + Flush_removesFromTheQueue( + createComposerStateVector(createComposerState(/*layerId*/ 1, mFenceUnsignaled))); +} + +TEST_F(TransactionApplicationTest, Flush_RemovesFromTheQueueSameLayerId_LatchUnsignaled_Always) { + SurfaceFlinger::enableLatchUnsignaledConfig = LatchUnsignaledConfig::Always; + Flush_removesFromTheQueue( + createComposerStateVector(createComposerState(/*layerId*/ 1, mFenceUnsignaled), + createComposerState(/*layerId*/ 1, mFenceSignaled))); +} + +TEST_F(TransactionApplicationTest, + Flush_RemovesFromTheQueueDifferentLayerId_LatchUnsignaled_Always) { + SurfaceFlinger::enableLatchUnsignaledConfig = LatchUnsignaledConfig::Always; + Flush_removesFromTheQueue( + createComposerStateVector(createComposerState(/*layerId*/ 1, mFenceUnsignaled), + createComposerState(/*layerId*/ 2, mFenceSignaled))); +} + +TEST_F(TransactionApplicationTest, Flush_RemovesSignaledFromTheQueue_LatchUnSignaled_Always) { + SurfaceFlinger::enableLatchUnsignaledConfig = LatchUnsignaledConfig::Always; + Flush_removesSignaledFromTheQueue(createComposerStateVector( + createComposerState(/*layerId*/ 1, mFenceSignaled)), + createComposerStateVector( + createComposerState(/*layerId*/ 2, mFenceSignaled2))); +} + +TEST_F(TransactionApplicationTest, + Flush_RemovesFromTheQueueDifferentApplyToken_LatchUnsignaled_Always) { + SurfaceFlinger::enableLatchUnsignaledConfig = LatchUnsignaledConfig::Always; + Flush_removesUnsignaledFromTheQueue(createComposerStateVector( + createComposerState(/*layerId*/ 1, mFenceSignaled)), + createComposerStateVector( + createComposerState(/*layerId*/ 2, + mFenceUnsignaled))); +} + +TEST_F(TransactionApplicationTest, + Flush_RemovesUnsignaledFromTheQueueSameApplyToken_LatchUnsignaled_Always) { + SurfaceFlinger::enableLatchUnsignaledConfig = LatchUnsignaledConfig::Always; + Flush_removesUnsignaledFromTheQueue(createComposerStateVector( + createComposerState(/*layerId*/ 1, + mFenceUnsignaled)), + createComposerStateVector( + createComposerState(/*layerId*/ 2, mFenceSignaled)), + /*updateApplyToken*/ false); +} + +TEST_F(TransactionApplicationTest, Flush_RemovesUnsignaledFromTheQueue_LatchUnsignaled_Always) { + SurfaceFlinger::enableLatchUnsignaledConfig = LatchUnsignaledConfig::Always; + Flush_removesUnsignaledFromTheQueue(createComposerStateVector( + createComposerState(/*layerId*/ 1, + mFenceUnsignaled)), + createComposerStateVector( + createComposerState(/*layerId*/ 2, + mFenceUnsignaled))); +} + } // namespace android -- cgit v1.2.3-59-g8ed1b From 86653e9e2caae7ee5295d36a85e1d5b098751bbc Mon Sep 17 00:00:00 2001 From: Vishnu Nair Date: Wed, 3 Nov 2021 17:19:36 -0700 Subject: SF: Add autorefresh to drawingstate Autorefresh does not need to be an atomic variable. It is only accessed from the main thread. Move it to drawing state so it can be accessed from the base Layer class when creating the starting state. Test: presubmit Bug: 200284593 Change-Id: I52a00c4185a3a883e4d5cf850257bb3a098b4d22 --- services/surfaceflinger/BufferLayer.h | 3 +-- services/surfaceflinger/BufferQueueLayer.cpp | 4 ++-- services/surfaceflinger/BufferStateLayer.cpp | 4 +--- services/surfaceflinger/Layer.h | 2 ++ 4 files changed, 6 insertions(+), 7 deletions(-) (limited to 'services/surfaceflinger/BufferQueueLayer.cpp') diff --git a/services/surfaceflinger/BufferLayer.h b/services/surfaceflinger/BufferLayer.h index 8c4c8b7a78..a4c21f4caf 100644 --- a/services/surfaceflinger/BufferLayer.h +++ b/services/surfaceflinger/BufferLayer.h @@ -171,7 +171,7 @@ protected: // the mStateLock. ui::Transform::RotationFlags mTransformHint = ui::Transform::ROT_0; - bool getAutoRefresh() const { return mAutoRefresh; } + bool getAutoRefresh() const { return mDrawingState.autoRefresh; } bool getSidebandStreamChanged() const { return mSidebandStreamChanged; } // Returns true if the next buffer should be presented at the expected present time @@ -182,7 +182,6 @@ protected: // specific logic virtual bool isBufferDue(nsecs_t /*expectedPresentTime*/) const = 0; - std::atomic mAutoRefresh{false}; std::atomic mSidebandStreamChanged{false}; private: diff --git a/services/surfaceflinger/BufferQueueLayer.cpp b/services/surfaceflinger/BufferQueueLayer.cpp index 8aecec131f..28c387e5bd 100644 --- a/services/surfaceflinger/BufferQueueLayer.cpp +++ b/services/surfaceflinger/BufferQueueLayer.cpp @@ -216,7 +216,7 @@ status_t BufferQueueLayer::updateTexImage(bool& recomputeVisibleRegions, nsecs_t bool autoRefresh; status_t updateResult = mConsumer->updateTexImage(&r, expectedPresentTime, &autoRefresh, &queuedBuffer, maxFrameNumberToAcquire); - mAutoRefresh = autoRefresh; + mDrawingState.autoRefresh = autoRefresh; if (updateResult == BufferQueue::PRESENT_LATER) { // Producer doesn't want buffer to be displayed yet. Signal a // layer update so we check again at the next opportunity. @@ -300,7 +300,7 @@ status_t BufferQueueLayer::updateTexImage(bool& recomputeVisibleRegions, nsecs_t // Decrement the queued-frames count. Signal another event if we // have more frames pending. - if ((queuedBuffer && more_frames_pending) || mAutoRefresh) { + if ((queuedBuffer && more_frames_pending) || mDrawingState.autoRefresh) { mFlinger->onLayerUpdate(); } diff --git a/services/surfaceflinger/BufferStateLayer.cpp b/services/surfaceflinger/BufferStateLayer.cpp index f7f96ab1b1..4f0bbd243b 100644 --- a/services/surfaceflinger/BufferStateLayer.cpp +++ b/services/surfaceflinger/BufferStateLayer.cpp @@ -660,9 +660,7 @@ bool BufferStateLayer::onPreComposition(nsecs_t refreshStartTime) { } void BufferStateLayer::setAutoRefresh(bool autoRefresh) { - if (!mAutoRefresh.exchange(autoRefresh)) { - mFlinger->onLayerUpdate(); - } + mDrawingState.autoRefresh = autoRefresh; } bool BufferStateLayer::latchSidebandStream(bool& recomputeVisibleRegions) { diff --git a/services/surfaceflinger/Layer.h b/services/surfaceflinger/Layer.h index bf338c18ad..297ded043f 100644 --- a/services/surfaceflinger/Layer.h +++ b/services/surfaceflinger/Layer.h @@ -280,6 +280,8 @@ public: sp releaseBufferEndpoint; gui::DropInputMode dropInputMode; + + bool autoRefresh = false; }; /* -- cgit v1.2.3-59-g8ed1b From 7fb9e5a047292114552ba6523bd790269b6cf937 Mon Sep 17 00:00:00 2001 From: Vishnu Nair Date: Mon, 8 Nov 2021 12:44:05 -0800 Subject: SF: Create layers with layerid When recreating layer states from transaction traces we need to create layers with a specific layer id. Add the layer id as part of LayerCreationArgs and pass the struct around instead of individual args. Test: presubmit Bug: 200284593 Change-Id: I029cdb5362d1926deaf2ce64f70a1882a418705b --- services/surfaceflinger/BufferQueueLayer.cpp | 2 +- services/surfaceflinger/BufferQueueLayer.h | 5 + services/surfaceflinger/BufferStateLayer.cpp | 2 +- services/surfaceflinger/Client.cpp | 45 +++---- services/surfaceflinger/ContainerLayer.cpp | 3 +- services/surfaceflinger/EffectLayer.cpp | 3 +- services/surfaceflinger/Layer.cpp | 15 +-- services/surfaceflinger/Layer.h | 10 +- services/surfaceflinger/LayerRenderArea.cpp | 4 +- services/surfaceflinger/MonitoredProducer.cpp | 8 +- services/surfaceflinger/SurfaceFlinger.cpp | 132 +++++---------------- services/surfaceflinger/SurfaceFlinger.h | 44 ++----- .../tests/SurfaceInterceptor_test.cpp | 4 +- .../tests/unittests/CompositionTest.cpp | 5 +- .../tests/unittests/FpsReporterTest.cpp | 3 +- .../tests/unittests/GameModeTest.cpp | 2 +- .../tests/unittests/RefreshRateSelectionTest.cpp | 7 +- .../tests/unittests/SetFrameRateTest.cpp | 6 +- .../tests/unittests/TransactionFrameTracerTest.cpp | 2 +- .../unittests/TransactionSurfaceFrameTest.cpp | 2 +- .../unittests/TunnelModeEnabledReporterTest.cpp | 3 +- .../tests/unittests/mock/MockLayer.h | 2 +- 22 files changed, 99 insertions(+), 210 deletions(-) (limited to 'services/surfaceflinger/BufferQueueLayer.cpp') diff --git a/services/surfaceflinger/BufferQueueLayer.cpp b/services/surfaceflinger/BufferQueueLayer.cpp index 28c387e5bd..dec7cc0806 100644 --- a/services/surfaceflinger/BufferQueueLayer.cpp +++ b/services/surfaceflinger/BufferQueueLayer.cpp @@ -523,7 +523,7 @@ void BufferQueueLayer::gatherBufferInfo() { } sp BufferQueueLayer::createClone() { - LayerCreationArgs args(mFlinger.get(), nullptr, mName + " (Mirror)", 0, 0, 0, LayerMetadata()); + LayerCreationArgs args(mFlinger.get(), nullptr, mName + " (Mirror)", 0, LayerMetadata()); args.textureName = mTextureName; sp layer = mFlinger->getFactory().createBufferQueueLayer(args); layer->setInitialValuesForClone(this); diff --git a/services/surfaceflinger/BufferQueueLayer.h b/services/surfaceflinger/BufferQueueLayer.h index dfdb5c055d..c6e0727806 100644 --- a/services/surfaceflinger/BufferQueueLayer.h +++ b/services/surfaceflinger/BufferQueueLayer.h @@ -62,6 +62,11 @@ public: status_t setDefaultBufferProperties(uint32_t w, uint32_t h, PixelFormat format); sp getProducer() const; + void setSizeForTest(uint32_t w, uint32_t h) { + mDrawingState.active_legacy.w = w; + mDrawingState.active_legacy.h = h; + } + protected: void gatherBufferInfo() override; diff --git a/services/surfaceflinger/BufferStateLayer.cpp b/services/surfaceflinger/BufferStateLayer.cpp index b6cbbb658f..88e3fb6744 100644 --- a/services/surfaceflinger/BufferStateLayer.cpp +++ b/services/surfaceflinger/BufferStateLayer.cpp @@ -890,7 +890,7 @@ Rect BufferStateLayer::computeBufferCrop(const State& s) { } sp BufferStateLayer::createClone() { - LayerCreationArgs args(mFlinger.get(), nullptr, mName + " (Mirror)", 0, 0, 0, LayerMetadata()); + LayerCreationArgs args(mFlinger.get(), nullptr, mName + " (Mirror)", 0, LayerMetadata()); args.textureName = mTextureName; sp layer = mFlinger->getFactory().createBufferStateLayer(args); layer->mHwcSlotGenerator = mHwcSlotGenerator; diff --git a/services/surfaceflinger/Client.cpp b/services/surfaceflinger/Client.cpp index 8da2e24aa4..0a8ebec9f3 100644 --- a/services/surfaceflinger/Client.cpp +++ b/services/surfaceflinger/Client.cpp @@ -72,35 +72,28 @@ sp Client::getLayerUser(const sp& handle) const return lbc; } -status_t Client::createSurface(const String8& name, uint32_t w, uint32_t h, PixelFormat format, - uint32_t flags, const sp& parentHandle, - LayerMetadata metadata, sp* handle, - sp* gbp, int32_t* outLayerId, - uint32_t* outTransformHint) { +status_t Client::createSurface(const String8& name, uint32_t /* w */, uint32_t /* h */, + PixelFormat /* format */, uint32_t flags, + const sp& parentHandle, LayerMetadata metadata, + sp* outHandle, sp* /* gbp */, + int32_t* outLayerId, uint32_t* outTransformHint) { // We rely on createLayer to check permissions. - return mFlinger->createLayer(name, this, w, h, format, flags, std::move(metadata), handle, gbp, - parentHandle, outLayerId, nullptr, outTransformHint); + LayerCreationArgs args(mFlinger.get(), this, name.c_str(), flags, std::move(metadata)); + return mFlinger->createLayer(args, outHandle, parentHandle, outLayerId, nullptr, + outTransformHint); } -status_t Client::createWithSurfaceParent(const String8& name, uint32_t w, uint32_t h, - PixelFormat format, uint32_t flags, - const sp& parent, - LayerMetadata metadata, sp* handle, - sp* gbp, int32_t* outLayerId, - uint32_t* outTransformHint) { - if (mFlinger->authenticateSurfaceTexture(parent) == false) { - ALOGE("failed to authenticate surface texture"); - return BAD_VALUE; - } - - const auto& layer = (static_cast(parent.get()))->getLayer(); - if (layer == nullptr) { - ALOGE("failed to find parent layer"); - return BAD_VALUE; - } - - return mFlinger->createLayer(name, this, w, h, format, flags, std::move(metadata), handle, gbp, - nullptr, outLayerId, layer, outTransformHint); +status_t Client::createWithSurfaceParent(const String8& /* name */, uint32_t /* w */, + uint32_t /* h */, PixelFormat /* format */, + uint32_t /* flags */, + const sp& /* parent */, + LayerMetadata /* metadata */, sp* /* handle */, + sp* /* gbp */, + int32_t* /* outLayerId */, + uint32_t* /* outTransformHint */) { + // This api does not make sense with blast since SF no longer tracks IGBP. This api should be + // removed. + return BAD_VALUE; } status_t Client::mirrorSurface(const sp& mirrorFromHandle, sp* outHandle, diff --git a/services/surfaceflinger/ContainerLayer.cpp b/services/surfaceflinger/ContainerLayer.cpp index 841e79f8af..3ccc229261 100644 --- a/services/surfaceflinger/ContainerLayer.cpp +++ b/services/surfaceflinger/ContainerLayer.cpp @@ -36,8 +36,7 @@ bool ContainerLayer::isVisible() const { sp ContainerLayer::createClone() { sp layer = mFlinger->getFactory().createContainerLayer( - LayerCreationArgs(mFlinger.get(), nullptr, mName + " (Mirror)", 0, 0, 0, - LayerMetadata())); + LayerCreationArgs(mFlinger.get(), nullptr, mName + " (Mirror)", 0, LayerMetadata())); layer->setInitialValuesForClone(this); return layer; } diff --git a/services/surfaceflinger/EffectLayer.cpp b/services/surfaceflinger/EffectLayer.cpp index 86c6b2161c..845176c112 100644 --- a/services/surfaceflinger/EffectLayer.cpp +++ b/services/surfaceflinger/EffectLayer.cpp @@ -136,8 +136,7 @@ ui::Dataspace EffectLayer::getDataSpace() const { sp EffectLayer::createClone() { sp layer = mFlinger->getFactory().createEffectLayer( - LayerCreationArgs(mFlinger.get(), nullptr, mName + " (Mirror)", 0, 0, 0, - LayerMetadata())); + LayerCreationArgs(mFlinger.get(), nullptr, mName + " (Mirror)", 0, LayerMetadata())); layer->setInitialValuesForClone(this); return layer; } diff --git a/services/surfaceflinger/Layer.cpp b/services/surfaceflinger/Layer.cpp index d85e843d83..3d189d681b 100644 --- a/services/surfaceflinger/Layer.cpp +++ b/services/surfaceflinger/Layer.cpp @@ -87,11 +87,12 @@ using gui::WindowInfo; std::atomic Layer::sSequence{1}; Layer::Layer(const LayerCreationArgs& args) - : mFlinger(args.flinger), + : sequence(args.sequence.value_or(sSequence++)), + mFlinger(args.flinger), mName(base::StringPrintf("%s#%d", args.name.c_str(), sequence)), mClientRef(args.client), - mWindowType( - static_cast(args.metadata.getInt32(METADATA_WINDOW_TYPE, 0))) { + mWindowType(static_cast(args.metadata.getInt32(METADATA_WINDOW_TYPE, 0))), + mLayerCreationFlags(args.flags) { uint32_t layerFlags = 0; if (args.flags & ISurfaceComposerClient::eHidden) layerFlags |= layer_state_t::eLayerHidden; if (args.flags & ISurfaceComposerClient::eOpaque) layerFlags |= layer_state_t::eLayerOpaque; @@ -99,8 +100,6 @@ Layer::Layer(const LayerCreationArgs& args) if (args.flags & ISurfaceComposerClient::eSkipScreenshot) layerFlags |= layer_state_t::eLayerSkipScreenshot; - mDrawingState.active_legacy.w = args.w; - mDrawingState.active_legacy.h = args.h; mDrawingState.flags = layerFlags; mDrawingState.active_legacy.transform.set(0, 0); mDrawingState.crop.makeInvalid(); @@ -185,12 +184,10 @@ Layer::~Layer() { } LayerCreationArgs::LayerCreationArgs(SurfaceFlinger* flinger, sp client, std::string name, - uint32_t w, uint32_t h, uint32_t flags, LayerMetadata metadata) + uint32_t flags, LayerMetadata metadata) : flinger(flinger), client(std::move(client)), name(std::move(name)), - w(w), - h(h), flags(flags), metadata(std::move(metadata)) { IPCThreadState* ipc = IPCThreadState::self(); @@ -887,7 +884,7 @@ bool Layer::setBackgroundColor(const half3& color, float alpha, ui::Dataspace da uint32_t flags = ISurfaceComposerClient::eFXSurfaceEffect; std::string name = mName + "BackgroundColorLayer"; mDrawingState.bgColorLayer = mFlinger->getFactory().createEffectLayer( - LayerCreationArgs(mFlinger.get(), nullptr, std::move(name), 0, 0, flags, + LayerCreationArgs(mFlinger.get(), nullptr, std::move(name), flags, LayerMetadata())); // add to child list diff --git a/services/surfaceflinger/Layer.h b/services/surfaceflinger/Layer.h index b79903d11b..3da07e824d 100644 --- a/services/surfaceflinger/Layer.h +++ b/services/surfaceflinger/Layer.h @@ -85,20 +85,18 @@ class SurfaceFrame; } // namespace frametimeline struct LayerCreationArgs { - LayerCreationArgs(SurfaceFlinger*, sp, std::string name, uint32_t w, uint32_t h, - uint32_t flags, LayerMetadata); + LayerCreationArgs(SurfaceFlinger*, sp, std::string name, uint32_t flags, LayerMetadata); SurfaceFlinger* flinger; const sp client; std::string name; - uint32_t w; - uint32_t h; uint32_t flags; LayerMetadata metadata; pid_t callingPid; uid_t callingUid; uint32_t textureName; + std::optional sequence = std::nullopt; }; class Layer : public virtual RefBase, compositionengine::LayerFE { @@ -879,7 +877,7 @@ public: // Layer serial number. This gives layers an explicit ordering, so we // have a stable sort order when their layer stack and Z-order are // the same. - int32_t sequence{sSequence++}; + const int32_t sequence; bool mPendingHWCDestroy{false}; @@ -1117,6 +1115,8 @@ private: const std::vector getBlurRegions() const; bool mIsAtRoot = false; + + uint32_t mLayerCreationFlags; }; std::ostream& operator<<(std::ostream& stream, const Layer::FrameRate& rate); diff --git a/services/surfaceflinger/LayerRenderArea.cpp b/services/surfaceflinger/LayerRenderArea.cpp index 11fe6d0755..a1e14559e9 100644 --- a/services/surfaceflinger/LayerRenderArea.cpp +++ b/services/surfaceflinger/LayerRenderArea.cpp @@ -112,12 +112,10 @@ void LayerRenderArea::render(std::function drawLayers) { } drawLayers(); } else { - uint32_t w = static_cast(getWidth()); - uint32_t h = static_cast(getHeight()); // In the "childrenOnly" case we reparent the children to a screenshot // layer which has no properties set and which does not draw. sp screenshotParentLayer = mFlinger.getFactory().createContainerLayer( - {&mFlinger, nullptr, "Screenshot Parent"s, w, h, 0, LayerMetadata()}); + {&mFlinger, nullptr, "Screenshot Parent"s, 0, LayerMetadata()}); ReparentForDrawing reparent(mLayer, screenshotParentLayer, sourceCrop); drawLayers(); diff --git a/services/surfaceflinger/MonitoredProducer.cpp b/services/surfaceflinger/MonitoredProducer.cpp index 6b2d745998..df76f50112 100644 --- a/services/surfaceflinger/MonitoredProducer.cpp +++ b/services/surfaceflinger/MonitoredProducer.cpp @@ -33,13 +33,7 @@ MonitoredProducer::MonitoredProducer(const sp& producer, mFlinger(flinger), mLayer(layer) {} -MonitoredProducer::~MonitoredProducer() { - // Remove ourselves from SurfaceFlinger's list. We do this asynchronously - // because we don't know where this destructor is called from. It could be - // called with the mStateLock held, leading to a dead-lock (it actually - // happens). - mFlinger->removeGraphicBufferProducerAsync(onAsBinder()); -} +MonitoredProducer::~MonitoredProducer() {} status_t MonitoredProducer::requestBuffer(int slot, sp* buf) { return mProducer->requestBuffer(slot, buf); diff --git a/services/surfaceflinger/SurfaceFlinger.cpp b/services/surfaceflinger/SurfaceFlinger.cpp index c2dcd70166..5a6a8ce05a 100644 --- a/services/surfaceflinger/SurfaceFlinger.cpp +++ b/services/surfaceflinger/SurfaceFlinger.cpp @@ -904,9 +904,8 @@ bool SurfaceFlinger::authenticateSurfaceTexture( } bool SurfaceFlinger::authenticateSurfaceTextureLocked( - const sp& bufferProducer) const { - sp surfaceTextureBinder(IInterface::asBinder(bufferProducer)); - return mGraphicBufferProducerList.count(surfaceTextureBinder.get()) > 0; + const sp& /* bufferProducer */) const { + return false; } status_t SurfaceFlinger::getSupportedFrameTimestamps( @@ -3355,20 +3354,15 @@ bool SurfaceFlinger::latchBuffers() { } status_t SurfaceFlinger::addClientLayer(const sp& client, const sp& handle, - const sp& gbc, const sp& lbc, - const wp& parent, bool addToRoot, - uint32_t* outTransformHint) { + const sp& lbc, const wp& parent, + bool addToRoot, uint32_t* outTransformHint) { if (mNumLayers >= ISurfaceComposer::MAX_LAYERS) { ALOGE("AddClientLayer failed, mNumLayers (%zu) >= MAX_LAYERS (%zu)", mNumLayers.load(), ISurfaceComposer::MAX_LAYERS); return NO_MEMORY; } - wp initialProducer; - if (gbc != nullptr) { - initialProducer = IInterface::asBinder(gbc); - } - setLayerCreatedState(handle, lbc, parent, initialProducer, addToRoot); + setLayerCreatedState(handle, lbc, parent, addToRoot); // Create a transaction includes the initial parent and producer. Vector states; @@ -3384,7 +3378,9 @@ status_t SurfaceFlinger::addClientLayer(const sp& client, const spattachLayer(handle, lbc); + if (client != nullptr) { + client->attachLayer(handle, lbc); + } return setTransactionState(FrameTimelineInfo{}, states, displays, 0 /* flags */, nullptr, InputWindowCommands{}, -1 /* desiredPresentTime */, @@ -3392,13 +3388,6 @@ status_t SurfaceFlinger::addClientLayer(const sp& client, const sp& binder) { - static_cast(schedule([=] { - Mutex::Autolock lock(mStateLock); - mGraphicBufferProducerList.erase(binder); - })); -} - uint32_t SurfaceFlinger::getTransactionFlags() const { return mTransactionFlags; } @@ -4281,17 +4270,14 @@ status_t SurfaceFlinger::mirrorLayer(const sp& client, const sp sp mirrorLayer; sp mirrorFrom; - std::string layerName = "MirrorRoot"; - { Mutex::Autolock _l(mStateLock); mirrorFrom = fromHandle(mirrorFromHandle).promote(); if (!mirrorFrom) { return NAME_NOT_FOUND; } - - status_t result = createContainerLayer(client, std::move(layerName), -1, -1, 0, - LayerMetadata(), outHandle, &mirrorLayer); + LayerCreationArgs args(this, client, "MirrorRoot", 0, LayerMetadata()); + status_t result = createContainerLayer(args, outHandle, &mirrorLayer); if (result != NO_ERROR) { return result; } @@ -4300,22 +4286,13 @@ status_t SurfaceFlinger::mirrorLayer(const sp& client, const sp } *outLayerId = mirrorLayer->sequence; - return addClientLayer(client, *outHandle, nullptr, mirrorLayer, nullptr, false, - nullptr /* outTransformHint */); + return addClientLayer(client, *outHandle, mirrorLayer /* layer */, nullptr /* parent */, + false /* addAsRoot */, nullptr /* outTransformHint */); } -status_t SurfaceFlinger::createLayer(const String8& name, const sp& client, uint32_t w, - uint32_t h, PixelFormat format, uint32_t flags, - LayerMetadata metadata, sp* handle, - sp* gbp, +status_t SurfaceFlinger::createLayer(LayerCreationArgs& args, sp* outHandle, const sp& parentHandle, int32_t* outLayerId, const sp& parentLayer, uint32_t* outTransformHint) { - if (int32_t(w|h) < 0) { - ALOGE("createLayer() failed, w or h is negative (w=%d, h=%d)", - int(w), int(h)); - return BAD_VALUE; - } - ALOG_ASSERT(parentLayer == nullptr || parentHandle == nullptr, "Expected only one of parentLayer or parentHandle to be non-null. " "Programmer error?"); @@ -4324,40 +4301,22 @@ status_t SurfaceFlinger::createLayer(const String8& name, const sp& clie sp layer; - std::string layerName{name.string()}; - - switch (flags & ISurfaceComposerClient::eFXSurfaceMask) { + switch (args.flags & ISurfaceComposerClient::eFXSurfaceMask) { case ISurfaceComposerClient::eFXSurfaceBufferQueue: case ISurfaceComposerClient::eFXSurfaceBufferState: { - result = createBufferStateLayer(client, std::move(layerName), w, h, flags, - std::move(metadata), handle, &layer); + result = createBufferStateLayer(args, outHandle, &layer); std::atomic* pendingBufferCounter = layer->getPendingBufferCounter(); if (pendingBufferCounter) { std::string counterName = layer->getPendingBufferCounterName(); - mBufferCountTracker.add((*handle)->localBinder(), counterName, + mBufferCountTracker.add((*outHandle)->localBinder(), counterName, pendingBufferCounter); } } break; case ISurfaceComposerClient::eFXSurfaceEffect: - // check if buffer size is set for color layer. - if (w > 0 || h > 0) { - ALOGE("createLayer() failed, w or h cannot be set for color layer (w=%d, h=%d)", - int(w), int(h)); - return BAD_VALUE; - } - - result = createEffectLayer(client, std::move(layerName), w, h, flags, - std::move(metadata), handle, &layer); + result = createEffectLayer(args, outHandle, &layer); break; case ISurfaceComposerClient::eFXSurfaceContainer: - // check if buffer size is set for container layer. - if (w > 0 || h > 0) { - ALOGE("createLayer() failed, w or h cannot be set for container layer (w=%d, h=%d)", - int(w), int(h)); - return BAD_VALUE; - } - result = createContainerLayer(client, std::move(layerName), w, h, flags, - std::move(metadata), handle, &layer); + result = createContainerLayer(args, outHandle, &layer); break; default: result = BAD_VALUE; @@ -4377,7 +4336,7 @@ status_t SurfaceFlinger::createLayer(const String8& name, const sp& clie if (parentLayer != nullptr) { addToRoot = false; } - result = addClientLayer(client, *handle, *gbp, layer, parent, addToRoot, outTransformHint); + result = addClientLayer(args.client, *outHandle, layer, parent, addToRoot, outTransformHint); if (result != NO_ERROR) { return result; } @@ -4387,9 +4346,7 @@ status_t SurfaceFlinger::createLayer(const String8& name, const sp& clie return result; } -status_t SurfaceFlinger::createBufferQueueLayer(const sp& client, std::string name, - uint32_t w, uint32_t h, uint32_t flags, - LayerMetadata metadata, PixelFormat& format, +status_t SurfaceFlinger::createBufferQueueLayer(LayerCreationArgs& args, PixelFormat& format, sp* handle, sp* gbp, sp* outLayer) { @@ -4405,7 +4362,6 @@ status_t SurfaceFlinger::createBufferQueueLayer(const sp& client, std::s } sp layer; - LayerCreationArgs args(this, client, std::move(name), w, h, flags, std::move(metadata)); args.textureName = getNewTexture(); { // Grab the SF state lock during this since it's the only safe way to access @@ -4415,7 +4371,7 @@ status_t SurfaceFlinger::createBufferQueueLayer(const sp& client, std::s layer = getFactory().createBufferQueueLayer(args); } - status_t err = layer->setDefaultBufferProperties(w, h, format); + status_t err = layer->setDefaultBufferProperties(0, 0, format); if (err == NO_ERROR) { *handle = layer->getHandle(); *gbp = layer->getProducer(); @@ -4426,34 +4382,24 @@ status_t SurfaceFlinger::createBufferQueueLayer(const sp& client, std::s return err; } -status_t SurfaceFlinger::createBufferStateLayer(const sp& client, std::string name, - uint32_t w, uint32_t h, uint32_t flags, - LayerMetadata metadata, sp* handle, +status_t SurfaceFlinger::createBufferStateLayer(LayerCreationArgs& args, sp* handle, sp* outLayer) { - LayerCreationArgs args(this, client, std::move(name), w, h, flags, std::move(metadata)); args.textureName = getNewTexture(); - sp layer = getFactory().createBufferStateLayer(args); - *handle = layer->getHandle(); - *outLayer = layer; - + *outLayer = getFactory().createBufferStateLayer(args); + *handle = (*outLayer)->getHandle(); return NO_ERROR; } -status_t SurfaceFlinger::createEffectLayer(const sp& client, std::string name, uint32_t w, - uint32_t h, uint32_t flags, LayerMetadata metadata, - sp* handle, sp* outLayer) { - *outLayer = getFactory().createEffectLayer( - {this, client, std::move(name), w, h, flags, std::move(metadata)}); +status_t SurfaceFlinger::createEffectLayer(LayerCreationArgs& args, sp* handle, + sp* outLayer) { + *outLayer = getFactory().createEffectLayer(args); *handle = (*outLayer)->getHandle(); return NO_ERROR; } -status_t SurfaceFlinger::createContainerLayer(const sp& client, std::string name, - uint32_t w, uint32_t h, uint32_t flags, - LayerMetadata metadata, sp* handle, +status_t SurfaceFlinger::createContainerLayer(LayerCreationArgs& args, sp* handle, sp* outLayer) { - *outLayer = getFactory().createContainerLayer( - {this, client, std::move(name), w, h, flags, std::move(metadata)}); + *outLayer = getFactory().createContainerLayer(args); *handle = (*outLayer)->getHandle(); return NO_ERROR; } @@ -5039,8 +4985,6 @@ void SurfaceFlinger::dumpAllLocked(const DumpArgs& args, std::string& result) co */ colorizer.bold(result); StringAppendF(&result, "Visible layers (count = %zu)\n", mNumLayers.load()); - StringAppendF(&result, "GraphicBufferProducers: %zu, max %zu\n", - mGraphicBufferProducerList.size(), mMaxGraphicBufferProducerListSize); colorizer.reset(result); { @@ -6802,11 +6746,10 @@ void TransactionState::traverseStatesWithBuffers( } void SurfaceFlinger::setLayerCreatedState(const sp& handle, const wp& layer, - const wp parent, const wp& producer, - bool addToRoot) { + const wp parent, bool addToRoot) { Mutex::Autolock lock(mCreatedLayersLock); mCreatedLayers[handle->localBinder()] = - std::make_unique(layer, parent, producer, addToRoot); + std::make_unique(layer, parent, addToRoot); } auto SurfaceFlinger::getLayerCreatedState(const sp& handle) { @@ -6867,19 +6810,6 @@ sp SurfaceFlinger::handleLayerCreatedLocked(const sp& handle) { layer->updateTransformHint(mActiveDisplayTransformHint); - if (state->initialProducer != nullptr) { - mGraphicBufferProducerList.insert(state->initialProducer); - LOG_ALWAYS_FATAL_IF(mGraphicBufferProducerList.size() > mMaxGraphicBufferProducerListSize, - "Suspected IGBP leak: %zu IGBPs (%zu max), %zu Layers", - mGraphicBufferProducerList.size(), mMaxGraphicBufferProducerListSize, - mNumLayers.load()); - if (mGraphicBufferProducerList.size() > mGraphicBufferProducerListSizeLogThreshold) { - ALOGW("Suspected IGBP leak: %zu IGBPs (%zu max), %zu Layers", - mGraphicBufferProducerList.size(), mMaxGraphicBufferProducerListSize, - mNumLayers.load()); - } - } - mInterceptor->saveSurfaceCreation(layer); return layer; } diff --git a/services/surfaceflinger/SurfaceFlinger.h b/services/surfaceflinger/SurfaceFlinger.h index bf628dc309..b432f246c0 100644 --- a/services/surfaceflinger/SurfaceFlinger.h +++ b/services/surfaceflinger/SurfaceFlinger.h @@ -763,29 +763,23 @@ private: /* * Layer management */ - status_t createLayer(const String8& name, const sp& client, uint32_t w, uint32_t h, - PixelFormat format, uint32_t flags, LayerMetadata metadata, - sp* handle, sp* gbp, + status_t createLayer(LayerCreationArgs& args, sp* outHandle, const sp& parentHandle, int32_t* outLayerId, const sp& parentLayer = nullptr, uint32_t* outTransformHint = nullptr); - status_t createBufferQueueLayer(const sp& client, std::string name, uint32_t w, - uint32_t h, uint32_t flags, LayerMetadata metadata, - PixelFormat& format, sp* outHandle, - sp* outGbp, sp* outLayer); + status_t createBufferQueueLayer(LayerCreationArgs& args, PixelFormat& format, + sp* outHandle, sp* outGbp, + sp* outLayer); - status_t createBufferStateLayer(const sp& client, std::string name, uint32_t w, - uint32_t h, uint32_t flags, LayerMetadata metadata, - sp* outHandle, sp* outLayer); + status_t createBufferStateLayer(LayerCreationArgs& args, sp* outHandle, + sp* outLayer); - status_t createEffectLayer(const sp& client, std::string name, uint32_t w, uint32_t h, - uint32_t flags, LayerMetadata metadata, sp* outHandle, + status_t createEffectLayer(LayerCreationArgs& args, sp* outHandle, sp* outLayer); - status_t createContainerLayer(const sp& client, std::string name, uint32_t w, - uint32_t h, uint32_t flags, LayerMetadata metadata, - sp* outHandle, sp* outLayer); + status_t createContainerLayer(LayerCreationArgs& args, sp* outHandle, + sp* outLayer); status_t mirrorLayer(const sp& client, const sp& mirrorFromHandle, sp* outHandle, int32_t* outLayerId); @@ -798,8 +792,7 @@ private: // add a layer to SurfaceFlinger status_t addClientLayer(const sp& client, const sp& handle, - const sp& gbc, const sp& lbc, - const wp& parentLayer, bool addToRoot, + const sp& lbc, const wp& parentLayer, bool addToRoot, uint32_t* outTransformHint); // Traverse through all the layers and compute and cache its bounds. @@ -1115,16 +1108,12 @@ private: float mGlobalSaturationFactor = 1.0f; mat4 mClientColorMatrix; - // Can't be unordered_set because wp<> isn't hashable - std::set> mGraphicBufferProducerList; size_t mMaxGraphicBufferProducerListSize = ISurfaceComposer::MAX_LAYERS; // If there are more GraphicBufferProducers tracked by SurfaceFlinger than // this threshold, then begin logging. size_t mGraphicBufferProducerListSizeLogThreshold = static_cast(0.95 * static_cast(MAX_LAYERS)); - void removeGraphicBufferProducerAsync(const wp&); - // protected by mStateLock (but we could use another lock) bool mLayersRemoved = false; bool mLayersAdded = false; @@ -1339,19 +1328,12 @@ private: GUARDED_BY(mStateLock); mutable Mutex mCreatedLayersLock; struct LayerCreatedState { - LayerCreatedState(const wp& layer, const wp parent, - const wp& producer, bool addToRoot) - : layer(layer), - initialParent(parent), - initialProducer(producer), - addToRoot(addToRoot) {} + LayerCreatedState(const wp& layer, const wp parent, bool addToRoot) + : layer(layer), initialParent(parent), addToRoot(addToRoot) {} wp layer; // Indicates the initial parent of the created layer, only used for creating layer in // SurfaceFlinger. If nullptr, it may add the created layer into the current root layers. wp initialParent; - // Indicates the initial graphic buffer producer of the created layer, only used for - // creating layer in SurfaceFlinger. - wp initialProducer; // Indicates whether the layer getting created should be added at root if there's no parent // and has permission ACCESS_SURFACE_FLINGER. If set to false and no parent, the layer will // be added offscreen. @@ -1362,7 +1344,7 @@ private: // thread. std::unordered_map> mCreatedLayers; void setLayerCreatedState(const sp& handle, const wp& layer, - const wp parent, const wp& producer, bool addToRoot); + const wp parent, bool addToRoot); auto getLayerCreatedState(const sp& handle); sp handleLayerCreatedLocked(const sp& handle) REQUIRES(mStateLock); diff --git a/services/surfaceflinger/tests/SurfaceInterceptor_test.cpp b/services/surfaceflinger/tests/SurfaceInterceptor_test.cpp index 2082c42001..28e8b8c78b 100644 --- a/services/surfaceflinger/tests/SurfaceInterceptor_test.cpp +++ b/services/surfaceflinger/tests/SurfaceInterceptor_test.cpp @@ -754,9 +754,7 @@ void SurfaceInterceptorTest::assertAllUpdatesFound(const Trace& trace) { } bool SurfaceInterceptorTest::surfaceCreationFound(const Increment& increment, bool foundSurface) { - bool isMatch(increment.surface_creation().name() == getUniqueName(LAYER_NAME, increment) && - increment.surface_creation().w() == SIZE_UPDATE && - increment.surface_creation().h() == SIZE_UPDATE); + bool isMatch(increment.surface_creation().name() == getUniqueName(LAYER_NAME, increment)); if (isMatch && !foundSurface) { foundSurface = true; } else if (isMatch && foundSurface) { diff --git a/services/surfaceflinger/tests/unittests/CompositionTest.cpp b/services/surfaceflinger/tests/unittests/CompositionTest.cpp index 40ef6e702d..52d8c35ede 100644 --- a/services/surfaceflinger/tests/unittests/CompositionTest.cpp +++ b/services/surfaceflinger/tests/unittests/CompositionTest.cpp @@ -535,6 +535,7 @@ struct BaseLayerProperties { static void setupLatchedBuffer(CompositionTest* test, sp layer) { // TODO: Eliminate the complexity of actually creating a buffer + layer->setSizeForTest(LayerProperties::WIDTH, LayerProperties::HEIGHT); status_t err = layer->setDefaultBufferProperties(LayerProperties::WIDTH, LayerProperties::HEIGHT, LayerProperties::FORMAT); @@ -901,7 +902,6 @@ struct EffectLayerVariant : public BaseLayerVariant { FlingerLayerType layer = Base::template createLayerWithFactory(test, [test]() { return new EffectLayer( LayerCreationArgs(test->mFlinger.flinger(), sp(), "test-layer", - LayerProperties::WIDTH, LayerProperties::HEIGHT, LayerProperties::LAYER_FLAGS, LayerMetadata())); }); @@ -940,7 +940,6 @@ struct BufferLayerVariant : public BaseLayerVariant { FlingerLayerType layer = Base::template createLayerWithFactory(test, [test]() { LayerCreationArgs args(test->mFlinger.flinger(), sp(), "test-layer", - LayerProperties::WIDTH, LayerProperties::HEIGHT, LayerProperties::LAYER_FLAGS, LayerMetadata()); args.textureName = test->mFlinger.mutableTexturePool().back(); return new BufferQueueLayer(args); @@ -952,7 +951,6 @@ struct BufferLayerVariant : public BaseLayerVariant { } static void cleanupInjectedLayers(CompositionTest* test) { - EXPECT_CALL(*test->mMessageQueue, postMessage(_)).Times(1); Base::cleanupInjectedLayers(test); } @@ -990,7 +988,6 @@ struct ContainerLayerVariant : public BaseLayerVariant { static FlingerLayerType createLayer(CompositionTest* test) { LayerCreationArgs args(test->mFlinger.flinger(), sp(), "test-container-layer", - LayerProperties::WIDTH, LayerProperties::HEIGHT, LayerProperties::LAYER_FLAGS, LayerMetadata()); FlingerLayerType layer = new ContainerLayer(args); Base::template initLayerDrawingStateAndComputeBounds(test, layer); diff --git a/services/surfaceflinger/tests/unittests/FpsReporterTest.cpp b/services/surfaceflinger/tests/unittests/FpsReporterTest.cpp index 010c675574..cd2fc7426e 100644 --- a/services/surfaceflinger/tests/unittests/FpsReporterTest.cpp +++ b/services/surfaceflinger/tests/unittests/FpsReporterTest.cpp @@ -114,8 +114,7 @@ FpsReporterTest::~FpsReporterTest() { sp FpsReporterTest::createBufferStateLayer(LayerMetadata metadata = {}) { sp client; - LayerCreationArgs args(mFlinger.flinger(), client, "buffer-state-layer", WIDTH, HEIGHT, - LAYER_FLAGS, metadata); + LayerCreationArgs args(mFlinger.flinger(), client, "buffer-state-layer", LAYER_FLAGS, metadata); return new BufferStateLayer(args); } diff --git a/services/surfaceflinger/tests/unittests/GameModeTest.cpp b/services/surfaceflinger/tests/unittests/GameModeTest.cpp index 3fa1a2c2f5..d6459429fb 100644 --- a/services/surfaceflinger/tests/unittests/GameModeTest.cpp +++ b/services/surfaceflinger/tests/unittests/GameModeTest.cpp @@ -53,7 +53,7 @@ public: sp createBufferStateLayer() { sp client; - LayerCreationArgs args(mFlinger.flinger(), client, "buffer-state-layer", 100, 100, 0, + LayerCreationArgs args(mFlinger.flinger(), client, "buffer-state-layer", 0, LayerMetadata()); return new BufferStateLayer(args); } diff --git a/services/surfaceflinger/tests/unittests/RefreshRateSelectionTest.cpp b/services/surfaceflinger/tests/unittests/RefreshRateSelectionTest.cpp index e388a6f40f..1e6e3361b2 100644 --- a/services/surfaceflinger/tests/unittests/RefreshRateSelectionTest.cpp +++ b/services/surfaceflinger/tests/unittests/RefreshRateSelectionTest.cpp @@ -91,15 +91,14 @@ RefreshRateSelectionTest::~RefreshRateSelectionTest() { sp RefreshRateSelectionTest::createBufferStateLayer() { sp client; - LayerCreationArgs args(mFlinger.flinger(), client, "buffer-queue-layer", WIDTH, HEIGHT, - LAYER_FLAGS, LayerMetadata()); + LayerCreationArgs args(mFlinger.flinger(), client, "buffer-queue-layer", LAYER_FLAGS, + LayerMetadata()); return new BufferStateLayer(args); } sp RefreshRateSelectionTest::createEffectLayer() { sp client; - LayerCreationArgs args(mFlinger.flinger(), client, "color-layer", WIDTH, HEIGHT, LAYER_FLAGS, - LayerMetadata()); + LayerCreationArgs args(mFlinger.flinger(), client, "color-layer", LAYER_FLAGS, LayerMetadata()); return new EffectLayer(args); } diff --git a/services/surfaceflinger/tests/unittests/SetFrameRateTest.cpp b/services/surfaceflinger/tests/unittests/SetFrameRateTest.cpp index d0211780ab..360f9c684f 100644 --- a/services/surfaceflinger/tests/unittests/SetFrameRateTest.cpp +++ b/services/surfaceflinger/tests/unittests/SetFrameRateTest.cpp @@ -70,8 +70,8 @@ public: std::string name() override { return "BufferStateLayer"; } sp createLayer(TestableSurfaceFlinger& flinger) override { sp client; - LayerCreationArgs args(flinger.flinger(), client, "buffer-state-layer", WIDTH, HEIGHT, - LAYER_FLAGS, LayerMetadata()); + LayerCreationArgs args(flinger.flinger(), client, "buffer-state-layer", LAYER_FLAGS, + LayerMetadata()); return new BufferStateLayer(args); } }; @@ -81,7 +81,7 @@ public: std::string name() override { return "EffectLayer"; } sp createLayer(TestableSurfaceFlinger& flinger) override { sp client; - LayerCreationArgs args(flinger.flinger(), client, "color-layer", WIDTH, HEIGHT, LAYER_FLAGS, + LayerCreationArgs args(flinger.flinger(), client, "color-layer", LAYER_FLAGS, LayerMetadata()); return new EffectLayer(args); } diff --git a/services/surfaceflinger/tests/unittests/TransactionFrameTracerTest.cpp b/services/surfaceflinger/tests/unittests/TransactionFrameTracerTest.cpp index bd6a7805ec..deeb785bb9 100644 --- a/services/surfaceflinger/tests/unittests/TransactionFrameTracerTest.cpp +++ b/services/surfaceflinger/tests/unittests/TransactionFrameTracerTest.cpp @@ -57,7 +57,7 @@ public: sp createBufferStateLayer() { sp client; - LayerCreationArgs args(mFlinger.flinger(), client, "buffer-state-layer", 100, 100, 0, + LayerCreationArgs args(mFlinger.flinger(), client, "buffer-state-layer", 0, LayerMetadata()); return new BufferStateLayer(args); } diff --git a/services/surfaceflinger/tests/unittests/TransactionSurfaceFrameTest.cpp b/services/surfaceflinger/tests/unittests/TransactionSurfaceFrameTest.cpp index bf69704210..704340deac 100644 --- a/services/surfaceflinger/tests/unittests/TransactionSurfaceFrameTest.cpp +++ b/services/surfaceflinger/tests/unittests/TransactionSurfaceFrameTest.cpp @@ -57,7 +57,7 @@ public: sp createBufferStateLayer() { sp client; - LayerCreationArgs args(mFlinger.flinger(), client, "buffer-state-layer", 100, 100, 0, + LayerCreationArgs args(mFlinger.flinger(), client, "buffer-state-layer", 0, LayerMetadata()); return new BufferStateLayer(args); } diff --git a/services/surfaceflinger/tests/unittests/TunnelModeEnabledReporterTest.cpp b/services/surfaceflinger/tests/unittests/TunnelModeEnabledReporterTest.cpp index e4f74694f7..ade4fbb850 100644 --- a/services/surfaceflinger/tests/unittests/TunnelModeEnabledReporterTest.cpp +++ b/services/surfaceflinger/tests/unittests/TunnelModeEnabledReporterTest.cpp @@ -100,8 +100,7 @@ TunnelModeEnabledReporterTest::~TunnelModeEnabledReporterTest() { sp TunnelModeEnabledReporterTest::createBufferStateLayer( LayerMetadata metadata = {}) { sp client; - LayerCreationArgs args(mFlinger.flinger(), client, "buffer-state-layer", WIDTH, HEIGHT, - LAYER_FLAGS, metadata); + LayerCreationArgs args(mFlinger.flinger(), client, "buffer-state-layer", LAYER_FLAGS, metadata); return new BufferStateLayer(args); } diff --git a/services/surfaceflinger/tests/unittests/mock/MockLayer.h b/services/surfaceflinger/tests/unittests/mock/MockLayer.h index ba2e4db0fa..8b48e1c16d 100644 --- a/services/surfaceflinger/tests/unittests/mock/MockLayer.h +++ b/services/surfaceflinger/tests/unittests/mock/MockLayer.h @@ -25,7 +25,7 @@ namespace android::mock { class MockLayer : public Layer { public: MockLayer(SurfaceFlinger* flinger, std::string name) - : Layer(LayerCreationArgs(flinger, nullptr, std::move(name), 800, 600, 0, {})) {} + : Layer(LayerCreationArgs(flinger, nullptr, std::move(name), 0, {})) {} explicit MockLayer(SurfaceFlinger* flinger) : MockLayer(flinger, "TestLayer") {} MOCK_CONST_METHOD0(getType, const char*()); -- cgit v1.2.3-59-g8ed1b From 068173d9076ca25fa5cc008a116e4ec22503b9be Mon Sep 17 00:00:00 2001 From: Dominik Laskowski Date: Wed, 11 Aug 2021 17:22:59 -0700 Subject: SF: Add VsyncSchedule skeleton Pull the Scheduler::VsyncSchedule struct and related code into its own file, as it will be extended with more per-display state, e.g. reactor registrations, resync state machine, etc. Add for feature flags. Move Scheduler into its namespace. Bug: 185535769 Test: libsurfaceflinger_unittest Change-Id: I6e10893632c5abf40380df924791d1fcc27c3cc2 --- services/surfaceflinger/Android.bp | 3 +- services/surfaceflinger/BufferQueueLayer.cpp | 5 +- services/surfaceflinger/BufferStateLayer.cpp | 5 +- services/surfaceflinger/DisplayDevice.cpp | 4 +- services/surfaceflinger/DisplayDevice.h | 2 +- services/surfaceflinger/Layer.cpp | 4 +- services/surfaceflinger/Scheduler/LayerHistory.h | 6 +- .../surfaceflinger/Scheduler/RefreshRateConfigs.h | 8 +- services/surfaceflinger/Scheduler/Scheduler.cpp | 216 +++++++-------------- services/surfaceflinger/Scheduler/Scheduler.h | 100 ++++------ services/surfaceflinger/Scheduler/VSyncReactor.cpp | 4 +- services/surfaceflinger/Scheduler/VSyncReactor.h | 2 +- .../surfaceflinger/Scheduler/VsyncController.h | 10 +- .../surfaceflinger/Scheduler/VsyncSchedule.cpp | 113 +++++++++++ services/surfaceflinger/Scheduler/VsyncSchedule.h | 75 +++++++ .../Scheduler/include/scheduler/Features.h | 34 ++++ services/surfaceflinger/SurfaceFlinger.cpp | 43 ++-- services/surfaceflinger/SurfaceFlinger.h | 7 +- services/surfaceflinger/SurfaceFlingerFactory.h | 4 - .../tests/unittests/CompositionTest.cpp | 2 +- .../unittests/DisplayDevice_InitiateModeChange.cpp | 2 +- .../unittests/DisplayTransactionTestHelpers.h | 2 +- .../tests/unittests/FpsReporterTest.cpp | 4 + .../tests/unittests/LayerHistoryTest.cpp | 13 +- .../tests/unittests/SchedulerTest.cpp | 43 ++-- .../tests/unittests/SetFrameRateTest.cpp | 2 + .../SurfaceFlinger_NotifyPowerBoostTest.cpp | 7 +- .../tests/unittests/TestableScheduler.h | 39 ++-- .../tests/unittests/TestableSurfaceFlinger.h | 20 +- .../tests/unittests/TransactionApplicationTest.cpp | 5 +- .../tests/unittests/mock/MockSchedulerCallback.h | 17 +- .../tests/unittests/mock/MockVsyncController.h | 2 +- 32 files changed, 461 insertions(+), 342 deletions(-) create mode 100644 services/surfaceflinger/Scheduler/VsyncSchedule.cpp create mode 100644 services/surfaceflinger/Scheduler/VsyncSchedule.h create mode 100644 services/surfaceflinger/Scheduler/include/scheduler/Features.h (limited to 'services/surfaceflinger/BufferQueueLayer.cpp') diff --git a/services/surfaceflinger/Android.bp b/services/surfaceflinger/Android.bp index 29636f84f5..c9fb7bc876 100644 --- a/services/surfaceflinger/Android.bp +++ b/services/surfaceflinger/Android.bp @@ -194,9 +194,10 @@ filegroup { "Scheduler/Timer.cpp", "Scheduler/VSyncDispatchTimerQueue.cpp", "Scheduler/VSyncPredictor.cpp", - "Scheduler/VsyncModulator.cpp", "Scheduler/VSyncReactor.cpp", "Scheduler/VsyncConfiguration.cpp", + "Scheduler/VsyncModulator.cpp", + "Scheduler/VsyncSchedule.cpp", "StartPropertySetThread.cpp", "SurfaceFlinger.cpp", "SurfaceFlingerDefaultFactory.cpp", diff --git a/services/surfaceflinger/BufferQueueLayer.cpp b/services/surfaceflinger/BufferQueueLayer.cpp index dec7cc0806..926aa1dfb2 100644 --- a/services/surfaceflinger/BufferQueueLayer.cpp +++ b/services/surfaceflinger/BufferQueueLayer.cpp @@ -372,8 +372,9 @@ void BufferQueueLayer::onFrameAvailable(const BufferItem& item) { // Add this buffer from our internal queue tracker { // Autolock scope const nsecs_t presentTime = item.mIsAutoTimestamp ? 0 : item.mTimestamp; - mFlinger->mScheduler->recordLayerHistory(this, presentTime, - LayerHistory::LayerUpdateType::Buffer); + + using LayerUpdateType = scheduler::LayerHistory::LayerUpdateType; + mFlinger->mScheduler->recordLayerHistory(this, presentTime, LayerUpdateType::Buffer); Mutex::Autolock lock(mQueueItemLock); // Reset the frame number tracker when we receive the first buffer after diff --git a/services/surfaceflinger/BufferStateLayer.cpp b/services/surfaceflinger/BufferStateLayer.cpp index b4ccb803e9..7d40fc87f9 100644 --- a/services/surfaceflinger/BufferStateLayer.cpp +++ b/services/surfaceflinger/BufferStateLayer.cpp @@ -476,8 +476,9 @@ bool BufferStateLayer::setBuffer(const BufferData& bufferData, nsecs_t postTime, return static_cast(0); }(); - mFlinger->mScheduler->recordLayerHistory(this, presentTime, - LayerHistory::LayerUpdateType::Buffer); + + using LayerUpdateType = scheduler::LayerHistory::LayerUpdateType; + mFlinger->mScheduler->recordLayerHistory(this, presentTime, LayerUpdateType::Buffer); addFrameEvent(mDrawingState.acquireFence, postTime, isAutoTimestamp ? 0 : desiredPresentTime); diff --git a/services/surfaceflinger/DisplayDevice.cpp b/services/surfaceflinger/DisplayDevice.cpp index fd09ae4066..76bbe2c58f 100644 --- a/services/surfaceflinger/DisplayDevice.cpp +++ b/services/surfaceflinger/DisplayDevice.cpp @@ -483,7 +483,7 @@ bool DisplayDevice::setDesiredActiveMode(const ActiveModeInfo& info) { std::scoped_lock lock(mActiveModeLock); if (mDesiredActiveModeChanged) { // If a mode change is pending, just cache the latest request in mDesiredActiveMode - const Scheduler::ModeEvent prevConfig = mDesiredActiveMode.event; + const auto prevConfig = mDesiredActiveMode.event; mDesiredActiveMode = info; mDesiredActiveMode.event = mDesiredActiveMode.event | prevConfig; return false; @@ -508,7 +508,7 @@ std::optional DisplayDevice::getDesiredActiveMode void DisplayDevice::clearDesiredActiveModeState() { std::scoped_lock lock(mActiveModeLock); - mDesiredActiveMode.event = Scheduler::ModeEvent::None; + mDesiredActiveMode.event = scheduler::DisplayModeEvent::None; mDesiredActiveModeChanged = false; } diff --git a/services/surfaceflinger/DisplayDevice.h b/services/surfaceflinger/DisplayDevice.h index 4b9718f608..324145ef47 100644 --- a/services/surfaceflinger/DisplayDevice.h +++ b/services/surfaceflinger/DisplayDevice.h @@ -190,7 +190,7 @@ public: struct ActiveModeInfo { DisplayModePtr mode; - scheduler::RefreshRateConfigEvent event = scheduler::RefreshRateConfigEvent::None; + scheduler::DisplayModeEvent event = scheduler::DisplayModeEvent::None; bool operator!=(const ActiveModeInfo& other) const { return mode != other.mode || event != other.event; diff --git a/services/surfaceflinger/Layer.cpp b/services/surfaceflinger/Layer.cpp index 968a49d526..b3ea94fd94 100644 --- a/services/surfaceflinger/Layer.cpp +++ b/services/surfaceflinger/Layer.cpp @@ -1293,8 +1293,8 @@ bool Layer::setFrameRateForLayerTree(FrameRate frameRate) { mDrawingState.modified = true; setTransactionFlags(eTransactionNeeded); - mFlinger->mScheduler->recordLayerHistory(this, systemTime(), - LayerHistory::LayerUpdateType::SetFrameRate); + using LayerUpdateType = scheduler::LayerHistory::LayerUpdateType; + mFlinger->mScheduler->recordLayerHistory(this, systemTime(), LayerUpdateType::SetFrameRate); return true; } diff --git a/services/surfaceflinger/Scheduler/LayerHistory.h b/services/surfaceflinger/Scheduler/LayerHistory.h index 92236f560a..8d56951363 100644 --- a/services/surfaceflinger/Scheduler/LayerHistory.h +++ b/services/surfaceflinger/Scheduler/LayerHistory.h @@ -31,11 +31,9 @@ namespace android { class Layer; -class TestableScheduler; namespace scheduler { -class LayerHistoryTest; class LayerInfo; class LayerHistory { @@ -75,8 +73,8 @@ public: std::string dump() const; private: - friend LayerHistoryTest; - friend TestableScheduler; + friend class LayerHistoryTest; + friend class TestableScheduler; using LayerPair = std::pair>; using LayerInfos = std::vector; diff --git a/services/surfaceflinger/Scheduler/RefreshRateConfigs.h b/services/surfaceflinger/Scheduler/RefreshRateConfigs.h index 8a1c2062a6..492feb14df 100644 --- a/services/surfaceflinger/Scheduler/RefreshRateConfigs.h +++ b/services/surfaceflinger/Scheduler/RefreshRateConfigs.h @@ -37,11 +37,11 @@ namespace android::scheduler { using namespace std::chrono_literals; -enum class RefreshRateConfigEvent : unsigned { None = 0b0, Changed = 0b1 }; +enum class DisplayModeEvent : unsigned { None = 0b0, Changed = 0b1 }; -inline RefreshRateConfigEvent operator|(RefreshRateConfigEvent lhs, RefreshRateConfigEvent rhs) { - using T = std::underlying_type_t; - return static_cast(static_cast(lhs) | static_cast(rhs)); +inline DisplayModeEvent operator|(DisplayModeEvent lhs, DisplayModeEvent rhs) { + using T = std::underlying_type_t; + return static_cast(static_cast(lhs) | static_cast(rhs)); } using FrameRateOverride = DisplayEventReceiver::Event::FrameRateOverride; diff --git a/services/surfaceflinger/Scheduler/Scheduler.cpp b/services/surfaceflinger/Scheduler/Scheduler.cpp index 4d72798086..cbe4552b0b 100644 --- a/services/surfaceflinger/Scheduler/Scheduler.cpp +++ b/services/surfaceflinger/Scheduler/Scheduler.cpp @@ -46,11 +46,8 @@ #include "OneShotTimer.h" #include "SchedulerUtils.h" #include "SurfaceFlingerProperties.h" -#include "Timer.h" -#include "VSyncDispatchTimerQueue.h" #include "VSyncPredictor.h" #include "VSyncReactor.h" -#include "VsyncController.h" #define RETURN_IF_INVALID_HANDLE(handle, ...) \ do { \ @@ -60,68 +57,14 @@ } \ } while (false) -using namespace std::string_literals; +namespace android::scheduler { -namespace android { - -using gui::WindowInfo; - -namespace { - -std::unique_ptr createVSyncTracker() { - // TODO(b/144707443): Tune constants. - constexpr int kDefaultRate = 60; - constexpr auto initialPeriod = std::chrono::duration>(1); - constexpr nsecs_t idealPeriod = - std::chrono::duration_cast(initialPeriod).count(); - constexpr size_t vsyncTimestampHistorySize = 20; - constexpr size_t minimumSamplesForPrediction = 6; - constexpr uint32_t discardOutlierPercent = 20; - return std::make_unique(idealPeriod, vsyncTimestampHistorySize, - minimumSamplesForPrediction, - discardOutlierPercent); -} - -std::unique_ptr createVSyncDispatch(scheduler::VSyncTracker& tracker) { - // TODO(b/144707443): Tune constants. - constexpr std::chrono::nanoseconds vsyncMoveThreshold = 3ms; - constexpr std::chrono::nanoseconds timerSlack = 500us; - return std::make_unique< - scheduler::VSyncDispatchTimerQueue>(std::make_unique(), tracker, - timerSlack.count(), vsyncMoveThreshold.count()); -} - -const char* toContentDetectionString(bool useContentDetection) { - return useContentDetection ? "on" : "off"; -} - -} // namespace - -class PredictedVsyncTracer { -public: - PredictedVsyncTracer(scheduler::VSyncDispatch& dispatch) - : mRegistration(dispatch, std::bind(&PredictedVsyncTracer::callback, this), - "PredictedVsyncTracer") { - scheduleRegistration(); - } - -private: - TracedOrdinal mParity = {"VSYNC-predicted", 0}; - scheduler::VSyncCallbackRegistration mRegistration; - - void scheduleRegistration() { mRegistration.schedule({0, 0, 0}); } - - void callback() { - mParity = !mParity; - scheduleRegistration(); - } -}; - -Scheduler::Scheduler(ICompositor& compositor, ISchedulerCallback& callback, Options options) - : impl::MessageQueue(compositor), mOptions(options), mSchedulerCallback(callback) {} +Scheduler::Scheduler(ICompositor& compositor, ISchedulerCallback& callback, FeatureFlags features) + : impl::MessageQueue(compositor), mFeatures(features), mSchedulerCallback(callback) {} void Scheduler::startTimers() { using namespace sysprop; + using namespace std::string_literals; if (const int64_t millis = set_touch_timer_ms(0); millis > 0) { // Touch events are coming to SF every 100ms, so the timer needs to be higher than that @@ -154,27 +97,14 @@ void Scheduler::run() { } } -void Scheduler::createVsyncSchedule(bool supportKernelTimer) { - auto clock = std::make_unique(); - auto tracker = createVSyncTracker(); - auto dispatch = createVSyncDispatch(*tracker); - - // TODO(b/144707443): Tune constants. - constexpr size_t pendingFenceLimit = 20; - auto controller = - std::make_unique(std::move(clock), *tracker, pendingFenceLimit, - supportKernelTimer); - mVsyncSchedule = {std::move(controller), std::move(tracker), std::move(dispatch)}; - - if (base::GetBoolProperty("debug.sf.show_predicted_vsync", false)) { - mPredictedVsyncTracer = std::make_unique(*mVsyncSchedule.dispatch); - } +void Scheduler::createVsyncSchedule(FeatureFlags features) { + mVsyncSchedule.emplace(features); } std::unique_ptr Scheduler::makePrimaryDispSyncSource( const char* name, std::chrono::nanoseconds workDuration, std::chrono::nanoseconds readyDuration, bool traceVsync) { - return std::make_unique(*mVsyncSchedule.dispatch, workDuration, + return std::make_unique(getVsyncDispatch(), workDuration, readyDuration, traceVsync, name); } @@ -210,7 +140,7 @@ bool Scheduler::isVsyncValid(nsecs_t expectedVsyncTimestamp, uid_t uid) const { return true; } - return mVsyncSchedule.tracker->isVSyncInPhase(expectedVsyncTimestamp, *frameRate); + return mVsyncSchedule->getTracker().isVSyncInPhase(expectedVsyncTimestamp, *frameRate); } impl::EventThread::ThrottleVsyncCallback Scheduler::makeThrottleVsyncCallback() const { @@ -245,7 +175,7 @@ impl::EventThread::GetVsyncPeriodFunction Scheduler::makeGetVsyncPeriodFunction( }; } -Scheduler::ConnectionHandle Scheduler::createConnection( +ConnectionHandle Scheduler::createConnection( const char* connectionName, frametimeline::TokenManager* tokenManager, std::chrono::nanoseconds workDuration, std::chrono::nanoseconds readyDuration, impl::EventThread::InterceptVSyncsCallback interceptCallback) { @@ -259,7 +189,7 @@ Scheduler::ConnectionHandle Scheduler::createConnection( return createConnection(std::move(eventThread)); } -Scheduler::ConnectionHandle Scheduler::createConnection(std::unique_ptr eventThread) { +ConnectionHandle Scheduler::createConnection(std::unique_ptr eventThread) { const ConnectionHandle handle = ConnectionHandle{mNextConnectionHandleId++}; ALOGV("Creating a connection handle with ID %" PRIuPTR, handle.id); @@ -346,24 +276,24 @@ void Scheduler::onFrameRateOverridesChanged(ConnectionHandle handle, PhysicalDis void Scheduler::onPrimaryDisplayModeChanged(ConnectionHandle handle, DisplayModePtr mode) { { - std::lock_guard lock(mFeatureStateLock); + std::lock_guard lock(mPolicyLock); // Cache the last reported modes for primary display. - mFeatures.cachedModeChangedParams = {handle, mode}; + mPolicy.cachedModeChangedParams = {handle, mode}; // Invalidate content based refresh rate selection so it could be calculated // again for the new refresh rate. - mFeatures.contentRequirements.clear(); + mPolicy.contentRequirements.clear(); } onNonPrimaryDisplayModeChanged(handle, mode); } void Scheduler::dispatchCachedReportedMode() { // Check optional fields first. - if (!mFeatures.mode) { + if (!mPolicy.mode) { ALOGW("No mode ID found, not dispatching cached mode."); return; } - if (!mFeatures.cachedModeChangedParams.has_value()) { + if (!mPolicy.cachedModeChangedParams) { ALOGW("No mode changed params found, not dispatching cached mode."); return; } @@ -372,18 +302,18 @@ void Scheduler::dispatchCachedReportedMode() { // mode change is in progress. In that case we shouldn't dispatch an event // as it will be dispatched when the current mode changes. if (std::scoped_lock lock(mRefreshRateConfigsLock); - mRefreshRateConfigs->getCurrentRefreshRate().getMode() != mFeatures.mode) { + mRefreshRateConfigs->getCurrentRefreshRate().getMode() != mPolicy.mode) { return; } // If there is no change from cached mode, there is no need to dispatch an event - if (mFeatures.mode == mFeatures.cachedModeChangedParams->mode) { + if (mPolicy.mode == mPolicy.cachedModeChangedParams->mode) { return; } - mFeatures.cachedModeChangedParams->mode = mFeatures.mode; - onNonPrimaryDisplayModeChanged(mFeatures.cachedModeChangedParams->handle, - mFeatures.cachedModeChangedParams->mode); + mPolicy.cachedModeChangedParams->mode = mPolicy.mode; + onNonPrimaryDisplayModeChanged(mPolicy.cachedModeChangedParams->handle, + mPolicy.cachedModeChangedParams->mode); } void Scheduler::onNonPrimaryDisplayModeChanged(ConnectionHandle handle, DisplayModePtr mode) { @@ -424,12 +354,12 @@ void Scheduler::setDuration(ConnectionHandle handle, std::chrono::nanoseconds wo } DisplayStatInfo Scheduler::getDisplayStatInfo(nsecs_t now) { - const auto vsyncTime = mVsyncSchedule.tracker->nextAnticipatedVSyncTimeFrom(now); - const auto vsyncPeriod = mVsyncSchedule.tracker->currentPeriod(); + const auto vsyncTime = mVsyncSchedule->getTracker().nextAnticipatedVSyncTimeFrom(now); + const auto vsyncPeriod = mVsyncSchedule->getTracker().currentPeriod(); return DisplayStatInfo{.vsyncTime = vsyncTime, .vsyncPeriod = vsyncPeriod}; } -Scheduler::ConnectionHandle Scheduler::enableVSyncInjection(bool enable) { +ConnectionHandle Scheduler::enableVSyncInjection(bool enable) { if (mInjectVSyncs == enable) { return {}; } @@ -470,7 +400,7 @@ bool Scheduler::injectVSync(nsecs_t when, nsecs_t expectedVSyncTime, nsecs_t dea void Scheduler::enableHardwareVsync() { std::lock_guard lock(mHWVsyncLock); if (!mPrimaryHWVsyncEnabled && mHWVsyncAvailable) { - mVsyncSchedule.tracker->resetModel(); + mVsyncSchedule->getTracker().resetModel(); mSchedulerCallback.setVsyncEnabled(true); mPrimaryHWVsyncEnabled = true; } @@ -523,10 +453,10 @@ void Scheduler::resync() { void Scheduler::setVsyncPeriod(nsecs_t period) { std::lock_guard lock(mHWVsyncLock); - mVsyncSchedule.controller->startPeriodTransition(period); + mVsyncSchedule->getController().startPeriodTransition(period); if (!mPrimaryHWVsyncEnabled) { - mVsyncSchedule.tracker->resetModel(); + mVsyncSchedule->getTracker().resetModel(); mSchedulerCallback.setVsyncEnabled(true); mPrimaryHWVsyncEnabled = true; } @@ -539,8 +469,9 @@ void Scheduler::addResyncSample(nsecs_t timestamp, std::optional hwcVsy { // Scope for the lock std::lock_guard lock(mHWVsyncLock); if (mPrimaryHWVsyncEnabled) { - needsHwVsync = mVsyncSchedule.controller->addHwVsyncTimestamp(timestamp, hwcVsyncPeriod, - periodFlushed); + needsHwVsync = + mVsyncSchedule->getController().addHwVsyncTimestamp(timestamp, hwcVsyncPeriod, + periodFlushed); } } @@ -551,24 +482,23 @@ void Scheduler::addResyncSample(nsecs_t timestamp, std::optional hwcVsy } } -void Scheduler::addPresentFence(const std::shared_ptr& fenceTime) { - if (mVsyncSchedule.controller->addPresentFence(fenceTime)) { +void Scheduler::addPresentFence(std::shared_ptr fence) { + if (mVsyncSchedule->getController().addPresentFence(std::move(fence))) { enableHardwareVsync(); } else { disableHardwareVsync(false); } } -void Scheduler::setIgnorePresentFences(bool ignore) { - mVsyncSchedule.controller->setIgnorePresentFences(ignore); -} - void Scheduler::registerLayer(Layer* layer) { + using WindowType = gui::WindowInfo::Type; + scheduler::LayerHistory::LayerVoteType voteType; - if (!mOptions.useContentDetection || layer->getWindowType() == WindowInfo::Type::STATUS_BAR) { + if (!mFeatures.test(Feature::kContentDetection) || + layer->getWindowType() == WindowType::STATUS_BAR) { voteType = scheduler::LayerHistory::LayerVoteType::NoVote; - } else if (layer->getWindowType() == WindowInfo::Type::WALLPAPER) { + } else if (layer->getWindowType() == WindowType::WALLPAPER) { // Running Wallpaper at Min is considered as part of content detection. voteType = scheduler::LayerHistory::LayerVoteType::Min; } else { @@ -615,13 +545,13 @@ void Scheduler::chooseRefreshRateForContent() { bool frameRateChanged; bool frameRateOverridesChanged; { - std::lock_guard lock(mFeatureStateLock); - mFeatures.contentRequirements = summary; + std::lock_guard lock(mPolicyLock); + mPolicy.contentRequirements = summary; newMode = calculateRefreshRateModeId(&consideredSignals); frameRateOverridesChanged = updateFrameRateOverrides(consideredSignals, newMode->getFps()); - if (mFeatures.mode == newMode) { + if (mPolicy.mode == newMode) { // We don't need to change the display mode, but we might need to send an event // about a mode change, since it was suppressed due to a previous idleConsidered if (!consideredSignals.idle) { @@ -629,15 +559,16 @@ void Scheduler::chooseRefreshRateForContent() { } frameRateChanged = false; } else { - mFeatures.mode = newMode; + mPolicy.mode = newMode; frameRateChanged = true; } } if (frameRateChanged) { - auto newRefreshRate = refreshRateConfigs->getRefreshRateFromModeId(newMode->getId()); + const auto newRefreshRate = refreshRateConfigs->getRefreshRateFromModeId(newMode->getId()); + mSchedulerCallback.changeRefreshRate(newRefreshRate, - consideredSignals.idle ? ModeEvent::None - : ModeEvent::Changed); + consideredSignals.idle ? DisplayModeEvent::None + : DisplayModeEvent::Changed); } if (frameRateOverridesChanged) { mSchedulerCallback.triggerOnFrameRateOverridesChanged(); @@ -660,8 +591,8 @@ void Scheduler::onTouchHint() { void Scheduler::setDisplayPowerState(bool normal) { { - std::lock_guard lock(mFeatureStateLock); - mFeatures.isDisplayPowerStateNormal = normal; + std::lock_guard lock(mPolicyLock); + mPolicy.isDisplayPowerStateNormal = normal; } if (mDisplayPowerTimer) { @@ -703,7 +634,7 @@ void Scheduler::kernelIdleTimerCallback(TimerState state) { } void Scheduler::idleTimerCallback(TimerState state) { - handleTimerStateChanged(&mFeatures.idleTimer, state); + handleTimerStateChanged(&mPolicy.idleTimer, state); ATRACE_INT("ExpiredIdleTimer", static_cast(state)); } @@ -713,14 +644,14 @@ void Scheduler::touchTimerCallback(TimerState state) { // Clear layer history to get fresh FPS detection. // NOTE: Instead of checking all the layers, we should be checking the layer // that is currently on top. b/142507166 will give us this capability. - if (handleTimerStateChanged(&mFeatures.touch, touch)) { + if (handleTimerStateChanged(&mPolicy.touch, touch)) { mLayerHistory.clear(); } ATRACE_INT("TouchState", static_cast(touch)); } void Scheduler::displayPowerTimerCallback(TimerState state) { - handleTimerStateChanged(&mFeatures.displayPowerTimer, state); + handleTimerStateChanged(&mPolicy.displayPowerTimer, state); ATRACE_INT("ExpiredDisplayPowerTimer", static_cast(state)); } @@ -730,7 +661,7 @@ void Scheduler::dump(std::string& result) const { StringAppendF(&result, "+ Touch timer: %s\n", mTouchTimer ? mTouchTimer->dump().c_str() : "off"); StringAppendF(&result, "+ Content detection: %s %s\n\n", - toContentDetectionString(mOptions.useContentDetection), + mFeatures.test(Feature::kContentDetection) ? "on" : "off", mLayerHistory.dump().c_str()); { @@ -756,13 +687,8 @@ void Scheduler::dump(std::string& result) const { } } -void Scheduler::dumpVsync(std::string& s) const { - using base::StringAppendF; - - StringAppendF(&s, "VSyncReactor:\n"); - mVsyncSchedule.controller->dump(s); - StringAppendF(&s, "VSyncDispatch:\n"); - mVsyncSchedule.dispatch->dump(s); +void Scheduler::dumpVsync(std::string& out) const { + mVsyncSchedule->dump(out); } bool Scheduler::updateFrameRateOverrides( @@ -774,7 +700,7 @@ bool Scheduler::updateFrameRateOverrides( if (!consideredSignals.idle) { const auto frameRateOverrides = - refreshRateConfigs->getFrameRateOverrides(mFeatures.contentRequirements, + refreshRateConfigs->getFrameRateOverrides(mPolicy.contentRequirements, displayRefreshRate, consideredSignals); std::lock_guard lock(mFrameRateOverridesLock); if (!std::equal(mFrameRateOverridesByContent.begin(), mFrameRateOverridesByContent.end(), @@ -797,31 +723,30 @@ bool Scheduler::handleTimerStateChanged(T* currentState, T newState) { scheduler::RefreshRateConfigs::GlobalSignals consideredSignals; const auto refreshRateConfigs = holdRefreshRateConfigs(); { - std::lock_guard lock(mFeatureStateLock); + std::lock_guard lock(mPolicyLock); if (*currentState == newState) { return false; } *currentState = newState; newMode = calculateRefreshRateModeId(&consideredSignals); frameRateOverridesChanged = updateFrameRateOverrides(consideredSignals, newMode->getFps()); - if (mFeatures.mode == newMode) { + if (mPolicy.mode == newMode) { // We don't need to change the display mode, but we might need to send an event // about a mode change, since it was suppressed due to a previous idleConsidered if (!consideredSignals.idle) { dispatchCachedReportedMode(); } } else { - mFeatures.mode = newMode; + mPolicy.mode = newMode; refreshRateChanged = true; } } if (refreshRateChanged) { - const RefreshRate& newRefreshRate = - refreshRateConfigs->getRefreshRateFromModeId(newMode->getId()); + const auto newRefreshRate = refreshRateConfigs->getRefreshRateFromModeId(newMode->getId()); mSchedulerCallback.changeRefreshRate(newRefreshRate, - consideredSignals.idle ? ModeEvent::None - : ModeEvent::Changed); + consideredSignals.idle ? DisplayModeEvent::None + : DisplayModeEvent::Changed); } if (frameRateOverridesChanged) { mSchedulerCallback.triggerOnFrameRateOverridesChanged(); @@ -838,27 +763,26 @@ DisplayModePtr Scheduler::calculateRefreshRateModeId( // If Display Power is not in normal operation we want to be in performance mode. When coming // back to normal mode, a grace period is given with DisplayPowerTimer. if (mDisplayPowerTimer && - (!mFeatures.isDisplayPowerStateNormal || - mFeatures.displayPowerTimer == TimerState::Reset)) { + (!mPolicy.isDisplayPowerStateNormal || mPolicy.displayPowerTimer == TimerState::Reset)) { return refreshRateConfigs->getMaxRefreshRateByPolicy().getMode(); } - const bool touchActive = mTouchTimer && mFeatures.touch == TouchState::Active; - const bool idle = mFeatures.idleTimer == TimerState::Expired; + const bool touchActive = mTouchTimer && mPolicy.touch == TouchState::Active; + const bool idle = mPolicy.idleTimer == TimerState::Expired; return refreshRateConfigs - ->getBestRefreshRate(mFeatures.contentRequirements, - {.touch = touchActive, .idle = idle}, consideredSignals) + ->getBestRefreshRate(mPolicy.contentRequirements, {.touch = touchActive, .idle = idle}, + consideredSignals) .getMode(); } DisplayModePtr Scheduler::getPreferredDisplayMode() { - std::lock_guard lock(mFeatureStateLock); + std::lock_guard lock(mPolicyLock); // Make sure that the default mode ID is first updated, before returned. - if (mFeatures.mode) { - mFeatures.mode = calculateRefreshRateModeId(); + if (mPolicy.mode) { + mPolicy.mode = calculateRefreshRateModeId(); } - return mFeatures.mode; + return mPolicy.mode; } void Scheduler::onNewVsyncPeriodChangeTimeline(const hal::VsyncPeriodChangeTimeline& timeline) { @@ -915,8 +839,8 @@ void Scheduler::setPreferredRefreshRateForUid(FrameRateOverride frameRateOverrid std::chrono::steady_clock::time_point Scheduler::getPreviousVsyncFrom( nsecs_t expectedPresentTime) const { const auto presentTime = std::chrono::nanoseconds(expectedPresentTime); - const auto vsyncPeriod = std::chrono::nanoseconds(mVsyncSchedule.tracker->currentPeriod()); + const auto vsyncPeriod = std::chrono::nanoseconds(mVsyncSchedule->getTracker().currentPeriod()); return std::chrono::steady_clock::time_point(presentTime - vsyncPeriod); } -} // namespace android +} // namespace android::scheduler diff --git a/services/surfaceflinger/Scheduler/Scheduler.h b/services/surfaceflinger/Scheduler/Scheduler.h index 2a6de54e93..e127ff7371 100644 --- a/services/surfaceflinger/Scheduler/Scheduler.h +++ b/services/surfaceflinger/Scheduler/Scheduler.h @@ -31,40 +31,37 @@ #include #pragma clang diagnostic pop // ignored "-Wconversion -Wextra" +#include + #include "EventThread.h" #include "LayerHistory.h" #include "MessageQueue.h" #include "OneShotTimer.h" #include "RefreshRateConfigs.h" #include "SchedulerUtils.h" +#include "VsyncSchedule.h" namespace android { -using namespace std::chrono_literals; -using scheduler::LayerHistory; - class FenceTime; class InjectVSyncSource; -class PredictedVsyncTracer; - -namespace scheduler { -class VsyncController; -class VSyncDispatch; -class VSyncTracker; -} // namespace scheduler namespace frametimeline { class TokenManager; } // namespace frametimeline +namespace scheduler { + struct ISchedulerCallback { // Indicates frame activity, i.e. whether commit and/or composite is taking place. enum class FrameHint { kNone, kActive }; + using RefreshRate = RefreshRateConfigs::RefreshRate; + using DisplayModeEvent = scheduler::DisplayModeEvent; + virtual void scheduleComposite(FrameHint) = 0; virtual void setVsyncEnabled(bool) = 0; - virtual void changeRefreshRate(const scheduler::RefreshRateConfigs::RefreshRate&, - scheduler::RefreshRateConfigEvent) = 0; + virtual void changeRefreshRate(const RefreshRate&, DisplayModeEvent) = 0; virtual void kernelTimerChanged(bool expired) = 0; virtual void triggerOnFrameRateOverridesChanged() = 0; @@ -76,18 +73,10 @@ class Scheduler : impl::MessageQueue { using Impl = impl::MessageQueue; public: - using RefreshRate = scheduler::RefreshRateConfigs::RefreshRate; - using ModeEvent = scheduler::RefreshRateConfigEvent; - - struct Options { - // Whether to use content detection at all. - bool useContentDetection; - }; - - Scheduler(ICompositor&, ISchedulerCallback&, Options); + Scheduler(ICompositor&, ISchedulerCallback&, FeatureFlags); ~Scheduler(); - void createVsyncSchedule(bool supportKernelIdleTimer); + void createVsyncSchedule(FeatureFlags); void startTimers(); void run(); @@ -107,7 +96,6 @@ public: return std::move(future); } - using ConnectionHandle = scheduler::ConnectionHandle; ConnectionHandle createConnection(const char* connectionName, frametimeline::TokenManager*, std::chrono::nanoseconds workDuration, std::chrono::nanoseconds readyDuration, @@ -119,7 +107,7 @@ public: sp getEventConnection(ConnectionHandle); void onHotplugReceived(ConnectionHandle, PhysicalDisplayId, bool connected); - void onPrimaryDisplayModeChanged(ConnectionHandle, DisplayModePtr) EXCLUDES(mFeatureStateLock); + void onPrimaryDisplayModeChanged(ConnectionHandle, DisplayModePtr) EXCLUDES(mPolicyLock); void onNonPrimaryDisplayModeChanged(ConnectionHandle, DisplayModePtr); void onScreenAcquired(ConnectionHandle); void onScreenReleased(ConnectionHandle); @@ -152,8 +140,7 @@ public: // VsyncController detected that the vsync period changed, and false otherwise. void addResyncSample(nsecs_t timestamp, std::optional hwcVsyncPeriod, bool* periodFlushed); - void addPresentFence(const std::shared_ptr&); - void setIgnorePresentFences(bool ignore); + void addPresentFence(std::shared_ptr); // Layers are registered on creation, and unregistered when the weak reference expires. void registerLayer(Layer*); @@ -172,7 +159,7 @@ public: void setDisplayPowerState(bool normal); - scheduler::VSyncDispatch& getVsyncDispatch() { return *mVsyncSchedule.dispatch; } + VSyncDispatch& getVsyncDispatch() { return mVsyncSchedule->getDispatch(); } // Returns true if a given vsync timestamp is considered valid vsync // for a given uid @@ -211,7 +198,7 @@ public: std::optional getFrameRateOverride(uid_t uid) const EXCLUDES(mRefreshRateConfigsLock, mFrameRateOverridesLock); - void setRefreshRateConfigs(std::shared_ptr refreshRateConfigs) + void setRefreshRateConfigs(std::shared_ptr refreshRateConfigs) EXCLUDES(mRefreshRateConfigsLock) { // We need to stop the idle timer on the previous RefreshRateConfigs instance // and cleanup the scheduler's state before we switch to the other RefreshRateConfigs. @@ -220,8 +207,8 @@ public: if (mRefreshRateConfigs) mRefreshRateConfigs->stopIdleTimer(); } { - std::scoped_lock lock(mFeatureStateLock); - mFeatures = {}; + std::scoped_lock lock(mPolicyLock); + mPolicy = {}; } { std::scoped_lock lock(mRefreshRateConfigsLock); @@ -251,18 +238,10 @@ private: using FrameHint = ISchedulerCallback::FrameHint; - // In order to make sure that the features don't override themselves, we need a state machine - // to keep track which feature requested the config change. enum class ContentDetectionState { Off, On }; enum class TimerState { Reset, Expired }; enum class TouchState { Inactive, Active }; - struct VsyncSchedule { - std::unique_ptr controller; - std::unique_ptr tracker; - std::unique_ptr dispatch; - }; - // Create a connection on the given EventThread. ConnectionHandle createConnection(std::unique_ptr); sp createConnectionInternal( @@ -284,19 +263,17 @@ private: // selection were initialized, prioritizes them, and calculates the DisplayModeId // for the suggested refresh rate. DisplayModePtr calculateRefreshRateModeId( - scheduler::RefreshRateConfigs::GlobalSignals* consideredSignals = nullptr) - REQUIRES(mFeatureStateLock); + RefreshRateConfigs::GlobalSignals* consideredSignals = nullptr) REQUIRES(mPolicyLock); - void dispatchCachedReportedMode() REQUIRES(mFeatureStateLock) EXCLUDES(mRefreshRateConfigsLock); - bool updateFrameRateOverrides(scheduler::RefreshRateConfigs::GlobalSignals consideredSignals, - Fps displayRefreshRate) REQUIRES(mFeatureStateLock) - EXCLUDES(mFrameRateOverridesLock); + void dispatchCachedReportedMode() REQUIRES(mPolicyLock) EXCLUDES(mRefreshRateConfigsLock); + bool updateFrameRateOverrides(RefreshRateConfigs::GlobalSignals, Fps displayRefreshRate) + REQUIRES(mPolicyLock) EXCLUDES(mFrameRateOverridesLock); impl::EventThread::ThrottleVsyncCallback makeThrottleVsyncCallback() const EXCLUDES(mRefreshRateConfigsLock); impl::EventThread::GetVsyncPeriodFunction makeGetVsyncPeriodFunction() const; - std::shared_ptr holdRefreshRateConfigs() const + std::shared_ptr holdRefreshRateConfigs() const EXCLUDES(mRefreshRateConfigsLock) { std::scoped_lock lock(mRefreshRateConfigsLock); return mRefreshRateConfigs; @@ -322,66 +299,63 @@ private: std::atomic mLastResyncTime = 0; - const Options mOptions; - VsyncSchedule mVsyncSchedule; + const FeatureFlags mFeatures; + std::optional mVsyncSchedule; // Used to choose refresh rate if content detection is enabled. LayerHistory mLayerHistory; // Timer used to monitor touch events. - std::optional mTouchTimer; + std::optional mTouchTimer; // Timer used to monitor display power mode. - std::optional mDisplayPowerTimer; + std::optional mDisplayPowerTimer; ISchedulerCallback& mSchedulerCallback; - // In order to make sure that the features don't override themselves, we need a state machine - // to keep track which feature requested the config change. - mutable std::mutex mFeatureStateLock; + mutable std::mutex mPolicyLock; struct { + // Policy for choosing the display mode. + LayerHistory::Summary contentRequirements; TimerState idleTimer = TimerState::Reset; TouchState touch = TouchState::Inactive; TimerState displayPowerTimer = TimerState::Expired; + bool isDisplayPowerStateNormal = true; + // Chosen display mode. DisplayModePtr mode; - LayerHistory::Summary contentRequirements; - - bool isDisplayPowerStateNormal = true; - // Used to cache the last parameters of onPrimaryDisplayModeChanged struct ModeChangedParams { ConnectionHandle handle; DisplayModePtr mode; }; + // Parameters for latest dispatch of mode change event. std::optional cachedModeChangedParams; - } mFeatures GUARDED_BY(mFeatureStateLock); + } mPolicy GUARDED_BY(mPolicyLock); mutable std::mutex mRefreshRateConfigsLock; - std::shared_ptr mRefreshRateConfigs - GUARDED_BY(mRefreshRateConfigsLock); + std::shared_ptr mRefreshRateConfigs GUARDED_BY(mRefreshRateConfigsLock); std::mutex mVsyncTimelineLock; std::optional mLastVsyncPeriodChangeTimeline GUARDED_BY(mVsyncTimelineLock); static constexpr std::chrono::nanoseconds MAX_VSYNC_APPLIED_TIME = 200ms; - std::unique_ptr mPredictedVsyncTracer; - // The frame rate override lists need their own mutex as they are being read // by SurfaceFlinger, Scheduler and EventThread (as a callback) to prevent deadlocks mutable std::mutex mFrameRateOverridesLock; // mappings between a UID and a preferred refresh rate that this app would // run at. - scheduler::RefreshRateConfigs::UidToFrameRateOverride mFrameRateOverridesByContent + RefreshRateConfigs::UidToFrameRateOverride mFrameRateOverridesByContent GUARDED_BY(mFrameRateOverridesLock); - scheduler::RefreshRateConfigs::UidToFrameRateOverride mFrameRateOverridesFromBackdoor + RefreshRateConfigs::UidToFrameRateOverride mFrameRateOverridesFromBackdoor GUARDED_BY(mFrameRateOverridesLock); // Keeps track of whether the screen is acquired for debug std::atomic mScreenAcquired = false; }; +} // namespace scheduler } // namespace android diff --git a/services/surfaceflinger/Scheduler/VSyncReactor.cpp b/services/surfaceflinger/Scheduler/VSyncReactor.cpp index ee973f718a..1c9de1c452 100644 --- a/services/surfaceflinger/Scheduler/VSyncReactor.cpp +++ b/services/surfaceflinger/Scheduler/VSyncReactor.cpp @@ -47,7 +47,7 @@ VSyncReactor::VSyncReactor(std::unique_ptr clock, VSyncTracker& tracker, VSyncReactor::~VSyncReactor() = default; -bool VSyncReactor::addPresentFence(const std::shared_ptr& fence) { +bool VSyncReactor::addPresentFence(std::shared_ptr fence) { if (!fence) { return false; } @@ -80,7 +80,7 @@ bool VSyncReactor::addPresentFence(const std::shared_ptr& fe if (mPendingLimit == mUnfiredFences.size()) { mUnfiredFences.erase(mUnfiredFences.begin()); } - mUnfiredFences.push_back(fence); + mUnfiredFences.push_back(std::move(fence)); } else { timestampAccepted &= mTracker.addVsyncTimestamp(signalTime); } diff --git a/services/surfaceflinger/Scheduler/VSyncReactor.h b/services/surfaceflinger/Scheduler/VSyncReactor.h index 449d4c3bee..a9d536be28 100644 --- a/services/surfaceflinger/Scheduler/VSyncReactor.h +++ b/services/surfaceflinger/Scheduler/VSyncReactor.h @@ -37,7 +37,7 @@ public: bool supportKernelIdleTimer); ~VSyncReactor(); - bool addPresentFence(const std::shared_ptr& fence) final; + bool addPresentFence(std::shared_ptr) final; void setIgnorePresentFences(bool ignore) final; void startPeriodTransition(nsecs_t period) final; diff --git a/services/surfaceflinger/Scheduler/VsyncController.h b/services/surfaceflinger/Scheduler/VsyncController.h index 0f0df222f4..59f65372a9 100644 --- a/services/surfaceflinger/Scheduler/VsyncController.h +++ b/services/surfaceflinger/Scheduler/VsyncController.h @@ -17,19 +17,15 @@ #pragma once #include +#include +#include #include #include #include -#include - -#include - namespace android::scheduler { -class FenceTime; - class VsyncController { public: virtual ~VsyncController(); @@ -43,7 +39,7 @@ public: * an accurate prediction, * False otherwise */ - virtual bool addPresentFence(const std::shared_ptr&) = 0; + virtual bool addPresentFence(std::shared_ptr) = 0; /* * Adds a hw sync timestamp to the model. The controller will use the timestamp diff --git a/services/surfaceflinger/Scheduler/VsyncSchedule.cpp b/services/surfaceflinger/Scheduler/VsyncSchedule.cpp new file mode 100644 index 0000000000..77d1223aeb --- /dev/null +++ b/services/surfaceflinger/Scheduler/VsyncSchedule.cpp @@ -0,0 +1,113 @@ +/* + * Copyright 2021 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#include + +#include "VsyncSchedule.h" + +#include "Timer.h" +#include "VSyncDispatchTimerQueue.h" +#include "VSyncPredictor.h" +#include "VSyncReactor.h" + +#include "../TracedOrdinal.h" + +namespace android::scheduler { + +class VsyncSchedule::PredictedVsyncTracer { + // Invoked from the thread of the VsyncDispatch owned by this VsyncSchedule. + constexpr auto makeVsyncCallback() { + return [this](nsecs_t, nsecs_t, nsecs_t) { + mParity = !mParity; + schedule(); + }; + } + +public: + explicit PredictedVsyncTracer(VsyncDispatch& dispatch) + : mRegistration(dispatch, makeVsyncCallback(), __func__) { + schedule(); + } + +private: + void schedule() { mRegistration.schedule({0, 0, 0}); } + + TracedOrdinal mParity = {"VSYNC-predicted", 0}; + VSyncCallbackRegistration mRegistration; +}; + +VsyncSchedule::VsyncSchedule(FeatureFlags features) + : mTracker(createTracker()), + mDispatch(createDispatch(*mTracker)), + mController(createController(*mTracker, features)) { + if (features.test(Feature::kTracePredictedVsync)) { + mTracer = std::make_unique(*mDispatch); + } +} + +VsyncSchedule::VsyncSchedule(TrackerPtr tracker, DispatchPtr dispatch, ControllerPtr controller) + : mTracker(std::move(tracker)), + mDispatch(std::move(dispatch)), + mController(std::move(controller)) {} + +VsyncSchedule::VsyncSchedule(VsyncSchedule&&) = default; +VsyncSchedule::~VsyncSchedule() = default; + +void VsyncSchedule::dump(std::string& out) const { + out.append("VsyncController:\n"); + mController->dump(out); + + out.append("VsyncDispatch:\n"); + mDispatch->dump(out); +} + +VsyncSchedule::TrackerPtr VsyncSchedule::createTracker() { + // TODO(b/144707443): Tune constants. + constexpr nsecs_t kInitialPeriod = (60_Hz).getPeriodNsecs(); + constexpr size_t kHistorySize = 20; + constexpr size_t kMinSamplesForPrediction = 6; + constexpr uint32_t kDiscardOutlierPercent = 20; + + return std::make_unique(kInitialPeriod, kHistorySize, kMinSamplesForPrediction, + kDiscardOutlierPercent); +} + +VsyncSchedule::DispatchPtr VsyncSchedule::createDispatch(VsyncTracker& tracker) { + using namespace std::chrono_literals; + + // TODO(b/144707443): Tune constants. + constexpr std::chrono::nanoseconds kGroupDispatchWithin = 500us; + constexpr std::chrono::nanoseconds kSnapToSameVsyncWithin = 3ms; + + return std::make_unique(std::make_unique(), tracker, + kGroupDispatchWithin.count(), + kSnapToSameVsyncWithin.count()); +} + +VsyncSchedule::ControllerPtr VsyncSchedule::createController(VsyncTracker& tracker, + FeatureFlags features) { + // TODO(b/144707443): Tune constants. + constexpr size_t kMaxPendingFences = 20; + const bool hasKernelIdleTimer = features.test(Feature::kKernelIdleTimer); + + auto reactor = std::make_unique(std::make_unique(), tracker, + kMaxPendingFences, hasKernelIdleTimer); + + reactor->setIgnorePresentFences(!features.test(Feature::kPresentFences)); + return reactor; +} + +} // namespace android::scheduler diff --git a/services/surfaceflinger/Scheduler/VsyncSchedule.h b/services/surfaceflinger/Scheduler/VsyncSchedule.h new file mode 100644 index 0000000000..0d9b114875 --- /dev/null +++ b/services/surfaceflinger/Scheduler/VsyncSchedule.h @@ -0,0 +1,75 @@ +/* + * Copyright 2021 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#pragma once + +#include +#include + +#include + +namespace android::scheduler { + +// TODO(b/185535769): Rename classes, and remove aliases. +class VSyncDispatch; +class VSyncTracker; + +class VsyncController; +using VsyncDispatch = VSyncDispatch; +using VsyncTracker = VSyncTracker; + +// Schedule that synchronizes to hardware VSYNC of a physical display. +class VsyncSchedule { +public: + explicit VsyncSchedule(FeatureFlags); + VsyncSchedule(VsyncSchedule&&); + ~VsyncSchedule(); + + // TODO(b/185535769): Hide behind API. + const VsyncTracker& getTracker() const { return *mTracker; } + VsyncTracker& getTracker() { return *mTracker; } + VsyncController& getController() { return *mController; } + + // TODO(b/185535769): Remove once VsyncSchedule owns all registrations. + VsyncDispatch& getDispatch() { return *mDispatch; } + + void dump(std::string&) const; + +private: + friend class TestableScheduler; + + using TrackerPtr = std::unique_ptr; + using DispatchPtr = std::unique_ptr; + using ControllerPtr = std::unique_ptr; + + // For tests. + VsyncSchedule(TrackerPtr, DispatchPtr, ControllerPtr); + + static TrackerPtr createTracker(); + static DispatchPtr createDispatch(VsyncTracker&); + static ControllerPtr createController(VsyncTracker&, FeatureFlags); + + class PredictedVsyncTracer; + using TracerPtr = std::unique_ptr; + + // Effectively const except in move constructor. + TrackerPtr mTracker; + DispatchPtr mDispatch; + ControllerPtr mController; + TracerPtr mTracer; +}; + +} // namespace android::scheduler diff --git a/services/surfaceflinger/Scheduler/include/scheduler/Features.h b/services/surfaceflinger/Scheduler/include/scheduler/Features.h new file mode 100644 index 0000000000..0e96678420 --- /dev/null +++ b/services/surfaceflinger/Scheduler/include/scheduler/Features.h @@ -0,0 +1,34 @@ +/* + * Copyright 2021 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#pragma once + +#include + +#include + +namespace android::scheduler { + +enum class Feature : std::uint8_t { + kPresentFences = 0b1, + kKernelIdleTimer = 0b10, + kContentDetection = 0b100, + kTracePredictedVsync = 0b1000, +}; + +using FeatureFlags = Flags; + +} // namespace android::scheduler diff --git a/services/surfaceflinger/SurfaceFlinger.cpp b/services/surfaceflinger/SurfaceFlinger.cpp index e497d95306..3860901edb 100644 --- a/services/surfaceflinger/SurfaceFlinger.cpp +++ b/services/surfaceflinger/SurfaceFlinger.cpp @@ -1200,7 +1200,7 @@ void SurfaceFlinger::updateInternalStateWithChangedMode() { mRefreshRateStats->setRefreshRate(refreshRate); updatePhaseConfiguration(refreshRate); - if (upcomingModeInfo.event != Scheduler::ModeEvent::None) { + if (upcomingModeInfo.event != DisplayModeEvent::None) { mScheduler->onPrimaryDisplayModeChanged(mAppConnectionHandle, upcomingModeInfo.mode); } } @@ -3099,7 +3099,7 @@ void SurfaceFlinger::updateCursorAsync() { mCompositionEngine->updateCursorAsync(refreshArgs); } -void SurfaceFlinger::changeRefreshRate(const RefreshRate& refreshRate, Scheduler::ModeEvent event) { +void SurfaceFlinger::changeRefreshRate(const RefreshRate& refreshRate, DisplayModeEvent event) { // If this is called from the main thread mStateLock must be locked before // Currently the only way to call this function from the main thread is from // Scheduler::chooseRefreshRateForContent @@ -3147,17 +3147,32 @@ void SurfaceFlinger::initScheduler(const sp& display) { mVsyncConfiguration = getFactory().createVsyncConfiguration(currRefreshRate); mVsyncModulator = sp::make(mVsyncConfiguration->getCurrentConfigs()); - const Scheduler::Options options = { - .useContentDetection = sysprop::use_content_detection_for_refresh_rate(false)}; + using Feature = scheduler::Feature; + scheduler::FeatureFlags features; - mScheduler = std::make_unique(static_cast(*this), - static_cast(*this), options); + if (sysprop::use_content_detection_for_refresh_rate(false)) { + features |= Feature::kContentDetection; + } + if (base::GetBoolProperty("debug.sf.show_predicted_vsync"s, false)) { + features |= Feature::kTracePredictedVsync; + } + if (!base::GetBoolProperty("debug.sf.vsync_reactor_ignore_present_fences"s, false) && + !getHwComposer().hasCapability(hal::Capability::PRESENT_FENCE_IS_NOT_RELIABLE)) { + features |= Feature::kPresentFences; + } + + mScheduler = std::make_unique(static_cast(*this), + static_cast(*this), + features); { auto configs = display->holdRefreshRateConfigs(); - mScheduler->createVsyncSchedule(configs->supportsKernelIdleTimer()); + if (configs->supportsKernelIdleTimer()) { + features |= Feature::kKernelIdleTimer; + } + + mScheduler->createVsyncSchedule(features); mScheduler->setRefreshRateConfigs(std::move(configs)); } - setVsyncEnabled(false); mScheduler->startTimers(); @@ -3190,11 +3205,6 @@ void SurfaceFlinger::initScheduler(const sp& display) { // classes from EventThread, and there should be no run-time binder cost // anyway since there are no connected apps at this point. mScheduler->onPrimaryDisplayModeChanged(mAppConnectionHandle, display->getActiveMode()); - static auto ignorePresentFences = - base::GetBoolProperty("debug.sf.vsync_reactor_ignore_present_fences"s, false); - mScheduler->setIgnorePresentFences( - ignorePresentFences || - getHwComposer().hasCapability(hal::Capability::PRESENT_FENCE_IS_NOT_RELIABLE)); } void SurfaceFlinger::updatePhaseConfiguration(const Fps& refreshRate) { @@ -3818,10 +3828,11 @@ bool SurfaceFlinger::applyTransactionState(const FrameTimelineInfo& frameTimelin clientStateFlags |= setClientStateLocked(frameTimelineInfo, state, desiredPresentTime, isAutoTimestamp, postTime, permissions); if ((flags & eAnimation) && state.state.surface) { - if (const auto layer = fromHandle(state.state.surface).promote(); layer) { + if (const auto layer = fromHandle(state.state.surface).promote()) { + using LayerUpdateType = scheduler::LayerHistory::LayerUpdateType; mScheduler->recordLayerHistory(layer.get(), isAutoTimestamp ? 0 : desiredPresentTime, - LayerHistory::LayerUpdateType::AnimationTX); + LayerUpdateType::AnimationTX); } } } @@ -6478,7 +6489,7 @@ status_t SurfaceFlinger::setDesiredDisplayModeSpecsInternal( if (display->refreshRateConfigs().isModeAllowed(preferredDisplayMode->getId())) { ALOGV("switching to Scheduler preferred display mode %d", preferredDisplayMode->getId().value()); - setDesiredActiveMode({preferredDisplayMode, Scheduler::ModeEvent::Changed}); + setDesiredActiveMode({preferredDisplayMode, DisplayModeEvent::Changed}); } else { LOG_ALWAYS_FATAL("Desired display mode not allowed: %d", preferredDisplayMode->getId().value()); diff --git a/services/surfaceflinger/SurfaceFlinger.h b/services/surfaceflinger/SurfaceFlinger.h index 05c058b9af..eb934b6b16 100644 --- a/services/surfaceflinger/SurfaceFlinger.h +++ b/services/surfaceflinger/SurfaceFlinger.h @@ -165,7 +165,7 @@ class SurfaceFlinger : public BnSurfaceComposer, private IBinder::DeathRecipient, private HWC2::ComposerCallback, private ICompositor, - private ISchedulerCallback { + private scheduler::ISchedulerCallback { public: struct SkipInitializationTag {}; @@ -356,7 +356,6 @@ private: friend class TransactionApplicationTest; friend class TunnelModeEnabledReporterTest; - using RefreshRate = scheduler::RefreshRateConfigs::RefreshRate; using VsyncModulator = scheduler::VsyncModulator; using TransactionSchedule = scheduler::TransactionSchedule; using TraverseLayersFunction = std::function; @@ -643,7 +642,7 @@ private: // Toggles hardware VSYNC by calling into HWC. void setVsyncEnabled(bool) override; // Initiates a refresh rate change to be applied on commit. - void changeRefreshRate(const Scheduler::RefreshRate&, Scheduler::ModeEvent) override; + void changeRefreshRate(const RefreshRate&, DisplayModeEvent) override; // Called when kernel idle timer has expired. Used to update the refresh rate overlay. void kernelTimerChanged(bool expired) override; // Called when the frame rate override list changed to trigger an event. @@ -1261,7 +1260,7 @@ private: /* * Scheduler */ - std::unique_ptr mScheduler; + std::unique_ptr mScheduler; scheduler::ConnectionHandle mAppConnectionHandle; scheduler::ConnectionHandle mSfConnectionHandle; diff --git a/services/surfaceflinger/SurfaceFlingerFactory.h b/services/surfaceflinger/SurfaceFlingerFactory.h index e509cc9385..6153e8e354 100644 --- a/services/surfaceflinger/SurfaceFlingerFactory.h +++ b/services/surfaceflinger/SurfaceFlingerFactory.h @@ -42,16 +42,12 @@ class HWComposer; class IGraphicBufferConsumer; class IGraphicBufferProducer; class Layer; -class MessageQueue; -class Scheduler; class StartPropertySetThread; class SurfaceFlinger; class SurfaceInterceptor; class TimeStats; struct DisplayDeviceCreationArgs; -struct ICompositor; -struct ISchedulerCallback; struct LayerCreationArgs; namespace compositionengine { diff --git a/services/surfaceflinger/tests/unittests/CompositionTest.cpp b/services/surfaceflinger/tests/unittests/CompositionTest.cpp index 8d2c078305..eb5f31e796 100644 --- a/services/surfaceflinger/tests/unittests/CompositionTest.cpp +++ b/services/surfaceflinger/tests/unittests/CompositionTest.cpp @@ -138,7 +138,7 @@ public: .WillRepeatedly(Return(FakeHwcDisplayInjector::DEFAULT_VSYNC_PERIOD)); EXPECT_CALL(*vsyncTracker, nextAnticipatedVSyncTimeFrom(_)).WillRepeatedly(Return(0)); - constexpr ISchedulerCallback* kCallback = nullptr; + constexpr scheduler::ISchedulerCallback* kCallback = nullptr; constexpr bool kHasMultipleConfigs = true; mFlinger.setupScheduler(std::move(vsyncController), std::move(vsyncTracker), std::move(eventThread), std::move(sfEventThread), kCallback, diff --git a/services/surfaceflinger/tests/unittests/DisplayDevice_InitiateModeChange.cpp b/services/surfaceflinger/tests/unittests/DisplayDevice_InitiateModeChange.cpp index d4cfbbbe0c..5a0033ea7e 100644 --- a/services/surfaceflinger/tests/unittests/DisplayDevice_InitiateModeChange.cpp +++ b/services/surfaceflinger/tests/unittests/DisplayDevice_InitiateModeChange.cpp @@ -29,7 +29,7 @@ using FakeDisplayDeviceInjector = TestableSurfaceFlinger::FakeDisplayDeviceInjec class InitiateModeChangeTest : public DisplayTransactionTest { public: - using Event = scheduler::RefreshRateConfigEvent; + using Event = scheduler::DisplayModeEvent; void SetUp() override { injectFakeBufferQueueFactory(); diff --git a/services/surfaceflinger/tests/unittests/DisplayTransactionTestHelpers.h b/services/surfaceflinger/tests/unittests/DisplayTransactionTestHelpers.h index de5e9dfb97..0a3437aab9 100644 --- a/services/surfaceflinger/tests/unittests/DisplayTransactionTestHelpers.h +++ b/services/surfaceflinger/tests/unittests/DisplayTransactionTestHelpers.h @@ -121,7 +121,7 @@ public: mock::VsyncController* mVsyncController = new mock::VsyncController; mock::VSyncTracker* mVSyncTracker = new mock::VSyncTracker; - mock::SchedulerCallback mSchedulerCallback; + scheduler::mock::SchedulerCallback mSchedulerCallback; mock::EventThread* mEventThread = new mock::EventThread; mock::EventThread* mSFEventThread = new mock::EventThread; diff --git a/services/surfaceflinger/tests/unittests/FpsReporterTest.cpp b/services/surfaceflinger/tests/unittests/FpsReporterTest.cpp index cd2fc7426e..bb1f4328b5 100644 --- a/services/surfaceflinger/tests/unittests/FpsReporterTest.cpp +++ b/services/surfaceflinger/tests/unittests/FpsReporterTest.cpp @@ -17,6 +17,8 @@ #undef LOG_TAG #define LOG_TAG "FpsReporterTest" +#include + #include #include #include @@ -36,6 +38,8 @@ namespace android { +using namespace std::chrono_literals; + using testing::_; using testing::DoAll; using testing::Mock; diff --git a/services/surfaceflinger/tests/unittests/LayerHistoryTest.cpp b/services/surfaceflinger/tests/unittests/LayerHistoryTest.cpp index 4993a2d8bc..00687ad4b6 100644 --- a/services/surfaceflinger/tests/unittests/LayerHistoryTest.cpp +++ b/services/surfaceflinger/tests/unittests/LayerHistoryTest.cpp @@ -38,9 +38,9 @@ using testing::_; using testing::Return; using testing::ReturnRef; -namespace android { +namespace android::scheduler { -namespace scheduler { +using MockLayer = android::mock::MockLayer; class LayerHistoryTest : public testing::Test { protected: @@ -93,12 +93,12 @@ protected: } } - auto createLayer() { return sp(new mock::MockLayer(mFlinger.flinger())); } + auto createLayer() { return sp::make(mFlinger.flinger()); } auto createLayer(std::string name) { - return sp(new mock::MockLayer(mFlinger.flinger(), std::move(name))); + return sp::make(mFlinger.flinger(), std::move(name)); } - void recordFramesAndExpect(const sp& layer, nsecs_t& time, Fps frameRate, + void recordFramesAndExpect(const sp& layer, nsecs_t& time, Fps frameRate, Fps desiredRefreshRate, int numFrames) { LayerHistory::Summary summary; for (int i = 0; i < numFrames; i++) { @@ -768,8 +768,7 @@ INSTANTIATE_TEST_CASE_P(LeapYearTests, LayerHistoryTestParameterized, ::testing::Values(1s, 2s, 3s, 4s, 5s)); } // namespace -} // namespace scheduler -} // namespace android +} // namespace android::scheduler // TODO(b/129481165): remove the #pragma below and fix conversion issues #pragma clang diagnostic pop // ignored "-Wextra" diff --git a/services/surfaceflinger/tests/unittests/SchedulerTest.cpp b/services/surfaceflinger/tests/unittests/SchedulerTest.cpp index e558f3b700..a6fd378d3d 100644 --- a/services/surfaceflinger/tests/unittests/SchedulerTest.cpp +++ b/services/surfaceflinger/tests/unittests/SchedulerTest.cpp @@ -28,12 +28,16 @@ #include "mock/MockLayer.h" #include "mock/MockSchedulerCallback.h" +namespace android::scheduler { + using testing::_; using testing::Return; -namespace android { namespace { +using MockEventThread = android::mock::EventThread; +using MockLayer = android::mock::MockLayer; + constexpr PhysicalDisplayId PHYSICAL_DISPLAY_ID = PhysicalDisplayId::fromPort(255u); class SchedulerTest : public testing::Test { @@ -64,21 +68,21 @@ protected: .setGroup(0) .build(); - std::shared_ptr mConfigs = - std::make_shared(DisplayModes{mode60}, mode60->getId()); + std::shared_ptr mConfigs = + std::make_shared(DisplayModes{mode60}, mode60->getId()); mock::SchedulerCallback mSchedulerCallback; TestableScheduler* mScheduler = new TestableScheduler{mConfigs, mSchedulerCallback}; - Scheduler::ConnectionHandle mConnectionHandle; - mock::EventThread* mEventThread; + ConnectionHandle mConnectionHandle; + MockEventThread* mEventThread; sp mEventThreadConnection; TestableSurfaceFlinger mFlinger; }; SchedulerTest::SchedulerTest() { - auto eventThread = std::make_unique(); + auto eventThread = std::make_unique(); mEventThread = eventThread.get(); EXPECT_CALL(*mEventThread, registerDisplayEventConnection(_)).WillOnce(Return(0)); @@ -98,7 +102,7 @@ SchedulerTest::SchedulerTest() { } // namespace TEST_F(SchedulerTest, invalidConnectionHandle) { - Scheduler::ConnectionHandle handle; + ConnectionHandle handle; const sp connection = mScheduler->createDisplayEventConnection(handle); @@ -155,7 +159,7 @@ TEST_F(SchedulerTest, validConnectionHandle) { TEST_F(SchedulerTest, chooseRefreshRateForContentIsNoopWhenModeSwitchingIsNotSupported) { // The layer is registered at creation time and deregistered at destruction time. - sp layer = sp::make(mFlinger.flinger()); + sp layer = sp::make(mFlinger.flinger()); // recordLayerHistory should be a noop ASSERT_EQ(0u, mScheduler->getNumActiveLayers()); @@ -174,24 +178,22 @@ TEST_F(SchedulerTest, chooseRefreshRateForContentIsNoopWhenModeSwitchingIsNotSup TEST_F(SchedulerTest, updateDisplayModes) { ASSERT_EQ(0u, mScheduler->layerHistorySize()); - sp layer = sp::make(mFlinger.flinger()); + sp layer = sp::make(mFlinger.flinger()); ASSERT_EQ(1u, mScheduler->layerHistorySize()); mScheduler->setRefreshRateConfigs( - std::make_shared(DisplayModes{mode60, mode120}, - mode60->getId())); + std::make_shared(DisplayModes{mode60, mode120}, mode60->getId())); ASSERT_EQ(0u, mScheduler->getNumActiveLayers()); mScheduler->recordLayerHistory(layer.get(), 0, LayerHistory::LayerUpdateType::Buffer); ASSERT_EQ(1u, mScheduler->getNumActiveLayers()); } -TEST_F(SchedulerTest, testDispatchCachedReportedMode) { - // If the optional fields are cleared, the function should return before - // onModeChange is called. - mScheduler->clearOptionalFieldsInFeatures(); - EXPECT_NO_FATAL_FAILURE(mScheduler->dispatchCachedReportedMode()); +TEST_F(SchedulerTest, dispatchCachedReportedMode) { + mScheduler->clearCachedReportedMode(); + EXPECT_CALL(*mEventThread, onModeChanged(_)).Times(0); + EXPECT_NO_FATAL_FAILURE(mScheduler->dispatchCachedReportedMode()); } TEST_F(SchedulerTest, onNonPrimaryDisplayModeChanged_invalidParameters) { @@ -203,7 +205,7 @@ TEST_F(SchedulerTest, onNonPrimaryDisplayModeChanged_invalidParameters) { // If the handle is incorrect, the function should return before // onModeChange is called. - Scheduler::ConnectionHandle invalidHandle = {.id = 123}; + ConnectionHandle invalidHandle = {.id = 123}; EXPECT_NO_FATAL_FAILURE(mScheduler->onNonPrimaryDisplayModeChanged(invalidHandle, mode)); EXPECT_CALL(*mEventThread, onModeChanged(_)).Times(0); } @@ -224,10 +226,9 @@ MATCHER(Is120Hz, "") { TEST_F(SchedulerTest, chooseRefreshRateForContentSelectsMaxRefreshRate) { mScheduler->setRefreshRateConfigs( - std::make_shared(DisplayModes{mode60, mode120}, - mode60->getId())); + std::make_shared(DisplayModes{mode60, mode120}, mode60->getId())); - sp layer = sp::make(mFlinger.flinger()); + sp layer = sp::make(mFlinger.flinger()); mScheduler->recordLayerHistory(layer.get(), 0, LayerHistory::LayerUpdateType::Buffer); @@ -241,4 +242,4 @@ TEST_F(SchedulerTest, chooseRefreshRateForContentSelectsMaxRefreshRate) { mScheduler->chooseRefreshRateForContent(); } -} // namespace android +} // namespace android::scheduler diff --git a/services/surfaceflinger/tests/unittests/SetFrameRateTest.cpp b/services/surfaceflinger/tests/unittests/SetFrameRateTest.cpp index eed62a70c3..fe5f9e0717 100644 --- a/services/surfaceflinger/tests/unittests/SetFrameRateTest.cpp +++ b/services/surfaceflinger/tests/unittests/SetFrameRateTest.cpp @@ -48,6 +48,8 @@ using android::Hwc2::IComposerClient; using FakeHwcDisplayInjector = TestableSurfaceFlinger::FakeHwcDisplayInjector; +using scheduler::LayerHistory; + using FrameRate = Layer::FrameRate; using FrameRateCompatibility = Layer::FrameRateCompatibility; diff --git a/services/surfaceflinger/tests/unittests/SurfaceFlinger_NotifyPowerBoostTest.cpp b/services/surfaceflinger/tests/unittests/SurfaceFlinger_NotifyPowerBoostTest.cpp index 69e0501bd6..ec7e8a7f82 100644 --- a/services/surfaceflinger/tests/unittests/SurfaceFlinger_NotifyPowerBoostTest.cpp +++ b/services/surfaceflinger/tests/unittests/SurfaceFlinger_NotifyPowerBoostTest.cpp @@ -17,6 +17,9 @@ #undef LOG_TAG #define LOG_TAG "LibSurfaceFlingerUnittests" +#include +#include + #include "DisplayTransactionTestHelpers.h" #include @@ -27,6 +30,8 @@ namespace { using android::hardware::power::Boost; TEST_F(DisplayTransactionTest, notifyPowerBoostNotifiesTouchEvent) { + using namespace std::chrono_literals; + mFlinger.scheduler()->replaceTouchTimer(100); std::this_thread::sleep_for(10ms); // wait for callback to be triggered EXPECT_TRUE(mFlinger.scheduler()->isTouchActive()); // Starting timer activates touch @@ -47,4 +52,4 @@ TEST_F(DisplayTransactionTest, notifyPowerBoostNotifiesTouchEvent) { } } // namespace -} // namespace android \ No newline at end of file +} // namespace android diff --git a/services/surfaceflinger/tests/unittests/TestableScheduler.h b/services/surfaceflinger/tests/unittests/TestableScheduler.h index 9d1fc981aa..dabd2d2cc2 100644 --- a/services/surfaceflinger/tests/unittests/TestableScheduler.h +++ b/services/surfaceflinger/tests/unittests/TestableScheduler.h @@ -28,22 +28,20 @@ #include "mock/MockVSyncTracker.h" #include "mock/MockVsyncController.h" -namespace android { +namespace android::scheduler { class TestableScheduler : public Scheduler, private ICompositor { public: - TestableScheduler(std::shared_ptr configs, - ISchedulerCallback& callback) + TestableScheduler(std::shared_ptr configs, ISchedulerCallback& callback) : TestableScheduler(std::make_unique(), std::make_unique(), std::move(configs), callback) {} - TestableScheduler(std::unique_ptr vsyncController, - std::unique_ptr vsyncTracker, - std::shared_ptr configs, - ISchedulerCallback& callback) - : Scheduler(*this, callback, {.useContentDetection = true}) { - mVsyncSchedule = {std::move(vsyncController), std::move(vsyncTracker), nullptr}; + TestableScheduler(std::unique_ptr controller, + std::unique_ptr tracker, + std::shared_ptr configs, ISchedulerCallback& callback) + : Scheduler(*this, callback, Feature::kContentDetection) { + mVsyncSchedule.emplace(VsyncSchedule(std::move(tracker), nullptr, std::move(controller))); setRefreshRateConfigs(std::move(configs)); ON_CALL(*this, postMessage).WillByDefault([](sp&& handler) { @@ -86,33 +84,24 @@ public: } bool isTouchActive() { - std::lock_guard lock(mFeatureStateLock); - return mFeatures.touch == Scheduler::TouchState::Active; + std::lock_guard lock(mPolicyLock); + return mPolicy.touch == Scheduler::TouchState::Active; } void dispatchCachedReportedMode() { - std::lock_guard lock(mFeatureStateLock); + std::lock_guard lock(mPolicyLock); return Scheduler::dispatchCachedReportedMode(); } - void clearOptionalFieldsInFeatures() { - std::lock_guard lock(mFeatureStateLock); - mFeatures.cachedModeChangedParams.reset(); + void clearCachedReportedMode() { + std::lock_guard lock(mPolicyLock); + mPolicy.cachedModeChangedParams.reset(); } void onNonPrimaryDisplayModeChanged(ConnectionHandle handle, DisplayModePtr mode) { return Scheduler::onNonPrimaryDisplayModeChanged(handle, mode); } - ~TestableScheduler() { - // All these pointer and container clears help ensure that GMock does - // not report a leaked object, since the Scheduler instance may - // still be referenced by something despite our best efforts to destroy - // it after each test is done. - mVsyncSchedule.controller.reset(); - mConnections.clear(); - } - private: // ICompositor overrides: bool commit(nsecs_t, int64_t, nsecs_t) override { return false; } @@ -120,4 +109,4 @@ private: void sample() override {} }; -} // namespace android +} // namespace android::scheduler diff --git a/services/surfaceflinger/tests/unittests/TestableSurfaceFlinger.h b/services/surfaceflinger/tests/unittests/TestableSurfaceFlinger.h index 4c5789e47f..4473e01c2b 100644 --- a/services/surfaceflinger/tests/unittests/TestableSurfaceFlinger.h +++ b/services/surfaceflinger/tests/unittests/TestableSurfaceFlinger.h @@ -169,12 +169,12 @@ public: } // namespace surfaceflinger::test -class TestableSurfaceFlinger final : private ISchedulerCallback { +class TestableSurfaceFlinger final : private scheduler::ISchedulerCallback { public: using HotplugEvent = SurfaceFlinger::HotplugEvent; SurfaceFlinger* flinger() { return mFlinger.get(); } - TestableScheduler* scheduler() { return mScheduler; } + scheduler::TestableScheduler* scheduler() { return mScheduler; } // Extend this as needed for accessing SurfaceFlinger private (and public) // functions. @@ -197,7 +197,8 @@ public: std::unique_ptr vsyncTracker, std::unique_ptr appEventThread, std::unique_ptr sfEventThread, - ISchedulerCallback* callback = nullptr, bool hasMultipleModes = false) { + scheduler::ISchedulerCallback* callback = nullptr, + bool hasMultipleModes = false) { DisplayModes modes{DisplayMode::Builder(0) .setId(DisplayModeId(0)) .setPhysicalDisplayId(PhysicalDisplayId::fromPort(0)) @@ -224,17 +225,18 @@ public: std::make_unique(*mFlinger->mTimeStats, currFps, /*powerMode=*/hal::PowerMode::OFF); - mScheduler = new TestableScheduler(std::move(vsyncController), std::move(vsyncTracker), - mRefreshRateConfigs, *(callback ?: this)); + mScheduler = new scheduler::TestableScheduler(std::move(vsyncController), + std::move(vsyncTracker), mRefreshRateConfigs, + *(callback ?: this)); mFlinger->mAppConnectionHandle = mScheduler->createConnection(std::move(appEventThread)); mFlinger->mSfConnectionHandle = mScheduler->createConnection(std::move(sfEventThread)); resetScheduler(mScheduler); } - void resetScheduler(Scheduler* scheduler) { mFlinger->mScheduler.reset(scheduler); } + void resetScheduler(scheduler::Scheduler* scheduler) { mFlinger->mScheduler.reset(scheduler); } - TestableScheduler& mutableScheduler() const { return *mScheduler; } + scheduler::TestableScheduler& mutableScheduler() const { return *mScheduler; } using CreateBufferQueueFunction = surfaceflinger::test::Factory::CreateBufferQueueFunction; void setCreateBufferQueueFunction(CreateBufferQueueFunction f) { @@ -759,13 +761,13 @@ public: private: void scheduleComposite(FrameHint) override {} void setVsyncEnabled(bool) override {} - void changeRefreshRate(const Scheduler::RefreshRate&, Scheduler::ModeEvent) override {} + void changeRefreshRate(const RefreshRate&, DisplayModeEvent) override {} void kernelTimerChanged(bool) override {} void triggerOnFrameRateOverridesChanged() {} surfaceflinger::test::Factory mFactory; sp mFlinger = new SurfaceFlinger(mFactory, SurfaceFlinger::SkipInitialization); - TestableScheduler* mScheduler = nullptr; + scheduler::TestableScheduler* mScheduler = nullptr; std::shared_ptr mRefreshRateConfigs; }; diff --git a/services/surfaceflinger/tests/unittests/TransactionApplicationTest.cpp b/services/surfaceflinger/tests/unittests/TransactionApplicationTest.cpp index ec19100c2b..16d4b59250 100644 --- a/services/surfaceflinger/tests/unittests/TransactionApplicationTest.cpp +++ b/services/surfaceflinger/tests/unittests/TransactionApplicationTest.cpp @@ -26,7 +26,7 @@ #include #include #include -#include "TestableScheduler.h" + #include "TestableSurfaceFlinger.h" #include "mock/MockEventThread.h" #include "mock/MockVsyncController.h" @@ -85,11 +85,8 @@ public: std::move(eventThread), std::move(sfEventThread)); } - TestableScheduler* mScheduler; TestableSurfaceFlinger mFlinger; - std::unique_ptr mEventThread = std::make_unique(); - mock::VsyncController* mVsyncController = new mock::VsyncController(); mock::VSyncTracker* mVSyncTracker = new mock::VSyncTracker(); mock::MockFence* mFenceUnsignaled = new mock::MockFence(); diff --git a/services/surfaceflinger/tests/unittests/mock/MockSchedulerCallback.h b/services/surfaceflinger/tests/unittests/mock/MockSchedulerCallback.h index e241dc903f..849e3083c4 100644 --- a/services/surfaceflinger/tests/unittests/mock/MockSchedulerCallback.h +++ b/services/surfaceflinger/tests/unittests/mock/MockSchedulerCallback.h @@ -20,25 +20,22 @@ #include "Scheduler/Scheduler.h" -namespace android::mock { +namespace android::scheduler::mock { struct SchedulerCallback final : ISchedulerCallback { MOCK_METHOD(void, scheduleComposite, (FrameHint), (override)); - MOCK_METHOD1(setVsyncEnabled, void(bool)); - MOCK_METHOD2(changeRefreshRate, - void(const scheduler::RefreshRateConfigs::RefreshRate&, - scheduler::RefreshRateConfigEvent)); - MOCK_METHOD1(kernelTimerChanged, void(bool)); - MOCK_METHOD0(triggerOnFrameRateOverridesChanged, void()); + MOCK_METHOD(void, setVsyncEnabled, (bool), (override)); + MOCK_METHOD(void, changeRefreshRate, (const RefreshRate&, DisplayModeEvent), (override)); + MOCK_METHOD(void, kernelTimerChanged, (bool), (override)); + MOCK_METHOD(void, triggerOnFrameRateOverridesChanged, (), (override)); }; struct NoOpSchedulerCallback final : ISchedulerCallback { void scheduleComposite(FrameHint) override {} void setVsyncEnabled(bool) override {} - void changeRefreshRate(const scheduler::RefreshRateConfigs::RefreshRate&, - scheduler::RefreshRateConfigEvent) override {} + void changeRefreshRate(const RefreshRate&, DisplayModeEvent) override {} void kernelTimerChanged(bool) override {} void triggerOnFrameRateOverridesChanged() {} }; -} // namespace android::mock +} // namespace android::scheduler::mock diff --git a/services/surfaceflinger/tests/unittests/mock/MockVsyncController.h b/services/surfaceflinger/tests/unittests/mock/MockVsyncController.h index 94d99665ce..314f681545 100644 --- a/services/surfaceflinger/tests/unittests/mock/MockVsyncController.h +++ b/services/surfaceflinger/tests/unittests/mock/MockVsyncController.h @@ -27,7 +27,7 @@ public: VsyncController(); ~VsyncController() override; - MOCK_METHOD1(addPresentFence, bool(const std::shared_ptr&)); + MOCK_METHOD(bool, addPresentFence, (std::shared_ptr), (override)); MOCK_METHOD3(addHwVsyncTimestamp, bool(nsecs_t, std::optional, bool*)); MOCK_METHOD1(startPeriodTransition, void(nsecs_t)); MOCK_METHOD1(setIgnorePresentFences, void(bool)); -- cgit v1.2.3-59-g8ed1b From 8977ce95657dd39d9b814bc4d2a4ca7817e425e0 Mon Sep 17 00:00:00 2001 From: Alec Mouri Date: Sat, 7 May 2022 00:34:50 +0000 Subject: Remove consumer frame event history At this point only used in a part of dumpsys that no one checks, and is churning a bunch of fd cost. Bug: 231762515 Test: builds Change-Id: Iaaba87a236971920b302960c5a09d9c01253d562 --- services/surfaceflinger/BufferLayer.cpp | 15 ++------- services/surfaceflinger/BufferLayer.h | 2 +- services/surfaceflinger/BufferLayerConsumer.cpp | 12 ------- services/surfaceflinger/BufferLayerConsumer.h | 3 +- services/surfaceflinger/BufferQueueLayer.cpp | 19 ++--------- services/surfaceflinger/BufferQueueLayer.h | 2 +- services/surfaceflinger/BufferStateLayer.cpp | 30 +---------------- services/surfaceflinger/BufferStateLayer.h | 4 +-- services/surfaceflinger/Layer.cpp | 38 ---------------------- services/surfaceflinger/Layer.h | 14 -------- services/surfaceflinger/SurfaceFlinger.cpp | 8 ----- services/surfaceflinger/SurfaceFlinger.h | 2 -- .../fuzzer/surfaceflinger_fuzzers_utils.h | 3 -- .../fuzzer/surfaceflinger_layer_fuzzer.cpp | 2 -- 14 files changed, 10 insertions(+), 144 deletions(-) (limited to 'services/surfaceflinger/BufferQueueLayer.cpp') diff --git a/services/surfaceflinger/BufferLayer.cpp b/services/surfaceflinger/BufferLayer.cpp index 635b0884d9..f8c53c338e 100644 --- a/services/surfaceflinger/BufferLayer.cpp +++ b/services/surfaceflinger/BufferLayer.cpp @@ -315,11 +315,7 @@ void BufferLayer::preparePerFrameCompositionState() { compositionState->sidebandStreamHasFrame = false; } -bool BufferLayer::onPreComposition(nsecs_t refreshStartTime) { - if (mBufferInfo.mBuffer != nullptr) { - Mutex::Autolock lock(mFrameEventHistoryMutex); - mFrameEventHistory.addPreComposition(mCurrentFrameNumber, refreshStartTime); - } +bool BufferLayer::onPreComposition(nsecs_t) { return hasReadyFrame(); } namespace { @@ -365,12 +361,7 @@ void BufferLayer::onPostComposition(const DisplayDevice* display, mAlreadyDisplayedThisCompose = false; // Update mFrameEventHistory. - { - Mutex::Autolock lock(mFrameEventHistoryMutex); - mFrameEventHistory.addPostComposition(mCurrentFrameNumber, glDoneFence, presentFence, - compositorTiming); - finalizeFrameEventHistory(glDoneFence, compositorTiming); - } + finalizeFrameEventHistory(glDoneFence, compositorTiming); // Update mFrameTracker. nsecs_t desiredPresentTime = mBufferInfo.mDesiredPresentTime; @@ -500,7 +491,7 @@ bool BufferLayer::latchBuffer(bool& recomputeVisibleRegions, nsecs_t latchTime, return false; } - err = updateFrameNumber(latchTime); + err = updateFrameNumber(); if (err != NO_ERROR) { return false; } diff --git a/services/surfaceflinger/BufferLayer.h b/services/surfaceflinger/BufferLayer.h index 3e70493101..4c70eb58bf 100644 --- a/services/surfaceflinger/BufferLayer.h +++ b/services/surfaceflinger/BufferLayer.h @@ -192,7 +192,7 @@ private: nsecs_t expectedPresentTime) = 0; virtual status_t updateActiveBuffer() = 0; - virtual status_t updateFrameNumber(nsecs_t latchTime) = 0; + virtual status_t updateFrameNumber() = 0; // We generate InputWindowHandles for all non-cursor buffered layers regardless of whether they // have an InputChannel. This is to enable the InputDispatcher to do PID based occlusion diff --git a/services/surfaceflinger/BufferLayerConsumer.cpp b/services/surfaceflinger/BufferLayerConsumer.cpp index 9ae45fc4cb..7361a4fdef 100644 --- a/services/surfaceflinger/BufferLayerConsumer.cpp +++ b/services/surfaceflinger/BufferLayerConsumer.cpp @@ -471,18 +471,6 @@ void BufferLayerConsumer::onBufferAvailable(const BufferItem& item) { } } -void BufferLayerConsumer::addAndGetFrameTimestamps(const NewFrameEventsEntry* newTimestamps, - FrameEventHistoryDelta* outDelta) { - Mutex::Autolock lock(mMutex); - - if (mAbandoned) { - // Nothing to do if we're already abandoned. - return; - } - - mLayer->addAndGetFrameTimestamps(newTimestamps, outDelta); -} - void BufferLayerConsumer::abandonLocked() { BLC_LOGV("abandonLocked"); mCurrentTextureBuffer = nullptr; diff --git a/services/surfaceflinger/BufferLayerConsumer.h b/services/surfaceflinger/BufferLayerConsumer.h index 9ed80b46bd..23ad2a3f91 100644 --- a/services/surfaceflinger/BufferLayerConsumer.h +++ b/services/surfaceflinger/BufferLayerConsumer.h @@ -236,8 +236,7 @@ private: // IConsumerListener interface void onDisconnect() override; void onSidebandStreamChanged() override; - void addAndGetFrameTimestamps(const NewFrameEventsEntry* newTimestamps, - FrameEventHistoryDelta* outDelta) override; + void addAndGetFrameTimestamps(const NewFrameEventsEntry*, FrameEventHistoryDelta*) override {} // computeCurrentTransformMatrixLocked computes the transform matrix for the // current texture. It uses mCurrentTransform and the current GraphicBuffer diff --git a/services/surfaceflinger/BufferQueueLayer.cpp b/services/surfaceflinger/BufferQueueLayer.cpp index 926aa1dfb2..50146d7907 100644 --- a/services/surfaceflinger/BufferQueueLayer.cpp +++ b/services/surfaceflinger/BufferQueueLayer.cpp @@ -67,20 +67,10 @@ void BufferQueueLayer::setTransformHint(ui::Transform::RotationFlags displayTran mConsumer->setTransformHint(mTransformHint); } -void BufferQueueLayer::releasePendingBuffer(nsecs_t dequeueReadyTime) { +void BufferQueueLayer::releasePendingBuffer(nsecs_t) { if (!mConsumer->releasePendingBuffer()) { return; } - - auto releaseFenceTime = std::make_shared(mConsumer->getPrevFinalReleaseFence()); - mReleaseTimeline.updateSignalTimes(); - mReleaseTimeline.push(releaseFenceTime); - - Mutex::Autolock lock(mFrameEventHistoryMutex); - if (mPreviousFrameNumber != 0) { - mFrameEventHistory.addRelease(mPreviousFrameNumber, dequeueReadyTime, - std::move(releaseFenceTime)); - } } void BufferQueueLayer::setDefaultBufferSize(uint32_t w, uint32_t h) { @@ -320,14 +310,9 @@ status_t BufferQueueLayer::updateActiveBuffer() { return NO_ERROR; } -status_t BufferQueueLayer::updateFrameNumber(nsecs_t latchTime) { +status_t BufferQueueLayer::updateFrameNumber() { mPreviousFrameNumber = mCurrentFrameNumber; mCurrentFrameNumber = mConsumer->getFrameNumber(); - - { - Mutex::Autolock lock(mFrameEventHistoryMutex); - mFrameEventHistory.addLatch(mCurrentFrameNumber, latchTime); - } return NO_ERROR; } diff --git a/services/surfaceflinger/BufferQueueLayer.h b/services/surfaceflinger/BufferQueueLayer.h index c6e0727806..cca7f707fc 100644 --- a/services/surfaceflinger/BufferQueueLayer.h +++ b/services/surfaceflinger/BufferQueueLayer.h @@ -103,7 +103,7 @@ private: nsecs_t expectedPresentTime) override; status_t updateActiveBuffer() override; - status_t updateFrameNumber(nsecs_t latchTime) override; + status_t updateFrameNumber() override; void setFrameTimelineInfoForBuffer(const FrameTimelineInfo& frameTimelineInfo) override; sp createClone() override; diff --git a/services/surfaceflinger/BufferStateLayer.cpp b/services/surfaceflinger/BufferStateLayer.cpp index c5d7a601c5..af0039cd2c 100644 --- a/services/surfaceflinger/BufferStateLayer.cpp +++ b/services/surfaceflinger/BufferStateLayer.cpp @@ -179,15 +179,6 @@ void BufferStateLayer::releasePendingBuffer(nsecs_t dequeueReadyTime) { } mDrawingState.callbackHandles = {}; - - std::shared_ptr releaseFenceTime = std::make_shared(releaseFence); - { - Mutex::Autolock lock(mFrameEventHistoryMutex); - if (mPreviousFrameNumber != 0) { - mFrameEventHistory.addRelease(mPreviousFrameNumber, dequeueReadyTime, - std::move(releaseFenceTime)); - } - } } void BufferStateLayer::finalizeFrameEventHistory(const std::shared_ptr& glDoneFence, @@ -347,19 +338,6 @@ bool BufferStateLayer::setPosition(float x, float y) { return true; } -bool BufferStateLayer::addFrameEvent(const sp& acquireFence, nsecs_t postedTime, - nsecs_t desiredPresentTime) { - Mutex::Autolock lock(mFrameEventHistoryMutex); - mAcquireTimeline.updateSignalTimes(); - std::shared_ptr acquireFenceTime = - std::make_shared((acquireFence ? acquireFence : Fence::NO_FENCE)); - NewFrameEventsEntry newTimestamps = {mDrawingState.frameNumber, postedTime, desiredPresentTime, - acquireFenceTime}; - mFrameEventHistory.setProducerWantsEvents(); - mFrameEventHistory.addQueue(newTimestamps); - return true; -} - bool BufferStateLayer::setBuffer(std::shared_ptr& buffer, const BufferData& bufferData, nsecs_t postTime, nsecs_t desiredPresentTime, bool isAutoTimestamp, @@ -446,8 +424,6 @@ bool BufferStateLayer::setBuffer(std::shared_ptr& using LayerUpdateType = scheduler::LayerHistory::LayerUpdateType; mFlinger->mScheduler->recordLayerHistory(this, presentTime, LayerUpdateType::Buffer); - addFrameEvent(mDrawingState.acquireFence, postTime, isAutoTimestamp ? 0 : desiredPresentTime); - setFrameTimelineVsyncForBufferTransaction(info, postTime); if (dequeueTime && *dequeueTime != 0) { @@ -727,14 +703,10 @@ status_t BufferStateLayer::updateActiveBuffer() { return NO_ERROR; } -status_t BufferStateLayer::updateFrameNumber(nsecs_t latchTime) { +status_t BufferStateLayer::updateFrameNumber() { // TODO(marissaw): support frame history events mPreviousFrameNumber = mCurrentFrameNumber; mCurrentFrameNumber = mDrawingState.frameNumber; - { - Mutex::Autolock lock(mFrameEventHistoryMutex); - mFrameEventHistory.addLatch(mCurrentFrameNumber, latchTime); - } return NO_ERROR; } diff --git a/services/surfaceflinger/BufferStateLayer.h b/services/surfaceflinger/BufferStateLayer.h index 8a696f11b4..e98aa9abf9 100644 --- a/services/surfaceflinger/BufferStateLayer.h +++ b/services/surfaceflinger/BufferStateLayer.h @@ -67,8 +67,6 @@ public: bool setApi(int32_t api) override; bool setSidebandStream(const sp& sidebandStream) override; bool setTransactionCompletedListeners(const std::vector>& handles) override; - bool addFrameEvent(const sp& acquireFence, nsecs_t postedTime, - nsecs_t requestedPresentTime) override; bool setPosition(float /*x*/, float /*y*/) override; bool setMatrix(const layer_state_t::matrix22_t& /*matrix*/); @@ -125,7 +123,7 @@ private: nsecs_t expectedPresentTime) override; status_t updateActiveBuffer() override; - status_t updateFrameNumber(nsecs_t latchTime) override; + status_t updateFrameNumber() override; sp createClone() override; diff --git a/services/surfaceflinger/Layer.cpp b/services/surfaceflinger/Layer.cpp index e1eec8b97e..e4859c1354 100644 --- a/services/surfaceflinger/Layer.cpp +++ b/services/surfaceflinger/Layer.cpp @@ -151,10 +151,8 @@ Layer::Layer(const LayerCreationArgs& args) mDrawingState.color.g = -1.0_hf; mDrawingState.color.b = -1.0_hf; } - CompositorTiming compositorTiming; args.flinger->getCompositorTiming(&compositorTiming); - mFrameEventHistory.initializeCompositorTiming(compositorTiming); mFrameTracker.setDisplayRefreshPeriod(compositorTiming.interval); mCallingPid = args.callingPid; @@ -1532,53 +1530,17 @@ void Layer::getFrameStats(FrameStats* outStats) const { mFrameTracker.getStats(outStats); } -void Layer::dumpFrameEvents(std::string& result) { - StringAppendF(&result, "- Layer %s (%s, %p)\n", getName().c_str(), getType(), this); - Mutex::Autolock lock(mFrameEventHistoryMutex); - mFrameEventHistory.checkFencesForCompletion(); - mFrameEventHistory.dump(result); -} - void Layer::dumpCallingUidPid(std::string& result) const { StringAppendF(&result, "Layer %s (%s) callingPid:%d callingUid:%d ownerUid:%d\n", getName().c_str(), getType(), mCallingPid, mCallingUid, mOwnerUid); } void Layer::onDisconnect() { - Mutex::Autolock lock(mFrameEventHistoryMutex); - mFrameEventHistory.onDisconnect(); const int32_t layerId = getSequence(); mFlinger->mTimeStats->onDestroy(layerId); mFlinger->mFrameTracer->onDestroy(layerId); } -void Layer::addAndGetFrameTimestamps(const NewFrameEventsEntry* newTimestamps, - FrameEventHistoryDelta* outDelta) { - if (newTimestamps) { - mFlinger->mTimeStats->setPostTime(getSequence(), newTimestamps->frameNumber, - getName().c_str(), mOwnerUid, newTimestamps->postedTime, - getGameMode()); - mFlinger->mTimeStats->setAcquireFence(getSequence(), newTimestamps->frameNumber, - newTimestamps->acquireFence); - } - - Mutex::Autolock lock(mFrameEventHistoryMutex); - if (newTimestamps) { - // If there are any unsignaled fences in the aquire timeline at this - // point, the previously queued frame hasn't been latched yet. Go ahead - // and try to get the signal time here so the syscall is taken out of - // the main thread's critical path. - mAcquireTimeline.updateSignalTimes(); - // Push the new fence after updating since it's likely still pending. - mAcquireTimeline.push(newTimestamps->acquireFence); - mFrameEventHistory.addQueue(*newTimestamps); - } - - if (outDelta) { - mFrameEventHistory.getAndResetDelta(outDelta); - } -} - size_t Layer::getChildrenCount() const { size_t count = 0; for (const sp& child : mCurrentChildren) { diff --git a/services/surfaceflinger/Layer.h b/services/surfaceflinger/Layer.h index ecea74413c..0b63fabe50 100644 --- a/services/surfaceflinger/Layer.h +++ b/services/surfaceflinger/Layer.h @@ -432,10 +432,6 @@ public: virtual bool setSidebandStream(const sp& /*sidebandStream*/) { return false; }; virtual bool setTransactionCompletedListeners( const std::vector>& /*handles*/); - virtual bool addFrameEvent(const sp& /*acquireFence*/, nsecs_t /*postedTime*/, - nsecs_t /*requestedPresentTime*/) { - return false; - } virtual bool setBackgroundColor(const half3& color, float alpha, ui::Dataspace dataspace); virtual bool setColorSpaceAgnostic(const bool agnostic); virtual bool setDimmingEnabled(const bool dimmingEnabled); @@ -743,14 +739,11 @@ public: void miniDump(std::string& result, const DisplayDevice&) const; void dumpFrameStats(std::string& result) const; - void dumpFrameEvents(std::string& result); void dumpCallingUidPid(std::string& result) const; void clearFrameStats(); void logFrameStats(); void getFrameStats(FrameStats* outStats) const; void onDisconnect(); - void addAndGetFrameTimestamps(const NewFrameEventsEntry* newEntry, - FrameEventHistoryDelta* outDelta); ui::Transform getTransform() const; bool isTransformValid() const; @@ -995,13 +988,6 @@ protected: // Timestamp history for UIAutomation. Thread safe. FrameTracker mFrameTracker; - // Timestamp history for the consumer to query. - // Accessed by both consumer and producer on main and binder threads. - Mutex mFrameEventHistoryMutex; - ConsumerFrameEventHistory mFrameEventHistory; - FenceTimeline mAcquireTimeline; - FenceTimeline mReleaseTimeline; - // main thread sp mSidebandStream; // False if the buffer and its contents have been previously used for GPU diff --git a/services/surfaceflinger/SurfaceFlinger.cpp b/services/surfaceflinger/SurfaceFlinger.cpp index e6b64c15e9..47478f7ecc 100644 --- a/services/surfaceflinger/SurfaceFlinger.cpp +++ b/services/surfaceflinger/SurfaceFlinger.cpp @@ -4974,7 +4974,6 @@ status_t SurfaceFlinger::doDump(int fd, const DumpArgs& args, bool asProto) { {"--displays"s, dumper(&SurfaceFlinger::dumpDisplays)}, {"--dispsync"s, dumper([this](std::string& s) { mScheduler->dumpVsync(s); })}, {"--edid"s, argsDumper(&SurfaceFlinger::dumpRawDisplayIdentificationData)}, - {"--frame-events"s, dumper(&SurfaceFlinger::dumpFrameEventsLocked)}, {"--latency"s, argsDumper(&SurfaceFlinger::dumpStatsLocked)}, {"--latency-clear"s, argsDumper(&SurfaceFlinger::clearStatsLocked)}, {"--list"s, dumper(&SurfaceFlinger::listLayersLocked)}, @@ -5141,13 +5140,6 @@ void SurfaceFlinger::dumpStaticScreenStats(std::string& result) const { bucketTimeSec, percent); } -void SurfaceFlinger::dumpFrameEventsLocked(std::string& result) { - result.append("Layer frame timestamps:\n"); - // Traverse all layers to dump frame-events for each layer - mCurrentState.traverseInZOrder( - [&] (Layer* layer) { layer->dumpFrameEvents(result); }); -} - void SurfaceFlinger::dumpCompositionDisplays(std::string& result) const { for (const auto& [token, display] : mDisplays) { display->getCompositionDisplay()->dump(result); diff --git a/services/surfaceflinger/SurfaceFlinger.h b/services/surfaceflinger/SurfaceFlinger.h index fc27b62b33..db5fd470c5 100644 --- a/services/surfaceflinger/SurfaceFlinger.h +++ b/services/surfaceflinger/SurfaceFlinger.h @@ -1098,8 +1098,6 @@ private: void dumpVSync(std::string& result) const REQUIRES(mStateLock); void dumpStaticScreenStats(std::string& result) const; - // Not const because each Layer needs to query Fences and cache timestamps. - void dumpFrameEventsLocked(std::string& result); void dumpCompositionDisplays(std::string& result) const REQUIRES(mStateLock); void dumpDisplays(std::string& result) const REQUIRES(mStateLock); diff --git a/services/surfaceflinger/fuzzer/surfaceflinger_fuzzers_utils.h b/services/surfaceflinger/fuzzer/surfaceflinger_fuzzers_utils.h index a80aca2f73..867a1985bd 100644 --- a/services/surfaceflinger/fuzzer/surfaceflinger_fuzzers_utils.h +++ b/services/surfaceflinger/fuzzer/surfaceflinger_fuzzers_utils.h @@ -455,9 +455,6 @@ public: result = fdp->ConsumeRandomLengthString().c_str(); mFlinger->dumpStaticScreenStats(result); - result = fdp->ConsumeRandomLengthString().c_str(); - mFlinger->dumpFrameEventsLocked(result); - result = fdp->ConsumeRandomLengthString().c_str(); mFlinger->dumpRawDisplayIdentificationData(dumpArgs, result); diff --git a/services/surfaceflinger/fuzzer/surfaceflinger_layer_fuzzer.cpp b/services/surfaceflinger/fuzzer/surfaceflinger_layer_fuzzer.cpp index 46d52dd221..8b58298766 100644 --- a/services/surfaceflinger/fuzzer/surfaceflinger_layer_fuzzer.cpp +++ b/services/surfaceflinger/fuzzer/surfaceflinger_layer_fuzzer.cpp @@ -146,8 +146,6 @@ void LayerFuzzer::invokeBufferStateLayer() { const bool ownsHandle = mFdp.ConsumeBool(); sp nativeHandle = sp::make(testHandle, ownsHandle); layer->setSidebandStream(nativeHandle); - layer->addFrameEvent(fence, mFdp.ConsumeIntegral() /*postedTime*/, - mFdp.ConsumeIntegral() /*requestedTime*/); layer->computeSourceBounds(getFuzzedFloatRect(&mFdp)); layer->fenceHasSignaled(); -- cgit v1.2.3-59-g8ed1b From bb448ce9aa521f9574d94c9ec2d57eb7d37382cb Mon Sep 17 00:00:00 2001 From: Dominik Laskowski Date: Sat, 7 May 2022 15:52:55 -0700 Subject: SF: Do not duplicate fences per layer per frame Convert the unique_fd of RenderEngineResult (and futures thereof) into sp such that postFramebuffer does not duplicate release/present fences. Remove a few copies of shared futures/pointers with std::move. Bug: 232436803 Test: simpleperf (-33% cycles in sys_dup) Change-Id: Ia7c6c8333a712441f3612fb5c720ea2932799636 --- services/surfaceflinger/BufferQueueLayer.cpp | 5 +- services/surfaceflinger/BufferQueueLayer.h | 3 +- services/surfaceflinger/BufferStateLayer.cpp | 5 +- services/surfaceflinger/BufferStateLayer.h | 3 +- .../include/compositionengine/FenceResult.h | 49 +++++++++ .../include/compositionengine/LayerFE.h | 5 +- .../include/compositionengine/mock/LayerFE.h | 2 +- .../CompositionEngine/src/Output.cpp | 43 ++++---- .../CompositionEngine/src/planner/CachedSet.cpp | 15 +-- .../CompositionEngine/tests/OutputTest.cpp | 54 ++++------ services/surfaceflinger/Layer.cpp | 3 +- services/surfaceflinger/Layer.h | 3 +- services/surfaceflinger/RegionSamplingThread.cpp | 15 +-- services/surfaceflinger/SurfaceFlinger.cpp | 117 ++++++++++----------- services/surfaceflinger/SurfaceFlinger.h | 12 ++- .../surfaceflinger/TransactionCallbackInvoker.cpp | 13 +-- .../surfaceflinger/TransactionCallbackInvoker.h | 4 +- .../fuzzer/surfaceflinger_layer_fuzzer.cpp | 11 +- .../tests/unittests/CompositionTest.cpp | 13 ++- 19 files changed, 201 insertions(+), 174 deletions(-) create mode 100644 services/surfaceflinger/CompositionEngine/include/compositionengine/FenceResult.h (limited to 'services/surfaceflinger/BufferQueueLayer.cpp') diff --git a/services/surfaceflinger/BufferQueueLayer.cpp b/services/surfaceflinger/BufferQueueLayer.cpp index 926aa1dfb2..6a1a38b39c 100644 --- a/services/surfaceflinger/BufferQueueLayer.cpp +++ b/services/surfaceflinger/BufferQueueLayer.cpp @@ -48,9 +48,8 @@ BufferQueueLayer::~BufferQueueLayer() { // Interface implementation for Layer // ----------------------------------------------------------------------- -void BufferQueueLayer::onLayerDisplayed( - std::shared_future futureRenderEngineResult) { - sp releaseFence = new Fence(dup(futureRenderEngineResult.get().drawFence)); +void BufferQueueLayer::onLayerDisplayed(std::shared_future futureFenceResult) { + const sp releaseFence = futureFenceResult.get().value_or(Fence::NO_FENCE); mConsumer->setReleaseFence(releaseFence); // Prevent tracing the same release multiple times. diff --git a/services/surfaceflinger/BufferQueueLayer.h b/services/surfaceflinger/BufferQueueLayer.h index c6e0727806..4587b5e27c 100644 --- a/services/surfaceflinger/BufferQueueLayer.h +++ b/services/surfaceflinger/BufferQueueLayer.h @@ -42,8 +42,7 @@ public: // Implements Layer. const char* getType() const override { return "BufferQueueLayer"; } - void onLayerDisplayed( - std::shared_future futureRenderEngineResult) override; + void onLayerDisplayed(std::shared_future) override; // If a buffer was replaced this frame, release the former buffer void releasePendingBuffer(nsecs_t dequeueReadyTime) override; diff --git a/services/surfaceflinger/BufferStateLayer.cpp b/services/surfaceflinger/BufferStateLayer.cpp index c5d7a601c5..c88511049b 100644 --- a/services/surfaceflinger/BufferStateLayer.cpp +++ b/services/surfaceflinger/BufferStateLayer.cpp @@ -73,8 +73,7 @@ BufferStateLayer::~BufferStateLayer() { // ----------------------------------------------------------------------- // Interface implementation for Layer // ----------------------------------------------------------------------- -void BufferStateLayer::onLayerDisplayed( - std::shared_future futureRenderEngineResult) { +void BufferStateLayer::onLayerDisplayed(std::shared_future futureFenceResult) { // If we are displayed on multiple displays in a single composition cycle then we would // need to do careful tracking to enable the use of the mLastClientCompositionFence. // For example we can only use it if all the displays are client comp, and we need @@ -118,7 +117,7 @@ void BufferStateLayer::onLayerDisplayed( if (ch != nullptr) { ch->previousReleaseCallbackId = mPreviousReleaseCallbackId; - ch->previousReleaseFences.emplace_back(futureRenderEngineResult); + ch->previousReleaseFences.emplace_back(std::move(futureFenceResult)); ch->name = mName; } } diff --git a/services/surfaceflinger/BufferStateLayer.h b/services/surfaceflinger/BufferStateLayer.h index 8a696f11b4..cc510d8c74 100644 --- a/services/surfaceflinger/BufferStateLayer.h +++ b/services/surfaceflinger/BufferStateLayer.h @@ -39,8 +39,7 @@ public: // Implements Layer. const char* getType() const override { return "BufferStateLayer"; } - void onLayerDisplayed( - std::shared_future futureRenderEngineResult) override; + void onLayerDisplayed(std::shared_future) override; void releasePendingBuffer(nsecs_t dequeueReadyTime) override; diff --git a/services/surfaceflinger/CompositionEngine/include/compositionengine/FenceResult.h b/services/surfaceflinger/CompositionEngine/include/compositionengine/FenceResult.h new file mode 100644 index 0000000000..0ce263b930 --- /dev/null +++ b/services/surfaceflinger/CompositionEngine/include/compositionengine/FenceResult.h @@ -0,0 +1,49 @@ +/* + * Copyright 2022 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#pragma once + +#include +#include +#include + +// TODO(b/232535621): Pull this file to so that RenderEngine::drawLayers returns +// FenceResult rather than RenderEngineResult. +#pragma clang diagnostic push +#pragma clang diagnostic ignored "-Wconversion" +#include +#pragma clang diagnostic pop + +namespace android { + +class Fence; + +using FenceResult = base::expected, status_t>; + +// TODO(b/232535621): Prevent base::unexpected(NO_ERROR) from being a valid FenceResult. +inline status_t fenceStatus(const FenceResult& fenceResult) { + return fenceResult.ok() ? NO_ERROR : fenceResult.error(); +} + +inline FenceResult toFenceResult(renderengine::RenderEngineResult&& result) { + if (auto [status, fence] = std::move(result); fence.ok()) { + return sp::make(std::move(fence)); + } else { + return base::unexpected(status); + } +} + +} // namespace android diff --git a/services/surfaceflinger/CompositionEngine/include/compositionengine/LayerFE.h b/services/surfaceflinger/CompositionEngine/include/compositionengine/LayerFE.h index e77e155cb8..b7fc62fd21 100644 --- a/services/surfaceflinger/CompositionEngine/include/compositionengine/LayerFE.h +++ b/services/surfaceflinger/CompositionEngine/include/compositionengine/LayerFE.h @@ -21,13 +21,14 @@ #include #include +#include + // TODO(b/129481165): remove the #pragma below and fix conversion issues #pragma clang diagnostic push #pragma clang diagnostic ignored "-Wconversion" #pragma clang diagnostic ignored "-Wextra" #include -#include // TODO(b/129481165): remove the #pragma below and fix conversion issues #pragma clang diagnostic pop // ignored "-Wconversion -Wextra" @@ -156,7 +157,7 @@ public: ClientCompositionTargetSettings&) = 0; // Called after the layer is displayed to update the presentation fence - virtual void onLayerDisplayed(std::shared_future) = 0; + virtual void onLayerDisplayed(std::shared_future) = 0; // Gets some kind of identifier for the layer for debug purposes. virtual const char* getDebugName() const = 0; diff --git a/services/surfaceflinger/CompositionEngine/include/compositionengine/mock/LayerFE.h b/services/surfaceflinger/CompositionEngine/include/compositionengine/mock/LayerFE.h index ee0c53ded7..871599d2cd 100644 --- a/services/surfaceflinger/CompositionEngine/include/compositionengine/mock/LayerFE.h +++ b/services/surfaceflinger/CompositionEngine/include/compositionengine/mock/LayerFE.h @@ -49,7 +49,7 @@ public: std::vector( compositionengine::LayerFE::ClientCompositionTargetSettings&)); - MOCK_METHOD1(onLayerDisplayed, void(std::shared_future)); + MOCK_METHOD1(onLayerDisplayed, void(std::shared_future)); MOCK_CONST_METHOD0(getDebugName, const char*()); MOCK_CONST_METHOD0(getSequence, int32_t()); diff --git a/services/surfaceflinger/CompositionEngine/src/Output.cpp b/services/surfaceflinger/CompositionEngine/src/Output.cpp index 4c30f99610..742332ca24 100644 --- a/services/surfaceflinger/CompositionEngine/src/Output.cpp +++ b/services/surfaceflinger/CompositionEngine/src/Output.cpp @@ -1245,34 +1245,31 @@ std::optional Output::composeSurfaces( // probably to encapsulate the output buffer into a structure that dispatches resource cleanup // over to RenderEngine, in which case this flag can be removed from the drawLayers interface. const bool useFramebufferCache = outputState.layerFilter.toInternalDisplay; - auto [status, drawFence] = - renderEngine - .drawLayers(clientCompositionDisplay, clientRenderEngineLayers, tex, - useFramebufferCache, std::move(fd)) - .get(); - if (status != NO_ERROR && mClientCompositionRequestCache) { + auto fenceResult = + toFenceResult(renderEngine + .drawLayers(clientCompositionDisplay, clientRenderEngineLayers, + tex, useFramebufferCache, std::move(fd)) + .get()); + + if (mClientCompositionRequestCache && fenceStatus(fenceResult) != NO_ERROR) { // If rendering was not successful, remove the request from the cache. mClientCompositionRequestCache->remove(tex->getBuffer()->getId()); } - auto& timeStats = getCompositionEngine().getTimeStats(); - if (drawFence.get() < 0) { - timeStats.recordRenderEngineDuration(renderEngineStart, systemTime()); + const auto fence = std::move(fenceResult).value_or(Fence::NO_FENCE); + + if (auto& timeStats = getCompositionEngine().getTimeStats(); fence->isValid()) { + timeStats.recordRenderEngineDuration(renderEngineStart, std::make_shared(fence)); } else { - timeStats.recordRenderEngineDuration(renderEngineStart, - std::make_shared( - new Fence(dup(drawFence.get())))); + timeStats.recordRenderEngineDuration(renderEngineStart, systemTime()); } - if (clientCompositionLayersFE.size() > 0) { - sp clientCompFence = new Fence(dup(drawFence.get())); - for (auto clientComposedLayer : clientCompositionLayersFE) { - clientComposedLayer->setWasClientComposed(clientCompFence); - } + for (auto* clientComposedLayer : clientCompositionLayersFE) { + clientComposedLayer->setWasClientComposed(fence); } - return std::move(drawFence); + return base::unique_fd(fence->dup()); } std::vector Output::generateClientCompositionRequests( @@ -1429,19 +1426,15 @@ void Output::postFramebuffer() { Fence::merge("LayerRelease", releaseFence, frame.clientTargetAcquireFence); } layer->getLayerFE().onLayerDisplayed( - ftl::yield( - {NO_ERROR, base::unique_fd(releaseFence->dup())}) - .share()); + ftl::yield(std::move(releaseFence)).share()); } // We've got a list of layers needing fences, that are disjoint with // OutputLayersOrderedByZ. The best we can do is to // supply them with the present fence. for (auto& weakLayer : mReleasedLayers) { - if (auto layer = weakLayer.promote(); layer != nullptr) { - layer->onLayerDisplayed(ftl::yield( - {NO_ERROR, base::unique_fd(frame.presentFence->dup())}) - .share()); + if (const auto layer = weakLayer.promote()) { + layer->onLayerDisplayed(ftl::yield(frame.presentFence).share()); } } diff --git a/services/surfaceflinger/CompositionEngine/src/planner/CachedSet.cpp b/services/surfaceflinger/CompositionEngine/src/planner/CachedSet.cpp index aaca4fe424..d15b0a7646 100644 --- a/services/surfaceflinger/CompositionEngine/src/planner/CachedSet.cpp +++ b/services/surfaceflinger/CompositionEngine/src/planner/CachedSet.cpp @@ -271,13 +271,16 @@ void CachedSet::render(renderengine::RenderEngine& renderEngine, TexturePool& te bufferFence.reset(texture->getReadyFence()->dup()); } - auto [status, drawFence] = renderEngine - .drawLayers(displaySettings, layerSettings, texture->get(), - false, std::move(bufferFence)) - .get(); + constexpr bool kUseFramebufferCache = false; - if (status == NO_ERROR) { - mDrawFence = new Fence(drawFence.release()); + auto fenceResult = + toFenceResult(renderEngine + .drawLayers(displaySettings, layerSettings, texture->get(), + kUseFramebufferCache, std::move(bufferFence)) + .get()); + + if (fenceStatus(fenceResult) == NO_ERROR) { + mDrawFence = std::move(fenceResult).value_or(Fence::NO_FENCE); mOutputSpace = outputState.framebufferSpace; mTexture = texture; mTexture->setReadyFence(mDrawFence); diff --git a/services/surfaceflinger/CompositionEngine/tests/OutputTest.cpp b/services/surfaceflinger/CompositionEngine/tests/OutputTest.cpp index 3a3c91e518..784abeac29 100644 --- a/services/surfaceflinger/CompositionEngine/tests/OutputTest.cpp +++ b/services/surfaceflinger/CompositionEngine/tests/OutputTest.cpp @@ -3171,9 +3171,9 @@ TEST_F(OutputPostFramebufferTest, releaseFencesAreSentToLayerFE) { mOutput.mState.isEnabled = true; // Create three unique fence instances - sp layer1Fence = new Fence(); - sp layer2Fence = new Fence(); - sp layer3Fence = new Fence(); + sp layer1Fence = sp::make(); + sp layer2Fence = sp::make(); + sp layer3Fence = sp::make(); Output::FrameFences frameFences; frameFences.layerFences.emplace(&mLayer1.hwc2Layer, layer1Fence); @@ -3188,23 +3188,17 @@ TEST_F(OutputPostFramebufferTest, releaseFencesAreSentToLayerFE) { // are passed. This happens to work with the current implementation, but // would not survive certain calls like Fence::merge() which would return a // new instance. - base::unique_fd layer1FD(layer1Fence->dup()); - base::unique_fd layer2FD(layer2Fence->dup()); - base::unique_fd layer3FD(layer3Fence->dup()); EXPECT_CALL(*mLayer1.layerFE, onLayerDisplayed(_)) - .WillOnce([&layer1FD](std::shared_future - futureRenderEngineResult) { - EXPECT_EQ(layer1FD, futureRenderEngineResult.get().drawFence); + .WillOnce([&layer1Fence](std::shared_future futureFenceResult) { + EXPECT_EQ(FenceResult(layer1Fence), futureFenceResult.get()); }); EXPECT_CALL(*mLayer2.layerFE, onLayerDisplayed(_)) - .WillOnce([&layer2FD](std::shared_future - futureRenderEngineResult) { - EXPECT_EQ(layer2FD, futureRenderEngineResult.get().drawFence); + .WillOnce([&layer2Fence](std::shared_future futureFenceResult) { + EXPECT_EQ(FenceResult(layer2Fence), futureFenceResult.get()); }); EXPECT_CALL(*mLayer3.layerFE, onLayerDisplayed(_)) - .WillOnce([&layer3FD](std::shared_future - futureRenderEngineResult) { - EXPECT_EQ(layer3FD, futureRenderEngineResult.get().drawFence); + .WillOnce([&layer3Fence](std::shared_future futureFenceResult) { + EXPECT_EQ(FenceResult(layer3Fence), futureFenceResult.get()); }); mOutput.postFramebuffer(); @@ -3214,15 +3208,11 @@ TEST_F(OutputPostFramebufferTest, releaseFencesIncludeClientTargetAcquireFence) mOutput.mState.isEnabled = true; mOutput.mState.usesClientComposition = true; - sp clientTargetAcquireFence = new Fence(); - sp layer1Fence = new Fence(); - sp layer2Fence = new Fence(); - sp layer3Fence = new Fence(); Output::FrameFences frameFences; - frameFences.clientTargetAcquireFence = clientTargetAcquireFence; - frameFences.layerFences.emplace(&mLayer1.hwc2Layer, layer1Fence); - frameFences.layerFences.emplace(&mLayer2.hwc2Layer, layer2Fence); - frameFences.layerFences.emplace(&mLayer3.hwc2Layer, layer3Fence); + frameFences.clientTargetAcquireFence = sp::make(); + frameFences.layerFences.emplace(&mLayer1.hwc2Layer, sp::make()); + frameFences.layerFences.emplace(&mLayer2.hwc2Layer, sp::make()); + frameFences.layerFences.emplace(&mLayer3.hwc2Layer, sp::make()); EXPECT_CALL(*mRenderSurface, flip()); EXPECT_CALL(mOutput, presentAndGetFrameFences()).WillOnce(Return(frameFences)); @@ -3256,7 +3246,7 @@ TEST_F(OutputPostFramebufferTest, releasedLayersSentPresentFence) { mOutput.setReleasedLayers(std::move(layers)); // Set up a fake present fence - sp presentFence = new Fence(); + sp presentFence = sp::make(); Output::FrameFences frameFences; frameFences.presentFence = presentFence; @@ -3265,21 +3255,17 @@ TEST_F(OutputPostFramebufferTest, releasedLayersSentPresentFence) { EXPECT_CALL(*mRenderSurface, onPresentDisplayCompleted()); // Each released layer should be given the presentFence. - base::unique_fd layerFD(presentFence.get()->dup()); EXPECT_CALL(*releasedLayer1, onLayerDisplayed(_)) - .WillOnce([&layerFD](std::shared_future - futureRenderEngineResult) { - EXPECT_EQ(layerFD, futureRenderEngineResult.get().drawFence); + .WillOnce([&presentFence](std::shared_future futureFenceResult) { + EXPECT_EQ(FenceResult(presentFence), futureFenceResult.get()); }); EXPECT_CALL(*releasedLayer2, onLayerDisplayed(_)) - .WillOnce([&layerFD](std::shared_future - futureRenderEngineResult) { - EXPECT_EQ(layerFD, futureRenderEngineResult.get().drawFence); + .WillOnce([&presentFence](std::shared_future futureFenceResult) { + EXPECT_EQ(FenceResult(presentFence), futureFenceResult.get()); }); EXPECT_CALL(*releasedLayer3, onLayerDisplayed(_)) - .WillOnce([&layerFD](std::shared_future - futureRenderEngineResult) { - EXPECT_EQ(layerFD, futureRenderEngineResult.get().drawFence); + .WillOnce([&presentFence](std::shared_future futureFenceResult) { + EXPECT_EQ(FenceResult(presentFence), futureFenceResult.get()); }); mOutput.postFramebuffer(); diff --git a/services/surfaceflinger/Layer.cpp b/services/surfaceflinger/Layer.cpp index e1eec8b97e..2298f038e9 100644 --- a/services/surfaceflinger/Layer.cpp +++ b/services/surfaceflinger/Layer.cpp @@ -213,8 +213,7 @@ LayerCreationArgs::LayerCreationArgs(SurfaceFlinger* flinger, sp client, * Layer. So, the implementation is done in BufferLayer. When called on a * EffectLayer object, it's essentially a NOP. */ -void Layer::onLayerDisplayed( - std::shared_future /*futureRenderEngineResult*/) {} +void Layer::onLayerDisplayed(std::shared_future) {} void Layer::removeRelativeZ(const std::vector& layersInTree) { if (mDrawingState.zOrderRelativeOf == nullptr) { diff --git a/services/surfaceflinger/Layer.h b/services/surfaceflinger/Layer.h index ecea74413c..100704369e 100644 --- a/services/surfaceflinger/Layer.h +++ b/services/surfaceflinger/Layer.h @@ -620,8 +620,7 @@ public: void prepareCompositionState(compositionengine::LayerFE::StateSubset subset) override; std::vector prepareClientCompositionList( compositionengine::LayerFE::ClientCompositionTargetSettings&) override; - void onLayerDisplayed( - std::shared_future futureRenderEngineResult) override; + void onLayerDisplayed(std::shared_future) override; void setWasClientComposed(const sp& fence) override { mLastClientCompositionFence = fence; diff --git a/services/surfaceflinger/RegionSamplingThread.cpp b/services/surfaceflinger/RegionSamplingThread.cpp index e29e6ab05f..2487dbd793 100644 --- a/services/surfaceflinger/RegionSamplingThread.cpp +++ b/services/surfaceflinger/RegionSamplingThread.cpp @@ -355,12 +355,15 @@ void RegionSamplingThread::captureSample() { WRITEABLE); } - auto captureScreenResultFuture = - mFlinger.captureScreenCommon(std::move(renderAreaFuture), traverseLayers, buffer, - true /* regionSampling */, false /* grayscale */, nullptr); - auto& captureScreenResult = captureScreenResultFuture.get(); - if (captureScreenResult.drawFence.ok()) { - sync_wait(captureScreenResult.drawFence.get(), -1); + constexpr bool kRegionSampling = true; + constexpr bool kGrayscale = false; + + if (const auto fenceResult = + mFlinger.captureScreenCommon(std::move(renderAreaFuture), traverseLayers, buffer, + kRegionSampling, kGrayscale, nullptr) + .get(); + fenceResult.ok()) { + fenceResult.value()->waitForever(LOG_TAG); } std::vector activeDescriptors; diff --git a/services/surfaceflinger/SurfaceFlinger.cpp b/services/surfaceflinger/SurfaceFlinger.cpp index e72e21ceb3..d8a2696ef0 100644 --- a/services/surfaceflinger/SurfaceFlinger.cpp +++ b/services/surfaceflinger/SurfaceFlinger.cpp @@ -6410,10 +6410,10 @@ status_t SurfaceFlinger::captureDisplay(const DisplayCaptureArgs& args, traverseLayersInLayerStack(layerStack, args.uid, visitor); }; - auto captureResultFuture = captureScreenCommon(std::move(renderAreaFuture), traverseLayers, - reqSize, args.pixelFormat, args.allowProtected, - args.grayscale, captureListener); - return captureResultFuture.get().status; + auto future = captureScreenCommon(std::move(renderAreaFuture), traverseLayers, reqSize, + args.pixelFormat, args.allowProtected, args.grayscale, + captureListener); + return fenceStatus(future.get()); } status_t SurfaceFlinger::captureDisplay(DisplayId displayId, @@ -6452,11 +6452,14 @@ status_t SurfaceFlinger::captureDisplay(DisplayId displayId, ALOGE("capture screen must provide a capture listener callback"); return BAD_VALUE; } - auto captureResultFuture = - captureScreenCommon(std::move(renderAreaFuture), traverseLayers, size, - ui::PixelFormat::RGBA_8888, false /* allowProtected */, - false /* grayscale */, captureListener); - return captureResultFuture.get().status; + + constexpr bool kAllowProtected = false; + constexpr bool kGrayscale = false; + + auto future = captureScreenCommon(std::move(renderAreaFuture), traverseLayers, size, + ui::PixelFormat::RGBA_8888, kAllowProtected, kGrayscale, + captureListener); + return fenceStatus(future.get()); } status_t SurfaceFlinger::captureLayers(const LayerCaptureArgs& args, @@ -6568,13 +6571,13 @@ status_t SurfaceFlinger::captureLayers(const LayerCaptureArgs& args, return BAD_VALUE; } - auto captureResultFuture = captureScreenCommon(std::move(renderAreaFuture), traverseLayers, - reqSize, args.pixelFormat, args.allowProtected, - args.grayscale, captureListener); - return captureResultFuture.get().status; + auto future = captureScreenCommon(std::move(renderAreaFuture), traverseLayers, reqSize, + args.pixelFormat, args.allowProtected, args.grayscale, + captureListener); + return fenceStatus(future.get()); } -std::shared_future SurfaceFlinger::captureScreenCommon( +std::shared_future SurfaceFlinger::captureScreenCommon( RenderAreaFuture renderAreaFuture, TraverseLayersFunction traverseLayers, ui::Size bufferSize, ui::PixelFormat reqPixelFormat, bool allowProtected, bool grayscale, const sp& captureListener) { @@ -6584,7 +6587,7 @@ std::shared_future SurfaceFlinger::captureScre ALOGE("Attempted to capture screen with size (%" PRId32 ", %" PRId32 ") that exceeds render target size limit.", bufferSize.getWidth(), bufferSize.getHeight()); - return ftl::yield({BAD_VALUE, base::unique_fd()}).share(); + return ftl::yield(base::unexpected(BAD_VALUE)).share(); } // Loop over all visible layers to see whether there's any protected layer. A protected layer is @@ -6626,7 +6629,7 @@ std::shared_future SurfaceFlinger::captureScre false /* regionSampling */, grayscale, captureListener); } -std::shared_future SurfaceFlinger::captureScreenCommon( +std::shared_future SurfaceFlinger::captureScreenCommon( RenderAreaFuture renderAreaFuture, TraverseLayersFunction traverseLayers, const std::shared_ptr& buffer, bool regionSampling, bool grayscale, const sp& captureListener) { @@ -6634,59 +6637,53 @@ std::shared_future SurfaceFlinger::captureScre bool canCaptureBlackoutContent = hasCaptureBlackoutContentPermission(); - auto scheduleResultFuture = mScheduler->schedule([=, - renderAreaFuture = - std::move(renderAreaFuture)]() mutable - -> std::shared_future< - renderengine::RenderEngineResult> { + auto future = mScheduler->schedule([=, renderAreaFuture = std::move(renderAreaFuture)]() mutable + -> std::shared_future { ScreenCaptureResults captureResults; std::unique_ptr renderArea = renderAreaFuture.get(); if (!renderArea) { ALOGW("Skipping screen capture because of invalid render area."); captureResults.result = NO_MEMORY; captureListener->onScreenCaptureCompleted(captureResults); - return ftl::yield({NO_ERROR, base::unique_fd()}) - .share(); + return ftl::yield(base::unexpected(NO_ERROR)).share(); } - std::shared_future renderEngineResultFuture; - + std::shared_future renderFuture; renderArea->render([&] { - renderEngineResultFuture = - renderScreenImpl(*renderArea, traverseLayers, buffer, - canCaptureBlackoutContent, regionSampling, grayscale, - captureResults); + renderFuture = + renderScreenImpl(*renderArea, traverseLayers, buffer, canCaptureBlackoutContent, + regionSampling, grayscale, captureResults); }); - // spring up a thread to unblock SF main thread and wait for - // RenderEngineResult to be available - if (captureListener != nullptr) { + + if (captureListener) { + // TODO: The future returned by std::async blocks the main thread. Return a chain of + // futures to the Binder thread instead. std::async([=]() mutable { ATRACE_NAME("captureListener is nonnull!"); - auto& [status, drawFence] = renderEngineResultFuture.get(); - captureResults.result = status; - captureResults.fence = new Fence(dup(drawFence)); + auto fenceResult = renderFuture.get(); + // TODO(b/232535621): Change ScreenCaptureResults to store a FenceResult. + captureResults.result = fenceStatus(fenceResult); + captureResults.fence = std::move(fenceResult).value_or(Fence::NO_FENCE); captureListener->onScreenCaptureCompleted(captureResults); }); } - return renderEngineResultFuture; + return renderFuture; }); - // flatten scheduleResultFuture object to single shared_future object - if (captureListener == nullptr) { - std::future captureScreenResultFuture = - ftl::chain(std::move(scheduleResultFuture)) - .then([=](std::shared_future futureObject) - -> renderengine::RenderEngineResult { - auto& [status, drawFence] = futureObject.get(); - return {status, base::unique_fd(dup(drawFence))}; - }); - return captureScreenResultFuture.share(); - } else { - return ftl::yield({NO_ERROR, base::unique_fd()}).share(); + if (captureListener) { + return ftl::yield(base::unexpected(NO_ERROR)).share(); } + + // Flatten nested futures. + std::future chain = + ftl::chain(std::move(future)).then([](std::shared_future future) { + return future.get(); + }); + + return chain.share(); } -std::shared_future SurfaceFlinger::renderScreenImpl( +std::shared_future SurfaceFlinger::renderScreenImpl( const RenderArea& renderArea, TraverseLayersFunction traverseLayers, const std::shared_ptr& buffer, bool canCaptureBlackoutContent, bool regionSampling, bool grayscale, @@ -6705,8 +6702,7 @@ std::shared_future SurfaceFlinger::renderScree // the impetus on WindowManager to not persist them. if (captureResults.capturedSecureLayers && !canCaptureBlackoutContent) { ALOGW("FB is protected: PERMISSION_DENIED"); - return ftl::yield({PERMISSION_DENIED, base::unique_fd()}) - .share(); + return ftl::yield(base::unexpected(PERMISSION_DENIED)).share(); } captureResults.buffer = buffer->getBuffer(); @@ -6827,23 +6823,22 @@ std::shared_future SurfaceFlinger::renderScree base::unique_fd bufferFence; getRenderEngine().useProtectedContext(useProtected); - const constexpr bool kUseFramebufferCache = false; - std::future drawLayersResult = - getRenderEngine().drawLayers(clientCompositionDisplay, clientRenderEngineLayers, buffer, - kUseFramebufferCache, std::move(bufferFence)); - - std::shared_future drawLayersResultFuture = - drawLayersResult.share(); // drawLayersResult will be moved to shared one + constexpr bool kUseFramebufferCache = false; + std::future chain = + ftl::chain(getRenderEngine().drawLayers(clientCompositionDisplay, + clientRenderEngineLayers, buffer, + kUseFramebufferCache, std::move(bufferFence))) + .then(&toFenceResult); + const auto future = chain.share(); for (auto* layer : renderedLayers) { - // make a copy of shared_future object for each layer - layer->onLayerDisplayed(drawLayersResultFuture); + layer->onLayerDisplayed(future); } // Always switch back to unprotected context. getRenderEngine().useProtectedContext(false); - return drawLayersResultFuture; + return future; } void SurfaceFlinger::windowInfosReported() { diff --git a/services/surfaceflinger/SurfaceFlinger.h b/services/surfaceflinger/SurfaceFlinger.h index c70e1749ff..dc54ac245b 100644 --- a/services/surfaceflinger/SurfaceFlinger.h +++ b/services/surfaceflinger/SurfaceFlinger.h @@ -49,6 +49,7 @@ #include #include +#include #include #include @@ -867,14 +868,15 @@ private: // Boot animation, on/off animations and screen capture void startBootAnim(); - std::shared_future captureScreenCommon( - RenderAreaFuture, TraverseLayersFunction, ui::Size bufferSize, ui::PixelFormat, - bool allowProtected, bool grayscale, const sp&); - std::shared_future captureScreenCommon( + std::shared_future captureScreenCommon(RenderAreaFuture, TraverseLayersFunction, + ui::Size bufferSize, ui::PixelFormat, + bool allowProtected, bool grayscale, + const sp&); + std::shared_future captureScreenCommon( RenderAreaFuture, TraverseLayersFunction, const std::shared_ptr&, bool regionSampling, bool grayscale, const sp&); - std::shared_future renderScreenImpl( + std::shared_future renderScreenImpl( const RenderArea&, TraverseLayersFunction, const std::shared_ptr&, bool canCaptureBlackoutContent, bool regionSampling, bool grayscale, ScreenCaptureResults&) EXCLUDES(mStateLock); diff --git a/services/surfaceflinger/TransactionCallbackInvoker.cpp b/services/surfaceflinger/TransactionCallbackInvoker.cpp index e1f348fdba..fa8cffc32a 100644 --- a/services/surfaceflinger/TransactionCallbackInvoker.cpp +++ b/services/surfaceflinger/TransactionCallbackInvoker.cpp @@ -133,10 +133,10 @@ status_t TransactionCallbackInvoker::addCallbackHandle(const sp& if (surfaceControl) { sp prevFence = nullptr; - for (const auto& futureStruct : handle->previousReleaseFences) { - sp currentFence = sp::make(dup(futureStruct.get().drawFence)); + for (const auto& future : handle->previousReleaseFences) { + sp currentFence = future.get().value_or(Fence::NO_FENCE); if (prevFence == nullptr && currentFence->getStatus() != Fence::Status::Invalid) { - prevFence = currentFence; + prevFence = std::move(currentFence); handle->previousReleaseFence = prevFence; } else if (prevFence != nullptr) { // If both fences are signaled or both are unsignaled, we need to merge @@ -147,7 +147,7 @@ status_t TransactionCallbackInvoker::addCallbackHandle(const sp& snprintf(fenceName, 32, "%.28s", handle->name.c_str()); sp mergedFence = Fence::merge(fenceName, prevFence, currentFence); if (mergedFence->isValid()) { - handle->previousReleaseFence = mergedFence; + handle->previousReleaseFence = std::move(mergedFence); prevFence = handle->previousReleaseFence; } } else if (currentFence->getStatus() == Fence::Status::Unsignaled) { @@ -158,11 +158,12 @@ status_t TransactionCallbackInvoker::addCallbackHandle(const sp& // by this point, they will have both signaled and only the timestamp // will be slightly off; any dependencies after this point will // already have been met. - handle->previousReleaseFence = currentFence; + handle->previousReleaseFence = std::move(currentFence); } } } - handle->previousReleaseFences = {}; + handle->previousReleaseFences.clear(); + FrameEventHistoryStats eventStats(handle->frameNumber, handle->gpuCompositionDoneFence->getSnapshot().fence, handle->compositorTiming, handle->refreshStartTime, diff --git a/services/surfaceflinger/TransactionCallbackInvoker.h b/services/surfaceflinger/TransactionCallbackInvoker.h index a68cd87313..b96444dcfb 100644 --- a/services/surfaceflinger/TransactionCallbackInvoker.h +++ b/services/surfaceflinger/TransactionCallbackInvoker.h @@ -28,8 +28,8 @@ #include #include +#include #include -#include #include namespace android { @@ -46,7 +46,7 @@ public: bool releasePreviousBuffer = false; std::string name; sp previousReleaseFence; - std::vector> previousReleaseFences; + std::vector> previousReleaseFences; std::variant> acquireTimeOrFence = -1; nsecs_t latchTime = -1; uint32_t transformHint = 0; diff --git a/services/surfaceflinger/fuzzer/surfaceflinger_layer_fuzzer.cpp b/services/surfaceflinger/fuzzer/surfaceflinger_layer_fuzzer.cpp index 46d52dd221..bd8081f863 100644 --- a/services/surfaceflinger/fuzzer/surfaceflinger_layer_fuzzer.cpp +++ b/services/surfaceflinger/fuzzer/surfaceflinger_layer_fuzzer.cpp @@ -21,6 +21,7 @@ #include #include #include +#include #include #include #include @@ -117,11 +118,11 @@ void LayerFuzzer::invokeBufferStateLayer() { const CompositorTiming compositor = {mFdp.ConsumeIntegral(), mFdp.ConsumeIntegral(), mFdp.ConsumeIntegral()}; - std::packaged_task renderResult([&] { - return renderengine::RenderEngineResult{mFdp.ConsumeIntegral(), - base::unique_fd(fence->get())}; - }); - layer->onLayerDisplayed(renderResult.get_future()); + + layer->onLayerDisplayed(ftl::yield(fence).share()); + layer->onLayerDisplayed( + ftl::yield(base::unexpected(mFdp.ConsumeIntegral())).share()); + layer->releasePendingBuffer(mFdp.ConsumeIntegral()); layer->finalizeFrameEventHistory(fenceTime, compositor); layer->onPostComposition(nullptr, fenceTime, fenceTime, compositor); diff --git a/services/surfaceflinger/tests/unittests/CompositionTest.cpp b/services/surfaceflinger/tests/unittests/CompositionTest.cpp index c541b9291f..bbfedc7685 100644 --- a/services/surfaceflinger/tests/unittests/CompositionTest.cpp +++ b/services/surfaceflinger/tests/unittests/CompositionTest.cpp @@ -245,15 +245,14 @@ void CompositionTest::captureScreenComposition() { HAL_PIXEL_FORMAT_RGBA_8888, 1, usage); - auto result = mFlinger.renderScreenImpl(*renderArea, traverseLayers, mCaptureScreenBuffer, + auto future = mFlinger.renderScreenImpl(*renderArea, traverseLayers, mCaptureScreenBuffer, forSystem, regionSampling); - EXPECT_TRUE(result.valid()); + ASSERT_TRUE(future.valid()); + const auto fenceResult = future.get(); - auto& [status, drawFence] = result.get(); - - EXPECT_EQ(NO_ERROR, status); - if (drawFence.ok()) { - sync_wait(drawFence.get(), -1); + EXPECT_EQ(NO_ERROR, fenceStatus(fenceResult)); + if (fenceResult.ok()) { + fenceResult.value()->waitForever(LOG_TAG); } LayerCase::cleanup(this); -- cgit v1.2.3-59-g8ed1b From b17c62120b646f378c0b842b3d7fcce8a5540e3e Mon Sep 17 00:00:00 2001 From: Dominik Laskowski Date: Mon, 9 May 2022 09:36:19 -0700 Subject: FTL: Yield futures without overhead ftl::yield, which lifts T to std::future, incurs the cost of allocating, ref counting, and locking the latter's shared state. Consolidate the existing std::future extensions into ftl::Future, and optimize ftl::yield by including static storage for T within. Bug: 232436803 Test: simpleperf (-31% cycles in postFramebuffer) Change-Id: I9a7ca7de17e7af10515de97d2f6a0dfa24e35d7a --- include/ftl/details/future.h | 98 ++++++++++++++ include/ftl/future.h | 146 ++++++++++++--------- libs/ftl/future_test.cpp | 10 +- services/surfaceflinger/BufferQueueLayer.cpp | 2 +- services/surfaceflinger/BufferQueueLayer.h | 2 +- services/surfaceflinger/BufferStateLayer.cpp | 2 +- services/surfaceflinger/BufferStateLayer.h | 2 +- .../include/compositionengine/LayerFE.h | 4 +- .../include/compositionengine/mock/LayerFE.h | 2 +- .../CompositionEngine/tests/MockHWComposer.h | 6 +- .../CompositionEngine/tests/OutputTest.cpp | 12 +- services/surfaceflinger/DisplayHardware/HWC2.cpp | 3 +- services/surfaceflinger/DisplayHardware/HWC2.h | 6 +- .../surfaceflinger/DisplayHardware/HWComposer.cpp | 5 +- .../surfaceflinger/DisplayHardware/HWComposer.h | 6 +- services/surfaceflinger/Layer.cpp | 2 +- services/surfaceflinger/Layer.h | 2 +- services/surfaceflinger/SurfaceFlinger.cpp | 29 ++-- services/surfaceflinger/SurfaceFlinger.h | 16 +-- .../surfaceflinger/TransactionCallbackInvoker.h | 5 +- .../unittests/mock/DisplayHardware/MockHWC2.h | 2 +- 21 files changed, 240 insertions(+), 122 deletions(-) create mode 100644 include/ftl/details/future.h (limited to 'services/surfaceflinger/BufferQueueLayer.cpp') diff --git a/include/ftl/details/future.h b/include/ftl/details/future.h new file mode 100644 index 0000000000..df1323e8be --- /dev/null +++ b/include/ftl/details/future.h @@ -0,0 +1,98 @@ +/* + * Copyright 2022 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#pragma once + +namespace android::ftl { + +template class> +class Future; + +namespace details { + +template +struct future_result { + using type = T; +}; + +template +struct future_result> { + using type = T; +}; + +template +struct future_result> { + using type = T; +}; + +template class FutureImpl> +struct future_result> { + using type = T; +}; + +template +using future_result_t = typename future_result::type; + +struct ValueTag {}; + +template class> +class BaseFuture; + +template +class BaseFuture { + using Impl = std::future; + + public: + Future share() { + if (T* value = std::get_if(&self())) { + return {ValueTag{}, std::move(*value)}; + } + + return std::get(self()).share(); + } + + protected: + T get() { + if (T* value = std::get_if(&self())) { + return std::move(*value); + } + + return std::get(self()).get(); + } + + private: + auto& self() { return static_cast(*this).future_; } +}; + +template +class BaseFuture { + using Impl = std::shared_future; + + protected: + const T& get() const { + if (const T* value = std::get_if(&self())) { + return *value; + } + + return std::get(self()).get(); + } + + private: + const auto& self() const { return static_cast(*this).future_; } +}; + +} // namespace details +} // namespace android::ftl diff --git a/include/ftl/future.h b/include/ftl/future.h index dd6358fa7d..c78f9b76b6 100644 --- a/include/ftl/future.h +++ b/include/ftl/future.h @@ -19,91 +19,115 @@ #include #include #include +#include + +#include namespace android::ftl { -// Creates a future that defers a function call until its result is queried. +// Thin wrapper around FutureImpl (concretely std::future or std::shared_future) with +// extensions for pure values (created via ftl::yield) and continuations. // -// auto future = ftl::defer([](int x) { return x + 1; }, 99); -// assert(future.get() == 100); +// See also SharedFuture shorthand below. // -template -inline auto defer(F&& f, Args&&... args) { - return std::async(std::launch::deferred, std::forward(f), std::forward(args)...); -} +template class FutureImpl = std::future> +class Future final : public details::BaseFuture, T, FutureImpl> { + using Base = details::BaseFuture; -// Creates a future that wraps a value. -// -// auto future = ftl::yield(42); -// assert(future.get() == 42); -// -// auto ptr = std::make_unique('!'); -// auto future = ftl::yield(std::move(ptr)); -// assert(*future.get() == '!'); -// -template -inline std::future yield(T&& v) { - return defer([](T&& v) { return std::forward(v); }, std::forward(v)); -} - -namespace details { - -template -struct future_result { - using type = T; -}; + friend Base; // For BaseFuture<...>::self. + friend details::BaseFuture, T, std::future>; // For BaseFuture<...>::share. -template -struct future_result> { - using type = T; -}; - -template -using future_result_t = typename future_result::type; + public: + // Constructs an invalid future. + Future() : future_(std::in_place_type>) {} -// Attaches a continuation to a future. The continuation is a function that maps T to either R or -// std::future. In the former case, the chain wraps the result in a future as if by ftl::yield. -// -// auto future = ftl::yield(123); -// std::future futures[] = {ftl::yield('a'), ftl::yield('b')}; -// -// std::future chain = -// ftl::chain(std::move(future)) -// .then([](int x) { return static_cast(x % 2); }) -// .then([&futures](std::size_t i) { return std::move(futures[i]); }); -// -// assert(chain.get() == 'b'); -// -template -struct Chain { - // Implicit conversion. - Chain(std::future&& f) : future(std::move(f)) {} - operator std::future&&() && { return std::move(future); } + // Constructs a future from its standard counterpart, implicitly. + Future(FutureImpl&& f) : future_(std::move(f)) {} - T get() && { return future.get(); } + bool valid() const { + return std::holds_alternative(future_) || std::get>(future_).valid(); + } + // Forwarding functions. Base::share is only defined when FutureImpl is std::future, whereas the + // following are defined for either FutureImpl: + using Base::get; + + // Attaches a continuation to the future. The continuation is a function that maps T to either R + // or ftl::Future. In the former case, the chain wraps the result in a future as if by + // ftl::yield. + // + // auto future = ftl::yield(123); + // ftl::Future futures[] = {ftl::yield('a'), ftl::yield('b')}; + // + // auto chain = + // ftl::Future(std::move(future)) + // .then([](int x) { return static_cast(x % 2); }) + // .then([&futures](std::size_t i) { return std::move(futures[i]); }); + // + // assert(chain.get() == 'b'); + // template > - auto then(F&& op) && -> Chain> { + auto then(F&& op) && -> Future> { return defer( [](auto&& f, F&& op) { R r = op(f.get()); - if constexpr (std::is_same_v>) { + if constexpr (std::is_same_v>) { return r; } else { return r.get(); } }, - std::move(future), std::forward(op)); + std::move(*this), std::forward(op)); } - std::future future; -}; + private: + template + friend Future yield(V&&); -} // namespace details + template + friend Future yield(Args&&...); + + template + Future(details::ValueTag, Args&&... args) + : future_(std::in_place_type, std::forward(args)...) {} + + std::variant> future_; +}; template -inline auto chain(std::future&& f) -> details::Chain { - return std::move(f); +using SharedFuture = Future; + +// Deduction guide for implicit conversion. +template class FutureImpl> +Future(FutureImpl&&) -> Future; + +// Creates a future that wraps a value. +// +// auto future = ftl::yield(42); +// assert(future.get() == 42); +// +// auto ptr = std::make_unique('!'); +// auto future = ftl::yield(std::move(ptr)); +// assert(*future.get() == '!'); +// +template +inline Future yield(V&& value) { + return {details::ValueTag{}, std::move(value)}; +} + +template +inline Future yield(Args&&... args) { + return {details::ValueTag{}, std::forward(args)...}; +} + +// Creates a future that defers a function call until its result is queried. +// +// auto future = ftl::defer([](int x) { return x + 1; }, 99); +// assert(future.get() == 100); +// +template +inline auto defer(F&& f, Args&&... args) { + return Future(std::async(std::launch::deferred, std::forward(f), std::forward(args)...)); } } // namespace android::ftl diff --git a/libs/ftl/future_test.cpp b/libs/ftl/future_test.cpp index 9b3e93683f..5a245b681c 100644 --- a/libs/ftl/future_test.cpp +++ b/libs/ftl/future_test.cpp @@ -42,9 +42,9 @@ TEST(Future, Example) { } { auto future = ftl::yield(123); - std::future futures[] = {ftl::yield('a'), ftl::yield('b')}; + ftl::Future futures[] = {ftl::yield('a'), ftl::yield('b')}; - std::future chain = ftl::chain(std::move(future)) + ftl::Future chain = ftl::Future(std::move(future)) .then([](int x) { return static_cast(x % 2); }) .then([&futures](size_t i) { return std::move(futures[i]); }); @@ -71,7 +71,7 @@ TEST(Future, Chain) { return ByteVector{str.begin(), str.end()}; }); - std::packaged_task(ByteVector)> decrement_bytes( + std::packaged_task(ByteVector)> decrement_bytes( [](ByteVector bytes) { return ftl::defer(decrement, std::move(bytes)); }); auto fetch = fetch_string.get_future(); @@ -81,7 +81,7 @@ TEST(Future, Chain) { EXPECT_EQ( "hello, world", - ftl::chain(std::move(fetch)) + ftl::Future(std::move(fetch)) .then([](const char* str) { return std::string(str); }) .then([&](std::string str) { auto append = append_string.get_future(); @@ -93,7 +93,7 @@ TEST(Future, Chain) { decrement_thread = std::thread(std::move(decrement_bytes), std::move(bytes)); return decrement; }) - .then([](std::future bytes) { return bytes; }) + .then([](ftl::Future bytes) { return bytes; }) .then([](const ByteVector& bytes) { return std::string(bytes.begin(), bytes.end()); }) .get()); diff --git a/services/surfaceflinger/BufferQueueLayer.cpp b/services/surfaceflinger/BufferQueueLayer.cpp index 6a1a38b39c..00b7085c8f 100644 --- a/services/surfaceflinger/BufferQueueLayer.cpp +++ b/services/surfaceflinger/BufferQueueLayer.cpp @@ -48,7 +48,7 @@ BufferQueueLayer::~BufferQueueLayer() { // Interface implementation for Layer // ----------------------------------------------------------------------- -void BufferQueueLayer::onLayerDisplayed(std::shared_future futureFenceResult) { +void BufferQueueLayer::onLayerDisplayed(ftl::SharedFuture futureFenceResult) { const sp releaseFence = futureFenceResult.get().value_or(Fence::NO_FENCE); mConsumer->setReleaseFence(releaseFence); diff --git a/services/surfaceflinger/BufferQueueLayer.h b/services/surfaceflinger/BufferQueueLayer.h index 4587b5e27c..60380837d1 100644 --- a/services/surfaceflinger/BufferQueueLayer.h +++ b/services/surfaceflinger/BufferQueueLayer.h @@ -42,7 +42,7 @@ public: // Implements Layer. const char* getType() const override { return "BufferQueueLayer"; } - void onLayerDisplayed(std::shared_future) override; + void onLayerDisplayed(ftl::SharedFuture) override; // If a buffer was replaced this frame, release the former buffer void releasePendingBuffer(nsecs_t dequeueReadyTime) override; diff --git a/services/surfaceflinger/BufferStateLayer.cpp b/services/surfaceflinger/BufferStateLayer.cpp index c88511049b..b424a4ae3a 100644 --- a/services/surfaceflinger/BufferStateLayer.cpp +++ b/services/surfaceflinger/BufferStateLayer.cpp @@ -73,7 +73,7 @@ BufferStateLayer::~BufferStateLayer() { // ----------------------------------------------------------------------- // Interface implementation for Layer // ----------------------------------------------------------------------- -void BufferStateLayer::onLayerDisplayed(std::shared_future futureFenceResult) { +void BufferStateLayer::onLayerDisplayed(ftl::SharedFuture futureFenceResult) { // If we are displayed on multiple displays in a single composition cycle then we would // need to do careful tracking to enable the use of the mLastClientCompositionFence. // For example we can only use it if all the displays are client comp, and we need diff --git a/services/surfaceflinger/BufferStateLayer.h b/services/surfaceflinger/BufferStateLayer.h index cc510d8c74..bce36d8092 100644 --- a/services/surfaceflinger/BufferStateLayer.h +++ b/services/surfaceflinger/BufferStateLayer.h @@ -39,7 +39,7 @@ public: // Implements Layer. const char* getType() const override { return "BufferStateLayer"; } - void onLayerDisplayed(std::shared_future) override; + void onLayerDisplayed(ftl::SharedFuture) override; void releasePendingBuffer(nsecs_t dequeueReadyTime) override; diff --git a/services/surfaceflinger/CompositionEngine/include/compositionengine/LayerFE.h b/services/surfaceflinger/CompositionEngine/include/compositionengine/LayerFE.h index b7fc62fd21..ec610c1b1d 100644 --- a/services/surfaceflinger/CompositionEngine/include/compositionengine/LayerFE.h +++ b/services/surfaceflinger/CompositionEngine/include/compositionengine/LayerFE.h @@ -16,7 +16,6 @@ #pragma once -#include #include #include #include @@ -33,6 +32,7 @@ // TODO(b/129481165): remove the #pragma below and fix conversion issues #pragma clang diagnostic pop // ignored "-Wconversion -Wextra" +#include #include #include @@ -157,7 +157,7 @@ public: ClientCompositionTargetSettings&) = 0; // Called after the layer is displayed to update the presentation fence - virtual void onLayerDisplayed(std::shared_future) = 0; + virtual void onLayerDisplayed(ftl::SharedFuture) = 0; // Gets some kind of identifier for the layer for debug purposes. virtual const char* getDebugName() const = 0; diff --git a/services/surfaceflinger/CompositionEngine/include/compositionengine/mock/LayerFE.h b/services/surfaceflinger/CompositionEngine/include/compositionengine/mock/LayerFE.h index 871599d2cd..1c5c10f823 100644 --- a/services/surfaceflinger/CompositionEngine/include/compositionengine/mock/LayerFE.h +++ b/services/surfaceflinger/CompositionEngine/include/compositionengine/mock/LayerFE.h @@ -49,7 +49,7 @@ public: std::vector( compositionengine::LayerFE::ClientCompositionTargetSettings&)); - MOCK_METHOD1(onLayerDisplayed, void(std::shared_future)); + MOCK_METHOD(void, onLayerDisplayed, (ftl::SharedFuture), (override)); MOCK_CONST_METHOD0(getDebugName, const char*()); MOCK_CONST_METHOD0(getSequence, int32_t()); diff --git a/services/surfaceflinger/CompositionEngine/tests/MockHWComposer.h b/services/surfaceflinger/CompositionEngine/tests/MockHWComposer.h index ff2aa15dc9..9b12b08063 100644 --- a/services/surfaceflinger/CompositionEngine/tests/MockHWComposer.h +++ b/services/surfaceflinger/CompositionEngine/tests/MockHWComposer.h @@ -84,9 +84,9 @@ public: MOCK_METHOD4(setDisplayContentSamplingEnabled, status_t(HalDisplayId, bool, uint8_t, uint64_t)); MOCK_METHOD4(getDisplayedContentSample, status_t(HalDisplayId, uint64_t, uint64_t, DisplayedFrameStats*)); - MOCK_METHOD4(setDisplayBrightness, - std::future(PhysicalDisplayId, float, float, - const Hwc2::Composer::DisplayBrightnessOptions&)); + MOCK_METHOD(ftl::Future, setDisplayBrightness, + (PhysicalDisplayId, float, float, const Hwc2::Composer::DisplayBrightnessOptions&), + (override)); MOCK_METHOD2(getDisplayBrightnessSupport, status_t(PhysicalDisplayId, bool*)); MOCK_METHOD2(onHotplug, diff --git a/services/surfaceflinger/CompositionEngine/tests/OutputTest.cpp b/services/surfaceflinger/CompositionEngine/tests/OutputTest.cpp index 784abeac29..deaea87ff0 100644 --- a/services/surfaceflinger/CompositionEngine/tests/OutputTest.cpp +++ b/services/surfaceflinger/CompositionEngine/tests/OutputTest.cpp @@ -3189,15 +3189,15 @@ TEST_F(OutputPostFramebufferTest, releaseFencesAreSentToLayerFE) { // would not survive certain calls like Fence::merge() which would return a // new instance. EXPECT_CALL(*mLayer1.layerFE, onLayerDisplayed(_)) - .WillOnce([&layer1Fence](std::shared_future futureFenceResult) { + .WillOnce([&layer1Fence](ftl::SharedFuture futureFenceResult) { EXPECT_EQ(FenceResult(layer1Fence), futureFenceResult.get()); }); EXPECT_CALL(*mLayer2.layerFE, onLayerDisplayed(_)) - .WillOnce([&layer2Fence](std::shared_future futureFenceResult) { + .WillOnce([&layer2Fence](ftl::SharedFuture futureFenceResult) { EXPECT_EQ(FenceResult(layer2Fence), futureFenceResult.get()); }); EXPECT_CALL(*mLayer3.layerFE, onLayerDisplayed(_)) - .WillOnce([&layer3Fence](std::shared_future futureFenceResult) { + .WillOnce([&layer3Fence](ftl::SharedFuture futureFenceResult) { EXPECT_EQ(FenceResult(layer3Fence), futureFenceResult.get()); }); @@ -3256,15 +3256,15 @@ TEST_F(OutputPostFramebufferTest, releasedLayersSentPresentFence) { // Each released layer should be given the presentFence. EXPECT_CALL(*releasedLayer1, onLayerDisplayed(_)) - .WillOnce([&presentFence](std::shared_future futureFenceResult) { + .WillOnce([&presentFence](ftl::SharedFuture futureFenceResult) { EXPECT_EQ(FenceResult(presentFence), futureFenceResult.get()); }); EXPECT_CALL(*releasedLayer2, onLayerDisplayed(_)) - .WillOnce([&presentFence](std::shared_future futureFenceResult) { + .WillOnce([&presentFence](ftl::SharedFuture futureFenceResult) { EXPECT_EQ(FenceResult(presentFence), futureFenceResult.get()); }); EXPECT_CALL(*releasedLayer3, onLayerDisplayed(_)) - .WillOnce([&presentFence](std::shared_future futureFenceResult) { + .WillOnce([&presentFence](ftl::SharedFuture futureFenceResult) { EXPECT_EQ(FenceResult(presentFence), futureFenceResult.get()); }); diff --git a/services/surfaceflinger/DisplayHardware/HWC2.cpp b/services/surfaceflinger/DisplayHardware/HWC2.cpp index adf4be3df5..c52e96d146 100644 --- a/services/surfaceflinger/DisplayHardware/HWC2.cpp +++ b/services/surfaceflinger/DisplayHardware/HWC2.cpp @@ -27,7 +27,6 @@ #include "HWC2.h" #include -#include #include #include #include @@ -543,7 +542,7 @@ Error Display::presentOrValidate(nsecs_t expectedPresentTime, uint32_t* outNumTy return error; } -std::future Display::setDisplayBrightness( +ftl::Future Display::setDisplayBrightness( float brightness, float brightnessNits, const Hwc2::Composer::DisplayBrightnessOptions& options) { return ftl::defer([composer = &mComposer, id = mId, brightness, brightnessNits, options] { diff --git a/services/surfaceflinger/DisplayHardware/HWC2.h b/services/surfaceflinger/DisplayHardware/HWC2.h index cca20bd47f..24aef9b73c 100644 --- a/services/surfaceflinger/DisplayHardware/HWC2.h +++ b/services/surfaceflinger/DisplayHardware/HWC2.h @@ -18,6 +18,7 @@ #include #include +#include #include #include #include @@ -28,7 +29,6 @@ #include #include -#include #include #include #include @@ -147,7 +147,7 @@ public: uint32_t* outNumRequests, android::sp* outPresentFence, uint32_t* state) = 0; - [[nodiscard]] virtual std::future setDisplayBrightness( + [[nodiscard]] virtual ftl::Future setDisplayBrightness( float brightness, float brightnessNits, const Hwc2::Composer::DisplayBrightnessOptions& options) = 0; [[nodiscard]] virtual hal::Error setActiveConfigWithConstraints( @@ -229,7 +229,7 @@ public: uint32_t* outNumRequests, android::sp* outPresentFence, uint32_t* state) override; - std::future setDisplayBrightness( + ftl::Future setDisplayBrightness( float brightness, float brightnessNits, const Hwc2::Composer::DisplayBrightnessOptions& options) override; hal::Error setActiveConfigWithConstraints(hal::HWConfigId configId, diff --git a/services/surfaceflinger/DisplayHardware/HWComposer.cpp b/services/surfaceflinger/DisplayHardware/HWComposer.cpp index 79e4c75393..0da8ecea85 100644 --- a/services/surfaceflinger/DisplayHardware/HWComposer.cpp +++ b/services/surfaceflinger/DisplayHardware/HWComposer.cpp @@ -30,7 +30,6 @@ #include #include #include -#include #include #include #include @@ -720,13 +719,13 @@ status_t HWComposer::getDisplayedContentSample(HalDisplayId displayId, uint64_t return NO_ERROR; } -std::future HWComposer::setDisplayBrightness( +ftl::Future HWComposer::setDisplayBrightness( PhysicalDisplayId displayId, float brightness, float brightnessNits, const Hwc2::Composer::DisplayBrightnessOptions& options) { RETURN_IF_INVALID_DISPLAY(displayId, ftl::yield(BAD_INDEX)); auto& display = mDisplayData[displayId].hwcDisplay; - return ftl::chain(display->setDisplayBrightness(brightness, brightnessNits, options)) + return display->setDisplayBrightness(brightness, brightnessNits, options) .then([displayId](hal::Error error) -> status_t { if (error == hal::Error::UNSUPPORTED) { RETURN_IF_HWC_ERROR(error, displayId, INVALID_OPERATION); diff --git a/services/surfaceflinger/DisplayHardware/HWComposer.h b/services/surfaceflinger/DisplayHardware/HWComposer.h index 7dc10eaa7d..4c0ecd8502 100644 --- a/services/surfaceflinger/DisplayHardware/HWComposer.h +++ b/services/surfaceflinger/DisplayHardware/HWComposer.h @@ -17,7 +17,6 @@ #pragma once #include -#include #include #include #include @@ -26,6 +25,7 @@ #include #include +#include #include #include @@ -195,7 +195,7 @@ public: DisplayedFrameStats* outStats) = 0; // Sets the brightness of a display. - virtual std::future setDisplayBrightness( + virtual ftl::Future setDisplayBrightness( PhysicalDisplayId, float brightness, float brightnessNits, const Hwc2::Composer::DisplayBrightnessOptions&) = 0; @@ -372,7 +372,7 @@ public: uint64_t maxFrames) override; status_t getDisplayedContentSample(HalDisplayId, uint64_t maxFrames, uint64_t timestamp, DisplayedFrameStats* outStats) override; - std::future setDisplayBrightness( + ftl::Future setDisplayBrightness( PhysicalDisplayId, float brightness, float brightnessNits, const Hwc2::Composer::DisplayBrightnessOptions&) override; diff --git a/services/surfaceflinger/Layer.cpp b/services/surfaceflinger/Layer.cpp index 2298f038e9..a4f25e2900 100644 --- a/services/surfaceflinger/Layer.cpp +++ b/services/surfaceflinger/Layer.cpp @@ -213,7 +213,7 @@ LayerCreationArgs::LayerCreationArgs(SurfaceFlinger* flinger, sp client, * Layer. So, the implementation is done in BufferLayer. When called on a * EffectLayer object, it's essentially a NOP. */ -void Layer::onLayerDisplayed(std::shared_future) {} +void Layer::onLayerDisplayed(ftl::SharedFuture) {} void Layer::removeRelativeZ(const std::vector& layersInTree) { if (mDrawingState.zOrderRelativeOf == nullptr) { diff --git a/services/surfaceflinger/Layer.h b/services/surfaceflinger/Layer.h index 100704369e..74755106c6 100644 --- a/services/surfaceflinger/Layer.h +++ b/services/surfaceflinger/Layer.h @@ -620,7 +620,7 @@ public: void prepareCompositionState(compositionengine::LayerFE::StateSubset subset) override; std::vector prepareClientCompositionList( compositionengine::LayerFE::ClientCompositionTargetSettings&) override; - void onLayerDisplayed(std::shared_future) override; + void onLayerDisplayed(ftl::SharedFuture) override; void setWasClientComposed(const sp& fence) override { mLastClientCompositionFence = fence; diff --git a/services/surfaceflinger/SurfaceFlinger.cpp b/services/surfaceflinger/SurfaceFlinger.cpp index d8a2696ef0..d333ff85f0 100644 --- a/services/surfaceflinger/SurfaceFlinger.cpp +++ b/services/surfaceflinger/SurfaceFlinger.cpp @@ -1693,7 +1693,7 @@ status_t SurfaceFlinger::setDisplayBrightness(const sp& displayToken, } const char* const whence = __func__; - return ftl::chain(mScheduler->schedule([=]() FTL_FAKE_GUARD(mStateLock) { + return ftl::Future(mScheduler->schedule([=]() FTL_FAKE_GUARD(mStateLock) { if (const auto display = getDisplayDeviceLocked(displayToken)) { const bool supportsDisplayBrightnessCommand = getHwComposer().getComposer()->isSupported( @@ -1731,7 +1731,7 @@ status_t SurfaceFlinger::setDisplayBrightness(const sp& displayToken, return ftl::yield(NAME_NOT_FOUND); } })) - .then([](std::future task) { return task; }) + .then([](ftl::Future task) { return task; }) .get(); } @@ -6577,7 +6577,7 @@ status_t SurfaceFlinger::captureLayers(const LayerCaptureArgs& args, return fenceStatus(future.get()); } -std::shared_future SurfaceFlinger::captureScreenCommon( +ftl::SharedFuture SurfaceFlinger::captureScreenCommon( RenderAreaFuture renderAreaFuture, TraverseLayersFunction traverseLayers, ui::Size bufferSize, ui::PixelFormat reqPixelFormat, bool allowProtected, bool grayscale, const sp& captureListener) { @@ -6629,7 +6629,7 @@ std::shared_future SurfaceFlinger::captureScreenCommon( false /* regionSampling */, grayscale, captureListener); } -std::shared_future SurfaceFlinger::captureScreenCommon( +ftl::SharedFuture SurfaceFlinger::captureScreenCommon( RenderAreaFuture renderAreaFuture, TraverseLayersFunction traverseLayers, const std::shared_ptr& buffer, bool regionSampling, bool grayscale, const sp& captureListener) { @@ -6638,7 +6638,7 @@ std::shared_future SurfaceFlinger::captureScreenCommon( bool canCaptureBlackoutContent = hasCaptureBlackoutContentPermission(); auto future = mScheduler->schedule([=, renderAreaFuture = std::move(renderAreaFuture)]() mutable - -> std::shared_future { + -> ftl::SharedFuture { ScreenCaptureResults captureResults; std::unique_ptr renderArea = renderAreaFuture.get(); if (!renderArea) { @@ -6648,7 +6648,7 @@ std::shared_future SurfaceFlinger::captureScreenCommon( return ftl::yield(base::unexpected(NO_ERROR)).share(); } - std::shared_future renderFuture; + ftl::SharedFuture renderFuture; renderArea->render([&] { renderFuture = renderScreenImpl(*renderArea, traverseLayers, buffer, canCaptureBlackoutContent, @@ -6675,15 +6675,14 @@ std::shared_future SurfaceFlinger::captureScreenCommon( } // Flatten nested futures. - std::future chain = - ftl::chain(std::move(future)).then([](std::shared_future future) { - return future.get(); - }); + auto chain = ftl::Future(std::move(future)).then([](ftl::SharedFuture future) { + return future; + }); return chain.share(); } -std::shared_future SurfaceFlinger::renderScreenImpl( +ftl::SharedFuture SurfaceFlinger::renderScreenImpl( const RenderArea& renderArea, TraverseLayersFunction traverseLayers, const std::shared_ptr& buffer, bool canCaptureBlackoutContent, bool regionSampling, bool grayscale, @@ -6824,10 +6823,10 @@ std::shared_future SurfaceFlinger::renderScreenImpl( getRenderEngine().useProtectedContext(useProtected); constexpr bool kUseFramebufferCache = false; - std::future chain = - ftl::chain(getRenderEngine().drawLayers(clientCompositionDisplay, - clientRenderEngineLayers, buffer, - kUseFramebufferCache, std::move(bufferFence))) + auto chain = + ftl::Future(getRenderEngine().drawLayers(clientCompositionDisplay, + clientRenderEngineLayers, buffer, + kUseFramebufferCache, std::move(bufferFence))) .then(&toFenceResult); const auto future = chain.share(); diff --git a/services/surfaceflinger/SurfaceFlinger.h b/services/surfaceflinger/SurfaceFlinger.h index dc54ac245b..52dd418bd2 100644 --- a/services/surfaceflinger/SurfaceFlinger.h +++ b/services/surfaceflinger/SurfaceFlinger.h @@ -27,6 +27,7 @@ #include #include #include +#include #include #include #include @@ -77,7 +78,6 @@ #include #include #include -#include #include #include #include @@ -398,7 +398,7 @@ private: using VsyncModulator = scheduler::VsyncModulator; using TransactionSchedule = scheduler::TransactionSchedule; using TraverseLayersFunction = std::function; - using RenderAreaFuture = std::future>; + using RenderAreaFuture = ftl::Future>; using DumpArgs = Vector; using Dumper = std::function; @@ -868,15 +868,15 @@ private: // Boot animation, on/off animations and screen capture void startBootAnim(); - std::shared_future captureScreenCommon(RenderAreaFuture, TraverseLayersFunction, - ui::Size bufferSize, ui::PixelFormat, - bool allowProtected, bool grayscale, - const sp&); - std::shared_future captureScreenCommon( + ftl::SharedFuture captureScreenCommon(RenderAreaFuture, TraverseLayersFunction, + ui::Size bufferSize, ui::PixelFormat, + bool allowProtected, bool grayscale, + const sp&); + ftl::SharedFuture captureScreenCommon( RenderAreaFuture, TraverseLayersFunction, const std::shared_ptr&, bool regionSampling, bool grayscale, const sp&); - std::shared_future renderScreenImpl( + ftl::SharedFuture renderScreenImpl( const RenderArea&, TraverseLayersFunction, const std::shared_ptr&, bool canCaptureBlackoutContent, bool regionSampling, bool grayscale, ScreenCaptureResults&) EXCLUDES(mStateLock); diff --git a/services/surfaceflinger/TransactionCallbackInvoker.h b/services/surfaceflinger/TransactionCallbackInvoker.h index b96444dcfb..81d79f0777 100644 --- a/services/surfaceflinger/TransactionCallbackInvoker.h +++ b/services/surfaceflinger/TransactionCallbackInvoker.h @@ -18,7 +18,6 @@ #include #include -#include #include #include #include @@ -26,9 +25,9 @@ #include #include - #include #include +#include #include #include @@ -46,7 +45,7 @@ public: bool releasePreviousBuffer = false; std::string name; sp previousReleaseFence; - std::vector> previousReleaseFences; + std::vector> previousReleaseFences; std::variant> acquireTimeOrFence = -1; nsecs_t latchTime = -1; uint32_t transformHint = 0; diff --git a/services/surfaceflinger/tests/unittests/mock/DisplayHardware/MockHWC2.h b/services/surfaceflinger/tests/unittests/mock/DisplayHardware/MockHWC2.h index 3e0d6d304b..07cd15da93 100644 --- a/services/surfaceflinger/tests/unittests/mock/DisplayHardware/MockHWC2.h +++ b/services/surfaceflinger/tests/unittests/mock/DisplayHardware/MockHWC2.h @@ -80,7 +80,7 @@ public: MOCK_METHOD(hal::Error, presentOrValidate, (nsecs_t, uint32_t *, uint32_t *, android::sp *, uint32_t *), (override)); - MOCK_METHOD(std::future, setDisplayBrightness, + MOCK_METHOD(ftl::Future, setDisplayBrightness, (float, float, const Hwc2::Composer::DisplayBrightnessOptions &), (override)); MOCK_METHOD(hal::Error, setActiveConfigWithConstraints, (hal::HWConfigId, const hal::VsyncPeriodChangeConstraints &, -- cgit v1.2.3-59-g8ed1b