未验证 提交 1ef8cd2f 编写于 作者: L liyuqian 提交者: GitHub

Use drawImage for picture layer cache (#5315)

Fixes
1. https://github.com/flutter/flutter/issues/12148
2. most part of https://github.com/flutter/flutter/issues/17731 except some tiny AA diffs.
上级 87944d84
......@@ -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;
}
......
......@@ -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());
}
......
......@@ -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<SkSurface> 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;
......
......@@ -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 {
......@@ -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,
......
......@@ -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"
......@@ -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
......
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册