| 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 |