diff options
| author | 2023-02-09 14:55:57 +0000 | |
|---|---|---|
| committer | 2023-02-10 14:17:39 +0000 | |
| commit | 545da0e1040dabe238140c2ccdced5b3d60b0366 (patch) | |
| tree | 9df7679ed2d0b9226d897eee59543ea81f6d2b91 | |
| parent | 858a6a88062131547db91e341fc4c3cde4bc54a4 (diff) | |
Some fixes to TrustedPresentationListener
1. Ignore display overlays since we don't want screen decorations
included in the occlusion
2. Handle occluded region as separate Rects to ensure that disconnected
Rects in a Region are not considered occluding in the disconnected
area.
Test: LayerTrustedPresentationListenerTest
Bug: 256993331
Change-Id: Ib0a4b850e2aafb42e206b8728fcc9b6013171f3f
8 files changed, 110 insertions, 13 deletions
diff --git a/services/surfaceflinger/CompositionEngine/include/compositionengine/CompositionRefreshArgs.h b/services/surfaceflinger/CompositionEngine/include/compositionengine/CompositionRefreshArgs.h index 4777f13598..a8322d8572 100644 --- a/services/surfaceflinger/CompositionEngine/include/compositionengine/CompositionRefreshArgs.h +++ b/services/surfaceflinger/CompositionEngine/include/compositionengine/CompositionRefreshArgs.h @@ -97,6 +97,8 @@ struct CompositionRefreshArgs { std::optional<std::chrono::steady_clock::time_point> scheduledFrameTime; std::vector<BorderRenderInfo> borderInfoList; + + bool hasTrustedPresentationListener = false; }; } // namespace android::compositionengine diff --git a/services/surfaceflinger/CompositionEngine/include/compositionengine/LayerFECompositionState.h b/services/surfaceflinger/CompositionEngine/include/compositionengine/LayerFECompositionState.h index 5bb249719e..32684fc3b7 100644 --- a/services/surfaceflinger/CompositionEngine/include/compositionengine/LayerFECompositionState.h +++ b/services/surfaceflinger/CompositionEngine/include/compositionengine/LayerFECompositionState.h @@ -212,6 +212,8 @@ struct LayerFECompositionState { float currentSdrHdrRatio = 1.f; float desiredSdrHdrRatio = 1.f; + bool isInternalDisplayOverlay = false; + virtual ~LayerFECompositionState(); // Debugging diff --git a/services/surfaceflinger/CompositionEngine/include/compositionengine/Output.h b/services/surfaceflinger/CompositionEngine/include/compositionengine/Output.h index 52ebd9ebec..a3d86398cf 100644 --- a/services/surfaceflinger/CompositionEngine/include/compositionengine/Output.h +++ b/services/surfaceflinger/CompositionEngine/include/compositionengine/Output.h @@ -153,6 +153,10 @@ public: Region aboveOpaqueLayers; // The region of the output which should be considered dirty Region dirtyRegion; + // The region of the output which is covered by layers, excluding display overlays. This + // only has a value if there's something needing it, like when a TrustedPresentationListener + // is set + std::optional<Region> aboveCoveredLayersExcludingOverlays; }; virtual ~Output(); diff --git a/services/surfaceflinger/CompositionEngine/include/compositionengine/impl/OutputLayerCompositionState.h b/services/surfaceflinger/CompositionEngine/include/compositionengine/impl/OutputLayerCompositionState.h index b86782f417..7b0af3a248 100644 --- a/services/surfaceflinger/CompositionEngine/include/compositionengine/impl/OutputLayerCompositionState.h +++ b/services/surfaceflinger/CompositionEngine/include/compositionengine/impl/OutputLayerCompositionState.h @@ -63,9 +63,15 @@ struct OutputLayerCompositionState { // The portion of the layer that is not obscured and is also opaque Region visibleNonTransparentRegion; - // The portion of the layer that is obscured by opaque layers on top + // The portion of the layer that is obscured by all layers on top. This includes transparent and + // opaque. Region coveredRegion; + // The portion of the layer that is obscured by all layers on top excluding display overlays. + // This only has a value if there's something needing it, like when a + // TrustedPresentationListener is set. + std::optional<Region> coveredRegionExcludingDisplayOverlays; + // The visibleRegion transformed to output space Region outputSpaceVisibleRegion; diff --git a/services/surfaceflinger/CompositionEngine/src/Output.cpp b/services/surfaceflinger/CompositionEngine/src/Output.cpp index 403385ea8c..7d9431605d 100644 --- a/services/surfaceflinger/CompositionEngine/src/Output.cpp +++ b/services/surfaceflinger/CompositionEngine/src/Output.cpp @@ -31,6 +31,7 @@ #include <ftl/future.h> #include <gui/TraceUtils.h> +#include <optional> #include <thread> #include "renderengine/ExternalTexture.h" @@ -480,6 +481,9 @@ void Output::rebuildLayerStacks(const compositionengine::CompositionRefreshArgs& // Process the layers to determine visibility and coverage compositionengine::Output::CoverageState coverage{layerFESet}; + coverage.aboveCoveredLayersExcludingOverlays = refreshArgs.hasTrustedPresentationListener + ? std::make_optional<Region>() + : std::nullopt; collectVisibleLayers(refreshArgs, coverage); // Compute the resulting coverage for this output, and store it for later @@ -534,6 +538,9 @@ void Output::ensureOutputLayerIfVisible(sp<compositionengine::LayerFE>& layerFE, return; } + bool computeAboveCoveredExcludingOverlays = + coverage.aboveCoveredLayersExcludingOverlays && !layerFEState->isInternalDisplayOverlay; + /* * opaqueRegion: area of a surface that is fully opaque. */ @@ -575,6 +582,11 @@ void Output::ensureOutputLayerIfVisible(sp<compositionengine::LayerFE>& layerFE, */ Region shadowRegion; + /** + * covered region above excluding internal display overlay layers + */ + std::optional<Region> coveredRegionExcludingDisplayOverlays = std::nullopt; + const ui::Transform& tr = layerFEState->geomLayerTransform; // Get the visible region @@ -647,6 +659,12 @@ void Output::ensureOutputLayerIfVisible(sp<compositionengine::LayerFE>& layerFE, // Update accumAboveCoveredLayers for next (lower) layer coverage.aboveCoveredLayers.orSelf(visibleRegion); + if (CC_UNLIKELY(computeAboveCoveredExcludingOverlays)) { + coveredRegionExcludingDisplayOverlays = + coverage.aboveCoveredLayersExcludingOverlays->intersect(visibleRegion); + coverage.aboveCoveredLayersExcludingOverlays->orSelf(visibleRegion); + } + // subtract the opaque region covered by the layers above us visibleRegion.subtractSelf(coverage.aboveOpaqueLayers); @@ -733,6 +751,10 @@ void Output::ensureOutputLayerIfVisible(sp<compositionengine::LayerFE>& layerFE, ? outputState.transform.transform( transparentRegion.intersect(outputState.layerStackSpace.getContent())) : Region(); + if (CC_UNLIKELY(computeAboveCoveredExcludingOverlays)) { + outputLayerState.coveredRegionExcludingDisplayOverlays = + std::move(coveredRegionExcludingDisplayOverlays); + } } void Output::setReleasedLayers(const compositionengine::CompositionRefreshArgs&) { diff --git a/services/surfaceflinger/Layer.cpp b/services/surfaceflinger/Layer.cpp index 66c2fb658f..0a27bddb58 100644 --- a/services/surfaceflinger/Layer.cpp +++ b/services/surfaceflinger/Layer.cpp @@ -395,14 +395,22 @@ void Layer::updateTrustedPresentationState(const DisplayDevice* display, if (!leaveState) { const auto outputLayer = findOutputLayerForDisplay(display); - if (outputLayer != nullptr && snapshot != nullptr) { - mLastComputedTrustedPresentationState = - computeTrustedPresentationState(snapshot->geomLayerBounds, - snapshot->sourceBounds(), - outputLayer->getState().coveredRegion, - snapshot->transformedBounds, snapshot->alpha, - snapshot->geomLayerTransform, - mTrustedPresentationThresholds); + if (outputLayer != nullptr) { + if (outputLayer->getState().coveredRegionExcludingDisplayOverlays) { + Region coveredRegion = + *outputLayer->getState().coveredRegionExcludingDisplayOverlays; + mLastComputedTrustedPresentationState = + computeTrustedPresentationState(snapshot->geomLayerBounds, + snapshot->sourceBounds(), coveredRegion, + snapshot->transformedBounds, + snapshot->alpha, + snapshot->geomLayerTransform, + mTrustedPresentationThresholds); + } else { + ALOGE("CoveredRegionExcludingDisplayOverlays was not set for %s. Don't compute " + "TrustedPresentationState", + getDebugName()); + } } } const bool newState = mLastComputedTrustedPresentationState; @@ -459,10 +467,15 @@ bool Layer::computeTrustedPresentationState(const FloatRect& bounds, const Float float boundsOverSourceH = bounds.getHeight() / (float)sourceBounds.getHeight(); fractionRendered *= boundsOverSourceW * boundsOverSourceH; - Rect coveredBounds = coveredRegion.bounds(); - fractionRendered *= (1 - - ((coveredBounds.width() / (float)screenBounds.getWidth()) * - coveredBounds.height() / (float)screenBounds.getHeight())); + Region tJunctionFreeRegion = Region::createTJunctionFreeRegion(coveredRegion); + // Compute the size of all the rects since they may be disconnected. + float coveredSize = 0; + for (auto rect = tJunctionFreeRegion.begin(); rect < tJunctionFreeRegion.end(); rect++) { + float size = rect->width() * rect->height(); + coveredSize += size; + } + + fractionRendered *= (1 - (coveredSize / (screenBounds.getWidth() * screenBounds.getHeight()))); if (fractionRendered < thresholds.minFractionRendered) { return false; @@ -3996,6 +4009,7 @@ void Layer::updateSnapshot(bool updateGeometry) { snapshot->bufferSize = getBufferSize(mDrawingState); snapshot->externalTexture = mBufferInfo.mBuffer; snapshot->hasReadyFrame = hasReadyFrame(); + snapshot->isInternalDisplayOverlay = isInternalDisplayOverlay(); preparePerFrameCompositionState(); } diff --git a/services/surfaceflinger/SurfaceFlinger.cpp b/services/surfaceflinger/SurfaceFlinger.cpp index 68ab776400..39b942c3cb 100644 --- a/services/surfaceflinger/SurfaceFlinger.cpp +++ b/services/surfaceflinger/SurfaceFlinger.cpp @@ -2511,6 +2511,7 @@ void SurfaceFlinger::composite(TimePoint frameTime, VsyncId vsyncId) refreshArgs.previousPresentFence = mPreviousPresentFences[0].fenceTime; refreshArgs.scheduledFrameTime = mScheduler->getScheduledFrameTime(); refreshArgs.expectedPresentTime = mExpectedPresentTime.ns(); + refreshArgs.hasTrustedPresentationListener = mNumTrustedPresentationListeners > 0; // Store the present time just before calling to the composition engine so we could notify // the scheduler. diff --git a/services/surfaceflinger/tests/LayerTrustedPresentationListener_test.cpp b/services/surfaceflinger/tests/LayerTrustedPresentationListener_test.cpp index a843fd17b1..2be8d3b013 100644 --- a/services/surfaceflinger/tests/LayerTrustedPresentationListener_test.cpp +++ b/services/surfaceflinger/tests/LayerTrustedPresentationListener_test.cpp @@ -238,4 +238,50 @@ TEST_F(LayerTrustedPresentationListenerTest, obscuring_with_alpha) { EXPECT_TRUE(pch.awaitCallback()); } +TEST_F(LayerTrustedPresentationListenerTest, obscuring_with_display_overlay) { + auto otherLayer = makeLayer(); + t.show(otherLayer) + .setPosition(otherLayer, 100, 100) + .setLayer(otherLayer, INT32_MAX) + .setFlags(otherLayer, layer_state_t::eLayerSkipScreenshot, + layer_state_t::eLayerSkipScreenshot) + .setLayer(mainLayer, INT32_MAX - 1) + .show(mainLayer) + .setPosition(mainLayer, 100, 100) + .setTrustedPresentationCallback( + mainLayer, + [&](void* context, bool state) { + PresentationCallbackHelper* helper = (PresentationCallbackHelper*)context; + helper->callbackArrived(state); + }, + thresholds, &pch, mCallback) + .apply(); + EXPECT_TRUE(pch.awaitCallback()); +} + +TEST_F(LayerTrustedPresentationListenerTest, obscuring_with_non_overlapping_bounds) { + thresholds.minFractionRendered = 0.5; + auto otherLayer1 = makeLayer(); + auto otherLayer2 = makeLayer(); + t.show(otherLayer1) + .show(otherLayer2) + .setPosition(otherLayer1, 100, 25) + .setLayer(otherLayer1, INT32_MAX) + .setPosition(otherLayer2, 100, 175) + .setLayer(otherLayer2, INT32_MAX) + .setLayer(mainLayer, INT32_MAX - 1) + .show(mainLayer) + .setPosition(mainLayer, 100, 100) + .setTrustedPresentationCallback( + mainLayer, + [&](void* context, bool state) { + PresentationCallbackHelper* helper = (PresentationCallbackHelper*)context; + helper->callbackArrived(state); + }, + thresholds, &pch, mCallback) + .apply(); + + EXPECT_TRUE(pch.awaitCallback()); +} + } // namespace android |