| OLD | NEW |
| 1 // Copyright 2015 The Chromium Authors. All rights reserved. | 1 // Copyright 2015 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/tiles/software_image_decode_controller.h" | 5 #include "cc/tiles/software_image_decode_controller.h" |
| 6 | 6 |
| 7 #include <stdint.h> | 7 #include <stdint.h> |
| 8 | 8 |
| 9 #include <functional> | 9 #include <functional> |
| 10 | 10 |
| 11 #include "base/format_macros.h" | 11 #include "base/format_macros.h" |
| 12 #include "base/macros.h" | 12 #include "base/macros.h" |
| 13 #include "base/memory/discardable_memory.h" | 13 #include "base/memory/discardable_memory.h" |
| 14 #include "base/memory/ptr_util.h" |
| 14 #include "base/strings/stringprintf.h" | 15 #include "base/strings/stringprintf.h" |
| 15 #include "base/thread_task_runner_handle.h" | 16 #include "base/thread_task_runner_handle.h" |
| 16 #include "base/trace_event/memory_dump_manager.h" | 17 #include "base/trace_event/memory_dump_manager.h" |
| 17 #include "cc/debug/devtools_instrumentation.h" | 18 #include "cc/debug/devtools_instrumentation.h" |
| 18 #include "cc/raster/tile_task_runner.h" | 19 #include "cc/raster/tile_task_runner.h" |
| 19 #include "third_party/skia/include/core/SkCanvas.h" | 20 #include "third_party/skia/include/core/SkCanvas.h" |
| 20 #include "third_party/skia/include/core/SkImage.h" | 21 #include "third_party/skia/include/core/SkImage.h" |
| 21 #include "ui/gfx/skia_util.h" | 22 #include "ui/gfx/skia_util.h" |
| 22 | 23 |
| 23 namespace cc { | 24 namespace cc { |
| (...skipping 316 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 340 return; | 341 return; |
| 341 } | 342 } |
| 342 | 343 |
| 343 auto image_it = decoded_images_.Peek(key); | 344 auto image_it = decoded_images_.Peek(key); |
| 344 if (image_it != decoded_images_.end()) { | 345 if (image_it != decoded_images_.end()) { |
| 345 if (image_it->second->is_locked() || image_it->second->Lock()) | 346 if (image_it->second->is_locked() || image_it->second->Lock()) |
| 346 return; | 347 return; |
| 347 decoded_images_.Erase(image_it); | 348 decoded_images_.Erase(image_it); |
| 348 } | 349 } |
| 349 | 350 |
| 350 scoped_ptr<DecodedImage> decoded_image; | 351 std::unique_ptr<DecodedImage> decoded_image; |
| 351 { | 352 { |
| 352 base::AutoUnlock unlock(lock_); | 353 base::AutoUnlock unlock(lock_); |
| 353 decoded_image = DecodeImageInternal(key, image); | 354 decoded_image = DecodeImageInternal(key, image); |
| 354 } | 355 } |
| 355 | 356 |
| 356 // Abort if we failed to decode the image. | 357 // Abort if we failed to decode the image. |
| 357 if (!decoded_image) | 358 if (!decoded_image) |
| 358 return; | 359 return; |
| 359 | 360 |
| 360 // At this point, it could have been the case that this image was decoded in | 361 // At this point, it could have been the case that this image was decoded in |
| (...skipping 15 matching lines...) Expand all Loading... |
| 376 // ref counts. Unlock it immediately in this case. | 377 // ref counts. Unlock it immediately in this case. |
| 377 if (decoded_images_ref_counts_.find(key) == | 378 if (decoded_images_ref_counts_.find(key) == |
| 378 decoded_images_ref_counts_.end()) { | 379 decoded_images_ref_counts_.end()) { |
| 379 decoded_image->Unlock(); | 380 decoded_image->Unlock(); |
| 380 } | 381 } |
| 381 | 382 |
| 382 decoded_images_.Put(key, std::move(decoded_image)); | 383 decoded_images_.Put(key, std::move(decoded_image)); |
| 383 SanityCheckState(__LINE__, true); | 384 SanityCheckState(__LINE__, true); |
| 384 } | 385 } |
| 385 | 386 |
| 386 scoped_ptr<SoftwareImageDecodeController::DecodedImage> | 387 std::unique_ptr<SoftwareImageDecodeController::DecodedImage> |
| 387 SoftwareImageDecodeController::DecodeImageInternal( | 388 SoftwareImageDecodeController::DecodeImageInternal( |
| 388 const ImageKey& key, | 389 const ImageKey& key, |
| 389 const DrawImage& draw_image) { | 390 const DrawImage& draw_image) { |
| 390 TRACE_EVENT1("disabled-by-default-cc.debug", | 391 TRACE_EVENT1("disabled-by-default-cc.debug", |
| 391 "SoftwareImageDecodeController::DecodeImageInternal", "key", | 392 "SoftwareImageDecodeController::DecodeImageInternal", "key", |
| 392 key.ToString()); | 393 key.ToString()); |
| 393 const SkImage* image = draw_image.image(); | 394 const SkImage* image = draw_image.image(); |
| 394 | 395 |
| 395 // If we can use the original decode, then we don't need to do scaling. We can | 396 // If we can use the original decode, then we don't need to do scaling. We can |
| 396 // just read pixels into the final memory. | 397 // just read pixels into the final memory. |
| 397 if (key.can_use_original_decode()) { | 398 if (key.can_use_original_decode()) { |
| 398 SkImageInfo decoded_info = | 399 SkImageInfo decoded_info = |
| 399 CreateImageInfo(image->width(), image->height(), format_); | 400 CreateImageInfo(image->width(), image->height(), format_); |
| 400 scoped_ptr<base::DiscardableMemory> decoded_pixels; | 401 std::unique_ptr<base::DiscardableMemory> decoded_pixels; |
| 401 { | 402 { |
| 402 TRACE_EVENT0( | 403 TRACE_EVENT0( |
| 403 "disabled-by-default-cc.debug", | 404 "disabled-by-default-cc.debug", |
| 404 "SoftwareImageDecodeController::DecodeImageInternal - allocate " | 405 "SoftwareImageDecodeController::DecodeImageInternal - allocate " |
| 405 "decoded pixels"); | 406 "decoded pixels"); |
| 406 decoded_pixels = | 407 decoded_pixels = |
| 407 base::DiscardableMemoryAllocator::GetInstance() | 408 base::DiscardableMemoryAllocator::GetInstance() |
| 408 ->AllocateLockedDiscardableMemory(decoded_info.minRowBytes() * | 409 ->AllocateLockedDiscardableMemory(decoded_info.minRowBytes() * |
| 409 decoded_info.height()); | 410 decoded_info.height()); |
| 410 } | 411 } |
| 411 { | 412 { |
| 412 TRACE_EVENT0( | 413 TRACE_EVENT0( |
| 413 "disabled-by-default-cc.debug", | 414 "disabled-by-default-cc.debug", |
| 414 "SoftwareImageDecodeController::DecodeImageInternal - read pixels"); | 415 "SoftwareImageDecodeController::DecodeImageInternal - read pixels"); |
| 415 bool result = image->readPixels(decoded_info, decoded_pixels->data(), | 416 bool result = image->readPixels(decoded_info, decoded_pixels->data(), |
| 416 decoded_info.minRowBytes(), 0, 0, | 417 decoded_info.minRowBytes(), 0, 0, |
| 417 SkImage::kDisallow_CachingHint); | 418 SkImage::kDisallow_CachingHint); |
| 418 | 419 |
| 419 if (!result) { | 420 if (!result) { |
| 420 decoded_pixels->Unlock(); | 421 decoded_pixels->Unlock(); |
| 421 return nullptr; | 422 return nullptr; |
| 422 } | 423 } |
| 423 } | 424 } |
| 424 | 425 |
| 425 return make_scoped_ptr( | 426 return base::WrapUnique( |
| 426 new DecodedImage(decoded_info, std::move(decoded_pixels), | 427 new DecodedImage(decoded_info, std::move(decoded_pixels), |
| 427 SkSize::Make(0, 0), next_tracing_id_.GetNext())); | 428 SkSize::Make(0, 0), next_tracing_id_.GetNext())); |
| 428 } | 429 } |
| 429 | 430 |
| 430 // If we get here, that means we couldn't use the original sized decode for | 431 // If we get here, that means we couldn't use the original sized decode for |
| 431 // whatever reason. However, in all cases we do need an original decode to | 432 // whatever reason. However, in all cases we do need an original decode to |
| 432 // either do a scale or to extract a subrect from the image. So, what we can | 433 // either do a scale or to extract a subrect from the image. So, what we can |
| 433 // do is construct a key that would require a full sized decode, then get that | 434 // do is construct a key that would require a full sized decode, then get that |
| 434 // decode via GetDecodedImageForDrawInternal(), use it, and unref it. This | 435 // decode via GetDecodedImageForDrawInternal(), use it, and unref it. This |
| 435 // ensures that if the original sized decode is already available in any of | 436 // ensures that if the original sized decode is already available in any of |
| (...skipping 26 matching lines...) Expand all Loading... |
| 462 result = decoded_pixmap.extractSubset(&decoded_pixmap, | 463 result = decoded_pixmap.extractSubset(&decoded_pixmap, |
| 463 gfx::RectToSkIRect(key.src_rect())); | 464 gfx::RectToSkIRect(key.src_rect())); |
| 464 DCHECK(result) << key.ToString(); | 465 DCHECK(result) << key.ToString(); |
| 465 } | 466 } |
| 466 | 467 |
| 467 // Now we have a decoded_pixmap which represents the src_rect at the | 468 // Now we have a decoded_pixmap which represents the src_rect at the |
| 468 // original scale. All we need to do is scale it. | 469 // original scale. All we need to do is scale it. |
| 469 DCHECK(!key.target_size().IsEmpty()); | 470 DCHECK(!key.target_size().IsEmpty()); |
| 470 SkImageInfo scaled_info = CreateImageInfo( | 471 SkImageInfo scaled_info = CreateImageInfo( |
| 471 key.target_size().width(), key.target_size().height(), format_); | 472 key.target_size().width(), key.target_size().height(), format_); |
| 472 scoped_ptr<base::DiscardableMemory> scaled_pixels; | 473 std::unique_ptr<base::DiscardableMemory> scaled_pixels; |
| 473 { | 474 { |
| 474 TRACE_EVENT0( | 475 TRACE_EVENT0( |
| 475 "disabled-by-default-cc.debug", | 476 "disabled-by-default-cc.debug", |
| 476 "SoftwareImageDecodeController::DecodeImageInternal - allocate " | 477 "SoftwareImageDecodeController::DecodeImageInternal - allocate " |
| 477 "scaled pixels"); | 478 "scaled pixels"); |
| 478 scaled_pixels = base::DiscardableMemoryAllocator::GetInstance() | 479 scaled_pixels = base::DiscardableMemoryAllocator::GetInstance() |
| 479 ->AllocateLockedDiscardableMemory( | 480 ->AllocateLockedDiscardableMemory( |
| 480 scaled_info.minRowBytes() * scaled_info.height()); | 481 scaled_info.minRowBytes() * scaled_info.height()); |
| 481 } | 482 } |
| 482 SkPixmap scaled_pixmap(scaled_info, scaled_pixels->data(), | 483 SkPixmap scaled_pixmap(scaled_info, scaled_pixels->data(), |
| 483 scaled_info.minRowBytes()); | 484 scaled_info.minRowBytes()); |
| 484 // TODO(vmpstr): Start handling more than just high filter quality. | 485 // TODO(vmpstr): Start handling more than just high filter quality. |
| 485 DCHECK_EQ(kHigh_SkFilterQuality, key.filter_quality()); | 486 DCHECK_EQ(kHigh_SkFilterQuality, key.filter_quality()); |
| 486 { | 487 { |
| 487 TRACE_EVENT0( | 488 TRACE_EVENT0( |
| 488 "disabled-by-default-cc.debug", | 489 "disabled-by-default-cc.debug", |
| 489 "SoftwareImageDecodeController::DecodeImageInternal - scale pixels"); | 490 "SoftwareImageDecodeController::DecodeImageInternal - scale pixels"); |
| 490 bool result = | 491 bool result = |
| 491 decoded_pixmap.scalePixels(scaled_pixmap, key.filter_quality()); | 492 decoded_pixmap.scalePixels(scaled_pixmap, key.filter_quality()); |
| 492 DCHECK(result) << key.ToString(); | 493 DCHECK(result) << key.ToString(); |
| 493 } | 494 } |
| 494 | 495 |
| 495 // Release the original sized decode. Any other intermediate result to release | 496 // Release the original sized decode. Any other intermediate result to release |
| 496 // would be the subrect memory. However, that's in a scoped_ptr and will be | 497 // would be the subrect memory. However, that's in a unique_ptr and will be |
| 497 // deleted automatically when we return. | 498 // deleted automatically when we return. |
| 498 DrawWithImageFinished(original_size_draw_image, decoded_draw_image); | 499 DrawWithImageFinished(original_size_draw_image, decoded_draw_image); |
| 499 | 500 |
| 500 return make_scoped_ptr( | 501 return base::WrapUnique( |
| 501 new DecodedImage(scaled_info, std::move(scaled_pixels), | 502 new DecodedImage(scaled_info, std::move(scaled_pixels), |
| 502 SkSize::Make(-key.src_rect().x(), -key.src_rect().y()), | 503 SkSize::Make(-key.src_rect().x(), -key.src_rect().y()), |
| 503 next_tracing_id_.GetNext())); | 504 next_tracing_id_.GetNext())); |
| 504 } | 505 } |
| 505 | 506 |
| 506 DecodedDrawImage SoftwareImageDecodeController::GetDecodedImageForDraw( | 507 DecodedDrawImage SoftwareImageDecodeController::GetDecodedImageForDraw( |
| 507 const DrawImage& draw_image) { | 508 const DrawImage& draw_image) { |
| 508 ImageKey key = ImageKey::FromDrawImage(draw_image); | 509 ImageKey key = ImageKey::FromDrawImage(draw_image); |
| 509 TRACE_EVENT1("disabled-by-default-cc.debug", | 510 TRACE_EVENT1("disabled-by-default-cc.debug", |
| 510 "SoftwareImageDecodeController::GetDecodedImageForDraw", "key", | 511 "SoftwareImageDecodeController::GetDecodedImageForDraw", "key", |
| (...skipping 11 matching lines...) Expand all Loading... |
| 522 DecodedDrawImage SoftwareImageDecodeController::GetDecodedImageForDrawInternal( | 523 DecodedDrawImage SoftwareImageDecodeController::GetDecodedImageForDrawInternal( |
| 523 const ImageKey& key, | 524 const ImageKey& key, |
| 524 const DrawImage& draw_image) { | 525 const DrawImage& draw_image) { |
| 525 TRACE_EVENT1("disabled-by-default-cc.debug", | 526 TRACE_EVENT1("disabled-by-default-cc.debug", |
| 526 "SoftwareImageDecodeController::GetDecodedImageForDrawInternal", | 527 "SoftwareImageDecodeController::GetDecodedImageForDrawInternal", |
| 527 "key", key.ToString()); | 528 "key", key.ToString()); |
| 528 base::AutoLock lock(lock_); | 529 base::AutoLock lock(lock_); |
| 529 auto decoded_images_it = decoded_images_.Get(key); | 530 auto decoded_images_it = decoded_images_.Get(key); |
| 530 // If we found the image and it's locked, then return it. If it's not locked, | 531 // If we found the image and it's locked, then return it. If it's not locked, |
| 531 // erase it from the cache since it might be put into the at-raster cache. | 532 // erase it from the cache since it might be put into the at-raster cache. |
| 532 scoped_ptr<DecodedImage> scoped_decoded_image; | 533 std::unique_ptr<DecodedImage> scoped_decoded_image; |
| 533 DecodedImage* decoded_image = nullptr; | 534 DecodedImage* decoded_image = nullptr; |
| 534 if (decoded_images_it != decoded_images_.end()) { | 535 if (decoded_images_it != decoded_images_.end()) { |
| 535 decoded_image = decoded_images_it->second.get(); | 536 decoded_image = decoded_images_it->second.get(); |
| 536 if (decoded_image->is_locked()) { | 537 if (decoded_image->is_locked()) { |
| 537 RefImage(key); | 538 RefImage(key); |
| 538 SanityCheckState(__LINE__, true); | 539 SanityCheckState(__LINE__, true); |
| 539 return DecodedDrawImage( | 540 return DecodedDrawImage( |
| 540 decoded_image->image(), decoded_image->src_rect_offset(), | 541 decoded_image->image(), decoded_image->src_rect_offset(), |
| 541 GetScaleAdjustment(key), GetDecodedFilterQuality(key)); | 542 GetScaleAdjustment(key), GetDecodedFilterQuality(key)); |
| 542 } else { | 543 } else { |
| (...skipping 343 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 886 << "] target_size[" << target_size_.width() << "x" | 887 << "] target_size[" << target_size_.width() << "x" |
| 887 << target_size_.height() << "] filter_quality[" << filter_quality_ | 888 << target_size_.height() << "] filter_quality[" << filter_quality_ |
| 888 << "] can_use_original_decode [" << can_use_original_decode_ << "] hash [" | 889 << "] can_use_original_decode [" << can_use_original_decode_ << "] hash [" |
| 889 << hash_ << "]"; | 890 << hash_ << "]"; |
| 890 return str.str(); | 891 return str.str(); |
| 891 } | 892 } |
| 892 | 893 |
| 893 // DecodedImage | 894 // DecodedImage |
| 894 SoftwareImageDecodeController::DecodedImage::DecodedImage( | 895 SoftwareImageDecodeController::DecodedImage::DecodedImage( |
| 895 const SkImageInfo& info, | 896 const SkImageInfo& info, |
| 896 scoped_ptr<base::DiscardableMemory> memory, | 897 std::unique_ptr<base::DiscardableMemory> memory, |
| 897 const SkSize& src_rect_offset, | 898 const SkSize& src_rect_offset, |
| 898 uint64_t tracing_id) | 899 uint64_t tracing_id) |
| 899 : locked_(true), | 900 : locked_(true), |
| 900 image_info_(info), | 901 image_info_(info), |
| 901 memory_(std::move(memory)), | 902 memory_(std::move(memory)), |
| 902 src_rect_offset_(src_rect_offset), | 903 src_rect_offset_(src_rect_offset), |
| 903 tracing_id_(tracing_id) { | 904 tracing_id_(tracing_id) { |
| 904 image_ = skia::AdoptRef(SkImage::NewFromRaster( | 905 image_ = skia::AdoptRef(SkImage::NewFromRaster( |
| 905 image_info_, memory_->data(), image_info_.minRowBytes(), | 906 image_info_, memory_->data(), image_info_.minRowBytes(), |
| 906 [](const void* pixels, void* context) {}, nullptr)); | 907 [](const void* pixels, void* context) {}, nullptr)); |
| (...skipping 40 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 947 void SoftwareImageDecodeController::MemoryBudget::ResetUsage() { | 948 void SoftwareImageDecodeController::MemoryBudget::ResetUsage() { |
| 948 current_usage_bytes_ = 0; | 949 current_usage_bytes_ = 0; |
| 949 } | 950 } |
| 950 | 951 |
| 951 size_t SoftwareImageDecodeController::MemoryBudget::GetCurrentUsageSafe() | 952 size_t SoftwareImageDecodeController::MemoryBudget::GetCurrentUsageSafe() |
| 952 const { | 953 const { |
| 953 return current_usage_bytes_.ValueOrDie(); | 954 return current_usage_bytes_.ValueOrDie(); |
| 954 } | 955 } |
| 955 | 956 |
| 956 } // namespace cc | 957 } // namespace cc |
| OLD | NEW |