Skip to content

Commit

Permalink
Use drawImage for picture layer cache (flutter#5315)
Browse files Browse the repository at this point in the history
Fixes
1. flutter/flutter#12148
2. most part of flutter/flutter#17731 except some tiny AA diffs.
  • Loading branch information
liyuqian authored May 23, 2018
1 parent 87944d8 commit 1ef8cd2
Show file tree
Hide file tree
Showing 5 changed files with 70 additions and 61 deletions.
10 changes: 3 additions & 7 deletions flow/debug_print.cc
Original file line number Diff line number Diff line change
Expand Up @@ -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;
}

Expand Down
21 changes: 11 additions & 10 deletions flow/layers/picture_layer.cc
Original file line number Diff line number Diff line change
Expand Up @@ -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();
Expand All @@ -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());
}
Expand Down
40 changes: 19 additions & 21 deletions flow/raster_cache.cc
Original file line number Diff line number Diff line change
Expand Up @@ -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) {}

Expand Down Expand Up @@ -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<SkSurface> surface =
context
Expand All @@ -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) {
Expand Down Expand Up @@ -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_);
Expand All @@ -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;
Expand Down
34 changes: 20 additions & 14 deletions flow/raster_cache.h
Original file line number Diff line number Diff line change
Expand Up @@ -19,29 +19,20 @@ namespace flow {

class RasterCacheResult {
public:
RasterCacheResult()
: source_rect_(SkRect::MakeEmpty()),
destination_rect_(SkRect::MakeEmpty()) {}
RasterCacheResult() {}

RasterCacheResult(sk_sp<SkImage> image, SkRect source, SkRect destination)
: image_(std::move(image)),
source_rect_(source),
destination_rect_(destination) {}
RasterCacheResult(sk_sp<SkImage> image, const SkRect& logical_rect)
: image_(std::move(image)), logical_rect_(logical_rect) {}

operator bool() const { return static_cast<bool>(image_); }

bool is_valid() const { return static_cast<bool>(image_); };

sk_sp<SkImage> 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<SkImage> image_;
SkRect source_rect_;
SkRect destination_rect_;
SkRect logical_rect_;
};

class RasterCache {
Expand All @@ -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,
Expand Down
26 changes: 17 additions & 9 deletions flow/raster_cache_key.h
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@

#include <unordered_map>
#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"
Expand All @@ -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 {
Expand All @@ -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_;
}
};

Expand All @@ -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
Expand Down

0 comments on commit 1ef8cd2

Please sign in to comment.