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 18 matching lines...) Expand all Loading... |
29 const size_t kMaxHighQualityImageSizeBytes = 64 * 1024 * 1024; | 29 const size_t kMaxHighQualityImageSizeBytes = 64 * 1024 * 1024; |
30 | 30 |
31 // The number of entries to keep around in the cache. This limit can be breached | 31 // The number of entries to keep around in the cache. This limit can be breached |
32 // if more items are locked. That is, locked items ignore this limit. | 32 // if more items are locked. That is, locked items ignore this limit. |
33 const size_t kMaxItemsInCache = 1000; | 33 const size_t kMaxItemsInCache = 1000; |
34 | 34 |
35 class AutoRemoveKeyFromTaskMap { | 35 class AutoRemoveKeyFromTaskMap { |
36 public: | 36 public: |
37 AutoRemoveKeyFromTaskMap( | 37 AutoRemoveKeyFromTaskMap( |
38 std::unordered_map<SoftwareImageDecodeController::ImageKey, | 38 std::unordered_map<SoftwareImageDecodeController::ImageKey, |
39 scoped_refptr<ImageDecodeTask>, | 39 scoped_refptr<Task>, |
40 SoftwareImageDecodeController::ImageKeyHash>* task_map, | 40 SoftwareImageDecodeController::ImageKeyHash>* task_map, |
41 const SoftwareImageDecodeController::ImageKey& key) | 41 const SoftwareImageDecodeController::ImageKey& key) |
42 : task_map_(task_map), key_(key) {} | 42 : task_map_(task_map), key_(key) {} |
43 ~AutoRemoveKeyFromTaskMap() { task_map_->erase(key_); } | 43 ~AutoRemoveKeyFromTaskMap() { task_map_->erase(key_); } |
44 | 44 |
45 private: | 45 private: |
46 std::unordered_map<SoftwareImageDecodeController::ImageKey, | 46 std::unordered_map<SoftwareImageDecodeController::ImageKey, |
47 scoped_refptr<ImageDecodeTask>, | 47 scoped_refptr<Task>, |
48 SoftwareImageDecodeController::ImageKeyHash>* task_map_; | 48 SoftwareImageDecodeController::ImageKeyHash>* task_map_; |
49 SoftwareImageDecodeController::ImageKey key_; | 49 SoftwareImageDecodeController::ImageKey key_; |
50 }; | 50 }; |
51 | 51 |
52 class ImageDecodeTaskImpl : public ImageDecodeTask { | 52 class ImageDecodeTaskImpl : public Task { |
53 public: | 53 public: |
54 ImageDecodeTaskImpl(SoftwareImageDecodeController* controller, | 54 ImageDecodeTaskImpl(SoftwareImageDecodeController* controller, |
55 const SoftwareImageDecodeController::ImageKey& image_key, | 55 const SoftwareImageDecodeController::ImageKey& image_key, |
56 const DrawImage& image, | 56 const DrawImage& image, |
57 uint64_t source_prepare_tiles_id) | 57 uint64_t source_prepare_tiles_id) |
58 : controller_(controller), | 58 : controller_(controller), |
59 image_key_(image_key), | 59 image_key_(image_key), |
60 image_(image), | 60 image_(image), |
61 image_ref_(skia::SharePtr(image.image())), | 61 image_ref_(skia::SharePtr(image.image())), |
62 source_prepare_tiles_id_(source_prepare_tiles_id) {} | 62 source_prepare_tiles_id_(source_prepare_tiles_id) {} |
63 | 63 |
64 // Overridden from Task: | 64 // Overridden from Task: |
| 65 void ScheduleOnOriginThread() override {} |
| 66 void CompleteOnOriginThread() override { |
| 67 controller_->RemovePendingTask(image_key_); |
| 68 } |
65 void RunOnWorkerThread() override { | 69 void RunOnWorkerThread() override { |
66 TRACE_EVENT2("cc", "ImageDecodeTaskImpl::RunOnWorkerThread", "mode", | 70 TRACE_EVENT2("cc", "ImageDecodeTaskImpl::RunOnWorkerThread", "mode", |
67 "software", "source_prepare_tiles_id", | 71 "software", "source_prepare_tiles_id", |
68 source_prepare_tiles_id_); | 72 source_prepare_tiles_id_); |
69 devtools_instrumentation::ScopedImageDecodeTask image_decode_task( | 73 devtools_instrumentation::ScopedImageDecodeTask image_decode_task( |
70 image_ref_.get()); | 74 image_ref_.get()); |
71 controller_->DecodeImage(image_key_, image_); | 75 controller_->DecodeImage(image_key_, image_); |
72 } | 76 } |
73 | 77 |
74 // Overridden from TileTask: | |
75 void ScheduleOnOriginThread(TileTaskClient* client) override {} | |
76 void CompleteOnOriginThread(TileTaskClient* client) override { | |
77 controller_->RemovePendingTask(image_key_); | |
78 } | |
79 | |
80 protected: | 78 protected: |
81 ~ImageDecodeTaskImpl() override {} | 79 ~ImageDecodeTaskImpl() override {} |
82 | 80 |
83 private: | 81 private: |
84 SoftwareImageDecodeController* controller_; | 82 SoftwareImageDecodeController* controller_; |
85 SoftwareImageDecodeController::ImageKey image_key_; | 83 SoftwareImageDecodeController::ImageKey image_key_; |
86 DrawImage image_; | 84 DrawImage image_; |
87 skia::RefPtr<const SkImage> image_ref_; | 85 skia::RefPtr<const SkImage> image_ref_; |
88 uint64_t source_prepare_tiles_id_; | 86 uint64_t source_prepare_tiles_id_; |
89 | 87 |
(...skipping 60 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
150 : SoftwareImageDecodeController(RGBA_8888) {} | 148 : SoftwareImageDecodeController(RGBA_8888) {} |
151 | 149 |
152 SoftwareImageDecodeController::~SoftwareImageDecodeController() { | 150 SoftwareImageDecodeController::~SoftwareImageDecodeController() { |
153 DCHECK_EQ(0u, decoded_images_ref_counts_.size()); | 151 DCHECK_EQ(0u, decoded_images_ref_counts_.size()); |
154 DCHECK_EQ(0u, at_raster_decoded_images_ref_counts_.size()); | 152 DCHECK_EQ(0u, at_raster_decoded_images_ref_counts_.size()); |
155 } | 153 } |
156 | 154 |
157 bool SoftwareImageDecodeController::GetTaskForImageAndRef( | 155 bool SoftwareImageDecodeController::GetTaskForImageAndRef( |
158 const DrawImage& image, | 156 const DrawImage& image, |
159 uint64_t prepare_tiles_id, | 157 uint64_t prepare_tiles_id, |
160 scoped_refptr<ImageDecodeTask>* task) { | 158 scoped_refptr<Task>* task) { |
161 // If the image already exists or if we're going to create a task for it, then | 159 // If the image already exists or if we're going to create a task for it, then |
162 // we'll likely need to ref this image (the exception is if we're prerolling | 160 // we'll likely need to ref this image (the exception is if we're prerolling |
163 // the image only). That means the image is or will be in the cache. When the | 161 // the image only). That means the image is or will be in the cache. When the |
164 // ref goes to 0, it will be unpinned but will remain in the cache. If the | 162 // ref goes to 0, it will be unpinned but will remain in the cache. If the |
165 // image does not fit into the budget, then we don't ref this image, since it | 163 // image does not fit into the budget, then we don't ref this image, since it |
166 // will be decoded at raster time which is when it will be temporarily put in | 164 // will be decoded at raster time which is when it will be temporarily put in |
167 // the cache. | 165 // the cache. |
168 ImageKey key = ImageKey::FromDrawImage(image); | 166 ImageKey key = ImageKey::FromDrawImage(image); |
169 TRACE_EVENT1("disabled-by-default-cc.debug", | 167 TRACE_EVENT1("disabled-by-default-cc.debug", |
170 "SoftwareImageDecodeController::GetTaskForImageAndRef", "key", | 168 "SoftwareImageDecodeController::GetTaskForImageAndRef", "key", |
171 key.ToString()); | 169 key.ToString()); |
172 | 170 |
173 // If the target size is empty, we can skip this image during draw (and thus | 171 // If the target size is empty, we can skip this image during draw (and thus |
174 // we don't need to decode it or ref it). | 172 // we don't need to decode it or ref it). |
175 if (key.target_size().IsEmpty()) { | 173 if (key.target_size().IsEmpty()) { |
176 *task = nullptr; | 174 *task = nullptr; |
177 return false; | 175 return false; |
178 } | 176 } |
179 | 177 |
180 // If we're not going to do a scale, we will just create a task to preroll the | 178 // If we're not going to do a scale, we will just create a task to preroll the |
181 // image the first time we see it. This doesn't need to account for memory. | 179 // image the first time we see it. This doesn't need to account for memory. |
182 // TODO(vmpstr): We can also lock the original sized image, in which case it | 180 // TODO(vmpstr): We can also lock the original sized image, in which case it |
183 // does require memory bookkeeping. | 181 // does require memory bookkeeping. |
184 if (!CanHandleImage(key)) { | 182 if (!CanHandleImage(key)) { |
185 base::AutoLock lock(lock_); | 183 base::AutoLock lock(lock_); |
186 if (prerolled_images_.count(key.image_id()) == 0) { | 184 if (prerolled_images_.count(key.image_id()) == 0) { |
187 scoped_refptr<ImageDecodeTask>& existing_task = pending_image_tasks_[key]; | 185 scoped_refptr<Task>& existing_task = pending_image_tasks_[key]; |
188 if (!existing_task) { | 186 if (!existing_task) { |
189 existing_task = make_scoped_refptr( | 187 existing_task = make_scoped_refptr( |
190 new ImageDecodeTaskImpl(this, key, image, prepare_tiles_id)); | 188 new ImageDecodeTaskImpl(this, key, image, prepare_tiles_id)); |
191 } | 189 } |
192 *task = existing_task; | 190 *task = existing_task; |
193 } else { | 191 } else { |
194 *task = nullptr; | 192 *task = nullptr; |
195 } | 193 } |
196 return false; | 194 return false; |
197 } | 195 } |
(...skipping 12 matching lines...) Expand all Loading... |
210 SanityCheckState(__LINE__, true); | 208 SanityCheckState(__LINE__, true); |
211 return true; | 209 return true; |
212 } | 210 } |
213 // If the image fits in memory, then we at least tried to lock it and | 211 // If the image fits in memory, then we at least tried to lock it and |
214 // failed. This means that it's not valid anymore. | 212 // failed. This means that it's not valid anymore. |
215 if (new_image_fits_in_memory) | 213 if (new_image_fits_in_memory) |
216 decoded_images_.Erase(decoded_it); | 214 decoded_images_.Erase(decoded_it); |
217 } | 215 } |
218 | 216 |
219 // If the task exists, return it. | 217 // If the task exists, return it. |
220 scoped_refptr<ImageDecodeTask>& existing_task = pending_image_tasks_[key]; | 218 scoped_refptr<Task>& existing_task = pending_image_tasks_[key]; |
221 if (existing_task) { | 219 if (existing_task) { |
222 RefImage(key); | 220 RefImage(key); |
223 *task = existing_task; | 221 *task = existing_task; |
224 SanityCheckState(__LINE__, true); | 222 SanityCheckState(__LINE__, true); |
225 return true; | 223 return true; |
226 } | 224 } |
227 | 225 |
228 // At this point, we have to create a new image/task, so we need to abort if | 226 // At this point, we have to create a new image/task, so we need to abort if |
229 // it doesn't fit into memory and there are currently no raster tasks that | 227 // it doesn't fit into memory and there are currently no raster tasks that |
230 // would have already accounted for memory. The latter part is possible if | 228 // would have already accounted for memory. The latter part is possible if |
(...skipping 659 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
890 void SoftwareImageDecodeController::MemoryBudget::ResetUsage() { | 888 void SoftwareImageDecodeController::MemoryBudget::ResetUsage() { |
891 current_usage_bytes_ = 0; | 889 current_usage_bytes_ = 0; |
892 } | 890 } |
893 | 891 |
894 size_t SoftwareImageDecodeController::MemoryBudget::GetCurrentUsageSafe() | 892 size_t SoftwareImageDecodeController::MemoryBudget::GetCurrentUsageSafe() |
895 const { | 893 const { |
896 return current_usage_bytes_.ValueOrDie(); | 894 return current_usage_bytes_.ValueOrDie(); |
897 } | 895 } |
898 | 896 |
899 } // namespace cc | 897 } // namespace cc |
OLD | NEW |