OLD | NEW |
1 // Copyright 2012 The Chromium Authors. All rights reserved. | 1 // Copyright 2012 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 <algorithm> | 5 #include <algorithm> |
6 #include <limits> | 6 #include <limits> |
7 | 7 |
8 #include "base/debug/trace_event.h" | 8 #include "base/debug/trace_event.h" |
9 #include "cc/base/region.h" | 9 #include "cc/base/region.h" |
10 #include "cc/debug/debug_colors.h" | 10 #include "cc/debug/debug_colors.h" |
11 #include "cc/resources/picture_pile_impl.h" | 11 #include "cc/resources/picture_pile_impl.h" |
12 #include "cc/resources/raster_worker_pool.h" | |
13 #include "skia/ext/analysis_canvas.h" | 12 #include "skia/ext/analysis_canvas.h" |
14 #include "third_party/skia/include/core/SkCanvas.h" | 13 #include "third_party/skia/include/core/SkCanvas.h" |
15 #include "third_party/skia/include/core/SkPictureRecorder.h" | 14 #include "third_party/skia/include/core/SkPictureRecorder.h" |
16 #include "third_party/skia/include/core/SkSize.h" | 15 #include "third_party/skia/include/core/SkSize.h" |
17 #include "ui/gfx/rect_conversions.h" | 16 #include "ui/gfx/rect_conversions.h" |
18 #include "ui/gfx/size_conversions.h" | 17 #include "ui/gfx/size_conversions.h" |
19 #include "ui/gfx/skia_util.h" | 18 #include "ui/gfx/skia_util.h" |
20 | 19 |
21 namespace cc { | 20 namespace cc { |
22 | 21 |
23 PicturePileImpl::ClonesForDrawing::ClonesForDrawing( | |
24 const PicturePileImpl* pile, int num_threads) { | |
25 for (int i = 0; i < num_threads; i++) { | |
26 scoped_refptr<PicturePileImpl> clone = | |
27 PicturePileImpl::CreateCloneForDrawing(pile, i); | |
28 clones_.push_back(clone); | |
29 } | |
30 } | |
31 | |
32 PicturePileImpl::ClonesForDrawing::~ClonesForDrawing() { | |
33 } | |
34 | |
35 scoped_refptr<PicturePileImpl> PicturePileImpl::Create() { | 22 scoped_refptr<PicturePileImpl> PicturePileImpl::Create() { |
36 return make_scoped_refptr(new PicturePileImpl); | 23 return make_scoped_refptr(new PicturePileImpl); |
37 } | 24 } |
38 | 25 |
39 scoped_refptr<PicturePileImpl> PicturePileImpl::CreateFromOther( | 26 scoped_refptr<PicturePileImpl> PicturePileImpl::CreateFromOther( |
40 const PicturePileBase* other) { | 27 const PicturePileBase* other) { |
41 return make_scoped_refptr(new PicturePileImpl(other)); | 28 return make_scoped_refptr(new PicturePileImpl(other)); |
42 } | 29 } |
43 | 30 |
44 scoped_refptr<PicturePileImpl> PicturePileImpl::CreateCloneForDrawing( | 31 PicturePileImpl::PicturePileImpl() { |
45 const PicturePileImpl* other, unsigned thread_index) { | |
46 return make_scoped_refptr(new PicturePileImpl(other, thread_index)); | |
47 } | |
48 | |
49 PicturePileImpl::PicturePileImpl() | |
50 : clones_for_drawing_(ClonesForDrawing(this, 0)) { | |
51 } | 32 } |
52 | 33 |
53 PicturePileImpl::PicturePileImpl(const PicturePileBase* other) | 34 PicturePileImpl::PicturePileImpl(const PicturePileBase* other) |
54 : PicturePileBase(other), | 35 : PicturePileBase(other) { |
55 clones_for_drawing_(ClonesForDrawing( | |
56 this, RasterWorkerPool::GetNumRasterThreads())) { | |
57 } | |
58 | |
59 PicturePileImpl::PicturePileImpl( | |
60 const PicturePileImpl* other, unsigned thread_index) | |
61 : PicturePileBase(other, thread_index), | |
62 clones_for_drawing_(ClonesForDrawing(this, 0)) { | |
63 } | 36 } |
64 | 37 |
65 PicturePileImpl::~PicturePileImpl() { | 38 PicturePileImpl::~PicturePileImpl() { |
66 } | 39 } |
67 | 40 |
68 PicturePileImpl* PicturePileImpl::GetCloneForDrawingOnThread( | |
69 unsigned thread_index) const { | |
70 CHECK_GT(clones_for_drawing_.clones_.size(), thread_index); | |
71 return clones_for_drawing_.clones_[thread_index].get(); | |
72 } | |
73 | |
74 void PicturePileImpl::RasterDirect( | 41 void PicturePileImpl::RasterDirect( |
75 SkCanvas* canvas, | 42 SkCanvas* canvas, |
76 const gfx::Rect& canvas_rect, | 43 const gfx::Rect& canvas_rect, |
77 float contents_scale, | 44 float contents_scale, |
78 RenderingStatsInstrumentation* rendering_stats_instrumentation) { | 45 RenderingStatsInstrumentation* rendering_stats_instrumentation) { |
79 RasterCommon(canvas, | 46 RasterCommon(canvas, |
80 NULL, | 47 NULL, |
81 canvas_rect, | 48 canvas_rect, |
82 contents_scale, | 49 contents_scale, |
83 rendering_stats_instrumentation, | 50 rendering_stats_instrumentation, |
84 false); | 51 false); |
85 } | 52 } |
86 | 53 |
87 void PicturePileImpl::RasterForAnalysis( | 54 void PicturePileImpl::RasterForAnalysis( |
88 skia::AnalysisCanvas* canvas, | 55 skia::AnalysisCanvas* canvas, |
89 const gfx::Rect& canvas_rect, | 56 const gfx::Rect& canvas_rect, |
90 float contents_scale, | 57 float contents_scale, |
91 RenderingStatsInstrumentation* stats_instrumentation) { | 58 RenderingStatsInstrumentation* stats_instrumentation) const { |
92 RasterCommon( | 59 RasterCommon( |
93 canvas, canvas, canvas_rect, contents_scale, stats_instrumentation, true); | 60 canvas, canvas, canvas_rect, contents_scale, stats_instrumentation, true); |
94 } | 61 } |
95 | 62 |
96 void PicturePileImpl::RasterToBitmap( | 63 void PicturePileImpl::RasterToBitmap( |
97 SkCanvas* canvas, | 64 SkCanvas* canvas, |
98 const gfx::Rect& canvas_rect, | 65 const gfx::Rect& canvas_rect, |
99 float contents_scale, | 66 float contents_scale, |
100 RenderingStatsInstrumentation* rendering_stats_instrumentation) { | 67 RenderingStatsInstrumentation* rendering_stats_instrumentation) const { |
101 canvas->discard(); | 68 canvas->discard(); |
102 if (clear_canvas_with_debug_color_) { | 69 if (clear_canvas_with_debug_color_) { |
103 // Any non-painted areas in the content bounds will be left in this color. | 70 // Any non-painted areas in the content bounds will be left in this color. |
104 canvas->clear(DebugColors::NonPaintedFillColor()); | 71 canvas->clear(DebugColors::NonPaintedFillColor()); |
105 } | 72 } |
106 | 73 |
107 // If this picture has opaque contents, it is guaranteeing that it will | 74 // If this picture has opaque contents, it is guaranteeing that it will |
108 // draw an opaque rect the size of the layer. If it is not, then we must | 75 // draw an opaque rect the size of the layer. If it is not, then we must |
109 // clear this canvas ourselves. | 76 // clear this canvas ourselves. |
110 if (contents_opaque_ || contents_fill_bounds_completely_) { | 77 if (contents_opaque_ || contents_fill_bounds_completely_) { |
(...skipping 48 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
159 NULL, | 126 NULL, |
160 canvas_rect, | 127 canvas_rect, |
161 contents_scale, | 128 contents_scale, |
162 rendering_stats_instrumentation, | 129 rendering_stats_instrumentation, |
163 false); | 130 false); |
164 } | 131 } |
165 | 132 |
166 void PicturePileImpl::CoalesceRasters(const gfx::Rect& canvas_rect, | 133 void PicturePileImpl::CoalesceRasters(const gfx::Rect& canvas_rect, |
167 const gfx::Rect& content_rect, | 134 const gfx::Rect& content_rect, |
168 float contents_scale, | 135 float contents_scale, |
169 PictureRegionMap* results) { | 136 PictureRegionMap* results) const { |
170 DCHECK(results); | 137 DCHECK(results); |
171 // Rasterize the collection of relevant picture piles. | 138 // Rasterize the collection of relevant picture piles. |
172 gfx::Rect layer_rect = gfx::ScaleToEnclosingRect( | 139 gfx::Rect layer_rect = gfx::ScaleToEnclosingRect( |
173 content_rect, 1.f / contents_scale); | 140 content_rect, 1.f / contents_scale); |
174 | 141 |
175 // Make sure pictures don't overlap by keeping track of previous right/bottom. | 142 // Make sure pictures don't overlap by keeping track of previous right/bottom. |
176 int min_content_left = -1; | 143 int min_content_left = -1; |
177 int min_content_top = -1; | 144 int min_content_top = -1; |
178 int last_row_index = -1; | 145 int last_row_index = -1; |
179 int last_col_index = -1; | 146 int last_col_index = -1; |
(...skipping 10 matching lines...) Expand all Loading... |
190 // ignores the transform). Intersect then can be written as subtracting the | 157 // ignores the transform). Intersect then can be written as subtracting the |
191 // negation of the region we're trying to intersect. Luckily, we know that all | 158 // negation of the region we're trying to intersect. Luckily, we know that all |
192 // of the rects will have to fit into |content_rect|, so we can start with | 159 // of the rects will have to fit into |content_rect|, so we can start with |
193 // that and subtract chunk rects to get the region that we need to subtract | 160 // that and subtract chunk rects to get the region that we need to subtract |
194 // from the canvas. Then, we can use clipRect with difference op to subtract | 161 // from the canvas. Then, we can use clipRect with difference op to subtract |
195 // each rect in the region. | 162 // each rect in the region. |
196 bool include_borders = true; | 163 bool include_borders = true; |
197 for (TilingData::Iterator tile_iter(&tiling_, layer_rect, include_borders); | 164 for (TilingData::Iterator tile_iter(&tiling_, layer_rect, include_borders); |
198 tile_iter; | 165 tile_iter; |
199 ++tile_iter) { | 166 ++tile_iter) { |
200 PictureMap::iterator map_iter = picture_map_.find(tile_iter.index()); | 167 PictureMap::const_iterator map_iter = picture_map_.find(tile_iter.index()); |
201 if (map_iter == picture_map_.end()) | 168 if (map_iter == picture_map_.end()) |
202 continue; | 169 continue; |
203 PictureInfo& info = map_iter->second; | 170 const PictureInfo& info = map_iter->second; |
204 Picture* picture = info.GetPicture(); | 171 const Picture* picture = info.GetPicture(); |
205 if (!picture) | 172 if (!picture) |
206 continue; | 173 continue; |
207 | 174 |
208 // This is intentionally *enclosed* rect, so that the clip is aligned on | 175 // This is intentionally *enclosed* rect, so that the clip is aligned on |
209 // integral post-scale content pixels and does not extend past the edges | 176 // integral post-scale content pixels and does not extend past the edges |
210 // of the picture chunk's layer rect. The min_contents_scale enforces that | 177 // of the picture chunk's layer rect. The min_contents_scale enforces that |
211 // enough buffer pixels have been added such that the enclosed rect | 178 // enough buffer pixels have been added such that the enclosed rect |
212 // encompasses all invalidated pixels at any larger scale level. | 179 // encompasses all invalidated pixels at any larger scale level. |
213 gfx::Rect chunk_rect = PaddedRect(tile_iter.index()); | 180 gfx::Rect chunk_rect = PaddedRect(tile_iter.index()); |
214 gfx::Rect content_clip = | 181 gfx::Rect content_clip = |
(...skipping 42 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
257 last_content_rect = content_clip; | 224 last_content_rect = content_clip; |
258 } | 225 } |
259 } | 226 } |
260 | 227 |
261 void PicturePileImpl::RasterCommon( | 228 void PicturePileImpl::RasterCommon( |
262 SkCanvas* canvas, | 229 SkCanvas* canvas, |
263 SkDrawPictureCallback* callback, | 230 SkDrawPictureCallback* callback, |
264 const gfx::Rect& canvas_rect, | 231 const gfx::Rect& canvas_rect, |
265 float contents_scale, | 232 float contents_scale, |
266 RenderingStatsInstrumentation* rendering_stats_instrumentation, | 233 RenderingStatsInstrumentation* rendering_stats_instrumentation, |
267 bool is_analysis) { | 234 bool is_analysis) const { |
268 DCHECK(contents_scale >= min_contents_scale_); | 235 DCHECK(contents_scale >= min_contents_scale_); |
269 | 236 |
270 canvas->translate(-canvas_rect.x(), -canvas_rect.y()); | 237 canvas->translate(-canvas_rect.x(), -canvas_rect.y()); |
271 gfx::Rect content_tiling_rect = gfx::ToEnclosingRect( | 238 gfx::Rect content_tiling_rect = gfx::ToEnclosingRect( |
272 gfx::ScaleRect(gfx::Rect(tiling_.tiling_size()), contents_scale)); | 239 gfx::ScaleRect(gfx::Rect(tiling_.tiling_size()), contents_scale)); |
273 content_tiling_rect.Intersect(canvas_rect); | 240 content_tiling_rect.Intersect(canvas_rect); |
274 | 241 |
275 canvas->clipRect(gfx::RectToSkRect(content_tiling_rect), | 242 canvas->clipRect(gfx::RectToSkRect(content_tiling_rect), |
276 SkRegion::kIntersect_Op); | 243 SkRegion::kIntersect_Op); |
277 | 244 |
278 PictureRegionMap picture_region_map; | 245 PictureRegionMap picture_region_map; |
279 CoalesceRasters( | 246 CoalesceRasters( |
280 canvas_rect, content_tiling_rect, contents_scale, &picture_region_map); | 247 canvas_rect, content_tiling_rect, contents_scale, &picture_region_map); |
281 | 248 |
282 #ifndef NDEBUG | 249 #ifndef NDEBUG |
283 Region total_clip; | 250 Region total_clip; |
284 #endif // NDEBUG | 251 #endif // NDEBUG |
285 | 252 |
286 // Iterate the coalesced map and use each picture's region | 253 // Iterate the coalesced map and use each picture's region |
287 // to clip the canvas. | 254 // to clip the canvas. |
288 for (PictureRegionMap::iterator it = picture_region_map.begin(); | 255 for (PictureRegionMap::iterator it = picture_region_map.begin(); |
289 it != picture_region_map.end(); | 256 it != picture_region_map.end(); |
290 ++it) { | 257 ++it) { |
291 Picture* picture = it->first; | 258 const Picture* picture = it->first; |
292 Region negated_clip_region = it->second; | 259 Region negated_clip_region = it->second; |
293 | 260 |
294 #ifndef NDEBUG | 261 #ifndef NDEBUG |
295 Region positive_clip = content_tiling_rect; | 262 Region positive_clip = content_tiling_rect; |
296 positive_clip.Subtract(negated_clip_region); | 263 positive_clip.Subtract(negated_clip_region); |
297 // Make sure we never rasterize the same region twice. | 264 // Make sure we never rasterize the same region twice. |
298 DCHECK(!total_clip.Intersects(positive_clip)); | 265 DCHECK(!total_clip.Intersects(positive_clip)); |
299 total_clip.Union(positive_clip); | 266 total_clip.Union(positive_clip); |
300 #endif // NDEBUG | 267 #endif // NDEBUG |
301 | 268 |
(...skipping 47 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
349 SkPictureRecorder recorder; | 316 SkPictureRecorder recorder; |
350 SkCanvas* canvas = | 317 SkCanvas* canvas = |
351 recorder.beginRecording(tiling_rect.width(), tiling_rect.height()); | 318 recorder.beginRecording(tiling_rect.width(), tiling_rect.height()); |
352 if (!tiling_rect.IsEmpty()) | 319 if (!tiling_rect.IsEmpty()) |
353 RasterToBitmap(canvas, tiling_rect, 1.0, NULL); | 320 RasterToBitmap(canvas, tiling_rect, 1.0, NULL); |
354 skia::RefPtr<SkPicture> picture = skia::AdoptRef(recorder.endRecording()); | 321 skia::RefPtr<SkPicture> picture = skia::AdoptRef(recorder.endRecording()); |
355 | 322 |
356 return picture; | 323 return picture; |
357 } | 324 } |
358 | 325 |
359 void PicturePileImpl::AnalyzeInRect( | 326 void PicturePileImpl::AnalyzeInRect(const gfx::Rect& content_rect, |
360 const gfx::Rect& content_rect, | 327 float contents_scale, |
361 float contents_scale, | 328 PicturePileImpl::Analysis* analysis) const { |
362 PicturePileImpl::Analysis* analysis) { | |
363 AnalyzeInRect(content_rect, contents_scale, analysis, NULL); | 329 AnalyzeInRect(content_rect, contents_scale, analysis, NULL); |
364 } | 330 } |
365 | 331 |
366 void PicturePileImpl::AnalyzeInRect( | 332 void PicturePileImpl::AnalyzeInRect( |
367 const gfx::Rect& content_rect, | 333 const gfx::Rect& content_rect, |
368 float contents_scale, | 334 float contents_scale, |
369 PicturePileImpl::Analysis* analysis, | 335 PicturePileImpl::Analysis* analysis, |
370 RenderingStatsInstrumentation* stats_instrumentation) { | 336 RenderingStatsInstrumentation* stats_instrumentation) const { |
371 DCHECK(analysis); | 337 DCHECK(analysis); |
372 TRACE_EVENT0("cc", "PicturePileImpl::AnalyzeInRect"); | 338 TRACE_EVENT0("cc", "PicturePileImpl::AnalyzeInRect"); |
373 | 339 |
374 gfx::Rect layer_rect = gfx::ScaleToEnclosingRect( | 340 gfx::Rect layer_rect = gfx::ScaleToEnclosingRect( |
375 content_rect, 1.0f / contents_scale); | 341 content_rect, 1.0f / contents_scale); |
376 | 342 |
377 layer_rect.Intersect(gfx::Rect(tiling_.tiling_size())); | 343 layer_rect.Intersect(gfx::Rect(tiling_.tiling_size())); |
378 | 344 |
379 skia::AnalysisCanvas canvas(layer_rect.width(), layer_rect.height()); | 345 skia::AnalysisCanvas canvas(layer_rect.width(), layer_rect.height()); |
380 | 346 |
(...skipping 56 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
437 continue; | 403 continue; |
438 | 404 |
439 processed_pictures_.insert(picture); | 405 processed_pictures_.insert(picture); |
440 pixel_ref_iterator_ = Picture::PixelRefIterator(layer_rect_, picture); | 406 pixel_ref_iterator_ = Picture::PixelRefIterator(layer_rect_, picture); |
441 if (pixel_ref_iterator_) | 407 if (pixel_ref_iterator_) |
442 break; | 408 break; |
443 } | 409 } |
444 } | 410 } |
445 | 411 |
446 void PicturePileImpl::DidBeginTracing() { | 412 void PicturePileImpl::DidBeginTracing() { |
447 std::set<void*> processed_pictures; | 413 std::set<const void*> processed_pictures; |
448 for (PictureMap::iterator it = picture_map_.begin(); | 414 for (PictureMap::iterator it = picture_map_.begin(); |
449 it != picture_map_.end(); | 415 it != picture_map_.end(); |
450 ++it) { | 416 ++it) { |
451 Picture* picture = it->second.GetPicture(); | 417 const Picture* picture = it->second.GetPicture(); |
452 if (picture && (processed_pictures.count(picture) == 0)) { | 418 if (picture && (processed_pictures.count(picture) == 0)) { |
453 picture->EmitTraceSnapshot(); | 419 picture->EmitTraceSnapshot(); |
454 processed_pictures.insert(picture); | 420 processed_pictures.insert(picture); |
455 } | 421 } |
456 } | 422 } |
457 } | 423 } |
458 | 424 |
459 } // namespace cc | 425 } // namespace cc |
OLD | NEW |