Merge changes I8d2a0988,I5f8f7c4a into sc-dev
* changes:
Fix bg blur not showing when layer alpha is 0
Fix blur sampling outside bounds of layer
diff --git a/libs/renderengine/skia/filters/BlurFilter.cpp b/libs/renderengine/skia/filters/BlurFilter.cpp
index 5960e48..ec710d9 100644
--- a/libs/renderengine/skia/filters/BlurFilter.cpp
+++ b/libs/renderengine/skia/filters/BlurFilter.cpp
@@ -36,13 +36,18 @@
SkString blurString(R"(
in shader input;
uniform float2 in_blurOffset;
+ uniform float2 in_maxSizeXY;
half4 main(float2 xy) {
half4 c = sample(input, xy);
- c += sample(input, xy + float2( in_blurOffset.x, in_blurOffset.y));
- c += sample(input, xy + float2( in_blurOffset.x, -in_blurOffset.y));
- c += sample(input, xy + float2(-in_blurOffset.x, in_blurOffset.y));
- c += sample(input, xy + float2(-in_blurOffset.x, -in_blurOffset.y));
+ c += sample(input, float2( clamp( in_blurOffset.x + xy.x, 0, in_maxSizeXY.x),
+ clamp(in_blurOffset.y + xy.y, 0, in_maxSizeXY.y)));
+ c += sample(input, float2( clamp( in_blurOffset.x + xy.x, 0, in_maxSizeXY.x),
+ clamp(-in_blurOffset.y + xy.y, 0, in_maxSizeXY.y)));
+ c += sample(input, float2( clamp( -in_blurOffset.x + xy.x, 0, in_maxSizeXY.x),
+ clamp(in_blurOffset.y + xy.y, 0, in_maxSizeXY.y)));
+ c += sample(input, float2( clamp( -in_blurOffset.x + xy.x, 0, in_maxSizeXY.x),
+ clamp(-in_blurOffset.y + xy.y, 0, in_maxSizeXY.y)));
return half4(c.rgb * 0.2, 1.0);
}
@@ -99,6 +104,8 @@
blurBuilder.child("input") =
input->makeShader(SkTileMode::kClamp, SkTileMode::kClamp, linear, blurMatrix);
blurBuilder.uniform("in_blurOffset") = SkV2{stepX * kInputScale, stepY * kInputScale};
+ blurBuilder.uniform("in_maxSizeXY") =
+ SkV2{blurRect.width() * kInputScale - 1, blurRect.height() * kInputScale - 1};
sk_sp<SkImage> tmpBlur(blurBuilder.makeImage(context, nullptr, scaledInfo, false));
@@ -108,6 +115,8 @@
blurBuilder.child("input") =
tmpBlur->makeShader(SkTileMode::kClamp, SkTileMode::kClamp, linear);
blurBuilder.uniform("in_blurOffset") = SkV2{stepX * stepScale, stepY * stepScale};
+ blurBuilder.uniform("in_maxSizeXY") =
+ SkV2{blurRect.width() * kInputScale - 1, blurRect.height() * kInputScale - 1};
tmpBlur = blurBuilder.makeImage(context, nullptr, scaledInfo, false);
}
diff --git a/services/surfaceflinger/EffectLayer.cpp b/services/surfaceflinger/EffectLayer.cpp
index 44d4d75..caef338 100644
--- a/services/surfaceflinger/EffectLayer.cpp
+++ b/services/surfaceflinger/EffectLayer.cpp
@@ -77,7 +77,7 @@
}
bool EffectLayer::isVisible() const {
- return !isHiddenByPolicy() && getAlpha() > 0.0_hf && hasSomethingToDraw();
+ return !isHiddenByPolicy() && (getAlpha() > 0.0_hf || hasBlur()) && hasSomethingToDraw();
}
bool EffectLayer::setColor(const half3& color) {
diff --git a/services/surfaceflinger/tests/EffectLayer_test.cpp b/services/surfaceflinger/tests/EffectLayer_test.cpp
index fafb49e..7a3c45d 100644
--- a/services/surfaceflinger/tests/EffectLayer_test.cpp
+++ b/services/surfaceflinger/tests/EffectLayer_test.cpp
@@ -111,6 +111,72 @@
}
}
+TEST_F(EffectLayerTest, BlurEffectLayerIsVisible) {
+ if (!deviceSupportsBlurs()) GTEST_SKIP();
+ if (!deviceUsesSkiaRenderEngine()) GTEST_SKIP();
+
+ const auto canvasSize = 256;
+
+ sp<SurfaceControl> leftLayer = createColorLayer("Left", Color::BLUE);
+ sp<SurfaceControl> rightLayer = createColorLayer("Right", Color::GREEN);
+ sp<SurfaceControl> blurLayer;
+ const auto leftRect = Rect(0, 0, canvasSize / 2, canvasSize);
+ const auto rightRect = Rect(canvasSize / 2, 0, canvasSize, canvasSize);
+ const auto blurRect = Rect(0, 0, canvasSize, canvasSize);
+
+ asTransaction([&](Transaction& t) {
+ t.setLayer(leftLayer, mLayerZBase + 1);
+ t.reparent(leftLayer, mParentLayer);
+ t.setCrop_legacy(leftLayer, leftRect);
+ t.setLayer(rightLayer, mLayerZBase + 2);
+ t.reparent(rightLayer, mParentLayer);
+ t.setCrop_legacy(rightLayer, rightRect);
+ t.show(leftLayer);
+ t.show(rightLayer);
+ });
+
+ {
+ auto shot = screenshot();
+ shot->expectColor(leftRect, Color::BLUE);
+ shot->expectColor(rightRect, Color::GREEN);
+ }
+
+ ASSERT_NO_FATAL_FAILURE(blurLayer = createColorLayer("BackgroundBlur", Color::TRANSPARENT));
+
+ const auto blurRadius = canvasSize / 2;
+ asTransaction([&](Transaction& t) {
+ t.setLayer(blurLayer, mLayerZBase + 3);
+ t.reparent(blurLayer, mParentLayer);
+ t.setBackgroundBlurRadius(blurLayer, blurRadius);
+ t.setCrop_legacy(blurLayer, blurRect);
+ t.setFrame(blurLayer, blurRect);
+ t.setAlpha(blurLayer, 0.0f);
+ t.show(blurLayer);
+ });
+
+ {
+ auto shot = screenshot();
+
+ const auto stepSize = 1;
+ const auto blurAreaOffset = blurRadius * 0.7f;
+ const auto blurAreaStartX = canvasSize / 2 - blurRadius + blurAreaOffset;
+ const auto blurAreaEndX = canvasSize / 2 + blurRadius - blurAreaOffset;
+ Color previousColor;
+ Color currentColor;
+ for (int y = 0; y < canvasSize; y++) {
+ shot->checkPixel(0, y, /* r = */ 0, /* g = */ 0, /* b = */ 255);
+ previousColor = shot->getPixelColor(0, y);
+ for (int x = blurAreaStartX; x < blurAreaEndX; x += stepSize) {
+ currentColor = shot->getPixelColor(x, y);
+ ASSERT_GT(currentColor.g, previousColor.g);
+ ASSERT_LT(currentColor.b, previousColor.b);
+ ASSERT_EQ(0, currentColor.r);
+ }
+ shot->checkPixel(canvasSize - 1, y, 0, 255, 0);
+ }
+ }
+}
+
} // namespace android
// TODO(b/129481165): remove the #pragma below and fix conversion issues
diff --git a/services/surfaceflinger/tests/LayerTransactionTest.h b/services/surfaceflinger/tests/LayerTransactionTest.h
index eba2c25..05729be 100644
--- a/services/surfaceflinger/tests/LayerTransactionTest.h
+++ b/services/surfaceflinger/tests/LayerTransactionTest.h
@@ -21,6 +21,7 @@
#pragma clang diagnostic ignored "-Wconversion"
#pragma clang diagnostic ignored "-Wextra"
+#include <cutils/properties.h>
#include <gtest/gtest.h>
#include <gui/ISurfaceComposer.h>
#include <gui/SurfaceComposerClient.h>
@@ -245,6 +246,18 @@
sp<SurfaceComposerClient> mClient;
+ bool deviceSupportsBlurs() {
+ char value[PROPERTY_VALUE_MAX];
+ property_get("ro.surface_flinger.supports_background_blur", value, "0");
+ return atoi(value);
+ }
+
+ bool deviceUsesSkiaRenderEngine() {
+ char value[PROPERTY_VALUE_MAX];
+ property_get("debug.renderengine.backend", value, "default");
+ return strstr(value, "skia") != nullptr;
+ }
+
sp<IBinder> mDisplay;
uint32_t mDisplayWidth;
uint32_t mDisplayHeight;
@@ -307,4 +320,4 @@
} // namespace android
// TODO(b/129481165): remove the #pragma below and fix conversion issues
-#pragma clang diagnostic pop // ignored "-Wconversion -Wextra"
\ No newline at end of file
+#pragma clang diagnostic pop // ignored "-Wconversion -Wextra"
diff --git a/services/surfaceflinger/tests/LayerTypeAndRenderTypeTransaction_test.cpp b/services/surfaceflinger/tests/LayerTypeAndRenderTypeTransaction_test.cpp
index 782a364..44e7189 100644
--- a/services/surfaceflinger/tests/LayerTypeAndRenderTypeTransaction_test.cpp
+++ b/services/surfaceflinger/tests/LayerTypeAndRenderTypeTransaction_test.cpp
@@ -18,7 +18,6 @@
#pragma clang diagnostic push
#pragma clang diagnostic ignored "-Wconversion"
-#include <cutils/properties.h>
#include <gui/BufferItemConsumer.h>
#include "TransactionTestHarnesses.h"
@@ -301,47 +300,86 @@
}
}
-TEST_P(LayerTypeAndRenderTypeTransactionTest, SetBackgroundBlurRadius) {
- char value[PROPERTY_VALUE_MAX];
- property_get("ro.surface_flinger.supports_background_blur", value, "0");
- if (!atoi(value)) {
- // This device doesn't support blurs, no-op.
- return;
- }
+TEST_P(LayerTypeAndRenderTypeTransactionTest, SetBackgroundBlurRadiusSimple) {
+ if (!deviceSupportsBlurs()) GTEST_SKIP();
+ if (!deviceUsesSkiaRenderEngine()) GTEST_SKIP();
- auto size = 256;
- auto center = size / 2;
- auto blurRadius = 50;
-
- sp<SurfaceControl> backgroundLayer;
- ASSERT_NO_FATAL_FAILURE(backgroundLayer = createLayer("background", size, size));
- ASSERT_NO_FATAL_FAILURE(fillLayerColor(backgroundLayer, Color::GREEN, size, size));
+ const auto canvasSize = 256;
sp<SurfaceControl> leftLayer;
- ASSERT_NO_FATAL_FAILURE(leftLayer = createLayer("left", size / 2, size));
- ASSERT_NO_FATAL_FAILURE(fillLayerColor(leftLayer, Color::RED, size / 2, size));
-
+ sp<SurfaceControl> rightLayer;
+ sp<SurfaceControl> greenLayer;
sp<SurfaceControl> blurLayer;
- ASSERT_NO_FATAL_FAILURE(blurLayer = createLayer("blur", size, size));
- ASSERT_NO_FATAL_FAILURE(fillLayerColor(blurLayer, Color::TRANSPARENT, size, size));
+ const auto leftRect = Rect(0, 0, canvasSize / 2, canvasSize);
+ const auto rightRect = Rect(canvasSize / 2, 0, canvasSize, canvasSize);
+ const auto blurRect = Rect(0, 0, canvasSize, canvasSize);
- Transaction().setBackgroundBlurRadius(blurLayer, blurRadius).apply();
+ ASSERT_NO_FATAL_FAILURE(leftLayer =
+ createLayer("Left", leftRect.getWidth(), leftRect.getHeight()));
+ ASSERT_NO_FATAL_FAILURE(
+ fillLayerColor(leftLayer, Color::BLUE, leftRect.getWidth(), leftRect.getHeight()));
+ ASSERT_NO_FATAL_FAILURE(greenLayer = createLayer("Green", canvasSize * 2, canvasSize * 2));
+ ASSERT_NO_FATAL_FAILURE(
+ fillLayerColor(greenLayer, Color::GREEN, canvasSize * 2, canvasSize * 2));
+ ASSERT_NO_FATAL_FAILURE(
+ rightLayer = createLayer("Right", rightRect.getWidth(), rightRect.getHeight()));
+ ASSERT_NO_FATAL_FAILURE(
+ fillLayerColor(rightLayer, Color::RED, rightRect.getWidth(), rightRect.getHeight()));
- auto shot = getScreenCapture();
- // Edges are mixed
- shot->expectColor(Rect(center - 1, center - 5, center, center + 5), Color{150, 150, 0, 255},
- 50 /* tolerance */);
- shot->expectColor(Rect(center, center - 5, center + 1, center + 5), Color{150, 150, 0, 255},
- 50 /* tolerance */);
+ Transaction()
+ .setLayer(greenLayer, mLayerZBase)
+ .setFrame(leftLayer, {0, 0, canvasSize * 2, canvasSize * 2})
+ .setLayer(leftLayer, mLayerZBase + 1)
+ .setFrame(leftLayer, leftRect)
+ .setLayer(rightLayer, mLayerZBase + 2)
+ .setPosition(rightLayer, rightRect.left, rightRect.top)
+ .setFrame(rightLayer, rightRect)
+ .apply();
+
+ {
+ auto shot = getScreenCapture();
+ shot->expectColor(leftRect, Color::BLUE);
+ shot->expectColor(rightRect, Color::RED);
+ }
+
+ ASSERT_NO_FATAL_FAILURE(blurLayer = createColorLayer("BackgroundBlur", Color::TRANSPARENT));
+
+ const auto blurRadius = canvasSize / 2;
+ Transaction()
+ .setLayer(blurLayer, mLayerZBase + 3)
+ .setBackgroundBlurRadius(blurLayer, blurRadius)
+ .setCrop_legacy(blurLayer, blurRect)
+ .setFrame(blurLayer, blurRect)
+ .setSize(blurLayer, blurRect.getWidth(), blurRect.getHeight())
+ .setAlpha(blurLayer, 0.0f)
+ .apply();
+
+ {
+ auto shot = getScreenCapture();
+
+ const auto stepSize = 1;
+ const auto blurAreaOffset = blurRadius * 0.7f;
+ const auto blurAreaStartX = canvasSize / 2 - blurRadius + blurAreaOffset;
+ const auto blurAreaEndX = canvasSize / 2 + blurRadius - blurAreaOffset;
+ Color previousColor;
+ Color currentColor;
+ for (int y = 0; y < canvasSize; y++) {
+ shot->checkPixel(0, y, /* r = */ 0, /* g = */ 0, /* b = */ 255);
+ previousColor = shot->getPixelColor(0, y);
+ for (int x = blurAreaStartX; x < blurAreaEndX; x += stepSize) {
+ currentColor = shot->getPixelColor(x, y);
+ ASSERT_GT(currentColor.r, previousColor.r);
+ ASSERT_LT(currentColor.b, previousColor.b);
+ ASSERT_EQ(0, currentColor.g);
+ }
+ shot->checkPixel(canvasSize - 1, y, 255, 0, 0);
+ }
+ }
}
TEST_P(LayerTypeAndRenderTypeTransactionTest, SetBackgroundBlurRadiusOnMultipleLayers) {
- char value[PROPERTY_VALUE_MAX];
- property_get("ro.surface_flinger.supports_background_blur", value, "0");
- if (!atoi(value)) {
- // This device doesn't support blurs, no-op.
- return;
- }
+ if (!deviceSupportsBlurs()) GTEST_SKIP();
+ if (!deviceUsesSkiaRenderEngine()) GTEST_SKIP();
auto size = 256;
auto center = size / 2;
@@ -378,25 +416,15 @@
}
TEST_P(LayerTypeAndRenderTypeTransactionTest, SetBackgroundBlurAffectedByParentAlpha) {
- char value[PROPERTY_VALUE_MAX];
- property_get("ro.surface_flinger.supports_background_blur", value, "0");
- if (!atoi(value)) {
- // This device doesn't support blurs, no-op.
- return;
- }
-
- property_get("debug.renderengine.backend", value, "");
- if (strcmp(value, "skiagl") != 0) {
- // This device isn't using Skia render engine, no-op.
- return;
- }
+ if (!deviceSupportsBlurs()) GTEST_SKIP();
+ if (!deviceUsesSkiaRenderEngine()) GTEST_SKIP();
sp<SurfaceControl> left;
sp<SurfaceControl> right;
sp<SurfaceControl> blur;
sp<SurfaceControl> blurParent;
- const auto size = 32;
+ const auto size = 256;
ASSERT_NO_FATAL_FAILURE(left = createLayer("Left", size, size));
ASSERT_NO_FATAL_FAILURE(fillLayerColor(left, Color::BLUE, size, size));
ASSERT_NO_FATAL_FAILURE(right = createLayer("Right", size, size));
diff --git a/services/surfaceflinger/tests/utils/ScreenshotUtils.h b/services/surfaceflinger/tests/utils/ScreenshotUtils.h
index 2fefa45..7efd730 100644
--- a/services/surfaceflinger/tests/utils/ScreenshotUtils.h
+++ b/services/surfaceflinger/tests/utils/ScreenshotUtils.h
@@ -159,6 +159,15 @@
}
}
+ Color getPixelColor(uint32_t x, uint32_t y) {
+ if (!mOutBuffer || mOutBuffer->getPixelFormat() != HAL_PIXEL_FORMAT_RGBA_8888) {
+ return {0, 0, 0, 0};
+ }
+
+ const uint8_t* pixel = mPixels + (4 * (y * mOutBuffer->getStride() + x));
+ return {pixel[0], pixel[1], pixel[2], pixel[3]};
+ }
+
void expectFGColor(uint32_t x, uint32_t y) { checkPixel(x, y, 195, 63, 63); }
void expectBGColor(uint32_t x, uint32_t y) { checkPixel(x, y, 63, 63, 195); }