summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
author Surbhi Kadam <surbhikadam@google.com> 2025-01-07 09:51:23 -0800
committer Android (Google) Code Review <android-gerrit@google.com> 2025-01-07 09:51:23 -0800
commit1926a933661dfbbfbcb6acdcbe8ce4b256d70a69 (patch)
tree9ceeeb9936ea689c5b1c736f58d74e2a354a7d8f
parent0ea3321806431e100e6784907711d6660dcaaebe (diff)
parent9674ffa1d161cd04b20789b4a960dfafc8cc140c (diff)
Merge "surfaceflinger: Add clientDrawnCornerRadius and clientDrawnShadowLength layer properties" into main
-rw-r--r--libs/gui/LayerState.cpp16
-rw-r--r--libs/gui/SurfaceComposerClient.cpp23
-rw-r--r--libs/gui/include/gui/LayerState.h14
-rw-r--r--libs/gui/include/gui/SurfaceComposerClient.h9
-rw-r--r--libs/ui/include/ui/ShadowSettings.h4
-rw-r--r--services/surfaceflinger/FrontEnd/LayerSnapshot.cpp8
-rw-r--r--services/surfaceflinger/FrontEnd/LayerSnapshot.h15
-rw-r--r--services/surfaceflinger/FrontEnd/LayerSnapshotBuilder.cpp28
-rw-r--r--services/surfaceflinger/FrontEnd/RequestedLayerState.cpp14
-rw-r--r--services/surfaceflinger/Layer.h5
-rw-r--r--services/surfaceflinger/tests/LayerTypeAndRenderTypeTransaction_test.cpp77
-rw-r--r--services/surfaceflinger/tests/common/LayerLifecycleManagerHelper.h23
-rw-r--r--services/surfaceflinger/tests/unittests/LayerSnapshotTest.cpp53
13 files changed, 267 insertions, 22 deletions
diff --git a/libs/gui/LayerState.cpp b/libs/gui/LayerState.cpp
index c1a03fcfea..44aac9bfae 100644
--- a/libs/gui/LayerState.cpp
+++ b/libs/gui/LayerState.cpp
@@ -66,6 +66,8 @@ layer_state_t::layer_state_t()
mask(0),
reserved(0),
cornerRadius(0.0f),
+ clientDrawnCornerRadius(0.0f),
+ clientDrawnShadowRadius(0.0f),
backgroundBlurRadius(0),
color(0),
bufferTransform(0),
@@ -140,6 +142,8 @@ status_t layer_state_t::write(Parcel& output) const
SAFE_PARCEL(output.write, colorTransform.asArray(), 16 * sizeof(float));
SAFE_PARCEL(output.writeFloat, cornerRadius);
+ SAFE_PARCEL(output.writeFloat, clientDrawnCornerRadius);
+ SAFE_PARCEL(output.writeFloat, clientDrawnShadowRadius);
SAFE_PARCEL(output.writeUint32, backgroundBlurRadius);
SAFE_PARCEL(output.writeParcelable, metadata);
SAFE_PARCEL(output.writeFloat, bgColor.r);
@@ -274,6 +278,8 @@ status_t layer_state_t::read(const Parcel& input)
SAFE_PARCEL(input.read, &colorTransform, 16 * sizeof(float));
SAFE_PARCEL(input.readFloat, &cornerRadius);
+ SAFE_PARCEL(input.readFloat, &clientDrawnCornerRadius);
+ SAFE_PARCEL(input.readFloat, &clientDrawnShadowRadius);
SAFE_PARCEL(input.readUint32, &backgroundBlurRadius);
SAFE_PARCEL(input.readParcelable, &metadata);
@@ -596,6 +602,14 @@ void layer_state_t::merge(const layer_state_t& other) {
what |= eCornerRadiusChanged;
cornerRadius = other.cornerRadius;
}
+ if (other.what & eClientDrawnCornerRadiusChanged) {
+ what |= eClientDrawnCornerRadiusChanged;
+ clientDrawnCornerRadius = other.clientDrawnCornerRadius;
+ }
+ if (other.what & eClientDrawnShadowsChanged) {
+ what |= eClientDrawnShadowsChanged;
+ clientDrawnShadowRadius = other.clientDrawnShadowRadius;
+ }
if (other.what & eBackgroundBlurRadiusChanged) {
what |= eBackgroundBlurRadiusChanged;
backgroundBlurRadius = other.backgroundBlurRadius;
@@ -809,6 +823,8 @@ uint64_t layer_state_t::diff(const layer_state_t& other) const {
}
CHECK_DIFF(diff, eLayerStackChanged, other, layerStack);
CHECK_DIFF(diff, eCornerRadiusChanged, other, cornerRadius);
+ CHECK_DIFF(diff, eClientDrawnCornerRadiusChanged, other, clientDrawnCornerRadius);
+ CHECK_DIFF(diff, eClientDrawnShadowsChanged, other, clientDrawnShadowRadius);
CHECK_DIFF(diff, eBackgroundBlurRadiusChanged, other, backgroundBlurRadius);
if (other.what & eBlurRegionsChanged) diff |= eBlurRegionsChanged;
if (other.what & eRelativeLayerChanged) {
diff --git a/libs/gui/SurfaceComposerClient.cpp b/libs/gui/SurfaceComposerClient.cpp
index cabde22c6d..2beeae0201 100644
--- a/libs/gui/SurfaceComposerClient.cpp
+++ b/libs/gui/SurfaceComposerClient.cpp
@@ -1695,6 +1695,29 @@ SurfaceComposerClient::Transaction& SurfaceComposerClient::Transaction::setCorne
return *this;
}
+SurfaceComposerClient::Transaction& SurfaceComposerClient::Transaction::setClientDrawnCornerRadius(
+ const sp<SurfaceControl>& sc, float clientDrawnCornerRadius) {
+ layer_state_t* s = getLayerState(sc);
+ if (!s) {
+ mStatus = BAD_INDEX;
+ return *this;
+ }
+ s->what |= layer_state_t::eClientDrawnCornerRadiusChanged;
+ s->clientDrawnCornerRadius = clientDrawnCornerRadius;
+ return *this;
+}
+
+SurfaceComposerClient::Transaction& SurfaceComposerClient::Transaction::setClientDrawnShadowRadius(
+ const sp<SurfaceControl>& sc, float clientDrawnShadowRadius) {
+ layer_state_t* s = getLayerState(sc);
+ if (!s) {
+ mStatus = BAD_INDEX;
+ return *this;
+ }
+ s->what |= layer_state_t::eClientDrawnShadowsChanged;
+ s->clientDrawnShadowRadius = clientDrawnShadowRadius;
+ return *this;
+}
SurfaceComposerClient::Transaction& SurfaceComposerClient::Transaction::setBackgroundBlurRadius(
const sp<SurfaceControl>& sc, int backgroundBlurRadius) {
layer_state_t* s = getLayerState(sc);
diff --git a/libs/gui/include/gui/LayerState.h b/libs/gui/include/gui/LayerState.h
index 64f191b867..16425c9872 100644
--- a/libs/gui/include/gui/LayerState.h
+++ b/libs/gui/include/gui/LayerState.h
@@ -231,6 +231,8 @@ struct layer_state_t {
eBufferReleaseChannelChanged = 0x40000'00000000,
ePictureProfileHandleChanged = 0x80000'00000000,
eAppContentPriorityChanged = 0x100000'00000000,
+ eClientDrawnCornerRadiusChanged = 0x200000'00000000,
+ eClientDrawnShadowsChanged = 0x400000'00000000,
};
layer_state_t();
@@ -251,9 +253,9 @@ struct layer_state_t {
// Geometry updates.
static constexpr uint64_t GEOMETRY_CHANGES = layer_state_t::eBufferCropChanged |
layer_state_t::eBufferTransformChanged | layer_state_t::eCornerRadiusChanged |
- layer_state_t::eCropChanged | layer_state_t::eDestinationFrameChanged |
- layer_state_t::eMatrixChanged | layer_state_t::ePositionChanged |
- layer_state_t::eTransformToDisplayInverseChanged |
+ layer_state_t::eClientDrawnCornerRadiusChanged | layer_state_t::eCropChanged |
+ layer_state_t::eDestinationFrameChanged | layer_state_t::eMatrixChanged |
+ layer_state_t::ePositionChanged | layer_state_t::eTransformToDisplayInverseChanged |
layer_state_t::eTransparentRegionChanged | layer_state_t::eEdgeExtensionChanged;
// Buffer and related updates.
@@ -274,8 +276,8 @@ struct layer_state_t {
layer_state_t::eColorSpaceAgnosticChanged | layer_state_t::eColorTransformChanged |
layer_state_t::eCornerRadiusChanged | layer_state_t::eDimmingEnabledChanged |
layer_state_t::eHdrMetadataChanged | layer_state_t::eShadowRadiusChanged |
- layer_state_t::eStretchChanged | layer_state_t::ePictureProfileHandleChanged |
- layer_state_t::eAppContentPriorityChanged;
+ layer_state_t::eClientDrawnShadowsChanged | layer_state_t::eStretchChanged |
+ layer_state_t::ePictureProfileHandleChanged | layer_state_t::eAppContentPriorityChanged;
// Changes which invalidates the layer's visible region in CE.
static constexpr uint64_t CONTENT_DIRTY = layer_state_t::CONTENT_CHANGES |
@@ -328,6 +330,8 @@ struct layer_state_t {
uint8_t reserved;
matrix22_t matrix;
float cornerRadius;
+ float clientDrawnCornerRadius;
+ float clientDrawnShadowRadius;
uint32_t backgroundBlurRadius;
sp<SurfaceControl> relativeLayerSurfaceControl;
diff --git a/libs/gui/include/gui/SurfaceComposerClient.h b/libs/gui/include/gui/SurfaceComposerClient.h
index 0f66c8b492..d20b3460b5 100644
--- a/libs/gui/include/gui/SurfaceComposerClient.h
+++ b/libs/gui/include/gui/SurfaceComposerClient.h
@@ -567,6 +567,15 @@ public:
Transaction& setCrop(const sp<SurfaceControl>& sc, const Rect& crop);
Transaction& setCrop(const sp<SurfaceControl>& sc, const FloatRect& crop);
Transaction& setCornerRadius(const sp<SurfaceControl>& sc, float cornerRadius);
+ // Sets the client drawn corner radius for the layer. If both a corner radius and a client
+ // radius are sent to SF, the client radius will be used. This indicates that the corner
+ // radius is drawn by the client and not SurfaceFlinger.
+ Transaction& setClientDrawnCornerRadius(const sp<SurfaceControl>& sc,
+ float clientDrawnCornerRadius);
+ // Sets the client drawn shadow radius for the layer. This indicates that the shadows
+ // are drawn by the client and not SurfaceFlinger.
+ Transaction& setClientDrawnShadowRadius(const sp<SurfaceControl>& sc,
+ float clientDrawnShadowRadius);
Transaction& setBackgroundBlurRadius(const sp<SurfaceControl>& sc,
int backgroundBlurRadius);
Transaction& setBlurRegions(const sp<SurfaceControl>& sc,
diff --git a/libs/ui/include/ui/ShadowSettings.h b/libs/ui/include/ui/ShadowSettings.h
index c0b83b8691..06be6dbbf5 100644
--- a/libs/ui/include/ui/ShadowSettings.h
+++ b/libs/ui/include/ui/ShadowSettings.h
@@ -46,6 +46,9 @@ struct ShadowSettings {
// Length of the cast shadow. If length is <= 0.f no shadows will be drawn.
float length = 0.f;
+ // Length of the cast shadow that is drawn by the client.
+ float clientDrawnLength = 0.f;
+
// If true fill in the casting layer is translucent and the shadow needs to fill the bounds.
// Otherwise the shadow will only be drawn around the edges of the casting layer.
bool casterIsTranslucent = false;
@@ -55,6 +58,7 @@ static inline bool operator==(const ShadowSettings& lhs, const ShadowSettings& r
return lhs.boundaries == rhs.boundaries && lhs.ambientColor == rhs.ambientColor &&
lhs.spotColor == rhs.spotColor && lhs.lightPos == rhs.lightPos &&
lhs.lightRadius == rhs.lightRadius && lhs.length == rhs.length &&
+ lhs.clientDrawnLength == rhs.clientDrawnLength &&
lhs.casterIsTranslucent == rhs.casterIsTranslucent;
}
diff --git a/services/surfaceflinger/FrontEnd/LayerSnapshot.cpp b/services/surfaceflinger/FrontEnd/LayerSnapshot.cpp
index 367132c113..42f3202f20 100644
--- a/services/surfaceflinger/FrontEnd/LayerSnapshot.cpp
+++ b/services/surfaceflinger/FrontEnd/LayerSnapshot.cpp
@@ -398,9 +398,13 @@ void LayerSnapshot::merge(const RequestedLayerState& requested, bool forceUpdate
if (forceUpdate || requested.what & layer_state_t::eSidebandStreamChanged) {
sidebandStream = requested.sidebandStream;
}
- if (forceUpdate || requested.what & layer_state_t::eShadowRadiusChanged) {
- shadowSettings.length = requested.shadowRadius;
+ if (forceUpdate || requested.what & layer_state_t::eShadowRadiusChanged ||
+ requested.what & layer_state_t::eClientDrawnShadowsChanged) {
+ shadowSettings.length =
+ requested.clientDrawnShadowRadius > 0 ? 0.f : requested.shadowRadius;
+ shadowSettings.clientDrawnLength = requested.clientDrawnShadowRadius;
}
+
if (forceUpdate || requested.what & layer_state_t::eFrameRateSelectionPriority) {
frameRateSelectionPriority = requested.frameRateSelectionPriority;
}
diff --git a/services/surfaceflinger/FrontEnd/LayerSnapshot.h b/services/surfaceflinger/FrontEnd/LayerSnapshot.h
index b8df3ed748..68b13959a8 100644
--- a/services/surfaceflinger/FrontEnd/LayerSnapshot.h
+++ b/services/surfaceflinger/FrontEnd/LayerSnapshot.h
@@ -28,16 +28,23 @@ namespace android::surfaceflinger::frontend {
struct RoundedCornerState {
RoundedCornerState() = default;
- RoundedCornerState(const FloatRect& cropRect, const vec2& radius)
- : cropRect(cropRect), radius(radius) {}
// Rounded rectangle in local layer coordinate space.
FloatRect cropRect = FloatRect();
- // Radius of the rounded rectangle.
+ // Radius of the rounded rectangle for composition
vec2 radius;
+ // Requested radius of the rounded rectangle
+ vec2 requestedRadius;
+ // Radius drawn by client for the rounded rectangle
+ vec2 clientDrawnRadius;
+ bool hasClientDrawnRadius() const {
+ return clientDrawnRadius.x > 0.0f && clientDrawnRadius.y > 0.0f;
+ }
+ bool hasRequestedRadius() const { return requestedRadius.x > 0.0f && requestedRadius.y > 0.0f; }
bool hasRoundedCorners() const { return radius.x > 0.0f && radius.y > 0.0f; }
bool operator==(RoundedCornerState const& rhs) const {
- return cropRect == rhs.cropRect && radius == rhs.radius;
+ return cropRect == rhs.cropRect && radius == rhs.radius &&
+ clientDrawnRadius == rhs.clientDrawnRadius;
}
};
diff --git a/services/surfaceflinger/FrontEnd/LayerSnapshotBuilder.cpp b/services/surfaceflinger/FrontEnd/LayerSnapshotBuilder.cpp
index d0dc065353..0be3a1153d 100644
--- a/services/surfaceflinger/FrontEnd/LayerSnapshotBuilder.cpp
+++ b/services/surfaceflinger/FrontEnd/LayerSnapshotBuilder.cpp
@@ -27,6 +27,7 @@
#include <common/FlagManager.h>
#include <common/trace.h>
#include <ftl/small_map.h>
+#include <math/vec2.h>
#include <ui/DisplayMap.h>
#include <ui/FloatRect.h>
@@ -934,7 +935,8 @@ void LayerSnapshotBuilder::updateSnapshot(LayerSnapshot& snapshot, const Args& a
if (forceUpdate || snapshot.clientChanges & layer_state_t::eCornerRadiusChanged ||
snapshot.changes.any(RequestedLayerState::Changes::Geometry |
- RequestedLayerState::Changes::BufferUsageFlags)) {
+ RequestedLayerState::Changes::BufferUsageFlags) ||
+ snapshot.clientChanges & layer_state_t::eClientDrawnCornerRadiusChanged) {
updateRoundedCorner(snapshot, requested, parentSnapshot, args);
}
@@ -974,7 +976,7 @@ void LayerSnapshotBuilder::updateRoundedCorner(LayerSnapshot& snapshot,
}
snapshot.roundedCorner = RoundedCornerState();
RoundedCornerState parentRoundedCorner;
- if (parentSnapshot.roundedCorner.hasRoundedCorners()) {
+ if (parentSnapshot.roundedCorner.hasRequestedRadius()) {
parentRoundedCorner = parentSnapshot.roundedCorner;
ui::Transform t = snapshot.localTransform.inverse();
parentRoundedCorner.cropRect = t.transform(parentRoundedCorner.cropRect);
@@ -983,10 +985,16 @@ void LayerSnapshotBuilder::updateRoundedCorner(LayerSnapshot& snapshot,
}
FloatRect layerCropRect = snapshot.croppedBufferSize;
- const vec2 radius(requested.cornerRadius, requested.cornerRadius);
- RoundedCornerState layerSettings(layerCropRect, radius);
- const bool layerSettingsValid = layerSettings.hasRoundedCorners() && !layerCropRect.isEmpty();
- const bool parentRoundedCornerValid = parentRoundedCorner.hasRoundedCorners();
+ const vec2 requestedRadius(requested.cornerRadius, requested.cornerRadius);
+ const vec2 clientDrawnRadius(requested.clientDrawnCornerRadius,
+ requested.clientDrawnCornerRadius);
+ RoundedCornerState layerSettings;
+ layerSettings.cropRect = layerCropRect;
+ layerSettings.requestedRadius = requestedRadius;
+ layerSettings.clientDrawnRadius = clientDrawnRadius;
+
+ const bool layerSettingsValid = layerSettings.hasRequestedRadius() && !layerCropRect.isEmpty();
+ const bool parentRoundedCornerValid = parentRoundedCorner.hasRequestedRadius();
if (layerSettingsValid && parentRoundedCornerValid) {
// If the parent and the layer have rounded corner settings, use the parent settings if
// the parent crop is entirely inside the layer crop. This has limitations and cause
@@ -1004,6 +1012,14 @@ void LayerSnapshotBuilder::updateRoundedCorner(LayerSnapshot& snapshot,
} else if (parentRoundedCornerValid) {
snapshot.roundedCorner = parentRoundedCorner;
}
+
+ if (snapshot.roundedCorner.requestedRadius.x == requested.clientDrawnCornerRadius) {
+ // If the client drawn radius matches the requested radius, then surfaceflinger
+ // does not need to draw rounded corners for this layer
+ snapshot.roundedCorner.radius = vec2(0.f, 0.f);
+ } else {
+ snapshot.roundedCorner.radius = snapshot.roundedCorner.requestedRadius;
+ }
}
/**
diff --git a/services/surfaceflinger/FrontEnd/RequestedLayerState.cpp b/services/surfaceflinger/FrontEnd/RequestedLayerState.cpp
index ee9302b937..591ebb2043 100644
--- a/services/surfaceflinger/FrontEnd/RequestedLayerState.cpp
+++ b/services/surfaceflinger/FrontEnd/RequestedLayerState.cpp
@@ -107,6 +107,8 @@ RequestedLayerState::RequestedLayerState(const LayerCreationArgs& args)
hdrMetadata.validTypes = 0;
surfaceDamageRegion = Region::INVALID_REGION;
cornerRadius = 0.0f;
+ clientDrawnCornerRadius = 0.0f;
+ clientDrawnShadowRadius = 0.0f;
backgroundBlurRadius = 0;
api = -1;
hasColorTransform = false;
@@ -348,6 +350,16 @@ void RequestedLayerState::merge(const ResolvedComposerState& resolvedComposerSta
requestedFrameRate.category = category;
changes |= RequestedLayerState::Changes::FrameRate;
}
+
+ if (clientState.what & layer_state_t::eClientDrawnCornerRadiusChanged) {
+ clientDrawnCornerRadius = clientState.clientDrawnCornerRadius;
+ changes |= RequestedLayerState::Changes::Geometry;
+ }
+
+ if (clientState.what & layer_state_t::eClientDrawnShadowsChanged) {
+ clientDrawnShadowRadius = clientState.clientDrawnShadowRadius;
+ changes |= RequestedLayerState::Changes::Geometry;
+ }
}
ui::Size RequestedLayerState::getUnrotatedBufferSize(uint32_t displayRotationFlags) const {
@@ -624,6 +636,8 @@ bool RequestedLayerState::isSimpleBufferUpdate(const layer_state_t& s) const {
const uint64_t deniedChanges = layer_state_t::ePositionChanged | layer_state_t::eAlphaChanged |
layer_state_t::eColorTransformChanged | layer_state_t::eBackgroundColorChanged |
layer_state_t::eMatrixChanged | layer_state_t::eCornerRadiusChanged |
+ layer_state_t::eClientDrawnCornerRadiusChanged |
+ layer_state_t::eClientDrawnShadowsChanged |
layer_state_t::eBackgroundBlurRadiusChanged | layer_state_t::eBufferTransformChanged |
layer_state_t::eTransformToDisplayInverseChanged | layer_state_t::eCropChanged |
layer_state_t::eDataspaceChanged | layer_state_t::eHdrMetadataChanged |
diff --git a/services/surfaceflinger/Layer.h b/services/surfaceflinger/Layer.h
index c234a75693..6af0f59d51 100644
--- a/services/surfaceflinger/Layer.h
+++ b/services/surfaceflinger/Layer.h
@@ -516,11 +516,6 @@ private:
bool mGetHandleCalled = false;
- // The inherited shadow radius after taking into account the layer hierarchy. This is the
- // final shadow radius for this layer. If a shadow is specified for a layer, then effective
- // shadow radius is the set shadow radius, otherwise its the parent's shadow radius.
- float mEffectiveShadowRadius = 0.f;
-
// Game mode for the layer. Set by WindowManagerShell and recorded by SurfaceFlingerStats.
gui::GameMode mGameMode = gui::GameMode::Unsupported;
diff --git a/services/surfaceflinger/tests/LayerTypeAndRenderTypeTransaction_test.cpp b/services/surfaceflinger/tests/LayerTypeAndRenderTypeTransaction_test.cpp
index f247c9f088..151611cad2 100644
--- a/services/surfaceflinger/tests/LayerTypeAndRenderTypeTransaction_test.cpp
+++ b/services/surfaceflinger/tests/LayerTypeAndRenderTypeTransaction_test.cpp
@@ -585,6 +585,83 @@ TEST_P(LayerTypeAndRenderTypeTransactionTest, ParentCornerRadiusTakesPrecedence)
}
}
+TEST_P(LayerTypeAndRenderTypeTransactionTest, SetClientDrawnCornerRadius) {
+ sp<SurfaceControl> layer;
+ const uint8_t size = 64;
+ const uint8_t testArea = 4;
+ const float cornerRadius = 20.0f;
+ ASSERT_NO_FATAL_FAILURE(layer = createLayer("test", size, size));
+ ASSERT_NO_FATAL_FAILURE(fillLayerColor(layer, Color::RED, size, size));
+
+ Transaction()
+ .setClientDrawnCornerRadius(layer, cornerRadius)
+ .setCornerRadius(layer, cornerRadius)
+ .setCrop(layer, Rect(size, size))
+ .apply();
+
+ {
+ const uint8_t bottom = size - 1;
+ const uint8_t right = size - 1;
+ auto shot = getScreenCapture();
+ // Solid corners
+ shot->expectColor(Rect(0, 0, testArea, testArea), Color::RED);
+ shot->expectColor(Rect(size - testArea, 0, right, testArea), Color::RED);
+ shot->expectColor(Rect(0, bottom - testArea, testArea, bottom), Color::RED);
+ shot->expectColor(Rect(size - testArea, bottom - testArea, right, bottom), Color::RED);
+ // Solid center
+ shot->expectColor(Rect(size / 2 - testArea / 2, size / 2 - testArea / 2,
+ size / 2 + testArea / 2, size / 2 + testArea / 2),
+ Color::RED);
+ }
+}
+
+// Test if ParentCornerRadiusTakesPrecedence if the parent's client drawn corner radius crop
+// is fully contained by the child corner radius crop.
+TEST_P(LayerTypeAndRenderTypeTransactionTest, ParentCornerRadiusPrecedenceClientDrawnCornerRadius) {
+ sp<SurfaceControl> parent;
+ sp<SurfaceControl> child;
+ const uint32_t size = 64;
+ const uint32_t parentSize = size * 3;
+ const Rect parentCrop(size, size, size, size);
+ const uint32_t testLength = 4;
+ const float cornerRadius = 20.0f;
+ ASSERT_NO_FATAL_FAILURE(parent = createLayer("parent", parentSize, parentSize));
+ ASSERT_NO_FATAL_FAILURE(fillLayerColor(parent, Color::RED, parentSize, parentSize));
+ ASSERT_NO_FATAL_FAILURE(child = createLayer("child", size, size));
+ ASSERT_NO_FATAL_FAILURE(fillLayerColor(child, Color::GREEN, size, size));
+
+ Transaction()
+ .setCornerRadius(parent, cornerRadius)
+ .setCrop(parent, parentCrop)
+ .setClientDrawnCornerRadius(parent, cornerRadius)
+ .reparent(child, parent)
+ .setPosition(child, size, size)
+ .apply(true);
+
+ {
+ const uint32_t top = size;
+ const uint32_t left = size;
+ const uint32_t bottom = size * 2;
+ const uint32_t right = size * 2;
+ auto shot = getScreenCapture();
+ // Corners are RED because parent's client drawn corner radius is actually 0
+ // and the child is fully within the parent's crop
+ // TL
+ shot->expectColor(Rect(left, top, testLength, testLength), Color::RED);
+ // TR
+ shot->expectColor(Rect(right - testLength, top, testLength, testLength), Color::RED);
+ // BL
+ shot->expectColor(Rect(left, bottom - testLength, testLength, testLength), Color::RED);
+ // BR
+ shot->expectColor(Rect(right - testLength, bottom - testLength, testLength, testLength),
+ Color::RED);
+ // Solid center
+ shot->expectColor(Rect(parentSize / 2 - testLength, parentSize / 2 - testLength, testLength,
+ testLength),
+ Color::GREEN);
+ }
+}
+
TEST_P(LayerTypeAndRenderTypeTransactionTest, SetBackgroundBlurRadiusSimple) {
if (!deviceSupportsBlurs()) GTEST_SKIP();
if (!deviceUsesSkiaRenderEngine()) GTEST_SKIP();
diff --git a/services/surfaceflinger/tests/common/LayerLifecycleManagerHelper.h b/services/surfaceflinger/tests/common/LayerLifecycleManagerHelper.h
index a894c418f6..ee5d9193ea 100644
--- a/services/surfaceflinger/tests/common/LayerLifecycleManagerHelper.h
+++ b/services/surfaceflinger/tests/common/LayerLifecycleManagerHelper.h
@@ -485,6 +485,29 @@ public:
mLifecycleManager.applyTransactions(transactions);
}
+ void setClientDrawnCornerRadius(uint32_t id, float clientDrawnCornerRadius) {
+ std::vector<QueuedTransactionState> transactions;
+ transactions.emplace_back();
+ transactions.back().states.push_back({});
+
+ transactions.back().states.front().state.what =
+ layer_state_t::eClientDrawnCornerRadiusChanged;
+ transactions.back().states.front().layerId = id;
+ transactions.back().states.front().state.clientDrawnCornerRadius = clientDrawnCornerRadius;
+ mLifecycleManager.applyTransactions(transactions);
+ }
+
+ void setClientDrawnShadowRadius(uint32_t id, float clientDrawnShadowRadius) {
+ std::vector<QueuedTransactionState> transactions;
+ transactions.emplace_back();
+ transactions.back().states.push_back({});
+
+ transactions.back().states.front().state.what = layer_state_t::eClientDrawnShadowsChanged;
+ transactions.back().states.front().layerId = id;
+ transactions.back().states.front().state.clientDrawnShadowRadius = clientDrawnShadowRadius;
+ mLifecycleManager.applyTransactions(transactions);
+ }
+
void setShadowRadius(uint32_t id, float shadowRadius) {
std::vector<QueuedTransactionState> transactions;
transactions.emplace_back();
diff --git a/services/surfaceflinger/tests/unittests/LayerSnapshotTest.cpp b/services/surfaceflinger/tests/unittests/LayerSnapshotTest.cpp
index 1177d1601e..2deb177496 100644
--- a/services/surfaceflinger/tests/unittests/LayerSnapshotTest.cpp
+++ b/services/surfaceflinger/tests/unittests/LayerSnapshotTest.cpp
@@ -1425,6 +1425,59 @@ TEST_F(LayerSnapshotTest, setBufferCrop) {
EXPECT_EQ(getSnapshot(1)->geomContentCrop, Rect(0, 0, 100, 100));
}
+TEST_F(LayerSnapshotTest, setCornerRadius) {
+ static constexpr float RADIUS = 123.f;
+ setRoundedCorners(1, RADIUS);
+ setCrop(1, Rect{1000, 1000});
+ UPDATE_AND_VERIFY(mSnapshotBuilder, STARTING_ZORDER);
+ EXPECT_EQ(getSnapshot({.id = 1})->roundedCorner.radius.x, RADIUS);
+}
+
+TEST_F(LayerSnapshotTest, ignoreCornerRadius) {
+ static constexpr float RADIUS = 123.f;
+ setClientDrawnCornerRadius(1, RADIUS);
+ setRoundedCorners(1, RADIUS);
+ setCrop(1, Rect{1000, 1000});
+ UPDATE_AND_VERIFY(mSnapshotBuilder, STARTING_ZORDER);
+ EXPECT_TRUE(getSnapshot({.id = 1})->roundedCorner.hasClientDrawnRadius());
+ EXPECT_EQ(getSnapshot({.id = 1})->roundedCorner.radius.x, 0.f);
+}
+
+TEST_F(LayerSnapshotTest, childInheritsParentIntendedCornerRadius) {
+ static constexpr float RADIUS = 123.f;
+
+ setClientDrawnCornerRadius(1, RADIUS);
+ setRoundedCorners(1, RADIUS);
+ setCrop(1, Rect(1, 1, 999, 999));
+
+ UPDATE_AND_VERIFY(mSnapshotBuilder, STARTING_ZORDER);
+ EXPECT_TRUE(getSnapshot({.id = 1})->roundedCorner.hasClientDrawnRadius());
+ EXPECT_TRUE(getSnapshot({.id = 11})->roundedCorner.hasRoundedCorners());
+ EXPECT_EQ(getSnapshot({.id = 11})->roundedCorner.radius.x, RADIUS);
+}
+
+TEST_F(LayerSnapshotTest, childIgnoreCornerRadiusOverridesParent) {
+ static constexpr float RADIUS = 123.f;
+
+ setRoundedCorners(1, RADIUS);
+ setCrop(1, Rect(1, 1, 999, 999));
+
+ setClientDrawnCornerRadius(11, RADIUS);
+
+ UPDATE_AND_VERIFY(mSnapshotBuilder, STARTING_ZORDER);
+ EXPECT_EQ(getSnapshot({.id = 1})->roundedCorner.radius.x, RADIUS);
+ EXPECT_EQ(getSnapshot({.id = 11})->roundedCorner.radius.x, 0.f);
+ EXPECT_EQ(getSnapshot({.id = 111})->roundedCorner.radius.x, RADIUS);
+}
+
+TEST_F(LayerSnapshotTest, ignoreShadows) {
+ static constexpr float SHADOW_RADIUS = 123.f;
+ setClientDrawnShadowRadius(1, SHADOW_RADIUS);
+ setShadowRadius(1, SHADOW_RADIUS);
+ UPDATE_AND_VERIFY(mSnapshotBuilder, STARTING_ZORDER);
+ EXPECT_EQ(getSnapshot({.id = 1})->shadowSettings.length, 0.f);
+}
+
TEST_F(LayerSnapshotTest, setShadowRadius) {
static constexpr float SHADOW_RADIUS = 123.f;
setShadowRadius(1, SHADOW_RADIUS);