Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(172)

Side by Side Diff: cc/resources/picture.cc

Issue 14230007: cc: Do GatherPixelRefs from skia at record time (Closed) Base URL: https://chromium.googlesource.com/chromium/src.git@master
Patch Set: updated unittests Created 7 years, 8 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch
OLDNEW
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>
10
7 #include "base/base64.h" 11 #include "base/base64.h"
8 #include "base/debug/trace_event.h" 12 #include "base/debug/trace_event.h"
9 #include "cc/debug/rendering_stats.h" 13 #include "cc/debug/rendering_stats.h"
10 #include "cc/layers/content_layer_client.h" 14 #include "cc/layers/content_layer_client.h"
11 #include "skia/ext/analysis_canvas.h" 15 #include "skia/ext/analysis_canvas.h"
12 #include "third_party/skia/include/core/SkCanvas.h" 16 #include "third_party/skia/include/core/SkCanvas.h"
13 #include "third_party/skia/include/core/SkData.h" 17 #include "third_party/skia/include/core/SkData.h"
14 #include "third_party/skia/include/core/SkDrawFilter.h" 18 #include "third_party/skia/include/core/SkDrawFilter.h"
15 #include "third_party/skia/include/core/SkPaint.h" 19 #include "third_party/skia/include/core/SkPaint.h"
16 #include "third_party/skia/include/core/SkStream.h" 20 #include "third_party/skia/include/core/SkStream.h"
17 #include "third_party/skia/include/utils/SkPictureUtils.h" 21 #include "third_party/skia/include/utils/SkPictureUtils.h"
18 #include "ui/gfx/rect_conversions.h" 22 #include "ui/gfx/rect_conversions.h"
19 #include "ui/gfx/skia_util.h" 23 #include "ui/gfx/skia_util.h"
20 24
21 namespace { 25 namespace {
22 // URI label for a lazily decoded SkPixelRef. 26 // URI label for a lazily decoded SkPixelRef.
23 const char kLabelLazyDecoded[] = "lazy"; 27 const char kLabelLazyDecoded[] = "lazy";
28
24 // Version ID; to be used in serialization. 29 // Version ID; to be used in serialization.
25 const int kPictureVersion = 1; 30 const int kPictureVersion = 1;
31
26 // Minimum size of a decoded stream that we need. 32 // Minimum size of a decoded stream that we need.
27 // 4 bytes for version, 4 * 4 for each of the 2 rects. 33 // 4 bytes for version, 4 * 4 for each of the 2 rects.
28 const unsigned int kMinPictureSizeBytes = 36; 34 const unsigned int kMinPictureSizeBytes = 36;
29 35
36 int ToMultiple(int value, int multiple) {
enne (OOO) 2013/04/23 01:59:39 Should this be moved to cc/base/util.h as RoundDow
vmpstr 2013/04/23 20:02:23 Done.
37 return (value < 0) ?
38 (value / multiple - 1) * multiple
39 : (value / multiple) * multiple;
40 }
41
30 class DisableLCDTextFilter : public SkDrawFilter { 42 class DisableLCDTextFilter : public SkDrawFilter {
31 public: 43 public:
32 // SkDrawFilter interface. 44 // SkDrawFilter interface.
33 virtual bool filter(SkPaint* paint, SkDrawFilter::Type type) OVERRIDE { 45 virtual bool filter(SkPaint* paint, SkDrawFilter::Type type) OVERRIDE {
34 if (type != SkDrawFilter::kText_Type) 46 if (type != SkDrawFilter::kText_Type)
35 return true; 47 return true;
36 48
37 paint->setLCDRenderText(false); 49 paint->setLCDRenderText(false);
38 return true; 50 return true;
39 } 51 }
(...skipping 54 matching lines...) Expand 10 before | Expand all | Expand 10 after
94 opaque_rect_y, 106 opaque_rect_y,
95 opaque_rect_width, 107 opaque_rect_width,
96 opaque_rect_height); 108 opaque_rect_height);
97 109
98 // Read the picture. This creates an empty picture on failure. 110 // Read the picture. This creates an empty picture on failure.
99 picture_ = skia::AdoptRef(new SkPicture(&stream, success, NULL)); 111 picture_ = skia::AdoptRef(new SkPicture(&stream, success, NULL));
100 } 112 }
101 113
102 Picture::Picture(const skia::RefPtr<SkPicture>& picture, 114 Picture::Picture(const skia::RefPtr<SkPicture>& picture,
103 gfx::Rect layer_rect, 115 gfx::Rect layer_rect,
104 gfx::Rect opaque_rect) : 116 gfx::Rect opaque_rect,
117 const PixelRefMap& lazy_pixel_refs) :
105 layer_rect_(layer_rect), 118 layer_rect_(layer_rect),
106 opaque_rect_(opaque_rect), 119 opaque_rect_(opaque_rect),
107 picture_(picture) { 120 picture_(picture),
121 lazy_pixel_refs_(lazy_pixel_refs) {
108 } 122 }
109 123
110 Picture::~Picture() { 124 Picture::~Picture() {
111 } 125 }
112 126
113 scoped_refptr<Picture> Picture::GetCloneForDrawingOnThread( 127 scoped_refptr<Picture> Picture::GetCloneForDrawingOnThread(
114 unsigned thread_index) const { 128 unsigned thread_index) const {
115 // SkPicture is not thread-safe to rasterize with, this returns a clone 129 // SkPicture is not thread-safe to rasterize with, this returns a clone
116 // to rasterize with on a specific thread. 130 // to rasterize with on a specific thread.
117 CHECK_GT(clones_.size(), thread_index); 131 CHECK_GT(clones_.size(), thread_index);
118 return clones_[thread_index]; 132 return clones_[thread_index];
119 } 133 }
120 134
121 void Picture::CloneForDrawing(int num_threads) { 135 void Picture::CloneForDrawing(int num_threads) {
122 TRACE_EVENT1("cc", "Picture::CloneForDrawing", "num_threads", num_threads); 136 TRACE_EVENT1("cc", "Picture::CloneForDrawing", "num_threads", num_threads);
123 137
124 DCHECK(picture_); 138 DCHECK(picture_);
125 scoped_ptr<SkPicture[]> clones(new SkPicture[num_threads]); 139 scoped_ptr<SkPicture[]> clones(new SkPicture[num_threads]);
126 picture_->clone(&clones[0], num_threads); 140 picture_->clone(&clones[0], num_threads);
127 141
128 clones_.clear(); 142 clones_.clear();
129 for (int i = 0; i < num_threads; i++) { 143 for (int i = 0; i < num_threads; i++) {
130 scoped_refptr<Picture> clone = make_scoped_refptr( 144 scoped_refptr<Picture> clone = make_scoped_refptr(
131 new Picture(skia::AdoptRef(new SkPicture(clones[i])), 145 new Picture(skia::AdoptRef(new SkPicture(clones[i])),
132 layer_rect_, 146 layer_rect_,
133 opaque_rect_)); 147 opaque_rect_,
148 lazy_pixel_refs_));
134 clones_.push_back(clone); 149 clones_.push_back(clone);
135 } 150 }
136 } 151 }
137 152
138 void Picture::Record(ContentLayerClient* painter, 153 void Picture::Record(ContentLayerClient* painter,
139 RenderingStats* stats, 154 RenderingStats* stats,
140 const SkTileGridPicture::TileGridInfo& tile_grid_info) { 155 const SkTileGridPicture::TileGridInfo& tile_grid_info) {
141 TRACE_EVENT2("cc", "Picture::Record", 156 TRACE_EVENT2("cc", "Picture::Record",
142 "width", layer_rect_.width(), "height", layer_rect_.height()); 157 "width", layer_rect_.width(), "height", layer_rect_.height());
143 158
(...skipping 31 matching lines...) Expand 10 before | Expand all | Expand 10 after
175 if (stats) { 190 if (stats) {
176 stats->total_paint_time += base::TimeTicks::Now() - begin_paint_time; 191 stats->total_paint_time += base::TimeTicks::Now() - begin_paint_time;
177 stats->total_pixels_painted += 192 stats->total_pixels_painted +=
178 layer_rect_.width() * layer_rect_.height(); 193 layer_rect_.width() * layer_rect_.height();
179 } 194 }
180 195
181 canvas->restore(); 196 canvas->restore();
182 picture_->endRecording(); 197 picture_->endRecording();
183 198
184 opaque_rect_ = gfx::ToEnclosedRect(opaque_layer_rect); 199 opaque_rect_ = gfx::ToEnclosedRect(opaque_layer_rect);
200
201 cell_size_ = gfx::Size(
enne (OOO) 2013/04/23 01:59:39 For what it's worth, this isn't going to line up w
reveman 2013/04/23 14:33:24 I would vote for getting this to line up properly
vmpstr 2013/04/23 20:02:23 I think I fixed this. Right now, when we do gather
202 tile_grid_info.fTileInterval.width() +
203 2 * tile_grid_info.fMargin.width(),
204 tile_grid_info.fTileInterval.height() +
205 2 * tile_grid_info.fMargin.height());
206 DCHECK_GT(cell_size_.width(), 0);
207 DCHECK_GT(cell_size_.height(), 0);
208 GatherAllPixelRefs();
185 } 209 }
186 210
187 void Picture::Raster( 211 void Picture::Raster(
188 SkCanvas* canvas, 212 SkCanvas* canvas,
189 gfx::Rect content_rect, 213 gfx::Rect content_rect,
190 float contents_scale, 214 float contents_scale,
191 bool enable_lcd_text) { 215 bool enable_lcd_text) {
192 TRACE_EVENT2("cc", "Picture::Raster", 216 TRACE_EVENT2("cc", "Picture::Raster",
193 "layer width", layer_rect_.width(), 217 "layer width", layer_rect_.width(),
194 "layer height", layer_rect_.height()); 218 "layer height", layer_rect_.height());
195 DCHECK(picture_); 219 DCHECK(picture_);
196 220
197 DisableLCDTextFilter disable_lcd_text_filter; 221 DisableLCDTextFilter disable_lcd_text_filter;
198 222
199 canvas->save(); 223 canvas->save();
200 canvas->clipRect(gfx::RectToSkRect(content_rect)); 224 canvas->clipRect(gfx::RectToSkRect(content_rect));
201 canvas->scale(contents_scale, contents_scale); 225 canvas->scale(contents_scale, contents_scale);
202 canvas->translate(layer_rect_.x(), layer_rect_.y()); 226 canvas->translate(layer_rect_.x(), layer_rect_.y());
203 // Pictures by default have LCD text enabled. 227 // Pictures by default have LCD text enabled.
204 if (!enable_lcd_text) 228 if (!enable_lcd_text)
205 canvas->setDrawFilter(&disable_lcd_text_filter); 229 canvas->setDrawFilter(&disable_lcd_text_filter);
206 canvas->drawPicture(*picture_); 230 canvas->drawPicture(*picture_);
207 canvas->restore(); 231 canvas->restore();
208 } 232 }
209 233
210 void Picture::GatherPixelRefs(const gfx::Rect& layer_rect, 234 void Picture::GatherPixelRefsFromSkia(
211 std::list<skia::LazyPixelRef*>& pixel_ref_list) { 235 const gfx::Rect& query_rect,
enne (OOO) 2013/04/23 01:59:39 const gfx::Rect& => gfx::Rect
vmpstr 2013/04/23 20:02:23 Done.
236 std::list<skia::LazyPixelRef*>& pixel_ref_list) {
reveman 2013/04/23 14:33:24 nit: while you're here. I think the style guide re
vmpstr 2013/04/23 20:02:23 Done.
212 DCHECK(picture_); 237 DCHECK(picture_);
213 SkData* pixel_refs = SkPictureUtils::GatherPixelRefs( 238 SkData* pixel_refs = SkPictureUtils::GatherPixelRefs(
214 picture_.get(), SkRect::MakeXYWH(layer_rect.x(), 239 picture_.get(), SkRect::MakeXYWH(query_rect.x() - layer_rect_.x(),
enne (OOO) 2013/04/23 01:59:39 Haha. Sorry for misreading earlier. Calling it q
vmpstr 2013/04/23 20:02:23 Yeah, I vote in general to avoid naming completely
215 layer_rect.y(), 240 query_rect.y() - layer_rect_.y(),
216 layer_rect.width(), 241 query_rect.width(),
217 layer_rect.height())); 242 query_rect.height()));
218 if (!pixel_refs) 243 if (!pixel_refs)
219 return; 244 return;
220 245
221 void* data = const_cast<void*>(pixel_refs->data()); 246 void* data = const_cast<void*>(pixel_refs->data());
222 if (!data) { 247 if (!data) {
223 pixel_refs->unref(); 248 pixel_refs->unref();
224 return; 249 return;
225 } 250 }
226 251
227 SkPixelRef** refs = reinterpret_cast<SkPixelRef**>(data); 252 SkPixelRef** refs = reinterpret_cast<SkPixelRef**>(data);
(...skipping 27 matching lines...) Expand all
255 picture_->serialize(&stream); 280 picture_->serialize(&stream);
256 281
257 // Encode the picture as base64. 282 // Encode the picture as base64.
258 size_t serialized_size = stream.bytesWritten(); 283 size_t serialized_size = stream.bytesWritten();
259 scoped_ptr<char[]> serialized_picture(new char[serialized_size]); 284 scoped_ptr<char[]> serialized_picture(new char[serialized_size]);
260 stream.copyTo(serialized_picture.get()); 285 stream.copyTo(serialized_picture.get());
261 base::Base64Encode(std::string(serialized_picture.get(), serialized_size), 286 base::Base64Encode(std::string(serialized_picture.get(), serialized_size),
262 output); 287 output);
263 } 288 }
264 289
290 void Picture::GatherAllPixelRefs() {
291 int min_x = std::numeric_limits<int>::max();
292 int min_y = std::numeric_limits<int>::max();
293 int max_x = 0;
294 int max_y = 0;
295
296 // Capture pixel refs for this picture in a grid
297 // with cell_size_ sized cells.
298 for (int y = layer_rect_.y();
299 y < layer_rect_.bottom();
300 y += cell_size_.height()) {
301 for (int x = layer_rect_.x();
302 x < layer_rect_.right();
303 x += cell_size_.width()) {
304 gfx::Size extent(std::min(cell_size_.width(), layer_rect_.right() - x),
enne (OOO) 2013/04/23 01:59:39 I think these lines would be more clearly put as:
vmpstr 2013/04/23 20:02:23 Done.
305 std::min(cell_size_.height(), layer_rect_.bottom() - y));
306 gfx::Rect rect(x, y, extent.width(), extent.height());
307
308 std::list<skia::LazyPixelRef*> lazy_pixel_refs;
309 GatherPixelRefsFromSkia(rect, lazy_pixel_refs);
310
311 // Only capture non-empty cells.
312 if (!lazy_pixel_refs.empty()) {
313 lazy_pixel_refs_[PixelRefMapKey(x, y)].swap(lazy_pixel_refs);
314 min_x = std::min(min_x, x);
315 min_y = std::min(min_y, y);
316 max_x = std::max(max_x, x);
317 max_y = std::max(max_y, y);
318 }
319 }
320 }
321
322 min_lazy_pixel_cell_ = gfx::Point(min_x, min_y);
323 max_lazy_pixel_cell_ = gfx::Point(max_x, max_y);
324 }
325
326 Picture::LazyPixelRefIterator::LazyPixelRefIterator()
327 : picture_(NULL),
328 current_list_(NULL),
329 current_pixel_ref_(NULL),
330 min_point_(-1, -1),
331 max_point_(-1, -1),
332 current_x_(0),
333 current_y_(0) {
334 }
335
336 Picture::LazyPixelRefIterator::LazyPixelRefIterator(
337 gfx::Rect rect,
enne (OOO) 2013/04/23 01:59:39 rect => query_rect?
vmpstr 2013/04/23 20:02:23 Done.
338 const Picture* picture)
339 : picture_(picture),
340 current_list_(NULL),
341 current_pixel_ref_(NULL) {
342 gfx::Rect layer_rect = picture->layer_rect_;
343 gfx::Size cell_size = picture->cell_size_;
344
345 // We have to find a cell_size aligned point that
346 // corresponds to the given rect. First, subtract the layer origin,
347 // then ensure the point is a multiple of cell_size,
348 // and finally, add the layer origin back.
349 min_point_ = gfx::Point(
350 ToMultiple(rect.x() - layer_rect.x(), cell_size.width())
351 + layer_rect.x(),
352 ToMultiple(rect.y() - layer_rect.y(), cell_size.height())
353 + layer_rect.y());
354 max_point_ = gfx::Point(
355 ToMultiple(rect.right() - layer_rect.x(), cell_size.width())
356 + layer_rect.x(),
357 ToMultiple(rect.bottom() - layer_rect.y(), cell_size.height())
358 + layer_rect.y());
359
360 // Limit the points to knows pixel ref boundaries.
enne (OOO) 2013/04/23 01:59:39 knows => known?
vmpstr 2013/04/23 20:02:23 Oops. Fixed.
361 min_point_ = gfx::Point(
362 std::max(min_point_.x(), picture->min_lazy_pixel_cell_.x()),
363 std::max(min_point_.y(), picture->min_lazy_pixel_cell_.y()));
364 max_point_ = gfx::Point(
365 std::min(max_point_.x(), picture->max_lazy_pixel_cell_.x()),
366 std::min(max_point_.y(), picture->max_lazy_pixel_cell_.y()));
367
368 // Make the current x be cell_size.width() less than min point, so that
369 // the first increment will point at min_point_.
370 current_x_ = min_point_.x() - cell_size.width();
371 current_y_ = min_point_.y();
372 ++(*this);
373 }
374
375 Picture::LazyPixelRefIterator::~LazyPixelRefIterator() {
376 }
377
378 Picture::LazyPixelRefIterator& Picture::LazyPixelRefIterator::operator++() {
379 // If we're not at the end of the list, then just get the next item.
380 if (current_list_ &&
381 current_list_iterator_ != current_list_->end()) {
reveman 2013/04/23 14:33:24 I think this would be cleaner if you used a sentin
vmpstr 2013/04/23 20:02:23 Done.
382 current_pixel_ref_ = *current_list_iterator_;
383 ++current_list_iterator_;
384 return *this;
385 }
386
387 // If we already passed the max y, do nothing.
388 if (current_y_ > max_point_.y())
389 return *this;
390
391 while (true) {
392 gfx::Size cell_size = picture_->cell_size_;
393
394 // Advance the current grid cell.
395 current_x_ += cell_size.width();
396 if (current_x_ > max_point_.x()) {
397 current_y_ += cell_size.height();
398 current_x_ = min_point_.x();
399 // Min x can be greater than max x if the query rect
400 // does not intersect the layer rect.
401 if (current_y_ > max_point_.y() ||
402 current_x_ > max_point_.x()) {
403 current_pixel_ref_ = NULL;
404 break;
405 }
406 }
407
408 // If there are no pixel refs at this grid cell, keep incrementing.
409 PixelRefMap::const_iterator iter =
410 picture_->lazy_pixel_refs_.find(PixelRefMapKey(current_x_, current_y_));
reveman 2013/04/23 14:33:24 nit: think it might be a bit cleaner to put "Pixel
vmpstr 2013/04/23 20:02:23 Done.
411 if (iter == picture_->lazy_pixel_refs_.end())
412 continue;
413
414 // We found a non-empty list: store it and get the first pixel ref.
415 current_list_ = &iter->second;
416 current_list_iterator_ = current_list_->begin();
417 current_pixel_ref_ = *current_list_iterator_;
418 ++current_list_iterator_;
419 break;
420 }
421 return *this;
422 }
423
265 } // namespace cc 424 } // namespace cc
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698