| 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 |