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> | 7 #include <algorithm> |
8 #include <limits> | 8 #include <limits> |
9 #include <set> | 9 #include <set> |
10 | 10 |
11 #include "base/base64.h" | 11 #include "base/base64.h" |
12 #include "base/command_line.h" | |
12 #include "base/debug/trace_event.h" | 13 #include "base/debug/trace_event.h" |
13 #include "base/values.h" | 14 #include "base/values.h" |
14 #include "cc/base/math_util.h" | 15 #include "cc/base/math_util.h" |
15 #include "cc/base/util.h" | 16 #include "cc/base/util.h" |
16 #include "cc/debug/traced_picture.h" | 17 #include "cc/debug/traced_picture.h" |
17 #include "cc/debug/traced_value.h" | 18 #include "cc/debug/traced_value.h" |
18 #include "cc/layers/content_layer_client.h" | 19 #include "cc/layers/content_layer_client.h" |
19 #include "skia/ext/pixel_ref_utils.h" | 20 #include "skia/ext/pixel_ref_utils.h" |
20 #include "third_party/skia/include/core/SkCanvas.h" | 21 #include "third_party/skia/include/core/SkCanvas.h" |
21 #include "third_party/skia/include/core/SkData.h" | 22 #include "third_party/skia/include/core/SkData.h" |
(...skipping 162 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
184 pixel_refs_(pixel_refs), | 185 pixel_refs_(pixel_refs), |
185 cell_size_(layer_rect.size()) { | 186 cell_size_(layer_rect.size()) { |
186 } | 187 } |
187 | 188 |
188 Picture::~Picture() { | 189 Picture::~Picture() { |
189 TRACE_EVENT_OBJECT_DELETED_WITH_ID( | 190 TRACE_EVENT_OBJECT_DELETED_WITH_ID( |
190 TRACE_DISABLED_BY_DEFAULT("cc.debug"), "cc::Picture", this); | 191 TRACE_DISABLED_BY_DEFAULT("cc.debug"), "cc::Picture", this); |
191 } | 192 } |
192 | 193 |
193 Picture* Picture::GetCloneForDrawingOnThread(unsigned thread_index) { | 194 Picture* Picture::GetCloneForDrawingOnThread(unsigned thread_index) { |
195 // We don't need clones to draw from multiple threads with SkRecord. | |
196 if (playback_.get() != NULL) { | |
197 return this; | |
198 } | |
199 | |
194 // SkPicture is not thread-safe to rasterize with, this returns a clone | 200 // SkPicture is not thread-safe to rasterize with, this returns a clone |
195 // to rasterize with on a specific thread. | 201 // to rasterize with on a specific thread. |
196 CHECK_GE(clones_.size(), thread_index); | 202 CHECK_GE(clones_.size(), thread_index); |
197 return thread_index == clones_.size() ? this : clones_[thread_index].get(); | 203 return thread_index == clones_.size() ? this : clones_[thread_index].get(); |
198 } | 204 } |
199 | 205 |
200 bool Picture::IsSuitableForGpuRasterization() const { | 206 bool Picture::IsSuitableForGpuRasterization() const { |
201 DCHECK(picture_); | 207 DCHECK(picture_); |
202 | 208 |
203 // TODO(alokp): SkPicture::suitableForGpuRasterization needs a GrContext. | 209 // TODO(alokp): SkPicture::suitableForGpuRasterization needs a GrContext. |
204 // Ideally this GrContext should be the same as that for rasterizing this | 210 // Ideally this GrContext should be the same as that for rasterizing this |
205 // picture. But we are on the main thread while the rasterization context | 211 // picture. But we are on the main thread while the rasterization context |
206 // may be on the compositor or raster thread. | 212 // may be on the compositor or raster thread. |
207 // SkPicture::suitableForGpuRasterization is not implemented yet. | 213 // SkPicture::suitableForGpuRasterization is not implemented yet. |
208 // Pass a NULL context for now and discuss with skia folks if the context | 214 // Pass a NULL context for now and discuss with skia folks if the context |
209 // is really needed. | 215 // is really needed. |
210 return picture_->suitableForGpuRasterization(NULL); | 216 return picture_->suitableForGpuRasterization(NULL); |
211 } | 217 } |
212 | 218 |
213 void Picture::CloneForDrawing(int num_threads) { | 219 void Picture::CloneForDrawing(int num_threads) { |
214 TRACE_EVENT1("cc", "Picture::CloneForDrawing", "num_threads", num_threads); | 220 TRACE_EVENT1("cc", "Picture::CloneForDrawing", "num_threads", num_threads); |
215 | 221 |
222 // We don't need clones to draw from multiple threads with SkRecord. | |
223 if (playback_.get() != NULL) { | |
224 return; | |
225 } | |
226 | |
216 DCHECK(picture_); | 227 DCHECK(picture_); |
217 DCHECK(clones_.empty()); | 228 DCHECK(clones_.empty()); |
218 | 229 |
219 // We can re-use this picture for one raster worker thread. | 230 // We can re-use this picture for one raster worker thread. |
220 raster_thread_checker_.DetachFromThread(); | 231 raster_thread_checker_.DetachFromThread(); |
221 | 232 |
222 if (num_threads > 1) { | 233 if (num_threads > 1) { |
223 scoped_ptr<SkPicture[]> clones(new SkPicture[num_threads - 1]); | 234 scoped_ptr<SkPicture[]> clones(new SkPicture[num_threads - 1]); |
224 picture_->clone(&clones[0], num_threads - 1); | 235 picture_->clone(&clones[0], num_threads - 1); |
225 | 236 |
226 for (int i = 0; i < num_threads - 1; i++) { | 237 for (int i = 0; i < num_threads - 1; i++) { |
227 scoped_refptr<Picture> clone = make_scoped_refptr( | 238 scoped_refptr<Picture> clone = make_scoped_refptr( |
228 new Picture(skia::AdoptRef(new SkPicture(clones[i])), | 239 new Picture(skia::AdoptRef(new SkPicture(clones[i])), |
229 layer_rect_, | 240 layer_rect_, |
230 opaque_rect_, | 241 opaque_rect_, |
231 pixel_refs_)); | 242 pixel_refs_)); |
232 clones_.push_back(clone); | 243 clones_.push_back(clone); |
233 | 244 |
234 clone->EmitTraceSnapshotAlias(this); | 245 clone->EmitTraceSnapshotAlias(this); |
235 clone->raster_thread_checker_.DetachFromThread(); | 246 clone->raster_thread_checker_.DetachFromThread(); |
236 } | 247 } |
237 } | 248 } |
238 } | 249 } |
239 | 250 |
240 void Picture::Record(ContentLayerClient* painter, | 251 void Picture::Record(ContentLayerClient* painter, |
241 const SkTileGridPicture::TileGridInfo& tile_grid_info, | 252 const SkTileGridPicture::TileGridInfo& tile_grid_info, |
242 RecordingMode recording_mode) { | 253 RecordingMode recording_mode) { |
254 const CommandLine& command_line = *CommandLine::ForCurrentProcess(); | |
255 // HACK HACK HACK HACK: checkdeps won't let me look at this flag here. :( | |
enne (OOO)
2014/04/17 17:09:49
If you want to make this patch more real, I'd sugg
mtklein
2014/04/17 17:32:04
Ah, thanks, figuring this out was actually my hang
| |
256 if (command_line.HasSwitch("enable-bleeding-edge-rendering-fast-paths")) { | |
257 recording_mode = RECORD_WITH_SKRECORD; | |
258 } | |
259 recording_mode = RECORD_WITH_SKRECORD; | |
260 | |
243 TRACE_EVENT2("cc", | 261 TRACE_EVENT2("cc", |
244 "Picture::Record", | 262 "Picture::Record", |
245 "data", | 263 "data", |
246 AsTraceableRecordData(), | 264 AsTraceableRecordData(), |
247 "recording_mode", | 265 "recording_mode", |
248 recording_mode); | 266 recording_mode); |
249 | 267 |
250 DCHECK(!picture_); | 268 DCHECK(!picture_); |
251 DCHECK(!tile_grid_info.fTileInterval.isEmpty()); | 269 DCHECK(!tile_grid_info.fTileInterval.isEmpty()); |
252 picture_ = skia::AdoptRef(new SkTileGridPicture( | 270 picture_ = skia::AdoptRef(new SkTileGridPicture( |
253 layer_rect_.width(), layer_rect_.height(), tile_grid_info)); | 271 layer_rect_.width(), layer_rect_.height(), tile_grid_info)); |
254 | 272 |
255 skia::RefPtr<SkCanvas> canvas; | 273 skia::RefPtr<SkCanvas> ownedCanvas; |
274 SkCanvas* canvas = NULL; | |
tomhudson
2014/04/17 16:44:03
cc/ dogma considers any naked SkCanvas pointer to
enne (OOO)
2014/04/17 17:09:49
And, on the third day, the clouds opened and Peevi
mtklein
2014/04/17 17:32:04
Do you guys have an UnownedPtr? Or a MaybeOwnedPt
danakj
2014/04/17 17:36:56
You can always ref something that's refcounted. If
enne (OOO)
2014/04/17 17:41:44
More seriously, raw Skia objects do have some code
| |
275 EXPERIMENTAL::SkRecording* recording = NULL; | |
276 | |
256 switch (recording_mode) { | 277 switch (recording_mode) { |
257 case RECORD_NORMALLY: | 278 case RECORD_NORMALLY: |
258 canvas = skia::SharePtr(picture_->beginRecording( | 279 ownedCanvas = skia::SharePtr(picture_->beginRecording( |
259 layer_rect_.width(), | 280 layer_rect_.width(), |
260 layer_rect_.height(), | 281 layer_rect_.height(), |
261 SkPicture::kUsePathBoundsForClip_RecordingFlag | | 282 SkPicture::kUsePathBoundsForClip_RecordingFlag | |
262 SkPicture::kOptimizeForClippedPlayback_RecordingFlag)); | 283 SkPicture::kOptimizeForClippedPlayback_RecordingFlag)); |
284 canvas = ownedCanvas.get(); | |
263 break; | 285 break; |
264 case RECORD_WITH_SK_NULL_CANVAS: | 286 case RECORD_WITH_SK_NULL_CANVAS: |
265 canvas = skia::AdoptRef(SkCreateNullCanvas()); | 287 ownedCanvas = skia::AdoptRef(SkCreateNullCanvas()); |
288 canvas = ownedCanvas.get(); | |
266 break; | 289 break; |
267 case RECORD_WITH_PAINTING_DISABLED: | 290 case RECORD_WITH_PAINTING_DISABLED: |
268 // Blink's GraphicsContext will disable painting when given a NULL | 291 // Blink's GraphicsContext will disable painting when given a NULL |
269 // canvas. | 292 // canvas. |
270 break; | 293 break; |
294 case RECORD_WITH_SKRECORD: { | |
295 recording = EXPERIMENTAL::SkRecording::Create(layer_rect_.width(), | |
296 layer_rect_.height()); | |
297 canvas = recording->canvas(); | |
298 break; | |
299 } | |
271 default: | 300 default: |
272 NOTREACHED(); | 301 NOTREACHED(); |
273 } | 302 } |
274 | 303 |
275 if (canvas) { | 304 if (canvas) { |
276 canvas->save(); | 305 canvas->save(); |
277 canvas->translate(SkFloatToScalar(-layer_rect_.x()), | 306 canvas->translate(SkFloatToScalar(-layer_rect_.x()), |
278 SkFloatToScalar(-layer_rect_.y())); | 307 SkFloatToScalar(-layer_rect_.y())); |
279 | 308 |
280 SkRect layer_skrect = SkRect::MakeXYWH(layer_rect_.x(), | 309 SkRect layer_skrect = SkRect::MakeXYWH(layer_rect_.x(), |
281 layer_rect_.y(), | 310 layer_rect_.y(), |
282 layer_rect_.width(), | 311 layer_rect_.width(), |
283 layer_rect_.height()); | 312 layer_rect_.height()); |
284 canvas->clipRect(layer_skrect); | 313 canvas->clipRect(layer_skrect); |
285 } | 314 } |
286 | 315 |
287 gfx::RectF opaque_layer_rect; | 316 gfx::RectF opaque_layer_rect; |
288 painter->PaintContents(canvas.get(), layer_rect_, &opaque_layer_rect); | 317 painter->PaintContents(canvas, layer_rect_, &opaque_layer_rect); |
289 | 318 |
290 if (canvas) | 319 if (canvas) |
291 canvas->restore(); | 320 canvas->restore(); |
292 if (picture_->getRecordingCanvas()) | 321 if (picture_->getRecordingCanvas()) |
293 picture_->endRecording(); | 322 picture_->endRecording(); |
294 | 323 |
324 if (recording != NULL) { | |
325 playback_.reset(EXPERIMENTAL::SkRecording::Delete(recording)); | |
326 } | |
327 | |
295 opaque_rect_ = gfx::ToEnclosedRect(opaque_layer_rect); | 328 opaque_rect_ = gfx::ToEnclosedRect(opaque_layer_rect); |
296 | 329 |
297 EmitTraceSnapshot(); | 330 EmitTraceSnapshot(); |
298 } | 331 } |
299 | 332 |
300 void Picture::GatherPixelRefs( | 333 void Picture::GatherPixelRefs( |
301 const SkTileGridPicture::TileGridInfo& tile_grid_info) { | 334 const SkTileGridPicture::TileGridInfo& tile_grid_info) { |
302 TRACE_EVENT2("cc", "Picture::GatherPixelRefs", | 335 TRACE_EVENT2("cc", "Picture::GatherPixelRefs", |
303 "width", layer_rect_.width(), | 336 "width", layer_rect_.width(), |
304 "height", layer_rect_.height()); | 337 "height", layer_rect_.height()); |
(...skipping 62 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
367 | 400 |
368 DCHECK(picture_); | 401 DCHECK(picture_); |
369 | 402 |
370 canvas->save(); | 403 canvas->save(); |
371 | 404 |
372 for (Region::Iterator it(negated_content_region); it.has_rect(); it.next()) | 405 for (Region::Iterator it(negated_content_region); it.has_rect(); it.next()) |
373 canvas->clipRect(gfx::RectToSkRect(it.rect()), SkRegion::kDifference_Op); | 406 canvas->clipRect(gfx::RectToSkRect(it.rect()), SkRegion::kDifference_Op); |
374 | 407 |
375 canvas->scale(contents_scale, contents_scale); | 408 canvas->scale(contents_scale, contents_scale); |
376 canvas->translate(layer_rect_.x(), layer_rect_.y()); | 409 canvas->translate(layer_rect_.x(), layer_rect_.y()); |
377 picture_->draw(canvas, callback); | 410 if (playback_.get() != NULL) { |
411 playback_->draw(canvas); | |
412 } else { | |
413 picture_->draw(canvas, callback); | |
414 } | |
378 SkIRect bounds; | 415 SkIRect bounds; |
379 canvas->getClipDeviceBounds(&bounds); | 416 canvas->getClipDeviceBounds(&bounds); |
380 canvas->restore(); | 417 canvas->restore(); |
381 TRACE_EVENT_END1( | 418 TRACE_EVENT_END1( |
382 "cc", "Picture::Raster", | 419 "cc", "Picture::Raster", |
383 "num_pixels_rasterized", bounds.width() * bounds.height()); | 420 "num_pixels_rasterized", bounds.width() * bounds.height()); |
384 return bounds.width() * bounds.height(); | 421 return bounds.width() * bounds.height(); |
385 } | 422 } |
386 | 423 |
387 void Picture::Replay(SkCanvas* canvas) { | 424 void Picture::Replay(SkCanvas* canvas) { |
388 DCHECK(raster_thread_checker_.CalledOnValidThread()); | 425 DCHECK(raster_thread_checker_.CalledOnValidThread()); |
389 TRACE_EVENT_BEGIN0("cc", "Picture::Replay"); | 426 TRACE_EVENT_BEGIN0("cc", "Picture::Replay"); |
390 DCHECK(picture_); | 427 DCHECK(picture_); |
391 | 428 |
392 picture_->draw(canvas); | 429 if (playback_.get() != NULL) { |
430 playback_->draw(canvas); | |
431 } else { | |
432 picture_->draw(canvas); | |
433 } | |
393 SkIRect bounds; | 434 SkIRect bounds; |
394 canvas->getClipDeviceBounds(&bounds); | 435 canvas->getClipDeviceBounds(&bounds); |
395 TRACE_EVENT_END1("cc", "Picture::Replay", | 436 TRACE_EVENT_END1("cc", "Picture::Replay", |
396 "num_pixels_replayed", bounds.width() * bounds.height()); | 437 "num_pixels_replayed", bounds.width() * bounds.height()); |
397 } | 438 } |
398 | 439 |
399 scoped_ptr<base::Value> Picture::AsValue() const { | 440 scoped_ptr<base::Value> Picture::AsValue() const { |
400 SkDynamicMemoryWStream stream; | 441 SkDynamicMemoryWStream stream; |
401 | 442 |
402 // Serialize the picture. | 443 // Serialize the picture. |
(...skipping 137 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
540 | 581 |
541 scoped_refptr<base::debug::ConvertableToTraceFormat> | 582 scoped_refptr<base::debug::ConvertableToTraceFormat> |
542 Picture::AsTraceableRecordData() const { | 583 Picture::AsTraceableRecordData() const { |
543 scoped_ptr<base::DictionaryValue> record_data(new base::DictionaryValue()); | 584 scoped_ptr<base::DictionaryValue> record_data(new base::DictionaryValue()); |
544 record_data->Set("picture_id", TracedValue::CreateIDRef(this).release()); | 585 record_data->Set("picture_id", TracedValue::CreateIDRef(this).release()); |
545 record_data->Set("layer_rect", MathUtil::AsValue(layer_rect_).release()); | 586 record_data->Set("layer_rect", MathUtil::AsValue(layer_rect_).release()); |
546 return TracedValue::FromValue(record_data.release()); | 587 return TracedValue::FromValue(record_data.release()); |
547 } | 588 } |
548 | 589 |
549 } // namespace cc | 590 } // namespace cc |
OLD | NEW |