Avoid blur behind for layers that are fully opaque.
This addresses cases where the layer is a solid color or has an
opaque buffer that will result in the blur being completely
overwritten by the layer's contents.
Bug: 188050128
Test: atest librenderengine_test and verfied by mskp capture
Change-Id: I5ef76eca9a3dda21d1faa652da60abb22282925a
diff --git a/libs/renderengine/skia/SkiaGLRenderEngine.cpp b/libs/renderengine/skia/SkiaGLRenderEngine.cpp
index 9f6ecaa..47c330f 100644
--- a/libs/renderengine/skia/SkiaGLRenderEngine.cpp
+++ b/libs/renderengine/skia/SkiaGLRenderEngine.cpp
@@ -725,6 +725,14 @@
return BAD_VALUE;
}
+ // setup color filter if necessary
+ sk_sp<SkColorFilter> displayColorTransform;
+ if (display.colorTransform != mat4()) {
+ displayColorTransform = SkColorFilters::Matrix(toSkColorMatrix(display.colorTransform));
+ }
+ const bool ctModifiesAlpha =
+ displayColorTransform && !displayColorTransform->isAlphaUnchanged();
+
// Find if any layers have requested blur, we'll use that info to decide when to render to an
// offscreen buffer and when to render to the native buffer.
sk_sp<SkSurface> activeSurface(dstSurface);
@@ -734,6 +742,10 @@
if (mBlurFilter) {
bool requiresCompositionLayer = false;
for (const auto& layer : layers) {
+ // if the layer doesn't have blur or it is not visible then continue
+ if (!layerHasBlur(layer, ctModifiesAlpha)) {
+ continue;
+ }
if (layer->backgroundBlurRadius > 0 &&
layer->backgroundBlurRadius < BlurFilter::kMaxCrossFadeRadius) {
requiresCompositionLayer = true;
@@ -779,12 +791,6 @@
canvas->drawRegion(clearRegion, paint);
}
- // setup color filter if necessary
- sk_sp<SkColorFilter> displayColorTransform;
- if (display.colorTransform != mat4()) {
- displayColorTransform = SkColorFilters::Matrix(toSkColorMatrix(display.colorTransform));
- }
-
for (const auto& layer : layers) {
ATRACE_NAME("DrawLayer");
@@ -850,7 +856,7 @@
const auto [bounds, roundRectClip] =
getBoundsAndClip(layer->geometry.boundaries, layer->geometry.roundedCornersCrop,
layer->geometry.roundedCornersRadius);
- if (mBlurFilter && layerHasBlur(layer)) {
+ if (mBlurFilter && layerHasBlur(layer, ctModifiesAlpha)) {
std::unordered_map<uint32_t, sk_sp<SkImage>> cachedBlurs;
// if multiple layers have blur, then we need to take a snapshot now because
@@ -1188,8 +1194,15 @@
return {SkRRect::MakeRect(bounds), clip};
}
-inline bool SkiaGLRenderEngine::layerHasBlur(const LayerSettings* layer) {
- return layer->backgroundBlurRadius > 0 || layer->blurRegions.size();
+inline bool SkiaGLRenderEngine::layerHasBlur(const LayerSettings* layer,
+ bool colorTransformModifiesAlpha) {
+ if (layer->backgroundBlurRadius > 0 || layer->blurRegions.size()) {
+ // return false if the content is opaque and would therefore occlude the blur
+ const bool opaqueContent = !layer->source.buffer.buffer || layer->source.buffer.isOpaque;
+ const bool opaqueAlpha = layer->alpha == 1.0f && !colorTransformModifiesAlpha;
+ return layer->skipContentDraw || !(opaqueContent && opaqueAlpha);
+ }
+ return false;
}
inline SkColor SkiaGLRenderEngine::getSkColor(const vec4& color) {