Second Patch for async RenderEngine
- pass a vector of <LayerSettings> 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
diff --git a/services/surfaceflinger/BufferQueueLayer.cpp b/services/surfaceflinger/BufferQueueLayer.cpp
index f98681e..6c60e53 100644
--- a/services/surfaceflinger/BufferQueueLayer.cpp
+++ b/services/surfaceflinger/BufferQueueLayer.cpp
@@ -48,7 +48,9 @@
// Interface implementation for Layer
// -----------------------------------------------------------------------
-void BufferQueueLayer::onLayerDisplayed(const sp<Fence>& releaseFence) {
+void BufferQueueLayer::onLayerDisplayed(
+ std::shared_future<renderengine::RenderEngineResult> futureRenderEngineResult) {
+ sp<Fence> 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 a3bd725..dfdb5c0 100644
--- a/services/surfaceflinger/BufferQueueLayer.h
+++ b/services/surfaceflinger/BufferQueueLayer.h
@@ -42,7 +42,8 @@
// Implements Layer.
const char* getType() const override { return "BufferQueueLayer"; }
- void onLayerDisplayed(const sp<Fence>& releaseFence) override;
+ void onLayerDisplayed(
+ std::shared_future<renderengine::RenderEngineResult> 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 132ee9d..454363a 100644
--- a/services/surfaceflinger/BufferStateLayer.cpp
+++ b/services/surfaceflinger/BufferStateLayer.cpp
@@ -70,69 +70,11 @@
}
}
-status_t BufferStateLayer::addReleaseFence(const sp<CallbackHandle>& ch,
- const sp<Fence>& 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<Fence> 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<Fence>& releaseFence) {
-
+void BufferStateLayer::onLayerDisplayed(
+ std::shared_future<renderengine::RenderEngineResult> 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 @@
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 @@
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 @@
mFlinger->getTransactionCallbackInvoker().addCallbackHandles(
mDrawingState.callbackHandles, jankData);
+ sp<Fence> 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<Fence>& releaseFence(mPreviousReleaseFence);
std::shared_ptr<FenceTime> releaseFenceTime = std::make_shared<FenceTime>(releaseFence);
{
Mutex::Autolock lock(mFrameEventHistoryMutex);
diff --git a/services/surfaceflinger/BufferStateLayer.h b/services/surfaceflinger/BufferStateLayer.h
index 87b68ea..6cb9b35 100644
--- a/services/surfaceflinger/BufferStateLayer.h
+++ b/services/surfaceflinger/BufferStateLayer.h
@@ -39,7 +39,9 @@
// Implements Layer.
const char* getType() const override { return "BufferStateLayer"; }
- void onLayerDisplayed(const sp<Fence>& releaseFence) override;
+ void onLayerDisplayed(
+ std::shared_future<renderengine::RenderEngineResult> futureRenderEngineResult) override;
+
void releasePendingBuffer(nsecs_t dequeueReadyTime) override;
void finalizeFrameEventHistory(const std::shared_ptr<FenceTime>& glDoneFence,
@@ -115,8 +117,6 @@
bool updateFrameEventHistory(const sp<Fence>& acquireFence, nsecs_t postedTime,
nsecs_t requestedPresentTime);
- status_t addReleaseFence(const sp<CallbackHandle>& ch, const sp<Fence>& releaseFence);
-
bool latchSidebandStream(bool& recomputeVisibleRegions) override;
bool hasFrameUpdate() const override;
@@ -139,7 +139,7 @@
std::shared_ptr<renderengine::ExternalTexture> getBufferFromBufferData(
const BufferData& bufferData);
- sp<Fence> mPreviousReleaseFence;
+ std::vector<std::shared_future<renderengine::RenderEngineResult>> 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 f7b71cf..ac243c0 100644
--- a/services/surfaceflinger/CompositionEngine/include/compositionengine/LayerFE.h
+++ b/services/surfaceflinger/CompositionEngine/include/compositionengine/LayerFE.h
@@ -16,6 +16,7 @@
#pragma once
+#include <future>
#include <optional>
#include <ostream>
#include <unordered_set>
@@ -26,6 +27,7 @@
#pragma clang diagnostic ignored "-Wextra"
#include <renderengine/LayerSettings.h>
+#include <renderengine/RenderEngine.h>
// TODO(b/129481165): remove the #pragma below and fix conversion issues
#pragma clang diagnostic pop // ignored "-Wconversion -Wextra"
@@ -151,7 +153,7 @@
ClientCompositionTargetSettings&) = 0;
// Called after the layer is displayed to update the presentation fence
- virtual void onLayerDisplayed(const sp<Fence>&) = 0;
+ virtual void onLayerDisplayed(std::shared_future<renderengine::RenderEngineResult>) = 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 d215bda..16aebef 100644
--- a/services/surfaceflinger/CompositionEngine/include/compositionengine/mock/LayerFE.h
+++ b/services/surfaceflinger/CompositionEngine/include/compositionengine/mock/LayerFE.h
@@ -39,7 +39,7 @@
std::vector<compositionengine::LayerFE::LayerSettings>(
compositionengine::LayerFE::ClientCompositionTargetSettings&));
- MOCK_METHOD1(onLayerDisplayed, void(const sp<Fence>&));
+ MOCK_METHOD1(onLayerDisplayed, void(std::shared_future<renderengine::RenderEngineResult>));
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 048d7c2..7ea1aa2 100644
--- a/services/surfaceflinger/CompositionEngine/src/Output.cpp
+++ b/services/surfaceflinger/CompositionEngine/src/Output.cpp
@@ -27,6 +27,7 @@
#include <compositionengine/impl/OutputLayer.h>
#include <compositionengine/impl/OutputLayerCompositionState.h>
#include <compositionengine/impl/planner/Planner.h>
+#include <ftl/future.h>
#include <thread>
@@ -1097,12 +1098,12 @@
setExpensiveRenderingExpected(true);
}
- std::vector<const renderengine::LayerSettings*> clientCompositionLayerPointers;
- clientCompositionLayerPointers.reserve(clientCompositionLayers.size());
+ std::vector<renderengine::LayerSettings> 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 @@
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 @@
releaseFence =
Fence::merge("LayerRelease", releaseFence, frame.clientTargetAcquireFence);
}
-
- layer->getLayerFE().onLayerDisplayed(releaseFence);
+ layer->getLayerFE().onLayerDisplayed(
+ ftl::yield<renderengine::RenderEngineResult>(
+ {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 @@
// 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<renderengine::RenderEngineResult>(
+ {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 e6b716e..ec52e59 100644
--- a/services/surfaceflinger/CompositionEngine/src/planner/CachedSet.cpp
+++ b/services/surfaceflinger/CompositionEngine/src/planner/CachedSet.cpp
@@ -193,11 +193,6 @@
clientCompositionList.cend());
}
- std::vector<const renderengine::LayerSettings*> 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 @@
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 @@
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 @@
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 @@
.alpha = half(0.05f),
};
- layerSettingsPointers.emplace_back(&highlight);
+ layerSettings.emplace_back(highlight);
}
auto texture = texturePool.borrowTexture();
@@ -273,8 +268,8 @@
}
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 8f0028c..cf63ef5 100644
--- a/services/surfaceflinger/CompositionEngine/tests/OutputTest.cpp
+++ b/services/surfaceflinger/CompositionEngine/tests/OutputTest.cpp
@@ -24,6 +24,7 @@
#include <compositionengine/mock/LayerFE.h>
#include <compositionengine/mock/OutputLayer.h>
#include <compositionengine/mock/RenderSurface.h>
+#include <ftl/future.h>
#include <gtest/gtest.h>
#include <renderengine/mock/RenderEngine.h>
#include <ui/Rect.h>
@@ -2884,12 +2885,24 @@
// 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<Fence>::get, Eq(layer1Fence.get()))));
- EXPECT_CALL(*mLayer2.layerFE,
- onLayerDisplayed(Property(&sp<Fence>::get, Eq(layer2Fence.get()))));
- EXPECT_CALL(*mLayer3.layerFE,
- onLayerDisplayed(Property(&sp<Fence>::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<renderengine::RenderEngineResult>
+ futureRenderEngineResult) {
+ EXPECT_EQ(layer1FD, futureRenderEngineResult.get().drawFence);
+ });
+ EXPECT_CALL(*mLayer2.layerFE, onLayerDisplayed(_))
+ .WillOnce([&layer2FD](std::shared_future<renderengine::RenderEngineResult>
+ futureRenderEngineResult) {
+ EXPECT_EQ(layer2FD, futureRenderEngineResult.get().drawFence);
+ });
+ EXPECT_CALL(*mLayer3.layerFE, onLayerDisplayed(_))
+ .WillOnce([&layer3FD](std::shared_future<renderengine::RenderEngineResult>
+ futureRenderEngineResult) {
+ EXPECT_EQ(layer3FD, futureRenderEngineResult.get().drawFence);
+ });
mOutput.postFramebuffer();
}
@@ -2915,9 +2928,9 @@
// 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 @@
EXPECT_CALL(*mRenderSurface, onPresentDisplayCompleted());
// Each released layer should be given the presentFence.
- EXPECT_CALL(*releasedLayer1,
- onLayerDisplayed(Property(&sp<Fence>::get, Eq(presentFence.get()))));
- EXPECT_CALL(*releasedLayer2,
- onLayerDisplayed(Property(&sp<Fence>::get, Eq(presentFence.get()))));
- EXPECT_CALL(*releasedLayer3,
- onLayerDisplayed(Property(&sp<Fence>::get, Eq(presentFence.get()))));
+ base::unique_fd layerFD(presentFence.get()->dup());
+ EXPECT_CALL(*releasedLayer1, onLayerDisplayed(_))
+ .WillOnce([&layerFD](std::shared_future<renderengine::RenderEngineResult>
+ futureRenderEngineResult) {
+ EXPECT_EQ(layerFD, futureRenderEngineResult.get().drawFence);
+ });
+ EXPECT_CALL(*releasedLayer2, onLayerDisplayed(_))
+ .WillOnce([&layerFD](std::shared_future<renderengine::RenderEngineResult>
+ futureRenderEngineResult) {
+ EXPECT_EQ(layerFD, futureRenderEngineResult.get().drawFence);
+ });
+ EXPECT_CALL(*releasedLayer3, onLayerDisplayed(_))
+ .WillOnce([&layerFD](std::shared_future<renderengine::RenderEngineResult>
+ futureRenderEngineResult) {
+ EXPECT_EQ(layerFD, futureRenderEngineResult.get().drawFence);
+ });
mOutput.postFramebuffer();
@@ -3131,9 +3154,9 @@
EXPECT_CALL(*mRenderSurface, dequeueBuffer(_)).WillRepeatedly(Return(mOutputBuffer));
EXPECT_CALL(mRenderEngine, drawLayers(_, IsEmpty(), _, false, _))
.WillRepeatedly([&](const renderengine::DisplaySettings&,
- const std::vector<const renderengine::LayerSettings*>&,
+ const std::vector<renderengine::LayerSettings>&,
const std::shared_ptr<renderengine::ExternalTexture>&, const bool,
- base::unique_fd &&)
+ base::unique_fd&&)
-> std::future<renderengine::RenderEngineResult> {
return futureOf<renderengine::RenderEngineResult>({NO_ERROR, base::unique_fd()});
});
@@ -3161,11 +3184,11 @@
}));
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 renderengine::LayerSettings*>&,
+ const std::vector<renderengine::LayerSettings>&,
const std::shared_ptr<renderengine::ExternalTexture>&, const bool,
- base::unique_fd &&)
+ base::unique_fd&&)
-> std::future<renderengine::RenderEngineResult> {
return futureOf<renderengine::RenderEngineResult>({NO_ERROR, base::unique_fd()});
});
@@ -3196,11 +3219,11 @@
}));
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 renderengine::LayerSettings*>&,
+ const std::vector<renderengine::LayerSettings>&,
const std::shared_ptr<renderengine::ExternalTexture>&, const bool,
- base::unique_fd &&)
+ base::unique_fd&&)
-> std::future<renderengine::RenderEngineResult> {
return futureOf<renderengine::RenderEngineResult>({NO_ERROR, base::unique_fd()});
});
@@ -3226,7 +3249,7 @@
.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<renderengine::RenderEngineResult>({NO_ERROR, base::unique_fd()}))))
@@ -3258,7 +3281,7 @@
.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<renderengine::RenderEngineResult>({NO_ERROR, base::unique_fd()}))));
EXPECT_CALL(mOutput, setExpensiveRenderingExpected(false));
@@ -3294,11 +3317,11 @@
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 renderengine::LayerSettings*>&,
+ const std::vector<renderengine::LayerSettings>&,
const std::shared_ptr<renderengine::ExternalTexture>&, const bool,
- base::unique_fd &&)
+ base::unique_fd&&)
-> std::future<renderengine::RenderEngineResult> {
return futureOf<renderengine::RenderEngineResult>({NO_ERROR, base::unique_fd()});
});
@@ -3330,10 +3353,10 @@
.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<renderengine::RenderEngineResult>({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<renderengine::RenderEngineResult>({NO_ERROR, base::unique_fd()}))));
@@ -3487,9 +3510,9 @@
EXPECT_CALL(mRenderEngine, drawLayers(_, _, _, false, _))
.WillRepeatedly(
[&](const renderengine::DisplaySettings&,
- const std::vector<const renderengine::LayerSettings*>&,
+ const std::vector<renderengine::LayerSettings>&,
const std::shared_ptr<renderengine::ExternalTexture>&, const bool,
- base::unique_fd &&) -> std::future<renderengine::RenderEngineResult> {
+ base::unique_fd&&) -> std::future<renderengine::RenderEngineResult> {
return futureOf<renderengine::RenderEngineResult>(
{NO_ERROR, base::unique_fd()});
});
diff --git a/services/surfaceflinger/CompositionEngine/tests/planner/CachedSetTest.cpp b/services/surfaceflinger/CompositionEngine/tests/planner/CachedSetTest.cpp
index ecb05f8..42b3d97 100644
--- a/services/surfaceflinger/CompositionEngine/tests/planner/CachedSetTest.cpp
+++ b/services/surfaceflinger/CompositionEngine/tests/planner/CachedSetTest.cpp
@@ -346,15 +346,15 @@
const auto drawLayers =
[&](const renderengine::DisplaySettings& displaySettings,
- const std::vector<const renderengine::LayerSettings*>& layers,
+ const std::vector<renderengine::LayerSettings>& layers,
const std::shared_ptr<renderengine::ExternalTexture>&, const bool,
- base::unique_fd &&) -> std::future<renderengine::RenderEngineResult> {
+ base::unique_fd&&) -> std::future<renderengine::RenderEngineResult> {
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<renderengine::RenderEngineResult>({NO_ERROR, base::unique_fd()});
};
@@ -398,15 +398,15 @@
const auto drawLayers =
[&](const renderengine::DisplaySettings& displaySettings,
- const std::vector<const renderengine::LayerSettings*>& layers,
+ const std::vector<renderengine::LayerSettings>& layers,
const std::shared_ptr<renderengine::ExternalTexture>&, const bool,
- base::unique_fd &&) -> std::future<renderengine::RenderEngineResult> {
+ base::unique_fd&&) -> std::future<renderengine::RenderEngineResult> {
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<renderengine::RenderEngineResult>({NO_ERROR, base::unique_fd()});
@@ -453,15 +453,15 @@
const auto drawLayers =
[&](const renderengine::DisplaySettings& displaySettings,
- const std::vector<const renderengine::LayerSettings*>& layers,
+ const std::vector<renderengine::LayerSettings>& layers,
const std::shared_ptr<renderengine::ExternalTexture>&, const bool,
- base::unique_fd &&) -> std::future<renderengine::RenderEngineResult> {
+ base::unique_fd&&) -> std::future<renderengine::RenderEngineResult> {
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<renderengine::RenderEngineResult>({NO_ERROR, base::unique_fd()});
@@ -656,26 +656,26 @@
const auto drawLayers =
[&](const renderengine::DisplaySettings&,
- const std::vector<const renderengine::LayerSettings*>& layers,
+ const std::vector<renderengine::LayerSettings>& layers,
const std::shared_ptr<renderengine::ExternalTexture>&, const bool,
- base::unique_fd &&) -> std::future<renderengine::RenderEngineResult> {
+ base::unique_fd&&) -> std::future<renderengine::RenderEngineResult> {
// 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<renderengine::RenderEngineResult>({NO_ERROR, base::unique_fd()});
@@ -717,27 +717,27 @@
const auto drawLayers =
[&](const renderengine::DisplaySettings&,
- const std::vector<const renderengine::LayerSettings*>& layers,
+ const std::vector<renderengine::LayerSettings>& layers,
const std::shared_ptr<renderengine::ExternalTexture>&, const bool,
- base::unique_fd &&) -> std::future<renderengine::RenderEngineResult> {
+ base::unique_fd&&) -> std::future<renderengine::RenderEngineResult> {
// 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<renderengine::RenderEngineResult>({NO_ERROR, base::unique_fd()});
@@ -867,16 +867,16 @@
const auto drawLayers =
[&](const renderengine::DisplaySettings&,
- const std::vector<const renderengine::LayerSettings*>& layers,
+ const std::vector<renderengine::LayerSettings>& layers,
const std::shared_ptr<renderengine::ExternalTexture>&, const bool,
- base::unique_fd &&) -> std::future<renderengine::RenderEngineResult> {
+ base::unique_fd&&) -> std::future<renderengine::RenderEngineResult> {
// 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<renderengine::RenderEngineResult>({NO_ERROR, base::unique_fd()});
};
diff --git a/services/surfaceflinger/Layer.cpp b/services/surfaceflinger/Layer.cpp
index 5707c67..d68cf97 100644
--- a/services/surfaceflinger/Layer.cpp
+++ b/services/surfaceflinger/Layer.cpp
@@ -221,7 +221,8 @@
* Layer. So, the implementation is done in BufferLayer. When called on a
* EffectLayer object, it's essentially a NOP.
*/
-void Layer::onLayerDisplayed(const sp<Fence>& /*releaseFence*/) {}
+void Layer::onLayerDisplayed(
+ std::shared_future<renderengine::RenderEngineResult> /*futureRenderEngineResult*/) {}
void Layer::removeRelativeZ(const std::vector<Layer*>& layersInTree) {
if (mDrawingState.zOrderRelativeOf == nullptr) {
diff --git a/services/surfaceflinger/Layer.h b/services/surfaceflinger/Layer.h
index 07b2eb5..4569f9a 100644
--- a/services/surfaceflinger/Layer.h
+++ b/services/surfaceflinger/Layer.h
@@ -616,7 +616,8 @@
void prepareCompositionState(compositionengine::LayerFE::StateSubset subset) override;
std::vector<compositionengine::LayerFE::LayerSettings> prepareClientCompositionList(
compositionengine::LayerFE::ClientCompositionTargetSettings&) override;
- void onLayerDisplayed(const sp<Fence>& releaseFence) override;
+ void onLayerDisplayed(
+ std::shared_future<renderengine::RenderEngineResult> futureRenderEngineResult) override;
void setWasClientComposed(const sp<Fence>& fence) override {
mLastClientCompositionFence = fence;
diff --git a/services/surfaceflinger/RegionSamplingThread.cpp b/services/surfaceflinger/RegionSamplingThread.cpp
index aa2fec5..d0f56b5 100644
--- a/services/surfaceflinger/RegionSamplingThread.cpp
+++ b/services/surfaceflinger/RegionSamplingThread.cpp
@@ -356,10 +356,13 @@
renderengine::ExternalTexture::Usage::WRITEABLE);
}
- const sp<SyncScreenCaptureListener> 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<Descriptor> activeDescriptors;
for (const auto& descriptor : descriptors) {
diff --git a/services/surfaceflinger/SurfaceFlinger.cpp b/services/surfaceflinger/SurfaceFlinger.cpp
index acb81dc..638458c 100644
--- a/services/surfaceflinger/SurfaceFlinger.cpp
+++ b/services/surfaceflinger/SurfaceFlinger.cpp
@@ -5972,9 +5972,10 @@
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 @@
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 @@
});
};
- 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<IScreenCaptureListener>& captureListener) {
+std::shared_future<renderengine::RenderEngineResult> SurfaceFlinger::captureScreenCommon(
+ RenderAreaFuture renderAreaFuture, TraverseLayersFunction traverseLayers,
+ ui::Size bufferSize, ui::PixelFormat reqPixelFormat, bool allowProtected, bool grayscale,
+ const sp<IScreenCaptureListener>& 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<renderengine::RenderEngineResult>({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 @@
false /* regionSampling */, grayscale, captureListener);
}
-status_t SurfaceFlinger::captureScreenCommon(
+std::shared_future<renderengine::RenderEngineResult> SurfaceFlinger::captureScreenCommon(
RenderAreaFuture renderAreaFuture, TraverseLayersFunction traverseLayers,
const std::shared_ptr<renderengine::ExternalTexture>& buffer, bool regionSampling,
bool grayscale, const sp<IScreenCaptureListener>& captureListener) {
ATRACE_CALL();
- if (captureListener == nullptr) {
- ALOGE("capture screen must provide a capture listener callback");
- return BAD_VALUE;
- }
-
bool canCaptureBlackoutContent = hasCaptureBlackoutContentPermission();
- static_cast<void>(schedule([=, renderAreaFuture = std::move(renderAreaFuture)]() mutable {
+ auto scheduleResultFuture = schedule([=,
+ renderAreaFuture = std::move(renderAreaFuture)]() mutable
+ -> std::shared_future<renderengine::RenderEngineResult> {
if (mRefreshPending) {
ALOGW("Skipping screenshot for now");
captureScreenCommon(std::move(renderAreaFuture), traverseLayers, buffer, regionSampling,
grayscale, captureListener);
- return;
+ return ftl::yield<renderengine::RenderEngineResult>({NO_ERROR, base::unique_fd()})
+ .share();
}
ScreenCaptureResults captureResults;
std::unique_ptr<RenderArea> renderArea = renderAreaFuture.get();
@@ -6220,24 +6230,44 @@
ALOGW("Skipping screen capture because of invalid render area.");
captureResults.result = NO_MEMORY;
captureListener->onScreenCaptureCompleted(captureResults);
- return;
+ return ftl::yield<renderengine::RenderEngineResult>({NO_ERROR, base::unique_fd()})
+ .share();
}
- status_t result = NO_ERROR;
+ std::shared_future<renderengine::RenderEngineResult> 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<renderengine::RenderEngineResult> captureScreenResultFuture =
+ ftl::chain(std::move(scheduleResultFuture))
+ .then([=](std::shared_future<renderengine::RenderEngineResult> 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<renderengine::RenderEngineResult> SurfaceFlinger::renderScreenImplLocked(
const RenderArea& renderArea, TraverseLayersFunction traverseLayers,
const std::shared_ptr<renderengine::ExternalTexture>& buffer,
bool canCaptureBlackoutContent, bool regionSampling, bool grayscale,
@@ -6256,7 +6286,8 @@
// the impetus on WindowManager to not persist them.
if (captureResults.capturedSecureLayers && !canCaptureBlackoutContent) {
ALOGW("FB is protected: PERMISSION_DENIED");
- return PERMISSION_DENIED;
+ return ftl::yield<renderengine::RenderEngineResult>({PERMISSION_DENIED, base::unique_fd()})
+ .share();
}
captureResults.buffer = buffer->getBuffer();
@@ -6338,11 +6369,12 @@
});
- std::vector<const renderengine::LayerSettings*> clientCompositionLayerPointers(
- clientCompositionLayers.size());
+ std::vector<renderengine::LayerSettings> clientRenderEngineLayers;
+ clientRenderEngineLayers.reserve(clientCompositionLayers.size());
std::transform(clientCompositionLayers.begin(), clientCompositionLayers.end(),
- clientCompositionLayerPointers.begin(),
- std::pointer_traits<renderengine::LayerSettings*>::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 @@
getRenderEngine().useProtectedContext(useProtected);
const constexpr bool kUseFramebufferCache = false;
- auto [status, drawFence] =
- getRenderEngine()
- .drawLayers(clientCompositionDisplay, clientCompositionLayerPointers, buffer,
- kUseFramebufferCache, std::move(bufferFence))
- .get();
+ std::future<renderengine::RenderEngineResult> drawLayersResult =
+ getRenderEngine().drawLayers(clientCompositionDisplay, clientRenderEngineLayers, buffer,
+ kUseFramebufferCache, std::move(bufferFence));
- if (drawFence >= 0) {
- sp<Fence> releaseFence = new Fence(dup(drawFence));
- for (auto* layer : renderedLayers) {
- layer->onLayerDisplayed(releaseFence);
- }
+ std::shared_future<renderengine::RenderEngineResult> 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 1f0e42d..45fd94e 100644
--- a/services/surfaceflinger/SurfaceFlinger.h
+++ b/services/surfaceflinger/SurfaceFlinger.h
@@ -906,17 +906,17 @@
// 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<IScreenCaptureListener>&);
- status_t captureScreenCommon(RenderAreaFuture, TraverseLayersFunction,
- const std::shared_ptr<renderengine::ExternalTexture>&,
- bool regionSampling, bool grayscale,
- const sp<IScreenCaptureListener>&);
- status_t renderScreenImplLocked(const RenderArea&, TraverseLayersFunction,
- const std::shared_ptr<renderengine::ExternalTexture>&,
- bool canCaptureBlackoutContent, bool regionSampling,
- bool grayscale, ScreenCaptureResults&);
+ std::shared_future<renderengine::RenderEngineResult> captureScreenCommon(
+ RenderAreaFuture, TraverseLayersFunction, ui::Size bufferSize, ui::PixelFormat,
+ bool allowProtected, bool grayscale, const sp<IScreenCaptureListener>&);
+ std::shared_future<renderengine::RenderEngineResult> captureScreenCommon(
+ RenderAreaFuture, TraverseLayersFunction,
+ const std::shared_ptr<renderengine::ExternalTexture>&, bool regionSampling,
+ bool grayscale, const sp<IScreenCaptureListener>&);
+ std::shared_future<renderengine::RenderEngineResult> renderScreenImplLocked(
+ const RenderArea&, TraverseLayersFunction,
+ const std::shared_ptr<renderengine::ExternalTexture>&, 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 c1eb896..8fbf0b4 100644
--- a/services/surfaceflinger/TransactionCallbackInvoker.cpp
+++ b/services/surfaceflinger/TransactionCallbackInvoker.cpp
@@ -154,6 +154,38 @@
// destroyed the client side is dead and there won't be anyone to send the callback to.
sp<IBinder> surfaceControl = handle->surfaceControl.promote();
if (surfaceControl) {
+ sp<Fence> prevFence = nullptr;
+
+ for (const auto& futureStruct : handle->previousReleaseFences) {
+ sp<Fence> currentFence = sp<Fence>::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<Fence> 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 7e879e1..100dbfa 100644
--- a/services/surfaceflinger/TransactionCallbackInvoker.h
+++ b/services/surfaceflinger/TransactionCallbackInvoker.h
@@ -18,8 +18,9 @@
#include <condition_variable>
#include <deque>
-#include <queue>
+#include <future>
#include <mutex>
+#include <queue>
#include <thread>
#include <unordered_map>
#include <unordered_set>
@@ -28,6 +29,7 @@
#include <binder/IBinder.h>
#include <gui/ITransactionCompletedListener.h>
+#include <renderengine/RenderEngine.h>
#include <ui/Fence.h>
namespace android {
@@ -42,7 +44,9 @@
wp<IBinder> surfaceControl;
bool releasePreviousBuffer = false;
+ std::string name;
sp<Fence> previousReleaseFence;
+ std::vector<std::shared_future<renderengine::RenderEngineResult>> 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 5135ff9..61c7c39 100644
--- a/services/surfaceflinger/tests/unittests/CompositionTest.cpp
+++ b/services/surfaceflinger/tests/unittests/CompositionTest.cpp
@@ -247,10 +247,16 @@
"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 @@
static void setupCommonScreensCaptureCallExpectations(CompositionTest* test) {
EXPECT_CALL(*test->mRenderEngine, drawLayers)
.WillRepeatedly([&](const renderengine::DisplaySettings& displaySettings,
- const std::vector<const renderengine::LayerSettings*>&,
+ const std::vector<renderengine::LayerSettings>&,
const std::shared_ptr<renderengine::ExternalTexture>&,
- const bool, base::unique_fd &&)
+ const bool, base::unique_fd&&)
-> std::future<renderengine::RenderEngineResult> {
EXPECT_EQ(DEFAULT_DISPLAY_MAX_LUMINANCE, displaySettings.maxLuminance);
EXPECT_EQ(Rect(DEFAULT_DISPLAY_WIDTH, DEFAULT_DISPLAY_HEIGHT),
@@ -397,9 +403,9 @@
Return(0)));
EXPECT_CALL(*test->mRenderEngine, drawLayers)
.WillRepeatedly([&](const renderengine::DisplaySettings& displaySettings,
- const std::vector<const renderengine::LayerSettings*>&,
+ const std::vector<renderengine::LayerSettings>&,
const std::shared_ptr<renderengine::ExternalTexture>&,
- const bool, base::unique_fd &&)
+ const bool, base::unique_fd&&)
-> std::future<renderengine::RenderEngineResult> {
EXPECT_EQ(DEFAULT_DISPLAY_MAX_LUMINANCE, displaySettings.maxLuminance);
EXPECT_EQ(Rect(DEFAULT_DISPLAY_WIDTH, DEFAULT_DISPLAY_HEIGHT),
@@ -633,9 +639,9 @@
static void setupREBufferCompositionCommonCallExpectations(CompositionTest* test) {
EXPECT_CALL(*test->mRenderEngine, drawLayers)
.WillOnce([&](const renderengine::DisplaySettings& displaySettings,
- const std::vector<const renderengine::LayerSettings*>& layerSettings,
+ const std::vector<renderengine::LayerSettings>& layerSettings,
const std::shared_ptr<renderengine::ExternalTexture>&, const bool,
- base::unique_fd &&) -> std::future<renderengine::RenderEngineResult> {
+ base::unique_fd&&) -> std::future<renderengine::RenderEngineResult> {
EXPECT_EQ(DEFAULT_DISPLAY_MAX_LUMINANCE, displaySettings.maxLuminance);
EXPECT_EQ(Rect(DEFAULT_DISPLAY_WIDTH, DEFAULT_DISPLAY_HEIGHT),
displaySettings.physicalDisplay);
@@ -652,16 +658,16 @@
"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 @@
static void setupREColorCompositionCallExpectations(CompositionTest* test) {
EXPECT_CALL(*test->mRenderEngine, drawLayers)
.WillOnce([&](const renderengine::DisplaySettings& displaySettings,
- const std::vector<const renderengine::LayerSettings*>& layerSettings,
+ const std::vector<renderengine::LayerSettings>& layerSettings,
const std::shared_ptr<renderengine::ExternalTexture>&, const bool,
- base::unique_fd &&) -> std::future<renderengine::RenderEngineResult> {
+ base::unique_fd&&) -> std::future<renderengine::RenderEngineResult> {
EXPECT_EQ(DEFAULT_DISPLAY_MAX_LUMINANCE, displaySettings.maxLuminance);
EXPECT_EQ(Rect(DEFAULT_DISPLAY_WIDTH, DEFAULT_DISPLAY_HEIGHT),
displaySettings.physicalDisplay);
@@ -704,14 +710,14 @@
"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 @@
static void setupInsecureREBufferCompositionCommonCallExpectations(CompositionTest* test) {
EXPECT_CALL(*test->mRenderEngine, drawLayers)
.WillOnce([&](const renderengine::DisplaySettings& displaySettings,
- const std::vector<const renderengine::LayerSettings*>& layerSettings,
+ const std::vector<renderengine::LayerSettings>& layerSettings,
const std::shared_ptr<renderengine::ExternalTexture>&, const bool,
- base::unique_fd &&) -> std::future<renderengine::RenderEngineResult> {
+ base::unique_fd&&) -> std::future<renderengine::RenderEngineResult> {
EXPECT_EQ(DEFAULT_DISPLAY_MAX_LUMINANCE, displaySettings.maxLuminance);
EXPECT_EQ(Rect(DEFAULT_DISPLAY_WIDTH, DEFAULT_DISPLAY_HEIGHT),
displaySettings.physicalDisplay);
@@ -784,12 +790,12 @@
"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;
});
}