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 |