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

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

Issue 2703633004: cc: Make image controller return a status with the callback. (Closed)
Patch Set: update Created 3 years, 9 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/image_controller.h ('k') | cc/tiles/image_controller_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 2016 The Chromium Authors. All rights reserved. 1 // Copyright 2016 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/image_controller.h" 5 #include "cc/tiles/image_controller.h"
6 6
7 #include "base/bind.h" 7 #include "base/bind.h"
8 #include "base/task_scheduler/post_task.h" 8 #include "base/task_scheduler/post_task.h"
9 #include "base/task_scheduler/task_traits.h" 9 #include "base/task_scheduler/task_traits.h"
10 #include "base/threading/thread_restrictions.h" 10 #include "base/threading/thread_restrictions.h"
(...skipping 70 matching lines...) Expand 10 before | Expand all | Expand 10 after
81 // sure it was completed. Multiple requests for the same image use the same 81 // sure it was completed. Multiple requests for the same image use the same
82 // task so it could have already been completed. 82 // task so it could have already been completed.
83 if (request.task && !request.task->HasCompleted()) 83 if (request.task && !request.task->HasCompleted())
84 request.task->DidComplete(); 84 request.task->DidComplete();
85 85
86 // Issue the callback, and unref the image immediately. This is so that any 86 // Issue the callback, and unref the image immediately. This is so that any
87 // code waiting on the callback can proceed, although we're breaking the 87 // code waiting on the callback can proceed, although we're breaking the
88 // promise of having this image decoded. This is unfortunate, but it seems 88 // promise of having this image decoded. This is unfortunate, but it seems
89 // like the least complexity to process an image decode controller becoming 89 // like the least complexity to process an image decode controller becoming
90 // nullptr. 90 // nullptr.
91 request.callback.Run(id); 91 // TODO(vmpstr): We can move these back to |image_decode_queue_| instead
92 // and defer completion until we get a new cache and process the request
93 // again. crbug.com/693692.
94 request.callback.Run(id, ImageDecodeResult::FAILURE);
92 if (request.need_unref) 95 if (request.need_unref)
93 cache_->UnrefImage(request.draw_image); 96 cache_->UnrefImage(request.draw_image);
94 } 97 }
95 requests_needing_completion_.clear(); 98 requests_needing_completion_.clear();
96 99
97 // Finally, complete all of the tasks that never started running. This is 100 // Finally, complete all of the tasks that never started running. This is
98 // similar to the |requests_needing_completion_|, but happens at a different 101 // similar to the |requests_needing_completion_|, but happens at a different
99 // stage in the pipeline. 102 // stage in the pipeline.
100 for (auto& request_pair : image_decode_queue_) { 103 for (auto& request_pair : image_decode_queue_) {
101 ImageDecodeRequestId id = request_pair.first; 104 ImageDecodeRequestId id = request_pair.first;
102 ImageDecodeRequest& request = request_pair.second; 105 ImageDecodeRequest& request = request_pair.second;
103 106
104 if (request.task) { 107 if (request.task) {
105 // This task may have run via a different request, so only cancel it if 108 // This task may have run via a different request, so only cancel it if
106 // it's "new". That is, the same task could have been referenced by 109 // it's "new". That is, the same task could have been referenced by
107 // several different image deque requests for the same image. 110 // several different image deque requests for the same image.
108 if (request.task->state().IsNew()) 111 if (request.task->state().IsNew())
109 request.task->state().DidCancel(); 112 request.task->state().DidCancel();
110 113
111 if (!request.task->HasCompleted()) 114 if (!request.task->HasCompleted())
112 request.task->DidComplete(); 115 request.task->DidComplete();
113 } 116 }
114 // Run the callback and unref the image. 117 // Run the callback and unref the image.
115 request.callback.Run(id); 118 // TODO(vmpstr): We can regenerate the tasks for the new cache if we get
119 // one. crbug.com/693692.
120 request.callback.Run(id, ImageDecodeResult::FAILURE);
116 cache_->UnrefImage(request.draw_image); 121 cache_->UnrefImage(request.draw_image);
117 } 122 }
118 image_decode_queue_.clear(); 123 image_decode_queue_.clear();
119 } 124 }
120 125
121 void ImageController::SetImageDecodeCache(ImageDecodeCache* cache) { 126 void ImageController::SetImageDecodeCache(ImageDecodeCache* cache) {
122 DCHECK(!cache_ || !cache); 127 DCHECK(!cache_ || !cache);
123 128
124 if (!cache) { 129 if (!cache) {
125 SetPredecodeImages(std::vector<DrawImage>(), 130 SetPredecodeImages(std::vector<DrawImage>(),
(...skipping 46 matching lines...) Expand 10 before | Expand all | Expand 10 after
172 ImageController::ImageDecodeRequestId ImageController::QueueImageDecode( 177 ImageController::ImageDecodeRequestId ImageController::QueueImageDecode(
173 sk_sp<const SkImage> image, 178 sk_sp<const SkImage> image,
174 const ImageDecodedCallback& callback) { 179 const ImageDecodedCallback& callback) {
175 // We must not receive any image requests if we have no worker. 180 // We must not receive any image requests if we have no worker.
176 CHECK(worker_task_runner_); 181 CHECK(worker_task_runner_);
177 182
178 // Generate the next id. 183 // Generate the next id.
179 ImageDecodeRequestId id = s_next_image_decode_queue_id_++; 184 ImageDecodeRequestId id = s_next_image_decode_queue_id_++;
180 185
181 DCHECK(image); 186 DCHECK(image);
187 bool is_image_lazy = image->isLazyGenerated();
182 auto image_bounds = image->bounds(); 188 auto image_bounds = image->bounds();
183 DrawImage draw_image(std::move(image), image_bounds, kNone_SkFilterQuality, 189 DrawImage draw_image(std::move(image), image_bounds, kNone_SkFilterQuality,
184 SkMatrix::I()); 190 SkMatrix::I());
185 191
186 // Get the tasks for this decode. 192 // Get the tasks for this decode.
187 scoped_refptr<TileTask> task; 193 scoped_refptr<TileTask> task;
188 bool need_unref = 194 bool need_unref = false;
189 cache_->GetOutOfRasterDecodeTaskForImageAndRef(draw_image, &task); 195 if (is_image_lazy) {
196 need_unref =
197 cache_->GetOutOfRasterDecodeTaskForImageAndRef(draw_image, &task);
198 }
190 // If we don't need to unref this, we don't actually have a task. 199 // If we don't need to unref this, we don't actually have a task.
191 DCHECK(need_unref || !task); 200 DCHECK(need_unref || !task);
192 201
193 // Schedule the task and signal that there is more work. 202 // Schedule the task and signal that there is more work.
194 base::AutoLock hold(lock_); 203 base::AutoLock hold(lock_);
195 image_decode_queue_[id] = 204 image_decode_queue_[id] =
196 ImageDecodeRequest(id, draw_image, callback, std::move(task), need_unref); 205 ImageDecodeRequest(id, draw_image, callback, std::move(task), need_unref);
197 206
198 // If this is the only image decode request, schedule a task to run. 207 // If this is the only image decode request, schedule a task to run.
199 // Otherwise, the task will be scheduled in the previou task's completion. 208 // Otherwise, the task will be scheduled in the previou task's completion.
(...skipping 56 matching lines...) Expand 10 before | Expand all | Expand 10 after
256 decode.task->RunOnWorkerThread(); 265 decode.task->RunOnWorkerThread();
257 decode.task->state().DidFinish(); 266 decode.task->state().DidFinish();
258 } 267 }
259 origin_task_runner_->PostTask( 268 origin_task_runner_->PostTask(
260 FROM_HERE, base::Bind(&ImageController::ImageDecodeCompleted, 269 FROM_HERE, base::Bind(&ImageController::ImageDecodeCompleted,
261 weak_ptr_factory_.GetWeakPtr(), decode.id)); 270 weak_ptr_factory_.GetWeakPtr(), decode.id));
262 } 271 }
263 272
264 void ImageController::ImageDecodeCompleted(ImageDecodeRequestId id) { 273 void ImageController::ImageDecodeCompleted(ImageDecodeRequestId id) {
265 ImageDecodedCallback callback; 274 ImageDecodedCallback callback;
275 ImageDecodeResult result = ImageDecodeResult::SUCCESS;
266 { 276 {
267 base::AutoLock hold(lock_); 277 base::AutoLock hold(lock_);
268 278
269 auto request_it = requests_needing_completion_.find(id); 279 auto request_it = requests_needing_completion_.find(id);
270 DCHECK(request_it != requests_needing_completion_.end()); 280 DCHECK(request_it != requests_needing_completion_.end());
271 id = request_it->first; 281 id = request_it->first;
272 ImageDecodeRequest& request = request_it->second; 282 ImageDecodeRequest& request = request_it->second;
273 283
284 // First, Determine the status of the decode. This has to happen here, since
285 // we conditionally move from the draw image below.
286 // Also note that if we don't need an unref for a lazy decoded images, it
287 // implies that we never attempted the decode. Some of the reasons for this
288 // would be that the image is of an empty size, or if the image doesn't fit
289 // into memory. In all cases, this implies that the decode was a failure.
290 if (!request.draw_image.image()->isLazyGenerated())
291 result = ImageDecodeResult::DECODE_NOT_REQUIRED;
292 else if (!request.need_unref)
293 result = ImageDecodeResult::FAILURE;
294 else
295 result = ImageDecodeResult::SUCCESS;
296
274 // If we need to unref this decode, then we have to put it into the locked 297 // If we need to unref this decode, then we have to put it into the locked
275 // images vector. 298 // images vector.
276 if (request.need_unref) 299 if (request.need_unref)
277 requested_locked_images_[id] = std::move(request.draw_image); 300 requested_locked_images_[id] = std::move(request.draw_image);
278 301
279 // If we have a task that isn't completed yet, we need to complete it. 302 // If we have a task that isn't completed yet, we need to complete it.
280 if (request.task && !request.task->HasCompleted()) { 303 if (request.task && !request.task->HasCompleted()) {
281 request.task->OnTaskCompleted(); 304 request.task->OnTaskCompleted();
282 request.task->DidComplete(); 305 request.task->DidComplete();
283 } 306 }
307
284 // Finally, save the callback so we can run it without the lock, and erase 308 // Finally, save the callback so we can run it without the lock, and erase
285 // the request from |requests_needing_completion_|. 309 // the request from |requests_needing_completion_|.
286 callback = std::move(request.callback); 310 callback = std::move(request.callback);
287 requests_needing_completion_.erase(request_it); 311 requests_needing_completion_.erase(request_it);
288 } 312 }
289 313
290 // Post another task to run. 314 // Post another task to run.
291 worker_task_runner_->PostTask( 315 worker_task_runner_->PostTask(
292 FROM_HERE, 316 FROM_HERE,
293 base::Bind(&ImageController::ProcessNextImageDecodeOnWorkerThread, 317 base::Bind(&ImageController::ProcessNextImageDecodeOnWorkerThread,
294 base::Unretained(this))); 318 base::Unretained(this)));
295 319
296 // Finally run the requested callback. 320 // Finally run the requested callback.
297 callback.Run(id); 321 callback.Run(id, result);
298 } 322 }
299 323
300 ImageController::ImageDecodeRequest::ImageDecodeRequest() = default; 324 ImageController::ImageDecodeRequest::ImageDecodeRequest() = default;
301 ImageController::ImageDecodeRequest::ImageDecodeRequest( 325 ImageController::ImageDecodeRequest::ImageDecodeRequest(
302 ImageDecodeRequestId id, 326 ImageDecodeRequestId id,
303 const DrawImage& draw_image, 327 const DrawImage& draw_image,
304 const ImageDecodedCallback& callback, 328 const ImageDecodedCallback& callback,
305 scoped_refptr<TileTask> task, 329 scoped_refptr<TileTask> task,
306 bool need_unref) 330 bool need_unref)
307 : id(id), 331 : id(id),
308 draw_image(draw_image), 332 draw_image(draw_image),
309 callback(callback), 333 callback(callback),
310 task(std::move(task)), 334 task(std::move(task)),
311 need_unref(need_unref) {} 335 need_unref(need_unref) {}
312 ImageController::ImageDecodeRequest::ImageDecodeRequest( 336 ImageController::ImageDecodeRequest::ImageDecodeRequest(
313 ImageDecodeRequest&& other) = default; 337 ImageDecodeRequest&& other) = default;
314 ImageController::ImageDecodeRequest::ImageDecodeRequest( 338 ImageController::ImageDecodeRequest::ImageDecodeRequest(
315 const ImageDecodeRequest& other) = default; 339 const ImageDecodeRequest& other) = default;
316 ImageController::ImageDecodeRequest::~ImageDecodeRequest() = default; 340 ImageController::ImageDecodeRequest::~ImageDecodeRequest() = default;
317 341
318 ImageController::ImageDecodeRequest& ImageController::ImageDecodeRequest:: 342 ImageController::ImageDecodeRequest& ImageController::ImageDecodeRequest::
319 operator=(ImageDecodeRequest&& other) = default; 343 operator=(ImageDecodeRequest&& other) = default;
320 ImageController::ImageDecodeRequest& ImageController::ImageDecodeRequest:: 344 ImageController::ImageDecodeRequest& ImageController::ImageDecodeRequest::
321 operator=(const ImageDecodeRequest& other) = default; 345 operator=(const ImageDecodeRequest& other) = default;
322 346
323 } // namespace cc 347 } // namespace cc
OLDNEW
« no previous file with comments | « cc/tiles/image_controller.h ('k') | cc/tiles/image_controller_unittest.cc » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698