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

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

Issue 2718243002: cc: Regenerate image decode requests tasks when cache switches. (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"
11 #include "base/trace_event/trace_event.h" 11 #include "base/trace_event/trace_event.h"
12 #include "cc/base/completion_event.h" 12 #include "cc/base/completion_event.h"
13 #include "cc/tiles/tile_task_manager.h" 13 #include "cc/tiles/tile_task_manager.h"
14 14
15 namespace cc { 15 namespace cc {
16 16
17 ImageController::ImageDecodeRequestId 17 ImageController::ImageDecodeRequestId
18 ImageController::s_next_image_decode_queue_id_ = 1; 18 ImageController::s_next_image_decode_queue_id_ = 1;
19 19
20 ImageController::ImageController( 20 ImageController::ImageController(
21 base::SequencedTaskRunner* origin_task_runner, 21 base::SequencedTaskRunner* origin_task_runner,
22 scoped_refptr<base::SequencedTaskRunner> worker_task_runner) 22 scoped_refptr<base::SequencedTaskRunner> worker_task_runner)
23 : worker_task_runner_(std::move(worker_task_runner)), 23 : worker_task_runner_(std::move(worker_task_runner)),
24 origin_task_runner_(origin_task_runner), 24 origin_task_runner_(origin_task_runner),
25 weak_ptr_factory_(this) {} 25 weak_ptr_factory_(this) {}
26 26
27 ImageController::~ImageController() { 27 ImageController::~ImageController() {
28 StopWorkerTasks(); 28 StopWorkerTasks();
29 for (auto& request : orphaned_decode_requests_)
30 request.callback.Run(request.id, ImageDecodeResult::FAILURE);
29 } 31 }
30 32
31 void ImageController::StopWorkerTasks() { 33 void ImageController::StopWorkerTasks() {
32 // We can't have worker threads without a cache_ or a worker_task_runner_, so 34 // We can't have worker threads without a cache_ or a worker_task_runner_, so
33 // terminate early. 35 // terminate early.
34 if (!cache_ || !worker_task_runner_) 36 if (!cache_ || !worker_task_runner_)
35 return; 37 return;
36 38
37 // Abort all tasks that are currently scheduled to run (we'll wait for them to 39 // Abort all tasks that are currently scheduled to run (we'll wait for them to
38 // finish next). 40 // finish next).
(...skipping 28 matching lines...) Expand all
67 // Unlock all of the locked images (note that this vector would only be 69 // Unlock all of the locked images (note that this vector would only be
68 // populated if we actually need to unref the image. 70 // populated if we actually need to unref the image.
69 for (auto image_pair : requested_locked_images_) 71 for (auto image_pair : requested_locked_images_)
70 cache_->UnrefImage(image_pair.second); 72 cache_->UnrefImage(image_pair.second);
71 requested_locked_images_.clear(); 73 requested_locked_images_.clear();
72 74
73 // Now, complete the tasks that already ran but haven't completed. These would 75 // Now, complete the tasks that already ran but haven't completed. These would
74 // be posted in the run loop, but since we invalidated the weak ptrs, we need 76 // be posted in the run loop, but since we invalidated the weak ptrs, we need
75 // to run everything manually. 77 // to run everything manually.
76 for (auto& request_to_complete : requests_needing_completion_) { 78 for (auto& request_to_complete : requests_needing_completion_) {
77 ImageDecodeRequestId id = request_to_complete.first;
78 ImageDecodeRequest& request = request_to_complete.second; 79 ImageDecodeRequest& request = request_to_complete.second;
79 80
80 // The task (if one exists) would have run already, we just need to make 81 // The task (if one exists) would have run already, we just need to make
81 // sure it was completed. Multiple requests for the same image use the same 82 // sure it was completed. Multiple requests for the same image use the same
82 // task so it could have already been completed. 83 // task so it could have already been completed.
83 if (request.task && !request.task->HasCompleted()) 84 if (request.task && !request.task->HasCompleted())
84 request.task->DidComplete(); 85 request.task->DidComplete();
85 86
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
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
90 // nullptr.
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);
95 if (request.need_unref) 87 if (request.need_unref)
96 cache_->UnrefImage(request.draw_image); 88 cache_->UnrefImage(request.draw_image);
89
90 // Orphan the request so that we can still run it when a new cache is set.
91 request.task = nullptr;
92 request.need_unref = false;
93 orphaned_decode_requests_.push_back(std::move(request));
97 } 94 }
98 requests_needing_completion_.clear(); 95 requests_needing_completion_.clear();
99 96
100 // Finally, complete all of the tasks that never started running. This is 97 // Finally, complete all of the tasks that never started running. This is
101 // similar to the |requests_needing_completion_|, but happens at a different 98 // similar to the |requests_needing_completion_|, but happens at a different
102 // stage in the pipeline. 99 // stage in the pipeline.
103 for (auto& request_pair : image_decode_queue_) { 100 for (auto& request_pair : image_decode_queue_) {
104 ImageDecodeRequestId id = request_pair.first;
105 ImageDecodeRequest& request = request_pair.second; 101 ImageDecodeRequest& request = request_pair.second;
106 102
107 if (request.task) { 103 if (request.task) {
108 // This task may have run via a different request, so only cancel it if 104 // This task may have run via a different request, so only cancel it if
109 // it's "new". That is, the same task could have been referenced by 105 // it's "new". That is, the same task could have been referenced by
110 // several different image deque requests for the same image. 106 // several different image deque requests for the same image.
111 if (request.task->state().IsNew()) 107 if (request.task->state().IsNew())
112 request.task->state().DidCancel(); 108 request.task->state().DidCancel();
113 109
114 if (!request.task->HasCompleted()) 110 if (!request.task->HasCompleted())
115 request.task->DidComplete(); 111 request.task->DidComplete();
116 } 112 }
117 // Run the callback and unref the image.
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);
121 cache_->UnrefImage(request.draw_image); 113 cache_->UnrefImage(request.draw_image);
114
115 // Orphan the request so that we can still run it when a new cache is set.
116 request.task = nullptr;
117 request.need_unref = false;
118 orphaned_decode_requests_.push_back(std::move(request));
122 } 119 }
123 image_decode_queue_.clear(); 120 image_decode_queue_.clear();
124 } 121 }
125 122
126 void ImageController::SetImageDecodeCache(ImageDecodeCache* cache) { 123 void ImageController::SetImageDecodeCache(ImageDecodeCache* cache) {
127 DCHECK(!cache_ || !cache); 124 DCHECK(!cache_ || !cache);
128 125
129 if (!cache) { 126 if (!cache) {
130 SetPredecodeImages(std::vector<DrawImage>(), 127 SetPredecodeImages(std::vector<DrawImage>(),
131 ImageDecodeCache::TracingInfo()); 128 ImageDecodeCache::TracingInfo());
132 StopWorkerTasks(); 129 StopWorkerTasks();
133 } 130 }
134 131
135 cache_ = cache; 132 cache_ = cache;
133
134 if (cache_)
135 GenerateTasksForOrphanedRequests();
136 } 136 }
137 137
138 void ImageController::GetTasksForImagesAndRef( 138 void ImageController::GetTasksForImagesAndRef(
139 std::vector<DrawImage>* images, 139 std::vector<DrawImage>* images,
140 std::vector<scoped_refptr<TileTask>>* tasks, 140 std::vector<scoped_refptr<TileTask>>* tasks,
141 const ImageDecodeCache::TracingInfo& tracing_info) { 141 const ImageDecodeCache::TracingInfo& tracing_info) {
142 DCHECK(cache_); 142 DCHECK(cache_);
143 for (auto it = images->begin(); it != images->end();) { 143 for (auto it = images->begin(); it != images->end();) {
144 scoped_refptr<TileTask> task; 144 scoped_refptr<TileTask> task;
145 bool need_to_unref_when_finished = 145 bool need_to_unref_when_finished =
(...skipping 168 matching lines...) Expand 10 before | Expand all | Expand 10 after
314 // Post another task to run. 314 // Post another task to run.
315 worker_task_runner_->PostTask( 315 worker_task_runner_->PostTask(
316 FROM_HERE, 316 FROM_HERE,
317 base::Bind(&ImageController::ProcessNextImageDecodeOnWorkerThread, 317 base::Bind(&ImageController::ProcessNextImageDecodeOnWorkerThread,
318 base::Unretained(this))); 318 base::Unretained(this)));
319 319
320 // Finally run the requested callback. 320 // Finally run the requested callback.
321 callback.Run(id, result); 321 callback.Run(id, result);
322 } 322 }
323 323
324 void ImageController::GenerateTasksForOrphanedRequests() {
325 base::AutoLock hold(lock_);
326 DCHECK_EQ(0u, image_decode_queue_.size());
327 DCHECK_EQ(0u, requests_needing_completion_.size());
328 DCHECK(cache_);
329
330 for (auto& request : orphaned_decode_requests_) {
331 DCHECK(!request.task);
332 DCHECK(!request.need_unref);
333 if (request.draw_image.image()->isLazyGenerated()) {
334 // Get the task for this decode.
335 request.need_unref = cache_->GetOutOfRasterDecodeTaskForImageAndRef(
336 request.draw_image, &request.task);
337 }
338 image_decode_queue_[request.id] = std::move(request);
339 }
340
341 orphaned_decode_requests_.clear();
342 if (!image_decode_queue_.empty()) {
343 // Post a worker task.
344 worker_task_runner_->PostTask(
345 FROM_HERE,
346 base::Bind(&ImageController::ProcessNextImageDecodeOnWorkerThread,
347 base::Unretained(this)));
348 }
349 }
350
324 ImageController::ImageDecodeRequest::ImageDecodeRequest() = default; 351 ImageController::ImageDecodeRequest::ImageDecodeRequest() = default;
325 ImageController::ImageDecodeRequest::ImageDecodeRequest( 352 ImageController::ImageDecodeRequest::ImageDecodeRequest(
326 ImageDecodeRequestId id, 353 ImageDecodeRequestId id,
327 const DrawImage& draw_image, 354 const DrawImage& draw_image,
328 const ImageDecodedCallback& callback, 355 const ImageDecodedCallback& callback,
329 scoped_refptr<TileTask> task, 356 scoped_refptr<TileTask> task,
330 bool need_unref) 357 bool need_unref)
331 : id(id), 358 : id(id),
332 draw_image(draw_image), 359 draw_image(draw_image),
333 callback(callback), 360 callback(callback),
334 task(std::move(task)), 361 task(std::move(task)),
335 need_unref(need_unref) {} 362 need_unref(need_unref) {}
336 ImageController::ImageDecodeRequest::ImageDecodeRequest( 363 ImageController::ImageDecodeRequest::ImageDecodeRequest(
337 ImageDecodeRequest&& other) = default; 364 ImageDecodeRequest&& other) = default;
338 ImageController::ImageDecodeRequest::ImageDecodeRequest( 365 ImageController::ImageDecodeRequest::ImageDecodeRequest(
339 const ImageDecodeRequest& other) = default; 366 const ImageDecodeRequest& other) = default;
340 ImageController::ImageDecodeRequest::~ImageDecodeRequest() = default; 367 ImageController::ImageDecodeRequest::~ImageDecodeRequest() = default;
341 368
342 ImageController::ImageDecodeRequest& ImageController::ImageDecodeRequest:: 369 ImageController::ImageDecodeRequest& ImageController::ImageDecodeRequest::
343 operator=(ImageDecodeRequest&& other) = default; 370 operator=(ImageDecodeRequest&& other) = default;
344 ImageController::ImageDecodeRequest& ImageController::ImageDecodeRequest:: 371 ImageController::ImageDecodeRequest& ImageController::ImageDecodeRequest::
345 operator=(const ImageDecodeRequest& other) = default; 372 operator=(const ImageDecodeRequest& other) = default;
346 373
347 } // namespace cc 374 } // 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