Chromium Code Reviews| Index: cc/resources/picture.cc |
| diff --git a/cc/resources/picture.cc b/cc/resources/picture.cc |
| index 2b6eca8777fbc0c3d7d280170d3f7008ce85d990..24cbb244a2493a6f7231b0d4f696bf59ea0213e4 100644 |
| --- a/cc/resources/picture.cc |
| +++ b/cc/resources/picture.cc |
| @@ -2,10 +2,14 @@ |
| // Use of this source code is governed by a BSD-style license that can be |
| // found in the LICENSE file. |
| +#include "cc/resources/picture.h" |
| + |
| +#include <algorithm> |
| +#include <set> |
| + |
| #include "base/debug/trace_event.h" |
| #include "cc/debug/rendering_stats.h" |
| #include "cc/layers/content_layer_client.h" |
| -#include "cc/resources/picture.h" |
| #include "skia/ext/analysis_canvas.h" |
| #include "third_party/skia/include/core/SkCanvas.h" |
| #include "third_party/skia/include/core/SkData.h" |
| @@ -18,6 +22,9 @@ |
| namespace { |
| // URI label for a lazily decoded SkPixelRef. |
| const char kLabelLazyDecoded[] = "lazy"; |
| +// Size of each of the grid cells for storing lazy pixel refs. |
| +const int kRegionWidth = 512; |
| +const int kRegionHeight = 512; |
| class DisableLCDTextFilter : public SkDrawFilter { |
| public: |
| @@ -44,10 +51,12 @@ Picture::Picture(gfx::Rect layer_rect) |
| Picture::Picture(const skia::RefPtr<SkPicture>& picture, |
| gfx::Rect layer_rect, |
| - gfx::Rect opaque_rect) : |
| + gfx::Rect opaque_rect, |
| + const PixelRefsMap& lazy_pixel_refs) : |
| layer_rect_(layer_rect), |
| opaque_rect_(opaque_rect), |
| - picture_(picture) { |
| + picture_(picture), |
| + lazy_pixel_refs_(lazy_pixel_refs) { |
| } |
| Picture::~Picture() { |
| @@ -73,7 +82,8 @@ void Picture::CloneForDrawing(int num_threads) { |
| scoped_refptr<Picture> clone = make_scoped_refptr( |
| new Picture(skia::AdoptRef(new SkPicture(clones[i])), |
| layer_rect_, |
| - opaque_rect_)); |
| + opaque_rect_, |
| + lazy_pixel_refs_)); |
| clones_.push_back(clone); |
| } |
| } |
| @@ -125,6 +135,8 @@ void Picture::Record(ContentLayerClient* painter, |
| picture_->endRecording(); |
| opaque_rect_ = gfx::ToEnclosedRect(opaque_layer_rect); |
| + |
| + GatherAllPixelRefs(); |
| } |
| void Picture::Raster( |
| @@ -150,8 +162,9 @@ void Picture::Raster( |
| canvas->restore(); |
| } |
| -void Picture::GatherPixelRefs(const gfx::Rect& layer_rect, |
| - std::list<skia::LazyPixelRef*>& pixel_ref_list) { |
| +void Picture::GatherPixelRefsFromSkia( |
| + const gfx::Rect& layer_rect, |
| + std::list<skia::LazyPixelRef*>& pixel_ref_list) { |
| DCHECK(picture_); |
| SkData* pixel_refs = SkPictureUtils::GatherPixelRefs( |
| picture_.get(), SkRect::MakeXYWH(layer_rect.x(), |
| @@ -178,4 +191,96 @@ void Picture::GatherPixelRefs(const gfx::Rect& layer_rect, |
| pixel_refs->unref(); |
| } |
| +void Picture::GatherAllPixelRefs() { |
| + // Capture pixel refs for this picture in a grid |
| + // with kRegionWidth by kRegionHeight cells. |
| + for (int y = layer_rect_.y(); y < layer_rect_.bottom(); y += kRegionHeight) { |
| + for (int x = layer_rect_.x(); x < layer_rect_.right(); x += kRegionWidth) { |
| + gfx::Size extent(std::min(kRegionWidth, layer_rect_.right() - x), |
| + std::min(kRegionHeight, layer_rect_.bottom() - y)); |
| + gfx::Rect rect(x, y, extent.width(), extent.height()); |
| + |
| + std::list<skia::LazyPixelRef*> lazy_pixel_refs; |
| + GatherPixelRefsFromSkia(rect, lazy_pixel_refs); |
| + |
| + // Only capture non-empty cells. |
| + if (!lazy_pixel_refs.empty()) |
| + lazy_pixel_refs_[std::make_pair(x, y)].swap(lazy_pixel_refs); |
| + } |
| + } |
| +} |
| + |
| +Picture::LazyPixelRefsIterator::LazyPixelRefsIterator() |
|
enne (OOO)
2013/04/22 16:47:26
What's the default ctor for?
|
| + : picture_(0), |
| + current_pixel_ref_(0), |
| + min_point_(-1, -1), |
| + max_point_(-1, -1), |
| + current_x_(0), |
| + current_y_(0) { |
| +} |
| + |
| +Picture::LazyPixelRefsIterator::LazyPixelRefsIterator( |
|
enne (OOO)
2013/04/22 16:47:26
To be consistent with other code, could you call t
|
| + gfx::Rect layer_rect, |
| + const Picture* picture) |
| + : picture_(picture), |
| + current_pixel_ref_(NULL) { |
| + // The min/max point calculation assumes that layer_rect |
| + // origin's coordinates are non-negative. |
| + DCHECK(layer_rect.x() >= 0 && layer_rect.y() >= 0); |
| + min_point_ = gfx::Point( |
| + (layer_rect.x() / kRegionWidth) * kRegionWidth, |
| + (layer_rect.y() / kRegionHeight) * kRegionHeight); |
| + max_point_ = gfx::Point( |
| + (layer_rect.right() / kRegionWidth) * kRegionWidth, |
| + (layer_rect.bottom() / kRegionHeight) * kRegionHeight); |
| + |
| + // Make the current x be kRegionWidth less than min point, so that |
| + // the first increment will point at min_point_. |
| + current_x_ = min_point_.x() - kRegionWidth; |
| + current_y_ = min_point_.y(); |
| + ++(*this); |
| +} |
| + |
| +Picture::LazyPixelRefsIterator::~LazyPixelRefsIterator() { |
| +} |
| + |
| +Picture::LazyPixelRefsIterator& Picture::LazyPixelRefsIterator::operator++() { |
| + // If we're not at the end of the list, then just get the next item. |
| + if (!current_list_.empty()) { |
| + current_pixel_ref_ = current_list_.front(); |
| + current_list_.pop_front(); |
| + return *this; |
| + } |
| + |
| + // If we already passed the max y, do nothing. |
| + if (current_y_ > max_point_.y()) |
| + return *this; |
| + |
| + while (true) { |
| + // Advance the current grid cell. |
| + current_x_ += kRegionWidth; |
| + if (current_x_ > max_point_.x()) { |
| + current_y_ += kRegionHeight; |
| + current_x_ = min_point_.x(); |
| + if (current_y_ > max_point_.y()) { |
| + current_pixel_ref_ = NULL; |
| + break; |
| + } |
| + } |
| + |
| + // If there are no pixel refs at this grid cell, keep incrementing. |
| + PixelRefsMap::const_iterator iter = |
| + picture_->lazy_pixel_refs_.find(std::make_pair(current_x_, current_y_)); |
| + if (iter == picture_->lazy_pixel_refs_.end() || iter->second.empty()) |
| + continue; |
| + |
| + // We found a non-empty list: store it and get the first pixel ref. |
| + current_list_ = iter->second; |
| + current_pixel_ref_ = current_list_.front(); |
| + current_list_.pop_front(); |
| + break; |
| + } |
| + return *this; |
| +} |
| + |
| } // namespace cc |