| 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 120 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 131 // we don't need to decode it or ref it). | 131 // we don't need to decode it or ref it). |
| 132 if (key.target_size().IsEmpty()) { | 132 if (key.target_size().IsEmpty()) { |
| 133 *task = nullptr; | 133 *task = nullptr; |
| 134 return false; | 134 return false; |
| 135 } | 135 } |
| 136 | 136 |
| 137 // If we're not going to do a scale, we will just create a task to preroll the | 137 // If we're not going to do a scale, we will just create a task to preroll the |
| 138 // image the first time we see it. This doesn't need to account for memory. | 138 // image the first time we see it. This doesn't need to account for memory. |
| 139 // TODO(vmpstr): We can also lock the original sized image, in which case it | 139 // TODO(vmpstr): We can also lock the original sized image, in which case it |
| 140 // does require memory bookkeeping. | 140 // does require memory bookkeeping. |
| 141 if (!CanHandleImage(key, image)) { | 141 if (!CanHandleImage(key)) { |
| 142 base::AutoLock lock(lock_); | 142 base::AutoLock lock(lock_); |
| 143 if (prerolled_images_.count(key.image_id()) == 0) { | 143 if (prerolled_images_.count(key.image_id()) == 0) { |
| 144 scoped_refptr<ImageDecodeTask>& existing_task = pending_image_tasks_[key]; | 144 scoped_refptr<ImageDecodeTask>& existing_task = pending_image_tasks_[key]; |
| 145 if (!existing_task) { | 145 if (!existing_task) { |
| 146 existing_task = make_scoped_refptr( | 146 existing_task = make_scoped_refptr( |
| 147 new ImageDecodeTaskImpl(this, key, image, prepare_tiles_id)); | 147 new ImageDecodeTaskImpl(this, key, image, prepare_tiles_id)); |
| 148 } | 148 } |
| 149 *task = existing_task; | 149 *task = existing_task; |
| 150 } else { | 150 } else { |
| 151 *task = nullptr; | 151 *task = nullptr; |
| (...skipping 65 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 217 } | 217 } |
| 218 | 218 |
| 219 void SoftwareImageDecodeController::UnrefImage(const DrawImage& image) { | 219 void SoftwareImageDecodeController::UnrefImage(const DrawImage& image) { |
| 220 // When we unref the image, there are several situations we need to consider: | 220 // When we unref the image, there are several situations we need to consider: |
| 221 // 1. The ref did not reach 0, which means we have to keep the image locked. | 221 // 1. The ref did not reach 0, which means we have to keep the image locked. |
| 222 // 2. The ref reached 0, we should unlock it. | 222 // 2. The ref reached 0, we should unlock it. |
| 223 // 2a. The image isn't in the locked cache because we didn't get to decode | 223 // 2a. The image isn't in the locked cache because we didn't get to decode |
| 224 // it yet (or failed to decode it). | 224 // it yet (or failed to decode it). |
| 225 // 2b. Unlock the image but keep it in list. | 225 // 2b. Unlock the image but keep it in list. |
| 226 const ImageKey& key = ImageKey::FromDrawImage(image); | 226 const ImageKey& key = ImageKey::FromDrawImage(image); |
| 227 DCHECK(CanHandleImage(key, image)); | 227 DCHECK(CanHandleImage(key)); |
| 228 TRACE_EVENT1("disabled-by-default-cc.debug", | 228 TRACE_EVENT1("disabled-by-default-cc.debug", |
| 229 "SoftwareImageDecodeController::UnrefImage", "key", | 229 "SoftwareImageDecodeController::UnrefImage", "key", |
| 230 key.ToString()); | 230 key.ToString()); |
| 231 | 231 |
| 232 base::AutoLock lock(lock_); | 232 base::AutoLock lock(lock_); |
| 233 auto ref_count_it = decoded_images_ref_counts_.find(key); | 233 auto ref_count_it = decoded_images_ref_counts_.find(key); |
| 234 DCHECK(ref_count_it != decoded_images_ref_counts_.end()); | 234 DCHECK(ref_count_it != decoded_images_ref_counts_.end()); |
| 235 | 235 |
| 236 --ref_count_it->second; | 236 --ref_count_it->second; |
| 237 if (ref_count_it->second == 0) { | 237 if (ref_count_it->second == 0) { |
| (...skipping 10 matching lines...) Expand all Loading... |
| 248 DCHECK(decoded_image_it->second->is_locked()); | 248 DCHECK(decoded_image_it->second->is_locked()); |
| 249 decoded_image_it->second->Unlock(); | 249 decoded_image_it->second->Unlock(); |
| 250 } | 250 } |
| 251 SanityCheckState(__LINE__, true); | 251 SanityCheckState(__LINE__, true); |
| 252 } | 252 } |
| 253 | 253 |
| 254 void SoftwareImageDecodeController::DecodeImage(const ImageKey& key, | 254 void SoftwareImageDecodeController::DecodeImage(const ImageKey& key, |
| 255 const DrawImage& image) { | 255 const DrawImage& image) { |
| 256 TRACE_EVENT1("cc", "SoftwareImageDecodeController::DecodeImage", "key", | 256 TRACE_EVENT1("cc", "SoftwareImageDecodeController::DecodeImage", "key", |
| 257 key.ToString()); | 257 key.ToString()); |
| 258 if (!CanHandleImage(key, image)) { | 258 if (!CanHandleImage(key)) { |
| 259 image.image()->preroll(); | 259 image.image()->preroll(); |
| 260 | 260 |
| 261 base::AutoLock lock(lock_); | 261 base::AutoLock lock(lock_); |
| 262 prerolled_images_.insert(key.image_id()); | 262 prerolled_images_.insert(key.image_id()); |
| 263 // Erase the pending task from the queue, since the task won't be doing | 263 // Erase the pending task from the queue, since the task won't be doing |
| 264 // anything useful after this function terminates. Since we don't preroll | 264 // anything useful after this function terminates. Since we don't preroll |
| 265 // images twice, this is actually not necessary but it behaves similar to | 265 // images twice, this is actually not necessary but it behaves similar to |
| 266 // the other code path: when this function finishes, the task isn't in the | 266 // the other code path: when this function finishes, the task isn't in the |
| 267 // pending_image_tasks_ list. | 267 // pending_image_tasks_ list. |
| 268 pending_image_tasks_.erase(key); | 268 pending_image_tasks_.erase(key); |
| (...skipping 232 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 501 DecodedDrawImage SoftwareImageDecodeController::GetDecodedImageForDraw( | 501 DecodedDrawImage SoftwareImageDecodeController::GetDecodedImageForDraw( |
| 502 const DrawImage& draw_image) { | 502 const DrawImage& draw_image) { |
| 503 ImageKey key = ImageKey::FromDrawImage(draw_image); | 503 ImageKey key = ImageKey::FromDrawImage(draw_image); |
| 504 TRACE_EVENT1("disabled-by-default-cc.debug", | 504 TRACE_EVENT1("disabled-by-default-cc.debug", |
| 505 "SoftwareImageDecodeController::GetDecodedImageForDraw", "key", | 505 "SoftwareImageDecodeController::GetDecodedImageForDraw", "key", |
| 506 key.ToString()); | 506 key.ToString()); |
| 507 // If the target size is empty, we can skip this image draw. | 507 // If the target size is empty, we can skip this image draw. |
| 508 if (key.target_size().IsEmpty()) | 508 if (key.target_size().IsEmpty()) |
| 509 return DecodedDrawImage(nullptr, kNone_SkFilterQuality); | 509 return DecodedDrawImage(nullptr, kNone_SkFilterQuality); |
| 510 | 510 |
| 511 if (!CanHandleImage(key, draw_image)) | 511 if (!CanHandleImage(key)) |
| 512 return DecodedDrawImage(draw_image.image(), draw_image.filter_quality()); | 512 return DecodedDrawImage(draw_image.image(), draw_image.filter_quality()); |
| 513 | 513 |
| 514 return GetDecodedImageForDrawInternal(key, draw_image); | 514 return GetDecodedImageForDrawInternal(key, draw_image); |
| 515 } | 515 } |
| 516 | 516 |
| 517 DecodedDrawImage SoftwareImageDecodeController::GetDecodedImageForDrawInternal( | 517 DecodedDrawImage SoftwareImageDecodeController::GetDecodedImageForDrawInternal( |
| 518 const ImageKey& key, | 518 const ImageKey& key, |
| 519 const DrawImage& draw_image) { | 519 const DrawImage& draw_image) { |
| 520 TRACE_EVENT1("disabled-by-default-cc.debug", | 520 TRACE_EVENT1("disabled-by-default-cc.debug", |
| 521 "SoftwareImageDecodeController::GetDecodedImageForDrawInternal", | 521 "SoftwareImageDecodeController::GetDecodedImageForDrawInternal", |
| (...skipping 84 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 606 return decoded_draw_image; | 606 return decoded_draw_image; |
| 607 } | 607 } |
| 608 | 608 |
| 609 void SoftwareImageDecodeController::DrawWithImageFinished( | 609 void SoftwareImageDecodeController::DrawWithImageFinished( |
| 610 const DrawImage& image, | 610 const DrawImage& image, |
| 611 const DecodedDrawImage& decoded_image) { | 611 const DecodedDrawImage& decoded_image) { |
| 612 TRACE_EVENT1("disabled-by-default-cc.debug", | 612 TRACE_EVENT1("disabled-by-default-cc.debug", |
| 613 "SoftwareImageDecodeController::DrawWithImageFinished", "key", | 613 "SoftwareImageDecodeController::DrawWithImageFinished", "key", |
| 614 ImageKey::FromDrawImage(image).ToString()); | 614 ImageKey::FromDrawImage(image).ToString()); |
| 615 ImageKey key = ImageKey::FromDrawImage(image); | 615 ImageKey key = ImageKey::FromDrawImage(image); |
| 616 if (!decoded_image.image() || !CanHandleImage(key, image)) | 616 if (!decoded_image.image() || !CanHandleImage(key)) |
| 617 return; | 617 return; |
| 618 | 618 |
| 619 if (decoded_image.is_at_raster_decode()) | 619 if (decoded_image.is_at_raster_decode()) |
| 620 UnrefAtRasterImage(key); | 620 UnrefAtRasterImage(key); |
| 621 else | 621 else |
| 622 UnrefImage(image); | 622 UnrefImage(image); |
| 623 SanityCheckState(__LINE__, false); | 623 SanityCheckState(__LINE__, false); |
| 624 } | 624 } |
| 625 | 625 |
| 626 void SoftwareImageDecodeController::RefAtRasterImage(const ImageKey& key) { | 626 void SoftwareImageDecodeController::RefAtRasterImage(const ImageKey& key) { |
| (...skipping 46 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 673 DCHECK(decoded_images_ref_counts_.find(key) == | 673 DCHECK(decoded_images_ref_counts_.find(key) == |
| 674 decoded_images_ref_counts_.end()); | 674 decoded_images_ref_counts_.end()); |
| 675 at_raster_image_it->second->Unlock(); | 675 at_raster_image_it->second->Unlock(); |
| 676 decoded_images_.erase(image_it); | 676 decoded_images_.erase(image_it); |
| 677 decoded_images_.push_back(*at_raster_image_it); | 677 decoded_images_.push_back(*at_raster_image_it); |
| 678 } | 678 } |
| 679 at_raster_decoded_images_.erase(at_raster_image_it); | 679 at_raster_decoded_images_.erase(at_raster_image_it); |
| 680 } | 680 } |
| 681 } | 681 } |
| 682 | 682 |
| 683 bool SoftwareImageDecodeController::CanHandleImage(const ImageKey& key, | 683 bool SoftwareImageDecodeController::CanHandleImage(const ImageKey& key) { |
| 684 const DrawImage& image) { | 684 // TODO(vmpstr): Start handling medium filter quality as well. |
| 685 if (!CanHandleFilterQuality(key.filter_quality())) | 685 return key.filter_quality() != kMedium_SkFilterQuality; |
| 686 return false; | |
| 687 return true; | |
| 688 } | |
| 689 | |
| 690 bool SoftwareImageDecodeController::CanHandleFilterQuality( | |
| 691 SkFilterQuality filter_quality) { | |
| 692 // TODO(vmpstr): We need to start caching mipmaps for medium quality and | |
| 693 // caching the interpolated values from those. For now, we don't have this. | |
| 694 return filter_quality != kMedium_SkFilterQuality; | |
| 695 } | 686 } |
| 696 | 687 |
| 697 void SoftwareImageDecodeController::ReduceCacheUsage() { | 688 void SoftwareImageDecodeController::ReduceCacheUsage() { |
| 698 TRACE_EVENT0("cc", "SoftwareImageDecodeController::ReduceCacheUsage"); | 689 TRACE_EVENT0("cc", "SoftwareImageDecodeController::ReduceCacheUsage"); |
| 699 base::AutoLock lock(lock_); | 690 base::AutoLock lock(lock_); |
| 700 size_t num_to_remove = (decoded_images_.size() > kMaxItemsInCache) | 691 size_t num_to_remove = (decoded_images_.size() > kMaxItemsInCache) |
| 701 ? (decoded_images_.size() - kMaxItemsInCache) | 692 ? (decoded_images_.size() - kMaxItemsInCache) |
| 702 : 0; | 693 : 0; |
| 703 for (auto it = decoded_images_.begin(); | 694 for (auto it = decoded_images_.begin(); |
| 704 num_to_remove != 0 && it != decoded_images_.end();) { | 695 num_to_remove != 0 && it != decoded_images_.end();) { |
| (...skipping 215 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 920 void SoftwareImageDecodeController::MemoryBudget::ResetUsage() { | 911 void SoftwareImageDecodeController::MemoryBudget::ResetUsage() { |
| 921 current_usage_bytes_ = 0; | 912 current_usage_bytes_ = 0; |
| 922 } | 913 } |
| 923 | 914 |
| 924 size_t SoftwareImageDecodeController::MemoryBudget::GetCurrentUsageSafe() | 915 size_t SoftwareImageDecodeController::MemoryBudget::GetCurrentUsageSafe() |
| 925 const { | 916 const { |
| 926 return current_usage_bytes_.ValueOrDie(); | 917 return current_usage_bytes_.ValueOrDie(); |
| 927 } | 918 } |
| 928 | 919 |
| 929 } // namespace cc | 920 } // namespace cc |
| OLD | NEW |