Remove unnecessary drawing commands when drawing shadows.
When blurring behind a shadow, this will ensure that it
is only blurred once. It does so by updating
Layer::prepareShadowClientComposition to add ShadowSettings
to the input layer, rather than adding an extra layer.
Collapsing the shadow layer into the same layer as the caster will
result in undefined behavior in the old GLESRenderEngine.
Bug: 188050128
Bug: 175915334
Test: atest SurfaceFlinger_test and atest librenderengine_test
Change-Id: I5b74ef9659b519fcc6b89dfd873c35fc579fddd7
diff --git a/libs/renderengine/skia/SkiaGLRenderEngine.cpp b/libs/renderengine/skia/SkiaGLRenderEngine.cpp
index 6cc3d37..6d749ed 100644
--- a/libs/renderengine/skia/SkiaGLRenderEngine.cpp
+++ b/libs/renderengine/skia/SkiaGLRenderEngine.cpp
@@ -846,7 +846,9 @@
// Layers have a local transform that should be applied to them
canvas->concat(getSkM44(layer->geometry.positionTransform).asM33());
- const auto [bounds, roundRectClip] = getBoundsAndClip(layer);
+ const auto [bounds, roundRectClip] =
+ getBoundsAndClip(layer->geometry.boundaries, layer->geometry.roundedCornersCrop,
+ layer->geometry.roundedCornersRadius);
if (mBlurFilter && layerHasBlur(layer)) {
std::unordered_map<uint32_t, sk_sp<SkImage>> cachedBlurs;
@@ -895,14 +897,21 @@
}
}
- // Shadows are assumed to live only on their own layer - it's not valid
- // to draw the boundary rectangles when there is already a caster shadow
- // TODO(b/175915334): consider relaxing this restriction to enable more flexible
- // composition - using a well-defined invalid color is long-term less error-prone.
if (layer->shadow.length > 0) {
// This would require a new parameter/flag to SkShadowUtils::DrawShadow
LOG_ALWAYS_FATAL_IF(layer->disableBlending, "Cannot disableBlending with a shadow");
+ SkRRect shadowBounds, shadowClip;
+ if (layer->geometry.boundaries == layer->shadow.boundaries) {
+ shadowBounds = bounds;
+ shadowClip = roundRectClip;
+ } else {
+ std::tie(shadowBounds, shadowClip) =
+ getBoundsAndClip(layer->shadow.boundaries,
+ layer->geometry.roundedCornersCrop,
+ layer->geometry.roundedCornersRadius);
+ }
+
// Technically, if bounds is a rect and roundRectClip is not empty,
// it means that the bounds and roundedCornersCrop were different
// enough that we should intersect them to find the proper shadow.
@@ -910,9 +919,8 @@
// not match due to rounding errors. Draw the rounded version, which
// looks more like the intent.
const auto& rrect =
- bounds.isRect() && !roundRectClip.isEmpty() ? roundRectClip : bounds;
+ shadowBounds.isRect() && !shadowClip.isEmpty() ? shadowClip : shadowBounds;
drawShadow(canvas, rrect, layer->shadow);
- continue;
}
const bool requiresLinearEffect = layer->colorTransform != mat4() ||
@@ -922,8 +930,9 @@
display.sdrWhitePointNits != display.maxLuminance);
// quick abort from drawing the remaining portion of the layer
- if (layer->alpha == 0 && !requiresLinearEffect && !layer->disableBlending &&
- (!displayColorTransform || displayColorTransform->isAlphaUnchanged())) {
+ if (layer->skipContentDraw ||
+ (layer->alpha == 0 && !requiresLinearEffect && !layer->disableBlending &&
+ (!displayColorTransform || displayColorTransform->isAlphaUnchanged()))) {
continue;
}
@@ -1093,11 +1102,11 @@
return SkRect::MakeLTRB(rect.left, rect.top, rect.right, rect.bottom);
}
-inline std::pair<SkRRect, SkRRect> SkiaGLRenderEngine::getBoundsAndClip(
- const LayerSettings* layer) {
- const auto bounds = getSkRect(layer->geometry.boundaries);
- const auto crop = getSkRect(layer->geometry.roundedCornersCrop);
- const auto cornerRadius = layer->geometry.roundedCornersRadius;
+inline std::pair<SkRRect, SkRRect> SkiaGLRenderEngine::getBoundsAndClip(const FloatRect& boundsRect,
+ const FloatRect& cropRect,
+ const float cornerRadius) {
+ const SkRect bounds = getSkRect(boundsRect);
+ const SkRect crop = getSkRect(cropRect);
SkRRect clip;
if (cornerRadius > 0) {