Make blur surface with bounds of layer
This CL changes the blur logic to take a snapshot only of the layer, not
the whole screen.
This has 2 benefits:
1. The blur shader samples only within the bounds of the surface, so
this change fixes a black frame around the blurred layer
2. The blur surface is smaller when the layer is not fullscreen, so less
information gets copied around
Bug: 174464919
Test: check background blur doesn't have a black frame
Test: check blur regions are in place
Change-Id: Ic31742248cc8441225503af48f13e6ef95a59443
diff --git a/libs/renderengine/skia/SkiaGLRenderEngine.cpp b/libs/renderengine/skia/SkiaGLRenderEngine.cpp
index a0660fb..1c8ce9f 100644
--- a/libs/renderengine/skia/SkiaGLRenderEngine.cpp
+++ b/libs/renderengine/skia/SkiaGLRenderEngine.cpp
@@ -494,8 +494,7 @@
// displays might have different scaling when compared to the physical screen.
canvas->clipRect(getSkRect(display.physicalDisplay));
- SkMatrix screenTransform;
- screenTransform.setTranslate(display.physicalDisplay.left, display.physicalDisplay.top);
+ canvas->translate(display.physicalDisplay.left, display.physicalDisplay.top);
const auto clipWidth = display.clip.width();
const auto clipHeight = display.clip.height();
@@ -509,31 +508,33 @@
static_cast<SkScalar>(rotatedClipWidth);
const auto scaleY = static_cast<SkScalar>(display.physicalDisplay.height()) /
static_cast<SkScalar>(rotatedClipHeight);
- screenTransform.preScale(scaleX, scaleY);
+ canvas->scale(scaleX, scaleY);
// Canvas rotation is done by centering the clip window at the origin, rotating, translating
// back so that the top left corner of the clip is at (0, 0).
- screenTransform.preTranslate(rotatedClipWidth / 2, rotatedClipHeight / 2);
- screenTransform.preRotate(toDegrees(display.orientation));
- screenTransform.preTranslate(-clipWidth / 2, -clipHeight / 2);
- screenTransform.preTranslate(-display.clip.left, -display.clip.top);
+ canvas->translate(rotatedClipWidth / 2, rotatedClipHeight / 2);
+ canvas->rotate(toDegrees(display.orientation));
+ canvas->translate(-clipWidth / 2, -clipHeight / 2);
+ canvas->translate(-display.clip.left, -display.clip.top);
for (const auto& layer : layers) {
- const SkMatrix drawTransform = getDrawTransform(layer, screenTransform);
+ canvas->save();
+
+ // Layers have a local transform that should be applied to them
+ canvas->concat(getSkM44(layer->geometry.positionTransform).asM33());
SkPaint paint;
const auto& bounds = layer->geometry.boundaries;
const auto dest = getSkRect(bounds);
+ const auto layerRect = canvas->getTotalMatrix().mapRect(dest);
std::unordered_map<uint32_t, sk_sp<SkSurface>> cachedBlurs;
-
if (mBlurFilter) {
- const auto layerRect = drawTransform.mapRect(dest);
if (layer->backgroundBlurRadius > 0) {
ATRACE_NAME("BackgroundBlur");
auto blurredSurface = mBlurFilter->generate(canvas, surface,
layer->backgroundBlurRadius, layerRect);
cachedBlurs[layer->backgroundBlurRadius] = blurredSurface;
- drawBlurRegion(canvas, getBlurRegion(layer), drawTransform, blurredSurface);
+ drawBlurRegion(canvas, getBlurRegion(layer), layerRect, blurredSurface);
}
if (layer->blurRegions.size() > 0) {
for (auto region : layer->blurRegions) {
@@ -679,12 +680,9 @@
paint.setColorFilter(SkColorFilters::Matrix(toSkColorMatrix(display.colorTransform)));
for (const auto effectRegion : layer->blurRegions) {
- drawBlurRegion(canvas, effectRegion, drawTransform,
- cachedBlurs[effectRegion.blurRadius]);
+ drawBlurRegion(canvas, effectRegion, layerRect, cachedBlurs[effectRegion.blurRadius]);
}
- canvas->save();
- canvas->concat(drawTransform);
if (layer->shadow.length > 0) {
const auto rect = layer->geometry.roundedCornersRadius > 0
? getSkRect(layer->geometry.roundedCornersCrop)
@@ -771,13 +769,6 @@
matrix[0][3], matrix[1][3], matrix[2][3], matrix[3][3]);
}
-inline SkMatrix SkiaGLRenderEngine::getDrawTransform(const LayerSettings* layer,
- const SkMatrix& screenTransform) {
- // Layers have a local transform matrix that should be applied to them.
- const auto layerTransform = getSkM44(layer->geometry.positionTransform).asM33();
- return SkMatrix::Concat(screenTransform, layerTransform);
-}
-
inline SkPoint3 SkiaGLRenderEngine::getSkPoint3(const vec3& vector) {
return SkPoint3::Make(vector.x, vector.y, vector.z);
}
@@ -807,18 +798,16 @@
}
void SkiaGLRenderEngine::drawBlurRegion(SkCanvas* canvas, const BlurRegion& effectRegion,
- const SkMatrix& drawTransform,
- sk_sp<SkSurface> blurredSurface) {
+ const SkRect& layerRect, sk_sp<SkSurface> blurredSurface) {
ATRACE_CALL();
SkPaint paint;
paint.setAlpha(static_cast<int>(effectRegion.alpha * 255));
- const auto matrix = mBlurFilter->getShaderMatrix();
- paint.setShader(blurredSurface->makeImageSnapshot()->makeShader(matrix));
+ paint.setShader(blurredSurface->makeImageSnapshot()->makeShader(
+ getBlurShaderTransform(canvas, layerRect)));
auto rect = SkRect::MakeLTRB(effectRegion.left, effectRegion.top, effectRegion.right,
effectRegion.bottom);
- drawTransform.mapRect(&rect);
if (effectRegion.cornerRadiusTL > 0 || effectRegion.cornerRadiusTR > 0 ||
effectRegion.cornerRadiusBL > 0 || effectRegion.cornerRadiusBR > 0) {
@@ -835,6 +824,24 @@
}
}
+SkMatrix SkiaGLRenderEngine::getBlurShaderTransform(const SkCanvas* canvas,
+ const SkRect& layerRect) {
+ // 1. Apply the blur shader matrix, which scales up the blured surface to its real size
+ auto matrix = mBlurFilter->getShaderMatrix();
+ // 2. Since the blurred surface has the size of the layer, we align it with the
+ // top left corner of the layer position.
+ matrix.postConcat(SkMatrix::Translate(layerRect.fLeft, layerRect.fTop));
+ // 3. Finally, apply the inverse canvas matrix. The snapshot made in the BlurFilter is in the
+ // original surface orientation. The inverse matrix has to be applied to align the blur
+ // surface with the current orientation/position of the canvas.
+ SkMatrix drawInverse;
+ if (canvas->getTotalMatrix().invert(&drawInverse)) {
+ matrix.postConcat(drawInverse);
+ }
+
+ return matrix;
+}
+
EGLContext SkiaGLRenderEngine::createEglContext(EGLDisplay display, EGLConfig config,
EGLContext shareContext, bool useContextPriority,
Protection protection) {