pixel_buffer_raster_worker_pool.cc revision c5cede9ae108bb15f6b7a8aea21c7e1fefa2834c
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 <algorithm> 8 9#include "base/containers/stack_container.h" 10#include "base/debug/trace_event.h" 11#include "cc/debug/traced_value.h" 12#include "cc/resources/resource.h" 13 14namespace cc { 15namespace { 16 17const int kCheckForCompletedRasterTasksDelayMs = 6; 18 19const size_t kMaxScheduledRasterTasks = 48; 20 21typedef base::StackVector<internal::WorkerPoolTask*, kMaxScheduledRasterTasks> 22 WorkerPoolTaskVector; 23 24} // namespace 25 26// static 27scoped_ptr<PixelBufferRasterWorkerPool> PixelBufferRasterWorkerPool::Create( 28 base::SequencedTaskRunner* task_runner, 29 ResourceProvider* resource_provider, 30 size_t max_transfer_buffer_usage_bytes) { 31 return make_scoped_ptr( 32 new PixelBufferRasterWorkerPool(task_runner, 33 GetTaskGraphRunner(), 34 resource_provider, 35 max_transfer_buffer_usage_bytes)); 36} 37 38PixelBufferRasterWorkerPool::PixelBufferRasterWorkerPool( 39 base::SequencedTaskRunner* task_runner, 40 internal::TaskGraphRunner* task_graph_runner, 41 ResourceProvider* resource_provider, 42 size_t max_transfer_buffer_usage_bytes) 43 : task_runner_(task_runner), 44 task_graph_runner_(task_graph_runner), 45 namespace_token_(task_graph_runner->GetNamespaceToken()), 46 resource_provider_(resource_provider), 47 shutdown_(false), 48 scheduled_raster_task_count_(0u), 49 raster_tasks_required_for_activation_count_(0u), 50 bytes_pending_upload_(0u), 51 max_bytes_pending_upload_(max_transfer_buffer_usage_bytes), 52 has_performed_uploads_since_last_flush_(false), 53 check_for_completed_raster_tasks_pending_(false), 54 should_notify_client_if_no_tasks_are_pending_(false), 55 should_notify_client_if_no_tasks_required_for_activation_are_pending_( 56 false), 57 raster_finished_task_pending_(false), 58 raster_required_for_activation_finished_task_pending_(false), 59 raster_finished_weak_ptr_factory_(this), 60 weak_ptr_factory_(this) {} 61 62PixelBufferRasterWorkerPool::~PixelBufferRasterWorkerPool() { 63 DCHECK(!check_for_completed_raster_tasks_pending_); 64 DCHECK_EQ(0u, raster_task_states_.size()); 65 DCHECK_EQ(0u, raster_tasks_with_pending_upload_.size()); 66 DCHECK_EQ(0u, completed_raster_tasks_.size()); 67 DCHECK_EQ(0u, completed_image_decode_tasks_.size()); 68 DCHECK_EQ(0u, raster_tasks_required_for_activation_count_); 69} 70 71void PixelBufferRasterWorkerPool::SetClient(RasterWorkerPoolClient* client) { 72 client_ = client; 73} 74 75void PixelBufferRasterWorkerPool::Shutdown() { 76 TRACE_EVENT0("cc", "PixelBufferRasterWorkerPool::Shutdown"); 77 78 shutdown_ = true; 79 80 internal::TaskGraph empty; 81 task_graph_runner_->ScheduleTasks(namespace_token_, &empty); 82 task_graph_runner_->WaitForTasksToFinishRunning(namespace_token_); 83 84 CheckForCompletedWorkerPoolTasks(); 85 CheckForCompletedUploads(); 86 87 check_for_completed_raster_tasks_pending_ = false; 88 89 for (RasterTaskState::Vector::iterator it = raster_task_states_.begin(); 90 it != raster_task_states_.end(); 91 ++it) { 92 RasterTaskState& state = *it; 93 94 // All unscheduled tasks need to be canceled. 95 if (state.type == RasterTaskState::UNSCHEDULED) { 96 completed_raster_tasks_.push_back(state.task); 97 state.type = RasterTaskState::COMPLETED; 98 } 99 } 100 DCHECK_EQ(completed_raster_tasks_.size(), raster_task_states_.size()); 101} 102 103void PixelBufferRasterWorkerPool::ScheduleTasks(RasterTaskQueue* queue) { 104 TRACE_EVENT0("cc", "PixelBufferRasterWorkerPool::ScheduleTasks"); 105 106 DCHECK_EQ(queue->required_for_activation_count, 107 static_cast<size_t>( 108 std::count_if(queue->items.begin(), 109 queue->items.end(), 110 RasterTaskQueue::Item::IsRequiredForActivation))); 111 112 if (!should_notify_client_if_no_tasks_are_pending_) 113 TRACE_EVENT_ASYNC_BEGIN0("cc", "ScheduledTasks", this); 114 115 should_notify_client_if_no_tasks_are_pending_ = true; 116 should_notify_client_if_no_tasks_required_for_activation_are_pending_ = true; 117 118 raster_tasks_required_for_activation_count_ = 0u; 119 120 // Update raster task state and remove items from old queue. 121 for (RasterTaskQueue::Item::Vector::const_iterator it = queue->items.begin(); 122 it != queue->items.end(); 123 ++it) { 124 const RasterTaskQueue::Item& item = *it; 125 internal::WorkerPoolTask* task = item.task; 126 127 // Remove any old items that are associated with this task. The result is 128 // that the old queue is left with all items not present in this queue, 129 // which we use below to determine what tasks need to be canceled. 130 RasterTaskQueue::Item::Vector::iterator old_it = 131 std::find_if(raster_tasks_.items.begin(), 132 raster_tasks_.items.end(), 133 RasterTaskQueue::Item::TaskComparator(task)); 134 if (old_it != raster_tasks_.items.end()) { 135 std::swap(*old_it, raster_tasks_.items.back()); 136 raster_tasks_.items.pop_back(); 137 } 138 139 RasterTaskState::Vector::iterator state_it = 140 std::find_if(raster_task_states_.begin(), 141 raster_task_states_.end(), 142 RasterTaskState::TaskComparator(task)); 143 if (state_it != raster_task_states_.end()) { 144 RasterTaskState& state = *state_it; 145 146 state.required_for_activation = item.required_for_activation; 147 // |raster_tasks_required_for_activation_count| accounts for all tasks 148 // that need to complete before we can send a "ready to activate" signal. 149 // Tasks that have already completed should not be part of this count. 150 if (state.type != RasterTaskState::COMPLETED) { 151 raster_tasks_required_for_activation_count_ += 152 item.required_for_activation; 153 } 154 continue; 155 } 156 157 DCHECK(!task->HasBeenScheduled()); 158 raster_task_states_.push_back( 159 RasterTaskState(task, item.required_for_activation)); 160 raster_tasks_required_for_activation_count_ += item.required_for_activation; 161 } 162 163 // Determine what tasks in old queue need to be canceled. 164 for (RasterTaskQueue::Item::Vector::const_iterator it = 165 raster_tasks_.items.begin(); 166 it != raster_tasks_.items.end(); 167 ++it) { 168 const RasterTaskQueue::Item& item = *it; 169 internal::WorkerPoolTask* task = item.task; 170 171 RasterTaskState::Vector::iterator state_it = 172 std::find_if(raster_task_states_.begin(), 173 raster_task_states_.end(), 174 RasterTaskState::TaskComparator(task)); 175 // We've already processed completion if we can't find a RasterTaskState for 176 // this task. 177 if (state_it == raster_task_states_.end()) 178 continue; 179 180 RasterTaskState& state = *state_it; 181 182 // Unscheduled task can be canceled. 183 if (state.type == RasterTaskState::UNSCHEDULED) { 184 DCHECK(!task->HasBeenScheduled()); 185 DCHECK(std::find(completed_raster_tasks_.begin(), 186 completed_raster_tasks_.end(), 187 task) == completed_raster_tasks_.end()); 188 completed_raster_tasks_.push_back(task); 189 state.type = RasterTaskState::COMPLETED; 190 } 191 192 // No longer required for activation. 193 state.required_for_activation = false; 194 } 195 196 raster_tasks_.Swap(queue); 197 198 // Check for completed tasks when ScheduleTasks() is called as 199 // priorities might have changed and this maximizes the number 200 // of top priority tasks that are scheduled. 201 CheckForCompletedWorkerPoolTasks(); 202 CheckForCompletedUploads(); 203 FlushUploads(); 204 205 // Schedule new tasks. 206 ScheduleMoreTasks(); 207 208 // Cancel any pending check for completed raster tasks and schedule 209 // another check. 210 check_for_completed_raster_tasks_time_ = base::TimeTicks(); 211 ScheduleCheckForCompletedRasterTasks(); 212 213 TRACE_EVENT_ASYNC_STEP_INTO1( 214 "cc", 215 "ScheduledTasks", 216 this, 217 StateName(), 218 "state", 219 TracedValue::FromValue(StateAsValue().release())); 220} 221 222unsigned PixelBufferRasterWorkerPool::GetResourceTarget() const { 223 return GL_TEXTURE_2D; 224} 225 226ResourceFormat PixelBufferRasterWorkerPool::GetResourceFormat() const { 227 return resource_provider_->memory_efficient_texture_format(); 228} 229 230void PixelBufferRasterWorkerPool::CheckForCompletedTasks() { 231 TRACE_EVENT0("cc", "PixelBufferRasterWorkerPool::CheckForCompletedTasks"); 232 233 CheckForCompletedWorkerPoolTasks(); 234 CheckForCompletedUploads(); 235 FlushUploads(); 236 237 for (internal::WorkerPoolTask::Vector::const_iterator it = 238 completed_image_decode_tasks_.begin(); 239 it != completed_image_decode_tasks_.end(); 240 ++it) { 241 internal::WorkerPoolTask* task = it->get(); 242 task->RunReplyOnOriginThread(); 243 } 244 completed_image_decode_tasks_.clear(); 245 246 for (internal::WorkerPoolTask::Vector::const_iterator it = 247 completed_raster_tasks_.begin(); 248 it != completed_raster_tasks_.end(); 249 ++it) { 250 internal::WorkerPoolTask* task = it->get(); 251 RasterTaskState::Vector::iterator state_it = 252 std::find_if(raster_task_states_.begin(), 253 raster_task_states_.end(), 254 RasterTaskState::TaskComparator(task)); 255 DCHECK(state_it != raster_task_states_.end()); 256 DCHECK_EQ(RasterTaskState::COMPLETED, state_it->type); 257 258 std::swap(*state_it, raster_task_states_.back()); 259 raster_task_states_.pop_back(); 260 261 task->RunReplyOnOriginThread(); 262 } 263 completed_raster_tasks_.clear(); 264} 265 266SkCanvas* PixelBufferRasterWorkerPool::AcquireCanvasForRaster( 267 internal::WorkerPoolTask* task, 268 const Resource* resource) { 269 RasterTaskState::Vector::iterator it = 270 std::find_if(raster_task_states_.begin(), 271 raster_task_states_.end(), 272 RasterTaskState::TaskComparator(task)); 273 DCHECK(it != raster_task_states_.end()); 274 DCHECK(!it->resource); 275 it->resource = resource; 276 resource_provider_->AcquirePixelRasterBuffer(resource->id()); 277 return resource_provider_->MapPixelRasterBuffer(resource->id()); 278} 279 280void PixelBufferRasterWorkerPool::ReleaseCanvasForRaster( 281 internal::WorkerPoolTask* task, 282 const Resource* resource) { 283 RasterTaskState::Vector::iterator it = 284 std::find_if(raster_task_states_.begin(), 285 raster_task_states_.end(), 286 RasterTaskState::TaskComparator(task)); 287 DCHECK(it != raster_task_states_.end()); 288 DCHECK(it->resource == resource); 289 resource_provider_->ReleasePixelRasterBuffer(resource->id()); 290} 291 292void PixelBufferRasterWorkerPool::OnRasterFinished() { 293 TRACE_EVENT0("cc", "PixelBufferRasterWorkerPool::OnRasterFinished"); 294 295 // |should_notify_client_if_no_tasks_are_pending_| can be set to false as 296 // a result of a scheduled CheckForCompletedRasterTasks() call. No need to 297 // perform another check in that case as we've already notified the client. 298 if (!should_notify_client_if_no_tasks_are_pending_) 299 return; 300 raster_finished_task_pending_ = false; 301 302 // Call CheckForCompletedRasterTasks() when we've finished running all 303 // raster tasks needed since last time ScheduleTasks() was called. 304 // This reduces latency between the time when all tasks have finished 305 // running and the time when the client is notified. 306 CheckForCompletedRasterTasks(); 307} 308 309void PixelBufferRasterWorkerPool::OnRasterRequiredForActivationFinished() { 310 TRACE_EVENT0( 311 "cc", 312 "PixelBufferRasterWorkerPool::OnRasterRequiredForActivationFinished"); 313 314 // Analogous to OnRasterTasksFinished(), there's no need to call 315 // CheckForCompletedRasterTasks() if the client has already been notified. 316 if (!should_notify_client_if_no_tasks_required_for_activation_are_pending_) 317 return; 318 raster_required_for_activation_finished_task_pending_ = false; 319 320 // This reduces latency between the time when all tasks required for 321 // activation have finished running and the time when the client is 322 // notified. 323 CheckForCompletedRasterTasks(); 324} 325 326void PixelBufferRasterWorkerPool::FlushUploads() { 327 if (!has_performed_uploads_since_last_flush_) 328 return; 329 330 resource_provider_->ShallowFlushIfSupported(); 331 has_performed_uploads_since_last_flush_ = false; 332} 333 334void PixelBufferRasterWorkerPool::CheckForCompletedUploads() { 335 internal::WorkerPoolTask::Vector tasks_with_completed_uploads; 336 337 // First check if any have completed. 338 while (!raster_tasks_with_pending_upload_.empty()) { 339 internal::WorkerPoolTask* task = 340 raster_tasks_with_pending_upload_.front().get(); 341 RasterTaskState::Vector::const_iterator it = 342 std::find_if(raster_task_states_.begin(), 343 raster_task_states_.end(), 344 RasterTaskState::TaskComparator(task)); 345 DCHECK(it != raster_task_states_.end()); 346 DCHECK_EQ(RasterTaskState::UPLOADING, it->type); 347 348 // Uploads complete in the order they are issued. 349 if (!resource_provider_->DidSetPixelsComplete(it->resource->id())) 350 break; 351 352 tasks_with_completed_uploads.push_back(task); 353 raster_tasks_with_pending_upload_.pop_front(); 354 } 355 356 DCHECK(client_); 357 bool should_force_some_uploads_to_complete = 358 shutdown_ || client_->ShouldForceTasksRequiredForActivationToComplete(); 359 360 if (should_force_some_uploads_to_complete) { 361 internal::WorkerPoolTask::Vector tasks_with_uploads_to_force; 362 TaskDeque::iterator it = raster_tasks_with_pending_upload_.begin(); 363 while (it != raster_tasks_with_pending_upload_.end()) { 364 internal::WorkerPoolTask* task = it->get(); 365 RasterTaskState::Vector::const_iterator state_it = 366 std::find_if(raster_task_states_.begin(), 367 raster_task_states_.end(), 368 RasterTaskState::TaskComparator(task)); 369 DCHECK(state_it != raster_task_states_.end()); 370 371 // Force all uploads required for activation to complete. 372 // During shutdown, force all pending uploads to complete. 373 if (shutdown_ || state_it->required_for_activation) { 374 tasks_with_uploads_to_force.push_back(task); 375 tasks_with_completed_uploads.push_back(task); 376 it = raster_tasks_with_pending_upload_.erase(it); 377 continue; 378 } 379 380 ++it; 381 } 382 383 // Force uploads in reverse order. Since forcing can cause a wait on 384 // all previous uploads, we would rather wait only once downstream. 385 for (internal::WorkerPoolTask::Vector::reverse_iterator it = 386 tasks_with_uploads_to_force.rbegin(); 387 it != tasks_with_uploads_to_force.rend(); 388 ++it) { 389 internal::WorkerPoolTask* task = it->get(); 390 RasterTaskState::Vector::const_iterator state_it = 391 std::find_if(raster_task_states_.begin(), 392 raster_task_states_.end(), 393 RasterTaskState::TaskComparator(task)); 394 DCHECK(state_it != raster_task_states_.end()); 395 DCHECK(state_it->resource); 396 397 resource_provider_->ForceSetPixelsToComplete(state_it->resource->id()); 398 has_performed_uploads_since_last_flush_ = true; 399 } 400 } 401 402 // Release shared memory and move tasks with completed uploads 403 // to |completed_raster_tasks_|. 404 for (internal::WorkerPoolTask::Vector::const_iterator it = 405 tasks_with_completed_uploads.begin(); 406 it != tasks_with_completed_uploads.end(); 407 ++it) { 408 internal::WorkerPoolTask* task = it->get(); 409 RasterTaskState::Vector::iterator state_it = 410 std::find_if(raster_task_states_.begin(), 411 raster_task_states_.end(), 412 RasterTaskState::TaskComparator(task)); 413 DCHECK(state_it != raster_task_states_.end()); 414 RasterTaskState& state = *state_it; 415 416 bytes_pending_upload_ -= state.resource->bytes(); 417 418 task->WillComplete(); 419 task->CompleteOnOriginThread(this); 420 task->DidComplete(); 421 422 DCHECK(std::find(completed_raster_tasks_.begin(), 423 completed_raster_tasks_.end(), 424 task) == completed_raster_tasks_.end()); 425 completed_raster_tasks_.push_back(task); 426 state.type = RasterTaskState::COMPLETED; 427 DCHECK_LE(static_cast<size_t>(state.required_for_activation), 428 raster_tasks_required_for_activation_count_); 429 raster_tasks_required_for_activation_count_ -= 430 state.required_for_activation; 431 } 432} 433 434void PixelBufferRasterWorkerPool::ScheduleCheckForCompletedRasterTasks() { 435 base::TimeDelta delay = 436 base::TimeDelta::FromMilliseconds(kCheckForCompletedRasterTasksDelayMs); 437 if (check_for_completed_raster_tasks_time_.is_null()) 438 check_for_completed_raster_tasks_time_ = base::TimeTicks::Now() + delay; 439 440 if (check_for_completed_raster_tasks_pending_) 441 return; 442 443 task_runner_->PostDelayedTask( 444 FROM_HERE, 445 base::Bind(&PixelBufferRasterWorkerPool::OnCheckForCompletedRasterTasks, 446 weak_ptr_factory_.GetWeakPtr()), 447 delay); 448 check_for_completed_raster_tasks_pending_ = true; 449} 450 451void PixelBufferRasterWorkerPool::OnCheckForCompletedRasterTasks() { 452 if (check_for_completed_raster_tasks_time_.is_null()) { 453 check_for_completed_raster_tasks_pending_ = false; 454 return; 455 } 456 457 base::TimeDelta delay = 458 check_for_completed_raster_tasks_time_ - base::TimeTicks::Now(); 459 460 // Post another delayed task if it is not yet time to check for completed 461 // raster tasks. 462 if (delay > base::TimeDelta()) { 463 task_runner_->PostDelayedTask( 464 FROM_HERE, 465 base::Bind(&PixelBufferRasterWorkerPool::OnCheckForCompletedRasterTasks, 466 weak_ptr_factory_.GetWeakPtr()), 467 delay); 468 return; 469 } 470 471 check_for_completed_raster_tasks_pending_ = false; 472 CheckForCompletedRasterTasks(); 473} 474 475void PixelBufferRasterWorkerPool::CheckForCompletedRasterTasks() { 476 TRACE_EVENT0("cc", 477 "PixelBufferRasterWorkerPool::CheckForCompletedRasterTasks"); 478 479 DCHECK(should_notify_client_if_no_tasks_are_pending_); 480 check_for_completed_raster_tasks_time_ = base::TimeTicks(); 481 482 CheckForCompletedWorkerPoolTasks(); 483 CheckForCompletedUploads(); 484 FlushUploads(); 485 486 // Determine what client notifications to generate. 487 bool will_notify_client_that_no_tasks_required_for_activation_are_pending = 488 (should_notify_client_if_no_tasks_required_for_activation_are_pending_ && 489 !raster_required_for_activation_finished_task_pending_ && 490 !HasPendingTasksRequiredForActivation()); 491 bool will_notify_client_that_no_tasks_are_pending = 492 (should_notify_client_if_no_tasks_are_pending_ && 493 !raster_required_for_activation_finished_task_pending_ && 494 !raster_finished_task_pending_ && !HasPendingTasks()); 495 496 // Adjust the need to generate notifications before scheduling more tasks. 497 should_notify_client_if_no_tasks_required_for_activation_are_pending_ &= 498 !will_notify_client_that_no_tasks_required_for_activation_are_pending; 499 should_notify_client_if_no_tasks_are_pending_ &= 500 !will_notify_client_that_no_tasks_are_pending; 501 502 scheduled_raster_task_count_ = 0; 503 if (PendingRasterTaskCount()) 504 ScheduleMoreTasks(); 505 506 TRACE_EVENT_ASYNC_STEP_INTO1( 507 "cc", 508 "ScheduledTasks", 509 this, 510 StateName(), 511 "state", 512 TracedValue::FromValue(StateAsValue().release())); 513 514 // Schedule another check for completed raster tasks while there are 515 // pending raster tasks or pending uploads. 516 if (HasPendingTasks()) 517 ScheduleCheckForCompletedRasterTasks(); 518 519 // Generate client notifications. 520 if (will_notify_client_that_no_tasks_required_for_activation_are_pending) { 521 DCHECK(!HasPendingTasksRequiredForActivation()); 522 client_->DidFinishRunningTasksRequiredForActivation(); 523 } 524 if (will_notify_client_that_no_tasks_are_pending) { 525 TRACE_EVENT_ASYNC_END0("cc", "ScheduledTasks", this); 526 DCHECK(!HasPendingTasksRequiredForActivation()); 527 client_->DidFinishRunningTasks(); 528 } 529} 530 531void PixelBufferRasterWorkerPool::ScheduleMoreTasks() { 532 TRACE_EVENT0("cc", "PixelBufferRasterWorkerPool::ScheduleMoreTasks"); 533 534 WorkerPoolTaskVector tasks; 535 WorkerPoolTaskVector tasks_required_for_activation; 536 537 unsigned priority = kRasterTaskPriorityBase; 538 539 graph_.Reset(); 540 541 size_t bytes_pending_upload = bytes_pending_upload_; 542 bool did_throttle_raster_tasks = false; 543 bool did_throttle_raster_tasks_required_for_activation = false; 544 545 for (RasterTaskQueue::Item::Vector::const_iterator it = 546 raster_tasks_.items.begin(); 547 it != raster_tasks_.items.end(); 548 ++it) { 549 const RasterTaskQueue::Item& item = *it; 550 internal::RasterWorkerPoolTask* task = item.task; 551 552 // |raster_task_states_| contains the state of all tasks that we have not 553 // yet run reply callbacks for. 554 RasterTaskState::Vector::iterator state_it = 555 std::find_if(raster_task_states_.begin(), 556 raster_task_states_.end(), 557 RasterTaskState::TaskComparator(task)); 558 if (state_it == raster_task_states_.end()) 559 continue; 560 561 RasterTaskState& state = *state_it; 562 563 // Skip task if completed. 564 if (state.type == RasterTaskState::COMPLETED) { 565 DCHECK(std::find(completed_raster_tasks_.begin(), 566 completed_raster_tasks_.end(), 567 task) != completed_raster_tasks_.end()); 568 continue; 569 } 570 571 // All raster tasks need to be throttled by bytes of pending uploads. 572 size_t new_bytes_pending_upload = bytes_pending_upload; 573 new_bytes_pending_upload += task->resource()->bytes(); 574 if (new_bytes_pending_upload > max_bytes_pending_upload_) { 575 did_throttle_raster_tasks = true; 576 if (item.required_for_activation) 577 did_throttle_raster_tasks_required_for_activation = true; 578 continue; 579 } 580 581 // If raster has finished, just update |bytes_pending_upload|. 582 if (state.type == RasterTaskState::UPLOADING) { 583 DCHECK(!task->HasCompleted()); 584 bytes_pending_upload = new_bytes_pending_upload; 585 continue; 586 } 587 588 // Throttle raster tasks based on kMaxScheduledRasterTasks. 589 if (tasks.container().size() >= kMaxScheduledRasterTasks) { 590 did_throttle_raster_tasks = true; 591 if (item.required_for_activation) 592 did_throttle_raster_tasks_required_for_activation = true; 593 continue; 594 } 595 596 // Update |bytes_pending_upload| now that task has cleared all 597 // throttling limits. 598 bytes_pending_upload = new_bytes_pending_upload; 599 600 DCHECK(state.type == RasterTaskState::UNSCHEDULED || 601 state.type == RasterTaskState::SCHEDULED); 602 state.type = RasterTaskState::SCHEDULED; 603 604 InsertNodesForRasterTask(&graph_, task, task->dependencies(), priority++); 605 606 tasks.container().push_back(task); 607 if (item.required_for_activation) 608 tasks_required_for_activation.container().push_back(task); 609 } 610 611 // Cancel existing OnRasterFinished callbacks. 612 raster_finished_weak_ptr_factory_.InvalidateWeakPtrs(); 613 614 scoped_refptr<internal::WorkerPoolTask> 615 new_raster_required_for_activation_finished_task; 616 617 size_t scheduled_raster_task_required_for_activation_count = 618 tasks_required_for_activation.container().size(); 619 DCHECK_LE(scheduled_raster_task_required_for_activation_count, 620 raster_tasks_required_for_activation_count_); 621 // Schedule OnRasterTasksRequiredForActivationFinished call only when 622 // notification is pending and throttling is not preventing all pending 623 // tasks required for activation from being scheduled. 624 if (!did_throttle_raster_tasks_required_for_activation && 625 should_notify_client_if_no_tasks_required_for_activation_are_pending_) { 626 new_raster_required_for_activation_finished_task = 627 CreateRasterRequiredForActivationFinishedTask( 628 raster_tasks_.required_for_activation_count, 629 task_runner_.get(), 630 base::Bind(&PixelBufferRasterWorkerPool:: 631 OnRasterRequiredForActivationFinished, 632 raster_finished_weak_ptr_factory_.GetWeakPtr())); 633 raster_required_for_activation_finished_task_pending_ = true; 634 InsertNodeForTask(&graph_, 635 new_raster_required_for_activation_finished_task.get(), 636 kRasterRequiredForActivationFinishedTaskPriority, 637 scheduled_raster_task_required_for_activation_count); 638 for (WorkerPoolTaskVector::ContainerType::const_iterator it = 639 tasks_required_for_activation.container().begin(); 640 it != tasks_required_for_activation.container().end(); 641 ++it) { 642 graph_.edges.push_back(internal::TaskGraph::Edge( 643 *it, new_raster_required_for_activation_finished_task.get())); 644 } 645 } 646 647 scoped_refptr<internal::WorkerPoolTask> new_raster_finished_task; 648 649 size_t scheduled_raster_task_count = tasks.container().size(); 650 DCHECK_LE(scheduled_raster_task_count, PendingRasterTaskCount()); 651 // Schedule OnRasterTasksFinished call only when notification is pending 652 // and throttling is not preventing all pending tasks from being scheduled. 653 if (!did_throttle_raster_tasks && 654 should_notify_client_if_no_tasks_are_pending_) { 655 new_raster_finished_task = CreateRasterFinishedTask( 656 task_runner_.get(), 657 base::Bind(&PixelBufferRasterWorkerPool::OnRasterFinished, 658 raster_finished_weak_ptr_factory_.GetWeakPtr())); 659 raster_finished_task_pending_ = true; 660 InsertNodeForTask(&graph_, 661 new_raster_finished_task.get(), 662 kRasterFinishedTaskPriority, 663 scheduled_raster_task_count); 664 for (WorkerPoolTaskVector::ContainerType::const_iterator it = 665 tasks.container().begin(); 666 it != tasks.container().end(); 667 ++it) { 668 graph_.edges.push_back( 669 internal::TaskGraph::Edge(*it, new_raster_finished_task.get())); 670 } 671 } 672 673 ScheduleTasksOnOriginThread(this, &graph_); 674 task_graph_runner_->ScheduleTasks(namespace_token_, &graph_); 675 676 scheduled_raster_task_count_ = scheduled_raster_task_count; 677 678 raster_finished_task_ = new_raster_finished_task; 679 raster_required_for_activation_finished_task_ = 680 new_raster_required_for_activation_finished_task; 681} 682 683unsigned PixelBufferRasterWorkerPool::PendingRasterTaskCount() const { 684 unsigned num_completed_raster_tasks = 685 raster_tasks_with_pending_upload_.size() + completed_raster_tasks_.size(); 686 DCHECK_GE(raster_task_states_.size(), num_completed_raster_tasks); 687 return raster_task_states_.size() - num_completed_raster_tasks; 688} 689 690bool PixelBufferRasterWorkerPool::HasPendingTasks() const { 691 return PendingRasterTaskCount() || !raster_tasks_with_pending_upload_.empty(); 692} 693 694bool PixelBufferRasterWorkerPool::HasPendingTasksRequiredForActivation() const { 695 return !!raster_tasks_required_for_activation_count_; 696} 697 698const char* PixelBufferRasterWorkerPool::StateName() const { 699 if (scheduled_raster_task_count_) 700 return "rasterizing"; 701 if (PendingRasterTaskCount()) 702 return "throttled"; 703 if (!raster_tasks_with_pending_upload_.empty()) 704 return "waiting_for_uploads"; 705 706 return "finishing"; 707} 708 709void PixelBufferRasterWorkerPool::CheckForCompletedWorkerPoolTasks() { 710 TRACE_EVENT0("cc", 711 "PixelBufferRasterWorkerPool::CheckForCompletedWorkerPoolTasks"); 712 713 task_graph_runner_->CollectCompletedTasks(namespace_token_, 714 &completed_tasks_); 715 for (internal::Task::Vector::const_iterator it = completed_tasks_.begin(); 716 it != completed_tasks_.end(); 717 ++it) { 718 internal::WorkerPoolTask* task = 719 static_cast<internal::WorkerPoolTask*>(it->get()); 720 721 RasterTaskState::Vector::iterator state_it = 722 std::find_if(raster_task_states_.begin(), 723 raster_task_states_.end(), 724 RasterTaskState::TaskComparator(task)); 725 if (state_it == raster_task_states_.end()) { 726 task->WillComplete(); 727 task->CompleteOnOriginThread(this); 728 task->DidComplete(); 729 730 completed_image_decode_tasks_.push_back(task); 731 continue; 732 } 733 734 RasterTaskState& state = *state_it; 735 DCHECK_EQ(RasterTaskState::SCHEDULED, state.type); 736 DCHECK(state.resource); 737 738 // Balanced with MapPixelRasterBuffer() call in AcquireCanvasForRaster(). 739 bool content_has_changed = 740 resource_provider_->UnmapPixelRasterBuffer(state.resource->id()); 741 742 // |content_has_changed| can be false as result of task being canceled or 743 // task implementation deciding not to modify bitmap (ie. analysis of raster 744 // commands detected content as a solid color). 745 if (!content_has_changed) { 746 task->WillComplete(); 747 task->CompleteOnOriginThread(this); 748 task->DidComplete(); 749 750 if (!task->HasFinishedRunning()) { 751 // When priorites change, a raster task can be canceled as a result of 752 // no longer being of high enough priority to fit in our throttled 753 // raster task budget. The task has not yet completed in this case. 754 RasterTaskQueue::Item::Vector::const_iterator item_it = 755 std::find_if(raster_tasks_.items.begin(), 756 raster_tasks_.items.end(), 757 RasterTaskQueue::Item::TaskComparator(task)); 758 if (item_it != raster_tasks_.items.end()) { 759 state.type = RasterTaskState::UNSCHEDULED; 760 state.resource = NULL; 761 continue; 762 } 763 } 764 765 DCHECK(std::find(completed_raster_tasks_.begin(), 766 completed_raster_tasks_.end(), 767 task) == completed_raster_tasks_.end()); 768 completed_raster_tasks_.push_back(task); 769 state.type = RasterTaskState::COMPLETED; 770 DCHECK_LE(static_cast<size_t>(state.required_for_activation), 771 raster_tasks_required_for_activation_count_); 772 raster_tasks_required_for_activation_count_ -= 773 state.required_for_activation; 774 continue; 775 } 776 777 DCHECK(task->HasFinishedRunning()); 778 779 resource_provider_->BeginSetPixels(state.resource->id()); 780 has_performed_uploads_since_last_flush_ = true; 781 782 bytes_pending_upload_ += state.resource->bytes(); 783 raster_tasks_with_pending_upload_.push_back(task); 784 state.type = RasterTaskState::UPLOADING; 785 } 786 completed_tasks_.clear(); 787} 788 789scoped_ptr<base::Value> PixelBufferRasterWorkerPool::StateAsValue() const { 790 scoped_ptr<base::DictionaryValue> state(new base::DictionaryValue); 791 792 state->SetInteger("completed_count", completed_raster_tasks_.size()); 793 state->SetInteger("pending_count", raster_task_states_.size()); 794 state->SetInteger("pending_upload_count", 795 raster_tasks_with_pending_upload_.size()); 796 state->SetInteger("pending_required_for_activation_count", 797 raster_tasks_required_for_activation_count_); 798 state->Set("throttle_state", ThrottleStateAsValue().release()); 799 return state.PassAs<base::Value>(); 800} 801 802scoped_ptr<base::Value> PixelBufferRasterWorkerPool::ThrottleStateAsValue() 803 const { 804 scoped_ptr<base::DictionaryValue> throttle_state(new base::DictionaryValue); 805 806 throttle_state->SetInteger("bytes_available_for_upload", 807 max_bytes_pending_upload_ - bytes_pending_upload_); 808 throttle_state->SetInteger("bytes_pending_upload", bytes_pending_upload_); 809 throttle_state->SetInteger("scheduled_raster_task_count", 810 scheduled_raster_task_count_); 811 return throttle_state.PassAs<base::Value>(); 812} 813 814} // namespace cc 815