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

Side by Side Diff: cc/playback/raster_source.cc

Issue 2748263002: Move cc::DisplayItemList and related classes into cc/paint/ (Closed)
Patch Set: none Created 3 years, 9 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
OLDNEW
(Empty)
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
3 // found in the LICENSE file.
4
5 #include "cc/playback/raster_source.h"
6
7 #include <stddef.h>
8
9 #include "base/trace_event/trace_event.h"
10 #include "cc/base/math_util.h"
11 #include "cc/base/region.h"
12 #include "cc/debug/debug_colors.h"
13 #include "cc/debug/traced_value.h"
14 #include "cc/playback/display_item_list.h"
15 #include "cc/playback/image_hijack_canvas.h"
16 #include "cc/playback/skip_image_canvas.h"
17 #include "skia/ext/analysis_canvas.h"
18 #include "third_party/skia/include/core/SkCanvas.h"
19 #include "third_party/skia/include/core/SkPictureRecorder.h"
20 #include "ui/gfx/geometry/rect_conversions.h"
21
22 namespace cc {
23
24 scoped_refptr<RasterSource> RasterSource::CreateFromRecordingSource(
25 const RecordingSource* other,
26 bool can_use_lcd_text) {
27 return make_scoped_refptr(new RasterSource(other, can_use_lcd_text));
28 }
29
30 RasterSource::RasterSource(const RecordingSource* other, bool can_use_lcd_text)
31 : display_list_(other->display_list_),
32 painter_reported_memory_usage_(other->painter_reported_memory_usage_),
33 background_color_(other->background_color_),
34 requires_clear_(other->requires_clear_),
35 can_use_lcd_text_(can_use_lcd_text),
36 is_solid_color_(other->is_solid_color_),
37 solid_color_(other->solid_color_),
38 recorded_viewport_(other->recorded_viewport_),
39 size_(other->size_),
40 clear_canvas_with_debug_color_(other->clear_canvas_with_debug_color_),
41 slow_down_raster_scale_factor_for_debug_(
42 other->slow_down_raster_scale_factor_for_debug_),
43 image_decode_cache_(nullptr) {}
44
45 RasterSource::RasterSource(const RasterSource* other, bool can_use_lcd_text)
46 : display_list_(other->display_list_),
47 painter_reported_memory_usage_(other->painter_reported_memory_usage_),
48 background_color_(other->background_color_),
49 requires_clear_(other->requires_clear_),
50 can_use_lcd_text_(can_use_lcd_text),
51 is_solid_color_(other->is_solid_color_),
52 solid_color_(other->solid_color_),
53 recorded_viewport_(other->recorded_viewport_),
54 size_(other->size_),
55 clear_canvas_with_debug_color_(other->clear_canvas_with_debug_color_),
56 slow_down_raster_scale_factor_for_debug_(
57 other->slow_down_raster_scale_factor_for_debug_),
58 image_decode_cache_(other->image_decode_cache_) {}
59
60 RasterSource::~RasterSource() {
61 }
62
63 void RasterSource::PlaybackToCanvas(SkCanvas* raster_canvas,
64 const gfx::Rect& canvas_bitmap_rect,
65 const gfx::Rect& canvas_playback_rect,
66 float raster_scale,
67 const PlaybackSettings& settings) const {
68 SkIRect raster_bounds = gfx::RectToSkIRect(canvas_bitmap_rect);
69 if (!canvas_playback_rect.IsEmpty() &&
70 !raster_bounds.intersect(gfx::RectToSkIRect(canvas_playback_rect)))
71 return;
72 // Treat all subnormal values as zero for performance.
73 ScopedSubnormalFloatDisabler disabler;
74
75 raster_canvas->save();
76 raster_canvas->translate(-canvas_bitmap_rect.x(), -canvas_bitmap_rect.y());
77 raster_canvas->clipRect(SkRect::MakeFromIRect(raster_bounds));
78 raster_canvas->scale(raster_scale, raster_scale);
79 PlaybackToCanvas(raster_canvas, settings);
80 raster_canvas->restore();
81 }
82
83 void RasterSource::PlaybackToCanvas(SkCanvas* raster_canvas,
84 const PlaybackSettings& settings) const {
85 if (!settings.playback_to_shared_canvas)
86 PrepareForPlaybackToCanvas(raster_canvas);
87
88 if (settings.skip_images) {
89 SkipImageCanvas canvas(raster_canvas);
90 RasterCommon(&canvas, nullptr);
91 } else if (settings.use_image_hijack_canvas) {
92 const SkImageInfo& info = raster_canvas->imageInfo();
93 ImageHijackCanvas canvas(info.width(), info.height(), image_decode_cache_,
94 &settings.images_to_skip);
95 // Before adding the canvas, make sure that the ImageHijackCanvas is aware
96 // of the current transform and clip, which may affect the clip bounds.
97 // Since we query the clip bounds of the current canvas to get the list of
98 // draw commands to process, this is important to produce correct content.
99 canvas.clipRect(
100 SkRect::MakeFromIRect(raster_canvas->getDeviceClipBounds()));
101 canvas.setMatrix(raster_canvas->getTotalMatrix());
102 canvas.addCanvas(raster_canvas);
103
104 RasterCommon(&canvas, nullptr);
105 } else {
106 RasterCommon(raster_canvas, nullptr);
107 }
108 }
109
110 namespace {
111
112 bool CanvasIsUnclipped(const SkCanvas* canvas) {
113 if (!canvas->isClipRect())
114 return false;
115
116 SkIRect bounds;
117 if (!canvas->getDeviceClipBounds(&bounds))
118 return false;
119
120 SkISize size = canvas->getBaseLayerSize();
121 return bounds.contains(0, 0, size.width(), size.height());
122 }
123
124 } // namespace
125
126 void RasterSource::PrepareForPlaybackToCanvas(SkCanvas* canvas) const {
127 // TODO(hendrikw): See if we can split this up into separate functions.
128
129 if (CanvasIsUnclipped(canvas))
130 canvas->discard();
131
132 // If this raster source has opaque contents, it is guaranteeing that it will
133 // draw an opaque rect the size of the layer. If it is not, then we must
134 // clear this canvas ourselves.
135 if (requires_clear_) {
136 canvas->clear(SK_ColorTRANSPARENT);
137 return;
138 }
139
140 if (clear_canvas_with_debug_color_)
141 canvas->clear(DebugColors::NonPaintedFillColor());
142
143 // If the canvas wants us to raster with complex transform, it is hard to
144 // determine the exact region we must clear. Just clear everything.
145 // TODO(trchen): Optimize the common case that transformed content bounds
146 // covers the whole clip region.
147 if (!canvas->getTotalMatrix().rectStaysRect()) {
148 canvas->clear(SK_ColorTRANSPARENT);
149 return;
150 }
151
152 SkRect content_device_rect;
153 canvas->getTotalMatrix().mapRect(
154 &content_device_rect, SkRect::MakeWH(size_.width(), size_.height()));
155
156 // The final texel of content may only be partially covered by a
157 // rasterization; this rect represents the content rect that is fully
158 // covered by content.
159 SkIRect opaque_rect;
160 content_device_rect.roundIn(&opaque_rect);
161
162 if (opaque_rect.contains(canvas->getDeviceClipBounds()))
163 return;
164
165 // Even if completely covered, for rasterizations that touch the edge of the
166 // layer, we also need to raster the background color underneath the last
167 // texel (since the recording won't cover it) and outside the last texel
168 // (due to linear filtering when using this texture).
169 SkIRect interest_rect;
170 content_device_rect.roundOut(&interest_rect);
171 interest_rect.outset(1, 1);
172
173 if (clear_canvas_with_debug_color_) {
174 // Any non-painted areas outside of the content bounds are left in
175 // this color. If this is seen then it means that cc neglected to
176 // rerasterize a tile that used to intersect with the content rect
177 // after the content bounds grew.
178 canvas->save();
179 // Use clipRegion to bypass CTM because the rects are device rects.
180 SkRegion interest_region;
181 interest_region.setRect(interest_rect);
182 canvas->clipRegion(interest_region, SkClipOp::kDifference);
183 canvas->clear(DebugColors::MissingResizeInvalidations());
184 canvas->restore();
185 }
186
187 // Drawing at most 2 x 2 x (canvas width + canvas height) texels is 2-3X
188 // faster than clearing, so special case this.
189 canvas->save();
190 // Use clipRegion to bypass CTM because the rects are device rects.
191 SkRegion interest_region;
192 interest_region.setRect(interest_rect);
193 interest_region.op(opaque_rect, SkRegion::kDifference_Op);
194 canvas->clipRegion(interest_region);
195 canvas->clear(background_color_);
196 canvas->restore();
197 }
198
199 void RasterSource::RasterCommon(SkCanvas* canvas,
200 SkPicture::AbortCallback* callback) const {
201 DCHECK(display_list_.get());
202 int repeat_count = std::max(1, slow_down_raster_scale_factor_for_debug_);
203 for (int i = 0; i < repeat_count; ++i)
204 display_list_->Raster(canvas, callback);
205 }
206
207 sk_sp<SkPicture> RasterSource::GetFlattenedPicture() {
208 TRACE_EVENT0("cc", "RasterSource::GetFlattenedPicture");
209
210 SkPictureRecorder recorder;
211 SkCanvas* canvas = recorder.beginRecording(size_.width(), size_.height());
212 if (!size_.IsEmpty()) {
213 PrepareForPlaybackToCanvas(canvas);
214 RasterCommon(canvas, nullptr);
215 }
216
217 return recorder.finishRecordingAsPicture();
218 }
219
220 size_t RasterSource::GetMemoryUsage() const {
221 if (!display_list_)
222 return 0;
223 return display_list_->ApproximateMemoryUsage() +
224 painter_reported_memory_usage_;
225 }
226
227 bool RasterSource::PerformSolidColorAnalysis(const gfx::Rect& content_rect,
228 float contents_scale,
229 SkColor* color) const {
230 TRACE_EVENT0("cc", "RasterSource::PerformSolidColorAnalysis");
231
232 gfx::Rect layer_rect =
233 gfx::ScaleToEnclosingRect(content_rect, 1.f / contents_scale);
234
235 layer_rect.Intersect(gfx::Rect(size_));
236 skia::AnalysisCanvas canvas(layer_rect.width(), layer_rect.height());
237 canvas.translate(-layer_rect.x(), -layer_rect.y());
238 RasterCommon(&canvas, &canvas);
239 return canvas.GetColorIfSolid(color);
240 }
241
242 void RasterSource::GetDiscardableImagesInRect(
243 const gfx::Rect& layer_rect,
244 float contents_scale,
245 std::vector<DrawImage>* images) const {
246 DCHECK_EQ(0u, images->size());
247 display_list_->GetDiscardableImagesInRect(layer_rect, contents_scale, images);
248 }
249
250 gfx::Rect RasterSource::GetRectForImage(ImageId image_id) const {
251 if (!display_list_)
252 return gfx::Rect();
253 return display_list_->GetRectForImage(image_id);
254 }
255
256 bool RasterSource::CoversRect(const gfx::Rect& layer_rect) const {
257 if (size_.IsEmpty())
258 return false;
259 gfx::Rect bounded_rect = layer_rect;
260 bounded_rect.Intersect(gfx::Rect(size_));
261 return recorded_viewport_.Contains(bounded_rect);
262 }
263
264 gfx::Size RasterSource::GetSize() const {
265 return size_;
266 }
267
268 bool RasterSource::IsSolidColor() const {
269 return is_solid_color_;
270 }
271
272 SkColor RasterSource::GetSolidColor() const {
273 DCHECK(IsSolidColor());
274 return solid_color_;
275 }
276
277 bool RasterSource::HasRecordings() const {
278 return !!display_list_.get();
279 }
280
281 gfx::Rect RasterSource::RecordedViewport() const {
282 return recorded_viewport_;
283 }
284
285 void RasterSource::AsValueInto(base::trace_event::TracedValue* array) const {
286 if (display_list_.get())
287 TracedValue::AppendIDRef(display_list_.get(), array);
288 }
289
290 void RasterSource::DidBeginTracing() {
291 if (display_list_.get())
292 display_list_->EmitTraceSnapshot();
293 }
294
295 bool RasterSource::CanUseLCDText() const {
296 return can_use_lcd_text_;
297 }
298
299 scoped_refptr<RasterSource> RasterSource::CreateCloneWithoutLCDText() const {
300 bool can_use_lcd_text = false;
301 return scoped_refptr<RasterSource>(new RasterSource(this, can_use_lcd_text));
302 }
303
304 RasterSource::PlaybackSettings::PlaybackSettings()
305 : playback_to_shared_canvas(false),
306 skip_images(false),
307 use_image_hijack_canvas(true) {}
308
309 RasterSource::PlaybackSettings::PlaybackSettings(const PlaybackSettings&) =
310 default;
311
312 RasterSource::PlaybackSettings::PlaybackSettings(PlaybackSettings&&) = default;
313
314 RasterSource::PlaybackSettings::~PlaybackSettings() = default;
315
316 } // namespace cc
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698