Skip to content

Commit

Permalink
Ensure pre-rolled opacity children see snapped matrix (#36173)
Browse files Browse the repository at this point in the history
  • Loading branch information
jonahwilliams authored Sep 15, 2022
1 parent 9a6caba commit 3284e30
Show file tree
Hide file tree
Showing 2 changed files with 43 additions and 1 deletion.
5 changes: 4 additions & 1 deletion flow/layers/opacity_layer.cc
Original file line number Diff line number Diff line change
Expand Up @@ -42,6 +42,9 @@ void OpacityLayer::Preroll(PrerollContext* context, const SkMatrix& matrix) {

SkMatrix child_matrix = matrix;
child_matrix.preTranslate(offset_.fX, offset_.fY);
if (context->raster_cache) {
child_matrix = RasterCacheUtil::GetIntegralTransCTM(child_matrix);
}

// Similar to what's done in TransformLayer::Preroll, we have to apply the
// reverse transformation to the cull rect to properly cull child layers.
Expand All @@ -52,7 +55,7 @@ void OpacityLayer::Preroll(PrerollContext* context, const SkMatrix& matrix) {
context->mutators_stack.PushOpacity(alpha_);

AutoCache auto_cache =
AutoCache(layer_raster_cache_item_.get(), context, matrix);
AutoCache(layer_raster_cache_item_.get(), context, child_matrix);
Layer::AutoPrerollSaveLayerState save =
Layer::AutoPrerollSaveLayerState::Create(context);

Expand Down
39 changes: 39 additions & 0 deletions flow/layers/opacity_layer_unittests.cc
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@
#include "flutter/flow/layers/image_filter_layer.h"
#include "flutter/flow/layers/layer_tree.h"
#include "flutter/flow/layers/transform_layer.h"
#include "flutter/flow/raster_cache_util.h"
#include "flutter/flow/testing/diff_context_test.h"
#include "flutter/flow/testing/layer_test.h"
#include "flutter/flow/testing/mock_layer.h"
Expand Down Expand Up @@ -662,5 +663,43 @@ TEST_F(OpacityLayerDiffTest, FractionalTranslationWithRasterCache) {
EXPECT_EQ(damage.frame_damage, SkIRect::MakeLTRB(11, 11, 61, 61));
}

TEST_F(OpacityLayerTest, FullyOpaqueWithFractionalValues) {
use_mock_raster_cache(); // Ensure non-fractional alignment.

const SkPath child_path = SkPath().addRect(SkRect::MakeWH(5.0f, 5.0f));
const SkPoint layer_offset = SkPoint::Make(0.5f, 1.5f);
const SkMatrix initial_transform = SkMatrix::Translate(0.5f, 0.5f);
const SkMatrix layer_transform =
SkMatrix::Translate(layer_offset.fX, layer_offset.fY);
const SkPaint child_paint = SkPaint(SkColors::kGreen);
const SkRect expected_layer_bounds =
layer_transform.mapRect(child_path.getBounds());
auto mock_layer = std::make_shared<MockLayer>(child_path, child_paint);
auto layer = std::make_shared<OpacityLayer>(SK_AlphaOPAQUE, layer_offset);
layer->Add(mock_layer);
layer->Preroll(preroll_context(), initial_transform);

const SkPaint opacity_paint = SkPaint(SkColors::kBlack); // A = 1.0f
SkRect opacity_bounds;
expected_layer_bounds.makeOffset(-layer_offset.fX, -layer_offset.fY)
.roundOut(&opacity_bounds);
auto expected_draw_calls = std::vector(
{MockCanvas::DrawCall{0, MockCanvas::SaveData{1}},
MockCanvas::DrawCall{
1, MockCanvas::ConcatMatrixData{SkM44(layer_transform)}},
MockCanvas::DrawCall{
1, MockCanvas::SetMatrixData{SkM44(
RasterCacheUtil::GetIntegralTransCTM(layer_transform))}},
MockCanvas::DrawCall{
1, MockCanvas::SaveLayerData{opacity_bounds, opacity_paint, nullptr,
2}},
MockCanvas::DrawCall{2,
MockCanvas::DrawPathData{child_path, child_paint}},
MockCanvas::DrawCall{2, MockCanvas::RestoreData{1}},
MockCanvas::DrawCall{1, MockCanvas::RestoreData{0}}});
layer->Paint(paint_context());
EXPECT_EQ(mock_canvas().draw_calls(), expected_draw_calls);
}

} // namespace testing
} // namespace flutter

0 comments on commit 3284e30

Please sign in to comment.