[sf] Avoid rounded corners without EGL_EXT_protected_content with new frontend
Override the rounded corner state in the layer snapshots if the device
doesn't support EGL_EXT_protected_content. This is passed in via a new
arg to LayerSnapshotBuilder.
Test: libsurfaceflinger_unittest
Fixes: 196271643
Change-Id: I8cbe6ea2818305c93494177df239381b0d02b464
diff --git a/services/surfaceflinger/FrontEnd/LayerSnapshotBuilder.cpp b/services/surfaceflinger/FrontEnd/LayerSnapshotBuilder.cpp
index 23cfe928..f7b685d 100644
--- a/services/surfaceflinger/FrontEnd/LayerSnapshotBuilder.cpp
+++ b/services/surfaceflinger/FrontEnd/LayerSnapshotBuilder.cpp
@@ -854,8 +854,9 @@
}
if (forceUpdate || snapshot.clientChanges & layer_state_t::eCornerRadiusChanged ||
- snapshot.changes.any(RequestedLayerState::Changes::Geometry)) {
- updateRoundedCorner(snapshot, requested, parentSnapshot);
+ snapshot.changes.any(RequestedLayerState::Changes::Geometry |
+ RequestedLayerState::Changes::BufferUsageFlags)) {
+ updateRoundedCorner(snapshot, requested, parentSnapshot, args);
}
if (forceUpdate || snapshot.clientChanges & layer_state_t::eShadowRadiusChanged ||
@@ -886,7 +887,12 @@
void LayerSnapshotBuilder::updateRoundedCorner(LayerSnapshot& snapshot,
const RequestedLayerState& requested,
- const LayerSnapshot& parentSnapshot) {
+ const LayerSnapshot& parentSnapshot,
+ const Args& args) {
+ if (args.skipRoundCornersWhenProtected && requested.isProtected()) {
+ snapshot.roundedCorner = RoundedCornerState();
+ return;
+ }
snapshot.roundedCorner = RoundedCornerState();
RoundedCornerState parentRoundedCorner;
if (parentSnapshot.roundedCorner.hasRoundedCorners()) {
diff --git a/services/surfaceflinger/FrontEnd/LayerSnapshotBuilder.h b/services/surfaceflinger/FrontEnd/LayerSnapshotBuilder.h
index d361605..3d64b36 100644
--- a/services/surfaceflinger/FrontEnd/LayerSnapshotBuilder.h
+++ b/services/surfaceflinger/FrontEnd/LayerSnapshotBuilder.h
@@ -54,6 +54,7 @@
std::unordered_set<uint32_t> excludeLayerIds;
const std::unordered_map<std::string, bool>& supportedLayerGenericMetadata;
const std::unordered_map<std::string, uint32_t>& genericLayerMetadataKeyMap;
+ bool skipRoundCornersWhenProtected = false;
};
LayerSnapshotBuilder();
@@ -103,7 +104,7 @@
bool parentIsRelative, const Args& args);
static void resetRelativeState(LayerSnapshot& snapshot);
static void updateRoundedCorner(LayerSnapshot& snapshot, const RequestedLayerState& layerState,
- const LayerSnapshot& parentSnapshot);
+ const LayerSnapshot& parentSnapshot, const Args& args);
void updateLayerBounds(LayerSnapshot& snapshot, const RequestedLayerState& layerState,
const LayerSnapshot& parentSnapshot, uint32_t displayRotationFlags);
static void updateShadows(LayerSnapshot& snapshot, const RequestedLayerState& requested,
diff --git a/services/surfaceflinger/FrontEnd/RequestedLayerState.cpp b/services/surfaceflinger/FrontEnd/RequestedLayerState.cpp
index a4777d1..d979c46 100644
--- a/services/surfaceflinger/FrontEnd/RequestedLayerState.cpp
+++ b/services/surfaceflinger/FrontEnd/RequestedLayerState.cpp
@@ -147,6 +147,8 @@
const ui::Size oldBufferSize = hadBuffer
? ui::Size(externalTexture->getWidth(), externalTexture->getHeight())
: ui::Size();
+ const uint64_t oldUsageFlags = hadBuffer ? externalTexture->getUsage() : 0;
+
const bool hadSideStream = sidebandStream != nullptr;
const layer_state_t& clientState = resolvedComposerState.state;
const bool hadBlur = hasBlur();
@@ -177,6 +179,10 @@
changes |= RequestedLayerState::Changes::BufferSize;
changes |= RequestedLayerState::Changes::Geometry;
}
+ const uint64_t usageFlags = hasBuffer ? externalTexture->getUsage() : 0;
+ if (oldUsageFlags != usageFlags) {
+ changes |= RequestedLayerState::Changes::BufferUsageFlags;
+ }
}
if (hasBuffer != hadBuffer) {
@@ -570,6 +576,10 @@
return true;
}
+bool RequestedLayerState::isProtected() const {
+ return externalTexture && externalTexture->getUsage() & GRALLOC_USAGE_PROTECTED;
+}
+
void RequestedLayerState::clearChanges() {
what = 0;
changes.clear();
diff --git a/services/surfaceflinger/FrontEnd/RequestedLayerState.h b/services/surfaceflinger/FrontEnd/RequestedLayerState.h
index 1c19d6d..0309302 100644
--- a/services/surfaceflinger/FrontEnd/RequestedLayerState.h
+++ b/services/surfaceflinger/FrontEnd/RequestedLayerState.h
@@ -56,6 +56,7 @@
Animation = 1u << 17,
BufferSize = 1u << 18,
GameMode = 1u << 19,
+ BufferUsageFlags = 1u << 20,
};
static Rect reduce(const Rect& win, const Region& exclude);
RequestedLayerState(const LayerCreationArgs&);
@@ -85,6 +86,7 @@
bool willReleaseBufferOnLatch() const;
bool backpressureEnabled() const;
bool isSimpleBufferUpdate(const layer_state_t&) const;
+ bool isProtected() const;
// Layer serial number. This gives layers an explicit ordering, so we
// have a stable sort order when their layer stack and Z-order are
diff --git a/services/surfaceflinger/SurfaceFlinger.cpp b/services/surfaceflinger/SurfaceFlinger.cpp
index 9de623f..bcce2a6 100644
--- a/services/surfaceflinger/SurfaceFlinger.cpp
+++ b/services/surfaceflinger/SurfaceFlinger.cpp
@@ -2315,7 +2315,9 @@
.forceFullDamage = mForceFullDamage,
.supportedLayerGenericMetadata =
getHwComposer().getSupportedLayerGenericMetadata(),
- .genericLayerMetadataKeyMap = getGenericLayerMetadataKeyMap()};
+ .genericLayerMetadataKeyMap = getGenericLayerMetadataKeyMap(),
+ .skipRoundCornersWhenProtected =
+ !getRenderEngine().supportsProtectedContent()};
mLayerSnapshotBuilder.update(args);
}
@@ -8547,7 +8549,9 @@
.excludeLayerIds = std::move(excludeLayerIds),
.supportedLayerGenericMetadata =
getHwComposer().getSupportedLayerGenericMetadata(),
- .genericLayerMetadataKeyMap = getGenericLayerMetadataKeyMap()};
+ .genericLayerMetadataKeyMap = getGenericLayerMetadataKeyMap(),
+ .skipRoundCornersWhenProtected =
+ !getRenderEngine().supportsProtectedContent()};
mLayerSnapshotBuilder.update(args);
auto getLayerSnapshotsFn =
@@ -8582,7 +8586,9 @@
.excludeLayerIds = std::move(excludeLayerIds),
.supportedLayerGenericMetadata =
getHwComposer().getSupportedLayerGenericMetadata(),
- .genericLayerMetadataKeyMap = getGenericLayerMetadataKeyMap()};
+ .genericLayerMetadataKeyMap = getGenericLayerMetadataKeyMap(),
+ .skipRoundCornersWhenProtected =
+ !getRenderEngine().supportsProtectedContent()};
mLayerSnapshotBuilder.update(args);
auto getLayerSnapshotsFn =
diff --git a/services/surfaceflinger/tests/unittests/LayerHierarchyTest.h b/services/surfaceflinger/tests/unittests/LayerHierarchyTest.h
index e475b84..1380555 100644
--- a/services/surfaceflinger/tests/unittests/LayerHierarchyTest.h
+++ b/services/surfaceflinger/tests/unittests/LayerHierarchyTest.h
@@ -17,6 +17,8 @@
#include <gmock/gmock.h>
#include <gtest/gtest.h>
+#include <gui/fake/BufferData.h>
+
#include "Client.h" // temporarily needed for LayerCreationArgs
#include "FrontEnd/LayerCreationArgs.h"
#include "FrontEnd/LayerHierarchy.h"
@@ -333,6 +335,32 @@
mLifecycleManager.applyTransactions(transactions);
}
+ void setRoundedCorners(uint32_t id, float radius) {
+ std::vector<TransactionState> transactions;
+ transactions.emplace_back();
+ transactions.back().states.push_back({});
+
+ transactions.back().states.front().state.what = layer_state_t::eCornerRadiusChanged;
+ transactions.back().states.front().layerId = id;
+ transactions.back().states.front().state.cornerRadius = radius;
+ mLifecycleManager.applyTransactions(transactions);
+ }
+
+ void setBuffer(uint32_t id, std::shared_ptr<renderengine::ExternalTexture> texture) {
+ std::vector<TransactionState> transactions;
+ transactions.emplace_back();
+ transactions.back().states.push_back({});
+
+ transactions.back().states.front().state.what = layer_state_t::eBufferChanged;
+ transactions.back().states.front().layerId = id;
+ transactions.back().states.front().externalTexture = texture;
+ transactions.back().states.front().state.bufferData =
+ std::make_shared<fake::BufferData>(texture->getId(), texture->getWidth(),
+ texture->getHeight(), texture->getPixelFormat(),
+ texture->getUsage());
+ mLifecycleManager.applyTransactions(transactions);
+ }
+
LayerLifecycleManager mLifecycleManager;
};
diff --git a/services/surfaceflinger/tests/unittests/LayerSnapshotTest.cpp b/services/surfaceflinger/tests/unittests/LayerSnapshotTest.cpp
index a581d5b..65bac00 100644
--- a/services/surfaceflinger/tests/unittests/LayerSnapshotTest.cpp
+++ b/services/surfaceflinger/tests/unittests/LayerSnapshotTest.cpp
@@ -17,6 +17,8 @@
#include <gmock/gmock.h>
#include <gtest/gtest.h>
+#include <renderengine/mock/FakeExternalTexture.h>
+
#include "FrontEnd/LayerHierarchy.h"
#include "FrontEnd/LayerLifecycleManager.h"
#include "FrontEnd/LayerSnapshotBuilder.h"
@@ -68,12 +70,17 @@
setColor(id);
}
- void updateAndVerify(LayerSnapshotBuilder& actualBuilder, bool hasDisplayChanges,
- const std::vector<uint32_t> expectedVisibleLayerIdsInZOrder) {
+ void update(LayerSnapshotBuilder& actualBuilder, LayerSnapshotBuilder::Args& args) {
if (mLifecycleManager.getGlobalChanges().test(RequestedLayerState::Changes::Hierarchy)) {
mHierarchyBuilder.update(mLifecycleManager.getLayers(),
mLifecycleManager.getDestroyedLayers());
}
+ args.root = mHierarchyBuilder.getHierarchy();
+ actualBuilder.update(args);
+ }
+
+ void updateAndVerify(LayerSnapshotBuilder& actualBuilder, bool hasDisplayChanges,
+ const std::vector<uint32_t> expectedVisibleLayerIdsInZOrder) {
LayerSnapshotBuilder::Args args{.root = mHierarchyBuilder.getHierarchy(),
.layerLifecycleManager = mLifecycleManager,
.includeMetadata = false,
@@ -83,7 +90,7 @@
.supportsBlur = true,
.supportedLayerGenericMetadata = {},
.genericLayerMetadataKeyMap = {}};
- actualBuilder.update(args);
+ update(actualBuilder, args);
// rebuild layer snapshots from scratch and verify that it matches the updated state.
LayerSnapshotBuilder expectedBuilder(args);
@@ -596,4 +603,50 @@
scheduler::LayerInfo::FrameRateCompatibility::Default);
}
+TEST_F(LayerSnapshotTest, skipRoundCornersWhenProtected) {
+ setRoundedCorners(1, 42.f);
+ setRoundedCorners(2, 42.f);
+ setCrop(1, Rect{1000, 1000});
+ setCrop(2, Rect{1000, 1000});
+
+ UPDATE_AND_VERIFY(mSnapshotBuilder, STARTING_ZORDER);
+ EXPECT_TRUE(getSnapshot({.id = 1})->roundedCorner.hasRoundedCorners());
+ EXPECT_EQ(getSnapshot({.id = 1})->roundedCorner.radius.x, 42.f);
+ EXPECT_TRUE(getSnapshot({.id = 2})->roundedCorner.hasRoundedCorners());
+
+ // add a buffer with the protected bit, check rounded corners are not set when
+ // skipRoundCornersWhenProtected == true
+ setBuffer(1,
+ std::make_shared<
+ renderengine::mock::FakeExternalTexture>(1U /*width*/, 1U /*height*/,
+ 1ULL /* bufferId */,
+ HAL_PIXEL_FORMAT_RGBA_8888,
+ GRALLOC_USAGE_PROTECTED /*usage*/));
+
+ LayerSnapshotBuilder::Args args{.root = mHierarchyBuilder.getHierarchy(),
+ .layerLifecycleManager = mLifecycleManager,
+ .includeMetadata = false,
+ .displays = mFrontEndDisplayInfos,
+ .displayChanges = false,
+ .globalShadowSettings = globalShadowSettings,
+ .supportsBlur = true,
+ .supportedLayerGenericMetadata = {},
+ .genericLayerMetadataKeyMap = {},
+ .skipRoundCornersWhenProtected = true};
+ update(mSnapshotBuilder, args);
+ EXPECT_FALSE(getSnapshot({.id = 1})->roundedCorner.hasRoundedCorners());
+ // layer 2 doesn't have a buffer and should be unaffected
+ EXPECT_TRUE(getSnapshot({.id = 2})->roundedCorner.hasRoundedCorners());
+
+ // remove protected bit, check rounded corners are set
+ setBuffer(1,
+ std::make_shared<renderengine::mock::FakeExternalTexture>(1U /*width*/, 1U /*height*/,
+ 2ULL /* bufferId */,
+ HAL_PIXEL_FORMAT_RGBA_8888,
+ 0 /*usage*/));
+ update(mSnapshotBuilder, args);
+ EXPECT_TRUE(getSnapshot({.id = 1})->roundedCorner.hasRoundedCorners());
+ EXPECT_EQ(getSnapshot({.id = 1})->roundedCorner.radius.x, 42.f);
+}
+
} // namespace android::surfaceflinger::frontend