Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(470)

Side by Side Diff: cc/tiles/checker_image_tracker.cc

Issue 2928433003: cc: Add scaling for checkered images. (Closed)
Patch Set: .. Created 3 years, 6 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch
« no previous file with comments | « cc/tiles/checker_image_tracker.h ('k') | cc/tiles/checker_image_tracker_unittest.cc » ('j') | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
OLDNEW
1 // Copyright 2017 The Chromium Authors. All rights reserved. 1 // Copyright 2017 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/checker_image_tracker.h" 5 #include "cc/tiles/checker_image_tracker.h"
6 6
7 #include "base/bind.h" 7 #include "base/bind.h"
8 #include "base/memory/ptr_util.h" 8 #include "base/memory/ptr_util.h"
9 #include "base/stl_util.h" 9 #include "base/stl_util.h"
10 #include "base/trace_event/trace_event.h" 10 #include "base/trace_event/trace_event.h"
11 11
12 namespace cc { 12 namespace cc {
13 namespace { 13 namespace {
14 // The minimum size of an image that we should consider checkering. 14 // The minimum size of an image that we should consider checkering.
15 size_t kMinImageSizeToCheckerBytes = 512 * 1024; 15 size_t kMinImageSizeToCheckerBytes = 512 * 1024;
16 16
17 size_t SafeSizeOfImage(const SkImage* image) { 17 size_t SafeSizeOfImage(const SkImage* image) {
18 base::CheckedNumeric<size_t> checked_size = 4; 18 base::CheckedNumeric<size_t> checked_size = 4;
19 checked_size *= image->width(); 19 checked_size *= image->width();
20 checked_size *= image->height(); 20 checked_size *= image->height();
21 return checked_size.ValueOrDefault(std::numeric_limits<size_t>::max()); 21 return checked_size.ValueOrDefault(std::numeric_limits<size_t>::max());
22 } 22 }
23 23
24 std::string ToString(PaintImage::Id paint_image_id,
25 SkImageId sk_image_id,
26 bool complete,
27 bool static_image,
28 bool fits_size_constraints,
29 size_t size) {
30 std::ostringstream str;
31 str << "paint_image_id[" << paint_image_id << "] sk_image_id[" << sk_image_id
32 << "] complete[" << complete << "] static[" << static_image
33 << "], fits_size_constraints[" << fits_size_constraints << "], size["
34 << size << "]";
35 return str.str();
36 }
37
24 } // namespace 38 } // namespace
25 39
26 CheckerImageTracker::CheckerImageTracker(ImageController* image_controller, 40 CheckerImageTracker::CheckerImageTracker(ImageController* image_controller,
27 CheckerImageTrackerClient* client, 41 CheckerImageTrackerClient* client,
28 bool enable_checker_imaging) 42 bool enable_checker_imaging)
29 : image_controller_(image_controller), 43 : image_controller_(image_controller),
30 client_(client), 44 client_(client),
31 enable_checker_imaging_(enable_checker_imaging), 45 enable_checker_imaging_(enable_checker_imaging),
32 weak_factory_(this) {} 46 weak_factory_(this) {}
33 47
(...skipping 48 matching lines...) Expand 10 before | Expand all | Expand 10 after
82 image_id_to_decode_.clear(); 96 image_id_to_decode_.clear();
83 97
84 if (can_clear_decode_policy_tracking) { 98 if (can_clear_decode_policy_tracking) {
85 image_async_decode_state_.clear(); 99 image_async_decode_state_.clear();
86 } else { 100 } else {
87 // If we can't clear the decode policy, we need to make sure we still 101 // If we can't clear the decode policy, we need to make sure we still
88 // re-decode and checker images that were pending invalidation. 102 // re-decode and checker images that were pending invalidation.
89 for (auto image_id : images_pending_invalidation_) { 103 for (auto image_id : images_pending_invalidation_) {
90 auto it = image_async_decode_state_.find(image_id); 104 auto it = image_async_decode_state_.find(image_id);
91 DCHECK(it != image_async_decode_state_.end()); 105 DCHECK(it != image_async_decode_state_.end());
92 DCHECK_EQ(it->second, DecodePolicy::SYNC); 106 DCHECK_EQ(it->second.policy, DecodePolicy::SYNC);
93 it->second = DecodePolicy::ASYNC; 107 it->second.policy = DecodePolicy::ASYNC;
94 } 108 }
95 } 109 }
96 images_pending_invalidation_.clear(); 110 images_pending_invalidation_.clear();
97 } 111 }
98 112
99 void CheckerImageTracker::DisallowCheckeringForImage(const PaintImage& image) { 113 void CheckerImageTracker::DisallowCheckeringForImage(const PaintImage& image) {
100 image_async_decode_state_.insert( 114 image_async_decode_state_.insert(
101 std::make_pair(image.stable_id(), DecodePolicy::SYNC)); 115 std::make_pair(image.stable_id(), DecodeState()));
102 } 116 }
103 117
104 void CheckerImageTracker::DidFinishImageDecode( 118 void CheckerImageTracker::DidFinishImageDecode(
105 PaintImage::Id image_id, 119 PaintImage::Id image_id,
106 ImageController::ImageDecodeRequestId request_id, 120 ImageController::ImageDecodeRequestId request_id,
107 ImageController::ImageDecodeResult result) { 121 ImageController::ImageDecodeResult result) {
108 TRACE_EVENT0(TRACE_DISABLED_BY_DEFAULT("cc.debug"), 122 TRACE_EVENT0(TRACE_DISABLED_BY_DEFAULT("cc.debug"),
109 "CheckerImageTracker::DidFinishImageDecode"); 123 "CheckerImageTracker::DidFinishImageDecode");
110 TRACE_EVENT_ASYNC_END0("cc", "CheckerImageTracker::DeferImageDecode", 124 TRACE_EVENT_ASYNC_END0("cc", "CheckerImageTracker::DeferImageDecode",
111 image_id); 125 image_id);
112 126
113 DCHECK_NE(ImageController::ImageDecodeResult::DECODE_NOT_REQUIRED, result); 127 DCHECK_NE(ImageController::ImageDecodeResult::DECODE_NOT_REQUIRED, result);
114 DCHECK_EQ(outstanding_image_decode_.value().stable_id(), image_id); 128 DCHECK_EQ(outstanding_image_decode_.value().stable_id(), image_id);
115 outstanding_image_decode_.reset(); 129 outstanding_image_decode_.reset();
116 130
117 // The async decode state may have been cleared if the tracker was cleared 131 // The async decode state may have been cleared if the tracker was cleared
118 // before this decode could be finished. 132 // before this decode could be finished.
119 auto it = image_async_decode_state_.find(image_id); 133 auto it = image_async_decode_state_.find(image_id);
120 if (it == image_async_decode_state_.end()) { 134 if (it == image_async_decode_state_.end()) {
121 DCHECK_EQ(image_id_to_decode_.count(image_id), 0u); 135 DCHECK_EQ(image_id_to_decode_.count(image_id), 0u);
122 return; 136 return;
123 } 137 }
124 138
125 it->second = DecodePolicy::SYNC; 139 it->second.policy = DecodePolicy::SYNC;
126 images_pending_invalidation_.insert(image_id); 140 images_pending_invalidation_.insert(image_id);
127 ScheduleNextImageDecode(); 141 ScheduleNextImageDecode();
128 client_->NeedsInvalidationForCheckerImagedTiles(); 142 client_->NeedsInvalidationForCheckerImagedTiles();
129 } 143 }
130 144
131 bool CheckerImageTracker::ShouldCheckerImage(const PaintImage& image, 145 bool CheckerImageTracker::ShouldCheckerImage(const DrawImage& draw_image,
132 WhichTree tree) { 146 WhichTree tree) {
147 const PaintImage& image = draw_image.paint_image();
148 PaintImage::Id image_id = image.stable_id();
133 TRACE_EVENT1("cc", "CheckerImageTracker::ShouldCheckerImage", "image_id", 149 TRACE_EVENT1("cc", "CheckerImageTracker::ShouldCheckerImage", "image_id",
134 image.stable_id()); 150 image_id);
135 151
136 if (!enable_checker_imaging_) 152 if (!enable_checker_imaging_)
137 return false; 153 return false;
138 154
139 PaintImage::Id image_id = image.stable_id();
140
141 // If the image was invalidated on the current sync tree and the tile is 155 // If the image was invalidated on the current sync tree and the tile is
142 // for the active tree, continue checkering it on the active tree to ensure 156 // for the active tree, continue checkering it on the active tree to ensure
143 // the image update is atomic for the frame. 157 // the image update is atomic for the frame.
144 if (invalidated_images_on_current_sync_tree_.count(image_id) != 0 && 158 if (invalidated_images_on_current_sync_tree_.count(image_id) != 0 &&
145 tree == WhichTree::ACTIVE_TREE) { 159 tree == WhichTree::ACTIVE_TREE) {
146 return true; 160 return true;
147 } 161 }
148 162
149 // If the image is pending invalidation, continue checkering it. All tiles 163 // If the image is pending invalidation, continue checkering it. All tiles
150 // for these images will be invalidated on the next pending tree. 164 // for these images will be invalidated on the next pending tree.
151 if (images_pending_invalidation_.find(image_id) != 165 if (images_pending_invalidation_.find(image_id) !=
152 images_pending_invalidation_.end()) { 166 images_pending_invalidation_.end()) {
153 return true; 167 return true;
154 } 168 }
155 169
156 auto insert_result = image_async_decode_state_.insert( 170 auto insert_result = image_async_decode_state_.insert(
157 std::pair<PaintImage::Id, DecodePolicy>(image_id, DecodePolicy::SYNC)); 171 std::pair<PaintImage::Id, DecodeState>(image_id, DecodeState()));
158 auto it = insert_result.first; 172 auto it = insert_result.first;
159 if (insert_result.second) { 173 if (insert_result.second) {
160 bool can_checker_image = 174 bool complete =
161 image.animation_type() == PaintImage::AnimationType::STATIC &&
162 image.completion_state() == PaintImage::CompletionState::DONE; 175 image.completion_state() == PaintImage::CompletionState::DONE;
163 if (can_checker_image) { 176 bool static_image =
164 size_t size = SafeSizeOfImage(image.sk_image().get()); 177 image.animation_type() == PaintImage::AnimationType::STATIC;
165 it->second = (size >= kMinImageSizeToCheckerBytes && 178 size_t size = SafeSizeOfImage(image.sk_image().get());
166 size <= image_controller_->image_cache_max_limit_bytes()) 179 bool fits_size_constraints =
167 ? DecodePolicy::ASYNC 180 size >= kMinImageSizeToCheckerBytes &&
168 : DecodePolicy::SYNC; 181 size <= image_controller_->image_cache_max_limit_bytes();
169 } 182
183 // Only checker images that are static and completely loaded and fit within
184 // the size constraints.
185 bool can_checker_image = complete && static_image && fits_size_constraints;
186 if (can_checker_image)
187 it->second.policy = DecodePolicy::ASYNC;
188
189 TRACE_EVENT2(TRACE_DISABLED_BY_DEFAULT("cc.debug"),
190 "CheckerImageTracker::CheckerImagingDecision",
191 "can_checker_image", can_checker_image, "image_params",
192 ToString(image_id, image.sk_image()->uniqueID(), complete,
193 static_image, fits_size_constraints, size));
170 } 194 }
171 195
172 return it->second == DecodePolicy::ASYNC; 196 // Update the decode state from the latest image we have seen. Note that it
197 // is not necessary to perform this in the early out cases above since in
198 // each of those cases the image has already been decoded.
199 UpdateDecodeState(draw_image, image_id, &it->second);
200
201 return it->second.policy == DecodePolicy::ASYNC;
202 }
203
204 void CheckerImageTracker::UpdateDecodeState(const DrawImage& draw_image,
205 PaintImage::Id paint_image_id,
206 DecodeState* decode_state) {
207 // If the policy is not async then either we decoded this image already or
208 // we decided not to ever checker it.
209 if (decode_state->policy != DecodePolicy::ASYNC)
210 return;
211
212 // If the decode is already in flight, then we will have to live with what we
213 // have now.
214 if (outstanding_image_decode_.has_value() &&
215 outstanding_image_decode_.value().stable_id() == paint_image_id) {
216 return;
217 }
218
219 // Choose the max scale and filter quality. This keeps the memory usage to the
220 // minimum possible while still increasing the possibility of getting a cache
221 // hit.
222 decode_state->scale = SkSize::Make(
223 std::max(decode_state->scale.fWidth, draw_image.scale().fWidth),
224 std::max(decode_state->scale.fHeight, draw_image.scale().fHeight));
225 decode_state->filter_quality =
226 std::max(decode_state->filter_quality, draw_image.filter_quality());
227 decode_state->color_space = draw_image.target_color_space();
173 } 228 }
174 229
175 void CheckerImageTracker::ScheduleNextImageDecode() { 230 void CheckerImageTracker::ScheduleNextImageDecode() {
176 TRACE_EVENT0(TRACE_DISABLED_BY_DEFAULT("cc.debug"), 231 TRACE_EVENT0(TRACE_DISABLED_BY_DEFAULT("cc.debug"),
177 "CheckerImageTracker::ScheduleNextImageDecode"); 232 "CheckerImageTracker::ScheduleNextImageDecode");
178 // We can have only one outsanding decode pending completion with the decode 233 // We can have only one outstanding decode pending completion with the decode
179 // service. We'll come back here when it is completed. 234 // service. We'll come back here when it is completed.
180 if (outstanding_image_decode_.has_value()) 235 if (outstanding_image_decode_.has_value())
181 return; 236 return;
182 237
238 DrawImage draw_image;
183 while (!image_decode_queue_.empty()) { 239 while (!image_decode_queue_.empty()) {
184 auto candidate = std::move(image_decode_queue_.front()); 240 auto candidate = std::move(image_decode_queue_.front());
185 image_decode_queue_.erase(image_decode_queue_.begin()); 241 image_decode_queue_.erase(image_decode_queue_.begin());
186 242
187 // Once an image has been decoded, it can still be present in the decode 243 // Once an image has been decoded, it can still be present in the decode
188 // queue (duplicate entries), or while an image is still being skipped on 244 // queue (duplicate entries), or while an image is still being skipped on
189 // the active tree. Check if the image is still ASYNC to see if a decode is 245 // the active tree. Check if the image is still ASYNC to see if a decode is
190 // needed. 246 // needed.
191 PaintImage::Id image_id = candidate.stable_id(); 247 PaintImage::Id image_id = candidate.stable_id();
192 auto it = image_async_decode_state_.find(image_id); 248 auto it = image_async_decode_state_.find(image_id);
193 DCHECK(it != image_async_decode_state_.end()); 249 DCHECK(it != image_async_decode_state_.end());
194 if (it->second != DecodePolicy::ASYNC) 250 if (it->second.policy != DecodePolicy::ASYNC)
195 continue; 251 continue;
196 252
253 draw_image = DrawImage(candidate, candidate.sk_image()->bounds(),
254 it->second.filter_quality,
255 SkMatrix::MakeScale(it->second.scale.width(),
256 it->second.scale.height()),
257 it->second.color_space);
197 outstanding_image_decode_.emplace(candidate); 258 outstanding_image_decode_.emplace(candidate);
198 break; 259 break;
199 } 260 }
200 261
201 // We either found an image to decode or we reached the end of the queue. If 262 // We either found an image to decode or we reached the end of the queue. If
202 // we couldn't find an image, we're done. 263 // we couldn't find an image, we're done.
203 if (!outstanding_image_decode_.has_value()) { 264 if (!outstanding_image_decode_.has_value()) {
204 DCHECK(image_decode_queue_.empty()); 265 DCHECK(image_decode_queue_.empty());
205 return; 266 return;
206 } 267 }
207 268
208 PaintImage::Id image_id = outstanding_image_decode_.value().stable_id(); 269 PaintImage::Id image_id = outstanding_image_decode_.value().stable_id();
209 DCHECK_EQ(image_id_to_decode_.count(image_id), 0u); 270 DCHECK_EQ(image_id_to_decode_.count(image_id), 0u);
210 TRACE_EVENT_ASYNC_BEGIN0("cc", "CheckerImageTracker::DeferImageDecode", 271 TRACE_EVENT_ASYNC_BEGIN0("cc", "CheckerImageTracker::DeferImageDecode",
211 image_id); 272 image_id);
212 ImageController::ImageDecodeRequestId request_id = 273 ImageController::ImageDecodeRequestId request_id =
213 image_controller_->QueueImageDecode( 274 image_controller_->QueueImageDecode(
214 outstanding_image_decode_.value().sk_image(), 275 draw_image, base::Bind(&CheckerImageTracker::DidFinishImageDecode,
215 base::Bind(&CheckerImageTracker::DidFinishImageDecode, 276 weak_factory_.GetWeakPtr(), image_id));
216 weak_factory_.GetWeakPtr(), image_id));
217 277
218 image_id_to_decode_.emplace(image_id, base::MakeUnique<ScopedDecodeHolder>( 278 image_id_to_decode_.emplace(image_id, base::MakeUnique<ScopedDecodeHolder>(
219 image_controller_, request_id)); 279 image_controller_, request_id));
220 } 280 }
221 281
222 } // namespace cc 282 } // namespace cc
OLDNEW
« no previous file with comments | « cc/tiles/checker_image_tracker.h ('k') | cc/tiles/checker_image_tracker_unittest.cc » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698