| 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/macros.h" | 11 #include "base/macros.h" |
| 12 #include "base/memory/discardable_memory.h" | 12 #include "base/memory/discardable_memory.h" |
| 13 #include "base/memory/ptr_util.h" |
| 13 #include "cc/debug/devtools_instrumentation.h" | 14 #include "cc/debug/devtools_instrumentation.h" |
| 14 #include "cc/raster/tile_task_runner.h" | 15 #include "cc/raster/tile_task_runner.h" |
| 15 #include "third_party/skia/include/core/SkCanvas.h" | 16 #include "third_party/skia/include/core/SkCanvas.h" |
| 16 #include "third_party/skia/include/core/SkImage.h" | 17 #include "third_party/skia/include/core/SkImage.h" |
| 17 #include "ui/gfx/skia_util.h" | 18 #include "ui/gfx/skia_util.h" |
| 18 | 19 |
| 19 namespace cc { | 20 namespace cc { |
| 20 namespace { | 21 namespace { |
| 21 | 22 |
| 22 // The amount of memory we can lock ahead of time (128MB). This limit is only | 23 // The amount of memory we can lock ahead of time (128MB). This limit is only |
| (...skipping 301 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 324 return; | 325 return; |
| 325 } | 326 } |
| 326 | 327 |
| 327 auto image_it = decoded_images_.Peek(key); | 328 auto image_it = decoded_images_.Peek(key); |
| 328 if (image_it != decoded_images_.end()) { | 329 if (image_it != decoded_images_.end()) { |
| 329 if (image_it->second->is_locked() || image_it->second->Lock()) | 330 if (image_it->second->is_locked() || image_it->second->Lock()) |
| 330 return; | 331 return; |
| 331 decoded_images_.Erase(image_it); | 332 decoded_images_.Erase(image_it); |
| 332 } | 333 } |
| 333 | 334 |
| 334 scoped_ptr<DecodedImage> decoded_image; | 335 std::unique_ptr<DecodedImage> decoded_image; |
| 335 { | 336 { |
| 336 base::AutoUnlock unlock(lock_); | 337 base::AutoUnlock unlock(lock_); |
| 337 decoded_image = DecodeImageInternal(key, image); | 338 decoded_image = DecodeImageInternal(key, image); |
| 338 } | 339 } |
| 339 | 340 |
| 340 // Abort if we failed to decode the image. | 341 // Abort if we failed to decode the image. |
| 341 if (!decoded_image) | 342 if (!decoded_image) |
| 342 return; | 343 return; |
| 343 | 344 |
| 344 // At this point, it could have been the case that this image was decoded in | 345 // At this point, it could have been the case that this image was decoded in |
| (...skipping 15 matching lines...) Expand all Loading... |
| 360 // ref counts. Unlock it immediately in this case. | 361 // ref counts. Unlock it immediately in this case. |
| 361 if (decoded_images_ref_counts_.find(key) == | 362 if (decoded_images_ref_counts_.find(key) == |
| 362 decoded_images_ref_counts_.end()) { | 363 decoded_images_ref_counts_.end()) { |
| 363 decoded_image->Unlock(); | 364 decoded_image->Unlock(); |
| 364 } | 365 } |
| 365 | 366 |
| 366 decoded_images_.Put(key, std::move(decoded_image)); | 367 decoded_images_.Put(key, std::move(decoded_image)); |
| 367 SanityCheckState(__LINE__, true); | 368 SanityCheckState(__LINE__, true); |
| 368 } | 369 } |
| 369 | 370 |
| 370 scoped_ptr<SoftwareImageDecodeController::DecodedImage> | 371 std::unique_ptr<SoftwareImageDecodeController::DecodedImage> |
| 371 SoftwareImageDecodeController::DecodeImageInternal( | 372 SoftwareImageDecodeController::DecodeImageInternal( |
| 372 const ImageKey& key, | 373 const ImageKey& key, |
| 373 const DrawImage& draw_image) { | 374 const DrawImage& draw_image) { |
| 374 TRACE_EVENT1("disabled-by-default-cc.debug", | 375 TRACE_EVENT1("disabled-by-default-cc.debug", |
| 375 "SoftwareImageDecodeController::DecodeImageInternal", "key", | 376 "SoftwareImageDecodeController::DecodeImageInternal", "key", |
| 376 key.ToString()); | 377 key.ToString()); |
| 377 const SkImage* image = draw_image.image(); | 378 const SkImage* image = draw_image.image(); |
| 378 | 379 |
| 379 // If we can use the original decode, then we don't need to do scaling. We can | 380 // If we can use the original decode, then we don't need to do scaling. We can |
| 380 // just read pixels into the final memory. | 381 // just read pixels into the final memory. |
| 381 if (key.can_use_original_decode()) { | 382 if (key.can_use_original_decode()) { |
| 382 SkImageInfo decoded_info = | 383 SkImageInfo decoded_info = |
| 383 CreateImageInfo(image->width(), image->height(), format_); | 384 CreateImageInfo(image->width(), image->height(), format_); |
| 384 scoped_ptr<base::DiscardableMemory> decoded_pixels; | 385 std::unique_ptr<base::DiscardableMemory> decoded_pixels; |
| 385 { | 386 { |
| 386 TRACE_EVENT0( | 387 TRACE_EVENT0( |
| 387 "disabled-by-default-cc.debug", | 388 "disabled-by-default-cc.debug", |
| 388 "SoftwareImageDecodeController::DecodeImageInternal - allocate " | 389 "SoftwareImageDecodeController::DecodeImageInternal - allocate " |
| 389 "decoded pixels"); | 390 "decoded pixels"); |
| 390 decoded_pixels = | 391 decoded_pixels = |
| 391 base::DiscardableMemoryAllocator::GetInstance() | 392 base::DiscardableMemoryAllocator::GetInstance() |
| 392 ->AllocateLockedDiscardableMemory(decoded_info.minRowBytes() * | 393 ->AllocateLockedDiscardableMemory(decoded_info.minRowBytes() * |
| 393 decoded_info.height()); | 394 decoded_info.height()); |
| 394 } | 395 } |
| 395 { | 396 { |
| 396 TRACE_EVENT0( | 397 TRACE_EVENT0( |
| 397 "disabled-by-default-cc.debug", | 398 "disabled-by-default-cc.debug", |
| 398 "SoftwareImageDecodeController::DecodeImageInternal - read pixels"); | 399 "SoftwareImageDecodeController::DecodeImageInternal - read pixels"); |
| 399 bool result = image->readPixels(decoded_info, decoded_pixels->data(), | 400 bool result = image->readPixels(decoded_info, decoded_pixels->data(), |
| 400 decoded_info.minRowBytes(), 0, 0, | 401 decoded_info.minRowBytes(), 0, 0, |
| 401 SkImage::kDisallow_CachingHint); | 402 SkImage::kDisallow_CachingHint); |
| 402 | 403 |
| 403 if (!result) { | 404 if (!result) { |
| 404 decoded_pixels->Unlock(); | 405 decoded_pixels->Unlock(); |
| 405 return nullptr; | 406 return nullptr; |
| 406 } | 407 } |
| 407 } | 408 } |
| 408 | 409 |
| 409 return make_scoped_ptr(new DecodedImage( | 410 return base::WrapUnique(new DecodedImage( |
| 410 decoded_info, std::move(decoded_pixels), SkSize::Make(0, 0))); | 411 decoded_info, std::move(decoded_pixels), SkSize::Make(0, 0))); |
| 411 } | 412 } |
| 412 | 413 |
| 413 // If we get here, that means we couldn't use the original sized decode for | 414 // If we get here, that means we couldn't use the original sized decode for |
| 414 // whatever reason. However, in all cases we do need an original decode to | 415 // whatever reason. However, in all cases we do need an original decode to |
| 415 // either do a scale or to extract a subrect from the image. So, what we can | 416 // either do a scale or to extract a subrect from the image. So, what we can |
| 416 // do is construct a key that would require a full sized decode, then get that | 417 // do is construct a key that would require a full sized decode, then get that |
| 417 // decode via GetDecodedImageForDrawInternal(), use it, and unref it. This | 418 // decode via GetDecodedImageForDrawInternal(), use it, and unref it. This |
| 418 // ensures that if the original sized decode is already available in any of | 419 // ensures that if the original sized decode is already available in any of |
| 419 // the caches, we reuse that. We also ensure that all the proper locking takes | 420 // the caches, we reuse that. We also ensure that all the proper locking takes |
| (...skipping 25 matching lines...) Expand all Loading... |
| 445 result = decoded_pixmap.extractSubset(&decoded_pixmap, | 446 result = decoded_pixmap.extractSubset(&decoded_pixmap, |
| 446 gfx::RectToSkIRect(key.src_rect())); | 447 gfx::RectToSkIRect(key.src_rect())); |
| 447 DCHECK(result) << key.ToString(); | 448 DCHECK(result) << key.ToString(); |
| 448 } | 449 } |
| 449 | 450 |
| 450 // Now we have a decoded_pixmap which represents the src_rect at the | 451 // Now we have a decoded_pixmap which represents the src_rect at the |
| 451 // original scale. All we need to do is scale it. | 452 // original scale. All we need to do is scale it. |
| 452 DCHECK(!key.target_size().IsEmpty()); | 453 DCHECK(!key.target_size().IsEmpty()); |
| 453 SkImageInfo scaled_info = CreateImageInfo( | 454 SkImageInfo scaled_info = CreateImageInfo( |
| 454 key.target_size().width(), key.target_size().height(), format_); | 455 key.target_size().width(), key.target_size().height(), format_); |
| 455 scoped_ptr<base::DiscardableMemory> scaled_pixels; | 456 std::unique_ptr<base::DiscardableMemory> scaled_pixels; |
| 456 { | 457 { |
| 457 TRACE_EVENT0( | 458 TRACE_EVENT0( |
| 458 "disabled-by-default-cc.debug", | 459 "disabled-by-default-cc.debug", |
| 459 "SoftwareImageDecodeController::DecodeImageInternal - allocate " | 460 "SoftwareImageDecodeController::DecodeImageInternal - allocate " |
| 460 "scaled pixels"); | 461 "scaled pixels"); |
| 461 scaled_pixels = base::DiscardableMemoryAllocator::GetInstance() | 462 scaled_pixels = base::DiscardableMemoryAllocator::GetInstance() |
| 462 ->AllocateLockedDiscardableMemory( | 463 ->AllocateLockedDiscardableMemory( |
| 463 scaled_info.minRowBytes() * scaled_info.height()); | 464 scaled_info.minRowBytes() * scaled_info.height()); |
| 464 } | 465 } |
| 465 SkPixmap scaled_pixmap(scaled_info, scaled_pixels->data(), | 466 SkPixmap scaled_pixmap(scaled_info, scaled_pixels->data(), |
| 466 scaled_info.minRowBytes()); | 467 scaled_info.minRowBytes()); |
| 467 // TODO(vmpstr): Start handling more than just high filter quality. | 468 // TODO(vmpstr): Start handling more than just high filter quality. |
| 468 DCHECK_EQ(kHigh_SkFilterQuality, key.filter_quality()); | 469 DCHECK_EQ(kHigh_SkFilterQuality, key.filter_quality()); |
| 469 { | 470 { |
| 470 TRACE_EVENT0( | 471 TRACE_EVENT0( |
| 471 "disabled-by-default-cc.debug", | 472 "disabled-by-default-cc.debug", |
| 472 "SoftwareImageDecodeController::DecodeImageInternal - scale pixels"); | 473 "SoftwareImageDecodeController::DecodeImageInternal - scale pixels"); |
| 473 bool result = | 474 bool result = |
| 474 decoded_pixmap.scalePixels(scaled_pixmap, key.filter_quality()); | 475 decoded_pixmap.scalePixels(scaled_pixmap, key.filter_quality()); |
| 475 DCHECK(result) << key.ToString(); | 476 DCHECK(result) << key.ToString(); |
| 476 } | 477 } |
| 477 | 478 |
| 478 // Release the original sized decode. Any other intermediate result to release | 479 // Release the original sized decode. Any other intermediate result to release |
| 479 // would be the subrect memory. However, that's in a scoped_ptr and will be | 480 // would be the subrect memory. However, that's in a scoped_ptr and will be |
| 480 // deleted automatically when we return. | 481 // deleted automatically when we return. |
| 481 DrawWithImageFinished(original_size_draw_image, decoded_draw_image); | 482 DrawWithImageFinished(original_size_draw_image, decoded_draw_image); |
| 482 | 483 |
| 483 return make_scoped_ptr( | 484 return base::WrapUnique( |
| 484 new DecodedImage(scaled_info, std::move(scaled_pixels), | 485 new DecodedImage(scaled_info, std::move(scaled_pixels), |
| 485 SkSize::Make(-key.src_rect().x(), -key.src_rect().y()))); | 486 SkSize::Make(-key.src_rect().x(), -key.src_rect().y()))); |
| 486 } | 487 } |
| 487 | 488 |
| 488 DecodedDrawImage SoftwareImageDecodeController::GetDecodedImageForDraw( | 489 DecodedDrawImage SoftwareImageDecodeController::GetDecodedImageForDraw( |
| 489 const DrawImage& draw_image) { | 490 const DrawImage& draw_image) { |
| 490 ImageKey key = ImageKey::FromDrawImage(draw_image); | 491 ImageKey key = ImageKey::FromDrawImage(draw_image); |
| 491 TRACE_EVENT1("disabled-by-default-cc.debug", | 492 TRACE_EVENT1("disabled-by-default-cc.debug", |
| 492 "SoftwareImageDecodeController::GetDecodedImageForDraw", "key", | 493 "SoftwareImageDecodeController::GetDecodedImageForDraw", "key", |
| 493 key.ToString()); | 494 key.ToString()); |
| (...skipping 10 matching lines...) Expand all Loading... |
| 504 DecodedDrawImage SoftwareImageDecodeController::GetDecodedImageForDrawInternal( | 505 DecodedDrawImage SoftwareImageDecodeController::GetDecodedImageForDrawInternal( |
| 505 const ImageKey& key, | 506 const ImageKey& key, |
| 506 const DrawImage& draw_image) { | 507 const DrawImage& draw_image) { |
| 507 TRACE_EVENT1("disabled-by-default-cc.debug", | 508 TRACE_EVENT1("disabled-by-default-cc.debug", |
| 508 "SoftwareImageDecodeController::GetDecodedImageForDrawInternal", | 509 "SoftwareImageDecodeController::GetDecodedImageForDrawInternal", |
| 509 "key", key.ToString()); | 510 "key", key.ToString()); |
| 510 base::AutoLock lock(lock_); | 511 base::AutoLock lock(lock_); |
| 511 auto decoded_images_it = decoded_images_.Get(key); | 512 auto decoded_images_it = decoded_images_.Get(key); |
| 512 // If we found the image and it's locked, then return it. If it's not locked, | 513 // If we found the image and it's locked, then return it. If it's not locked, |
| 513 // erase it from the cache since it might be put into the at-raster cache. | 514 // erase it from the cache since it might be put into the at-raster cache. |
| 514 scoped_ptr<DecodedImage> scoped_decoded_image; | 515 std::unique_ptr<DecodedImage> scoped_decoded_image; |
| 515 DecodedImage* decoded_image = nullptr; | 516 DecodedImage* decoded_image = nullptr; |
| 516 if (decoded_images_it != decoded_images_.end()) { | 517 if (decoded_images_it != decoded_images_.end()) { |
| 517 decoded_image = decoded_images_it->second.get(); | 518 decoded_image = decoded_images_it->second.get(); |
| 518 if (decoded_image->is_locked()) { | 519 if (decoded_image->is_locked()) { |
| 519 RefImage(key); | 520 RefImage(key); |
| 520 SanityCheckState(__LINE__, true); | 521 SanityCheckState(__LINE__, true); |
| 521 return DecodedDrawImage( | 522 return DecodedDrawImage( |
| 522 decoded_image->image(), decoded_image->src_rect_offset(), | 523 decoded_image->image(), decoded_image->src_rect_offset(), |
| 523 GetScaleAdjustment(key), GetDecodedFilterQuality(key)); | 524 GetScaleAdjustment(key), GetDecodedFilterQuality(key)); |
| 524 } else { | 525 } else { |
| (...skipping 307 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 832 << "] target_size[" << target_size_.width() << "x" | 833 << "] target_size[" << target_size_.width() << "x" |
| 833 << target_size_.height() << "] filter_quality[" << filter_quality_ | 834 << target_size_.height() << "] filter_quality[" << filter_quality_ |
| 834 << "] can_use_original_decode [" << can_use_original_decode_ << "] hash [" | 835 << "] can_use_original_decode [" << can_use_original_decode_ << "] hash [" |
| 835 << hash_ << "]"; | 836 << hash_ << "]"; |
| 836 return str.str(); | 837 return str.str(); |
| 837 } | 838 } |
| 838 | 839 |
| 839 // DecodedImage | 840 // DecodedImage |
| 840 SoftwareImageDecodeController::DecodedImage::DecodedImage( | 841 SoftwareImageDecodeController::DecodedImage::DecodedImage( |
| 841 const SkImageInfo& info, | 842 const SkImageInfo& info, |
| 842 scoped_ptr<base::DiscardableMemory> memory, | 843 std::unique_ptr<base::DiscardableMemory> memory, |
| 843 const SkSize& src_rect_offset) | 844 const SkSize& src_rect_offset) |
| 844 : locked_(true), | 845 : locked_(true), |
| 845 image_info_(info), | 846 image_info_(info), |
| 846 memory_(std::move(memory)), | 847 memory_(std::move(memory)), |
| 847 src_rect_offset_(src_rect_offset) { | 848 src_rect_offset_(src_rect_offset) { |
| 848 image_ = skia::AdoptRef(SkImage::NewFromRaster( | 849 image_ = skia::AdoptRef(SkImage::NewFromRaster( |
| 849 image_info_, memory_->data(), image_info_.minRowBytes(), | 850 image_info_, memory_->data(), image_info_.minRowBytes(), |
| 850 [](const void* pixels, void* context) {}, nullptr)); | 851 [](const void* pixels, void* context) {}, nullptr)); |
| 851 } | 852 } |
| 852 | 853 |
| (...skipping 38 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 891 void SoftwareImageDecodeController::MemoryBudget::ResetUsage() { | 892 void SoftwareImageDecodeController::MemoryBudget::ResetUsage() { |
| 892 current_usage_bytes_ = 0; | 893 current_usage_bytes_ = 0; |
| 893 } | 894 } |
| 894 | 895 |
| 895 size_t SoftwareImageDecodeController::MemoryBudget::GetCurrentUsageSafe() | 896 size_t SoftwareImageDecodeController::MemoryBudget::GetCurrentUsageSafe() |
| 896 const { | 897 const { |
| 897 return current_usage_bytes_.ValueOrDie(); | 898 return current_usage_bytes_.ValueOrDie(); |
| 898 } | 899 } |
| 899 | 900 |
| 900 } // namespace cc | 901 } // namespace cc |
| OLD | NEW |