Commit dc956b25 authored by Xida Chen's avatar Xida Chen Committed by Commit Bot

[OT-PW] Implement RasterWithFlags for PaintWorklet

This CL implements the rasterization part for a paint image that is
generated by PaintWorklet, which is the DrawImageOp::RasterWithFlags.

Bug: 907897
Change-Id: I993d29035f1ad09e7cbe3caecc5445876078ac01
Reviewed-on: https://chromium-review.googlesource.com/c/1426015Reviewed-by: default avatarKhushal <khushalsagar@chromium.org>
Reviewed-by: default avatarvmpstr <vmpstr@chromium.org>
Commit-Queue: Xida Chen <xidachen@chromium.org>
Cr-Commit-Position: refs/heads/master@{#633815}
parent 48ef5e92
...@@ -28,6 +28,14 @@ DrawImage::DrawImage() ...@@ -28,6 +28,14 @@ DrawImage::DrawImage()
scale_(SkSize::Make(1.f, 1.f)), scale_(SkSize::Make(1.f, 1.f)),
matrix_is_decomposable_(true) {} matrix_is_decomposable_(true) {}
DrawImage::DrawImage(PaintImage image)
: paint_image_(std::move(image)),
src_rect_(
SkIRect::MakeXYWH(0, 0, paint_image_.width(), paint_image_.height())),
filter_quality_(kNone_SkFilterQuality),
scale_(SkSize::Make(1.f, 1.f)),
matrix_is_decomposable_(true) {}
DrawImage::DrawImage(PaintImage image, DrawImage::DrawImage(PaintImage image,
const SkIRect& src_rect, const SkIRect& src_rect,
SkFilterQuality filter_quality, SkFilterQuality filter_quality,
......
...@@ -24,6 +24,7 @@ namespace cc { ...@@ -24,6 +24,7 @@ namespace cc {
class CC_PAINT_EXPORT DrawImage { class CC_PAINT_EXPORT DrawImage {
public: public:
DrawImage(); DrawImage();
explicit DrawImage(PaintImage image);
DrawImage(PaintImage image, DrawImage(PaintImage image,
const SkIRect& src_rect, const SkIRect& src_rect,
SkFilterQuality filter_quality, SkFilterQuality filter_quality,
......
...@@ -1205,8 +1205,22 @@ void DrawImageOp::RasterWithFlags(const DrawImageOp* op, ...@@ -1205,8 +1205,22 @@ void DrawImageOp::RasterWithFlags(const DrawImageOp* op,
const PaintFlags* flags, const PaintFlags* flags,
SkCanvas* canvas, SkCanvas* canvas,
const PlaybackParams& params) { const PlaybackParams& params) {
// TODO(crbug.com/931704): make sure to support the case where paint worklet
// generated images are used in other raster work such as canvas2d.
SkPaint paint = flags ? flags->ToSkPaint() : SkPaint(); SkPaint paint = flags ? flags->ToSkPaint() : SkPaint();
if (op->image.IsPaintWorklet()) {
DCHECK(params.image_provider);
ImageProvider::ScopedResult result =
params.image_provider->GetRasterContent(DrawImage(op->image));
DCHECK(IsScaleAdjustmentIdentity(op->scale_adjustment));
SkAutoCanvasRestore save_restore(canvas, true);
canvas->translate(op->left, op->top);
result.paint_record()->Playback(canvas, params);
return;
}
if (!params.image_provider) { if (!params.image_provider) {
const bool needs_scale = !IsScaleAdjustmentIdentity(op->scale_adjustment); const bool needs_scale = !IsScaleAdjustmentIdentity(op->scale_adjustment);
SkAutoCanvasRestore save_restore(canvas, needs_scale); SkAutoCanvasRestore save_restore(canvas, needs_scale);
...@@ -1245,6 +1259,7 @@ void DrawImageOp::RasterWithFlags(const DrawImageOp* op, ...@@ -1245,6 +1259,7 @@ void DrawImageOp::RasterWithFlags(const DrawImageOp* op,
canvas->drawImage(decoded_image.image().get(), op->left, op->top, &paint); canvas->drawImage(decoded_image.image().get(), op->left, op->top, &paint);
} }
// TODO(xidachen): ensure paint worklet generated images are correctly handled.
void DrawImageRectOp::RasterWithFlags(const DrawImageRectOp* op, void DrawImageRectOp::RasterWithFlags(const DrawImageRectOp* op,
const PaintFlags* flags, const PaintFlags* flags,
SkCanvas* canvas, SkCanvas* canvas,
...@@ -2393,8 +2408,6 @@ void PaintOpBuffer::Playback(SkCanvas* canvas, ...@@ -2393,8 +2408,6 @@ void PaintOpBuffer::Playback(SkCanvas* canvas,
PlaybackParams new_params(params.image_provider, canvas->getTotalMatrix(), PlaybackParams new_params(params.image_provider, canvas->getTotalMatrix(),
params.custom_callback, params.custom_callback,
params.did_draw_op_callback); params.did_draw_op_callback);
// TODO(xidachen): retrieve the PaintRecord stored in PaintWorkletImageCache,
// from the PaintWorkletImageProvider in the params.
for (PlaybackFoldingIterator iter(this, offsets); iter; ++iter) { for (PlaybackFoldingIterator iter(this, offsets); iter; ++iter) {
const PaintOp* op = *iter; const PaintOp* op = *iter;
......
...@@ -20,6 +20,7 @@ ...@@ -20,6 +20,7 @@
#include "cc/test/paint_op_helper.h" #include "cc/test/paint_op_helper.h"
#include "cc/test/skia_common.h" #include "cc/test/skia_common.h"
#include "cc/test/test_options_provider.h" #include "cc/test/test_options_provider.h"
#include "cc/test/test_paint_worklet_input.h"
#include "cc/test/test_skcanvas.h" #include "cc/test/test_skcanvas.h"
#include "cc/test/transfer_cache_test_helper.h" #include "cc/test/transfer_cache_test_helper.h"
#include "testing/gtest/include/gtest/gtest.h" #include "testing/gtest/include/gtest/gtest.h"
...@@ -429,6 +430,15 @@ TEST(PaintOpBufferTest, DiscardableImagesTracking_DrawImage) { ...@@ -429,6 +430,15 @@ TEST(PaintOpBufferTest, DiscardableImagesTracking_DrawImage) {
EXPECT_TRUE(buffer.HasDiscardableImages()); EXPECT_TRUE(buffer.HasDiscardableImages());
} }
TEST(PaintOpBufferTest, DiscardableImagesTracking_PaintWorkletImage) {
scoped_refptr<TestPaintWorkletInput> input =
base::MakeRefCounted<TestPaintWorkletInput>(gfx::SizeF(32.0f, 32.0f));
PaintOpBuffer buffer;
PaintImage image = CreatePaintWorkletPaintImage(input);
buffer.push<DrawImageOp>(image, SkIntToScalar(0), SkIntToScalar(0), nullptr);
EXPECT_TRUE(buffer.HasDiscardableImages());
}
TEST(PaintOpBufferTest, DiscardableImagesTracking_DrawImageRect) { TEST(PaintOpBufferTest, DiscardableImagesTracking_DrawImageRect) {
PaintOpBuffer buffer; PaintOpBuffer buffer;
PaintImage image = CreateDiscardablePaintImage(gfx::Size(100, 100)); PaintImage image = CreateDiscardablePaintImage(gfx::Size(100, 100));
...@@ -2711,9 +2721,16 @@ class MockImageProvider : public ImageProvider { ...@@ -2711,9 +2721,16 @@ class MockImageProvider : public ImageProvider {
~MockImageProvider() override = default; ~MockImageProvider() override = default;
void DoNothing() {}
ImageProvider::ScopedResult GetRasterContent( ImageProvider::ScopedResult GetRasterContent(
const DrawImage& draw_image) override { const DrawImage& draw_image) override {
DCHECK(!draw_image.paint_image().IsPaintWorklet()); if (draw_image.paint_image().IsPaintWorklet()) {
auto callback =
base::BindOnce(&MockImageProvider::DoNothing, base::Unretained(this));
return ScopedResult(record_, std::move(callback));
}
if (fail_all_decodes_) if (fail_all_decodes_)
return ImageProvider::ScopedResult(); return ImageProvider::ScopedResult();
...@@ -2726,12 +2743,15 @@ class MockImageProvider : public ImageProvider { ...@@ -2726,12 +2743,15 @@ class MockImageProvider : public ImageProvider {
quality_[i], true)); quality_[i], true));
} }
void SetRecord(PaintRecord* record) { record_ = record; }
private: private:
std::vector<SkSize> src_rect_offset_; std::vector<SkSize> src_rect_offset_;
std::vector<SkSize> scale_; std::vector<SkSize> scale_;
std::vector<SkFilterQuality> quality_; std::vector<SkFilterQuality> quality_;
size_t index_ = 0; size_t index_ = 0;
bool fail_all_decodes_ = false; bool fail_all_decodes_ = false;
PaintRecord* record_;
}; };
TEST(PaintOpBufferTest, SkipsOpsOutsideClip) { TEST(PaintOpBufferTest, SkipsOpsOutsideClip) {
...@@ -2827,6 +2847,78 @@ MATCHER_P2(MatchesShader, flags, scale, "") { ...@@ -2827,6 +2847,78 @@ MATCHER_P2(MatchesShader, flags, scale, "") {
return true; return true;
} }
TEST(PaintOpBufferTest, RasterPaintWorkletImage1) {
PaintOpBuffer paint_worklet_buffer;
PaintFlags noop_flags;
SkRect savelayer_rect = SkRect::MakeXYWH(0, 0, 100, 100);
paint_worklet_buffer.push<TranslateOp>(8.0f, 8.0f);
paint_worklet_buffer.push<SaveLayerOp>(&savelayer_rect, &noop_flags);
PaintFlags draw_flags;
draw_flags.setColor(0u);
SkRect rect = SkRect::MakeXYWH(0, 0, 100, 100);
paint_worklet_buffer.push<DrawRectOp>(rect, draw_flags);
MockImageProvider provider;
provider.SetRecord(&paint_worklet_buffer);
PaintOpBuffer blink_buffer;
scoped_refptr<TestPaintWorkletInput> input =
base::MakeRefCounted<TestPaintWorkletInput>(gfx::SizeF(100, 100));
PaintImage image = CreatePaintWorkletPaintImage(input);
blink_buffer.push<DrawImageOp>(image, 0.0f, 0.0f, nullptr);
testing::StrictMock<MockCanvas> canvas;
testing::Sequence s;
EXPECT_CALL(canvas, willSave()).InSequence(s);
EXPECT_CALL(canvas, didConcat(SkMatrix::MakeTrans(8.0f, 8.0f)));
EXPECT_CALL(canvas, OnSaveLayer()).InSequence(s);
EXPECT_CALL(canvas, OnDrawRectWithColor(0u));
EXPECT_CALL(canvas, willRestore()).InSequence(s);
EXPECT_CALL(canvas, willRestore()).InSequence(s);
blink_buffer.Playback(&canvas, PlaybackParams(&provider));
}
TEST(PaintOpBufferTest, RasterPaintWorkletImage2) {
PaintOpBuffer paint_worklet_buffer;
PaintFlags noop_flags;
SkRect savelayer_rect = SkRect::MakeXYWH(0, 0, 10, 10);
paint_worklet_buffer.push<SaveLayerOp>(&savelayer_rect, &noop_flags);
PaintFlags draw_flags;
draw_flags.setFilterQuality(kLow_SkFilterQuality);
PaintImage paint_image = CreateDiscardablePaintImage(gfx::Size(10, 10));
paint_worklet_buffer.push<DrawImageOp>(paint_image, 0.0f, 0.0f, &draw_flags);
std::vector<SkSize> src_rect_offset = {SkSize::MakeEmpty()};
std::vector<SkSize> scale_adjustment = {SkSize::Make(0.2f, 0.2f)};
std::vector<SkFilterQuality> quality = {kHigh_SkFilterQuality};
MockImageProvider provider(src_rect_offset, scale_adjustment, quality);
provider.SetRecord(&paint_worklet_buffer);
PaintOpBuffer blink_buffer;
scoped_refptr<TestPaintWorkletInput> input =
base::MakeRefCounted<TestPaintWorkletInput>(gfx::SizeF(100, 100));
PaintImage image = CreatePaintWorkletPaintImage(input);
blink_buffer.push<DrawImageOp>(image, 5.0f, 7.0f, nullptr);
testing::StrictMock<MockCanvas> canvas;
testing::Sequence s;
EXPECT_CALL(canvas, willSave()).InSequence(s);
EXPECT_CALL(canvas, didConcat(SkMatrix::MakeTrans(5.0f, 7.0f)));
EXPECT_CALL(canvas, OnSaveLayer()).InSequence(s);
EXPECT_CALL(canvas, willSave()).InSequence(s);
EXPECT_CALL(canvas, didConcat(MatchesInvScale(scale_adjustment[0])));
EXPECT_CALL(canvas, onDrawImage(NonLazyImage(), 0.0f, 0.0f,
MatchesQuality(quality[0])));
EXPECT_CALL(canvas, willRestore()).InSequence(s);
EXPECT_CALL(canvas, willRestore()).InSequence(s);
EXPECT_CALL(canvas, willRestore()).InSequence(s);
blink_buffer.Playback(&canvas, PlaybackParams(&provider));
}
TEST(PaintOpBufferTest, ReplacesImagesFromProvider) { TEST(PaintOpBufferTest, ReplacesImagesFromProvider) {
std::vector<SkSize> src_rect_offset = { std::vector<SkSize> src_rect_offset = {
SkSize::MakeEmpty(), SkSize::Make(2.0f, 2.0f), SkSize::Make(3.0f, 3.0f)}; SkSize::MakeEmpty(), SkSize::Make(2.0f, 2.0f), SkSize::Make(3.0f, 3.0f)};
......
...@@ -49,6 +49,8 @@ scoped_refptr<TileTask> PaintWorkletImageCache::GetTaskForPaintWorkletImage( ...@@ -49,6 +49,8 @@ scoped_refptr<TileTask> PaintWorkletImageCache::GetTaskForPaintWorkletImage(
// Do check the cache first. If there is already a cache entry for this input, // Do check the cache first. If there is already a cache entry for this input,
// then there is no need to call the Paint() function. // then there is no need to call the Paint() function.
void PaintWorkletImageCache::PaintImageInTask(const PaintImage& paint_image) { void PaintWorkletImageCache::PaintImageInTask(const PaintImage& paint_image) {
// TODO(xidachen): ensure that the canvas operations in the PaintRecord
// matches the PaintGeneratedImage::Draw.
sk_sp<PaintRecord> record = painter_->Paint(); sk_sp<PaintRecord> record = painter_->Paint();
records_[paint_image.paint_worklet_input()] = records_[paint_image.paint_worklet_input()] =
PaintWorkletImageCacheValue(std::move(record), 0); PaintWorkletImageCacheValue(std::move(record), 0);
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment