| 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 |
| (...skipping 352 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 363 } | 363 } |
| 364 | 364 |
| 365 std::unique_ptr<SoftwareImageDecodeController::DecodedImage> | 365 std::unique_ptr<SoftwareImageDecodeController::DecodedImage> |
| 366 SoftwareImageDecodeController::DecodeImageInternal( | 366 SoftwareImageDecodeController::DecodeImageInternal( |
| 367 const ImageKey& key, | 367 const ImageKey& key, |
| 368 const DrawImage& draw_image) { | 368 const DrawImage& draw_image) { |
| 369 TRACE_EVENT1("disabled-by-default-cc.debug", | 369 TRACE_EVENT1("disabled-by-default-cc.debug", |
| 370 "SoftwareImageDecodeController::DecodeImageInternal", "key", | 370 "SoftwareImageDecodeController::DecodeImageInternal", "key", |
| 371 key.ToString()); | 371 key.ToString()); |
| 372 const SkImage* image = draw_image.image(); | 372 const SkImage* image = draw_image.image(); |
| 373 if (!image) |
| 374 return nullptr; |
| 373 | 375 |
| 374 // If we can use the original decode, then we don't need to do scaling. We can | 376 switch (key.filter_quality()) { |
| 375 // just read pixels into the final memory. | 377 case kNone_SkFilterQuality: |
| 376 if (key.can_use_original_decode()) { | 378 case kLow_SkFilterQuality: |
| 377 SkImageInfo decoded_info = | 379 return GetOriginalImageDecode(key, *image); |
| 378 CreateImageInfo(image->width(), image->height(), format_); | 380 case kMedium_SkFilterQuality: |
| 379 std::unique_ptr<base::DiscardableMemory> decoded_pixels; | 381 NOTIMPLEMENTED(); |
| 380 { | 382 return nullptr; |
| 381 TRACE_EVENT0( | 383 case kHigh_SkFilterQuality: |
| 382 "disabled-by-default-cc.debug", | 384 return GetScaledImageDecode(key, *image); |
| 383 "SoftwareImageDecodeController::DecodeImageInternal - allocate " | 385 default: |
| 384 "decoded pixels"); | 386 NOTREACHED(); |
| 385 decoded_pixels = | 387 return nullptr; |
| 386 base::DiscardableMemoryAllocator::GetInstance() | |
| 387 ->AllocateLockedDiscardableMemory(decoded_info.minRowBytes() * | |
| 388 decoded_info.height()); | |
| 389 } | |
| 390 { | |
| 391 TRACE_EVENT0( | |
| 392 "disabled-by-default-cc.debug", | |
| 393 "SoftwareImageDecodeController::DecodeImageInternal - read pixels"); | |
| 394 bool result = image->readPixels(decoded_info, decoded_pixels->data(), | |
| 395 decoded_info.minRowBytes(), 0, 0, | |
| 396 SkImage::kDisallow_CachingHint); | |
| 397 | |
| 398 if (!result) { | |
| 399 decoded_pixels->Unlock(); | |
| 400 return nullptr; | |
| 401 } | |
| 402 } | |
| 403 | |
| 404 return base::WrapUnique( | |
| 405 new DecodedImage(decoded_info, std::move(decoded_pixels), | |
| 406 SkSize::Make(0, 0), next_tracing_id_.GetNext())); | |
| 407 } | 388 } |
| 408 | |
| 409 // If we get here, that means we couldn't use the original sized decode for | |
| 410 // whatever reason. However, in all cases we do need an original decode to | |
| 411 // either do a scale or to extract a subrect from the image. So, what we can | |
| 412 // do is construct a key that would require a full sized decode, then get that | |
| 413 // decode via GetDecodedImageForDrawInternal(), use it, and unref it. This | |
| 414 // ensures that if the original sized decode is already available in any of | |
| 415 // the caches, we reuse that. We also ensure that all the proper locking takes | |
| 416 // place. If, on the other hand, the decode was not available, | |
| 417 // GetDecodedImageForDrawInternal() would decode the image, and unreffing it | |
| 418 // later ensures that we will store the discardable memory unlocked in the | |
| 419 // cache to be used by future requests. | |
| 420 gfx::Rect full_image_rect(image->width(), image->height()); | |
| 421 DrawImage original_size_draw_image(image, gfx::RectToSkIRect(full_image_rect), | |
| 422 kNone_SkFilterQuality, SkMatrix::I()); | |
| 423 ImageKey original_size_key = | |
| 424 ImageKey::FromDrawImage(original_size_draw_image); | |
| 425 // Sanity checks. | |
| 426 DCHECK(original_size_key.can_use_original_decode()) | |
| 427 << original_size_key.ToString(); | |
| 428 DCHECK(full_image_rect.size() == original_size_key.target_size()); | |
| 429 | |
| 430 auto decoded_draw_image = GetDecodedImageForDrawInternal( | |
| 431 original_size_key, original_size_draw_image); | |
| 432 if (!decoded_draw_image.image()) { | |
| 433 DrawWithImageFinished(original_size_draw_image, decoded_draw_image); | |
| 434 return nullptr; | |
| 435 } | |
| 436 | |
| 437 SkPixmap decoded_pixmap; | |
| 438 bool result = decoded_draw_image.image()->peekPixels(&decoded_pixmap); | |
| 439 DCHECK(result) << key.ToString(); | |
| 440 if (key.src_rect() != full_image_rect) { | |
| 441 result = decoded_pixmap.extractSubset(&decoded_pixmap, | |
| 442 gfx::RectToSkIRect(key.src_rect())); | |
| 443 DCHECK(result) << key.ToString(); | |
| 444 } | |
| 445 | |
| 446 // Now we have a decoded_pixmap which represents the src_rect at the | |
| 447 // original scale. All we need to do is scale it. | |
| 448 DCHECK(!key.target_size().IsEmpty()); | |
| 449 SkImageInfo scaled_info = CreateImageInfo( | |
| 450 key.target_size().width(), key.target_size().height(), format_); | |
| 451 std::unique_ptr<base::DiscardableMemory> scaled_pixels; | |
| 452 { | |
| 453 TRACE_EVENT0( | |
| 454 "disabled-by-default-cc.debug", | |
| 455 "SoftwareImageDecodeController::DecodeImageInternal - allocate " | |
| 456 "scaled pixels"); | |
| 457 scaled_pixels = base::DiscardableMemoryAllocator::GetInstance() | |
| 458 ->AllocateLockedDiscardableMemory( | |
| 459 scaled_info.minRowBytes() * scaled_info.height()); | |
| 460 } | |
| 461 SkPixmap scaled_pixmap(scaled_info, scaled_pixels->data(), | |
| 462 scaled_info.minRowBytes()); | |
| 463 // TODO(vmpstr): Start handling more than just high filter quality. | |
| 464 DCHECK_EQ(kHigh_SkFilterQuality, key.filter_quality()); | |
| 465 { | |
| 466 TRACE_EVENT0( | |
| 467 "disabled-by-default-cc.debug", | |
| 468 "SoftwareImageDecodeController::DecodeImageInternal - scale pixels"); | |
| 469 bool result = | |
| 470 decoded_pixmap.scalePixels(scaled_pixmap, key.filter_quality()); | |
| 471 DCHECK(result) << key.ToString(); | |
| 472 } | |
| 473 | |
| 474 // Release the original sized decode. Any other intermediate result to release | |
| 475 // would be the subrect memory. However, that's in a unique_ptr and will be | |
| 476 // deleted automatically when we return. | |
| 477 DrawWithImageFinished(original_size_draw_image, decoded_draw_image); | |
| 478 | |
| 479 return base::WrapUnique( | |
| 480 new DecodedImage(scaled_info, std::move(scaled_pixels), | |
| 481 SkSize::Make(-key.src_rect().x(), -key.src_rect().y()), | |
| 482 next_tracing_id_.GetNext())); | |
| 483 } | 389 } |
| 484 | 390 |
| 485 DecodedDrawImage SoftwareImageDecodeController::GetDecodedImageForDraw( | 391 DecodedDrawImage SoftwareImageDecodeController::GetDecodedImageForDraw( |
| 486 const DrawImage& draw_image) { | 392 const DrawImage& draw_image) { |
| 487 ImageKey key = ImageKey::FromDrawImage(draw_image); | 393 ImageKey key = ImageKey::FromDrawImage(draw_image); |
| 488 TRACE_EVENT1("disabled-by-default-cc.debug", | 394 TRACE_EVENT1("disabled-by-default-cc.debug", |
| 489 "SoftwareImageDecodeController::GetDecodedImageForDraw", "key", | 395 "SoftwareImageDecodeController::GetDecodedImageForDraw", "key", |
| 490 key.ToString()); | 396 key.ToString()); |
| 491 // If the target size is empty, we can skip this image draw. | 397 // If the target size is empty, we can skip this image draw. |
| 492 if (key.target_size().IsEmpty()) | 398 if (key.target_size().IsEmpty()) |
| (...skipping 91 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 584 DCHECK(decoded_image->is_locked()); | 490 DCHECK(decoded_image->is_locked()); |
| 585 RefAtRasterImage(key); | 491 RefAtRasterImage(key); |
| 586 SanityCheckState(__LINE__, true); | 492 SanityCheckState(__LINE__, true); |
| 587 auto decoded_draw_image = | 493 auto decoded_draw_image = |
| 588 DecodedDrawImage(decoded_image->image(), decoded_image->src_rect_offset(), | 494 DecodedDrawImage(decoded_image->image(), decoded_image->src_rect_offset(), |
| 589 GetScaleAdjustment(key), GetDecodedFilterQuality(key)); | 495 GetScaleAdjustment(key), GetDecodedFilterQuality(key)); |
| 590 decoded_draw_image.set_at_raster_decode(true); | 496 decoded_draw_image.set_at_raster_decode(true); |
| 591 return decoded_draw_image; | 497 return decoded_draw_image; |
| 592 } | 498 } |
| 593 | 499 |
| 500 std::unique_ptr<SoftwareImageDecodeController::DecodedImage> |
| 501 SoftwareImageDecodeController::GetOriginalImageDecode(const ImageKey& key, |
| 502 const SkImage& image) { |
| 503 SkImageInfo decoded_info = |
| 504 CreateImageInfo(image.width(), image.height(), format_); |
| 505 std::unique_ptr<base::DiscardableMemory> decoded_pixels; |
| 506 { |
| 507 TRACE_EVENT0("disabled-by-default-cc.debug", |
| 508 "SoftwareImageDecodeController::GetOriginalImageDecode - " |
| 509 "allocate decoded pixels"); |
| 510 decoded_pixels = |
| 511 base::DiscardableMemoryAllocator::GetInstance() |
| 512 ->AllocateLockedDiscardableMemory(decoded_info.minRowBytes() * |
| 513 decoded_info.height()); |
| 514 } |
| 515 { |
| 516 TRACE_EVENT0("disabled-by-default-cc.debug", |
| 517 "SoftwareImageDecodeController::GetOriginalImageDecode - " |
| 518 "read pixels"); |
| 519 bool result = image.readPixels(decoded_info, decoded_pixels->data(), |
| 520 decoded_info.minRowBytes(), 0, 0, |
| 521 SkImage::kDisallow_CachingHint); |
| 522 |
| 523 if (!result) { |
| 524 decoded_pixels->Unlock(); |
| 525 return nullptr; |
| 526 } |
| 527 } |
| 528 return base::WrapUnique( |
| 529 new DecodedImage(decoded_info, std::move(decoded_pixels), |
| 530 SkSize::Make(0, 0), next_tracing_id_.GetNext())); |
| 531 } |
| 532 |
| 533 std::unique_ptr<SoftwareImageDecodeController::DecodedImage> |
| 534 SoftwareImageDecodeController::GetScaledImageDecode(const ImageKey& key, |
| 535 const SkImage& image) { |
| 536 // Construct a key to use in GetDecodedImageForDrawInternal(). |
| 537 // This allows us to reuse an image in any cache if available. |
| 538 gfx::Rect full_image_rect(image.width(), image.height()); |
| 539 DrawImage original_size_draw_image(&image, |
| 540 gfx::RectToSkIRect(full_image_rect), |
| 541 kNone_SkFilterQuality, SkMatrix::I()); |
| 542 ImageKey original_size_key = |
| 543 ImageKey::FromDrawImage(original_size_draw_image); |
| 544 // Sanity checks. |
| 545 DCHECK(original_size_key.can_use_original_decode()) |
| 546 << original_size_key.ToString(); |
| 547 DCHECK(full_image_rect.size() == original_size_key.target_size()); |
| 548 |
| 549 auto decoded_draw_image = GetDecodedImageForDrawInternal( |
| 550 original_size_key, original_size_draw_image); |
| 551 if (!decoded_draw_image.image()) { |
| 552 DrawWithImageFinished(original_size_draw_image, decoded_draw_image); |
| 553 return nullptr; |
| 554 } |
| 555 |
| 556 SkPixmap decoded_pixmap; |
| 557 bool result = decoded_draw_image.image()->peekPixels(&decoded_pixmap); |
| 558 DCHECK(result) << key.ToString(); |
| 559 if (key.src_rect() != full_image_rect) { |
| 560 result = decoded_pixmap.extractSubset(&decoded_pixmap, |
| 561 gfx::RectToSkIRect(key.src_rect())); |
| 562 DCHECK(result) << key.ToString(); |
| 563 } |
| 564 |
| 565 DCHECK(!key.target_size().IsEmpty()); |
| 566 SkImageInfo scaled_info = CreateImageInfo( |
| 567 key.target_size().width(), key.target_size().height(), format_); |
| 568 std::unique_ptr<base::DiscardableMemory> scaled_pixels; |
| 569 { |
| 570 TRACE_EVENT0( |
| 571 "disabled-by-default-cc.debug", |
| 572 "SoftwareImageDecodeController::ScaleImage - allocate scaled pixels"); |
| 573 scaled_pixels = base::DiscardableMemoryAllocator::GetInstance() |
| 574 ->AllocateLockedDiscardableMemory( |
| 575 scaled_info.minRowBytes() * scaled_info.height()); |
| 576 } |
| 577 SkPixmap scaled_pixmap(scaled_info, scaled_pixels->data(), |
| 578 scaled_info.minRowBytes()); |
| 579 // TODO(vmpstr): Start handling more than just high filter quality. |
| 580 DCHECK_EQ(kHigh_SkFilterQuality, key.filter_quality()); |
| 581 { |
| 582 TRACE_EVENT0("disabled-by-default-cc.debug", |
| 583 "SoftwareImageDecodeController::ScaleImage - scale pixels"); |
| 584 bool result = |
| 585 decoded_pixmap.scalePixels(scaled_pixmap, key.filter_quality()); |
| 586 DCHECK(result) << key.ToString(); |
| 587 } |
| 588 |
| 589 // Release the original sized decode. Any other intermediate result to release |
| 590 // would be the subrect memory. However, that's in a scoped_ptr and will be |
| 591 // deleted automatically when we return. |
| 592 DrawWithImageFinished(original_size_draw_image, decoded_draw_image); |
| 593 |
| 594 return base::WrapUnique( |
| 595 new DecodedImage(scaled_info, std::move(scaled_pixels), |
| 596 SkSize::Make(-key.src_rect().x(), -key.src_rect().y()), |
| 597 next_tracing_id_.GetNext())); |
| 598 } |
| 599 |
| 594 void SoftwareImageDecodeController::DrawWithImageFinished( | 600 void SoftwareImageDecodeController::DrawWithImageFinished( |
| 595 const DrawImage& image, | 601 const DrawImage& image, |
| 596 const DecodedDrawImage& decoded_image) { | 602 const DecodedDrawImage& decoded_image) { |
| 597 TRACE_EVENT1("disabled-by-default-cc.debug", | 603 TRACE_EVENT1("disabled-by-default-cc.debug", |
| 598 "SoftwareImageDecodeController::DrawWithImageFinished", "key", | 604 "SoftwareImageDecodeController::DrawWithImageFinished", "key", |
| 599 ImageKey::FromDrawImage(image).ToString()); | 605 ImageKey::FromDrawImage(image).ToString()); |
| 600 ImageKey key = ImageKey::FromDrawImage(image); | 606 ImageKey key = ImageKey::FromDrawImage(image); |
| 601 if (!decoded_image.image() || !CanHandleImage(key)) | 607 if (!decoded_image.image() || !CanHandleImage(key)) |
| 602 return; | 608 return; |
| 603 | 609 |
| (...skipping 322 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 926 void SoftwareImageDecodeController::MemoryBudget::ResetUsage() { | 932 void SoftwareImageDecodeController::MemoryBudget::ResetUsage() { |
| 927 current_usage_bytes_ = 0; | 933 current_usage_bytes_ = 0; |
| 928 } | 934 } |
| 929 | 935 |
| 930 size_t SoftwareImageDecodeController::MemoryBudget::GetCurrentUsageSafe() | 936 size_t SoftwareImageDecodeController::MemoryBudget::GetCurrentUsageSafe() |
| 931 const { | 937 const { |
| 932 return current_usage_bytes_.ValueOrDie(); | 938 return current_usage_bytes_.ValueOrDie(); |
| 933 } | 939 } |
| 934 | 940 |
| 935 } // namespace cc | 941 } // namespace cc |
| OLD | NEW |