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 "cc/resources/picture.h" | 5 #include "cc/resources/picture.h" |
6 | 6 |
7 #include <algorithm> | |
8 #include <limits> | |
9 #include <set> | 7 #include <set> |
| 8 #include <string> |
10 | 9 |
11 #include "base/base64.h" | 10 #include "base/base64.h" |
12 #include "base/trace_event/trace_event.h" | 11 #include "base/trace_event/trace_event.h" |
13 #include "base/trace_event/trace_event_argument.h" | 12 #include "base/trace_event/trace_event_argument.h" |
14 #include "base/values.h" | 13 #include "base/values.h" |
15 #include "cc/base/math_util.h" | 14 #include "cc/base/math_util.h" |
16 #include "cc/base/util.h" | 15 #include "cc/base/util.h" |
17 #include "cc/debug/picture_debug_util.h" | 16 #include "cc/debug/picture_debug_util.h" |
18 #include "cc/debug/traced_picture.h" | 17 #include "cc/debug/traced_picture.h" |
19 #include "cc/debug/traced_value.h" | 18 #include "cc/debug/traced_value.h" |
(...skipping 32 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
52 } | 51 } |
53 | 52 |
54 } // namespace | 53 } // namespace |
55 | 54 |
56 scoped_refptr<Picture> Picture::Create( | 55 scoped_refptr<Picture> Picture::Create( |
57 const gfx::Rect& layer_rect, | 56 const gfx::Rect& layer_rect, |
58 ContentLayerClient* client, | 57 ContentLayerClient* client, |
59 const gfx::Size& tile_grid_size, | 58 const gfx::Size& tile_grid_size, |
60 bool gather_pixel_refs, | 59 bool gather_pixel_refs, |
61 RecordingSource::RecordingMode recording_mode) { | 60 RecordingSource::RecordingMode recording_mode) { |
62 scoped_refptr<Picture> picture = make_scoped_refptr(new Picture(layer_rect)); | 61 scoped_refptr<Picture> picture = |
| 62 make_scoped_refptr(new Picture(layer_rect, tile_grid_size)); |
63 | 63 |
64 picture->Record(client, tile_grid_size, recording_mode); | 64 picture->Record(client, recording_mode); |
65 if (gather_pixel_refs) | 65 if (gather_pixel_refs) |
66 picture->GatherPixelRefs(tile_grid_size); | 66 picture->GatherPixelRefs(); |
67 | 67 |
68 return picture; | 68 return picture; |
69 } | 69 } |
70 | 70 |
71 Picture::Picture(const gfx::Rect& layer_rect) | 71 Picture::Picture(const gfx::Rect& layer_rect, const gfx::Size& tile_grid_size) |
72 : layer_rect_(layer_rect), | 72 : layer_rect_(layer_rect), pixel_refs_(tile_grid_size) { |
73 cell_size_(layer_rect.size()) { | |
74 // Instead of recording a trace event for object creation here, we wait for | 73 // Instead of recording a trace event for object creation here, we wait for |
75 // the picture to be recorded in Picture::Record. | 74 // the picture to be recorded in Picture::Record. |
76 } | 75 } |
77 | 76 |
78 scoped_refptr<Picture> Picture::CreateFromSkpValue(const base::Value* value) { | 77 scoped_refptr<Picture> Picture::CreateFromSkpValue(const base::Value* value) { |
79 // Decode the picture from base64. | 78 // Decode the picture from base64. |
80 std::string encoded; | 79 std::string encoded; |
81 if (!value->GetAsString(&encoded)) | 80 if (!value->GetAsString(&encoded)) |
82 return NULL; | 81 return NULL; |
83 | 82 |
(...skipping 36 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
120 SkPicture* skpicture = SkPicture::CreateFromStream(&stream, &DecodeBitmap); | 119 SkPicture* skpicture = SkPicture::CreateFromStream(&stream, &DecodeBitmap); |
121 if (skpicture == NULL) | 120 if (skpicture == NULL) |
122 return NULL; | 121 return NULL; |
123 | 122 |
124 return make_scoped_refptr(new Picture(skpicture, layer_rect)); | 123 return make_scoped_refptr(new Picture(skpicture, layer_rect)); |
125 } | 124 } |
126 | 125 |
127 Picture::Picture(SkPicture* picture, const gfx::Rect& layer_rect) | 126 Picture::Picture(SkPicture* picture, const gfx::Rect& layer_rect) |
128 : layer_rect_(layer_rect), | 127 : layer_rect_(layer_rect), |
129 picture_(skia::AdoptRef(picture)), | 128 picture_(skia::AdoptRef(picture)), |
130 cell_size_(layer_rect.size()) { | 129 pixel_refs_(layer_rect.size()) { |
131 } | 130 } |
132 | 131 |
133 Picture::Picture(const skia::RefPtr<SkPicture>& picture, | 132 Picture::Picture(const skia::RefPtr<SkPicture>& picture, |
134 const gfx::Rect& layer_rect, | 133 const gfx::Rect& layer_rect, |
135 const PixelRefMap& pixel_refs) : | 134 const PixelRefMap& pixel_refs) |
136 layer_rect_(layer_rect), | 135 : layer_rect_(layer_rect), picture_(picture), pixel_refs_(pixel_refs) { |
137 picture_(picture), | |
138 pixel_refs_(pixel_refs), | |
139 cell_size_(layer_rect.size()) { | |
140 } | 136 } |
141 | 137 |
142 Picture::~Picture() { | 138 Picture::~Picture() { |
143 TRACE_EVENT_OBJECT_DELETED_WITH_ID( | 139 TRACE_EVENT_OBJECT_DELETED_WITH_ID( |
144 TRACE_DISABLED_BY_DEFAULT("cc.debug.picture"), "cc::Picture", this); | 140 TRACE_DISABLED_BY_DEFAULT("cc.debug.picture"), "cc::Picture", this); |
145 } | 141 } |
146 | 142 |
147 bool Picture::IsSuitableForGpuRasterization(const char** reason) const { | 143 bool Picture::IsSuitableForGpuRasterization(const char** reason) const { |
148 DCHECK(picture_); | 144 DCHECK(picture_); |
149 | 145 |
(...skipping 12 matching lines...) Expand all Loading... |
162 DCHECK(picture_); | 158 DCHECK(picture_); |
163 return SkPictureUtils::ApproximateBytesUsed(picture_.get()); | 159 return SkPictureUtils::ApproximateBytesUsed(picture_.get()); |
164 } | 160 } |
165 | 161 |
166 bool Picture::HasText() const { | 162 bool Picture::HasText() const { |
167 DCHECK(picture_); | 163 DCHECK(picture_); |
168 return picture_->hasText(); | 164 return picture_->hasText(); |
169 } | 165 } |
170 | 166 |
171 void Picture::Record(ContentLayerClient* painter, | 167 void Picture::Record(ContentLayerClient* painter, |
172 const gfx::Size& tile_grid_size, | |
173 RecordingSource::RecordingMode recording_mode) { | 168 RecordingSource::RecordingMode recording_mode) { |
174 TRACE_EVENT2("cc", | 169 TRACE_EVENT2("cc", |
175 "Picture::Record", | 170 "Picture::Record", |
176 "data", | 171 "data", |
177 AsTraceableRecordData(), | 172 AsTraceableRecordData(), |
178 "recording_mode", | 173 "recording_mode", |
179 recording_mode); | 174 recording_mode); |
180 | 175 |
181 DCHECK(!picture_); | 176 DCHECK(!picture_); |
182 DCHECK(!tile_grid_size.IsEmpty()); | |
183 | 177 |
184 // TODO(mtklein): If SkRTree sticks, clean up tile_grid_info. skbug.com/3085 | |
185 SkRTreeFactory factory; | 178 SkRTreeFactory factory; |
186 SkPictureRecorder recorder; | 179 SkPictureRecorder recorder; |
187 | 180 |
188 skia::RefPtr<SkCanvas> canvas; | 181 skia::RefPtr<SkCanvas> canvas; |
189 canvas = skia::SharePtr(recorder.beginRecording( | 182 canvas = skia::SharePtr(recorder.beginRecording( |
190 layer_rect_.width(), layer_rect_.height(), &factory, | 183 layer_rect_.width(), layer_rect_.height(), &factory, |
191 SkPictureRecorder::kComputeSaveLayerInfo_RecordFlag)); | 184 SkPictureRecorder::kComputeSaveLayerInfo_RecordFlag)); |
192 | 185 |
193 ContentLayerClient::PaintingControlSetting painting_control = | 186 ContentLayerClient::PaintingControlSetting painting_control = |
194 ContentLayerClient::PAINTING_BEHAVIOR_NORMAL; | 187 ContentLayerClient::PAINTING_BEHAVIOR_NORMAL; |
(...skipping 33 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
228 | 221 |
229 painter->PaintContents(canvas.get(), layer_rect_, painting_control); | 222 painter->PaintContents(canvas.get(), layer_rect_, painting_control); |
230 | 223 |
231 canvas->restore(); | 224 canvas->restore(); |
232 picture_ = skia::AdoptRef(recorder.endRecording()); | 225 picture_ = skia::AdoptRef(recorder.endRecording()); |
233 DCHECK(picture_); | 226 DCHECK(picture_); |
234 | 227 |
235 EmitTraceSnapshot(); | 228 EmitTraceSnapshot(); |
236 } | 229 } |
237 | 230 |
238 void Picture::GatherPixelRefs(const gfx::Size& tile_grid_size) { | 231 void Picture::GatherPixelRefs() { |
239 TRACE_EVENT2("cc", "Picture::GatherPixelRefs", | 232 TRACE_EVENT2("cc", "Picture::GatherPixelRefs", |
240 "width", layer_rect_.width(), | 233 "width", layer_rect_.width(), |
241 "height", layer_rect_.height()); | 234 "height", layer_rect_.height()); |
242 | 235 |
243 DCHECK(picture_); | 236 DCHECK(picture_); |
244 DCHECK(pixel_refs_.empty()); | 237 DCHECK(pixel_refs_.empty()); |
245 if (!WillPlayBackBitmaps()) | 238 if (!WillPlayBackBitmaps()) |
246 return; | 239 return; |
247 cell_size_ = tile_grid_size; | |
248 DCHECK_GT(cell_size_.width(), 0); | |
249 DCHECK_GT(cell_size_.height(), 0); | |
250 | 240 |
251 int min_x = std::numeric_limits<int>::max(); | 241 pixel_refs_.GatherPixelRefsFromPicture(picture_.get()); |
252 int min_y = std::numeric_limits<int>::max(); | |
253 int max_x = 0; | |
254 int max_y = 0; | |
255 | |
256 skia::DiscardablePixelRefList pixel_refs; | |
257 skia::PixelRefUtils::GatherDiscardablePixelRefs(picture_.get(), &pixel_refs); | |
258 for (skia::DiscardablePixelRefList::const_iterator it = pixel_refs.begin(); | |
259 it != pixel_refs.end(); | |
260 ++it) { | |
261 gfx::Point min( | |
262 RoundDown(static_cast<int>(it->pixel_ref_rect.x()), | |
263 cell_size_.width()), | |
264 RoundDown(static_cast<int>(it->pixel_ref_rect.y()), | |
265 cell_size_.height())); | |
266 gfx::Point max( | |
267 RoundDown(static_cast<int>(std::ceil(it->pixel_ref_rect.right())), | |
268 cell_size_.width()), | |
269 RoundDown(static_cast<int>(std::ceil(it->pixel_ref_rect.bottom())), | |
270 cell_size_.height())); | |
271 | |
272 for (int y = min.y(); y <= max.y(); y += cell_size_.height()) { | |
273 for (int x = min.x(); x <= max.x(); x += cell_size_.width()) { | |
274 PixelRefMapKey key(x, y); | |
275 pixel_refs_[key].push_back(it->pixel_ref); | |
276 } | |
277 } | |
278 | |
279 min_x = std::min(min_x, min.x()); | |
280 min_y = std::min(min_y, min.y()); | |
281 max_x = std::max(max_x, max.x()); | |
282 max_y = std::max(max_y, max.y()); | |
283 } | |
284 | |
285 min_pixel_cell_ = gfx::Point(min_x, min_y); | |
286 max_pixel_cell_ = gfx::Point(max_x, max_y); | |
287 } | 242 } |
288 | 243 |
289 int Picture::Raster(SkCanvas* canvas, | 244 int Picture::Raster(SkCanvas* canvas, |
290 SkPicture::AbortCallback* callback, | 245 SkPicture::AbortCallback* callback, |
291 const Region& negated_content_region, | 246 const Region& negated_content_region, |
292 float contents_scale) const { | 247 float contents_scale) const { |
293 TRACE_EVENT_BEGIN1( | 248 TRACE_EVENT_BEGIN1( |
294 "cc", | 249 "cc", |
295 "Picture::Raster", | 250 "Picture::Raster", |
296 "data", | 251 "data", |
(...skipping 57 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
354 | 309 |
355 void Picture::EmitTraceSnapshotAlias(Picture* original) const { | 310 void Picture::EmitTraceSnapshotAlias(Picture* original) const { |
356 TRACE_EVENT_OBJECT_SNAPSHOT_WITH_ID( | 311 TRACE_EVENT_OBJECT_SNAPSHOT_WITH_ID( |
357 TRACE_DISABLED_BY_DEFAULT("cc.debug.picture") "," | 312 TRACE_DISABLED_BY_DEFAULT("cc.debug.picture") "," |
358 TRACE_DISABLED_BY_DEFAULT("devtools.timeline.picture"), | 313 TRACE_DISABLED_BY_DEFAULT("devtools.timeline.picture"), |
359 "cc::Picture", | 314 "cc::Picture", |
360 this, | 315 this, |
361 TracedPicture::AsTraceablePictureAlias(original)); | 316 TracedPicture::AsTraceablePictureAlias(original)); |
362 } | 317 } |
363 | 318 |
364 base::LazyInstance<Picture::PixelRefs> | 319 PixelRefMap::Iterator Picture::GetPixelRefMapIterator( |
365 Picture::PixelRefIterator::empty_pixel_refs_; | 320 const gfx::Rect& layer_rect) const { |
366 | 321 return PixelRefMap::Iterator(layer_rect, this); |
367 Picture::PixelRefIterator::PixelRefIterator() | |
368 : picture_(NULL), | |
369 current_pixel_refs_(empty_pixel_refs_.Pointer()), | |
370 current_index_(0), | |
371 min_point_(-1, -1), | |
372 max_point_(-1, -1), | |
373 current_x_(0), | |
374 current_y_(0) { | |
375 } | |
376 | |
377 Picture::PixelRefIterator::PixelRefIterator( | |
378 const gfx::Rect& rect, | |
379 const Picture* picture) | |
380 : picture_(picture), | |
381 current_pixel_refs_(empty_pixel_refs_.Pointer()), | |
382 current_index_(0) { | |
383 gfx::Rect layer_rect = picture->layer_rect_; | |
384 gfx::Size cell_size = picture->cell_size_; | |
385 DCHECK(!cell_size.IsEmpty()); | |
386 | |
387 gfx::Rect query_rect(rect); | |
388 // Early out if the query rect doesn't intersect this picture. | |
389 if (!query_rect.Intersects(layer_rect)) { | |
390 min_point_ = gfx::Point(0, 0); | |
391 max_point_ = gfx::Point(0, 0); | |
392 current_x_ = 1; | |
393 current_y_ = 1; | |
394 return; | |
395 } | |
396 | |
397 // First, subtract the layer origin as cells are stored in layer space. | |
398 query_rect.Offset(-layer_rect.OffsetFromOrigin()); | |
399 | |
400 // We have to find a cell_size aligned point that corresponds to | |
401 // query_rect. Point is a multiple of cell_size. | |
402 min_point_ = gfx::Point( | |
403 RoundDown(query_rect.x(), cell_size.width()), | |
404 RoundDown(query_rect.y(), cell_size.height())); | |
405 max_point_ = gfx::Point( | |
406 RoundDown(query_rect.right() - 1, cell_size.width()), | |
407 RoundDown(query_rect.bottom() - 1, cell_size.height())); | |
408 | |
409 // Limit the points to known pixel ref boundaries. | |
410 min_point_ = gfx::Point( | |
411 std::max(min_point_.x(), picture->min_pixel_cell_.x()), | |
412 std::max(min_point_.y(), picture->min_pixel_cell_.y())); | |
413 max_point_ = gfx::Point( | |
414 std::min(max_point_.x(), picture->max_pixel_cell_.x()), | |
415 std::min(max_point_.y(), picture->max_pixel_cell_.y())); | |
416 | |
417 // Make the current x be cell_size.width() less than min point, so that | |
418 // the first increment will point at min_point_. | |
419 current_x_ = min_point_.x() - cell_size.width(); | |
420 current_y_ = min_point_.y(); | |
421 if (current_y_ <= max_point_.y()) | |
422 ++(*this); | |
423 } | |
424 | |
425 Picture::PixelRefIterator::~PixelRefIterator() { | |
426 } | |
427 | |
428 Picture::PixelRefIterator& Picture::PixelRefIterator::operator++() { | |
429 ++current_index_; | |
430 // If we're not at the end of the list, then we have the next item. | |
431 if (current_index_ < current_pixel_refs_->size()) | |
432 return *this; | |
433 | |
434 DCHECK(current_y_ <= max_point_.y()); | |
435 while (true) { | |
436 gfx::Size cell_size = picture_->cell_size_; | |
437 | |
438 // Advance the current grid cell. | |
439 current_x_ += cell_size.width(); | |
440 if (current_x_ > max_point_.x()) { | |
441 current_y_ += cell_size.height(); | |
442 current_x_ = min_point_.x(); | |
443 if (current_y_ > max_point_.y()) { | |
444 current_pixel_refs_ = empty_pixel_refs_.Pointer(); | |
445 current_index_ = 0; | |
446 break; | |
447 } | |
448 } | |
449 | |
450 // If there are no pixel refs at this grid cell, keep incrementing. | |
451 PixelRefMapKey key(current_x_, current_y_); | |
452 PixelRefMap::const_iterator iter = picture_->pixel_refs_.find(key); | |
453 if (iter == picture_->pixel_refs_.end()) | |
454 continue; | |
455 | |
456 // We found a non-empty list: store it and get the first pixel ref. | |
457 current_pixel_refs_ = &iter->second; | |
458 current_index_ = 0; | |
459 break; | |
460 } | |
461 return *this; | |
462 } | 322 } |
463 | 323 |
464 scoped_refptr<base::trace_event::ConvertableToTraceFormat> | 324 scoped_refptr<base::trace_event::ConvertableToTraceFormat> |
465 Picture::AsTraceableRasterData(float scale) const { | 325 Picture::AsTraceableRasterData(float scale) const { |
466 scoped_refptr<base::trace_event::TracedValue> raster_data = | 326 scoped_refptr<base::trace_event::TracedValue> raster_data = |
467 new base::trace_event::TracedValue(); | 327 new base::trace_event::TracedValue(); |
468 TracedValue::SetIDRef(this, raster_data.get(), "picture_id"); | 328 TracedValue::SetIDRef(this, raster_data.get(), "picture_id"); |
469 raster_data->SetDouble("scale", scale); | 329 raster_data->SetDouble("scale", scale); |
470 return raster_data; | 330 return raster_data; |
471 } | 331 } |
472 | 332 |
473 scoped_refptr<base::trace_event::ConvertableToTraceFormat> | 333 scoped_refptr<base::trace_event::ConvertableToTraceFormat> |
474 Picture::AsTraceableRecordData() const { | 334 Picture::AsTraceableRecordData() const { |
475 scoped_refptr<base::trace_event::TracedValue> record_data = | 335 scoped_refptr<base::trace_event::TracedValue> record_data = |
476 new base::trace_event::TracedValue(); | 336 new base::trace_event::TracedValue(); |
477 TracedValue::SetIDRef(this, record_data.get(), "picture_id"); | 337 TracedValue::SetIDRef(this, record_data.get(), "picture_id"); |
478 MathUtil::AddToTracedValue("layer_rect", layer_rect_, record_data.get()); | 338 MathUtil::AddToTracedValue("layer_rect", layer_rect_, record_data.get()); |
479 return record_data; | 339 return record_data; |
480 } | 340 } |
481 | 341 |
482 } // namespace cc | 342 } // namespace cc |
OLD | NEW |