OLD | NEW |
1 // Copyright 2013 The Chromium Authors. All rights reserved. | 1 // Copyright 2013 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/resources/pixel_buffer_raster_worker_pool.h" | 5 #include "cc/resources/pixel_buffer_raster_worker_pool.h" |
6 | 6 |
7 #include "base/debug/trace_event.h" | 7 #include "base/debug/trace_event.h" |
8 #include "cc/resources/resource.h" | 8 #include "cc/resources/resource.h" |
9 #include "third_party/skia/include/core/SkDevice.h" | 9 #include "third_party/skia/include/core/SkDevice.h" |
10 | 10 |
11 namespace cc { | 11 namespace cc { |
12 | 12 |
13 namespace { | 13 namespace { |
14 | 14 |
15 class PixelBufferWorkerPoolTaskImpl : public internal::WorkerPoolTask { | 15 class PixelBufferWorkerPoolTaskImpl : public internal::WorkerPoolTask { |
16 public: | 16 public: |
17 typedef base::Callback<void(bool was_canceled, bool needs_upload)> Reply; | 17 typedef base::Callback<void(bool was_canceled, bool needs_upload)> Reply; |
18 | 18 |
19 PixelBufferWorkerPoolTaskImpl(internal::RasterWorkerPoolTask* task, | 19 PixelBufferWorkerPoolTaskImpl(internal::RasterWorkerPoolTask* task, |
20 TaskVector* dependencies, | |
21 uint8_t* buffer, | 20 uint8_t* buffer, |
22 const Reply& reply) | 21 const Reply& reply) |
23 : internal::WorkerPoolTask(dependencies), | 22 : task_(task), |
24 task_(task), | |
25 buffer_(buffer), | 23 buffer_(buffer), |
26 reply_(reply), | 24 reply_(reply), |
27 needs_upload_(false) { | 25 needs_upload_(false) { |
28 } | 26 } |
29 | 27 |
30 // Overridden from internal::WorkerPoolTask: | 28 // Overridden from internal::WorkerPoolTask: |
31 virtual void RunOnThread(unsigned thread_index) OVERRIDE { | 29 virtual void RunOnThread(unsigned thread_index) OVERRIDE { |
32 // |buffer_| can be NULL in lost context situations. | 30 // |buffer_| can be NULL in lost context situations. |
33 if (!buffer_) { | 31 if (!buffer_) { |
34 // |needs_upload_| still needs to be true as task has not | 32 // |needs_upload_| still needs to be true as task has not |
(...skipping 48 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
83 kMaxBytesUploadedPerMs * kCheckForCompletedRasterTasksDelayMs; | 81 kMaxBytesUploadedPerMs * kCheckForCompletedRasterTasksDelayMs; |
84 | 82 |
85 } // namespace | 83 } // namespace |
86 | 84 |
87 PixelBufferRasterWorkerPool::PixelBufferRasterWorkerPool( | 85 PixelBufferRasterWorkerPool::PixelBufferRasterWorkerPool( |
88 ResourceProvider* resource_provider, | 86 ResourceProvider* resource_provider, |
89 size_t num_threads) : RasterWorkerPool(resource_provider, num_threads), | 87 size_t num_threads) : RasterWorkerPool(resource_provider, num_threads), |
90 shutdown_(false), | 88 shutdown_(false), |
91 bytes_pending_upload_(0), | 89 bytes_pending_upload_(0), |
92 has_performed_uploads_since_last_flush_(false), | 90 has_performed_uploads_since_last_flush_(false), |
93 check_for_completed_raster_tasks_pending_(false), | 91 check_for_completed_raster_tasks_pending_(false) { |
94 weak_ptr_factory_(this), | |
95 schedule_more_tasks_count_(0) { | |
96 } | 92 } |
97 | 93 |
98 PixelBufferRasterWorkerPool::~PixelBufferRasterWorkerPool() { | 94 PixelBufferRasterWorkerPool::~PixelBufferRasterWorkerPool() { |
99 DCHECK(shutdown_); | 95 DCHECK(shutdown_); |
100 DCHECK(!check_for_completed_raster_tasks_pending_); | 96 DCHECK(!check_for_completed_raster_tasks_pending_); |
101 DCHECK_EQ(0u, pixel_buffer_tasks_.size()); | 97 DCHECK_EQ(0u, pixel_buffer_tasks_.size()); |
102 DCHECK_EQ(0u, tasks_with_pending_upload_.size()); | 98 DCHECK_EQ(0u, tasks_with_pending_upload_.size()); |
103 DCHECK_EQ(0u, completed_tasks_.size()); | 99 DCHECK_EQ(0u, completed_tasks_.size()); |
104 } | 100 } |
105 | 101 |
106 void PixelBufferRasterWorkerPool::Shutdown() { | 102 void PixelBufferRasterWorkerPool::Shutdown() { |
107 shutdown_ = true; | 103 shutdown_ = true; |
108 RasterWorkerPool::Shutdown(); | 104 RasterWorkerPool::Shutdown(); |
109 CheckForCompletedRasterTasks(); | 105 CheckForCompletedRasterTasks(); |
110 for (TaskMap::iterator it = pixel_buffer_tasks_.begin(); | 106 for (TaskMap::iterator it = pixel_buffer_tasks_.begin(); |
111 it != pixel_buffer_tasks_.end(); ++it) { | 107 it != pixel_buffer_tasks_.end(); ++it) { |
112 internal::RasterWorkerPoolTask* task = it->first; | 108 internal::RasterWorkerPoolTask* task = it->first; |
113 internal::WorkerPoolTask* pixel_buffer_task = it->second.get(); | 109 internal::WorkerPoolTask* pixel_buffer_task = it->second.get(); |
114 | 110 |
115 // All inactive tasks needs to be canceled. | 111 // All inactive tasks needs to be canceled. |
116 if (!pixel_buffer_task && !task->HasFinishedRunning()) { | 112 if (!pixel_buffer_task && !task->HasFinishedRunning()) { |
117 task->DidRun(true); | 113 task->DidRun(true); |
118 completed_tasks_.push_back(task); | 114 completed_tasks_.push_back(task); |
119 } | 115 } |
120 } | 116 } |
121 // Cancel any pending OnRasterFinished callback. | |
122 weak_ptr_factory_.InvalidateWeakPtrs(); | |
123 } | 117 } |
124 | 118 |
125 void PixelBufferRasterWorkerPool::ScheduleTasks(RasterTask::Queue* queue) { | 119 void PixelBufferRasterWorkerPool::ScheduleTasks(RasterTask::Queue* queue) { |
126 TRACE_EVENT0("cc", "PixelBufferRasterWorkerPool::ScheduleTasks"); | 120 TRACE_EVENT0("cc", "PixelBufferRasterWorkerPool::ScheduleTasks"); |
127 | 121 |
128 RasterWorkerPool::SetRasterTasks(queue); | 122 RasterWorkerPool::SetRasterTasks(queue); |
129 | 123 |
130 // Build new pixel buffer task set. | 124 // Build new pixel buffer task set. |
131 TaskMap new_pixel_buffer_tasks; | 125 TaskMap new_pixel_buffer_tasks; |
132 for (RasterTask::Queue::TaskVector::const_iterator it = | 126 for (RasterTaskVector::const_iterator it = raster_tasks().begin(); |
133 raster_tasks().begin(); | |
134 it != raster_tasks().end(); ++it) { | 127 it != raster_tasks().end(); ++it) { |
135 internal::RasterWorkerPoolTask* task = it->get(); | 128 internal::RasterWorkerPoolTask* task = it->get(); |
136 DCHECK(new_pixel_buffer_tasks.find(task) == new_pixel_buffer_tasks.end()); | 129 DCHECK(new_pixel_buffer_tasks.find(task) == new_pixel_buffer_tasks.end()); |
137 DCHECK(!task->HasCompleted()); | 130 DCHECK(!task->HasCompleted()); |
138 | 131 |
139 // Use existing pixel buffer task if available. | 132 // Use existing pixel buffer task if available. |
140 TaskMap::iterator pixel_buffer_it = pixel_buffer_tasks_.find(task); | 133 TaskMap::iterator pixel_buffer_it = pixel_buffer_tasks_.find(task); |
141 if (pixel_buffer_it == pixel_buffer_tasks_.end()) { | 134 if (pixel_buffer_it == pixel_buffer_tasks_.end()) { |
142 new_pixel_buffer_tasks[task] = NULL; | 135 new_pixel_buffer_tasks[task] = NULL; |
143 continue; | 136 continue; |
(...skipping 45 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
189 | 182 |
190 pixel_buffer_tasks_.erase(task); | 183 pixel_buffer_tasks_.erase(task); |
191 | 184 |
192 task->DidComplete(); | 185 task->DidComplete(); |
193 task->DispatchCompletionCallback(); | 186 task->DispatchCompletionCallback(); |
194 | 187 |
195 completed_tasks_.pop_front(); | 188 completed_tasks_.pop_front(); |
196 } | 189 } |
197 } | 190 } |
198 | 191 |
| 192 void PixelBufferRasterWorkerPool::OnRasterTasksFinished() { |
| 193 // Call CheckForCompletedTasks() when we've finished running all raster |
| 194 // tasks needed since last time ScheduleMoreTasks() was called. This |
| 195 // reduces latency when processing only a small number of raster tasks. |
| 196 CheckForCompletedRasterTasks(); |
| 197 } |
| 198 |
199 void PixelBufferRasterWorkerPool::FlushUploads() { | 199 void PixelBufferRasterWorkerPool::FlushUploads() { |
200 if (!has_performed_uploads_since_last_flush_) | 200 if (!has_performed_uploads_since_last_flush_) |
201 return; | 201 return; |
202 | 202 |
203 resource_provider()->ShallowFlushIfSupported(); | 203 resource_provider()->ShallowFlushIfSupported(); |
204 has_performed_uploads_since_last_flush_ = false; | 204 has_performed_uploads_since_last_flush_ = false; |
205 } | 205 } |
206 | 206 |
207 void PixelBufferRasterWorkerPool::CheckForCompletedUploads() { | 207 void PixelBufferRasterWorkerPool::CheckForCompletedUploads() { |
208 TaskDeque tasks_with_completed_uploads; | 208 TaskDeque tasks_with_completed_uploads; |
(...skipping 90 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
299 if (!tasks_with_pending_upload_.empty()) | 299 if (!tasks_with_pending_upload_.empty()) |
300 ScheduleCheckForCompletedRasterTasks(); | 300 ScheduleCheckForCompletedRasterTasks(); |
301 } | 301 } |
302 | 302 |
303 void PixelBufferRasterWorkerPool::ScheduleMoreTasks() { | 303 void PixelBufferRasterWorkerPool::ScheduleMoreTasks() { |
304 TRACE_EVENT0("cc", "PixelBufferRasterWorkerPool::ScheduleMoreTasks"); | 304 TRACE_EVENT0("cc", "PixelBufferRasterWorkerPool::ScheduleMoreTasks"); |
305 | 305 |
306 size_t bytes_pending_upload = bytes_pending_upload_; | 306 size_t bytes_pending_upload = bytes_pending_upload_; |
307 size_t bytes_pending_raster = 0; | 307 size_t bytes_pending_raster = 0; |
308 | 308 |
309 internal::WorkerPoolTask::TaskVector tasks; | 309 RasterTaskGraph graph; |
310 | 310 for (RasterTaskVector::const_iterator it = raster_tasks().begin(); |
311 for (RasterTask::Queue::TaskVector::const_iterator it = | |
312 raster_tasks().begin(); | |
313 it != raster_tasks().end(); ++it) { | 311 it != raster_tasks().end(); ++it) { |
314 internal::RasterWorkerPoolTask* task = it->get(); | 312 internal::RasterWorkerPoolTask* task = it->get(); |
315 | 313 |
316 // |pixel_buffer_tasks_| contains all tasks that have not yet completed. | 314 // |pixel_buffer_tasks_| contains all tasks that have not yet completed. |
317 TaskMap::iterator pixel_buffer_it = pixel_buffer_tasks_.find(task); | 315 TaskMap::iterator pixel_buffer_it = pixel_buffer_tasks_.find(task); |
318 if (pixel_buffer_it == pixel_buffer_tasks_.end()) | 316 if (pixel_buffer_it == pixel_buffer_tasks_.end()) |
319 continue; | 317 continue; |
320 | 318 |
321 // HasFinishedRunning() will return true when set pixels has completed. | 319 // HasFinishedRunning() will return true when set pixels has completed. |
322 if (task->HasFinishedRunning()) { | 320 if (task->HasFinishedRunning()) { |
(...skipping 24 matching lines...) Expand all Loading... |
347 if (new_bytes_pending_raster > kMaxPendingRasterBytes) | 345 if (new_bytes_pending_raster > kMaxPendingRasterBytes) |
348 break; | 346 break; |
349 | 347 |
350 // Update both |bytes_pending_raster| and |bytes_pending_upload| | 348 // Update both |bytes_pending_raster| and |bytes_pending_upload| |
351 // now that task has cleared all throttling limits. | 349 // now that task has cleared all throttling limits. |
352 bytes_pending_raster = new_bytes_pending_raster; | 350 bytes_pending_raster = new_bytes_pending_raster; |
353 bytes_pending_upload = new_bytes_pending_upload; | 351 bytes_pending_upload = new_bytes_pending_upload; |
354 | 352 |
355 // Use existing pixel buffer task if available. | 353 // Use existing pixel buffer task if available. |
356 if (pixel_buffer_task) { | 354 if (pixel_buffer_task) { |
357 DCHECK(!pixel_buffer_task->HasCompleted()); | 355 graph.InsertRasterTask(pixel_buffer_task, task->dependencies()); |
358 tasks.push_back(pixel_buffer_task); | |
359 continue; | 356 continue; |
360 } | 357 } |
361 | 358 |
362 // Request a pixel buffer. This will reserve shared memory. | 359 // Request a pixel buffer. This will reserve shared memory. |
363 resource_provider()->AcquirePixelBuffer(task->resource()->id()); | 360 resource_provider()->AcquirePixelBuffer(task->resource()->id()); |
364 | 361 |
365 // MapPixelBuffer() returns NULL if context was lost at the time | 362 // MapPixelBuffer() returns NULL if context was lost at the time |
366 // AcquirePixelBuffer() was called. For simplicity we still post | 363 // AcquirePixelBuffer() was called. For simplicity we still post |
367 // a raster task that is essentially a noop in these situations. | 364 // a raster task that is essentially a noop in these situations. |
368 uint8* buffer = resource_provider()->MapPixelBuffer( | 365 uint8* buffer = resource_provider()->MapPixelBuffer( |
369 task->resource()->id()); | 366 task->resource()->id()); |
370 | 367 |
371 // TODO(reveman): Avoid having to make a copy of dependencies. | |
372 internal::WorkerPoolTask::TaskVector dependencies = task->dependencies(); | |
373 scoped_refptr<internal::WorkerPoolTask> new_pixel_buffer_task( | 368 scoped_refptr<internal::WorkerPoolTask> new_pixel_buffer_task( |
374 new PixelBufferWorkerPoolTaskImpl( | 369 new PixelBufferWorkerPoolTaskImpl( |
375 task, | 370 task, |
376 &dependencies, | |
377 buffer, | 371 buffer, |
378 base::Bind(&PixelBufferRasterWorkerPool::OnRasterTaskCompleted, | 372 base::Bind(&PixelBufferRasterWorkerPool::OnRasterTaskCompleted, |
379 base::Unretained(this), | 373 base::Unretained(this), |
380 make_scoped_refptr(task)))); | 374 make_scoped_refptr(task)))); |
381 | |
382 pixel_buffer_tasks_[task] = new_pixel_buffer_task; | 375 pixel_buffer_tasks_[task] = new_pixel_buffer_task; |
383 tasks.push_back(new_pixel_buffer_task); | 376 graph.InsertRasterTask(new_pixel_buffer_task.get(), task->dependencies()); |
384 } | 377 } |
385 | 378 |
386 ++schedule_more_tasks_count_; | 379 SetRasterTaskGraph(&graph); |
387 | |
388 // We need to make sure not to schedule a check for completed raster | |
389 // tasks when |tasks| is empty as that would cause us to never stop | |
390 // checking. | |
391 if (tasks.empty()) { | |
392 ScheduleRasterTasks(RootTask()); | |
393 return; | |
394 } | |
395 | |
396 RootTask root( | |
397 base::Bind(&PixelBufferRasterWorkerPool::RunRasterFinishedTask, | |
398 base::MessageLoopProxy::current(), | |
399 base::Bind(&PixelBufferRasterWorkerPool::OnRasterFinished, | |
400 weak_ptr_factory_.GetWeakPtr(), | |
401 schedule_more_tasks_count_)), | |
402 &tasks); | |
403 ScheduleRasterTasks(root); | |
404 | 380 |
405 // At least one task that could need an upload is now pending, schedule | 381 // At least one task that could need an upload is now pending, schedule |
406 // a check for completed raster tasks to ensure this upload is dispatched | 382 // a check for completed raster tasks to ensure this upload is dispatched |
407 // without too much latency. | 383 // without too much latency. |
408 ScheduleCheckForCompletedRasterTasks(); | 384 if (bytes_pending_raster) |
| 385 ScheduleCheckForCompletedRasterTasks(); |
409 } | 386 } |
410 | 387 |
411 void PixelBufferRasterWorkerPool::OnRasterTaskCompleted( | 388 void PixelBufferRasterWorkerPool::OnRasterTaskCompleted( |
412 scoped_refptr<internal::RasterWorkerPoolTask> task, | 389 scoped_refptr<internal::RasterWorkerPoolTask> task, |
413 bool was_canceled, | 390 bool was_canceled, |
414 bool needs_upload) { | 391 bool needs_upload) { |
415 TRACE_EVENT2("cc", "PixelBufferRasterWorkerPool::OnRasterTaskCompleted", | 392 TRACE_EVENT2("cc", "PixelBufferRasterWorkerPool::OnRasterTaskCompleted", |
416 "was_canceled", was_canceled, | 393 "was_canceled", was_canceled, |
417 "needs_upload", needs_upload); | 394 "needs_upload", needs_upload); |
418 | 395 |
(...skipping 12 matching lines...) Expand all Loading... |
431 return; | 408 return; |
432 } | 409 } |
433 | 410 |
434 resource_provider()->BeginSetPixels(task->resource()->id()); | 411 resource_provider()->BeginSetPixels(task->resource()->id()); |
435 has_performed_uploads_since_last_flush_ = true; | 412 has_performed_uploads_since_last_flush_ = true; |
436 | 413 |
437 bytes_pending_upload_ += task->resource()->bytes(); | 414 bytes_pending_upload_ += task->resource()->bytes(); |
438 tasks_with_pending_upload_.push_back(task); | 415 tasks_with_pending_upload_.push_back(task); |
439 } | 416 } |
440 | 417 |
441 void PixelBufferRasterWorkerPool::OnRasterFinished( | |
442 int64 schedule_more_tasks_count) { | |
443 TRACE_EVENT1("cc", | |
444 "PixelBufferRasterWorkerPool::OnRasterFinishedTasks", | |
445 "schedule_more_tasks_count", schedule_more_tasks_count); | |
446 DCHECK_GE(schedule_more_tasks_count_, schedule_more_tasks_count); | |
447 // Call CheckForCompletedTasks() when we've finished running all raster | |
448 // tasks needed since last time ScheduleMoreTasks() was called. This | |
449 // reduces latency when processing only a small number of raster tasks. | |
450 if (schedule_more_tasks_count_ == schedule_more_tasks_count) | |
451 CheckForCompletedRasterTasks(); | |
452 } | |
453 | |
454 // static | |
455 void PixelBufferRasterWorkerPool::RunRasterFinishedTask( | |
456 scoped_refptr<base::MessageLoopProxy> origin_loop, | |
457 const base::Closure& on_raster_finished_callback) { | |
458 TRACE_EVENT0("cc", "RasterWorkerPool::RunRasterFinishedTask"); | |
459 origin_loop->PostTask(FROM_HERE, on_raster_finished_callback); | |
460 } | |
461 | |
462 } // namespace cc | 418 } // namespace cc |
OLD | NEW |