diff --git a/flow/debug_print.cc b/flow/debug_print.cc index 4c54319e85e..6326153aaa7 100644 --- a/flow/debug_print.cc +++ b/flow/debug_print.cc @@ -73,13 +73,9 @@ std::ostream& operator<<(std::ostream& os, const SkPoint& r) { } std::ostream& operator<<(std::ostream& os, const flow::RasterCacheKey& k) { - os << "Picture: " << k.picture_id() << " Scale: " << k.scale_key().width() - << ", " << k.scale_key().height() -#if defined(OS_FUCHSIA) - << " Metrics scale: (" << k.metrics_scale_x() << ", " - << k.metrics_scale_y() << ")" -#endif - ; + SkString matrix_string; + k.matrix().toString(&matrix_string); + os << "Picture: " << k.picture_id() << " matrix: " << matrix_string.c_str(); return os; } diff --git a/flow/layers/picture_layer.cc b/flow/layers/picture_layer.cc index 622e48a005b..bef944e7f34 100644 --- a/flow/layers/picture_layer.cc +++ b/flow/layers/picture_layer.cc @@ -16,8 +16,13 @@ void PictureLayer::Preroll(PrerollContext* context, const SkMatrix& matrix) { SkPicture* sk_picture = picture(); if (auto cache = context->raster_cache) { + SkMatrix ctm = matrix; + ctm.postTranslate(offset_.x(), offset_.y()); +#ifndef SUPPORT_FRACTIONAL_TRANSLATION + ctm = RasterCache::GetIntegralTransCTM(ctm); +#endif raster_cache_result_ = cache->GetPrerolledImage( - context->gr_context, sk_picture, matrix, context->dst_color_space, + context->gr_context, sk_picture, ctm, context->dst_color_space, is_complex_, will_change_); } else { raster_cache_result_ = RasterCacheResult(); @@ -34,17 +39,13 @@ void PictureLayer::Paint(PaintContext& context) const { SkAutoCanvasRestore save(&context.canvas, true); context.canvas.translate(offset_.x(), offset_.y()); +#ifndef SUPPORT_FRACTIONAL_TRANSLATION + context.canvas.setMatrix( + RasterCache::GetIntegralTransCTM(context.canvas.getTotalMatrix())); +#endif if (raster_cache_result_.is_valid()) { - SkPaint paint; - paint.setFilterQuality(kLow_SkFilterQuality); - context.canvas.drawImageRect( - raster_cache_result_.image(), // image - raster_cache_result_.source_rect(), // source - raster_cache_result_.destination_rect(), // destination - &paint, // paint - SkCanvas::kStrict_SrcRectConstraint // source constraint - ); + raster_cache_result_.draw(context.canvas); } else { context.canvas.drawPicture(picture()); } diff --git a/flow/raster_cache.cc b/flow/raster_cache.cc index 11a86729b48..afd3d27dab2 100644 --- a/flow/raster_cache.cc +++ b/flow/raster_cache.cc @@ -17,6 +17,15 @@ namespace flow { +void RasterCacheResult::draw(SkCanvas& canvas) const { + SkAutoCanvasRestore auto_restore(&canvas, false); + SkIRect bounds = + RasterCache::GetDeviceBounds(logical_rect_, canvas.getTotalMatrix()); + FXL_DCHECK(bounds.size() == image_->dimensions()); + canvas.resetMatrix(); + canvas.drawImage(image_, bounds.fLeft, bounds.fTop); +} + RasterCache::RasterCache(size_t threshold) : threshold_(threshold), checkerboard_images_(false), weak_factory_(this) {} @@ -70,23 +79,16 @@ static bool IsPictureWorthRasterizing(SkPicture* picture, RasterCacheResult RasterizePicture(SkPicture* picture, GrContext* context, - const MatrixDecomposition& matrix, + const SkMatrix& ctm, SkColorSpace* dst_color_space, bool checkerboard) { TRACE_EVENT0("flutter", "RasterCachePopulate"); - const SkVector3& scale = matrix.scale(); - const SkRect logical_rect = picture->cullRect(); + SkIRect cache_rect = RasterCache::GetDeviceBounds(logical_rect, ctm); - const SkRect physical_rect = - SkRect::MakeWH(std::fabs(logical_rect.width() * scale.x()), - std::fabs(logical_rect.height() * scale.y())); - - const SkImageInfo image_info = SkImageInfo::MakeN32Premul( - std::ceil(physical_rect.width()), // physical width - std::ceil(physical_rect.height()) // physical height - ); + const SkImageInfo image_info = + SkImageInfo::MakeN32Premul(cache_rect.width(), cache_rect.height()); sk_sp surface = context @@ -108,19 +110,15 @@ RasterCacheResult RasterizePicture(SkPicture* picture, } canvas->clear(SK_ColorTRANSPARENT); - canvas->scale(std::abs(scale.x()), std::abs(scale.y())); - canvas->translate(-logical_rect.left(), -logical_rect.top()); + canvas->translate(-cache_rect.left(), -cache_rect.top()); + canvas->concat(ctm); canvas->drawPicture(picture); if (checkerboard) { DrawCheckerboard(canvas, logical_rect); } - return { - surface->makeImageSnapshot(), // image - physical_rect, // source rect - logical_rect // destination rect - }; + return {surface->makeImageSnapshot(), logical_rect}; } static inline size_t ClampSize(size_t value, size_t min, size_t max) { @@ -156,7 +154,7 @@ RasterCacheResult RasterCache::GetPrerolledImage( return {}; } - RasterCacheKey cache_key(*picture, matrix); + RasterCacheKey cache_key(*picture, transformation_matrix); Entry& entry = cache_[cache_key]; entry.access_count = ClampSize(entry.access_count + 1, 0, threshold_); @@ -168,8 +166,8 @@ RasterCacheResult RasterCache::GetPrerolledImage( } if (!entry.image.is_valid()) { - entry.image = RasterizePicture(picture, context, matrix, dst_color_space, - checkerboard_images_); + entry.image = RasterizePicture(picture, context, transformation_matrix, + dst_color_space, checkerboard_images_); } return entry.image; diff --git a/flow/raster_cache.h b/flow/raster_cache.h index 3278eb355b0..e72e7437098 100644 --- a/flow/raster_cache.h +++ b/flow/raster_cache.h @@ -19,29 +19,20 @@ namespace flow { class RasterCacheResult { public: - RasterCacheResult() - : source_rect_(SkRect::MakeEmpty()), - destination_rect_(SkRect::MakeEmpty()) {} + RasterCacheResult() {} - RasterCacheResult(sk_sp image, SkRect source, SkRect destination) - : image_(std::move(image)), - source_rect_(source), - destination_rect_(destination) {} + RasterCacheResult(sk_sp image, const SkRect& logical_rect) + : image_(std::move(image)), logical_rect_(logical_rect) {} operator bool() const { return static_cast(image_); } bool is_valid() const { return static_cast(image_); }; - sk_sp image() const { return image_; } - - const SkRect& source_rect() const { return source_rect_; } - - const SkRect& destination_rect() const { return destination_rect_; } + void draw(SkCanvas& canvas) const; private: sk_sp image_; - SkRect source_rect_; - SkRect destination_rect_; + SkRect logical_rect_; }; class RasterCache { @@ -50,6 +41,21 @@ class RasterCache { ~RasterCache(); + static SkIRect GetDeviceBounds(const SkRect& rect, const SkMatrix& ctm) { + SkRect device_rect; + ctm.mapRect(&device_rect, rect); + SkIRect bounds; + device_rect.roundOut(&bounds); + return bounds; + } + + static SkMatrix GetIntegralTransCTM(const SkMatrix& ctm) { + SkMatrix result = ctm; + result[SkMatrix::kMTransX] = SkScalarRoundToScalar(ctm.getTranslateX()); + result[SkMatrix::kMTransY] = SkScalarRoundToScalar(ctm.getTranslateY()); + return result; + } + RasterCacheResult GetPrerolledImage(GrContext* context, SkPicture* picture, const SkMatrix& transformation_matrix, diff --git a/flow/raster_cache_key.h b/flow/raster_cache_key.h index 1f28ea5320d..c6f4c759378 100644 --- a/flow/raster_cache_key.h +++ b/flow/raster_cache_key.h @@ -7,6 +7,7 @@ #include #include "flutter/flow/matrix_decomposition.h" +#include "lib/fxl/logging.h" #include "lib/fxl/macros.h" #include "third_party/skia/include/core/SkImage.h" #include "third_party/skia/include/core/SkPicture.h" @@ -15,14 +16,17 @@ namespace flow { class RasterCacheKey { public: - RasterCacheKey(const SkPicture& picture, const MatrixDecomposition& matrix) - : picture_id_(picture.uniqueID()), - scale_key_(SkISize::Make(matrix.scale().x() * 1e3, - matrix.scale().y() * 1e3)) {} + RasterCacheKey(const SkPicture& picture, const SkMatrix& ctm) + : picture_id_(picture.uniqueID()), matrix_(ctm) { + matrix_[SkMatrix::kMTransX] = SkScalarFraction(ctm.getTranslateX()); + matrix_[SkMatrix::kMTransY] = SkScalarFraction(ctm.getTranslateY()); +#ifndef SUPPORT_FRACTIONAL_TRANSLATION + FXL_DCHECK(matrix_.getTranslateX() == 0 && matrix_.getTranslateY() == 0); +#endif + } uint32_t picture_id() const { return picture_id_; } - - const SkISize& scale_key() const { return scale_key_; } + const SkMatrix& matrix() const { return matrix_; } struct Hash { std::size_t operator()(RasterCacheKey const& key) const { @@ -33,8 +37,7 @@ class RasterCacheKey { struct Equal { constexpr bool operator()(const RasterCacheKey& lhs, const RasterCacheKey& rhs) const { - return lhs.picture_id_ == rhs.picture_id_ && - lhs.scale_key_ == rhs.scale_key_; + return lhs.picture_id_ == rhs.picture_id_ && lhs.matrix_ == rhs.matrix_; } }; @@ -43,7 +46,12 @@ class RasterCacheKey { private: uint32_t picture_id_; - SkISize scale_key_; + + // ctm where only fractional (0-1) translations are preserved: + // matrix_ = ctm; + // matrix_[SkMatrix::kMTransX] = SkScalarFraction(ctm.getTranslateX()); + // matrix_[SkMatrix::kMTransY] = SkScalarFraction(ctm.getTranslateY()); + SkMatrix matrix_; }; } // namespace flow