From 3d1047b26c81b8f83e3e420f95fc47dd004266b7 Mon Sep 17 00:00:00 2001 From: Robert Carr Date: Mon, 20 Sep 2021 18:22:32 -0700 Subject: Simplify TransactionCallbackInvoker The old code was written around the old threading model, and had to deal with callback registration coming from multiple binder threads that could interleave with sendCallbacks. The old code likewise had to deal with cases where a Transaction would apply but not "latch" in this frame. Both of these cases are removed by queued transactions, and so we can rework the model to be much simpler. This is the first step towards another simplification used to rework the frame queuing model. Test: Existing tests pass Bug: 201436596 Change-Id: I6983221ce66bb31c5da1122bde176ab4465556eb --- .../surfaceflinger/TransactionCallbackInvoker.cpp | 152 ++------------------- 1 file changed, 10 insertions(+), 142 deletions(-) (limited to 'services/surfaceflinger/TransactionCallbackInvoker.cpp') diff --git a/services/surfaceflinger/TransactionCallbackInvoker.cpp b/services/surfaceflinger/TransactionCallbackInvoker.cpp index 6af69f0ef2..4b12a2640b 100644 --- a/services/surfaceflinger/TransactionCallbackInvoker.cpp +++ b/services/surfaceflinger/TransactionCallbackInvoker.cpp @@ -49,121 +49,25 @@ static bool containsOnCommitCallbacks(const std::vector& callbacks) return !callbacks.empty() && callbacks.front().type == CallbackId::Type::ON_COMMIT; } -TransactionCallbackInvoker::~TransactionCallbackInvoker() { - { - std::lock_guard lock(mMutex); - for (const auto& [listener, transactionStats] : mCompletedTransactions) { - listener->unlinkToDeath(mDeathRecipient); - } - } -} - -status_t TransactionCallbackInvoker::startRegistration(const ListenerCallbacks& listenerCallbacks) { - std::lock_guard lock(mMutex); - - auto [itr, inserted] = mRegisteringTransactions.insert(listenerCallbacks); +void TransactionCallbackInvoker::addEmptyTransaction(const ListenerCallbacks& listenerCallbacks) { auto& [listener, callbackIds] = listenerCallbacks; - - if (inserted) { - if (mCompletedTransactions.count(listener) == 0) { - status_t err = listener->linkToDeath(mDeathRecipient); - if (err != NO_ERROR) { - ALOGE("cannot add callback because linkToDeath failed, err: %d", err); - return err; - } - } - auto& transactionStatsDeque = mCompletedTransactions[listener]; - transactionStatsDeque.emplace_back(callbackIds); - } - - return NO_ERROR; -} - -status_t TransactionCallbackInvoker::endRegistration(const ListenerCallbacks& listenerCallbacks) { - std::lock_guard lock(mMutex); - - auto itr = mRegisteringTransactions.find(listenerCallbacks); - if (itr == mRegisteringTransactions.end()) { - ALOGE("cannot end a registration that does not exist"); - return BAD_VALUE; - } - - mRegisteringTransactions.erase(itr); - - return NO_ERROR; -} - -bool TransactionCallbackInvoker::isRegisteringTransaction( - const sp& transactionListener, const std::vector& callbackIds) { - ListenerCallbacks listenerCallbacks(transactionListener, callbackIds); - - auto itr = mRegisteringTransactions.find(listenerCallbacks); - return itr != mRegisteringTransactions.end(); -} - -status_t TransactionCallbackInvoker::registerPendingCallbackHandle( - const sp& handle) { - std::lock_guard lock(mMutex); - - // If we can't find the transaction stats something has gone wrong. The client should call - // startRegistration before trying to register a pending callback handle. - TransactionStats* transactionStats; - status_t err = findTransactionStats(handle->listener, handle->callbackIds, &transactionStats); - if (err != NO_ERROR) { - ALOGE("cannot find transaction stats"); - return err; - } - - mPendingTransactions[handle->listener][handle->callbackIds]++; - return NO_ERROR; -} - -status_t TransactionCallbackInvoker::finalizeCallbackHandle(const sp& handle, - const std::vector& jankData) { - auto listener = mPendingTransactions.find(handle->listener); - if (listener != mPendingTransactions.end()) { - auto& pendingCallbacks = listener->second; - auto pendingCallback = pendingCallbacks.find(handle->callbackIds); - - if (pendingCallback != pendingCallbacks.end()) { - auto& pendingCount = pendingCallback->second; - - // Decrease the pending count for this listener - if (--pendingCount == 0) { - pendingCallbacks.erase(pendingCallback); - } - } else { - ALOGW("there are more latched callbacks than there were registered callbacks"); - } - if (listener->second.size() == 0) { - mPendingTransactions.erase(listener); - } - } else { - ALOGW("cannot find listener in mPendingTransactions"); - } - - status_t err = addCallbackHandle(handle, jankData); - if (err != NO_ERROR) { - ALOGE("could not add callback handle"); - return err; - } - return NO_ERROR; + auto& transactionStatsDeque = mCompletedTransactions[listener]; + transactionStatsDeque.emplace_back(callbackIds); } -status_t TransactionCallbackInvoker::finalizeOnCommitCallbackHandles( +status_t TransactionCallbackInvoker::addOnCommitCallbackHandles( const std::deque>& handles, std::deque>& outRemainingHandles) { if (handles.empty()) { return NO_ERROR; } - std::lock_guard lock(mMutex); const std::vector& jankData = std::vector(); for (const auto& handle : handles) { if (!containsOnCommitCallbacks(handle->callbackIds)) { outRemainingHandles.push_back(handle); continue; } - status_t err = finalizeCallbackHandle(handle, jankData); + status_t err = addCallbackHandle(handle, jankData); if (err != NO_ERROR) { return err; } @@ -172,14 +76,13 @@ status_t TransactionCallbackInvoker::finalizeOnCommitCallbackHandles( return NO_ERROR; } -status_t TransactionCallbackInvoker::finalizePendingCallbackHandles( +status_t TransactionCallbackInvoker::addCallbackHandles( const std::deque>& handles, const std::vector& jankData) { if (handles.empty()) { return NO_ERROR; } - std::lock_guard lock(mMutex); for (const auto& handle : handles) { - status_t err = finalizeCallbackHandle(handle, jankData); + status_t err = addCallbackHandle(handle, jankData); if (err != NO_ERROR) { return err; } @@ -190,8 +93,6 @@ status_t TransactionCallbackInvoker::finalizePendingCallbackHandles( status_t TransactionCallbackInvoker::registerUnpresentedCallbackHandle( const sp& handle) { - std::lock_guard lock(mMutex); - return addCallbackHandle(handle, std::vector()); } @@ -208,9 +109,8 @@ status_t TransactionCallbackInvoker::findTransactionStats( return NO_ERROR; } } - - ALOGE("could not find transaction stats"); - return BAD_VALUE; + *outTransactionStats = &transactionStatsDeque.emplace_back(callbackIds); + return NO_ERROR; } status_t TransactionCallbackInvoker::addCallbackHandle(const sp& handle, @@ -244,13 +144,10 @@ status_t TransactionCallbackInvoker::addCallbackHandle(const sp& } void TransactionCallbackInvoker::addPresentFence(const sp& presentFence) { - std::lock_guard lock(mMutex); mPresentFence = presentFence; } void TransactionCallbackInvoker::sendCallbacks() { - std::lock_guard lock(mMutex); - // For each listener auto completedTransactionsItr = mCompletedTransactions.begin(); while (completedTransactionsItr != mCompletedTransactions.end()) { @@ -263,27 +160,9 @@ void TransactionCallbackInvoker::sendCallbacks() { while (transactionStatsItr != transactionStatsDeque.end()) { auto& transactionStats = *transactionStatsItr; - // If this transaction is still registering, it is not safe to send a callback - // because there could be surface controls that haven't been added to - // transaction stats or mPendingTransactions. - if (isRegisteringTransaction(listener, transactionStats.callbackIds)) { - break; - } - - // If we are still waiting on the callback handles for this transaction, stop - // here because all transaction callbacks for the same listener must come in order - auto pendingTransactions = mPendingTransactions.find(listener); - if (pendingTransactions != mPendingTransactions.end() && - pendingTransactions->second.count(transactionStats.callbackIds) != 0) { - break; - } - // If the transaction has been latched if (transactionStats.latchTime >= 0 && !containsOnCommitCallbacks(transactionStats.callbackIds)) { - if (!mPresentFence) { - break; - } transactionStats.presentFence = mPresentFence; } @@ -303,20 +182,9 @@ void TransactionCallbackInvoker::sendCallbacks() { // we get pointers that compare unequal in the SF process. interface_cast(listenerStats.listener) ->onTransactionCompleted(listenerStats); - if (transactionStatsDeque.empty()) { - listener->unlinkToDeath(mDeathRecipient); - completedTransactionsItr = - mCompletedTransactions.erase(completedTransactionsItr); - } else { - completedTransactionsItr++; - } - } else { - completedTransactionsItr = - mCompletedTransactions.erase(completedTransactionsItr); } - } else { - completedTransactionsItr++; } + completedTransactionsItr++; } if (mPresentFence) { -- cgit v1.2.3-59-g8ed1b From 3ec2b85e6b682ba5426a48144b7a0fc2ee507e84 Mon Sep 17 00:00:00 2001 From: Robert Carr Date: Tue, 28 Sep 2021 17:46:57 -0700 Subject: TransactionCallbackInvoker: Send callbacks on thread The binder serialization cost and one way method cost can add up when we have multiple layers. We invoked these callbacks directly from the main thread in order to reduce latency. Latency requirements are now loosened by two changes: 1. Most of the time we have a queue on the server side and won't be trying to make the next frame from the callback 2. In GL comp where frames are back to back, we now have release at latch. Bug: 201436596 Test: Existing tests pass Change-Id: I1372022b5130e041d6b2429a2e87e2c622086d7a --- .../surfaceflinger/TransactionCallbackInvoker.cpp | 36 ++++++++++++++++++++-- .../surfaceflinger/TransactionCallbackInvoker.h | 12 +++++++- 2 files changed, 45 insertions(+), 3 deletions(-) (limited to 'services/surfaceflinger/TransactionCallbackInvoker.cpp') diff --git a/services/surfaceflinger/TransactionCallbackInvoker.cpp b/services/surfaceflinger/TransactionCallbackInvoker.cpp index 4b12a2640b..c1eb8966d1 100644 --- a/services/surfaceflinger/TransactionCallbackInvoker.cpp +++ b/services/surfaceflinger/TransactionCallbackInvoker.cpp @@ -49,6 +49,31 @@ static bool containsOnCommitCallbacks(const std::vector& callbacks) return !callbacks.empty() && callbacks.front().type == CallbackId::Type::ON_COMMIT; } +TransactionCallbackInvoker::TransactionCallbackInvoker() { + mThread = std::thread([&]() { + std::unique_lock lock(mCallbackThreadMutex); + + while (mKeepRunning) { + while (mCallbackThreadWork.size() > 0) { + mCallbackThreadWork.front()(); + mCallbackThreadWork.pop(); + } + mCallbackConditionVariable.wait(lock); + } + }); +} + +TransactionCallbackInvoker::~TransactionCallbackInvoker() { + { + std::unique_lock lock(mCallbackThreadMutex); + mKeepRunning = false; + mCallbackConditionVariable.notify_all(); + } + if (mThread.joinable()) { + mThread.join(); + } +} + void TransactionCallbackInvoker::addEmptyTransaction(const ListenerCallbacks& listenerCallbacks) { auto& [listener, callbackIds] = listenerCallbacks; auto& transactionStatsDeque = mCompletedTransactions[listener]; @@ -180,8 +205,15 @@ void TransactionCallbackInvoker::sendCallbacks() { // keep it as an IBinder due to consistency reasons: if we // interface_cast at the IPC boundary when reading a Parcel, // we get pointers that compare unequal in the SF process. - interface_cast(listenerStats.listener) - ->onTransactionCompleted(listenerStats); + { + std::unique_lock lock(mCallbackThreadMutex); + mCallbackThreadWork.push( + [stats = std::move(listenerStats)]() { + interface_cast(stats.listener) + ->onTransactionCompleted(stats); + }); + mCallbackConditionVariable.notify_all(); + } } } completedTransactionsItr++; diff --git a/services/surfaceflinger/TransactionCallbackInvoker.h b/services/surfaceflinger/TransactionCallbackInvoker.h index 71ca6e5360..7e879e119b 100644 --- a/services/surfaceflinger/TransactionCallbackInvoker.h +++ b/services/surfaceflinger/TransactionCallbackInvoker.h @@ -18,6 +18,7 @@ #include #include +#include #include #include #include @@ -56,8 +57,11 @@ public: class TransactionCallbackInvoker { public: + TransactionCallbackInvoker(); + ~TransactionCallbackInvoker(); + status_t addCallbackHandles(const std::deque>& handles, - const std::vector& jankData); + const std::vector& jankData); status_t addOnCommitCallbackHandles(const std::deque>& handles, std::deque>& outRemainingHandles); @@ -88,6 +92,12 @@ private: mCompletedTransactions; sp mPresentFence; + + std::mutex mCallbackThreadMutex; + std::condition_variable mCallbackConditionVariable; + std::thread mThread; + bool mKeepRunning = true; + std::queue> mCallbackThreadWork; }; } // namespace android -- 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/TransactionCallbackInvoker.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/TransactionCallbackInvoker.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/TransactionCallbackInvoker.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 cd52e2db6c57326c1380cd53e9520adc7faf5ec9 Mon Sep 17 00:00:00 2001 From: Vishnu Nair Date: Mon, 18 Oct 2021 08:42:46 -0700 Subject: SurfaceFlinger: Fix duplicate callbacks Transaction callbacks are emitted early, for empty transactions, after latch for on commit callbacks and on post composition for transaction complete callbacks. Pending callbacks are stored together. If a transaction contains a layer that is presented and a layer that is not presented, the transaction callback will get added to the pending list after the transaction is committed and it will get emitted after buffers are latched and then again at the end of composition. To fix this we make sure to only emit on commit callbacks after a buffer is latched. Test: atest SurfaceFlinger_test Bug: 202394221 Change-Id: I356fbf221812060c17765c53cc3df24cb3cd139a --- services/surfaceflinger/SurfaceFlinger.cpp | 71 +++++++++++----------- services/surfaceflinger/SurfaceFlinger.h | 9 +-- .../surfaceflinger/TransactionCallbackInvoker.cpp | 11 +++- .../surfaceflinger/TransactionCallbackInvoker.h | 10 ++- .../surfaceflinger/tests/LayerCallback_test.cpp | 56 +++++++++++++++++ 5 files changed, 107 insertions(+), 50 deletions(-) (limited to 'services/surfaceflinger/TransactionCallbackInvoker.cpp') diff --git a/services/surfaceflinger/SurfaceFlinger.cpp b/services/surfaceflinger/SurfaceFlinger.cpp index 54bcd15cc2..53a4ae02eb 100644 --- a/services/surfaceflinger/SurfaceFlinger.cpp +++ b/services/surfaceflinger/SurfaceFlinger.cpp @@ -2021,17 +2021,23 @@ bool SurfaceFlinger::commit(nsecs_t frameTime, int64_t vsyncId, nsecs_t expected bool SurfaceFlinger::flushAndCommitTransactions() { ATRACE_CALL(); + bool needsTraversal = false; if (clearTransactionFlags(eTransactionFlushNeeded)) { - flushTransactionQueues(); + needsTraversal = flushTransactionQueues(); } - const bool shouldCommit = (getTransactionFlags() & ~eTransactionFlushNeeded) || mForceTraversal; + const bool shouldCommit = (getTransactionFlags() & ~eTransactionFlushNeeded) || needsTraversal; if (shouldCommit) { commitTransactions(); } - // Invoke OnCommit callbacks. - mTransactionCallbackInvoker.sendCallbacks(); + if (!needsTraversal) { + // Invoke empty transaction callbacks early. + mTransactionCallbackInvoker.sendCallbacks(false /* onCommitOnly */); + } else { + // Invoke OnCommit callbacks. + mTransactionCallbackInvoker.sendCallbacks(true /* onCommitOnly */); + } if (transactionFlushNeeded()) { setTransactionFlags(eTransactionFlushNeeded); @@ -2328,7 +2334,7 @@ void SurfaceFlinger::postComposition() { mVisibleRegionsWereDirtyThisFrame = false; mTransactionCallbackInvoker.addPresentFence(mPreviousPresentFences[0].fence); - mTransactionCallbackInvoker.sendCallbacks(); + mTransactionCallbackInvoker.sendCallbacks(false /* onCommitOnly */); mTransactionCallbackInvoker.clearCompletedTransactions(); if (display && display->isInternal() && display->getPowerMode() == hal::PowerMode::ON && @@ -2941,7 +2947,6 @@ void SurfaceFlinger::commitTransactionsLocked(uint32_t transactionFlags) { processDisplayChangesLocked(); processDisplayHotplugEventsLocked(); } - mForceTraversal = false; mForceTransactionDisplayChange = displayTransactionNeeded; if (mSomeChildrenChanged) { @@ -3415,11 +3420,8 @@ uint32_t SurfaceFlinger::setTransactionFlags(uint32_t mask, TransactionSchedule return old; } -void SurfaceFlinger::setTraversalNeeded() { - mForceTraversal = true; -} - -void SurfaceFlinger::flushTransactionQueues() { +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 @@ -3488,19 +3490,23 @@ void SurfaceFlinger::flushTransactionQueues() { // Now apply all transactions. for (const auto& transaction : transactions) { - 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); + 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::transactionFlushNeeded() { @@ -3706,7 +3712,7 @@ status_t SurfaceFlinger::setTransactionState( return NO_ERROR; } -void SurfaceFlinger::applyTransactionState(const FrameTimelineInfo& frameTimelineInfo, +bool SurfaceFlinger::applyTransactionState(const FrameTimelineInfo& frameTimelineInfo, const Vector& states, const Vector& displays, uint32_t flags, const InputWindowCommands& inputWindowCommands, @@ -3728,12 +3734,10 @@ void SurfaceFlinger::applyTransactionState(const FrameTimelineInfo& frameTimelin mTransactionCallbackInvoker.addEmptyTransaction(listener); } - std::unordered_set listenerCallbacksWithSurfaces; uint32_t clientStateFlags = 0; for (const ComposerState& state : states) { - clientStateFlags |= - setClientStateLocked(frameTimelineInfo, state, desiredPresentTime, isAutoTimestamp, - postTime, permissions, listenerCallbacksWithSurfaces); + clientStateFlags |= setClientStateLocked(frameTimelineInfo, state, desiredPresentTime, + isAutoTimestamp, postTime, permissions); if ((flags & eAnimation) && state.state.surface) { if (const auto layer = fromHandle(state.state.surface).promote(); layer) { mScheduler->recordLayerHistory(layer.get(), @@ -3743,10 +3747,6 @@ void SurfaceFlinger::applyTransactionState(const FrameTimelineInfo& frameTimelin } } - // If the state doesn't require a traversal and there are callbacks, send them now - if (!(clientStateFlags & eTraversalNeeded) && hasListenerCallbacks) { - mTransactionCallbackInvoker.sendCallbacks(); - } transactionFlags |= clientStateFlags; if (permissions & Permission::ACCESS_SURFACE_FLINGER) { @@ -3768,6 +3768,7 @@ void SurfaceFlinger::applyTransactionState(const FrameTimelineInfo& frameTimelin transactionFlags = eTransactionNeeded; } + bool needsTraversal = false; if (transactionFlags) { if (mInterceptor->isEnabled()) { mInterceptor->saveTransaction(states, mCurrentState.displays, displays, flags, @@ -3778,7 +3779,7 @@ void SurfaceFlinger::applyTransactionState(const FrameTimelineInfo& frameTimelin // so we don't have to wake up again next frame to preform an unnecessary traversal. if (transactionFlags & eTraversalNeeded) { transactionFlags = transactionFlags & (~eTraversalNeeded); - mForceTraversal = true; + needsTraversal = true; } if (transactionFlags) { setTransactionFlags(transactionFlags); @@ -3788,6 +3789,8 @@ void SurfaceFlinger::applyTransactionState(const FrameTimelineInfo& frameTimelin mAnimTransactionPending = true; } } + + return needsTraversal; } uint32_t SurfaceFlinger::setDisplayStateLocked(const DisplayState& s) { @@ -3856,10 +3859,10 @@ bool SurfaceFlinger::callingThreadHasUnscopedSurfaceFlingerAccess(bool usePermis return true; } -uint32_t SurfaceFlinger::setClientStateLocked( - const FrameTimelineInfo& frameTimelineInfo, const ComposerState& composerState, - int64_t desiredPresentTime, bool isAutoTimestamp, int64_t postTime, uint32_t permissions, - std::unordered_set& outListenerCallbacks) { +uint32_t SurfaceFlinger::setClientStateLocked(const FrameTimelineInfo& frameTimelineInfo, + const ComposerState& composerState, + int64_t desiredPresentTime, bool isAutoTimestamp, + int64_t postTime, uint32_t permissions) { const layer_state_t& s = composerState.state; const bool privileged = permissions & Permission::ACCESS_SURFACE_FLINGER; @@ -3873,13 +3876,11 @@ uint32_t SurfaceFlinger::setClientStateLocked( ListenerCallbacks onCommitCallbacks = listener.filter(CallbackId::Type::ON_COMMIT); if (!onCommitCallbacks.callbackIds.empty()) { filteredListeners.push_back(onCommitCallbacks); - outListenerCallbacks.insert(onCommitCallbacks); } ListenerCallbacks onCompleteCallbacks = listener.filter(CallbackId::Type::ON_COMPLETE); if (!onCompleteCallbacks.callbackIds.empty()) { filteredListeners.push_back(onCompleteCallbacks); - outListenerCallbacks.insert(onCompleteCallbacks); } } diff --git a/services/surfaceflinger/SurfaceFlinger.h b/services/surfaceflinger/SurfaceFlinger.h index c45eee1b32..c712061983 100644 --- a/services/surfaceflinger/SurfaceFlinger.h +++ b/services/surfaceflinger/SurfaceFlinger.h @@ -712,7 +712,7 @@ private: /* * Transactions */ - void applyTransactionState(const FrameTimelineInfo& info, const Vector& state, + bool applyTransactionState(const FrameTimelineInfo& info, const Vector& state, const Vector& displays, uint32_t flags, const InputWindowCommands& inputWindowCommands, const int64_t desiredPresentTime, bool isAutoTimestamp, @@ -722,15 +722,13 @@ private: int originPid, int originUid, uint64_t transactionId) REQUIRES(mStateLock); // flush pending transaction that was presented after desiredPresentTime. - void flushTransactionQueues(); + bool flushTransactionQueues(); // Returns true if there is at least one transaction that needs to be flushed bool transactionFlushNeeded(); uint32_t setClientStateLocked(const FrameTimelineInfo&, const ComposerState&, int64_t desiredPresentTime, bool isAutoTimestamp, - int64_t postTime, uint32_t permissions, - std::unordered_set&) - REQUIRES(mStateLock); + int64_t postTime, uint32_t permissions) REQUIRES(mStateLock); uint32_t getTransactionFlags() const; @@ -1115,7 +1113,6 @@ private: std::vector> mTransactionCommittedSignals; bool mAnimTransactionPending = false; SortedVector> mLayersPendingRemoval; - bool mForceTraversal = false; // global color transform states Daltonizer mDaltonizer; diff --git a/services/surfaceflinger/TransactionCallbackInvoker.cpp b/services/surfaceflinger/TransactionCallbackInvoker.cpp index 8fbf0b4d07..f3d46ea061 100644 --- a/services/surfaceflinger/TransactionCallbackInvoker.cpp +++ b/services/surfaceflinger/TransactionCallbackInvoker.cpp @@ -121,7 +121,7 @@ status_t TransactionCallbackInvoker::registerUnpresentedCallbackHandle( return addCallbackHandle(handle, std::vector()); } -status_t TransactionCallbackInvoker::findTransactionStats( +status_t TransactionCallbackInvoker::findOrCreateTransactionStats( const sp& listener, const std::vector& callbackIds, TransactionStats** outTransactionStats) { auto& transactionStatsDeque = mCompletedTransactions[listener]; @@ -143,7 +143,8 @@ status_t TransactionCallbackInvoker::addCallbackHandle(const sp& // If we can't find the transaction stats something has gone wrong. The client should call // startRegistration before trying to add a callback handle. TransactionStats* transactionStats; - status_t err = findTransactionStats(handle->listener, handle->callbackIds, &transactionStats); + status_t err = + findOrCreateTransactionStats(handle->listener, handle->callbackIds, &transactionStats); if (err != NO_ERROR) { return err; } @@ -204,7 +205,7 @@ void TransactionCallbackInvoker::addPresentFence(const sp& presentFence) mPresentFence = presentFence; } -void TransactionCallbackInvoker::sendCallbacks() { +void TransactionCallbackInvoker::sendCallbacks(bool onCommitOnly) { // For each listener auto completedTransactionsItr = mCompletedTransactions.begin(); while (completedTransactionsItr != mCompletedTransactions.end()) { @@ -216,6 +217,10 @@ void TransactionCallbackInvoker::sendCallbacks() { auto transactionStatsItr = transactionStatsDeque.begin(); while (transactionStatsItr != transactionStatsDeque.end()) { auto& transactionStats = *transactionStatsItr; + if (onCommitOnly && !containsOnCommitCallbacks(transactionStats.callbackIds)) { + transactionStatsItr++; + continue; + } // If the transaction has been latched if (transactionStats.latchTime >= 0 && diff --git a/services/surfaceflinger/TransactionCallbackInvoker.h b/services/surfaceflinger/TransactionCallbackInvoker.h index 100dbfa8aa..e203d41bd9 100644 --- a/services/surfaceflinger/TransactionCallbackInvoker.h +++ b/services/surfaceflinger/TransactionCallbackInvoker.h @@ -76,7 +76,7 @@ public: void addPresentFence(const sp& presentFence); - void sendCallbacks(); + void sendCallbacks(bool onCommitOnly); void clearCompletedTransactions() { mCompletedTransactions.clear(); } @@ -86,11 +86,9 @@ public: private: - status_t findTransactionStats(const sp& listener, - const std::vector& callbackIds, - TransactionStats** outTransactionStats); - - + status_t findOrCreateTransactionStats(const sp& listener, + const std::vector& callbackIds, + TransactionStats** outTransactionStats); std::unordered_map, std::deque, IListenerHash> mCompletedTransactions; diff --git a/services/surfaceflinger/tests/LayerCallback_test.cpp b/services/surfaceflinger/tests/LayerCallback_test.cpp index 9ddbed21d8..91a5b528f8 100644 --- a/services/surfaceflinger/tests/LayerCallback_test.cpp +++ b/services/surfaceflinger/tests/LayerCallback_test.cpp @@ -1029,4 +1029,60 @@ TEST_F(LayerCallbackTest, ExpectedPresentTime) { EXPECT_NO_FATAL_FAILURE(waitForCallback(callback, expected, true)); } +// b202394221 +TEST_F(LayerCallbackTest, EmptyBufferStateChanges) { + sp bufferLayer, emptyBufferLayer; + ASSERT_NO_FATAL_FAILURE(bufferLayer = createBufferStateLayer()); + ASSERT_NO_FATAL_FAILURE(emptyBufferLayer = createBufferStateLayer()); + + Transaction transaction; + CallbackHelper callback; + for (size_t i = 0; i < 10; i++) { + int err = fillTransaction(transaction, &callback, bufferLayer); + if (err) { + GTEST_SUCCEED() << "test not supported"; + return; + } + + ui::Size bufferSize = getBufferSize(); + + TransactionUtils::setFrame(transaction, bufferLayer, + Rect(0, 0, bufferSize.width, bufferSize.height), + Rect(0, 0, 32, 32)); + transaction.setPosition(emptyBufferLayer, 1 + i, 2 + i); + transaction.apply(); + + ExpectedResult expected; + expected.addSurface(ExpectedResult::Transaction::PRESENTED, bufferLayer, + ExpectedResult::Buffer::ACQUIRED, + (i == 0) ? ExpectedResult::PreviousBuffer::NOT_RELEASED + : ExpectedResult::PreviousBuffer::RELEASED); + expected.addSurface(ExpectedResult::Transaction::PRESENTED, emptyBufferLayer, + ExpectedResult::Buffer::NOT_ACQUIRED, + ExpectedResult::PreviousBuffer::NOT_RELEASED); + + EXPECT_NO_FATAL_FAILURE(waitForCallback(callback, expected)); + } + ASSERT_NO_FATAL_FAILURE(callback.verifyFinalState()); +} + +// b202394221 +TEST_F(LayerCallbackTest, DISABLED_NonBufferLayerStateChanges) { + sp layer; + ASSERT_NO_FATAL_FAILURE(layer = createColorLayer("ColorLayer", Color::RED)); + + Transaction transaction; + CallbackHelper callback; + int err = fillTransaction(transaction, &callback); + if (err) { + GTEST_SUCCEED() << "test not supported"; + return; + } + transaction.setPosition(layer, 1, 2); + transaction.apply(); + + ExpectedResult expected; + EXPECT_NO_FATAL_FAILURE(waitForCallback(callback, expected, true)); +} + } // namespace android -- cgit v1.2.3-59-g8ed1b From da1fd1508c914c7f0849e4e00a5fae5412433337 Mon Sep 17 00:00:00 2001 From: Vishnu Nair Date: Mon, 18 Oct 2021 09:36:33 -0700 Subject: SurfaceFlinger: Emit callbacks for non-buffer layer transactions Ensure we emit callbacks if the transaction contains only non-buffer layer state changes. Test: atest SurfaceFlinger_test Fixes: 205183085 Change-Id: I56bf0dcaff4312628fe2cd1d0b93db520518ec54 --- services/surfaceflinger/BufferStateLayer.cpp | 15 ++++++-- services/surfaceflinger/BufferStateLayer.h | 3 +- services/surfaceflinger/Layer.cpp | 11 ++++++ services/surfaceflinger/Layer.h | 6 +-- services/surfaceflinger/SurfaceFlinger.cpp | 21 +++++----- .../surfaceflinger/TransactionCallbackInvoker.cpp | 8 ++-- .../surfaceflinger/TransactionCallbackInvoker.h | 12 +++--- .../surfaceflinger/tests/LayerCallback_test.cpp | 45 +++++++++++++++++++++- 8 files changed, 89 insertions(+), 32 deletions(-) (limited to 'services/surfaceflinger/TransactionCallbackInvoker.cpp') diff --git a/services/surfaceflinger/BufferStateLayer.cpp b/services/surfaceflinger/BufferStateLayer.cpp index c213570c7f..3e09a40eba 100644 --- a/services/surfaceflinger/BufferStateLayer.cpp +++ b/services/surfaceflinger/BufferStateLayer.cpp @@ -549,13 +549,19 @@ bool BufferStateLayer::setSidebandStream(const sp& sidebandStream) } bool BufferStateLayer::setTransactionCompletedListeners( - const std::vector>& handles) { + const std::vector& listenerCallbacks, const sp& layerHandle) { // If there is no handle, we will not send a callback so reset mReleasePreviousBuffer and return - if (handles.empty()) { + if (listenerCallbacks.empty()) { mReleasePreviousBuffer = false; return false; } + std::vector> handles; + handles.reserve(listenerCallbacks.size()); + for (auto& [listener, callbackIds] : listenerCallbacks) { + handles.emplace_back(new CallbackHandle(listener, callbackIds, layerHandle)); + } + const bool willPresent = willPresentCurrentTransaction(); for (const auto& handle : handles) { @@ -571,9 +577,10 @@ bool BufferStateLayer::setTransactionCompletedListeners( // Store so latched time and release fence can be set mDrawingState.callbackHandles.push_back(handle); - } else { // If this layer will NOT need to be relatched and presented this frame + } else { + // If this layer will NOT need to be relatched and presented this frame // Notify the transaction completed thread this handle is done - mFlinger->getTransactionCallbackInvoker().registerUnpresentedCallbackHandle(handle); + mFlinger->getTransactionCallbackInvoker().addUnpresentedCallbackHandle(handle); } } diff --git a/services/surfaceflinger/BufferStateLayer.h b/services/surfaceflinger/BufferStateLayer.h index eea700cf7b..ceed188f0e 100644 --- a/services/surfaceflinger/BufferStateLayer.h +++ b/services/surfaceflinger/BufferStateLayer.h @@ -65,7 +65,8 @@ public: bool setSurfaceDamageRegion(const Region& surfaceDamage) override; bool setApi(int32_t api) override; bool setSidebandStream(const sp& sidebandStream) override; - bool setTransactionCompletedListeners(const std::vector>& handles) override; + bool setTransactionCompletedListeners(const std::vector& handles, + const sp& layerHandle) override; bool addFrameEvent(const sp& acquireFence, nsecs_t postedTime, nsecs_t requestedPresentTime) override; bool setPosition(float /*x*/, float /*y*/) override; diff --git a/services/surfaceflinger/Layer.cpp b/services/surfaceflinger/Layer.cpp index d68cf9720f..d8854d3033 100644 --- a/services/surfaceflinger/Layer.cpp +++ b/services/surfaceflinger/Layer.cpp @@ -2645,6 +2645,17 @@ bool Layer::setDropInputMode(gui::DropInputMode mode) { return true; } +bool Layer::setTransactionCompletedListeners( + const std::vector& listenerCallbacks, const sp&) { + if (listenerCallbacks.empty()) { + return false; + } + for (auto& listener : listenerCallbacks) { + mFlinger->getTransactionCallbackInvoker().addEmptyCallback(listener); + } + return false; +} + // --------------------------------------------------------------------------- std::ostream& operator<<(std::ostream& stream, const Layer::FrameRate& rate) { diff --git a/services/surfaceflinger/Layer.h b/services/surfaceflinger/Layer.h index 4569f9af23..f6f162128f 100644 --- a/services/surfaceflinger/Layer.h +++ b/services/surfaceflinger/Layer.h @@ -426,10 +426,8 @@ public: virtual bool setSurfaceDamageRegion(const Region& /*surfaceDamage*/) { return false; }; virtual bool setApi(int32_t /*api*/) { return false; }; virtual bool setSidebandStream(const sp& /*sidebandStream*/) { return false; }; - virtual bool setTransactionCompletedListeners( - const std::vector>& /*handles*/) { - return false; - }; + virtual bool setTransactionCompletedListeners(const std::vector& /*handles*/, + const sp& /* layerHandle */); virtual bool addFrameEvent(const sp& /*acquireFence*/, nsecs_t /*postedTime*/, nsecs_t /*requestedPresentTime*/) { return false; diff --git a/services/surfaceflinger/SurfaceFlinger.cpp b/services/surfaceflinger/SurfaceFlinger.cpp index 53a4ae02eb..af6d00041e 100644 --- a/services/surfaceflinger/SurfaceFlinger.cpp +++ b/services/surfaceflinger/SurfaceFlinger.cpp @@ -3727,11 +3727,10 @@ bool SurfaceFlinger::applyTransactionState(const FrameTimelineInfo& frameTimelin transactionFlags |= setDisplayStateLocked(display); } - // start and end registration for listeners w/ no surface so they can get their callback. Note - // that listeners with SurfaceControls will start registration during setClientStateLocked - // below. + // Add listeners w/ surfaces so they can get their callback. Note that listeners with + // SurfaceControls will start registration during setClientStateLocked below. for (const auto& listener : listenerCallbacks) { - mTransactionCallbackInvoker.addEmptyTransaction(listener); + mTransactionCallbackInvoker.addEmptyCallback(listener); } uint32_t clientStateFlags = 0; @@ -3903,7 +3902,7 @@ uint32_t SurfaceFlinger::setClientStateLocked(const FrameTimelineInfo& frameTime } if (layer == nullptr) { for (auto& [listener, callbackIds] : s.listeners) { - mTransactionCallbackInvoker.registerUnpresentedCallbackHandle( + mTransactionCallbackInvoker.addUnpresentedCallbackHandle( new CallbackHandle(listener, callbackIds, s.surface)); } return 0; @@ -4173,12 +4172,6 @@ uint32_t SurfaceFlinger::setClientStateLocked(const FrameTimelineInfo& frameTime flags |= eTransactionNeeded | eTraversalNeeded; } } - std::vector> callbackHandles; - if ((what & layer_state_t::eHasListenerCallbacksChanged) && (!filteredListeners.empty())) { - for (auto& [listener, callbackIds] : filteredListeners) { - callbackHandles.emplace_back(new CallbackHandle(listener, callbackIds, s.surface)); - } - } if (what & layer_state_t::eBufferChanged && layer->setBuffer(s.bufferData, postTime, desiredPresentTime, isAutoTimestamp, @@ -4188,7 +4181,11 @@ uint32_t SurfaceFlinger::setClientStateLocked(const FrameTimelineInfo& frameTime layer->setFrameTimelineVsyncForBufferlessTransaction(frameTimelineInfo, postTime); } - if (layer->setTransactionCompletedListeners(callbackHandles)) flags |= eTraversalNeeded; + if ((what & layer_state_t::eHasListenerCallbacksChanged) && (!filteredListeners.empty())) { + if (layer->setTransactionCompletedListeners(filteredListeners, s.surface)) { + flags |= eTraversalNeeded; + } + } // Do not put anything that updates layer state or modifies flags after // setTransactionCompletedListener return flags; diff --git a/services/surfaceflinger/TransactionCallbackInvoker.cpp b/services/surfaceflinger/TransactionCallbackInvoker.cpp index f3d46ea061..418fbc5c44 100644 --- a/services/surfaceflinger/TransactionCallbackInvoker.cpp +++ b/services/surfaceflinger/TransactionCallbackInvoker.cpp @@ -74,10 +74,10 @@ TransactionCallbackInvoker::~TransactionCallbackInvoker() { } } -void TransactionCallbackInvoker::addEmptyTransaction(const ListenerCallbacks& listenerCallbacks) { +void TransactionCallbackInvoker::addEmptyCallback(const ListenerCallbacks& listenerCallbacks) { auto& [listener, callbackIds] = listenerCallbacks; - auto& transactionStatsDeque = mCompletedTransactions[listener]; - transactionStatsDeque.emplace_back(callbackIds); + TransactionStats* transactionStats; + findOrCreateTransactionStats(listener, callbackIds, &transactionStats); } status_t TransactionCallbackInvoker::addOnCommitCallbackHandles( @@ -116,7 +116,7 @@ status_t TransactionCallbackInvoker::addCallbackHandles( return NO_ERROR; } -status_t TransactionCallbackInvoker::registerUnpresentedCallbackHandle( +status_t TransactionCallbackInvoker::addUnpresentedCallbackHandle( const sp& handle) { return addCallbackHandle(handle, std::vector()); } diff --git a/services/surfaceflinger/TransactionCallbackInvoker.h b/services/surfaceflinger/TransactionCallbackInvoker.h index e203d41bd9..6f67947081 100644 --- a/services/surfaceflinger/TransactionCallbackInvoker.h +++ b/services/surfaceflinger/TransactionCallbackInvoker.h @@ -71,8 +71,10 @@ public: // Adds the Transaction CallbackHandle from a layer that does not need to be relatched and // presented this frame. - status_t registerUnpresentedCallbackHandle(const sp& handle); - void addEmptyTransaction(const ListenerCallbacks& listenerCallbacks); + status_t addUnpresentedCallbackHandle(const sp& handle); + // Adds the callback handles for empty transactions or for non-buffer layer updates which do not + // include layer stats. + void addEmptyCallback(const ListenerCallbacks& listenerCallbacks); void addPresentFence(const sp& presentFence); @@ -81,14 +83,12 @@ public: mCompletedTransactions.clear(); } - status_t addCallbackHandle(const sp& handle, - const std::vector& jankData); - - private: status_t findOrCreateTransactionStats(const sp& listener, const std::vector& callbackIds, TransactionStats** outTransactionStats); + status_t addCallbackHandle(const sp& handle, + const std::vector& jankData); std::unordered_map, std::deque, IListenerHash> mCompletedTransactions; diff --git a/services/surfaceflinger/tests/LayerCallback_test.cpp b/services/surfaceflinger/tests/LayerCallback_test.cpp index 91a5b528f8..7beba15062 100644 --- a/services/surfaceflinger/tests/LayerCallback_test.cpp +++ b/services/surfaceflinger/tests/LayerCallback_test.cpp @@ -1067,7 +1067,7 @@ TEST_F(LayerCallbackTest, EmptyBufferStateChanges) { } // b202394221 -TEST_F(LayerCallbackTest, DISABLED_NonBufferLayerStateChanges) { +TEST_F(LayerCallbackTest, NonBufferLayerStateChanges) { sp layer; ASSERT_NO_FATAL_FAILURE(layer = createColorLayer("ColorLayer", Color::RED)); @@ -1085,4 +1085,47 @@ TEST_F(LayerCallbackTest, DISABLED_NonBufferLayerStateChanges) { EXPECT_NO_FATAL_FAILURE(waitForCallback(callback, expected, true)); } +class TimedCallbackHelper { +public: + static void function(void* callbackContext, nsecs_t, const sp&, + const std::vector&) { + if (!callbackContext) { + ALOGE("failed to get callback context"); + } + TimedCallbackHelper* helper = static_cast(callbackContext); + std::lock_guard lock(helper->mMutex); + helper->mInvokedTime = systemTime(); + helper->mCv.notify_all(); + } + + void waitForCallback() { + std::unique_lock lock(mMutex); + ASSERT_TRUE(mCv.wait_for(lock, std::chrono::seconds(3), [&] { return mInvokedTime != -1; })) + << "did not receive callback"; + } + void* getContext() { return static_cast(this); } + + std::mutex mMutex; + std::condition_variable mCv; + nsecs_t mInvokedTime = -1; +}; + +TEST_F(LayerCallbackTest, EmptyTransactionCallbackOrder) { + TimedCallbackHelper onCommitCallback; + TimedCallbackHelper onCompleteCallback; + + // Add transaction callback before on commit callback + Transaction() + .addTransactionCompletedCallback(onCompleteCallback.function, + onCompleteCallback.getContext()) + .addTransactionCommittedCallback(onCommitCallback.function, + onCommitCallback.getContext()) + .apply(); + + EXPECT_NO_FATAL_FAILURE(onCompleteCallback.waitForCallback()); + EXPECT_NO_FATAL_FAILURE(onCommitCallback.waitForCallback()); + // verify we get the oncomplete at the same time or after the oncommit callback. + EXPECT_GE(onCompleteCallback.mInvokedTime, onCommitCallback.mInvokedTime); +} + } // namespace android -- cgit v1.2.3-59-g8ed1b From a5505cb8fa988023685e8d67fcc8117ee7c63b1e Mon Sep 17 00:00:00 2001 From: Jiakai Zhang Date: Tue, 9 Nov 2021 11:46:30 +0000 Subject: Revert "SurfaceFlinger: Emit callbacks for non-buffer layer transactions" This reverts commit da1fd1508c914c7f0849e4e00a5fae5412433337. Reason for revert: Potential culprit CL for broken test b/205501709 Change-Id: Iece745e0690f4d31b93918697b306ded3abfd0d0 --- services/surfaceflinger/BufferStateLayer.cpp | 15 ++------ services/surfaceflinger/BufferStateLayer.h | 3 +- services/surfaceflinger/Layer.cpp | 11 ------ services/surfaceflinger/Layer.h | 6 ++- services/surfaceflinger/SurfaceFlinger.cpp | 21 +++++----- .../surfaceflinger/TransactionCallbackInvoker.cpp | 8 ++-- .../surfaceflinger/TransactionCallbackInvoker.h | 12 +++--- .../surfaceflinger/tests/LayerCallback_test.cpp | 45 +--------------------- 8 files changed, 32 insertions(+), 89 deletions(-) (limited to 'services/surfaceflinger/TransactionCallbackInvoker.cpp') diff --git a/services/surfaceflinger/BufferStateLayer.cpp b/services/surfaceflinger/BufferStateLayer.cpp index 3e09a40eba..c213570c7f 100644 --- a/services/surfaceflinger/BufferStateLayer.cpp +++ b/services/surfaceflinger/BufferStateLayer.cpp @@ -549,19 +549,13 @@ bool BufferStateLayer::setSidebandStream(const sp& sidebandStream) } bool BufferStateLayer::setTransactionCompletedListeners( - const std::vector& listenerCallbacks, const sp& layerHandle) { + const std::vector>& handles) { // If there is no handle, we will not send a callback so reset mReleasePreviousBuffer and return - if (listenerCallbacks.empty()) { + if (handles.empty()) { mReleasePreviousBuffer = false; return false; } - std::vector> handles; - handles.reserve(listenerCallbacks.size()); - for (auto& [listener, callbackIds] : listenerCallbacks) { - handles.emplace_back(new CallbackHandle(listener, callbackIds, layerHandle)); - } - const bool willPresent = willPresentCurrentTransaction(); for (const auto& handle : handles) { @@ -577,10 +571,9 @@ bool BufferStateLayer::setTransactionCompletedListeners( // Store so latched time and release fence can be set mDrawingState.callbackHandles.push_back(handle); - } else { - // If this layer will NOT need to be relatched and presented this frame + } else { // If this layer will NOT need to be relatched and presented this frame // Notify the transaction completed thread this handle is done - mFlinger->getTransactionCallbackInvoker().addUnpresentedCallbackHandle(handle); + mFlinger->getTransactionCallbackInvoker().registerUnpresentedCallbackHandle(handle); } } diff --git a/services/surfaceflinger/BufferStateLayer.h b/services/surfaceflinger/BufferStateLayer.h index ceed188f0e..eea700cf7b 100644 --- a/services/surfaceflinger/BufferStateLayer.h +++ b/services/surfaceflinger/BufferStateLayer.h @@ -65,8 +65,7 @@ public: bool setSurfaceDamageRegion(const Region& surfaceDamage) override; bool setApi(int32_t api) override; bool setSidebandStream(const sp& sidebandStream) override; - bool setTransactionCompletedListeners(const std::vector& handles, - const sp& layerHandle) 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; diff --git a/services/surfaceflinger/Layer.cpp b/services/surfaceflinger/Layer.cpp index d8854d3033..d68cf9720f 100644 --- a/services/surfaceflinger/Layer.cpp +++ b/services/surfaceflinger/Layer.cpp @@ -2645,17 +2645,6 @@ bool Layer::setDropInputMode(gui::DropInputMode mode) { return true; } -bool Layer::setTransactionCompletedListeners( - const std::vector& listenerCallbacks, const sp&) { - if (listenerCallbacks.empty()) { - return false; - } - for (auto& listener : listenerCallbacks) { - mFlinger->getTransactionCallbackInvoker().addEmptyCallback(listener); - } - return false; -} - // --------------------------------------------------------------------------- std::ostream& operator<<(std::ostream& stream, const Layer::FrameRate& rate) { diff --git a/services/surfaceflinger/Layer.h b/services/surfaceflinger/Layer.h index f6f162128f..4569f9af23 100644 --- a/services/surfaceflinger/Layer.h +++ b/services/surfaceflinger/Layer.h @@ -426,8 +426,10 @@ public: virtual bool setSurfaceDamageRegion(const Region& /*surfaceDamage*/) { return false; }; virtual bool setApi(int32_t /*api*/) { return false; }; virtual bool setSidebandStream(const sp& /*sidebandStream*/) { return false; }; - virtual bool setTransactionCompletedListeners(const std::vector& /*handles*/, - const sp& /* layerHandle */); + virtual bool setTransactionCompletedListeners( + const std::vector>& /*handles*/) { + return false; + }; virtual bool addFrameEvent(const sp& /*acquireFence*/, nsecs_t /*postedTime*/, nsecs_t /*requestedPresentTime*/) { return false; diff --git a/services/surfaceflinger/SurfaceFlinger.cpp b/services/surfaceflinger/SurfaceFlinger.cpp index af6d00041e..53a4ae02eb 100644 --- a/services/surfaceflinger/SurfaceFlinger.cpp +++ b/services/surfaceflinger/SurfaceFlinger.cpp @@ -3727,10 +3727,11 @@ bool SurfaceFlinger::applyTransactionState(const FrameTimelineInfo& frameTimelin transactionFlags |= setDisplayStateLocked(display); } - // Add listeners w/ surfaces so they can get their callback. Note that listeners with - // SurfaceControls will start registration during setClientStateLocked below. + // start and end registration for listeners w/ no surface so they can get their callback. Note + // that listeners with SurfaceControls will start registration during setClientStateLocked + // below. for (const auto& listener : listenerCallbacks) { - mTransactionCallbackInvoker.addEmptyCallback(listener); + mTransactionCallbackInvoker.addEmptyTransaction(listener); } uint32_t clientStateFlags = 0; @@ -3902,7 +3903,7 @@ uint32_t SurfaceFlinger::setClientStateLocked(const FrameTimelineInfo& frameTime } if (layer == nullptr) { for (auto& [listener, callbackIds] : s.listeners) { - mTransactionCallbackInvoker.addUnpresentedCallbackHandle( + mTransactionCallbackInvoker.registerUnpresentedCallbackHandle( new CallbackHandle(listener, callbackIds, s.surface)); } return 0; @@ -4172,6 +4173,12 @@ uint32_t SurfaceFlinger::setClientStateLocked(const FrameTimelineInfo& frameTime flags |= eTransactionNeeded | eTraversalNeeded; } } + std::vector> callbackHandles; + if ((what & layer_state_t::eHasListenerCallbacksChanged) && (!filteredListeners.empty())) { + for (auto& [listener, callbackIds] : filteredListeners) { + callbackHandles.emplace_back(new CallbackHandle(listener, callbackIds, s.surface)); + } + } if (what & layer_state_t::eBufferChanged && layer->setBuffer(s.bufferData, postTime, desiredPresentTime, isAutoTimestamp, @@ -4181,11 +4188,7 @@ uint32_t SurfaceFlinger::setClientStateLocked(const FrameTimelineInfo& frameTime layer->setFrameTimelineVsyncForBufferlessTransaction(frameTimelineInfo, postTime); } - if ((what & layer_state_t::eHasListenerCallbacksChanged) && (!filteredListeners.empty())) { - if (layer->setTransactionCompletedListeners(filteredListeners, s.surface)) { - flags |= eTraversalNeeded; - } - } + if (layer->setTransactionCompletedListeners(callbackHandles)) flags |= eTraversalNeeded; // Do not put anything that updates layer state or modifies flags after // setTransactionCompletedListener return flags; diff --git a/services/surfaceflinger/TransactionCallbackInvoker.cpp b/services/surfaceflinger/TransactionCallbackInvoker.cpp index 418fbc5c44..f3d46ea061 100644 --- a/services/surfaceflinger/TransactionCallbackInvoker.cpp +++ b/services/surfaceflinger/TransactionCallbackInvoker.cpp @@ -74,10 +74,10 @@ TransactionCallbackInvoker::~TransactionCallbackInvoker() { } } -void TransactionCallbackInvoker::addEmptyCallback(const ListenerCallbacks& listenerCallbacks) { +void TransactionCallbackInvoker::addEmptyTransaction(const ListenerCallbacks& listenerCallbacks) { auto& [listener, callbackIds] = listenerCallbacks; - TransactionStats* transactionStats; - findOrCreateTransactionStats(listener, callbackIds, &transactionStats); + auto& transactionStatsDeque = mCompletedTransactions[listener]; + transactionStatsDeque.emplace_back(callbackIds); } status_t TransactionCallbackInvoker::addOnCommitCallbackHandles( @@ -116,7 +116,7 @@ status_t TransactionCallbackInvoker::addCallbackHandles( return NO_ERROR; } -status_t TransactionCallbackInvoker::addUnpresentedCallbackHandle( +status_t TransactionCallbackInvoker::registerUnpresentedCallbackHandle( const sp& handle) { return addCallbackHandle(handle, std::vector()); } diff --git a/services/surfaceflinger/TransactionCallbackInvoker.h b/services/surfaceflinger/TransactionCallbackInvoker.h index 6f67947081..e203d41bd9 100644 --- a/services/surfaceflinger/TransactionCallbackInvoker.h +++ b/services/surfaceflinger/TransactionCallbackInvoker.h @@ -71,10 +71,8 @@ public: // Adds the Transaction CallbackHandle from a layer that does not need to be relatched and // presented this frame. - status_t addUnpresentedCallbackHandle(const sp& handle); - // Adds the callback handles for empty transactions or for non-buffer layer updates which do not - // include layer stats. - void addEmptyCallback(const ListenerCallbacks& listenerCallbacks); + status_t registerUnpresentedCallbackHandle(const sp& handle); + void addEmptyTransaction(const ListenerCallbacks& listenerCallbacks); void addPresentFence(const sp& presentFence); @@ -83,12 +81,14 @@ public: mCompletedTransactions.clear(); } + status_t addCallbackHandle(const sp& handle, + const std::vector& jankData); + + private: status_t findOrCreateTransactionStats(const sp& listener, const std::vector& callbackIds, TransactionStats** outTransactionStats); - status_t addCallbackHandle(const sp& handle, - const std::vector& jankData); std::unordered_map, std::deque, IListenerHash> mCompletedTransactions; diff --git a/services/surfaceflinger/tests/LayerCallback_test.cpp b/services/surfaceflinger/tests/LayerCallback_test.cpp index 7beba15062..91a5b528f8 100644 --- a/services/surfaceflinger/tests/LayerCallback_test.cpp +++ b/services/surfaceflinger/tests/LayerCallback_test.cpp @@ -1067,7 +1067,7 @@ TEST_F(LayerCallbackTest, EmptyBufferStateChanges) { } // b202394221 -TEST_F(LayerCallbackTest, NonBufferLayerStateChanges) { +TEST_F(LayerCallbackTest, DISABLED_NonBufferLayerStateChanges) { sp layer; ASSERT_NO_FATAL_FAILURE(layer = createColorLayer("ColorLayer", Color::RED)); @@ -1085,47 +1085,4 @@ TEST_F(LayerCallbackTest, NonBufferLayerStateChanges) { EXPECT_NO_FATAL_FAILURE(waitForCallback(callback, expected, true)); } -class TimedCallbackHelper { -public: - static void function(void* callbackContext, nsecs_t, const sp&, - const std::vector&) { - if (!callbackContext) { - ALOGE("failed to get callback context"); - } - TimedCallbackHelper* helper = static_cast(callbackContext); - std::lock_guard lock(helper->mMutex); - helper->mInvokedTime = systemTime(); - helper->mCv.notify_all(); - } - - void waitForCallback() { - std::unique_lock lock(mMutex); - ASSERT_TRUE(mCv.wait_for(lock, std::chrono::seconds(3), [&] { return mInvokedTime != -1; })) - << "did not receive callback"; - } - void* getContext() { return static_cast(this); } - - std::mutex mMutex; - std::condition_variable mCv; - nsecs_t mInvokedTime = -1; -}; - -TEST_F(LayerCallbackTest, EmptyTransactionCallbackOrder) { - TimedCallbackHelper onCommitCallback; - TimedCallbackHelper onCompleteCallback; - - // Add transaction callback before on commit callback - Transaction() - .addTransactionCompletedCallback(onCompleteCallback.function, - onCompleteCallback.getContext()) - .addTransactionCommittedCallback(onCommitCallback.function, - onCommitCallback.getContext()) - .apply(); - - EXPECT_NO_FATAL_FAILURE(onCompleteCallback.waitForCallback()); - EXPECT_NO_FATAL_FAILURE(onCommitCallback.waitForCallback()); - // verify we get the oncomplete at the same time or after the oncommit callback. - EXPECT_GE(onCompleteCallback.mInvokedTime, onCommitCallback.mInvokedTime); -} - } // namespace android -- cgit v1.2.3-59-g8ed1b From 34eb9ca577d78524b992d2af367e23ce89a9f034 Mon Sep 17 00:00:00 2001 From: Vishnu Nair Date: Thu, 18 Nov 2021 15:23:23 -0800 Subject: SF: Introduce background task executor Extract logic to execute work outside of the main thread from TransactionCallbackInvoker so we can reuse the thread for other tasks that are not critical to drawing. Bug: 206380307 Test: presubmit Change-Id: I8128d2f333e3aab5639cd1200e820de39f0b3191 --- services/surfaceflinger/Android.bp | 1 + services/surfaceflinger/BackgroundExecutor.cpp | 65 ++++++++++++++++++++++ services/surfaceflinger/BackgroundExecutor.h | 42 ++++++++++++++ .../surfaceflinger/TransactionCallbackInvoker.cpp | 39 ++----------- .../surfaceflinger/TransactionCallbackInvoker.h | 9 --- 5 files changed, 113 insertions(+), 43 deletions(-) create mode 100644 services/surfaceflinger/BackgroundExecutor.cpp create mode 100644 services/surfaceflinger/BackgroundExecutor.h (limited to 'services/surfaceflinger/TransactionCallbackInvoker.cpp') diff --git a/services/surfaceflinger/Android.bp b/services/surfaceflinger/Android.bp index fb42cc02eb..2a9e2e7f0d 100644 --- a/services/surfaceflinger/Android.bp +++ b/services/surfaceflinger/Android.bp @@ -144,6 +144,7 @@ cc_library_headers { filegroup { name: "libsurfaceflinger_sources", srcs: [ + "BackgroundExecutor.cpp", "BufferLayer.cpp", "BufferLayerConsumer.cpp", "BufferQueueLayer.cpp", diff --git a/services/surfaceflinger/BackgroundExecutor.cpp b/services/surfaceflinger/BackgroundExecutor.cpp new file mode 100644 index 0000000000..3663cdb0ec --- /dev/null +++ b/services/surfaceflinger/BackgroundExecutor.cpp @@ -0,0 +1,65 @@ +/* + * 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. + */ + +//#define LOG_NDEBUG 0 +#undef LOG_TAG +#define LOG_TAG "BackgroundExecutor" +#define ATRACE_TAG ATRACE_TAG_GRAPHICS + +#include "BackgroundExecutor.h" + +namespace android { + +ANDROID_SINGLETON_STATIC_INSTANCE(BackgroundExecutor); + +BackgroundExecutor::BackgroundExecutor() : Singleton() { + mThread = std::thread([&]() { + bool done = false; + while (!done) { + std::vector> tasks; + { + std::unique_lock lock(mMutex); + mWorkAvailableCv.wait(lock, [&]() { return mDone || !mTasks.empty(); }); + tasks = std::move(mTasks); + mTasks.clear(); + done = mDone; + } // unlock mMutex + + for (auto& task : tasks) { + task(); + } + } + }); +} + +BackgroundExecutor::~BackgroundExecutor() { + { + std::unique_lock lock(mMutex); + mDone = true; + mWorkAvailableCv.notify_all(); + } + if (mThread.joinable()) { + mThread.join(); + } +} + +void BackgroundExecutor::execute(std::function task) { + std::unique_lock lock(mMutex); + mTasks.emplace_back(std::move(task)); + mWorkAvailableCv.notify_all(); +} + +} // namespace android \ No newline at end of file diff --git a/services/surfaceflinger/BackgroundExecutor.h b/services/surfaceflinger/BackgroundExecutor.h new file mode 100644 index 0000000000..6f6d305280 --- /dev/null +++ b/services/surfaceflinger/BackgroundExecutor.h @@ -0,0 +1,42 @@ +/* + * 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 +#include +#include + +namespace android { + +// Executes tasks off the main thread. +class BackgroundExecutor : public Singleton { +public: + BackgroundExecutor(); + ~BackgroundExecutor(); + void execute(std::function); + +private: + std::mutex mMutex; + std::condition_variable mWorkAvailableCv; + std::thread mThread; + bool mDone = false; + std::vector> mTasks; +}; + +} // namespace android diff --git a/services/surfaceflinger/TransactionCallbackInvoker.cpp b/services/surfaceflinger/TransactionCallbackInvoker.cpp index f3d46ea061..b705d9cf7b 100644 --- a/services/surfaceflinger/TransactionCallbackInvoker.cpp +++ b/services/surfaceflinger/TransactionCallbackInvoker.cpp @@ -24,6 +24,7 @@ #define ATRACE_TAG ATRACE_TAG_GRAPHICS #include "TransactionCallbackInvoker.h" +#include "BackgroundExecutor.h" #include @@ -49,31 +50,6 @@ static bool containsOnCommitCallbacks(const std::vector& callbacks) return !callbacks.empty() && callbacks.front().type == CallbackId::Type::ON_COMMIT; } -TransactionCallbackInvoker::TransactionCallbackInvoker() { - mThread = std::thread([&]() { - std::unique_lock lock(mCallbackThreadMutex); - - while (mKeepRunning) { - while (mCallbackThreadWork.size() > 0) { - mCallbackThreadWork.front()(); - mCallbackThreadWork.pop(); - } - mCallbackConditionVariable.wait(lock); - } - }); -} - -TransactionCallbackInvoker::~TransactionCallbackInvoker() { - { - std::unique_lock lock(mCallbackThreadMutex); - mKeepRunning = false; - mCallbackConditionVariable.notify_all(); - } - if (mThread.joinable()) { - mThread.join(); - } -} - void TransactionCallbackInvoker::addEmptyTransaction(const ListenerCallbacks& listenerCallbacks) { auto& [listener, callbackIds] = listenerCallbacks; auto& transactionStatsDeque = mCompletedTransactions[listener]; @@ -242,15 +218,10 @@ void TransactionCallbackInvoker::sendCallbacks(bool onCommitOnly) { // keep it as an IBinder due to consistency reasons: if we // interface_cast at the IPC boundary when reading a Parcel, // we get pointers that compare unequal in the SF process. - { - std::unique_lock lock(mCallbackThreadMutex); - mCallbackThreadWork.push( - [stats = std::move(listenerStats)]() { - interface_cast(stats.listener) - ->onTransactionCompleted(stats); - }); - mCallbackConditionVariable.notify_all(); - } + BackgroundExecutor::getInstance().execute([stats = std::move(listenerStats)]() { + interface_cast(stats.listener) + ->onTransactionCompleted(stats); + }); } } completedTransactionsItr++; diff --git a/services/surfaceflinger/TransactionCallbackInvoker.h b/services/surfaceflinger/TransactionCallbackInvoker.h index e203d41bd9..5ef54757d7 100644 --- a/services/surfaceflinger/TransactionCallbackInvoker.h +++ b/services/surfaceflinger/TransactionCallbackInvoker.h @@ -61,9 +61,6 @@ public: class TransactionCallbackInvoker { public: - TransactionCallbackInvoker(); - ~TransactionCallbackInvoker(); - status_t addCallbackHandles(const std::deque>& handles, const std::vector& jankData); status_t addOnCommitCallbackHandles(const std::deque>& handles, @@ -94,12 +91,6 @@ private: mCompletedTransactions; sp mPresentFence; - - std::mutex mCallbackThreadMutex; - std::condition_variable mCallbackConditionVariable; - std::thread mThread; - bool mKeepRunning = true; - std::queue> mCallbackThreadWork; }; } // namespace android -- cgit v1.2.3-59-g8ed1b From 461296a52224f58ea4ffe7235d744260cb3ad01d Mon Sep 17 00:00:00 2001 From: Ady Abraham Date: Fri, 21 Jan 2022 11:11:31 -0800 Subject: SF: pass acquire fence on BLAST callbacks When latching unsignaled buffers, the acquire fence is not signaled by the time BLAST callback is invoked. In that case pass a fence instead. For latch signaled, we still pass the acquire time itself to avoid sending file descriptors over binder. Bug: 198190384 Test: SF unit tests Change-Id: Ic7ad9b603b60dbf46a62eaf6b76bfbdeeebf6cec --- libs/gui/ITransactionCompletedListener.cpp | 21 +++++++++++++++++++-- libs/gui/SurfaceComposerClient.cpp | 4 ++-- .../gui/include/gui/ITransactionCompletedListener.h | 13 +++++++------ libs/gui/include/gui/SurfaceComposerClient.h | 7 ++++--- libs/gui/include/gui/test/CallbackUtils.h | 11 +++++++---- services/surfaceflinger/BufferStateLayer.cpp | 14 ++++++++++---- services/surfaceflinger/BufferStateLayer.h | 2 +- .../surfaceflinger/TransactionCallbackInvoker.cpp | 2 +- .../surfaceflinger/TransactionCallbackInvoker.h | 2 +- 9 files changed, 52 insertions(+), 24 deletions(-) (limited to 'services/surfaceflinger/TransactionCallbackInvoker.cpp') diff --git a/libs/gui/ITransactionCompletedListener.cpp b/libs/gui/ITransactionCompletedListener.cpp index aa7ebc9eb3..f7392d4969 100644 --- a/libs/gui/ITransactionCompletedListener.cpp +++ b/libs/gui/ITransactionCompletedListener.cpp @@ -111,7 +111,14 @@ status_t JankData::readFromParcel(const Parcel* input) { status_t SurfaceStats::writeToParcel(Parcel* output) const { SAFE_PARCEL(output->writeStrongBinder, surfaceControl); - SAFE_PARCEL(output->writeInt64, acquireTime); + if (const auto* acquireFence = std::get_if>(&acquireTimeOrFence)) { + SAFE_PARCEL(output->writeBool, true); + SAFE_PARCEL(output->write, **acquireFence); + } else { + SAFE_PARCEL(output->writeBool, false); + SAFE_PARCEL(output->writeInt64, std::get(acquireTimeOrFence)); + } + if (previousReleaseFence) { SAFE_PARCEL(output->writeBool, true); SAFE_PARCEL(output->write, *previousReleaseFence); @@ -131,8 +138,18 @@ status_t SurfaceStats::writeToParcel(Parcel* output) const { status_t SurfaceStats::readFromParcel(const Parcel* input) { SAFE_PARCEL(input->readStrongBinder, &surfaceControl); - SAFE_PARCEL(input->readInt64, &acquireTime); + bool hasFence = false; + SAFE_PARCEL(input->readBool, &hasFence); + if (hasFence) { + acquireTimeOrFence = sp::make(); + SAFE_PARCEL(input->read, *std::get>(acquireTimeOrFence)); + } else { + nsecs_t acquireTime; + SAFE_PARCEL(input->readInt64, &acquireTime); + acquireTimeOrFence = acquireTime; + } + SAFE_PARCEL(input->readBool, &hasFence); if (hasFence) { previousReleaseFence = new Fence(); diff --git a/libs/gui/SurfaceComposerClient.cpp b/libs/gui/SurfaceComposerClient.cpp index 91b2fb1c3b..f78726c5a2 100644 --- a/libs/gui/SurfaceComposerClient.cpp +++ b/libs/gui/SurfaceComposerClient.cpp @@ -296,7 +296,7 @@ void TransactionCompletedListener::onTransactionCompleted(ListenerStats listener surfaceControlStats .emplace_back(callbacksMap[callbackId] .surfaceControls[surfaceStats.surfaceControl], - transactionStats.latchTime, surfaceStats.acquireTime, + transactionStats.latchTime, surfaceStats.acquireTimeOrFence, transactionStats.presentFence, surfaceStats.previousReleaseFence, surfaceStats.transformHint, surfaceStats.eventStats); @@ -321,7 +321,7 @@ void TransactionCompletedListener::onTransactionCompleted(ListenerStats listener surfaceControlStats .emplace_back(callbacksMap[callbackId] .surfaceControls[surfaceStats.surfaceControl], - transactionStats.latchTime, surfaceStats.acquireTime, + transactionStats.latchTime, surfaceStats.acquireTimeOrFence, transactionStats.presentFence, surfaceStats.previousReleaseFence, surfaceStats.transformHint, surfaceStats.eventStats); diff --git a/libs/gui/include/gui/ITransactionCompletedListener.h b/libs/gui/include/gui/ITransactionCompletedListener.h index 0df5822597..a791c665e1 100644 --- a/libs/gui/include/gui/ITransactionCompletedListener.h +++ b/libs/gui/include/gui/ITransactionCompletedListener.h @@ -30,6 +30,7 @@ #include #include #include +#include namespace android { @@ -130,12 +131,12 @@ public: status_t readFromParcel(const Parcel* input) override; SurfaceStats() = default; - SurfaceStats(const sp& sc, nsecs_t time, const sp& prevReleaseFence, - uint32_t hint, uint32_t currentMaxAcquiredBuffersCount, - FrameEventHistoryStats frameEventStats, std::vector jankData, - ReleaseCallbackId previousReleaseCallbackId) + SurfaceStats(const sp& sc, std::variant> acquireTimeOrFence, + const sp& prevReleaseFence, uint32_t hint, + uint32_t currentMaxAcquiredBuffersCount, FrameEventHistoryStats frameEventStats, + std::vector jankData, ReleaseCallbackId previousReleaseCallbackId) : surfaceControl(sc), - acquireTime(time), + acquireTimeOrFence(std::move(acquireTimeOrFence)), previousReleaseFence(prevReleaseFence), transformHint(hint), currentMaxAcquiredBufferCount(currentMaxAcquiredBuffersCount), @@ -144,7 +145,7 @@ public: previousReleaseCallbackId(previousReleaseCallbackId) {} sp surfaceControl; - nsecs_t acquireTime = -1; + std::variant> acquireTimeOrFence = -1; sp previousReleaseFence; uint32_t transformHint = 0; uint32_t currentMaxAcquiredBufferCount = 0; diff --git a/libs/gui/include/gui/SurfaceComposerClient.h b/libs/gui/include/gui/SurfaceComposerClient.h index 61eeab35e5..731ac65cd8 100644 --- a/libs/gui/include/gui/SurfaceComposerClient.h +++ b/libs/gui/include/gui/SurfaceComposerClient.h @@ -58,12 +58,13 @@ class Region; using gui::IRegionSamplingListener; struct SurfaceControlStats { - SurfaceControlStats(const sp& sc, nsecs_t latchTime, nsecs_t acquireTime, + SurfaceControlStats(const sp& sc, nsecs_t latchTime, + std::variant> acquireTimeOrFence, const sp& presentFence, const sp& prevReleaseFence, uint32_t hint, FrameEventHistoryStats eventStats) : surfaceControl(sc), latchTime(latchTime), - acquireTime(acquireTime), + acquireTimeOrFence(std::move(acquireTimeOrFence)), presentFence(presentFence), previousReleaseFence(prevReleaseFence), transformHint(hint), @@ -71,7 +72,7 @@ struct SurfaceControlStats { sp surfaceControl; nsecs_t latchTime = -1; - nsecs_t acquireTime = -1; + std::variant> acquireTimeOrFence = -1; sp presentFence; sp previousReleaseFence; uint32_t transformHint = 0; diff --git a/libs/gui/include/gui/test/CallbackUtils.h b/libs/gui/include/gui/test/CallbackUtils.h index 64032087eb..62d1496ccd 100644 --- a/libs/gui/include/gui/test/CallbackUtils.h +++ b/libs/gui/include/gui/test/CallbackUtils.h @@ -134,12 +134,15 @@ private: void verifySurfaceControlStats(const SurfaceControlStats& surfaceControlStats, nsecs_t latchTime) const { - const auto& [surfaceControl, latch, acquireTime, presentFence, previousReleaseFence, - transformHint, frameEvents] = surfaceControlStats; + const auto& [surfaceControl, latch, acquireTimeOrFence, presentFence, + previousReleaseFence, transformHint, frameEvents] = surfaceControlStats; - ASSERT_EQ(acquireTime > 0, mBufferResult == ExpectedResult::Buffer::ACQUIRED) + ASSERT_TRUE(std::holds_alternative(acquireTimeOrFence)); + ASSERT_EQ(std::get(acquireTimeOrFence) > 0, + mBufferResult == ExpectedResult::Buffer::ACQUIRED) << "bad acquire time"; - ASSERT_LE(acquireTime, latchTime) << "acquire time should be <= latch time"; + ASSERT_LE(std::get(acquireTimeOrFence), latchTime) + << "acquire time should be <= latch time"; if (mPreviousBufferResult == ExpectedResult::PreviousBuffer::RELEASED) { ASSERT_NE(previousReleaseFence, nullptr) diff --git a/services/surfaceflinger/BufferStateLayer.cpp b/services/surfaceflinger/BufferStateLayer.cpp index fccd8f149a..02e444df8e 100644 --- a/services/surfaceflinger/BufferStateLayer.cpp +++ b/services/surfaceflinger/BufferStateLayer.cpp @@ -416,8 +416,14 @@ bool BufferStateLayer::setBuffer(std::shared_ptr& ? bufferData.acquireFence : Fence::NO_FENCE; mDrawingState.acquireFenceTime = std::make_unique(mDrawingState.acquireFence); - // The acquire fences of BufferStateLayers have already signaled before they are set - mCallbackHandleAcquireTime = mDrawingState.acquireFenceTime->getSignalTime(); + if (mDrawingState.acquireFenceTime->getSignalTime() == Fence::SIGNAL_TIME_PENDING) { + // We latched this buffer unsiganled, so we need to pass the acquire fence + // on the callback instead of just the acquire time, since it's unknown at + // this point. + mCallbackHandleAcquireTimeOrFence = mDrawingState.acquireFence; + } else { + mCallbackHandleAcquireTimeOrFence = mDrawingState.acquireFenceTime->getSignalTime(); + } mDrawingState.modified = true; setTransactionFlags(eTransactionNeeded); @@ -527,7 +533,7 @@ bool BufferStateLayer::setTransactionCompletedListeners( // If this layer will be presented in this frame if (willPresent) { // If this transaction set an acquire fence on this layer, set its acquire time - handle->acquireTime = mCallbackHandleAcquireTime; + handle->acquireTimeOrFence = mCallbackHandleAcquireTimeOrFence; handle->frameNumber = mDrawingState.frameNumber; // Store so latched time and release fence can be set @@ -540,7 +546,7 @@ bool BufferStateLayer::setTransactionCompletedListeners( } mReleasePreviousBuffer = false; - mCallbackHandleAcquireTime = -1; + mCallbackHandleAcquireTimeOrFence = -1; return willPresent; } diff --git a/services/surfaceflinger/BufferStateLayer.h b/services/surfaceflinger/BufferStateLayer.h index 42562126ae..669eaadfec 100644 --- a/services/surfaceflinger/BufferStateLayer.h +++ b/services/surfaceflinger/BufferStateLayer.h @@ -145,7 +145,7 @@ private: // Stores the last set acquire fence signal time used to populate the callback handle's acquire // time. - nsecs_t mCallbackHandleAcquireTime = -1; + std::variant> mCallbackHandleAcquireTimeOrFence = -1; std::deque> mPendingJankClassifications; // An upper bound on the number of SurfaceFrames in the pending classifications deque. diff --git a/services/surfaceflinger/TransactionCallbackInvoker.cpp b/services/surfaceflinger/TransactionCallbackInvoker.cpp index b705d9cf7b..e1f348fdba 100644 --- a/services/surfaceflinger/TransactionCallbackInvoker.cpp +++ b/services/surfaceflinger/TransactionCallbackInvoker.cpp @@ -167,7 +167,7 @@ status_t TransactionCallbackInvoker::addCallbackHandle(const sp& handle->gpuCompositionDoneFence->getSnapshot().fence, handle->compositorTiming, handle->refreshStartTime, handle->dequeueReadyTime); - transactionStats->surfaceStats.emplace_back(surfaceControl, handle->acquireTime, + transactionStats->surfaceStats.emplace_back(surfaceControl, handle->acquireTimeOrFence, handle->previousReleaseFence, handle->transformHint, handle->currentMaxAcquiredBufferCount, diff --git a/services/surfaceflinger/TransactionCallbackInvoker.h b/services/surfaceflinger/TransactionCallbackInvoker.h index 5ef54757d7..a68cd87313 100644 --- a/services/surfaceflinger/TransactionCallbackInvoker.h +++ b/services/surfaceflinger/TransactionCallbackInvoker.h @@ -47,7 +47,7 @@ public: std::string name; sp previousReleaseFence; std::vector> previousReleaseFences; - nsecs_t acquireTime = -1; + std::variant> acquireTimeOrFence = -1; nsecs_t latchTime = -1; uint32_t transformHint = 0; uint32_t currentMaxAcquiredBufferCount = 0; -- 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/TransactionCallbackInvoker.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 8d7d0f42c697ad893df9249b6e66684adb9439f5 Mon Sep 17 00:00:00 2001 From: Alec Mouri Date: Tue, 10 May 2022 23:33:40 +0000 Subject: Use semaphore instead of condition variable BackgroundExecutor uses a condition variable to synchronize processing to a work queue, which means that there is possible mutex contention on the main thread in rare scenarios. Instead, we can make the main thread non-blocking with a thread-safe queue, and use semaphores for signaling the background thread to wake up. Using semaphores saves a small number of instructions, but overall reduces contention Bug: 232113929 Test: bouncy ball Change-Id: Iced25e8349bdb2a70cac1ed681059a0b14258407 --- services/surfaceflinger/BackgroundExecutor.cpp | 56 +++++++++++++--------- services/surfaceflinger/BackgroundExecutor.h | 27 ++++++++--- services/surfaceflinger/SurfaceFlinger.cpp | 14 +++--- .../surfaceflinger/TransactionCallbackInvoker.cpp | 5 +- 4 files changed, 65 insertions(+), 37 deletions(-) (limited to 'services/surfaceflinger/TransactionCallbackInvoker.cpp') diff --git a/services/surfaceflinger/BackgroundExecutor.cpp b/services/surfaceflinger/BackgroundExecutor.cpp index de8e6b380f..a15de2b183 100644 --- a/services/surfaceflinger/BackgroundExecutor.cpp +++ b/services/surfaceflinger/BackgroundExecutor.cpp @@ -19,6 +19,8 @@ #define LOG_TAG "BackgroundExecutor" #define ATRACE_TAG ATRACE_TAG_GRAPHICS +#include + #include "BackgroundExecutor.h" namespace android { @@ -27,41 +29,49 @@ ANDROID_SINGLETON_STATIC_INSTANCE(BackgroundExecutor); BackgroundExecutor::BackgroundExecutor() : Singleton() { mThread = std::thread([&]() { - bool done = false; - while (!done) { - std::vector> tasks; - { - std::unique_lock lock(mMutex); - android::base::ScopedLockAssertion assumeLock(mMutex); - mWorkAvailableCv.wait(lock, - [&]() REQUIRES(mMutex) { return mDone || !mTasks.empty(); }); - tasks = std::move(mTasks); - mTasks.clear(); - done = mDone; - } // unlock mMutex + LOG_ALWAYS_FATAL_IF(sem_init(&mSemaphore, 0, 0), "sem_init failed"); + while (!mDone) { + LOG_ALWAYS_FATAL_IF(sem_wait(&mSemaphore), "sem_wait failed (%d)", errno); + + ftl::SmallVector workItems; - for (auto& task : tasks) { - task(); + Work* work = mWorks.pop(); + while (work) { + workItems.push_back(work); + work = mWorks.pop(); + } + + // Sequence numbers are guaranteed to be in intended order, as we assume a single + // producer and single consumer. + std::stable_sort(workItems.begin(), workItems.end(), [](Work* left, Work* right) { + return left->sequence < right->sequence; + }); + for (Work* work : workItems) { + for (auto& task : work->tasks) { + task(); + } + delete work; } } }); } BackgroundExecutor::~BackgroundExecutor() { - { - std::scoped_lock lock(mMutex); - mDone = true; - mWorkAvailableCv.notify_all(); - } + mDone = true; + LOG_ALWAYS_FATAL_IF(sem_post(&mSemaphore), "sem_post failed"); if (mThread.joinable()) { mThread.join(); + LOG_ALWAYS_FATAL_IF(sem_destroy(&mSemaphore), "sem_destroy failed"); } } -void BackgroundExecutor::execute(std::function task) { - std::scoped_lock lock(mMutex); - mTasks.emplace_back(std::move(task)); - mWorkAvailableCv.notify_all(); +void BackgroundExecutor::sendCallbacks(Callbacks&& tasks) { + Work* work = new Work(); + work->sequence = mSequence; + work->tasks = std::move(tasks); + mWorks.push(work); + mSequence++; + LOG_ALWAYS_FATAL_IF(sem_post(&mSemaphore), "sem_post failed"); } } // namespace android \ No newline at end of file diff --git a/services/surfaceflinger/BackgroundExecutor.h b/services/surfaceflinger/BackgroundExecutor.h index 6db7dda7aa..eeaf3bdd2e 100644 --- a/services/surfaceflinger/BackgroundExecutor.h +++ b/services/surfaceflinger/BackgroundExecutor.h @@ -16,9 +16,11 @@ #pragma once +#include #include +#include +#include #include -#include #include #include #include @@ -30,13 +32,26 @@ class BackgroundExecutor : public Singleton { public: BackgroundExecutor(); ~BackgroundExecutor(); - void execute(std::function); + using Callbacks = ftl::SmallVector, 10>; + // Queues callbacks onto a work queue to be executed by a background thread. + // Note that this is not thread-safe - a single producer is assumed. + void sendCallbacks(Callbacks&& tasks); private: - std::mutex mMutex; - std::condition_variable mWorkAvailableCv GUARDED_BY(mMutex); - bool mDone GUARDED_BY(mMutex) = false; - std::vector> mTasks GUARDED_BY(mMutex); + sem_t mSemaphore; + std::atomic_bool mDone = false; + + // Sequence number for work items. + // Work items are batched by sequence number. Work items for earlier sequence numbers are + // executed first. Work items with the same sequence number are executed in the same order they + // were added to the stack (meaning the stack must reverse the order after popping from the + // queue) + int32_t mSequence = 0; + struct Work { + int32_t sequence = 0; + Callbacks tasks; + }; + LocklessStack mWorks; std::thread mThread; }; diff --git a/services/surfaceflinger/SurfaceFlinger.cpp b/services/surfaceflinger/SurfaceFlinger.cpp index d93281be42..1495249f43 100644 --- a/services/surfaceflinger/SurfaceFlinger.cpp +++ b/services/surfaceflinger/SurfaceFlinger.cpp @@ -3226,12 +3226,12 @@ void SurfaceFlinger::updateInputFlinger() { if (!updateWindowInfo && mInputWindowCommands.empty()) { return; } - BackgroundExecutor::getInstance().execute([updateWindowInfo, - windowInfos = std::move(windowInfos), - displayInfos = std::move(displayInfos), - inputWindowCommands = - std::move(mInputWindowCommands), - inputFlinger = mInputFlinger, this]() { + BackgroundExecutor::getInstance().sendCallbacks({[updateWindowInfo, + windowInfos = std::move(windowInfos), + displayInfos = std::move(displayInfos), + inputWindowCommands = + std::move(mInputWindowCommands), + inputFlinger = mInputFlinger, this]() { ATRACE_NAME("BackgroundExecutor::updateInputFlinger"); if (updateWindowInfo) { mWindowInfosListenerInvoker->windowInfosChanged(windowInfos, displayInfos, @@ -3244,7 +3244,7 @@ void SurfaceFlinger::updateInputFlinger() { for (const auto& focusRequest : inputWindowCommands.focusRequests) { inputFlinger->setFocusedWindow(focusRequest); } - }); + }}); mInputWindowCommands.clear(); } diff --git a/services/surfaceflinger/TransactionCallbackInvoker.cpp b/services/surfaceflinger/TransactionCallbackInvoker.cpp index e1f348fdba..9f4a6cd0e6 100644 --- a/services/surfaceflinger/TransactionCallbackInvoker.cpp +++ b/services/surfaceflinger/TransactionCallbackInvoker.cpp @@ -184,6 +184,7 @@ void TransactionCallbackInvoker::addPresentFence(const sp& presentFence) void TransactionCallbackInvoker::sendCallbacks(bool onCommitOnly) { // For each listener auto completedTransactionsItr = mCompletedTransactions.begin(); + BackgroundExecutor::Callbacks callbacks; while (completedTransactionsItr != mCompletedTransactions.end()) { auto& [listener, transactionStatsDeque] = *completedTransactionsItr; ListenerStats listenerStats; @@ -218,7 +219,7 @@ void TransactionCallbackInvoker::sendCallbacks(bool onCommitOnly) { // keep it as an IBinder due to consistency reasons: if we // interface_cast at the IPC boundary when reading a Parcel, // we get pointers that compare unequal in the SF process. - BackgroundExecutor::getInstance().execute([stats = std::move(listenerStats)]() { + callbacks.emplace_back([stats = std::move(listenerStats)]() { interface_cast(stats.listener) ->onTransactionCompleted(stats); }); @@ -230,6 +231,8 @@ void TransactionCallbackInvoker::sendCallbacks(bool onCommitOnly) { if (mPresentFence) { mPresentFence.clear(); } + + BackgroundExecutor::getInstance().sendCallbacks(std::move(callbacks)); } // ----------------------------------------------------------------------- -- cgit v1.2.3-59-g8ed1b