pixel_buffer_raster_worker_pool.cc revision 58537e28ecd584eab876aee8be7156509866d23a
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 3// found in the LICENSE file. 4 5#include "cc/resources/pixel_buffer_raster_worker_pool.h" 6 7#include "base/containers/stack_container.h" 8#include "base/debug/trace_event.h" 9#include "base/values.h" 10#include "cc/debug/traced_value.h" 11#include "cc/resources/resource.h" 12#include "third_party/skia/include/core/SkBitmapDevice.h" 13 14#if defined(OS_ANDROID) 15#include "base/android/sys_utils.h" 16#endif 17 18namespace cc { 19 20namespace { 21 22class PixelBufferWorkerPoolTaskImpl : public internal::WorkerPoolTask { 23 public: 24 typedef base::Callback<void(bool was_canceled, bool needs_upload)> Reply; 25 26 PixelBufferWorkerPoolTaskImpl(internal::RasterWorkerPoolTask* task, 27 uint8_t* buffer, 28 const Reply& reply) 29 : task_(task), 30 buffer_(buffer), 31 reply_(reply), 32 needs_upload_(false) { 33 } 34 35 // Overridden from internal::WorkerPoolTask: 36 virtual void RunOnWorkerThread(unsigned thread_index) OVERRIDE { 37 // |buffer_| can be NULL in lost context situations. 38 if (!buffer_) { 39 // |needs_upload_| still needs to be true as task has not 40 // been canceled. 41 needs_upload_ = true; 42 return; 43 } 44 SkBitmap bitmap; 45 bitmap.setConfig(SkBitmap::kARGB_8888_Config, 46 task_->resource()->size().width(), 47 task_->resource()->size().height()); 48 bitmap.setPixels(buffer_); 49 SkBitmapDevice device(bitmap); 50 needs_upload_ = task_->RunOnWorkerThread(&device, thread_index); 51 } 52 virtual void CompleteOnOriginThread() OVERRIDE { 53 // |needs_upload_| must be be false if task didn't run. 54 DCHECK(HasFinishedRunning() || !needs_upload_); 55 reply_.Run(!HasFinishedRunning(), needs_upload_); 56 } 57 58 private: 59 virtual ~PixelBufferWorkerPoolTaskImpl() {} 60 61 scoped_refptr<internal::RasterWorkerPoolTask> task_; 62 uint8_t* buffer_; 63 const Reply reply_; 64 bool needs_upload_; 65 66 DISALLOW_COPY_AND_ASSIGN(PixelBufferWorkerPoolTaskImpl); 67}; 68 69const int kCheckForCompletedRasterTasksDelayMs = 6; 70 71const size_t kMaxScheduledRasterTasks = 48; 72 73typedef base::StackVector<internal::GraphNode*, 74 kMaxScheduledRasterTasks> NodeVector; 75 76void AddDependenciesToGraphNode( 77 internal::GraphNode* node, 78 const NodeVector::ContainerType& dependencies) { 79 for (NodeVector::ContainerType::const_iterator it = dependencies.begin(); 80 it != dependencies.end(); ++it) { 81 internal::GraphNode* dependency = *it; 82 83 node->add_dependency(); 84 dependency->add_dependent(node); 85 } 86} 87 88// Only used as std::find_if predicate for DCHECKs. 89bool WasCanceled(const internal::RasterWorkerPoolTask* task) { 90 return task->WasCanceled(); 91} 92 93} // namespace 94 95PixelBufferRasterWorkerPool::PixelBufferRasterWorkerPool( 96 ResourceProvider* resource_provider, 97 size_t num_threads, 98 size_t max_transfer_buffer_usage_bytes) 99 : RasterWorkerPool(resource_provider, num_threads), 100 shutdown_(false), 101 scheduled_raster_task_count_(0), 102 bytes_pending_upload_(0), 103 max_bytes_pending_upload_(max_transfer_buffer_usage_bytes), 104 has_performed_uploads_since_last_flush_(false), 105 check_for_completed_raster_tasks_pending_(false), 106 should_notify_client_if_no_tasks_are_pending_(false), 107 should_notify_client_if_no_tasks_required_for_activation_are_pending_( 108 false) { 109} 110 111PixelBufferRasterWorkerPool::~PixelBufferRasterWorkerPool() { 112 DCHECK(shutdown_); 113 DCHECK(!check_for_completed_raster_tasks_pending_); 114 DCHECK_EQ(0u, pixel_buffer_tasks_.size()); 115 DCHECK_EQ(0u, tasks_with_pending_upload_.size()); 116 DCHECK_EQ(0u, completed_tasks_.size()); 117} 118 119void PixelBufferRasterWorkerPool::Shutdown() { 120 shutdown_ = true; 121 RasterWorkerPool::Shutdown(); 122 RasterWorkerPool::CheckForCompletedTasks(); 123 CheckForCompletedUploads(); 124 check_for_completed_raster_tasks_callback_.Cancel(); 125 check_for_completed_raster_tasks_pending_ = false; 126 for (TaskMap::iterator it = pixel_buffer_tasks_.begin(); 127 it != pixel_buffer_tasks_.end(); ++it) { 128 internal::RasterWorkerPoolTask* task = it->first; 129 internal::WorkerPoolTask* pixel_buffer_task = it->second.get(); 130 131 // All inactive tasks needs to be canceled. 132 if (!pixel_buffer_task && !task->HasFinishedRunning()) { 133 task->DidRun(true); 134 completed_tasks_.push_back(task); 135 } 136 } 137 DCHECK_EQ(completed_tasks_.size(), pixel_buffer_tasks_.size()); 138} 139 140void PixelBufferRasterWorkerPool::ScheduleTasks(RasterTask::Queue* queue) { 141 TRACE_EVENT0("cc", "PixelBufferRasterWorkerPool::ScheduleTasks"); 142 143 RasterWorkerPool::SetRasterTasks(queue); 144 145 if (!should_notify_client_if_no_tasks_are_pending_) 146 TRACE_EVENT_ASYNC_BEGIN0("cc", "ScheduledTasks", this); 147 148 should_notify_client_if_no_tasks_are_pending_ = true; 149 should_notify_client_if_no_tasks_required_for_activation_are_pending_ = true; 150 151 // Build new pixel buffer task set. 152 TaskMap new_pixel_buffer_tasks; 153 for (RasterTaskVector::const_iterator it = raster_tasks().begin(); 154 it != raster_tasks().end(); ++it) { 155 internal::RasterWorkerPoolTask* task = it->get(); 156 DCHECK(new_pixel_buffer_tasks.find(task) == new_pixel_buffer_tasks.end()); 157 DCHECK(!task->HasCompleted()); 158 159 // Use existing pixel buffer task if available. 160 TaskMap::iterator pixel_buffer_it = pixel_buffer_tasks_.find(task); 161 if (pixel_buffer_it == pixel_buffer_tasks_.end()) { 162 new_pixel_buffer_tasks[task] = NULL; 163 continue; 164 } 165 166 new_pixel_buffer_tasks[task] = pixel_buffer_it->second; 167 pixel_buffer_tasks_.erase(task); 168 } 169 170 // Transfer remaining pixel buffer tasks to |new_pixel_buffer_tasks| 171 // and cancel all remaining inactive tasks. 172 for (TaskMap::iterator it = pixel_buffer_tasks_.begin(); 173 it != pixel_buffer_tasks_.end(); ++it) { 174 internal::RasterWorkerPoolTask* task = it->first; 175 internal::WorkerPoolTask* pixel_buffer_task = it->second.get(); 176 177 // Move task to |new_pixel_buffer_tasks| 178 new_pixel_buffer_tasks[task] = pixel_buffer_task; 179 180 // Inactive task can be canceled. 181 if (!pixel_buffer_task && !task->HasFinishedRunning()) { 182 task->DidRun(true); 183 DCHECK(std::find(completed_tasks_.begin(), 184 completed_tasks_.end(), 185 task) == completed_tasks_.end()); 186 completed_tasks_.push_back(task); 187 } 188 } 189 190 tasks_required_for_activation_.clear(); 191 for (TaskMap::iterator it = new_pixel_buffer_tasks.begin(); 192 it != new_pixel_buffer_tasks.end(); ++it) { 193 internal::RasterWorkerPoolTask* task = it->first; 194 if (IsRasterTaskRequiredForActivation(task)) 195 tasks_required_for_activation_.insert(task); 196 } 197 198 // |tasks_required_for_activation_| contains all tasks that need to 199 // complete before we can send a "ready to activate" signal. Tasks 200 // that have already completed should not be part of this set. 201 for (TaskDeque::const_iterator it = completed_tasks_.begin(); 202 it != completed_tasks_.end(); ++it) { 203 tasks_required_for_activation_.erase(*it); 204 } 205 206 pixel_buffer_tasks_.swap(new_pixel_buffer_tasks); 207 208 // Check for completed tasks when ScheduleTasks() is called as 209 // priorities might have changed and this maximizes the number 210 // of top priority tasks that are scheduled. 211 RasterWorkerPool::CheckForCompletedTasks(); 212 CheckForCompletedUploads(); 213 FlushUploads(); 214 215 // Schedule new tasks. 216 ScheduleMoreTasks(); 217 218 // Cancel any pending check for completed raster tasks and schedule 219 // another check. 220 check_for_completed_raster_tasks_callback_.Cancel(); 221 check_for_completed_raster_tasks_pending_ = false; 222 ScheduleCheckForCompletedRasterTasks(); 223 224 TRACE_EVENT_ASYNC_STEP1( 225 "cc", "ScheduledTasks", this, StateName(), 226 "state", TracedValue::FromValue(StateAsValue().release())); 227} 228 229GLenum PixelBufferRasterWorkerPool::GetResourceFormat() const { 230 return resource_provider()->best_texture_format(); 231} 232 233void PixelBufferRasterWorkerPool::CheckForCompletedTasks() { 234 TRACE_EVENT0("cc", "PixelBufferRasterWorkerPool::CheckForCompletedTasks"); 235 236 RasterWorkerPool::CheckForCompletedTasks(); 237 CheckForCompletedUploads(); 238 FlushUploads(); 239 240 TaskDeque completed_tasks; 241 completed_tasks_.swap(completed_tasks); 242 243 while (!completed_tasks.empty()) { 244 internal::RasterWorkerPoolTask* task = completed_tasks.front().get(); 245 DCHECK(pixel_buffer_tasks_.find(task) != pixel_buffer_tasks_.end()); 246 247 pixel_buffer_tasks_.erase(task); 248 249 task->WillComplete(); 250 task->CompleteOnOriginThread(); 251 task->DidComplete(); 252 253 completed_tasks.pop_front(); 254 } 255} 256 257void PixelBufferRasterWorkerPool::OnRasterTasksFinished() { 258 // |should_notify_client_if_no_tasks_are_pending_| can be set to false as 259 // a result of a scheduled CheckForCompletedRasterTasks() call. No need to 260 // perform another check in that case as we've already notified the client. 261 if (!should_notify_client_if_no_tasks_are_pending_) 262 return; 263 264 // Call CheckForCompletedRasterTasks() when we've finished running all 265 // raster tasks needed since last time ScheduleTasks() was called. 266 // This reduces latency between the time when all tasks have finished 267 // running and the time when the client is notified. 268 CheckForCompletedRasterTasks(); 269} 270 271void PixelBufferRasterWorkerPool::OnRasterTasksRequiredForActivationFinished() { 272 // Analogous to OnRasterTasksFinished(), there's no need to call 273 // CheckForCompletedRasterTasks() if the client has already been notified. 274 if (!should_notify_client_if_no_tasks_required_for_activation_are_pending_) 275 return; 276 277 // This reduces latency between the time when all tasks required for 278 // activation have finished running and the time when the client is 279 // notified. 280 CheckForCompletedRasterTasks(); 281} 282 283void PixelBufferRasterWorkerPool::FlushUploads() { 284 if (!has_performed_uploads_since_last_flush_) 285 return; 286 287 resource_provider()->ShallowFlushIfSupported(); 288 has_performed_uploads_since_last_flush_ = false; 289} 290 291void PixelBufferRasterWorkerPool::CheckForCompletedUploads() { 292 TaskDeque tasks_with_completed_uploads; 293 294 // First check if any have completed. 295 while (!tasks_with_pending_upload_.empty()) { 296 internal::RasterWorkerPoolTask* task = 297 tasks_with_pending_upload_.front().get(); 298 299 // Uploads complete in the order they are issued. 300 if (!resource_provider()->DidSetPixelsComplete(task->resource()->id())) 301 break; 302 303 tasks_with_completed_uploads.push_back(task); 304 tasks_with_pending_upload_.pop_front(); 305 } 306 307 DCHECK(client()); 308 bool should_force_some_uploads_to_complete = 309 shutdown_ || client()->ShouldForceTasksRequiredForActivationToComplete(); 310 311 if (should_force_some_uploads_to_complete) { 312 TaskDeque tasks_with_uploads_to_force; 313 TaskDeque::iterator it = tasks_with_pending_upload_.begin(); 314 while (it != tasks_with_pending_upload_.end()) { 315 internal::RasterWorkerPoolTask* task = it->get(); 316 DCHECK(pixel_buffer_tasks_.find(task) != pixel_buffer_tasks_.end()); 317 318 // Force all uploads required for activation to complete. 319 // During shutdown, force all pending uploads to complete. 320 if (shutdown_ || IsRasterTaskRequiredForActivation(task)) { 321 tasks_with_uploads_to_force.push_back(task); 322 tasks_with_completed_uploads.push_back(task); 323 it = tasks_with_pending_upload_.erase(it); 324 continue; 325 } 326 327 ++it; 328 } 329 330 // Force uploads in reverse order. Since forcing can cause a wait on 331 // all previous uploads, we would rather wait only once downstream. 332 for (TaskDeque::reverse_iterator it = tasks_with_uploads_to_force.rbegin(); 333 it != tasks_with_uploads_to_force.rend(); 334 ++it) { 335 resource_provider()->ForceSetPixelsToComplete((*it)->resource()->id()); 336 has_performed_uploads_since_last_flush_ = true; 337 } 338 } 339 340 // Release shared memory and move tasks with completed uploads 341 // to |completed_tasks_|. 342 while (!tasks_with_completed_uploads.empty()) { 343 internal::RasterWorkerPoolTask* task = 344 tasks_with_completed_uploads.front().get(); 345 346 // It's now safe to release the pixel buffer and the shared memory. 347 resource_provider()->ReleasePixelBuffer(task->resource()->id()); 348 349 bytes_pending_upload_ -= task->resource()->bytes(); 350 351 task->DidRun(false); 352 353 DCHECK(std::find(completed_tasks_.begin(), 354 completed_tasks_.end(), 355 task) == completed_tasks_.end()); 356 completed_tasks_.push_back(task); 357 358 tasks_required_for_activation_.erase(task); 359 360 tasks_with_completed_uploads.pop_front(); 361 } 362} 363 364void PixelBufferRasterWorkerPool::ScheduleCheckForCompletedRasterTasks() { 365 if (check_for_completed_raster_tasks_pending_) 366 return; 367 368 check_for_completed_raster_tasks_callback_.Reset( 369 base::Bind(&PixelBufferRasterWorkerPool::CheckForCompletedRasterTasks, 370 base::Unretained(this))); 371 base::MessageLoopProxy::current()->PostDelayedTask( 372 FROM_HERE, 373 check_for_completed_raster_tasks_callback_.callback(), 374 base::TimeDelta::FromMilliseconds(kCheckForCompletedRasterTasksDelayMs)); 375 check_for_completed_raster_tasks_pending_ = true; 376} 377 378void PixelBufferRasterWorkerPool::CheckForCompletedRasterTasks() { 379 TRACE_EVENT0( 380 "cc", "PixelBufferRasterWorkerPool::CheckForCompletedRasterTasks"); 381 382 DCHECK(should_notify_client_if_no_tasks_are_pending_); 383 384 check_for_completed_raster_tasks_callback_.Cancel(); 385 check_for_completed_raster_tasks_pending_ = false; 386 387 RasterWorkerPool::CheckForCompletedTasks(); 388 CheckForCompletedUploads(); 389 FlushUploads(); 390 391 // Determine what client notifications to generate. 392 bool will_notify_client_that_no_tasks_required_for_activation_are_pending = 393 (should_notify_client_if_no_tasks_required_for_activation_are_pending_ && 394 !HasPendingTasksRequiredForActivation()); 395 bool will_notify_client_that_no_tasks_are_pending = 396 (should_notify_client_if_no_tasks_are_pending_ && 397 !HasPendingTasks()); 398 399 // Adjust the need to generate notifications before scheduling more tasks. 400 should_notify_client_if_no_tasks_required_for_activation_are_pending_ &= 401 !will_notify_client_that_no_tasks_required_for_activation_are_pending; 402 should_notify_client_if_no_tasks_are_pending_ &= 403 !will_notify_client_that_no_tasks_are_pending; 404 405 scheduled_raster_task_count_ = 0; 406 if (PendingRasterTaskCount()) 407 ScheduleMoreTasks(); 408 409 TRACE_EVENT_ASYNC_STEP1( 410 "cc", "ScheduledTasks", this, StateName(), 411 "state", TracedValue::FromValue(StateAsValue().release())); 412 413 // Schedule another check for completed raster tasks while there are 414 // pending raster tasks or pending uploads. 415 if (HasPendingTasks()) 416 ScheduleCheckForCompletedRasterTasks(); 417 418 // Generate client notifications. 419 if (will_notify_client_that_no_tasks_required_for_activation_are_pending) { 420 DCHECK(std::find_if(raster_tasks_required_for_activation().begin(), 421 raster_tasks_required_for_activation().end(), 422 WasCanceled) == 423 raster_tasks_required_for_activation().end()); 424 client()->DidFinishRunningTasksRequiredForActivation(); 425 } 426 if (will_notify_client_that_no_tasks_are_pending) { 427 TRACE_EVENT_ASYNC_END0("cc", "ScheduledTasks", this); 428 DCHECK(!HasPendingTasksRequiredForActivation()); 429 client()->DidFinishRunningTasks(); 430 } 431} 432 433void PixelBufferRasterWorkerPool::ScheduleMoreTasks() { 434 TRACE_EVENT0("cc", "PixelBufferRasterWorkerPool::ScheduleMoreTasks"); 435 436 enum RasterTaskType { 437 PREPAINT_TYPE = 0, 438 REQUIRED_FOR_ACTIVATION_TYPE = 1, 439 NUM_TYPES = 2 440 }; 441 NodeVector tasks[NUM_TYPES]; 442 unsigned priority = 2u; // 0-1 reserved for RasterFinished tasks. 443 TaskGraph graph; 444 445 size_t bytes_pending_upload = bytes_pending_upload_; 446 447 for (RasterTaskVector::const_iterator it = raster_tasks().begin(); 448 it != raster_tasks().end(); ++it) { 449 internal::RasterWorkerPoolTask* task = it->get(); 450 451 // |pixel_buffer_tasks_| contains all tasks that have not yet completed. 452 TaskMap::iterator pixel_buffer_it = pixel_buffer_tasks_.find(task); 453 if (pixel_buffer_it == pixel_buffer_tasks_.end()) 454 continue; 455 456 // HasFinishedRunning() will return true when set pixels has completed. 457 if (task->HasFinishedRunning()) { 458 DCHECK(std::find(completed_tasks_.begin(), 459 completed_tasks_.end(), 460 task) != completed_tasks_.end()); 461 continue; 462 } 463 464 // All raster tasks need to be throttled by bytes of pending uploads. 465 size_t new_bytes_pending_upload = bytes_pending_upload; 466 new_bytes_pending_upload += task->resource()->bytes(); 467 if (new_bytes_pending_upload > max_bytes_pending_upload_) 468 break; 469 470 internal::WorkerPoolTask* pixel_buffer_task = pixel_buffer_it->second.get(); 471 472 // If raster has finished, just update |bytes_pending_upload|. 473 if (pixel_buffer_task && pixel_buffer_task->HasCompleted()) { 474 bytes_pending_upload = new_bytes_pending_upload; 475 continue; 476 } 477 478 // Throttle raster tasks based on kMaxScheduledRasterTasks. 479 size_t scheduled_raster_task_count = 480 tasks[PREPAINT_TYPE].container().size() + 481 tasks[REQUIRED_FOR_ACTIVATION_TYPE].container().size(); 482 if (scheduled_raster_task_count >= kMaxScheduledRasterTasks) 483 break; 484 485 // Update |bytes_pending_upload| now that task has cleared all 486 // throttling limits. 487 bytes_pending_upload = new_bytes_pending_upload; 488 489 RasterTaskType type = IsRasterTaskRequiredForActivation(task) ? 490 REQUIRED_FOR_ACTIVATION_TYPE : 491 PREPAINT_TYPE; 492 493 // Use existing pixel buffer task if available. 494 if (pixel_buffer_task) { 495 tasks[type].container().push_back( 496 CreateGraphNodeForRasterTask(pixel_buffer_task, 497 task->dependencies(), 498 priority++, 499 &graph)); 500 continue; 501 } 502 503 // Request a pixel buffer. This will reserve shared memory. 504 resource_provider()->AcquirePixelBuffer(task->resource()->id()); 505 506 // MapPixelBuffer() returns NULL if context was lost at the time 507 // AcquirePixelBuffer() was called. For simplicity we still post 508 // a raster task that is essentially a noop in these situations. 509 uint8* buffer = resource_provider()->MapPixelBuffer( 510 task->resource()->id()); 511 512 scoped_refptr<internal::WorkerPoolTask> new_pixel_buffer_task( 513 new PixelBufferWorkerPoolTaskImpl( 514 task, 515 buffer, 516 base::Bind(&PixelBufferRasterWorkerPool::OnRasterTaskCompleted, 517 base::Unretained(this), 518 make_scoped_refptr(task)))); 519 pixel_buffer_tasks_[task] = new_pixel_buffer_task; 520 tasks[type].container().push_back( 521 CreateGraphNodeForRasterTask(new_pixel_buffer_task.get(), 522 task->dependencies(), 523 priority++, 524 &graph)); 525 } 526 527 scoped_refptr<internal::WorkerPoolTask> 528 new_raster_required_for_activation_finished_task; 529 530 size_t scheduled_raster_task_required_for_activation_count = 531 tasks[REQUIRED_FOR_ACTIVATION_TYPE].container().size(); 532 DCHECK_LE(scheduled_raster_task_required_for_activation_count, 533 tasks_required_for_activation_.size()); 534 // Schedule OnRasterTasksRequiredForActivationFinished call only when 535 // notification is pending and throttling is not preventing all pending 536 // tasks required for activation from being scheduled. 537 if (scheduled_raster_task_required_for_activation_count == 538 tasks_required_for_activation_.size() && 539 should_notify_client_if_no_tasks_required_for_activation_are_pending_) { 540 new_raster_required_for_activation_finished_task = 541 CreateRasterRequiredForActivationFinishedTask(); 542 internal::GraphNode* raster_required_for_activation_finished_node = 543 CreateGraphNodeForTask( 544 new_raster_required_for_activation_finished_task.get(), 545 0u, // Priority 0 546 &graph); 547 AddDependenciesToGraphNode( 548 raster_required_for_activation_finished_node, 549 tasks[REQUIRED_FOR_ACTIVATION_TYPE].container()); 550 } 551 552 scoped_refptr<internal::WorkerPoolTask> new_raster_finished_task; 553 554 size_t scheduled_raster_task_count = 555 tasks[PREPAINT_TYPE].container().size() + 556 tasks[REQUIRED_FOR_ACTIVATION_TYPE].container().size(); 557 DCHECK_LE(scheduled_raster_task_count, PendingRasterTaskCount()); 558 // Schedule OnRasterTasksFinished call only when notification is pending 559 // and throttling is not preventing all pending tasks from being scheduled. 560 if (scheduled_raster_task_count == PendingRasterTaskCount() && 561 should_notify_client_if_no_tasks_are_pending_) { 562 new_raster_finished_task = CreateRasterFinishedTask(); 563 internal::GraphNode* raster_finished_node = 564 CreateGraphNodeForTask(new_raster_finished_task.get(), 565 1u, // Priority 1 566 &graph); 567 for (unsigned type = 0; type < NUM_TYPES; ++type) { 568 AddDependenciesToGraphNode( 569 raster_finished_node, 570 tasks[type].container()); 571 } 572 } 573 574 SetTaskGraph(&graph); 575 576 scheduled_raster_task_count_ = scheduled_raster_task_count; 577 578 set_raster_finished_task(new_raster_finished_task); 579 set_raster_required_for_activation_finished_task( 580 new_raster_required_for_activation_finished_task); 581} 582 583void PixelBufferRasterWorkerPool::OnRasterTaskCompleted( 584 scoped_refptr<internal::RasterWorkerPoolTask> task, 585 bool was_canceled, 586 bool needs_upload) { 587 TRACE_EVENT2(TRACE_DISABLED_BY_DEFAULT("cc"), 588 "PixelBufferRasterWorkerPool::OnRasterTaskCompleted", 589 "was_canceled", was_canceled, 590 "needs_upload", needs_upload); 591 592 DCHECK(pixel_buffer_tasks_.find(task.get()) != pixel_buffer_tasks_.end()); 593 594 // Balanced with MapPixelBuffer() call in ScheduleMoreTasks(). 595 resource_provider()->UnmapPixelBuffer(task->resource()->id()); 596 597 if (!needs_upload) { 598 resource_provider()->ReleasePixelBuffer(task->resource()->id()); 599 600 if (was_canceled) { 601 // When priorites change, a raster task can be canceled as a result of 602 // no longer being of high enough priority to fit in our throttled 603 // raster task budget. The task has not yet completed in this case. 604 RasterTaskVector::const_iterator it = std::find(raster_tasks().begin(), 605 raster_tasks().end(), 606 task); 607 if (it != raster_tasks().end()) { 608 pixel_buffer_tasks_[task.get()] = NULL; 609 return; 610 } 611 } 612 613 task->DidRun(was_canceled); 614 DCHECK(std::find(completed_tasks_.begin(), 615 completed_tasks_.end(), 616 task) == completed_tasks_.end()); 617 completed_tasks_.push_back(task); 618 tasks_required_for_activation_.erase(task); 619 return; 620 } 621 622 DCHECK(!was_canceled); 623 624 resource_provider()->BeginSetPixels(task->resource()->id()); 625 has_performed_uploads_since_last_flush_ = true; 626 627 bytes_pending_upload_ += task->resource()->bytes(); 628 tasks_with_pending_upload_.push_back(task); 629} 630 631unsigned PixelBufferRasterWorkerPool::PendingRasterTaskCount() const { 632 unsigned num_completed_raster_tasks = 633 tasks_with_pending_upload_.size() + completed_tasks_.size(); 634 DCHECK_GE(pixel_buffer_tasks_.size(), num_completed_raster_tasks); 635 return pixel_buffer_tasks_.size() - num_completed_raster_tasks; 636} 637 638bool PixelBufferRasterWorkerPool::HasPendingTasks() const { 639 return PendingRasterTaskCount() || !tasks_with_pending_upload_.empty(); 640} 641 642bool PixelBufferRasterWorkerPool::HasPendingTasksRequiredForActivation() const { 643 return !tasks_required_for_activation_.empty(); 644} 645 646const char* PixelBufferRasterWorkerPool::StateName() const { 647 if (scheduled_raster_task_count_) 648 return "rasterizing"; 649 if (PendingRasterTaskCount()) 650 return "throttled"; 651 if (!tasks_with_pending_upload_.empty()) 652 return "waiting_for_uploads"; 653 654 return "finishing"; 655} 656 657scoped_ptr<base::Value> PixelBufferRasterWorkerPool::StateAsValue() const { 658 scoped_ptr<base::DictionaryValue> state(new base::DictionaryValue); 659 660 state->SetInteger("completed_count", completed_tasks_.size()); 661 state->SetInteger("pending_count", pixel_buffer_tasks_.size()); 662 state->SetInteger("pending_upload_count", tasks_with_pending_upload_.size()); 663 state->SetInteger("required_for_activation_count", 664 tasks_required_for_activation_.size()); 665 state->Set("scheduled_state", ScheduledStateAsValue().release()); 666 state->Set("throttle_state", ThrottleStateAsValue().release()); 667 return state.PassAs<base::Value>(); 668} 669 670scoped_ptr<base::Value> PixelBufferRasterWorkerPool::ThrottleStateAsValue() 671 const { 672 scoped_ptr<base::DictionaryValue> throttle_state(new base::DictionaryValue); 673 674 throttle_state->SetInteger("bytes_available_for_upload", 675 max_bytes_pending_upload_ - bytes_pending_upload_); 676 throttle_state->SetInteger("bytes_pending_upload", bytes_pending_upload_); 677 throttle_state->SetInteger("scheduled_raster_task_count", 678 scheduled_raster_task_count_); 679 return throttle_state.PassAs<base::Value>(); 680} 681 682} // namespace cc 683