| 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 253 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 264 | 264 |
| 265 auto image_it = decoded_images_.Peek(key); | 265 auto image_it = decoded_images_.Peek(key); |
| 266 if (image_it != decoded_images_.end()) { | 266 if (image_it != decoded_images_.end()) { |
| 267 if (image_it->second->is_locked() || image_it->second->Lock()) { | 267 if (image_it->second->is_locked() || image_it->second->Lock()) { |
| 268 pending_image_tasks_.erase(key); | 268 pending_image_tasks_.erase(key); |
| 269 return; | 269 return; |
| 270 } | 270 } |
| 271 decoded_images_.Erase(image_it); | 271 decoded_images_.Erase(image_it); |
| 272 } | 272 } |
| 273 | 273 |
| 274 scoped_refptr<DecodedImage> decoded_image; | 274 scoped_ptr<DecodedImage> decoded_image; |
| 275 { | 275 { |
| 276 base::AutoUnlock unlock(lock_); | 276 base::AutoUnlock unlock(lock_); |
| 277 decoded_image = DecodeImageInternal(key, image); | 277 decoded_image = DecodeImageInternal(key, image); |
| 278 } | 278 } |
| 279 | 279 |
| 280 // Erase the pending task from the queue, since the task won't be doing | 280 // Erase the pending task from the queue, since the task won't be doing |
| 281 // anything useful after this function terminates. That is, if this image | 281 // anything useful after this function terminates. That is, if this image |
| 282 // needs to be decoded again, we have to create a new task. | 282 // needs to be decoded again, we have to create a new task. |
| 283 pending_image_tasks_.erase(key); | 283 pending_image_tasks_.erase(key); |
| 284 | 284 |
| (...skipping 20 matching lines...) Expand all Loading... |
| 305 // ref counts. Unlock it immediately in this case. | 305 // ref counts. Unlock it immediately in this case. |
| 306 if (decoded_images_ref_counts_.find(key) == | 306 if (decoded_images_ref_counts_.find(key) == |
| 307 decoded_images_ref_counts_.end()) { | 307 decoded_images_ref_counts_.end()) { |
| 308 decoded_image->Unlock(); | 308 decoded_image->Unlock(); |
| 309 } | 309 } |
| 310 | 310 |
| 311 decoded_images_.Put(key, std::move(decoded_image)); | 311 decoded_images_.Put(key, std::move(decoded_image)); |
| 312 SanityCheckState(__LINE__, true); | 312 SanityCheckState(__LINE__, true); |
| 313 } | 313 } |
| 314 | 314 |
| 315 scoped_refptr<SoftwareImageDecodeController::DecodedImage> | 315 scoped_ptr<SoftwareImageDecodeController::DecodedImage> |
| 316 SoftwareImageDecodeController::DecodeImageInternal( | 316 SoftwareImageDecodeController::DecodeImageInternal( |
| 317 const ImageKey& key, | 317 const ImageKey& key, |
| 318 const DrawImage& draw_image) { | 318 const DrawImage& draw_image) { |
| 319 TRACE_EVENT1("disabled-by-default-cc.debug", | 319 TRACE_EVENT1("disabled-by-default-cc.debug", |
| 320 "SoftwareImageDecodeController::DecodeImageInternal", "key", | 320 "SoftwareImageDecodeController::DecodeImageInternal", "key", |
| 321 key.ToString()); | 321 key.ToString()); |
| 322 const SkImage* image = draw_image.image(); | 322 const SkImage* image = draw_image.image(); |
| 323 | 323 |
| 324 // If we can use the original decode, then we don't need to do scaling. We can | 324 // If we can use the original decode, then we don't need to do scaling. We can |
| 325 // just read pixels into the final memory. | 325 // just read pixels into the final memory. |
| (...skipping 18 matching lines...) Expand all Loading... |
| 344 bool result = image->readPixels(decoded_info, decoded_pixels->data(), | 344 bool result = image->readPixels(decoded_info, decoded_pixels->data(), |
| 345 decoded_info.minRowBytes(), 0, 0, | 345 decoded_info.minRowBytes(), 0, 0, |
| 346 SkImage::kDisallow_CachingHint); | 346 SkImage::kDisallow_CachingHint); |
| 347 | 347 |
| 348 if (!result) { | 348 if (!result) { |
| 349 decoded_pixels->Unlock(); | 349 decoded_pixels->Unlock(); |
| 350 return nullptr; | 350 return nullptr; |
| 351 } | 351 } |
| 352 } | 352 } |
| 353 | 353 |
| 354 return make_scoped_refptr(new DecodedImage( | 354 return make_scoped_ptr(new DecodedImage( |
| 355 decoded_info, std::move(decoded_pixels), SkSize::Make(0, 0))); | 355 decoded_info, std::move(decoded_pixels), SkSize::Make(0, 0))); |
| 356 } | 356 } |
| 357 | 357 |
| 358 // If we get here, that means we couldn't use the original sized decode for | 358 // If we get here, that means we couldn't use the original sized decode for |
| 359 // whatever reason. However, in all cases we do need an original decode to | 359 // whatever reason. However, in all cases we do need an original decode to |
| 360 // either do a scale or to extract a subrect from the image. So, what we can | 360 // either do a scale or to extract a subrect from the image. So, what we can |
| 361 // do is construct a key that would require a full sized decode, then get that | 361 // do is construct a key that would require a full sized decode, then get that |
| 362 // decode via GetDecodedImageForDrawInternal(), use it, and unref it. This | 362 // decode via GetDecodedImageForDrawInternal(), use it, and unref it. This |
| 363 // ensures that if the original sized decode is already available in any of | 363 // ensures that if the original sized decode is already available in any of |
| 364 // the caches, we reuse that. We also ensure that all the proper locking takes | 364 // the caches, we reuse that. We also ensure that all the proper locking takes |
| (...skipping 52 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 417 bool result = | 417 bool result = |
| 418 decoded_pixmap.scalePixels(scaled_pixmap, key.filter_quality()); | 418 decoded_pixmap.scalePixels(scaled_pixmap, key.filter_quality()); |
| 419 DCHECK(result); | 419 DCHECK(result); |
| 420 } | 420 } |
| 421 | 421 |
| 422 // Release the original sized decode. Any other intermediate result to release | 422 // Release the original sized decode. Any other intermediate result to release |
| 423 // would be the subrect memory. However, that's in a scoped_ptr and will be | 423 // would be the subrect memory. However, that's in a scoped_ptr and will be |
| 424 // deleted automatically when we return. | 424 // deleted automatically when we return. |
| 425 DrawWithImageFinished(original_size_draw_image, decoded_draw_image); | 425 DrawWithImageFinished(original_size_draw_image, decoded_draw_image); |
| 426 | 426 |
| 427 return make_scoped_refptr( | 427 return make_scoped_ptr( |
| 428 new DecodedImage(scaled_info, std::move(scaled_pixels), | 428 new DecodedImage(scaled_info, std::move(scaled_pixels), |
| 429 SkSize::Make(-key.src_rect().x(), -key.src_rect().y()))); | 429 SkSize::Make(-key.src_rect().x(), -key.src_rect().y()))); |
| 430 } | 430 } |
| 431 | 431 |
| 432 DecodedDrawImage SoftwareImageDecodeController::GetDecodedImageForDraw( | 432 DecodedDrawImage SoftwareImageDecodeController::GetDecodedImageForDraw( |
| 433 const DrawImage& draw_image) { | 433 const DrawImage& draw_image) { |
| 434 ImageKey key = ImageKey::FromDrawImage(draw_image); | 434 ImageKey key = ImageKey::FromDrawImage(draw_image); |
| 435 TRACE_EVENT1("disabled-by-default-cc.debug", | 435 TRACE_EVENT1("disabled-by-default-cc.debug", |
| 436 "SoftwareImageDecodeController::GetDecodedImageForDraw", "key", | 436 "SoftwareImageDecodeController::GetDecodedImageForDraw", "key", |
| 437 key.ToString()); | 437 key.ToString()); |
| (...skipping 10 matching lines...) Expand all Loading... |
| 448 DecodedDrawImage SoftwareImageDecodeController::GetDecodedImageForDrawInternal( | 448 DecodedDrawImage SoftwareImageDecodeController::GetDecodedImageForDrawInternal( |
| 449 const ImageKey& key, | 449 const ImageKey& key, |
| 450 const DrawImage& draw_image) { | 450 const DrawImage& draw_image) { |
| 451 TRACE_EVENT1("disabled-by-default-cc.debug", | 451 TRACE_EVENT1("disabled-by-default-cc.debug", |
| 452 "SoftwareImageDecodeController::GetDecodedImageForDrawInternal", | 452 "SoftwareImageDecodeController::GetDecodedImageForDrawInternal", |
| 453 "key", key.ToString()); | 453 "key", key.ToString()); |
| 454 base::AutoLock lock(lock_); | 454 base::AutoLock lock(lock_); |
| 455 auto decoded_images_it = decoded_images_.Get(key); | 455 auto decoded_images_it = decoded_images_.Get(key); |
| 456 // If we found the image and it's locked, then return it. If it's not locked, | 456 // If we found the image and it's locked, then return it. If it's not locked, |
| 457 // erase it from the cache since it might be put into the at-raster cache. | 457 // erase it from the cache since it might be put into the at-raster cache. |
| 458 scoped_refptr<DecodedImage> decoded_image; | 458 scoped_ptr<DecodedImage> scoped_decoded_image; |
| 459 DecodedImage* decoded_image = nullptr; |
| 459 if (decoded_images_it != decoded_images_.end()) { | 460 if (decoded_images_it != decoded_images_.end()) { |
| 460 decoded_image = decoded_images_it->second; | 461 decoded_image = decoded_images_it->second.get(); |
| 461 if (decoded_image->is_locked()) { | 462 if (decoded_image->is_locked()) { |
| 462 RefImage(key); | 463 RefImage(key); |
| 463 SanityCheckState(__LINE__, true); | 464 SanityCheckState(__LINE__, true); |
| 464 return DecodedDrawImage( | 465 return DecodedDrawImage( |
| 465 decoded_image->image(), decoded_image->src_rect_offset(), | 466 decoded_image->image(), decoded_image->src_rect_offset(), |
| 466 GetScaleAdjustment(key), GetDecodedFilterQuality(key)); | 467 GetScaleAdjustment(key), GetDecodedFilterQuality(key)); |
| 467 } else { | 468 } else { |
| 469 scoped_decoded_image = std::move(decoded_images_it->second); |
| 468 decoded_images_.Erase(decoded_images_it); | 470 decoded_images_.Erase(decoded_images_it); |
| 469 } | 471 } |
| 470 } | 472 } |
| 471 | 473 |
| 472 // See if another thread already decoded this image at raster time. If so, we | 474 // See if another thread already decoded this image at raster time. If so, we |
| 473 // can just use that result directly. | 475 // can just use that result directly. |
| 474 auto at_raster_images_it = at_raster_decoded_images_.Get(key); | 476 auto at_raster_images_it = at_raster_decoded_images_.Get(key); |
| 475 if (at_raster_images_it != at_raster_decoded_images_.end()) { | 477 if (at_raster_images_it != at_raster_decoded_images_.end()) { |
| 476 DCHECK(at_raster_images_it->second->is_locked()); | 478 DCHECK(at_raster_images_it->second->is_locked()); |
| 477 RefAtRasterImage(key); | 479 RefAtRasterImage(key); |
| 478 SanityCheckState(__LINE__, true); | 480 SanityCheckState(__LINE__, true); |
| 479 const scoped_refptr<DecodedImage>& at_raster_decoded_image = | 481 DecodedImage* at_raster_decoded_image = at_raster_images_it->second.get(); |
| 480 at_raster_images_it->second; | |
| 481 auto decoded_draw_image = | 482 auto decoded_draw_image = |
| 482 DecodedDrawImage(at_raster_decoded_image->image(), | 483 DecodedDrawImage(at_raster_decoded_image->image(), |
| 483 at_raster_decoded_image->src_rect_offset(), | 484 at_raster_decoded_image->src_rect_offset(), |
| 484 GetScaleAdjustment(key), GetDecodedFilterQuality(key)); | 485 GetScaleAdjustment(key), GetDecodedFilterQuality(key)); |
| 485 decoded_draw_image.set_at_raster_decode(true); | 486 decoded_draw_image.set_at_raster_decode(true); |
| 486 return decoded_draw_image; | 487 return decoded_draw_image; |
| 487 } | 488 } |
| 488 | 489 |
| 489 // Now we know that we don't have a locked image, and we seem to be the first | 490 // Now we know that we don't have a locked image, and we seem to be the first |
| 490 // thread encountering this image (that might not be true, since other threads | 491 // thread encountering this image (that might not be true, since other threads |
| 491 // might be decoding it already). This means that we need to decode the image | 492 // might be decoding it already). This means that we need to decode the image |
| 492 // assuming we can't lock the one we found in the cache. | 493 // assuming we can't lock the one we found in the cache. |
| 493 bool check_at_raster_cache = false; | 494 bool check_at_raster_cache = false; |
| 494 if (!decoded_image || !decoded_image->Lock()) { | 495 if (!decoded_image || !decoded_image->Lock()) { |
| 495 // Note that we have to release the lock, since this lock is also accessed | 496 // Note that we have to release the lock, since this lock is also accessed |
| 496 // on the compositor thread. This means holding on to the lock might stall | 497 // on the compositor thread. This means holding on to the lock might stall |
| 497 // the compositor thread for the duration of the decode! | 498 // the compositor thread for the duration of the decode! |
| 498 base::AutoUnlock unlock(lock_); | 499 base::AutoUnlock unlock(lock_); |
| 499 decoded_image = DecodeImageInternal(key, draw_image); | 500 scoped_decoded_image = DecodeImageInternal(key, draw_image); |
| 501 decoded_image = scoped_decoded_image.get(); |
| 500 | 502 |
| 501 // Skip the image if we couldn't decode it. | 503 // Skip the image if we couldn't decode it. |
| 502 if (!decoded_image) | 504 if (!decoded_image) |
| 503 return DecodedDrawImage(nullptr, kNone_SkFilterQuality); | 505 return DecodedDrawImage(nullptr, kNone_SkFilterQuality); |
| 504 check_at_raster_cache = true; | 506 check_at_raster_cache = true; |
| 505 } | 507 } |
| 506 | 508 |
| 509 DCHECK(decoded_image == scoped_decoded_image.get()); |
| 510 |
| 507 // While we unlocked the lock, it could be the case that another thread | 511 // While we unlocked the lock, it could be the case that another thread |
| 508 // already decoded this already and put it in the at-raster cache. Look it up | 512 // already decoded this already and put it in the at-raster cache. Look it up |
| 509 // first. | 513 // first. |
| 510 bool need_to_add_image_to_cache = true; | |
| 511 if (check_at_raster_cache) { | 514 if (check_at_raster_cache) { |
| 512 at_raster_images_it = at_raster_decoded_images_.Get(key); | 515 at_raster_images_it = at_raster_decoded_images_.Get(key); |
| 513 if (at_raster_images_it != at_raster_decoded_images_.end()) { | 516 if (at_raster_images_it != at_raster_decoded_images_.end()) { |
| 514 // We have to drop our decode, since the one in the cache is being used by | 517 // We have to drop our decode, since the one in the cache is being used by |
| 515 // another thread. | 518 // another thread. |
| 516 decoded_image->Unlock(); | 519 decoded_image->Unlock(); |
| 517 decoded_image = at_raster_images_it->second; | 520 decoded_image = at_raster_images_it->second.get(); |
| 518 need_to_add_image_to_cache = false; | 521 scoped_decoded_image = nullptr; |
| 519 } | 522 } |
| 520 } | 523 } |
| 521 | 524 |
| 522 // If we really are the first ones, or if the other thread already unlocked | 525 // If we really are the first ones, or if the other thread already unlocked |
| 523 // the image, then put our work into at-raster time cache. | 526 // the image, then put our work into at-raster time cache. |
| 524 if (need_to_add_image_to_cache) | 527 if (scoped_decoded_image) |
| 525 at_raster_decoded_images_.Put(key, decoded_image); | 528 at_raster_decoded_images_.Put(key, std::move(scoped_decoded_image)); |
| 526 | 529 |
| 527 DCHECK(decoded_image); | 530 DCHECK(decoded_image); |
| 528 DCHECK(decoded_image->is_locked()); | 531 DCHECK(decoded_image->is_locked()); |
| 529 RefAtRasterImage(key); | 532 RefAtRasterImage(key); |
| 530 SanityCheckState(__LINE__, true); | 533 SanityCheckState(__LINE__, true); |
| 531 auto decoded_draw_image = | 534 auto decoded_draw_image = |
| 532 DecodedDrawImage(decoded_image->image(), decoded_image->src_rect_offset(), | 535 DecodedDrawImage(decoded_image->image(), decoded_image->src_rect_offset(), |
| 533 GetScaleAdjustment(key), GetDecodedFilterQuality(key)); | 536 GetScaleAdjustment(key), GetDecodedFilterQuality(key)); |
| 534 decoded_draw_image.set_at_raster_decode(true); | 537 decoded_draw_image.set_at_raster_decode(true); |
| 535 return decoded_draw_image; | 538 return decoded_draw_image; |
| (...skipping 52 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 588 // 2b. ... and is unlocked and... | 591 // 2b. ... and is unlocked and... |
| 589 // 2b1. ... its ref count is 0: unlock our image and replace the | 592 // 2b1. ... its ref count is 0: unlock our image and replace the |
| 590 // existing one with ours. | 593 // existing one with ours. |
| 591 // 2b2. ... its ref count is not 0: this shouldn't be possible. | 594 // 2b2. ... its ref count is not 0: this shouldn't be possible. |
| 592 auto image_it = decoded_images_.Peek(key); | 595 auto image_it = decoded_images_.Peek(key); |
| 593 if (image_it == decoded_images_.end()) { | 596 if (image_it == decoded_images_.end()) { |
| 594 if (decoded_images_ref_counts_.find(key) == | 597 if (decoded_images_ref_counts_.find(key) == |
| 595 decoded_images_ref_counts_.end()) { | 598 decoded_images_ref_counts_.end()) { |
| 596 at_raster_image_it->second->Unlock(); | 599 at_raster_image_it->second->Unlock(); |
| 597 } | 600 } |
| 598 decoded_images_.Put(key, at_raster_image_it->second); | 601 decoded_images_.Put(key, std::move(at_raster_image_it->second)); |
| 599 } else if (image_it->second->is_locked()) { | 602 } else if (image_it->second->is_locked()) { |
| 600 at_raster_image_it->second->Unlock(); | 603 at_raster_image_it->second->Unlock(); |
| 601 } else { | 604 } else { |
| 602 DCHECK(decoded_images_ref_counts_.find(key) == | 605 DCHECK(decoded_images_ref_counts_.find(key) == |
| 603 decoded_images_ref_counts_.end()); | 606 decoded_images_ref_counts_.end()); |
| 604 at_raster_image_it->second->Unlock(); | 607 at_raster_image_it->second->Unlock(); |
| 605 decoded_images_.Erase(image_it); | 608 decoded_images_.Erase(image_it); |
| 606 decoded_images_.Put(key, at_raster_image_it->second); | 609 decoded_images_.Put(key, std::move(at_raster_image_it->second)); |
| 607 } | 610 } |
| 608 at_raster_decoded_images_.Erase(at_raster_image_it); | 611 at_raster_decoded_images_.Erase(at_raster_image_it); |
| 609 } | 612 } |
| 610 } | 613 } |
| 611 | 614 |
| 612 bool SoftwareImageDecodeController::CanHandleImage(const ImageKey& key) { | 615 bool SoftwareImageDecodeController::CanHandleImage(const ImageKey& key) { |
| 613 // TODO(vmpstr): Start handling medium filter quality as well. | 616 // TODO(vmpstr): Start handling medium filter quality as well. |
| 614 return key.filter_quality() != kMedium_SkFilterQuality; | 617 return key.filter_quality() != kMedium_SkFilterQuality; |
| 615 } | 618 } |
| 616 | 619 |
| (...skipping 212 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 829 void SoftwareImageDecodeController::MemoryBudget::ResetUsage() { | 832 void SoftwareImageDecodeController::MemoryBudget::ResetUsage() { |
| 830 current_usage_bytes_ = 0; | 833 current_usage_bytes_ = 0; |
| 831 } | 834 } |
| 832 | 835 |
| 833 size_t SoftwareImageDecodeController::MemoryBudget::GetCurrentUsageSafe() | 836 size_t SoftwareImageDecodeController::MemoryBudget::GetCurrentUsageSafe() |
| 834 const { | 837 const { |
| 835 return current_usage_bytes_.ValueOrDie(); | 838 return current_usage_bytes_.ValueOrDie(); |
| 836 } | 839 } |
| 837 | 840 |
| 838 } // namespace cc | 841 } // namespace cc |
| OLD | NEW |