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 |
11 #include "base/format_macros.h" | 11 #include "base/format_macros.h" |
12 #include "base/macros.h" | 12 #include "base/macros.h" |
13 #include "base/memory/discardable_memory.h" | 13 #include "base/memory/discardable_memory.h" |
14 #include "base/memory/ptr_util.h" | 14 #include "base/memory/ptr_util.h" |
15 #include "base/strings/stringprintf.h" | 15 #include "base/strings/stringprintf.h" |
16 #include "base/thread_task_runner_handle.h" | 16 #include "base/thread_task_runner_handle.h" |
17 #include "base/trace_event/memory_dump_manager.h" | 17 #include "base/trace_event/memory_dump_manager.h" |
18 #include "cc/debug/devtools_instrumentation.h" | 18 #include "cc/debug/devtools_instrumentation.h" |
19 #include "cc/raster/tile_task_runner.h" | |
20 #include "third_party/skia/include/core/SkCanvas.h" | 19 #include "third_party/skia/include/core/SkCanvas.h" |
21 #include "third_party/skia/include/core/SkImage.h" | 20 #include "third_party/skia/include/core/SkImage.h" |
22 #include "ui/gfx/skia_util.h" | 21 #include "ui/gfx/skia_util.h" |
23 | 22 |
24 namespace cc { | 23 namespace cc { |
25 namespace { | 24 namespace { |
26 | 25 |
27 // The amount of memory we can lock ahead of time (128MB). This limit is only | 26 // The amount of memory we can lock ahead of time (128MB). This limit is only |
28 // used to inform the caller of the amount of space available in the cache. The | 27 // used to inform the caller of the amount of space available in the cache. The |
29 // caller can still request tasks which can cause this limit to be breached. | 28 // caller can still request tasks which can cause this limit to be breached. |
30 const size_t kLockedMemoryLimitBytes = 128 * 1024 * 1024; | 29 const size_t kLockedMemoryLimitBytes = 128 * 1024 * 1024; |
31 | 30 |
32 // The largest single high quality image to try and process. Images above this | 31 // The largest single high quality image to try and process. Images above this |
33 // size will drop down to medium quality. | 32 // size will drop down to medium quality. |
34 const size_t kMaxHighQualityImageSizeBytes = 64 * 1024 * 1024; | 33 const size_t kMaxHighQualityImageSizeBytes = 64 * 1024 * 1024; |
35 | 34 |
36 // The number of entries to keep around in the cache. This limit can be breached | 35 // The number of entries to keep around in the cache. This limit can be breached |
37 // if more items are locked. That is, locked items ignore this limit. | 36 // if more items are locked. That is, locked items ignore this limit. |
38 const size_t kMaxItemsInCache = 1000; | 37 const size_t kMaxItemsInCache = 1000; |
39 | 38 |
40 class AutoRemoveKeyFromTaskMap { | 39 class AutoRemoveKeyFromTaskMap { |
41 public: | 40 public: |
42 AutoRemoveKeyFromTaskMap( | 41 AutoRemoveKeyFromTaskMap( |
43 std::unordered_map<SoftwareImageDecodeController::ImageKey, | 42 std::unordered_map<SoftwareImageDecodeController::ImageKey, |
44 scoped_refptr<ImageDecodeTask>, | 43 scoped_refptr<Task>, |
45 SoftwareImageDecodeController::ImageKeyHash>* task_map, | 44 SoftwareImageDecodeController::ImageKeyHash>* task_map, |
46 const SoftwareImageDecodeController::ImageKey& key) | 45 const SoftwareImageDecodeController::ImageKey& key) |
47 : task_map_(task_map), key_(key) {} | 46 : task_map_(task_map), key_(key) {} |
48 ~AutoRemoveKeyFromTaskMap() { task_map_->erase(key_); } | 47 ~AutoRemoveKeyFromTaskMap() { task_map_->erase(key_); } |
49 | 48 |
50 private: | 49 private: |
51 std::unordered_map<SoftwareImageDecodeController::ImageKey, | 50 std::unordered_map<SoftwareImageDecodeController::ImageKey, |
52 scoped_refptr<ImageDecodeTask>, | 51 scoped_refptr<Task>, |
53 SoftwareImageDecodeController::ImageKeyHash>* task_map_; | 52 SoftwareImageDecodeController::ImageKeyHash>* task_map_; |
54 SoftwareImageDecodeController::ImageKey key_; | 53 SoftwareImageDecodeController::ImageKey key_; |
55 }; | 54 }; |
56 | 55 |
57 class ImageDecodeTaskImpl : public ImageDecodeTask { | 56 class ImageDecodeTaskImpl : public Task { |
58 public: | 57 public: |
59 ImageDecodeTaskImpl(SoftwareImageDecodeController* controller, | 58 ImageDecodeTaskImpl(SoftwareImageDecodeController* controller, |
60 const SoftwareImageDecodeController::ImageKey& image_key, | 59 const SoftwareImageDecodeController::ImageKey& image_key, |
61 const DrawImage& image, | 60 const DrawImage& image, |
62 uint64_t source_prepare_tiles_id) | 61 uint64_t source_prepare_tiles_id) |
63 : controller_(controller), | 62 : controller_(controller), |
64 image_key_(image_key), | 63 image_key_(image_key), |
65 image_(image), | 64 image_(image), |
66 image_ref_(skia::SharePtr(image.image())), | 65 image_ref_(skia::SharePtr(image.image())), |
67 source_prepare_tiles_id_(source_prepare_tiles_id) { | 66 source_prepare_tiles_id_(source_prepare_tiles_id) { |
68 SetTaskTypeId(TASK_TYPE_IMAGE_DECODE); | 67 SetTaskType(TASK_TYPE_IMAGE_DECODE); |
69 } | 68 } |
70 | 69 |
71 // Overridden from Task: | 70 // Overridden from Task: |
72 void RunOnWorkerThread() override { | 71 void RunOnWorkerThread() override { |
73 TRACE_EVENT2("cc", "ImageDecodeTaskImpl::RunOnWorkerThread", "mode", | 72 TRACE_EVENT2("cc", "ImageDecodeTaskImpl::RunOnWorkerThread", "mode", |
74 "software", "source_prepare_tiles_id", | 73 "software", "source_prepare_tiles_id", |
75 source_prepare_tiles_id_); | 74 source_prepare_tiles_id_); |
76 devtools_instrumentation::ScopedImageDecodeTask image_decode_task( | 75 devtools_instrumentation::ScopedImageDecodeTask image_decode_task( |
77 image_ref_.get()); | 76 image_ref_.get()); |
78 controller_->DecodeImage(image_key_, image_); | 77 controller_->DecodeImage(image_key_, image_); |
(...skipping 63 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
142 DCHECK_EQ(0u, at_raster_decoded_images_ref_counts_.size()); | 141 DCHECK_EQ(0u, at_raster_decoded_images_ref_counts_.size()); |
143 | 142 |
144 // It is safe to unregister, even if we didn't register in the constructor. | 143 // It is safe to unregister, even if we didn't register in the constructor. |
145 base::trace_event::MemoryDumpManager::GetInstance()->UnregisterDumpProvider( | 144 base::trace_event::MemoryDumpManager::GetInstance()->UnregisterDumpProvider( |
146 this); | 145 this); |
147 } | 146 } |
148 | 147 |
149 bool SoftwareImageDecodeController::GetTaskForImageAndRef( | 148 bool SoftwareImageDecodeController::GetTaskForImageAndRef( |
150 const DrawImage& image, | 149 const DrawImage& image, |
151 uint64_t prepare_tiles_id, | 150 uint64_t prepare_tiles_id, |
152 scoped_refptr<ImageDecodeTask>* task) { | 151 scoped_refptr<Task>* task) { |
153 // If the image already exists or if we're going to create a task for it, then | 152 // If the image already exists or if we're going to create a task for it, then |
154 // we'll likely need to ref this image (the exception is if we're prerolling | 153 // we'll likely need to ref this image (the exception is if we're prerolling |
155 // the image only). That means the image is or will be in the cache. When the | 154 // the image only). That means the image is or will be in the cache. When the |
156 // ref goes to 0, it will be unpinned but will remain in the cache. If the | 155 // ref goes to 0, it will be unpinned but will remain in the cache. If the |
157 // image does not fit into the budget, then we don't ref this image, since it | 156 // image does not fit into the budget, then we don't ref this image, since it |
158 // will be decoded at raster time which is when it will be temporarily put in | 157 // will be decoded at raster time which is when it will be temporarily put in |
159 // the cache. | 158 // the cache. |
160 ImageKey key = ImageKey::FromDrawImage(image); | 159 ImageKey key = ImageKey::FromDrawImage(image); |
161 TRACE_EVENT1("disabled-by-default-cc.debug", | 160 TRACE_EVENT1("disabled-by-default-cc.debug", |
162 "SoftwareImageDecodeController::GetTaskForImageAndRef", "key", | 161 "SoftwareImageDecodeController::GetTaskForImageAndRef", "key", |
163 key.ToString()); | 162 key.ToString()); |
164 | 163 |
165 // If the target size is empty, we can skip this image during draw (and thus | 164 // If the target size is empty, we can skip this image during draw (and thus |
166 // we don't need to decode it or ref it). | 165 // we don't need to decode it or ref it). |
167 if (key.target_size().IsEmpty()) { | 166 if (key.target_size().IsEmpty()) { |
168 *task = nullptr; | 167 *task = nullptr; |
169 return false; | 168 return false; |
170 } | 169 } |
171 | 170 |
172 // If we're not going to do a scale, we will just create a task to preroll the | 171 // If we're not going to do a scale, we will just create a task to preroll the |
173 // image the first time we see it. This doesn't need to account for memory. | 172 // image the first time we see it. This doesn't need to account for memory. |
174 // TODO(vmpstr): We can also lock the original sized image, in which case it | 173 // TODO(vmpstr): We can also lock the original sized image, in which case it |
175 // does require memory bookkeeping. | 174 // does require memory bookkeeping. |
176 if (!CanHandleImage(key)) { | 175 if (!CanHandleImage(key)) { |
177 base::AutoLock lock(lock_); | 176 base::AutoLock lock(lock_); |
178 if (prerolled_images_.count(key.image_id()) == 0) { | 177 if (prerolled_images_.count(key.image_id()) == 0) { |
179 scoped_refptr<ImageDecodeTask>& existing_task = pending_image_tasks_[key]; | 178 scoped_refptr<Task>& existing_task = pending_image_tasks_[key]; |
180 if (!existing_task) { | 179 if (!existing_task) { |
181 existing_task = make_scoped_refptr( | 180 existing_task = make_scoped_refptr( |
182 new ImageDecodeTaskImpl(this, key, image, prepare_tiles_id)); | 181 new ImageDecodeTaskImpl(this, key, image, prepare_tiles_id)); |
183 } | 182 } |
184 *task = existing_task; | 183 *task = existing_task; |
185 } else { | 184 } else { |
186 *task = nullptr; | 185 *task = nullptr; |
187 } | 186 } |
188 return false; | 187 return false; |
189 } | 188 } |
(...skipping 12 matching lines...) Expand all Loading... |
202 SanityCheckState(__LINE__, true); | 201 SanityCheckState(__LINE__, true); |
203 return true; | 202 return true; |
204 } | 203 } |
205 // If the image fits in memory, then we at least tried to lock it and | 204 // If the image fits in memory, then we at least tried to lock it and |
206 // failed. This means that it's not valid anymore. | 205 // failed. This means that it's not valid anymore. |
207 if (new_image_fits_in_memory) | 206 if (new_image_fits_in_memory) |
208 decoded_images_.Erase(decoded_it); | 207 decoded_images_.Erase(decoded_it); |
209 } | 208 } |
210 | 209 |
211 // If the task exists, return it. | 210 // If the task exists, return it. |
212 scoped_refptr<ImageDecodeTask>& existing_task = pending_image_tasks_[key]; | 211 scoped_refptr<Task>& existing_task = pending_image_tasks_[key]; |
213 if (existing_task) { | 212 if (existing_task) { |
214 RefImage(key); | 213 RefImage(key); |
215 *task = existing_task; | 214 *task = existing_task; |
216 SanityCheckState(__LINE__, true); | 215 SanityCheckState(__LINE__, true); |
217 return true; | 216 return true; |
218 } | 217 } |
219 | 218 |
220 // At this point, we have to create a new image/task, so we need to abort if | 219 // At this point, we have to create a new image/task, so we need to abort if |
221 // it doesn't fit into memory and there are currently no raster tasks that | 220 // it doesn't fit into memory and there are currently no raster tasks that |
222 // would have already accounted for memory. The latter part is possible if | 221 // would have already accounted for memory. The latter part is possible if |
(...skipping 706 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
929 void SoftwareImageDecodeController::MemoryBudget::ResetUsage() { | 928 void SoftwareImageDecodeController::MemoryBudget::ResetUsage() { |
930 current_usage_bytes_ = 0; | 929 current_usage_bytes_ = 0; |
931 } | 930 } |
932 | 931 |
933 size_t SoftwareImageDecodeController::MemoryBudget::GetCurrentUsageSafe() | 932 size_t SoftwareImageDecodeController::MemoryBudget::GetCurrentUsageSafe() |
934 const { | 933 const { |
935 return current_usage_bytes_.ValueOrDie(); | 934 return current_usage_bytes_.ValueOrDie(); |
936 } | 935 } |
937 | 936 |
938 } // namespace cc | 937 } // namespace cc |
OLD | NEW |