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

Side by Side 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 unified diff | 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 »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
OLDNEW
1 // Copyright 2014 The Chromium Authors. All rights reserved. 1 // Copyright 2014 The Chromium Authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style license that can be 2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file. 3 // found in the LICENSE file.
4 4
5 #include "cc/playback/raster_source.h" 5 #include "cc/playback/raster_source.h"
6 6
7 #include <stddef.h> 7 #include <stddef.h>
8 8
9 #include "base/trace_event/trace_event.h" 9 #include "base/trace_event/trace_event.h"
10 #include "cc/base/region.h" 10 #include "cc/base/region.h"
11 #include "cc/debug/debug_colors.h" 11 #include "cc/debug/debug_colors.h"
12 #include "cc/playback/display_item_list.h" 12 #include "cc/playback/display_item_list.h"
13 #include "cc/playback/image_hijack_canvas.h" 13 #include "cc/playback/image_hijack_canvas.h"
14 #include "cc/playback/skip_image_canvas.h" 14 #include "cc/playback/skip_image_canvas.h"
15 #include "skia/ext/analysis_canvas.h" 15 #include "skia/ext/analysis_canvas.h"
16 #include "third_party/skia/include/core/SkCanvas.h" 16 #include "third_party/skia/include/core/SkCanvas.h"
17 #include "third_party/skia/include/core/SkClipStack.h"
17 #include "third_party/skia/include/core/SkPictureRecorder.h" 18 #include "third_party/skia/include/core/SkPictureRecorder.h"
18 #include "ui/gfx/geometry/rect_conversions.h" 19 #include "ui/gfx/geometry/rect_conversions.h"
19 20
20 namespace cc { 21 namespace cc {
21 22
22 scoped_refptr<RasterSource> RasterSource::CreateFromRecordingSource( 23 scoped_refptr<RasterSource> RasterSource::CreateFromRecordingSource(
23 const RecordingSource* other, 24 const RecordingSource* other,
24 bool can_use_lcd_text) { 25 bool can_use_lcd_text) {
25 return make_scoped_refptr(new RasterSource(other, can_use_lcd_text)); 26 return make_scoped_refptr(new RasterSource(other, can_use_lcd_text));
26 } 27 }
(...skipping 34 matching lines...) Expand 10 before | Expand all | Expand 10 after
61 } 62 }
62 63
63 RasterSource::~RasterSource() { 64 RasterSource::~RasterSource() {
64 } 65 }
65 66
66 void RasterSource::PlaybackToCanvas(SkCanvas* raster_canvas, 67 void RasterSource::PlaybackToCanvas(SkCanvas* raster_canvas,
67 const gfx::Rect& canvas_bitmap_rect, 68 const gfx::Rect& canvas_bitmap_rect,
68 const gfx::Rect& canvas_playback_rect, 69 const gfx::Rect& canvas_playback_rect,
69 float contents_scale, 70 float contents_scale,
70 const PlaybackSettings& settings) const { 71 const PlaybackSettings& settings) const {
71 if (!settings.playback_to_shared_canvas) { 72 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
72 PrepareForPlaybackToCanvas(raster_canvas, canvas_bitmap_rect, 73 if (!canvas_playback_rect.IsEmpty() &&
73 canvas_playback_rect, contents_scale); 74 !raster_bounds.intersect(gfx::RectToSkIRect(canvas_playback_rect)))
74 } 75 return;
76
77 raster_canvas->save();
78 raster_canvas->translate(-canvas_bitmap_rect.x(), -canvas_bitmap_rect.y());
79 raster_canvas->clipRect(SkRect::MakeFromIRect(raster_bounds));
80 raster_canvas->scale(contents_scale, contents_scale);
81 PlaybackToCanvas(raster_canvas, settings);
82 raster_canvas->restore();
83 }
84
85 void RasterSource::PlaybackToCanvas(SkCanvas* raster_canvas,
86 const PlaybackSettings& settings) const {
87 if (!settings.playback_to_shared_canvas)
88 PrepareForPlaybackToCanvas(raster_canvas);
75 89
76 if (settings.skip_images) { 90 if (settings.skip_images) {
77 SkipImageCanvas canvas(raster_canvas); 91 SkipImageCanvas canvas(raster_canvas);
78 RasterCommon(&canvas, nullptr, canvas_bitmap_rect, canvas_playback_rect, 92 RasterCommon(&canvas, nullptr);
79 contents_scale);
80 } else if (settings.use_image_hijack_canvas) { 93 } else if (settings.use_image_hijack_canvas) {
81 const SkImageInfo& info = raster_canvas->imageInfo(); 94 const SkImageInfo& info = raster_canvas->imageInfo();
82 95
83 ImageHijackCanvas canvas(info.width(), info.height(), 96 ImageHijackCanvas canvas(info.width(), info.height(),
84 image_decode_controller_); 97 image_decode_controller_);
85 // Before adding the canvas, make sure that the ImageHijackCanvas is aware 98 // Before adding the canvas, make sure that the ImageHijackCanvas is aware
86 // of the current transform, which may affect the clip bounds. Since we 99 // of the current transform and clip, which may affect the clip bounds.
87 // query the clip bounds of the current canvas to get the list of draw 100 // Since we query the clip bounds of the current canvas to get the list of
88 // commands to process, this is important to produce correct content. 101 // draw commands to process, this is important to produce correct content.
102 SkIRect raster_bounds;
103 raster_canvas->getClipDeviceBounds(&raster_bounds);
104 canvas.clipRect(SkRect::MakeFromIRect(raster_bounds));
89 canvas.setMatrix(raster_canvas->getTotalMatrix()); 105 canvas.setMatrix(raster_canvas->getTotalMatrix());
90 canvas.addCanvas(raster_canvas); 106 canvas.addCanvas(raster_canvas);
91 107
92 RasterCommon(&canvas, nullptr, canvas_bitmap_rect, canvas_playback_rect, 108 RasterCommon(&canvas, nullptr);
93 contents_scale);
94 } else { 109 } else {
95 RasterCommon(raster_canvas, nullptr, canvas_bitmap_rect, 110 RasterCommon(raster_canvas, nullptr);
96 canvas_playback_rect, contents_scale);
97 } 111 }
98 } 112 }
99 113
100 void RasterSource::PrepareForPlaybackToCanvas( 114 void RasterSource::PrepareForPlaybackToCanvas(SkCanvas* canvas) const {
101 SkCanvas* canvas,
102 const gfx::Rect& canvas_bitmap_rect,
103 const gfx::Rect& canvas_playback_rect,
104 float contents_scale) const {
105 // TODO(hendrikw): See if we can split this up into separate functions. 115 // TODO(hendrikw): See if we can split this up into separate functions.
106 bool partial_update = canvas_bitmap_rect != canvas_playback_rect;
107 116
108 if (!partial_update) 117 if (canvas->getClipStack()->quickContains(
118 SkRect::MakeFromIRect(canvas->imageInfo().bounds()))) {
109 canvas->discard(); 119 canvas->discard();
110 if (clear_canvas_with_debug_color_) {
111 // Any non-painted areas in the content bounds will be left in this color.
112 if (!partial_update) {
113 canvas->clear(DebugColors::NonPaintedFillColor());
114 } else {
115 canvas->save();
116 canvas->clipRect(gfx::RectToSkRect(
117 canvas_playback_rect - canvas_bitmap_rect.OffsetFromOrigin()));
118 canvas->drawColor(DebugColors::NonPaintedFillColor());
119 canvas->restore();
120 }
121 } 120 }
122 121
123 // If this raster source has opaque contents, it is guaranteeing that it will 122 // If this raster source has opaque contents, it is guaranteeing that it will
124 // draw an opaque rect the size of the layer. If it is not, then we must 123 // draw an opaque rect the size of the layer. If it is not, then we must
125 // clear this canvas ourselves. 124 // clear this canvas ourselves.
126 if (requires_clear_) { 125 if (requires_clear_) {
127 TRACE_EVENT_INSTANT0("cc", "SkCanvas::clear", TRACE_EVENT_SCOPE_THREAD); 126 canvas->clear(SK_ColorTRANSPARENT);
128 // Clearing is about ~4x faster than drawing a rect even if the content 127 return;
129 // isn't covering a majority of the canvas. 128 }
130 if (!partial_update) {
131 canvas->clear(SK_ColorTRANSPARENT);
132 } else {
133 canvas->save();
134 canvas->clipRect(gfx::RectToSkRect(
135 canvas_playback_rect - canvas_bitmap_rect.OffsetFromOrigin()));
136 canvas->drawColor(SK_ColorTRANSPARENT, SkXfermode::kClear_Mode);
137 canvas->restore();
138 }
139 } else {
140 // Even if completely covered, for rasterizations that touch the edge of the
141 // layer, we also need to raster the background color underneath the last
142 // texel (since the recording won't cover it) and outside the last texel
143 // (due to linear filtering when using this texture).
144 gfx::Rect content_rect =
145 gfx::ScaleToEnclosingRect(gfx::Rect(size_), contents_scale);
146 129
147 // The final texel of content may only be partially covered by a 130 if (clear_canvas_with_debug_color_)
148 // rasterization; this rect represents the content rect that is fully 131 canvas->clear(DebugColors::NonPaintedFillColor());
149 // covered by content.
150 gfx::Rect deflated_content_rect = content_rect;
151 deflated_content_rect.Inset(0, 0, 1, 1);
152 deflated_content_rect.Intersect(canvas_playback_rect);
153 if (!deflated_content_rect.Contains(canvas_playback_rect)) {
154 if (clear_canvas_with_debug_color_) {
155 // Any non-painted areas outside of the content bounds are left in
156 // this color. If this is seen then it means that cc neglected to
157 // rerasterize a tile that used to intersect with the content rect
158 // after the content bounds grew.
159 canvas->save();
160 canvas->translate(-canvas_bitmap_rect.x(), -canvas_bitmap_rect.y());
161 canvas->clipRect(gfx::RectToSkRect(content_rect),
162 SkRegion::kDifference_Op);
163 canvas->drawColor(DebugColors::MissingResizeInvalidations(),
164 SkXfermode::kSrc_Mode);
165 canvas->restore();
166 }
167 132
168 // Drawing at most 2 x 2 x (canvas width + canvas height) texels is 2-3X 133 // If the canvas wants us to raster with complex transform, it is hard to
169 // faster than clearing, so special case this. 134 // determine the exact region we must clear. Just clear everything.
170 canvas->save(); 135 // TODO(trchen): Optimize the common case that transformed content bounds
171 canvas->translate(-canvas_bitmap_rect.x(), -canvas_bitmap_rect.y()); 136 // covers the whole clip region.
172 gfx::Rect inflated_content_rect = content_rect; 137 if (!canvas->getTotalMatrix().rectStaysRect()) {
173 // Only clear edges that will be inside the canvas_playback_rect, else we 138 canvas->clear(SK_ColorTRANSPARENT);
174 // clear things that are still valid from a previous raster. 139 return;
175 inflated_content_rect.Inset(0, 0, -1, -1);
176 inflated_content_rect.Intersect(canvas_playback_rect);
177 canvas->clipRect(gfx::RectToSkRect(inflated_content_rect),
178 SkRegion::kReplace_Op);
179 canvas->clipRect(gfx::RectToSkRect(deflated_content_rect),
180 SkRegion::kDifference_Op);
181 canvas->drawColor(background_color_, SkXfermode::kSrc_Mode);
182 canvas->restore();
183 }
184 } 140 }
141
142 SkRect content_device_rect;
143 canvas->getTotalMatrix().mapRect(
144 &content_device_rect, SkRect::MakeWH(size_.width(), size_.height()));
145
146 // The final texel of content may only be partially covered by a
147 // rasterization; this rect represents the content rect that is fully
148 // covered by content.
149 SkIRect opaque_rect;
150 content_device_rect.roundIn(&opaque_rect);
151
152 SkIRect raster_bounds;
153 canvas->getClipDeviceBounds(&raster_bounds);
154
155 if (opaque_rect.contains(raster_bounds))
156 return;
157
158 // Even if completely covered, for rasterizations that touch the edge of the
159 // layer, we also need to raster the background color underneath the last
160 // texel (since the recording won't cover it) and outside the last texel
161 // (due to linear filtering when using this texture).
162 SkIRect interest_rect;
163 content_device_rect.roundOut(&interest_rect);
164 interest_rect.outset(1, 1);
165
166 if (clear_canvas_with_debug_color_) {
167 // Any non-painted areas outside of the content bounds are left in
168 // this color. If this is seen then it means that cc neglected to
169 // rerasterize a tile that used to intersect with the content rect
170 // after the content bounds grew.
171 canvas->save();
172 // Use clipRegion to bypass CTM because the rects are device rects.
173 SkRegion interest_region;
174 interest_region.setRect(interest_rect);
175 canvas->clipRegion(interest_region, SkRegion::kDifference_Op);
176 canvas->clear(DebugColors::MissingResizeInvalidations());
177 canvas->restore();
178 }
179
180 // 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.
181 // faster than clearing, so special case this.
182 canvas->save();
183 // Use clipRegion to bypass CTM because the rects are device rects.
184 SkRegion interest_region;
185 interest_region.setRect(interest_rect);
186 interest_region.op(opaque_rect, SkRegion::kDifference_Op);
187 canvas->clipRegion(interest_region);
188 canvas->clear(background_color_);
189 canvas->restore();
185 } 190 }
186 191
187 void RasterSource::RasterCommon(SkCanvas* canvas, 192 void RasterSource::RasterCommon(SkCanvas* canvas,
188 SkPicture::AbortCallback* callback, 193 SkPicture::AbortCallback* callback) const {
189 const gfx::Rect& canvas_bitmap_rect,
190 const gfx::Rect& canvas_playback_rect,
191 float contents_scale) const {
192 canvas->translate(-canvas_bitmap_rect.x(), -canvas_bitmap_rect.y());
193 gfx::Rect content_rect =
194 gfx::ScaleToEnclosingRect(gfx::Rect(size_), contents_scale);
195 content_rect.Intersect(canvas_playback_rect);
196
197 canvas->clipRect(gfx::RectToSkRect(content_rect), SkRegion::kIntersect_Op);
198
199 DCHECK(display_list_.get()); 194 DCHECK(display_list_.get());
200 gfx::Rect canvas_target_playback_rect =
201 canvas_playback_rect - canvas_bitmap_rect.OffsetFromOrigin();
202 int repeat_count = std::max(1, slow_down_raster_scale_factor_for_debug_); 195 int repeat_count = std::max(1, slow_down_raster_scale_factor_for_debug_);
203 for (int i = 0; i < repeat_count; ++i) { 196 for (int i = 0; i < repeat_count; ++i)
204 display_list_->Raster(canvas, callback, canvas_target_playback_rect, 197 display_list_->Raster(canvas, callback);
205 contents_scale);
206 }
207 } 198 }
208 199
209 sk_sp<SkPicture> RasterSource::GetFlattenedPicture() { 200 sk_sp<SkPicture> RasterSource::GetFlattenedPicture() {
210 TRACE_EVENT0("cc", "RasterSource::GetFlattenedPicture"); 201 TRACE_EVENT0("cc", "RasterSource::GetFlattenedPicture");
211 202
212 gfx::Rect display_list_rect(size_);
213 SkPictureRecorder recorder; 203 SkPictureRecorder recorder;
214 SkCanvas* canvas = recorder.beginRecording(display_list_rect.width(), 204 SkCanvas* canvas = recorder.beginRecording(size_.width(), size_.height());
215 display_list_rect.height()); 205 if (!size_.IsEmpty()) {
216 if (!display_list_rect.IsEmpty()) { 206 PrepareForPlaybackToCanvas(canvas);
217 PrepareForPlaybackToCanvas(canvas, display_list_rect, display_list_rect, 207 RasterCommon(canvas, nullptr);
218 1.f);
219 RasterCommon(canvas, nullptr, display_list_rect, display_list_rect, 1.f);
220 } 208 }
221 209
222 return recorder.finishRecordingAsPicture(); 210 return recorder.finishRecordingAsPicture();
223 } 211 }
224 212
225 size_t RasterSource::GetPictureMemoryUsage() const { 213 size_t RasterSource::GetPictureMemoryUsage() const {
226 if (!display_list_) 214 if (!display_list_)
227 return 0; 215 return 0;
228 return display_list_->ApproximateMemoryUsage() + 216 return display_list_->ApproximateMemoryUsage() +
229 painter_reported_memory_usage_; 217 painter_reported_memory_usage_;
230 } 218 }
231 219
232 bool RasterSource::PerformSolidColorAnalysis(const gfx::Rect& content_rect, 220 bool RasterSource::PerformSolidColorAnalysis(const gfx::Rect& content_rect,
233 float contents_scale, 221 float contents_scale,
234 SkColor* color) const { 222 SkColor* color) const {
235 TRACE_EVENT0("cc", "RasterSource::PerformSolidColorAnalysis"); 223 TRACE_EVENT0("cc", "RasterSource::PerformSolidColorAnalysis");
236 224
237 gfx::Rect layer_rect = 225 gfx::Rect layer_rect =
238 gfx::ScaleToEnclosingRect(content_rect, 1.0f / contents_scale); 226 gfx::ScaleToEnclosingRect(content_rect, 1.0f / contents_scale);
239 227
240 layer_rect.Intersect(gfx::Rect(size_)); 228 layer_rect.Intersect(gfx::Rect(size_));
241 skia::AnalysisCanvas canvas(layer_rect.width(), layer_rect.height()); 229 skia::AnalysisCanvas canvas(layer_rect.width(), layer_rect.height());
242 RasterCommon(&canvas, &canvas, layer_rect, layer_rect, 1.0f); 230 canvas.translate(-layer_rect.x(), -layer_rect.y());
231 RasterCommon(&canvas, &canvas);
243 return canvas.GetColorIfSolid(color); 232 return canvas.GetColorIfSolid(color);
244 } 233 }
245 234
246 void RasterSource::GetDiscardableImagesInRect( 235 void RasterSource::GetDiscardableImagesInRect(
247 const gfx::Rect& layer_rect, 236 const gfx::Rect& layer_rect,
248 float raster_scale, 237 float raster_scale,
249 std::vector<DrawImage>* images) const { 238 std::vector<DrawImage>* images) const {
250 DCHECK_EQ(0u, images->size()); 239 DCHECK_EQ(0u, images->size());
251 display_list_->GetDiscardableImagesInRect(layer_rect, raster_scale, images); 240 display_list_->GetDiscardableImagesInRect(layer_rect, raster_scale, images);
252 } 241 }
(...skipping 59 matching lines...) Expand 10 before | Expand all | Expand 10 after
312 DCHECK(image_decode_controller); 301 DCHECK(image_decode_controller);
313 image_decode_controller_ = image_decode_controller; 302 image_decode_controller_ = image_decode_controller;
314 } 303 }
315 304
316 RasterSource::PlaybackSettings::PlaybackSettings() 305 RasterSource::PlaybackSettings::PlaybackSettings()
317 : playback_to_shared_canvas(false), 306 : playback_to_shared_canvas(false),
318 skip_images(false), 307 skip_images(false),
319 use_image_hijack_canvas(true) {} 308 use_image_hijack_canvas(true) {}
320 309
321 } // namespace cc 310 } // namespace cc
OLDNEW
« 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