Skip to content

Commit

Permalink
Restore snapping on scale/translate only pictures
Browse files Browse the repository at this point in the history
It turns out that our ios32 (iPhone4s) performacne can regress a lot
without snapping. My theory is that although the picture has a
fractional top left corner, many drawing operations inside the picture
have integral coordinations. In older hardwares, keeping those
coordinates integral seems to be performance critical.

To avoid flutter/flutter#41654, the snapping
will still be disabled if the matrix has non-scale-translation
transformations.
  • Loading branch information
liyuqian committed May 6, 2020
1 parent 358309f commit c6bc494
Show file tree
Hide file tree
Showing 3 changed files with 45 additions and 6 deletions.
11 changes: 10 additions & 1 deletion flow/layers/picture_layer.cc
Expand Up @@ -24,7 +24,12 @@ void PictureLayer::Preroll(PrerollContext* context, const SkMatrix& matrix) {
if (auto* cache = context->raster_cache) {
TRACE_EVENT0("flutter", "PictureLayer::RasterCache (Preroll)");

cache->Prepare(context->gr_context, sk_picture, matrix,
SkMatrix ctm = matrix;
ctm.postTranslate(offset_.x(), offset_.y());
#ifndef SUPPORT_FRACTIONAL_TRANSLATION
ctm = RasterCache::GetIntegralTransCTM(ctm);
#endif
cache->Prepare(context->gr_context, sk_picture, ctm,
context->dst_color_space, is_complex_, will_change_);
}

Expand All @@ -39,6 +44,10 @@ void PictureLayer::Paint(PaintContext& context) const {

SkAutoCanvasRestore save(context.leaf_nodes_canvas, true);
context.leaf_nodes_canvas->translate(offset_.x(), offset_.y());
#ifndef SUPPORT_FRACTIONAL_TRANSLATION
context.leaf_nodes_canvas->setMatrix(RasterCache::GetIntegralTransCTM(
context.leaf_nodes_canvas->getTotalMatrix()));
#endif

if (context.raster_cache &&
context.raster_cache->Draw(*picture(), *context.leaf_nodes_canvas)) {
Expand Down
19 changes: 14 additions & 5 deletions flow/layers/picture_layer_unittests.cc
Expand Up @@ -11,6 +11,10 @@
#include "flutter/testing/mock_canvas.h"
#include "third_party/skia/include/core/SkPicture.h"

#ifndef SUPPORT_FRACTIONAL_TRANSLATION
#include "flutter/flow/raster_cache.h"
#endif

namespace flutter {
namespace testing {

Expand Down Expand Up @@ -81,11 +85,16 @@ TEST_F(PictureLayerTest, SimplePicture) {
EXPECT_FALSE(layer->needs_system_composite());

layer->Paint(paint_context());
auto expected_draw_calls =
std::vector({MockCanvas::DrawCall{0, MockCanvas::SaveData{1}},
MockCanvas::DrawCall{
1, MockCanvas::ConcatMatrixData{layer_offset_matrix}},
MockCanvas::DrawCall{1, MockCanvas::RestoreData{0}}});
auto expected_draw_calls = std::vector(
{MockCanvas::DrawCall{0, MockCanvas::SaveData{1}},
MockCanvas::DrawCall{1,
MockCanvas::ConcatMatrixData{layer_offset_matrix}},
#ifndef SUPPORT_FRACTIONAL_TRANSLATION
MockCanvas::DrawCall{
1, MockCanvas::SetMatrixData{RasterCache::GetIntegralTransCTM(
layer_offset_matrix)}},
#endif
MockCanvas::DrawCall{1, MockCanvas::RestoreData{0}}});
EXPECT_EQ(mock_canvas().draw_calls(), expected_draw_calls);
}

Expand Down
21 changes: 21 additions & 0 deletions flow/raster_cache.h
Expand Up @@ -62,6 +62,27 @@ class RasterCache {
return bounds;
}

/**
* @brief Snap the translation components of the matrix to integers.
*
* The snapping will only happen if the matrix only has scale and translation
* transformations.
*
* @param ctm the current transformation matrix.
* @return SkMatrix the snapped transformation matrix.
*/
static SkMatrix GetIntegralTransCTM(const SkMatrix& ctm) {
// Avoid integral snapping if the matrix has complex transformation to avoid
// the artifact observed in https://github.com/flutter/flutter/issues/41654.
if (!ctm.isScaleTranslate()) {
return ctm;
}
SkMatrix result = ctm;
result[SkMatrix::kMTransX] = SkScalarRoundToScalar(ctm.getTranslateX());
result[SkMatrix::kMTransY] = SkScalarRoundToScalar(ctm.getTranslateY());
return result;
}

// Return true if the cache is generated.
//
// We may return false and not generate the cache if
Expand Down

0 comments on commit c6bc494

Please sign in to comment.