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.
5 #include "cc/raster/pixel_buffer_tile_task_worker_pool.h"
9 #include "base/containers/stack_container.h"
10 #include "base/strings/stringprintf.h"
11 #include "base/trace_event/trace_event.h"
12 #include "base/trace_event/trace_event_argument.h"
13 #include "cc/debug/traced_value.h"
14 #include "cc/raster/raster_buffer.h"
15 #include "cc/resources/platform_color.h"
16 #include "cc/resources/resource.h"
17 #include "gpu/command_buffer/client/gles2_interface.h"
22 class RasterBufferImpl
: public RasterBuffer
{
24 RasterBufferImpl(ResourceProvider
* resource_provider
,
25 const Resource
* resource
)
26 : resource_provider_(resource_provider
),
30 resource_provider_
->AcquirePixelBuffer(resource_
->id());
31 memory_
= resource_provider_
->MapPixelBuffer(resource_
->id(), &stride_
);
34 ~RasterBufferImpl() override
{
35 resource_provider_
->ReleasePixelBuffer(resource_
->id());
38 // Overridden from RasterBuffer:
39 void Playback(const RasterSource
* raster_source
,
40 const gfx::Rect
& raster_full_rect
,
41 const gfx::Rect
& raster_dirty_rect
,
42 uint64_t new_content_id
,
43 float scale
) override
{
47 // TileTaskWorkerPool::PlaybackToMemory only supports unsigned strides.
48 DCHECK_GE(stride_
, 0);
49 TileTaskWorkerPool::PlaybackToMemory(
50 memory_
, resource_
->format(), resource_
->size(),
51 static_cast<size_t>(stride_
), raster_source
, raster_full_rect
,
52 raster_full_rect
, scale
);
56 ResourceProvider
* resource_provider_
;
57 const Resource
* resource_
;
61 DISALLOW_COPY_AND_ASSIGN(RasterBufferImpl
);
64 const int kCheckForCompletedRasterTasksDelayMs
= 6;
66 const size_t kMaxScheduledRasterTasks
= 48;
68 typedef base::StackVector
<RasterTask
*, kMaxScheduledRasterTasks
>
71 TaskSetCollection
NonEmptyTaskSetsFromTaskCounts(const size_t* task_counts
) {
72 TaskSetCollection task_sets
;
73 for (TaskSet task_set
= 0; task_set
< kNumberOfTaskSets
; ++task_set
) {
74 if (task_counts
[task_set
])
75 task_sets
[task_set
] = true;
80 void AddTaskSetsToTaskCounts(size_t* task_counts
,
81 const TaskSetCollection
& task_sets
) {
82 for (TaskSet task_set
= 0; task_set
< kNumberOfTaskSets
; ++task_set
) {
83 if (task_sets
[task_set
])
84 task_counts
[task_set
]++;
88 void RemoveTaskSetsFromTaskCounts(size_t* task_counts
,
89 const TaskSetCollection
& task_sets
) {
90 for (TaskSet task_set
= 0; task_set
< kNumberOfTaskSets
; ++task_set
) {
91 if (task_sets
[task_set
])
92 task_counts
[task_set
]--;
98 PixelBufferTileTaskWorkerPool::RasterTaskState::RasterTaskState(
100 const TaskSetCollection
& task_sets
)
101 : type(UNSCHEDULED
), task(task
), task_sets(task_sets
) {
105 scoped_ptr
<TileTaskWorkerPool
> PixelBufferTileTaskWorkerPool::Create(
106 base::SequencedTaskRunner
* task_runner
,
107 TaskGraphRunner
* task_graph_runner
,
108 ContextProvider
* context_provider
,
109 ResourceProvider
* resource_provider
,
110 size_t max_transfer_buffer_usage_bytes
) {
111 return make_scoped_ptr
<TileTaskWorkerPool
>(new PixelBufferTileTaskWorkerPool(
112 task_runner
, task_graph_runner
, context_provider
, resource_provider
,
113 max_transfer_buffer_usage_bytes
));
116 PixelBufferTileTaskWorkerPool::PixelBufferTileTaskWorkerPool(
117 base::SequencedTaskRunner
* task_runner
,
118 TaskGraphRunner
* task_graph_runner
,
119 ContextProvider
* context_provider
,
120 ResourceProvider
* resource_provider
,
121 size_t max_transfer_buffer_usage_bytes
)
122 : task_runner_(task_runner
),
123 task_graph_runner_(task_graph_runner
),
124 namespace_token_(task_graph_runner
->GetNamespaceToken()),
125 context_provider_(context_provider
),
126 resource_provider_(resource_provider
),
128 scheduled_raster_task_count_(0u),
129 bytes_pending_upload_(0u),
130 max_bytes_pending_upload_(max_transfer_buffer_usage_bytes
),
131 has_performed_uploads_since_last_flush_(false),
132 check_for_completed_raster_task_notifier_(
135 &PixelBufferTileTaskWorkerPool::CheckForCompletedRasterTasks
,
136 base::Unretained(this)),
137 base::TimeDelta::FromMilliseconds(
138 kCheckForCompletedRasterTasksDelayMs
)),
139 task_set_finished_weak_ptr_factory_(this) {
140 DCHECK(context_provider_
);
141 std::fill(task_counts_
, task_counts_
+ kNumberOfTaskSets
, 0);
144 PixelBufferTileTaskWorkerPool::~PixelBufferTileTaskWorkerPool() {
145 DCHECK_EQ(0u, raster_task_states_
.size());
146 DCHECK_EQ(0u, raster_tasks_with_pending_upload_
.size());
147 DCHECK_EQ(0u, completed_raster_tasks_
.size());
148 DCHECK_EQ(0u, completed_image_decode_tasks_
.size());
149 DCHECK(NonEmptyTaskSetsFromTaskCounts(task_counts_
).none());
152 TileTaskRunner
* PixelBufferTileTaskWorkerPool::AsTileTaskRunner() {
156 void PixelBufferTileTaskWorkerPool::SetClient(TileTaskRunnerClient
* client
) {
160 void PixelBufferTileTaskWorkerPool::Shutdown() {
161 TRACE_EVENT0("cc", "PixelBufferTileTaskWorkerPool::Shutdown");
166 task_graph_runner_
->ScheduleTasks(namespace_token_
, &empty
);
167 task_graph_runner_
->WaitForTasksToFinishRunning(namespace_token_
);
169 CheckForCompletedRasterizerTasks();
170 CheckForCompletedUploads();
172 check_for_completed_raster_task_notifier_
.Shutdown();
174 for (RasterTaskState::Vector::iterator it
= raster_task_states_
.begin();
175 it
!= raster_task_states_
.end(); ++it
) {
176 RasterTaskState
& state
= *it
;
178 // All unscheduled tasks need to be canceled.
179 if (state
.type
== RasterTaskState::UNSCHEDULED
) {
180 completed_raster_tasks_
.push_back(state
.task
);
181 state
.type
= RasterTaskState::COMPLETED
;
184 DCHECK_EQ(completed_raster_tasks_
.size(), raster_task_states_
.size());
187 void PixelBufferTileTaskWorkerPool::ScheduleTasks(TileTaskQueue
* queue
) {
188 TRACE_EVENT0("cc", "PixelBufferTileTaskWorkerPool::ScheduleTasks");
190 if (should_notify_client_if_no_tasks_are_pending_
.none())
191 TRACE_EVENT_ASYNC_BEGIN0("cc", "ScheduledTasks", this);
193 should_notify_client_if_no_tasks_are_pending_
.set();
194 std::fill(task_counts_
, task_counts_
+ kNumberOfTaskSets
, 0);
196 // Update raster task state and remove items from old queue.
197 for (TileTaskQueue::Item::Vector::const_iterator it
= queue
->items
.begin();
198 it
!= queue
->items
.end(); ++it
) {
199 const TileTaskQueue::Item
& item
= *it
;
200 RasterTask
* task
= item
.task
;
202 // Remove any old items that are associated with this task. The result is
203 // that the old queue is left with all items not present in this queue,
204 // which we use below to determine what tasks need to be canceled.
205 TileTaskQueue::Item::Vector::iterator old_it
=
206 std::find_if(raster_tasks_
.items
.begin(), raster_tasks_
.items
.end(),
207 TileTaskQueue::Item::TaskComparator(task
));
208 if (old_it
!= raster_tasks_
.items
.end()) {
209 std::swap(*old_it
, raster_tasks_
.items
.back());
210 raster_tasks_
.items
.pop_back();
213 RasterTaskState::Vector::iterator state_it
=
214 std::find_if(raster_task_states_
.begin(), raster_task_states_
.end(),
215 RasterTaskState::TaskComparator(task
));
216 if (state_it
!= raster_task_states_
.end()) {
217 RasterTaskState
& state
= *state_it
;
219 state
.task_sets
= item
.task_sets
;
220 // |raster_tasks_required_for_activation_count| accounts for all tasks
221 // that need to complete before we can send a "ready to activate" signal.
222 // Tasks that have already completed should not be part of this count.
223 if (state
.type
!= RasterTaskState::COMPLETED
)
224 AddTaskSetsToTaskCounts(task_counts_
, item
.task_sets
);
229 DCHECK(!task
->HasBeenScheduled());
230 raster_task_states_
.push_back(RasterTaskState(task
, item
.task_sets
));
231 AddTaskSetsToTaskCounts(task_counts_
, item
.task_sets
);
234 // Determine what tasks in old queue need to be canceled.
235 for (TileTaskQueue::Item::Vector::const_iterator it
=
236 raster_tasks_
.items
.begin();
237 it
!= raster_tasks_
.items
.end(); ++it
) {
238 const TileTaskQueue::Item
& item
= *it
;
239 RasterTask
* task
= item
.task
;
241 RasterTaskState::Vector::iterator state_it
=
242 std::find_if(raster_task_states_
.begin(), raster_task_states_
.end(),
243 RasterTaskState::TaskComparator(task
));
244 // We've already processed completion if we can't find a RasterTaskState for
246 if (state_it
== raster_task_states_
.end())
249 RasterTaskState
& state
= *state_it
;
251 // Unscheduled task can be canceled.
252 if (state
.type
== RasterTaskState::UNSCHEDULED
) {
253 DCHECK(!task
->HasBeenScheduled());
254 DCHECK(std::find(completed_raster_tasks_
.begin(),
255 completed_raster_tasks_
.end(),
256 task
) == completed_raster_tasks_
.end());
257 completed_raster_tasks_
.push_back(task
);
258 state
.type
= RasterTaskState::COMPLETED
;
261 // No longer in any task set.
262 state
.task_sets
.reset();
265 raster_tasks_
.Swap(queue
);
267 // Check for completed tasks when ScheduleTasks() is called as
268 // priorities might have changed and this maximizes the number
269 // of top priority tasks that are scheduled.
270 CheckForCompletedRasterizerTasks();
271 CheckForCompletedUploads();
274 // Schedule new tasks.
277 // Reschedule check for completed raster tasks.
278 check_for_completed_raster_task_notifier_
.Schedule();
280 TRACE_EVENT_ASYNC_STEP_INTO1("cc", "ScheduledTasks", this, StateName(),
281 "state", StateAsValue());
284 void PixelBufferTileTaskWorkerPool::CheckForCompletedTasks() {
285 TRACE_EVENT0("cc", "PixelBufferTileTaskWorkerPool::CheckForCompletedTasks");
287 CheckForCompletedRasterizerTasks();
288 CheckForCompletedUploads();
291 for (TileTask::Vector::const_iterator it
=
292 completed_image_decode_tasks_
.begin();
293 it
!= completed_image_decode_tasks_
.end(); ++it
) {
294 TileTask
* task
= it
->get();
295 task
->RunReplyOnOriginThread();
297 completed_image_decode_tasks_
.clear();
299 for (RasterTask::Vector::const_iterator it
= completed_raster_tasks_
.begin();
300 it
!= completed_raster_tasks_
.end(); ++it
) {
301 RasterTask
* task
= it
->get();
302 RasterTaskState::Vector::iterator state_it
=
303 std::find_if(raster_task_states_
.begin(), raster_task_states_
.end(),
304 RasterTaskState::TaskComparator(task
));
305 DCHECK(state_it
!= raster_task_states_
.end());
306 DCHECK_EQ(RasterTaskState::COMPLETED
, state_it
->type
);
308 std::swap(*state_it
, raster_task_states_
.back());
309 raster_task_states_
.pop_back();
311 task
->RunReplyOnOriginThread();
313 completed_raster_tasks_
.clear();
316 ResourceFormat
PixelBufferTileTaskWorkerPool::GetResourceFormat() const {
317 return resource_provider_
->memory_efficient_texture_format();
320 bool PixelBufferTileTaskWorkerPool::GetResourceRequiresSwizzle() const {
321 return !PlatformColor::SameComponentOrder(GetResourceFormat());
324 scoped_ptr
<RasterBuffer
> PixelBufferTileTaskWorkerPool::AcquireBufferForRaster(
325 const Resource
* resource
,
326 uint64_t resource_content_id
,
327 uint64_t previous_content_id
) {
328 return make_scoped_ptr
<RasterBuffer
>(
329 new RasterBufferImpl(resource_provider_
, resource
));
332 void PixelBufferTileTaskWorkerPool::ReleaseBufferForRaster(
333 scoped_ptr
<RasterBuffer
> buffer
) {
334 // Nothing to do here. RasterBufferImpl destructor cleans up after itself.
337 void PixelBufferTileTaskWorkerPool::OnTaskSetFinished(TaskSet task_set
) {
338 TRACE_EVENT2("cc", "PixelBufferTileTaskWorkerPool::OnTaskSetFinished",
339 "task_set", task_set
,
340 "should_notify_client_if_no_tasks_are_pending",
341 should_notify_client_if_no_tasks_are_pending_
[task_set
]);
343 // There's no need to call CheckForCompletedRasterTasks() if the client has
344 // already been notified.
345 if (!should_notify_client_if_no_tasks_are_pending_
[task_set
])
347 task_set_finished_tasks_pending_
[task_set
] = false;
349 // This reduces latency between the time when all tasks required for
350 // activation have finished running and the time when the client is
352 CheckForCompletedRasterTasks();
355 void PixelBufferTileTaskWorkerPool::FlushUploads() {
356 if (!has_performed_uploads_since_last_flush_
)
359 context_provider_
->ContextGL()->ShallowFlushCHROMIUM();
360 has_performed_uploads_since_last_flush_
= false;
363 void PixelBufferTileTaskWorkerPool::CheckForCompletedUploads() {
364 RasterTask::Vector tasks_with_completed_uploads
;
366 // First check if any have completed.
367 while (!raster_tasks_with_pending_upload_
.empty()) {
368 RasterTask
* task
= raster_tasks_with_pending_upload_
.front().get();
369 DCHECK(std::find_if(raster_task_states_
.begin(), raster_task_states_
.end(),
370 RasterTaskState::TaskComparator(task
)) !=
371 raster_task_states_
.end());
373 RasterTaskState::UPLOADING
,
374 std::find_if(raster_task_states_
.begin(), raster_task_states_
.end(),
375 RasterTaskState::TaskComparator(task
))->type
);
377 // Uploads complete in the order they are issued.
378 if (!resource_provider_
->DidSetPixelsComplete(task
->resource()->id()))
381 tasks_with_completed_uploads
.push_back(task
);
382 raster_tasks_with_pending_upload_
.pop_front();
386 TaskSetCollection tasks_that_should_be_forced_to_complete
=
387 client_
->TasksThatShouldBeForcedToComplete();
388 bool should_force_some_uploads_to_complete
=
389 shutdown_
|| tasks_that_should_be_forced_to_complete
.any();
391 if (should_force_some_uploads_to_complete
) {
392 RasterTask::Vector tasks_with_uploads_to_force
;
393 RasterTaskDeque::iterator it
= raster_tasks_with_pending_upload_
.begin();
394 while (it
!= raster_tasks_with_pending_upload_
.end()) {
395 RasterTask
* task
= it
->get();
396 RasterTaskState::Vector::const_iterator state_it
=
397 std::find_if(raster_task_states_
.begin(), raster_task_states_
.end(),
398 RasterTaskState::TaskComparator(task
));
399 DCHECK(state_it
!= raster_task_states_
.end());
400 const RasterTaskState
& state
= *state_it
;
402 // Force all uploads to complete for which the client requests to do so.
403 // During shutdown, force all pending uploads to complete.
405 (state
.task_sets
& tasks_that_should_be_forced_to_complete
).any()) {
406 tasks_with_uploads_to_force
.push_back(task
);
407 tasks_with_completed_uploads
.push_back(task
);
408 it
= raster_tasks_with_pending_upload_
.erase(it
);
415 // Force uploads in reverse order. Since forcing can cause a wait on
416 // all previous uploads, we would rather wait only once downstream.
417 for (RasterTask::Vector::reverse_iterator it
=
418 tasks_with_uploads_to_force
.rbegin();
419 it
!= tasks_with_uploads_to_force
.rend(); ++it
) {
420 RasterTask
* task
= it
->get();
422 resource_provider_
->ForceSetPixelsToComplete(task
->resource()->id());
423 has_performed_uploads_since_last_flush_
= true;
427 // Release shared memory and move tasks with completed uploads
428 // to |completed_raster_tasks_|.
429 for (RasterTask::Vector::const_iterator it
=
430 tasks_with_completed_uploads
.begin();
431 it
!= tasks_with_completed_uploads
.end(); ++it
) {
432 RasterTask
* task
= it
->get();
433 RasterTaskState::Vector::iterator state_it
=
434 std::find_if(raster_task_states_
.begin(), raster_task_states_
.end(),
435 RasterTaskState::TaskComparator(task
));
436 DCHECK(state_it
!= raster_task_states_
.end());
437 RasterTaskState
& state
= *state_it
;
439 // We can use UncheckedMemorySizeBytes here, since these tasks come from
440 // tiles, the size of which is controlled by the compositor.
441 bytes_pending_upload_
-= Resource::UncheckedMemorySizeBytes(
442 task
->resource()->size(), task
->resource()->format());
444 task
->WillComplete();
445 task
->CompleteOnOriginThread(this);
448 DCHECK(std::find(completed_raster_tasks_
.begin(),
449 completed_raster_tasks_
.end(),
450 task
) == completed_raster_tasks_
.end());
451 completed_raster_tasks_
.push_back(task
);
452 state
.type
= RasterTaskState::COMPLETED
;
453 // Triggers if the current task belongs to a set that should be empty.
454 DCHECK((state
.task_sets
& ~NonEmptyTaskSetsFromTaskCounts(task_counts_
))
456 RemoveTaskSetsFromTaskCounts(task_counts_
, state
.task_sets
);
460 void PixelBufferTileTaskWorkerPool::CheckForCompletedRasterTasks() {
462 "PixelBufferTileTaskWorkerPool::CheckForCompletedRasterTasks");
464 // Since this function can be called directly, cancel any pending checks.
465 check_for_completed_raster_task_notifier_
.Cancel();
467 DCHECK(should_notify_client_if_no_tasks_are_pending_
.any());
469 CheckForCompletedRasterizerTasks();
470 CheckForCompletedUploads();
473 // Determine what client notifications to generate.
474 TaskSetCollection will_notify_client_that_no_tasks_are_pending
=
475 should_notify_client_if_no_tasks_are_pending_
&
476 ~task_set_finished_tasks_pending_
& ~PendingTasks();
478 // Adjust the need to generate notifications before scheduling more tasks.
479 should_notify_client_if_no_tasks_are_pending_
&=
480 ~will_notify_client_that_no_tasks_are_pending
;
482 scheduled_raster_task_count_
= 0;
483 if (PendingRasterTaskCount())
486 TRACE_EVENT_ASYNC_STEP_INTO1("cc", "ScheduledTasks", this, StateName(),
487 "state", StateAsValue());
489 // Schedule another check for completed raster tasks while there are
490 // pending raster tasks or pending uploads.
491 if (PendingTasks().any())
492 check_for_completed_raster_task_notifier_
.Schedule();
494 if (should_notify_client_if_no_tasks_are_pending_
.none())
495 TRACE_EVENT_ASYNC_END0("cc", "ScheduledTasks", this);
497 // Generate client notifications.
498 for (TaskSet task_set
= 0; task_set
< kNumberOfTaskSets
; ++task_set
) {
499 if (will_notify_client_that_no_tasks_are_pending
[task_set
]) {
500 DCHECK(!PendingTasks()[task_set
]);
501 client_
->DidFinishRunningTileTasks(task_set
);
506 void PixelBufferTileTaskWorkerPool::ScheduleMoreTasks() {
507 TRACE_EVENT0("cc", "PixelBufferTileTaskWorkerPool::ScheduleMoreTasks");
509 RasterTaskVector tasks
[kNumberOfTaskSets
];
511 size_t priority
= kTileTaskPriorityBase
;
515 size_t bytes_pending_upload
= bytes_pending_upload_
;
516 TaskSetCollection did_throttle_raster_tasks
;
517 size_t scheduled_raster_task_count
= 0;
519 for (TileTaskQueue::Item::Vector::const_iterator it
=
520 raster_tasks_
.items
.begin();
521 it
!= raster_tasks_
.items
.end(); ++it
) {
522 const TileTaskQueue::Item
& item
= *it
;
523 RasterTask
* task
= item
.task
;
524 DCHECK(item
.task_sets
.any());
526 // |raster_task_states_| contains the state of all tasks that we have not
527 // yet run reply callbacks for.
528 RasterTaskState::Vector::iterator state_it
=
529 std::find_if(raster_task_states_
.begin(), raster_task_states_
.end(),
530 RasterTaskState::TaskComparator(task
));
531 if (state_it
== raster_task_states_
.end())
534 RasterTaskState
& state
= *state_it
;
536 // Skip task if completed.
537 if (state
.type
== RasterTaskState::COMPLETED
) {
538 DCHECK(std::find(completed_raster_tasks_
.begin(),
539 completed_raster_tasks_
.end(),
540 task
) != completed_raster_tasks_
.end());
544 // All raster tasks need to be throttled by bytes of pending uploads,
545 // but if it's the only task allow it to complete no matter what its size,
546 // to prevent starvation of the task queue.
547 size_t new_bytes_pending_upload
= bytes_pending_upload
;
548 // We can use UncheckedMemorySizeBytes here, since these tasks come from
549 // tiles, the size of which is controlled by the compositor.
550 new_bytes_pending_upload
+= Resource::UncheckedMemorySizeBytes(
551 task
->resource()->size(), task
->resource()->format());
552 if (new_bytes_pending_upload
> max_bytes_pending_upload_
&&
553 bytes_pending_upload
) {
554 did_throttle_raster_tasks
|= item
.task_sets
;
558 // If raster has finished, just update |bytes_pending_upload|.
559 if (state
.type
== RasterTaskState::UPLOADING
) {
560 DCHECK(!task
->HasCompleted());
561 bytes_pending_upload
= new_bytes_pending_upload
;
565 // Throttle raster tasks based on kMaxScheduledRasterTasks.
566 if (scheduled_raster_task_count
>= kMaxScheduledRasterTasks
) {
567 did_throttle_raster_tasks
|= item
.task_sets
;
571 // Update |bytes_pending_upload| now that task has cleared all
572 // throttling limits.
573 bytes_pending_upload
= new_bytes_pending_upload
;
575 DCHECK(state
.type
== RasterTaskState::UNSCHEDULED
||
576 state
.type
== RasterTaskState::SCHEDULED
);
577 state
.type
= RasterTaskState::SCHEDULED
;
579 InsertNodesForRasterTask(&graph_
, task
, task
->dependencies(), priority
++);
581 ++scheduled_raster_task_count
;
582 for (TaskSet task_set
= 0; task_set
< kNumberOfTaskSets
; ++task_set
) {
583 if (item
.task_sets
[task_set
])
584 tasks
[task_set
].container().push_back(task
);
588 // Cancel existing OnTaskSetFinished callbacks.
589 task_set_finished_weak_ptr_factory_
.InvalidateWeakPtrs();
591 scoped_refptr
<TileTask
> new_task_set_finished_tasks
[kNumberOfTaskSets
];
592 size_t scheduled_task_counts
[kNumberOfTaskSets
] = {0};
594 for (TaskSet task_set
= 0; task_set
< kNumberOfTaskSets
; ++task_set
) {
595 scheduled_task_counts
[task_set
] = tasks
[task_set
].container().size();
596 DCHECK_LE(scheduled_task_counts
[task_set
], task_counts_
[task_set
]);
597 // Schedule OnTaskSetFinished call for task set only when notification is
598 // pending and throttling is not preventing all pending tasks in the set
599 // from being scheduled.
600 if (!did_throttle_raster_tasks
[task_set
] &&
601 should_notify_client_if_no_tasks_are_pending_
[task_set
]) {
602 new_task_set_finished_tasks
[task_set
] = CreateTaskSetFinishedTask(
604 base::Bind(&PixelBufferTileTaskWorkerPool::OnTaskSetFinished
,
605 task_set_finished_weak_ptr_factory_
.GetWeakPtr(),
607 task_set_finished_tasks_pending_
[task_set
] = true;
608 InsertNodeForTask(&graph_
, new_task_set_finished_tasks
[task_set
].get(),
609 kTaskSetFinishedTaskPriorityBase
+ task_set
,
610 scheduled_task_counts
[task_set
]);
611 for (RasterTaskVector::ContainerType::const_iterator it
=
612 tasks
[task_set
].container().begin();
613 it
!= tasks
[task_set
].container().end(); ++it
) {
614 graph_
.edges
.push_back(
615 TaskGraph::Edge(*it
, new_task_set_finished_tasks
[task_set
].get()));
620 DCHECK_LE(scheduled_raster_task_count
, PendingRasterTaskCount());
622 ScheduleTasksOnOriginThread(this, &graph_
);
623 task_graph_runner_
->ScheduleTasks(namespace_token_
, &graph_
);
625 scheduled_raster_task_count_
= scheduled_raster_task_count
;
627 std::copy(new_task_set_finished_tasks
,
628 new_task_set_finished_tasks
+ kNumberOfTaskSets
,
629 task_set_finished_tasks_
);
632 size_t PixelBufferTileTaskWorkerPool::PendingRasterTaskCount() const {
633 size_t num_completed_raster_tasks
=
634 raster_tasks_with_pending_upload_
.size() + completed_raster_tasks_
.size();
635 DCHECK_GE(raster_task_states_
.size(), num_completed_raster_tasks
);
636 return raster_task_states_
.size() - num_completed_raster_tasks
;
639 TaskSetCollection
PixelBufferTileTaskWorkerPool::PendingTasks() const {
640 return NonEmptyTaskSetsFromTaskCounts(task_counts_
);
643 const char* PixelBufferTileTaskWorkerPool::StateName() const {
644 if (scheduled_raster_task_count_
)
645 return "rasterizing";
646 if (PendingRasterTaskCount())
648 if (!raster_tasks_with_pending_upload_
.empty())
649 return "waiting_for_uploads";
654 void PixelBufferTileTaskWorkerPool::CheckForCompletedRasterizerTasks() {
656 "cc", "PixelBufferTileTaskWorkerPool::CheckForCompletedRasterizerTasks");
658 task_graph_runner_
->CollectCompletedTasks(namespace_token_
,
660 for (Task::Vector::const_iterator it
= completed_tasks_
.begin();
661 it
!= completed_tasks_
.end(); ++it
) {
662 TileTask
* task
= static_cast<TileTask
*>(it
->get());
664 RasterTask
* raster_task
= task
->AsRasterTask();
666 task
->WillComplete();
667 task
->CompleteOnOriginThread(this);
670 completed_image_decode_tasks_
.push_back(task
);
674 RasterTaskState::Vector::iterator state_it
=
675 std::find_if(raster_task_states_
.begin(), raster_task_states_
.end(),
676 RasterTaskState::TaskComparator(raster_task
));
677 DCHECK(state_it
!= raster_task_states_
.end());
679 RasterTaskState
& state
= *state_it
;
680 DCHECK_EQ(RasterTaskState::SCHEDULED
, state
.type
);
682 resource_provider_
->UnmapPixelBuffer(raster_task
->resource()->id());
684 if (!raster_task
->HasFinishedRunning()) {
685 // When priorites change, a raster task can be canceled as a result of
686 // no longer being of high enough priority to fit in our throttled
687 // raster task budget. The task has not yet completed in this case.
688 raster_task
->WillComplete();
689 raster_task
->CompleteOnOriginThread(this);
690 raster_task
->DidComplete();
692 TileTaskQueue::Item::Vector::const_iterator item_it
=
693 std::find_if(raster_tasks_
.items
.begin(), raster_tasks_
.items
.end(),
694 TileTaskQueue::Item::TaskComparator(raster_task
));
695 if (item_it
!= raster_tasks_
.items
.end()) {
696 state
.type
= RasterTaskState::UNSCHEDULED
;
700 DCHECK(std::find(completed_raster_tasks_
.begin(),
701 completed_raster_tasks_
.end(),
702 raster_task
) == completed_raster_tasks_
.end());
703 completed_raster_tasks_
.push_back(raster_task
);
704 state
.type
= RasterTaskState::COMPLETED
;
705 // Triggers if the current task belongs to a set that should be empty.
706 DCHECK((state
.task_sets
& ~NonEmptyTaskSetsFromTaskCounts(task_counts_
))
708 RemoveTaskSetsFromTaskCounts(task_counts_
, state
.task_sets
);
712 resource_provider_
->BeginSetPixels(raster_task
->resource()->id());
713 has_performed_uploads_since_last_flush_
= true;
715 // We can use UncheckedMemorySizeBytes here, since these tasks come from
716 // tiles, the size of which is controlled by the compositor.
717 bytes_pending_upload_
+= Resource::UncheckedMemorySizeBytes(
718 raster_task
->resource()->size(), raster_task
->resource()->format());
719 raster_tasks_with_pending_upload_
.push_back(raster_task
);
720 state
.type
= RasterTaskState::UPLOADING
;
722 completed_tasks_
.clear();
725 scoped_refptr
<base::trace_event::ConvertableToTraceFormat
>
726 PixelBufferTileTaskWorkerPool::StateAsValue() const {
727 scoped_refptr
<base::trace_event::TracedValue
> state
=
728 new base::trace_event::TracedValue();
729 state
->SetInteger("completed_count",
730 static_cast<int>(completed_raster_tasks_
.size()));
731 state
->BeginArray("pending_count");
732 for (TaskSet task_set
= 0; task_set
< kNumberOfTaskSets
; ++task_set
)
733 state
->AppendInteger(static_cast<int>(task_counts_
[task_set
]));
735 state
->SetInteger("pending_upload_count",
736 static_cast<int>(raster_tasks_with_pending_upload_
.size()));
737 state
->BeginDictionary("throttle_state");
738 ThrottleStateAsValueInto(state
.get());
739 state
->EndDictionary();
743 void PixelBufferTileTaskWorkerPool::ThrottleStateAsValueInto(
744 base::trace_event::TracedValue
* throttle_state
) const {
745 throttle_state
->SetInteger(
746 "bytes_available_for_upload",
747 static_cast<int>(max_bytes_pending_upload_
- bytes_pending_upload_
));
748 throttle_state
->SetInteger("bytes_pending_upload",
749 static_cast<int>(bytes_pending_upload_
));
750 throttle_state
->SetInteger("scheduled_raster_task_count",
751 static_cast<int>(scheduled_raster_task_count_
));