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" | |
6 | |
7 #include <algorithm> | |
8 #include <set> | |
9 | |
5 #include "base/debug/trace_event.h" | 10 #include "base/debug/trace_event.h" |
6 #include "cc/debug/rendering_stats.h" | 11 #include "cc/debug/rendering_stats.h" |
7 #include "cc/layers/content_layer_client.h" | 12 #include "cc/layers/content_layer_client.h" |
8 #include "cc/resources/picture.h" | |
9 #include "skia/ext/analysis_canvas.h" | 13 #include "skia/ext/analysis_canvas.h" |
10 #include "third_party/skia/include/core/SkCanvas.h" | 14 #include "third_party/skia/include/core/SkCanvas.h" |
11 #include "third_party/skia/include/core/SkData.h" | 15 #include "third_party/skia/include/core/SkData.h" |
12 #include "third_party/skia/include/core/SkDrawFilter.h" | 16 #include "third_party/skia/include/core/SkDrawFilter.h" |
13 #include "third_party/skia/include/core/SkPaint.h" | 17 #include "third_party/skia/include/core/SkPaint.h" |
14 #include "third_party/skia/include/utils/SkPictureUtils.h" | 18 #include "third_party/skia/include/utils/SkPictureUtils.h" |
15 #include "ui/gfx/rect_conversions.h" | 19 #include "ui/gfx/rect_conversions.h" |
16 #include "ui/gfx/skia_util.h" | 20 #include "ui/gfx/skia_util.h" |
17 | 21 |
18 namespace { | 22 namespace { |
19 // URI label for a lazily decoded SkPixelRef. | 23 // URI label for a lazily decoded SkPixelRef. |
20 const char kLabelLazyDecoded[] = "lazy"; | 24 const char kLabelLazyDecoded[] = "lazy"; |
25 // Size of each of the grid cells for storing lazy pixel refs. | |
26 const int kRegionWidth = 512; | |
27 const int kRegionHeight = 512; | |
21 | 28 |
22 class DisableLCDTextFilter : public SkDrawFilter { | 29 class DisableLCDTextFilter : public SkDrawFilter { |
23 public: | 30 public: |
24 // SkDrawFilter interface. | 31 // SkDrawFilter interface. |
25 virtual bool filter(SkPaint* paint, SkDrawFilter::Type type) OVERRIDE { | 32 virtual bool filter(SkPaint* paint, SkDrawFilter::Type type) OVERRIDE { |
26 if (type != SkDrawFilter::kText_Type) | 33 if (type != SkDrawFilter::kText_Type) |
27 return true; | 34 return true; |
28 | 35 |
29 paint->setLCDRenderText(false); | 36 paint->setLCDRenderText(false); |
30 return true; | 37 return true; |
31 } | 38 } |
32 }; | 39 }; |
33 } // namespace | 40 } // namespace |
34 | 41 |
35 namespace cc { | 42 namespace cc { |
36 | 43 |
37 scoped_refptr<Picture> Picture::Create(gfx::Rect layer_rect) { | 44 scoped_refptr<Picture> Picture::Create(gfx::Rect layer_rect) { |
38 return make_scoped_refptr(new Picture(layer_rect)); | 45 return make_scoped_refptr(new Picture(layer_rect)); |
39 } | 46 } |
40 | 47 |
41 Picture::Picture(gfx::Rect layer_rect) | 48 Picture::Picture(gfx::Rect layer_rect) |
42 : layer_rect_(layer_rect) { | 49 : layer_rect_(layer_rect) { |
43 } | 50 } |
44 | 51 |
45 Picture::Picture(const skia::RefPtr<SkPicture>& picture, | 52 Picture::Picture(const skia::RefPtr<SkPicture>& picture, |
46 gfx::Rect layer_rect, | 53 gfx::Rect layer_rect, |
47 gfx::Rect opaque_rect) : | 54 gfx::Rect opaque_rect, |
55 const PixelRefsMap& lazy_pixel_refs) : | |
48 layer_rect_(layer_rect), | 56 layer_rect_(layer_rect), |
49 opaque_rect_(opaque_rect), | 57 opaque_rect_(opaque_rect), |
50 picture_(picture) { | 58 picture_(picture), |
59 lazy_pixel_refs_(lazy_pixel_refs) { | |
51 } | 60 } |
52 | 61 |
53 Picture::~Picture() { | 62 Picture::~Picture() { |
54 } | 63 } |
55 | 64 |
56 scoped_refptr<Picture> Picture::GetCloneForDrawingOnThread( | 65 scoped_refptr<Picture> Picture::GetCloneForDrawingOnThread( |
57 unsigned thread_index) const { | 66 unsigned thread_index) const { |
58 // SkPicture is not thread-safe to rasterize with, this returns a clone | 67 // SkPicture is not thread-safe to rasterize with, this returns a clone |
59 // to rasterize with on a specific thread. | 68 // to rasterize with on a specific thread. |
60 CHECK_GT(clones_.size(), thread_index); | 69 CHECK_GT(clones_.size(), thread_index); |
61 return clones_[thread_index]; | 70 return clones_[thread_index]; |
62 } | 71 } |
63 | 72 |
64 void Picture::CloneForDrawing(int num_threads) { | 73 void Picture::CloneForDrawing(int num_threads) { |
65 TRACE_EVENT1("cc", "Picture::CloneForDrawing", "num_threads", num_threads); | 74 TRACE_EVENT1("cc", "Picture::CloneForDrawing", "num_threads", num_threads); |
66 | 75 |
67 DCHECK(picture_); | 76 DCHECK(picture_); |
68 scoped_ptr<SkPicture[]> clones(new SkPicture[num_threads]); | 77 scoped_ptr<SkPicture[]> clones(new SkPicture[num_threads]); |
69 picture_->clone(&clones[0], num_threads); | 78 picture_->clone(&clones[0], num_threads); |
70 | 79 |
71 clones_.clear(); | 80 clones_.clear(); |
72 for (int i = 0; i < num_threads; i++) { | 81 for (int i = 0; i < num_threads; i++) { |
73 scoped_refptr<Picture> clone = make_scoped_refptr( | 82 scoped_refptr<Picture> clone = make_scoped_refptr( |
74 new Picture(skia::AdoptRef(new SkPicture(clones[i])), | 83 new Picture(skia::AdoptRef(new SkPicture(clones[i])), |
75 layer_rect_, | 84 layer_rect_, |
76 opaque_rect_)); | 85 opaque_rect_, |
86 lazy_pixel_refs_)); | |
77 clones_.push_back(clone); | 87 clones_.push_back(clone); |
78 } | 88 } |
79 } | 89 } |
80 | 90 |
81 void Picture::Record(ContentLayerClient* painter, | 91 void Picture::Record(ContentLayerClient* painter, |
82 RenderingStats* stats, | 92 RenderingStats* stats, |
83 const SkTileGridPicture::TileGridInfo& tile_grid_info) { | 93 const SkTileGridPicture::TileGridInfo& tile_grid_info) { |
84 TRACE_EVENT2("cc", "Picture::Record", | 94 TRACE_EVENT2("cc", "Picture::Record", |
85 "width", layer_rect_.width(), "height", layer_rect_.height()); | 95 "width", layer_rect_.width(), "height", layer_rect_.height()); |
86 | 96 |
(...skipping 31 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
118 if (stats) { | 128 if (stats) { |
119 stats->total_paint_time += base::TimeTicks::Now() - begin_paint_time; | 129 stats->total_paint_time += base::TimeTicks::Now() - begin_paint_time; |
120 stats->total_pixels_painted += | 130 stats->total_pixels_painted += |
121 layer_rect_.width() * layer_rect_.height(); | 131 layer_rect_.width() * layer_rect_.height(); |
122 } | 132 } |
123 | 133 |
124 canvas->restore(); | 134 canvas->restore(); |
125 picture_->endRecording(); | 135 picture_->endRecording(); |
126 | 136 |
127 opaque_rect_ = gfx::ToEnclosedRect(opaque_layer_rect); | 137 opaque_rect_ = gfx::ToEnclosedRect(opaque_layer_rect); |
138 | |
139 GatherAllPixelRefs(); | |
128 } | 140 } |
129 | 141 |
130 void Picture::Raster( | 142 void Picture::Raster( |
131 SkCanvas* canvas, | 143 SkCanvas* canvas, |
132 gfx::Rect content_rect, | 144 gfx::Rect content_rect, |
133 float contents_scale, | 145 float contents_scale, |
134 bool enable_lcd_text) { | 146 bool enable_lcd_text) { |
135 TRACE_EVENT2("cc", "Picture::Raster", | 147 TRACE_EVENT2("cc", "Picture::Raster", |
136 "layer width", layer_rect_.width(), | 148 "layer width", layer_rect_.width(), |
137 "layer height", layer_rect_.height()); | 149 "layer height", layer_rect_.height()); |
138 DCHECK(picture_); | 150 DCHECK(picture_); |
139 | 151 |
140 DisableLCDTextFilter disable_lcd_text_filter; | 152 DisableLCDTextFilter disable_lcd_text_filter; |
141 | 153 |
142 canvas->save(); | 154 canvas->save(); |
143 canvas->clipRect(gfx::RectToSkRect(content_rect)); | 155 canvas->clipRect(gfx::RectToSkRect(content_rect)); |
144 canvas->scale(contents_scale, contents_scale); | 156 canvas->scale(contents_scale, contents_scale); |
145 canvas->translate(layer_rect_.x(), layer_rect_.y()); | 157 canvas->translate(layer_rect_.x(), layer_rect_.y()); |
146 // Pictures by default have LCD text enabled. | 158 // Pictures by default have LCD text enabled. |
147 if (!enable_lcd_text) | 159 if (!enable_lcd_text) |
148 canvas->setDrawFilter(&disable_lcd_text_filter); | 160 canvas->setDrawFilter(&disable_lcd_text_filter); |
149 canvas->drawPicture(*picture_); | 161 canvas->drawPicture(*picture_); |
150 canvas->restore(); | 162 canvas->restore(); |
151 } | 163 } |
152 | 164 |
153 void Picture::GatherPixelRefs(const gfx::Rect& layer_rect, | 165 void Picture::GatherPixelRefsFromSkia( |
154 std::list<skia::LazyPixelRef*>& pixel_ref_list) { | 166 const gfx::Rect& layer_rect, |
167 std::list<skia::LazyPixelRef*>& pixel_ref_list) { | |
155 DCHECK(picture_); | 168 DCHECK(picture_); |
156 SkData* pixel_refs = SkPictureUtils::GatherPixelRefs( | 169 SkData* pixel_refs = SkPictureUtils::GatherPixelRefs( |
157 picture_.get(), SkRect::MakeXYWH(layer_rect.x(), | 170 picture_.get(), SkRect::MakeXYWH(layer_rect.x(), |
158 layer_rect.y(), | 171 layer_rect.y(), |
159 layer_rect.width(), | 172 layer_rect.width(), |
160 layer_rect.height())); | 173 layer_rect.height())); |
161 if (!pixel_refs) | 174 if (!pixel_refs) |
162 return; | 175 return; |
163 | 176 |
164 void* data = const_cast<void*>(pixel_refs->data()); | 177 void* data = const_cast<void*>(pixel_refs->data()); |
165 if (!data) { | 178 if (!data) { |
166 pixel_refs->unref(); | 179 pixel_refs->unref(); |
167 return; | 180 return; |
168 } | 181 } |
169 | 182 |
170 SkPixelRef** refs = reinterpret_cast<SkPixelRef**>(data); | 183 SkPixelRef** refs = reinterpret_cast<SkPixelRef**>(data); |
171 for (size_t i = 0; i < pixel_refs->size() / sizeof(*refs); ++i) { | 184 for (size_t i = 0; i < pixel_refs->size() / sizeof(*refs); ++i) { |
172 if (*refs && (*refs)->getURI() && !strncmp( | 185 if (*refs && (*refs)->getURI() && !strncmp( |
173 (*refs)->getURI(), kLabelLazyDecoded, 4)) { | 186 (*refs)->getURI(), kLabelLazyDecoded, 4)) { |
174 pixel_ref_list.push_back(static_cast<skia::LazyPixelRef*>(*refs)); | 187 pixel_ref_list.push_back(static_cast<skia::LazyPixelRef*>(*refs)); |
175 } | 188 } |
176 refs++; | 189 refs++; |
177 } | 190 } |
178 pixel_refs->unref(); | 191 pixel_refs->unref(); |
179 } | 192 } |
180 | 193 |
194 void Picture::GatherAllPixelRefs() { | |
195 // Capture pixel refs for this picture in a grid | |
196 // with kRegionWidth by kRegionHeight cells. | |
197 for (int y = layer_rect_.y(); y < layer_rect_.bottom(); y += kRegionHeight) { | |
198 for (int x = layer_rect_.x(); x < layer_rect_.right(); x += kRegionWidth) { | |
199 gfx::Size extent(std::min(kRegionWidth, layer_rect_.right() - x), | |
200 std::min(kRegionHeight, layer_rect_.bottom() - y)); | |
201 gfx::Rect rect(x, y, extent.width(), extent.height()); | |
202 | |
203 std::list<skia::LazyPixelRef*> lazy_pixel_refs; | |
204 GatherPixelRefsFromSkia(rect, lazy_pixel_refs); | |
205 | |
206 // Only capture non-empty cells. | |
207 if (!lazy_pixel_refs.empty()) | |
208 lazy_pixel_refs_[std::make_pair(x, y)].swap(lazy_pixel_refs); | |
209 } | |
210 } | |
211 } | |
212 | |
213 Picture::LazyPixelRefsIterator::LazyPixelRefsIterator() | |
enne (OOO)
2013/04/22 16:47:26
What's the default ctor for?
| |
214 : picture_(0), | |
215 current_pixel_ref_(0), | |
216 min_point_(-1, -1), | |
217 max_point_(-1, -1), | |
218 current_x_(0), | |
219 current_y_(0) { | |
220 } | |
221 | |
222 Picture::LazyPixelRefsIterator::LazyPixelRefsIterator( | |
enne (OOO)
2013/04/22 16:47:26
To be consistent with other code, could you call t
| |
223 gfx::Rect layer_rect, | |
224 const Picture* picture) | |
225 : picture_(picture), | |
226 current_pixel_ref_(NULL) { | |
227 // The min/max point calculation assumes that layer_rect | |
228 // origin's coordinates are non-negative. | |
229 DCHECK(layer_rect.x() >= 0 && layer_rect.y() >= 0); | |
230 min_point_ = gfx::Point( | |
231 (layer_rect.x() / kRegionWidth) * kRegionWidth, | |
232 (layer_rect.y() / kRegionHeight) * kRegionHeight); | |
233 max_point_ = gfx::Point( | |
234 (layer_rect.right() / kRegionWidth) * kRegionWidth, | |
235 (layer_rect.bottom() / kRegionHeight) * kRegionHeight); | |
236 | |
237 // Make the current x be kRegionWidth less than min point, so that | |
238 // the first increment will point at min_point_. | |
239 current_x_ = min_point_.x() - kRegionWidth; | |
240 current_y_ = min_point_.y(); | |
241 ++(*this); | |
242 } | |
243 | |
244 Picture::LazyPixelRefsIterator::~LazyPixelRefsIterator() { | |
245 } | |
246 | |
247 Picture::LazyPixelRefsIterator& Picture::LazyPixelRefsIterator::operator++() { | |
248 // If we're not at the end of the list, then just get the next item. | |
249 if (!current_list_.empty()) { | |
250 current_pixel_ref_ = current_list_.front(); | |
251 current_list_.pop_front(); | |
252 return *this; | |
253 } | |
254 | |
255 // If we already passed the max y, do nothing. | |
256 if (current_y_ > max_point_.y()) | |
257 return *this; | |
258 | |
259 while (true) { | |
260 // Advance the current grid cell. | |
261 current_x_ += kRegionWidth; | |
262 if (current_x_ > max_point_.x()) { | |
263 current_y_ += kRegionHeight; | |
264 current_x_ = min_point_.x(); | |
265 if (current_y_ > max_point_.y()) { | |
266 current_pixel_ref_ = NULL; | |
267 break; | |
268 } | |
269 } | |
270 | |
271 // If there are no pixel refs at this grid cell, keep incrementing. | |
272 PixelRefsMap::const_iterator iter = | |
273 picture_->lazy_pixel_refs_.find(std::make_pair(current_x_, current_y_)); | |
274 if (iter == picture_->lazy_pixel_refs_.end() || iter->second.empty()) | |
275 continue; | |
276 | |
277 // We found a non-empty list: store it and get the first pixel ref. | |
278 current_list_ = iter->second; | |
279 current_pixel_ref_ = current_list_.front(); | |
280 current_list_.pop_front(); | |
281 break; | |
282 } | |
283 return *this; | |
284 } | |
285 | |
181 } // namespace cc | 286 } // namespace cc |
OLD | NEW |