| OLD | NEW |
| 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 Loading... |
| 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 Loading... |
| 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 Loading... |
| 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 |
| OLD | NEW |