Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(2730)

Unified Diff: cc/playback/raster_source.cc

Issue 2075873002: Support general raster matrix for RasterSource and DisplayItemList (Closed) Base URL: https://chromium.googlesource.com/chromium/src.git@master
Patch Set: fix a bug in PrepareForPlaybackToCanvas and fix cc_unittests Created 4 years, 6 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View side-by-side diff with in-line comments
Download patch
« no previous file with comments | « cc/playback/raster_source.h ('k') | cc/playback/transform_display_item.h » ('j') | no next file with comments »
Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
Index: cc/playback/raster_source.cc
diff --git a/cc/playback/raster_source.cc b/cc/playback/raster_source.cc
index 292d92512f134ed6054ae4d1664256b0c82f56fd..d464779c3fef57ee577b1e2c3df8783826dea5dd 100644
--- a/cc/playback/raster_source.cc
+++ b/cc/playback/raster_source.cc
@@ -14,6 +14,7 @@
#include "cc/playback/skip_image_canvas.h"
#include "skia/ext/analysis_canvas.h"
#include "third_party/skia/include/core/SkCanvas.h"
+#include "third_party/skia/include/core/SkClipStack.h"
#include "third_party/skia/include/core/SkPictureRecorder.h"
#include "ui/gfx/geometry/rect_conversions.h"
@@ -68,155 +69,142 @@ void RasterSource::PlaybackToCanvas(SkCanvas* raster_canvas,
const gfx::Rect& canvas_playback_rect,
float contents_scale,
const PlaybackSettings& settings) const {
- if (!settings.playback_to_shared_canvas) {
- PrepareForPlaybackToCanvas(raster_canvas, canvas_bitmap_rect,
- canvas_playback_rect, contents_scale);
- }
+ SkIRect raster_bounds = gfx::RectToSkIRect(canvas_bitmap_rect);
ajuma 2016/06/23 17:57:37 Is it worth intersecting this with size_?
trchen 2016/06/23 22:18:24 (I assume you meant interest_rect as in PrepareFor
+ if (!canvas_playback_rect.IsEmpty() &&
+ !raster_bounds.intersect(gfx::RectToSkIRect(canvas_playback_rect)))
+ return;
+
+ raster_canvas->save();
+ raster_canvas->translate(-canvas_bitmap_rect.x(), -canvas_bitmap_rect.y());
+ raster_canvas->clipRect(SkRect::MakeFromIRect(raster_bounds));
+ raster_canvas->scale(contents_scale, contents_scale);
+ PlaybackToCanvas(raster_canvas, settings);
+ raster_canvas->restore();
+}
+
+void RasterSource::PlaybackToCanvas(SkCanvas* raster_canvas,
+ const PlaybackSettings& settings) const {
+ if (!settings.playback_to_shared_canvas)
+ PrepareForPlaybackToCanvas(raster_canvas);
if (settings.skip_images) {
SkipImageCanvas canvas(raster_canvas);
- RasterCommon(&canvas, nullptr, canvas_bitmap_rect, canvas_playback_rect,
- contents_scale);
+ RasterCommon(&canvas, nullptr);
} else if (settings.use_image_hijack_canvas) {
const SkImageInfo& info = raster_canvas->imageInfo();
ImageHijackCanvas canvas(info.width(), info.height(),
image_decode_controller_);
// Before adding the canvas, make sure that the ImageHijackCanvas is aware
- // of the current transform, which may affect the clip bounds. Since we
- // query the clip bounds of the current canvas to get the list of draw
- // commands to process, this is important to produce correct content.
+ // of the current transform and clip, which may affect the clip bounds.
+ // Since we query the clip bounds of the current canvas to get the list of
+ // draw commands to process, this is important to produce correct content.
+ SkIRect raster_bounds;
+ raster_canvas->getClipDeviceBounds(&raster_bounds);
+ canvas.clipRect(SkRect::MakeFromIRect(raster_bounds));
canvas.setMatrix(raster_canvas->getTotalMatrix());
canvas.addCanvas(raster_canvas);
- RasterCommon(&canvas, nullptr, canvas_bitmap_rect, canvas_playback_rect,
- contents_scale);
+ RasterCommon(&canvas, nullptr);
} else {
- RasterCommon(raster_canvas, nullptr, canvas_bitmap_rect,
- canvas_playback_rect, contents_scale);
+ RasterCommon(raster_canvas, nullptr);
}
}
-void RasterSource::PrepareForPlaybackToCanvas(
- SkCanvas* canvas,
- const gfx::Rect& canvas_bitmap_rect,
- const gfx::Rect& canvas_playback_rect,
- float contents_scale) const {
+void RasterSource::PrepareForPlaybackToCanvas(SkCanvas* canvas) const {
// TODO(hendrikw): See if we can split this up into separate functions.
- bool partial_update = canvas_bitmap_rect != canvas_playback_rect;
- if (!partial_update)
+ if (canvas->getClipStack()->quickContains(
+ SkRect::MakeFromIRect(canvas->imageInfo().bounds()))) {
canvas->discard();
- if (clear_canvas_with_debug_color_) {
- // Any non-painted areas in the content bounds will be left in this color.
- if (!partial_update) {
- canvas->clear(DebugColors::NonPaintedFillColor());
- } else {
- canvas->save();
- canvas->clipRect(gfx::RectToSkRect(
- canvas_playback_rect - canvas_bitmap_rect.OffsetFromOrigin()));
- canvas->drawColor(DebugColors::NonPaintedFillColor());
- canvas->restore();
- }
}
// If this raster source has opaque contents, it is guaranteeing that it will
// draw an opaque rect the size of the layer. If it is not, then we must
// clear this canvas ourselves.
if (requires_clear_) {
- TRACE_EVENT_INSTANT0("cc", "SkCanvas::clear", TRACE_EVENT_SCOPE_THREAD);
- // Clearing is about ~4x faster than drawing a rect even if the content
- // isn't covering a majority of the canvas.
- if (!partial_update) {
- canvas->clear(SK_ColorTRANSPARENT);
- } else {
- canvas->save();
- canvas->clipRect(gfx::RectToSkRect(
- canvas_playback_rect - canvas_bitmap_rect.OffsetFromOrigin()));
- canvas->drawColor(SK_ColorTRANSPARENT, SkXfermode::kClear_Mode);
- canvas->restore();
- }
- } else {
- // Even if completely covered, for rasterizations that touch the edge of the
- // layer, we also need to raster the background color underneath the last
- // texel (since the recording won't cover it) and outside the last texel
- // (due to linear filtering when using this texture).
- gfx::Rect content_rect =
- gfx::ScaleToEnclosingRect(gfx::Rect(size_), contents_scale);
-
- // The final texel of content may only be partially covered by a
- // rasterization; this rect represents the content rect that is fully
- // covered by content.
- gfx::Rect deflated_content_rect = content_rect;
- deflated_content_rect.Inset(0, 0, 1, 1);
- deflated_content_rect.Intersect(canvas_playback_rect);
- if (!deflated_content_rect.Contains(canvas_playback_rect)) {
- if (clear_canvas_with_debug_color_) {
- // Any non-painted areas outside of the content bounds are left in
- // this color. If this is seen then it means that cc neglected to
- // rerasterize a tile that used to intersect with the content rect
- // after the content bounds grew.
- canvas->save();
- canvas->translate(-canvas_bitmap_rect.x(), -canvas_bitmap_rect.y());
- canvas->clipRect(gfx::RectToSkRect(content_rect),
- SkRegion::kDifference_Op);
- canvas->drawColor(DebugColors::MissingResizeInvalidations(),
- SkXfermode::kSrc_Mode);
- canvas->restore();
- }
-
- // Drawing at most 2 x 2 x (canvas width + canvas height) texels is 2-3X
- // faster than clearing, so special case this.
- canvas->save();
- canvas->translate(-canvas_bitmap_rect.x(), -canvas_bitmap_rect.y());
- gfx::Rect inflated_content_rect = content_rect;
- // Only clear edges that will be inside the canvas_playback_rect, else we
- // clear things that are still valid from a previous raster.
- inflated_content_rect.Inset(0, 0, -1, -1);
- inflated_content_rect.Intersect(canvas_playback_rect);
- canvas->clipRect(gfx::RectToSkRect(inflated_content_rect),
- SkRegion::kReplace_Op);
- canvas->clipRect(gfx::RectToSkRect(deflated_content_rect),
- SkRegion::kDifference_Op);
- canvas->drawColor(background_color_, SkXfermode::kSrc_Mode);
- canvas->restore();
- }
+ canvas->clear(SK_ColorTRANSPARENT);
+ return;
}
-}
-void RasterSource::RasterCommon(SkCanvas* canvas,
- SkPicture::AbortCallback* callback,
- const gfx::Rect& canvas_bitmap_rect,
- const gfx::Rect& canvas_playback_rect,
- float contents_scale) const {
- canvas->translate(-canvas_bitmap_rect.x(), -canvas_bitmap_rect.y());
- gfx::Rect content_rect =
- gfx::ScaleToEnclosingRect(gfx::Rect(size_), contents_scale);
- content_rect.Intersect(canvas_playback_rect);
+ if (clear_canvas_with_debug_color_)
+ canvas->clear(DebugColors::NonPaintedFillColor());
+
+ // If the canvas wants us to raster with complex transform, it is hard to
+ // determine the exact region we must clear. Just clear everything.
+ // TODO(trchen): Optimize the common case that transformed content bounds
+ // covers the whole clip region.
+ if (!canvas->getTotalMatrix().rectStaysRect()) {
+ canvas->clear(SK_ColorTRANSPARENT);
+ return;
+ }
- canvas->clipRect(gfx::RectToSkRect(content_rect), SkRegion::kIntersect_Op);
+ SkRect content_device_rect;
+ canvas->getTotalMatrix().mapRect(
+ &content_device_rect, SkRect::MakeWH(size_.width(), size_.height()));
+ // The final texel of content may only be partially covered by a
+ // rasterization; this rect represents the content rect that is fully
+ // covered by content.
+ SkIRect opaque_rect;
+ content_device_rect.roundIn(&opaque_rect);
+
+ SkIRect raster_bounds;
+ canvas->getClipDeviceBounds(&raster_bounds);
+
+ if (opaque_rect.contains(raster_bounds))
+ return;
+
+ // Even if completely covered, for rasterizations that touch the edge of the
+ // layer, we also need to raster the background color underneath the last
+ // texel (since the recording won't cover it) and outside the last texel
+ // (due to linear filtering when using this texture).
+ SkIRect interest_rect;
+ content_device_rect.roundOut(&interest_rect);
+ interest_rect.outset(1, 1);
+
+ if (clear_canvas_with_debug_color_) {
+ // Any non-painted areas outside of the content bounds are left in
+ // this color. If this is seen then it means that cc neglected to
+ // rerasterize a tile that used to intersect with the content rect
+ // after the content bounds grew.
+ canvas->save();
+ // Use clipRegion to bypass CTM because the rects are device rects.
+ SkRegion interest_region;
+ interest_region.setRect(interest_rect);
+ canvas->clipRegion(interest_region, SkRegion::kDifference_Op);
+ canvas->clear(DebugColors::MissingResizeInvalidations());
+ canvas->restore();
+ }
+
+ // Drawing at most 2 x 2 x (canvas width + canvas height) texels is 2-3X
enne (OOO) 2016/08/29 20:22:52 This comment seems no longer true.
+ // faster than clearing, so special case this.
+ canvas->save();
+ // Use clipRegion to bypass CTM because the rects are device rects.
+ SkRegion interest_region;
+ interest_region.setRect(interest_rect);
+ interest_region.op(opaque_rect, SkRegion::kDifference_Op);
+ canvas->clipRegion(interest_region);
+ canvas->clear(background_color_);
+ canvas->restore();
+}
+
+void RasterSource::RasterCommon(SkCanvas* canvas,
+ SkPicture::AbortCallback* callback) const {
DCHECK(display_list_.get());
- gfx::Rect canvas_target_playback_rect =
- canvas_playback_rect - canvas_bitmap_rect.OffsetFromOrigin();
int repeat_count = std::max(1, slow_down_raster_scale_factor_for_debug_);
- for (int i = 0; i < repeat_count; ++i) {
- display_list_->Raster(canvas, callback, canvas_target_playback_rect,
- contents_scale);
- }
+ for (int i = 0; i < repeat_count; ++i)
+ display_list_->Raster(canvas, callback);
}
sk_sp<SkPicture> RasterSource::GetFlattenedPicture() {
TRACE_EVENT0("cc", "RasterSource::GetFlattenedPicture");
- gfx::Rect display_list_rect(size_);
SkPictureRecorder recorder;
- SkCanvas* canvas = recorder.beginRecording(display_list_rect.width(),
- display_list_rect.height());
- if (!display_list_rect.IsEmpty()) {
- PrepareForPlaybackToCanvas(canvas, display_list_rect, display_list_rect,
- 1.f);
- RasterCommon(canvas, nullptr, display_list_rect, display_list_rect, 1.f);
+ SkCanvas* canvas = recorder.beginRecording(size_.width(), size_.height());
+ if (!size_.IsEmpty()) {
+ PrepareForPlaybackToCanvas(canvas);
+ RasterCommon(canvas, nullptr);
}
return recorder.finishRecordingAsPicture();
@@ -239,7 +227,8 @@ bool RasterSource::PerformSolidColorAnalysis(const gfx::Rect& content_rect,
layer_rect.Intersect(gfx::Rect(size_));
skia::AnalysisCanvas canvas(layer_rect.width(), layer_rect.height());
- RasterCommon(&canvas, &canvas, layer_rect, layer_rect, 1.0f);
+ canvas.translate(-layer_rect.x(), -layer_rect.y());
+ RasterCommon(&canvas, &canvas);
return canvas.GetColorIfSolid(color);
}
« no previous file with comments | « cc/playback/raster_source.h ('k') | cc/playback/transform_display_item.h » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698