Chromium Code Reviews| 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 |