summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
author Chavi Weingarten <chaviw@google.com> 2023-02-09 14:55:57 +0000
committer Chavi Weingarten <chaviw@google.com> 2023-02-10 14:17:39 +0000
commit545da0e1040dabe238140c2ccdced5b3d60b0366 (patch)
tree9df7679ed2d0b9226d897eee59543ea81f6d2b91
parent858a6a88062131547db91e341fc4c3cde4bc54a4 (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
-rw-r--r--services/surfaceflinger/CompositionEngine/include/compositionengine/CompositionRefreshArgs.h2
-rw-r--r--services/surfaceflinger/CompositionEngine/include/compositionengine/LayerFECompositionState.h2
-rw-r--r--services/surfaceflinger/CompositionEngine/include/compositionengine/Output.h4
-rw-r--r--services/surfaceflinger/CompositionEngine/include/compositionengine/impl/OutputLayerCompositionState.h8
-rw-r--r--services/surfaceflinger/CompositionEngine/src/Output.cpp22
-rw-r--r--services/surfaceflinger/Layer.cpp38
-rw-r--r--services/surfaceflinger/SurfaceFlinger.cpp1
-rw-r--r--services/surfaceflinger/tests/LayerTrustedPresentationListener_test.cpp46
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