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/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);