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

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: reviews 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"
13 #include "cc/base/util.h"
9 #include "cc/debug/rendering_stats.h" 14 #include "cc/debug/rendering_stats.h"
10 #include "cc/layers/content_layer_client.h" 15 #include "cc/layers/content_layer_client.h"
11 #include "skia/ext/analysis_canvas.h" 16 #include "skia/ext/analysis_canvas.h"
12 #include "third_party/skia/include/core/SkCanvas.h" 17 #include "third_party/skia/include/core/SkCanvas.h"
13 #include "third_party/skia/include/core/SkData.h" 18 #include "third_party/skia/include/core/SkData.h"
14 #include "third_party/skia/include/core/SkDrawFilter.h" 19 #include "third_party/skia/include/core/SkDrawFilter.h"
15 #include "third_party/skia/include/core/SkPaint.h" 20 #include "third_party/skia/include/core/SkPaint.h"
16 #include "third_party/skia/include/core/SkStream.h" 21 #include "third_party/skia/include/core/SkStream.h"
17 #include "third_party/skia/include/utils/SkPictureUtils.h" 22 #include "third_party/skia/include/utils/SkPictureUtils.h"
18 #include "ui/gfx/rect_conversions.h" 23 #include "ui/gfx/rect_conversions.h"
19 #include "ui/gfx/skia_util.h" 24 #include "ui/gfx/skia_util.h"
20 25
21 namespace { 26 namespace {
22 // URI label for a lazily decoded SkPixelRef. 27 // URI label for a lazily decoded SkPixelRef.
23 const char kLabelLazyDecoded[] = "lazy"; 28 const char kLabelLazyDecoded[] = "lazy";
29
24 // Version ID; to be used in serialization. 30 // Version ID; to be used in serialization.
25 const int kPictureVersion = 1; 31 const int kPictureVersion = 1;
32
26 // Minimum size of a decoded stream that we need. 33 // Minimum size of a decoded stream that we need.
27 // 4 bytes for version, 4 * 4 for each of the 2 rects. 34 // 4 bytes for version, 4 * 4 for each of the 2 rects.
28 const unsigned int kMinPictureSizeBytes = 36; 35 const unsigned int kMinPictureSizeBytes = 36;
29 36
30 class DisableLCDTextFilter : public SkDrawFilter { 37 class DisableLCDTextFilter : public SkDrawFilter {
31 public: 38 public:
32 // SkDrawFilter interface. 39 // SkDrawFilter interface.
33 virtual bool filter(SkPaint* paint, SkDrawFilter::Type type) OVERRIDE { 40 virtual bool filter(SkPaint* paint, SkDrawFilter::Type type) OVERRIDE {
34 if (type != SkDrawFilter::kText_Type) 41 if (type != SkDrawFilter::kText_Type)
35 return true; 42 return true;
(...skipping 58 matching lines...) Expand 10 before | Expand all | Expand 10 after
94 opaque_rect_y, 101 opaque_rect_y,
95 opaque_rect_width, 102 opaque_rect_width,
96 opaque_rect_height); 103 opaque_rect_height);
97 104
98 // Read the picture. This creates an empty picture on failure. 105 // Read the picture. This creates an empty picture on failure.
99 picture_ = skia::AdoptRef(new SkPicture(&stream, success, NULL)); 106 picture_ = skia::AdoptRef(new SkPicture(&stream, success, NULL));
100 } 107 }
101 108
102 Picture::Picture(const skia::RefPtr<SkPicture>& picture, 109 Picture::Picture(const skia::RefPtr<SkPicture>& picture,
103 gfx::Rect layer_rect, 110 gfx::Rect layer_rect,
104 gfx::Rect opaque_rect) : 111 gfx::Rect opaque_rect,
112 const PixelRefMap& pixel_refs) :
105 layer_rect_(layer_rect), 113 layer_rect_(layer_rect),
106 opaque_rect_(opaque_rect), 114 opaque_rect_(opaque_rect),
107 picture_(picture) { 115 picture_(picture),
116 pixel_refs_(pixel_refs) {
108 } 117 }
109 118
110 Picture::~Picture() { 119 Picture::~Picture() {
111 } 120 }
112 121
113 scoped_refptr<Picture> Picture::GetCloneForDrawingOnThread( 122 scoped_refptr<Picture> Picture::GetCloneForDrawingOnThread(
114 unsigned thread_index) const { 123 unsigned thread_index) const {
115 // SkPicture is not thread-safe to rasterize with, this returns a clone 124 // SkPicture is not thread-safe to rasterize with, this returns a clone
116 // to rasterize with on a specific thread. 125 // to rasterize with on a specific thread.
117 CHECK_GT(clones_.size(), thread_index); 126 CHECK_GT(clones_.size(), thread_index);
118 return clones_[thread_index]; 127 return clones_[thread_index];
119 } 128 }
120 129
121 void Picture::CloneForDrawing(int num_threads) { 130 void Picture::CloneForDrawing(int num_threads) {
122 TRACE_EVENT1("cc", "Picture::CloneForDrawing", "num_threads", num_threads); 131 TRACE_EVENT1("cc", "Picture::CloneForDrawing", "num_threads", num_threads);
123 132
124 DCHECK(picture_); 133 DCHECK(picture_);
125 scoped_ptr<SkPicture[]> clones(new SkPicture[num_threads]); 134 scoped_ptr<SkPicture[]> clones(new SkPicture[num_threads]);
126 picture_->clone(&clones[0], num_threads); 135 picture_->clone(&clones[0], num_threads);
127 136
128 clones_.clear(); 137 clones_.clear();
129 for (int i = 0; i < num_threads; i++) { 138 for (int i = 0; i < num_threads; i++) {
130 scoped_refptr<Picture> clone = make_scoped_refptr( 139 scoped_refptr<Picture> clone = make_scoped_refptr(
131 new Picture(skia::AdoptRef(new SkPicture(clones[i])), 140 new Picture(skia::AdoptRef(new SkPicture(clones[i])),
132 layer_rect_, 141 layer_rect_,
133 opaque_rect_)); 142 opaque_rect_,
143 pixel_refs_));
134 clones_.push_back(clone); 144 clones_.push_back(clone);
135 } 145 }
136 } 146 }
137 147
138 void Picture::Record(ContentLayerClient* painter, 148 void Picture::Record(ContentLayerClient* painter,
139 RenderingStats* stats, 149 RenderingStats* stats,
140 const SkTileGridPicture::TileGridInfo& tile_grid_info) { 150 const SkTileGridPicture::TileGridInfo& tile_grid_info) {
141 TRACE_EVENT2("cc", "Picture::Record", 151 TRACE_EVENT2("cc", "Picture::Record",
142 "width", layer_rect_.width(), "height", layer_rect_.height()); 152 "width", layer_rect_.width(), "height", layer_rect_.height());
143 153
(...skipping 31 matching lines...) Expand 10 before | Expand all | Expand 10 after
175 if (stats) { 185 if (stats) {
176 stats->total_paint_time += base::TimeTicks::Now() - begin_paint_time; 186 stats->total_paint_time += base::TimeTicks::Now() - begin_paint_time;
177 stats->total_pixels_painted += 187 stats->total_pixels_painted +=
178 layer_rect_.width() * layer_rect_.height(); 188 layer_rect_.width() * layer_rect_.height();
179 } 189 }
180 190
181 canvas->restore(); 191 canvas->restore();
182 picture_->endRecording(); 192 picture_->endRecording();
183 193
184 opaque_rect_ = gfx::ToEnclosedRect(opaque_layer_rect); 194 opaque_rect_ = gfx::ToEnclosedRect(opaque_layer_rect);
195
196 cell_size_ = gfx::Size(
197 tile_grid_info.fTileInterval.width() +
198 2 * tile_grid_info.fMargin.width(),
199 tile_grid_info.fTileInterval.height() +
200 2 * tile_grid_info.fMargin.height());
201 DCHECK_GT(cell_size_.width(), 0);
202 DCHECK_GT(cell_size_.height(), 0);
203 GatherAllPixelRefs();
185 } 204 }
186 205
187 void Picture::Raster( 206 void Picture::Raster(
188 SkCanvas* canvas, 207 SkCanvas* canvas,
189 gfx::Rect content_rect, 208 gfx::Rect content_rect,
190 float contents_scale, 209 float contents_scale,
191 bool enable_lcd_text) { 210 bool enable_lcd_text) {
192 TRACE_EVENT2("cc", "Picture::Raster", 211 TRACE_EVENT2("cc", "Picture::Raster",
193 "layer width", layer_rect_.width(), 212 "layer width", layer_rect_.width(),
194 "layer height", layer_rect_.height()); 213 "layer height", layer_rect_.height());
195 DCHECK(picture_); 214 DCHECK(picture_);
196 215
197 DisableLCDTextFilter disable_lcd_text_filter; 216 DisableLCDTextFilter disable_lcd_text_filter;
198 217
199 canvas->save(); 218 canvas->save();
200 canvas->clipRect(gfx::RectToSkRect(content_rect)); 219 canvas->clipRect(gfx::RectToSkRect(content_rect));
201 canvas->scale(contents_scale, contents_scale); 220 canvas->scale(contents_scale, contents_scale);
202 canvas->translate(layer_rect_.x(), layer_rect_.y()); 221 canvas->translate(layer_rect_.x(), layer_rect_.y());
203 // Pictures by default have LCD text enabled. 222 // Pictures by default have LCD text enabled.
204 if (!enable_lcd_text) 223 if (!enable_lcd_text)
205 canvas->setDrawFilter(&disable_lcd_text_filter); 224 canvas->setDrawFilter(&disable_lcd_text_filter);
206 canvas->drawPicture(*picture_); 225 canvas->drawPicture(*picture_);
207 canvas->restore(); 226 canvas->restore();
208 } 227 }
209 228
210 void Picture::GatherPixelRefs(const gfx::Rect& layer_rect, 229 void Picture::GatherPixelRefsFromSkia(
211 std::list<skia::LazyPixelRef*>& pixel_ref_list) { 230 gfx::Rect query_rect,
231 std::vector<skia::LazyPixelRef*>* pixel_refs) {
212 DCHECK(picture_); 232 DCHECK(picture_);
213 SkData* pixel_refs = SkPictureUtils::GatherPixelRefs( 233 SkData* pixel_ref_data = SkPictureUtils::GatherPixelRefs(
214 picture_.get(), SkRect::MakeXYWH(layer_rect.x(), 234 picture_.get(),
215 layer_rect.y(), 235 SkRect::MakeXYWH(query_rect.x() - layer_rect_.x(),
216 layer_rect.width(), 236 query_rect.y() - layer_rect_.y(),
217 layer_rect.height())); 237 query_rect.width(),
218 if (!pixel_refs) 238 query_rect.height()));
239 if (!pixel_ref_data)
219 return; 240 return;
220 241
221 void* data = const_cast<void*>(pixel_refs->data()); 242 void* data = const_cast<void*>(pixel_ref_data->data());
222 if (!data) { 243 if (!data) {
223 pixel_refs->unref(); 244 pixel_ref_data->unref();
224 return; 245 return;
225 } 246 }
226 247
227 SkPixelRef** refs = reinterpret_cast<SkPixelRef**>(data); 248 SkPixelRef** refs = reinterpret_cast<SkPixelRef**>(data);
228 for (size_t i = 0; i < pixel_refs->size() / sizeof(*refs); ++i) { 249 for (size_t i = 0; i < pixel_ref_data->size() / sizeof(*refs); ++i) {
229 if (*refs && (*refs)->getURI() && !strncmp( 250 if (*refs && (*refs)->getURI() && !strncmp(
230 (*refs)->getURI(), kLabelLazyDecoded, 4)) { 251 (*refs)->getURI(), kLabelLazyDecoded, 4)) {
231 pixel_ref_list.push_back(static_cast<skia::LazyPixelRef*>(*refs)); 252 pixel_refs->push_back(static_cast<skia::LazyPixelRef*>(*refs));
232 } 253 }
233 refs++; 254 refs++;
234 } 255 }
235 pixel_refs->unref(); 256 pixel_ref_data->unref();
236 } 257 }
237 258
238 void Picture::AsBase64String(std::string* output) const { 259 void Picture::AsBase64String(std::string* output) const {
239 SkDynamicMemoryWStream stream; 260 SkDynamicMemoryWStream stream;
240 261
241 // First save the version, layer_rect_ and opaque_rect. 262 // First save the version, layer_rect_ and opaque_rect.
242 stream.write32(kPictureVersion); 263 stream.write32(kPictureVersion);
243 264
244 stream.write32(layer_rect_.x()); 265 stream.write32(layer_rect_.x());
245 stream.write32(layer_rect_.y()); 266 stream.write32(layer_rect_.y());
246 stream.write32(layer_rect_.width()); 267 stream.write32(layer_rect_.width());
247 stream.write32(layer_rect_.height()); 268 stream.write32(layer_rect_.height());
248 269
249 stream.write32(opaque_rect_.x()); 270 stream.write32(opaque_rect_.x());
250 stream.write32(opaque_rect_.y()); 271 stream.write32(opaque_rect_.y());
251 stream.write32(opaque_rect_.width()); 272 stream.write32(opaque_rect_.width());
252 stream.write32(opaque_rect_.height()); 273 stream.write32(opaque_rect_.height());
253 274
254 // Serialize the picture. 275 // Serialize the picture.
255 picture_->serialize(&stream); 276 picture_->serialize(&stream);
256 277
257 // Encode the picture as base64. 278 // Encode the picture as base64.
258 size_t serialized_size = stream.bytesWritten(); 279 size_t serialized_size = stream.bytesWritten();
259 scoped_ptr<char[]> serialized_picture(new char[serialized_size]); 280 scoped_ptr<char[]> serialized_picture(new char[serialized_size]);
260 stream.copyTo(serialized_picture.get()); 281 stream.copyTo(serialized_picture.get());
261 base::Base64Encode(std::string(serialized_picture.get(), serialized_size), 282 base::Base64Encode(std::string(serialized_picture.get(), serialized_size),
262 output); 283 output);
263 } 284 }
264 285
286 void Picture::GatherAllPixelRefs() {
287 int min_x = std::numeric_limits<int>::max();
288 int min_y = std::numeric_limits<int>::max();
289 int max_x = 0;
290 int max_y = 0;
291
292 // Capture pixel refs for this picture in a grid
293 // with cell_size_ sized cells.
294 for (int y = layer_rect_.y();
295 y < layer_rect_.bottom();
296 y += cell_size_.height()) {
297 for (int x = layer_rect_.x();
298 x < layer_rect_.right();
299 x += cell_size_.width()) {
300 gfx::Rect rect(gfx::Point(x, y), cell_size_);
301 rect.Intersect(layer_rect_);
302
303 std::vector<skia::LazyPixelRef*> pixel_refs;
304 GatherPixelRefsFromSkia(rect, &pixel_refs);
305
306 // Only capture non-empty cells.
307 if (!pixel_refs.empty()) {
308 pixel_refs_[PixelRefMapKey(x, y)].swap(pixel_refs);
309 min_x = std::min(min_x, x);
310 min_y = std::min(min_y, y);
311 max_x = std::max(max_x, x);
312 max_y = std::max(max_y, y);
313 }
314 }
315 }
316
317 min_pixel_cell_ = gfx::Point(min_x, min_y);
318 max_pixel_cell_ = gfx::Point(max_x, max_y);
319 }
320
321 Picture::PixelRefIterator::PixelRefIterator()
322 : picture_(NULL),
323 min_point_(-1, -1),
324 max_point_(-1, -1),
325 current_x_(0),
326 current_y_(0) {
327 sentinel_.push_back(NULL);
328 current_pixel_refs_ = &sentinel_;
329 current_iterator_ = current_pixel_refs_->begin();
330 }
331
332 Picture::PixelRefIterator::PixelRefIterator(const PixelRefIterator& other) {
333 sentinel_.push_back(NULL);
334 *this = other;
335 }
336
337 Picture::PixelRefIterator::PixelRefIterator(
338 gfx::Rect query_rect,
339 const Picture* picture)
340 : picture_(picture) {
341 gfx::Rect layer_rect = picture->layer_rect_;
342 gfx::Size cell_size = picture->cell_size_;
343
344 sentinel_.push_back(NULL);
345 current_pixel_refs_ = &sentinel_;
346 current_iterator_ = current_pixel_refs_->begin();
347
348 // Early out if the query rect doesn't intersect this picture
349 if (!query_rect.Intersects(layer_rect)) {
350 min_point_ = gfx::Point(0, 0);
351 max_point_ = gfx::Point(0, 0);
352 current_x_ = 1;
353 current_y_ = 1;
354 return;
355 }
356
357 // We have to find a cell_size aligned point that
358 // corresponds to query_rect. First, subtract the layer origin,
359 // then ensure the point is a multiple of cell_size,
360 // and finally, add the layer origin back.
361 min_point_ = gfx::Point(
362 RoundDown(query_rect.x() - layer_rect.x(), cell_size.width())
363 + layer_rect.x(),
364 RoundDown(query_rect.y() - layer_rect.y(), cell_size.height())
365 + layer_rect.y());
366 max_point_ = gfx::Point(
367 RoundDown(query_rect.right() - layer_rect.x() - 1, cell_size.width())
368 + layer_rect.x(),
369 RoundDown(query_rect.bottom() - layer_rect.y() - 1, cell_size.height())
370 + layer_rect.y());
371
372 // Limit the points to known pixel ref boundaries.
373 min_point_ = gfx::Point(
374 std::max(min_point_.x(), picture->min_pixel_cell_.x()),
375 std::max(min_point_.y(), picture->min_pixel_cell_.y()));
376 max_point_ = gfx::Point(
377 std::min(max_point_.x(), picture->max_pixel_cell_.x()),
378 std::min(max_point_.y(), picture->max_pixel_cell_.y()));
379
380 // Make the current x be cell_size.width() less than min point, so that
381 // the first increment will point at min_point_.
382 current_x_ = min_point_.x() - cell_size.width();
383 current_y_ = min_point_.y();
384 ++(*this);
385 }
386
387 Picture::PixelRefIterator::~PixelRefIterator() {
388 }
389
390 Picture::PixelRefIterator& Picture::PixelRefIterator::operator++() {
391 ++current_iterator_;
392 // If we're not at the end of the list, then we have the next item.
393 if (current_iterator_ != current_pixel_refs_->end())
394 return *this;
395
396 // If we already passed the max y, reset back to sentinel list.
397 if (current_y_ > max_point_.y()) {
398 current_pixel_refs_ = &sentinel_;
399 current_iterator_ = current_pixel_refs_->begin();
400 return *this;
401 }
402
403 while (true) {
404 gfx::Size cell_size = picture_->cell_size_;
405
406 // Advance the current grid cell.
407 current_x_ += cell_size.width();
408 if (current_x_ > max_point_.x()) {
409 current_y_ += cell_size.height();
410 current_x_ = min_point_.x();
411 if (current_y_ > max_point_.y()) {
412 current_pixel_refs_ = &sentinel_;
413 current_iterator_ = current_pixel_refs_->begin();
414 break;
415 }
416 }
417
418 // If there are no pixel refs at this grid cell, keep incrementing.
419 PixelRefMapKey key(current_x_, current_y_);
420 PixelRefMap::const_iterator iter = picture_->pixel_refs_.find(key);
421 if (iter == picture_->pixel_refs_.end())
422 continue;
423
424 // We found a non-empty list: store it and get the first pixel ref.
425 current_pixel_refs_ = &iter->second;
426 current_iterator_ = current_pixel_refs_->begin();
427 break;
428 }
429 return *this;
430 }
431
432 Picture::PixelRefIterator& Picture::PixelRefIterator::operator=(
433 const PixelRefIterator& other) {
434 if (this == &other)
435 return *this;
436
437 picture_ = other.picture_;
438 // If other is pointing to its sentinel list, set
439 // the iterator to point to our sentinel list.
440 if (other.current_pixel_refs_ == &other.sentinel_) {
441 current_pixel_refs_ = &sentinel_;
442 current_iterator_ = current_pixel_refs_->begin();
443 } else {
444 current_pixel_refs_ = other.current_pixel_refs_;
445 current_iterator_ = other.current_iterator_;
446 }
447 min_point_ = other.min_point_;
448 max_point_ = other.max_point_;
449 current_x_ = other.current_x_;
450 current_y_ = other.current_y_;
451 return *this;
452 }
453
265 } // namespace cc 454 } // namespace cc
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698