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
,
44 bool include_images
) override
{
48 // TileTaskWorkerPool::PlaybackToMemory only supports unsigned strides.
49 DCHECK_GE(stride_
, 0);
50 TileTaskWorkerPool::PlaybackToMemory(
51 memory_
, resource_
->format(), resource_
->size(),
52 static_cast<size_t>(stride_
), raster_source
, raster_full_rect
,
53 raster_full_rect
, scale
, include_images
);
57 ResourceProvider
* resource_provider_
;
58 const Resource
* resource_
;
62 DISALLOW_COPY_AND_ASSIGN(RasterBufferImpl
);
65 const int kCheckForCompletedRasterTasksDelayMs
= 6;
67 const size_t kMaxScheduledRasterTasks
= 48;
69 typedef base::StackVector
<RasterTask
*, kMaxScheduledRasterTasks
>
72 TaskSetCollection
NonEmptyTaskSetsFromTaskCounts(const size_t* task_counts
) {
73 TaskSetCollection task_sets
;
74 for (TaskSet task_set
= 0; task_set
< kNumberOfTaskSets
; ++task_set
) {
75 if (task_counts
[task_set
])
76 task_sets
[task_set
] = true;
81 void AddTaskSetsToTaskCounts(size_t* task_counts
,
82 const TaskSetCollection
& task_sets
) {
83 for (TaskSet task_set
= 0; task_set
< kNumberOfTaskSets
; ++task_set
) {
84 if (task_sets
[task_set
])
85 task_counts
[task_set
]++;
89 void RemoveTaskSetsFromTaskCounts(size_t* task_counts
,
90 const TaskSetCollection
& task_sets
) {
91 for (TaskSet task_set
= 0; task_set
< kNumberOfTaskSets
; ++task_set
) {
92 if (task_sets
[task_set
])
93 task_counts
[task_set
]--;
99 PixelBufferTileTaskWorkerPool::RasterTaskState::RasterTaskState(
101 const TaskSetCollection
& task_sets
)
102 : type(UNSCHEDULED
), task(task
), task_sets(task_sets
) {
106 scoped_ptr
<TileTaskWorkerPool
> PixelBufferTileTaskWorkerPool::Create(
107 base::SequencedTaskRunner
* task_runner
,
108 TaskGraphRunner
* task_graph_runner
,
109 ContextProvider
* context_provider
,
110 ResourceProvider
* resource_provider
,
111 size_t max_transfer_buffer_usage_bytes
) {
112 return make_scoped_ptr
<TileTaskWorkerPool
>(new PixelBufferTileTaskWorkerPool(
113 task_runner
, task_graph_runner
, context_provider
, resource_provider
,
114 max_transfer_buffer_usage_bytes
));
117 PixelBufferTileTaskWorkerPool::PixelBufferTileTaskWorkerPool(
118 base::SequencedTaskRunner
* task_runner
,
119 TaskGraphRunner
* task_graph_runner
,
120 ContextProvider
* context_provider
,
121 ResourceProvider
* resource_provider
,
122 size_t max_transfer_buffer_usage_bytes
)
123 : task_runner_(task_runner
),
124 task_graph_runner_(task_graph_runner
),
125 namespace_token_(task_graph_runner
->GetNamespaceToken()),
126 context_provider_(context_provider
),
127 resource_provider_(resource_provider
),
129 scheduled_raster_task_count_(0u),
130 bytes_pending_upload_(0u),
131 max_bytes_pending_upload_(max_transfer_buffer_usage_bytes
),
132 has_performed_uploads_since_last_flush_(false),
133 check_for_completed_raster_task_notifier_(
136 &PixelBufferTileTaskWorkerPool::CheckForCompletedRasterTasks
,
137 base::Unretained(this)),
138 base::TimeDelta::FromMilliseconds(
139 kCheckForCompletedRasterTasksDelayMs
)),
140 task_set_finished_weak_ptr_factory_(this) {
141 DCHECK(context_provider_
);
142 std::fill(task_counts_
, task_counts_
+ kNumberOfTaskSets
, 0);
145 PixelBufferTileTaskWorkerPool::~PixelBufferTileTaskWorkerPool() {
146 DCHECK_EQ(0u, raster_task_states_
.size());
147 DCHECK_EQ(0u, raster_tasks_with_pending_upload_
.size());
148 DCHECK_EQ(0u, completed_raster_tasks_
.size());
149 DCHECK_EQ(0u, completed_image_decode_tasks_
.size());
150 DCHECK(NonEmptyTaskSetsFromTaskCounts(task_counts_
).none());
153 TileTaskRunner
* PixelBufferTileTaskWorkerPool::AsTileTaskRunner() {
157 void PixelBufferTileTaskWorkerPool::SetClient(TileTaskRunnerClient
* client
) {
161 void PixelBufferTileTaskWorkerPool::Shutdown() {
162 TRACE_EVENT0("cc", "PixelBufferTileTaskWorkerPool::Shutdown");
167 task_graph_runner_
->ScheduleTasks(namespace_token_
, &empty
);
168 task_graph_runner_
->WaitForTasksToFinishRunning(namespace_token_
);
170 CheckForCompletedRasterizerTasks();
171 CheckForCompletedUploads();
173 check_for_completed_raster_task_notifier_
.Shutdown();
175 for (RasterTaskState::Vector::iterator it
= raster_task_states_
.begin();
176 it
!= raster_task_states_
.end(); ++it
) {
177 RasterTaskState
& state
= *it
;
179 // All unscheduled tasks need to be canceled.
180 if (state
.type
== RasterTaskState::UNSCHEDULED
) {
181 completed_raster_tasks_
.push_back(state
.task
);
182 state
.type
= RasterTaskState::COMPLETED
;
185 DCHECK_EQ(completed_raster_tasks_
.size(), raster_task_states_
.size());
188 void PixelBufferTileTaskWorkerPool::ScheduleTasks(TileTaskQueue
* queue
) {
189 TRACE_EVENT0("cc", "PixelBufferTileTaskWorkerPool::ScheduleTasks");
191 if (should_notify_client_if_no_tasks_are_pending_
.none())
192 TRACE_EVENT_ASYNC_BEGIN0("cc", "ScheduledTasks", this);
194 should_notify_client_if_no_tasks_are_pending_
.set();
195 std::fill(task_counts_
, task_counts_
+ kNumberOfTaskSets
, 0);
197 // Update raster task state and remove items from old queue.
198 for (TileTaskQueue::Item::Vector::const_iterator it
= queue
->items
.begin();
199 it
!= queue
->items
.end(); ++it
) {
200 const TileTaskQueue::Item
& item
= *it
;
201 RasterTask
* task
= item
.task
;
203 // Remove any old items that are associated with this task. The result is
204 // that the old queue is left with all items not present in this queue,
205 // which we use below to determine what tasks need to be canceled.
206 TileTaskQueue::Item::Vector::iterator old_it
=
207 std::find_if(raster_tasks_
.items
.begin(), raster_tasks_
.items
.end(),
208 TileTaskQueue::Item::TaskComparator(task
));
209 if (old_it
!= raster_tasks_
.items
.end()) {
210 std::swap(*old_it
, raster_tasks_
.items
.back());
211 raster_tasks_
.items
.pop_back();
214 RasterTaskState::Vector::iterator state_it
=
215 std::find_if(raster_task_states_
.begin(), raster_task_states_
.end(),
216 RasterTaskState::TaskComparator(task
));
217 if (state_it
!= raster_task_states_
.end()) {
218 RasterTaskState
& state
= *state_it
;
220 state
.task_sets
= item
.task_sets
;
221 // |raster_tasks_required_for_activation_count| accounts for all tasks
222 // that need to complete before we can send a "ready to activate" signal.
223 // Tasks that have already completed should not be part of this count.
224 if (state
.type
!= RasterTaskState::COMPLETED
)
225 AddTaskSetsToTaskCounts(task_counts_
, item
.task_sets
);
230 DCHECK(!task
->HasBeenScheduled());
231 raster_task_states_
.push_back(RasterTaskState(task
, item
.task_sets
));
232 AddTaskSetsToTaskCounts(task_counts_
, item
.task_sets
);
235 // Determine what tasks in old queue need to be canceled.
236 for (TileTaskQueue::Item::Vector::const_iterator it
=
237 raster_tasks_
.items
.begin();
238 it
!= raster_tasks_
.items
.end(); ++it
) {
239 const TileTaskQueue::Item
& item
= *it
;
240 RasterTask
* task
= item
.task
;
242 RasterTaskState::Vector::iterator state_it
=
243 std::find_if(raster_task_states_
.begin(), raster_task_states_
.end(),
244 RasterTaskState::TaskComparator(task
));
245 // We've already processed completion if we can't find a RasterTaskState for
247 if (state_it
== raster_task_states_
.end())
250 RasterTaskState
& state
= *state_it
;
252 // Unscheduled task can be canceled.
253 if (state
.type
== RasterTaskState::UNSCHEDULED
) {
254 DCHECK(!task
->HasBeenScheduled());
255 DCHECK(std::find(completed_raster_tasks_
.begin(),
256 completed_raster_tasks_
.end(),
257 task
) == completed_raster_tasks_
.end());
258 completed_raster_tasks_
.push_back(task
);
259 state
.type
= RasterTaskState::COMPLETED
;
262 // No longer in any task set.
263 state
.task_sets
.reset();
266 raster_tasks_
.Swap(queue
);
268 // Check for completed tasks when ScheduleTasks() is called as
269 // priorities might have changed and this maximizes the number
270 // of top priority tasks that are scheduled.
271 CheckForCompletedRasterizerTasks();
272 CheckForCompletedUploads();
275 // Schedule new tasks.
278 // Reschedule check for completed raster tasks.
279 check_for_completed_raster_task_notifier_
.Schedule();
281 TRACE_EVENT_ASYNC_STEP_INTO1("cc", "ScheduledTasks", this, StateName(),
282 "state", StateAsValue());
285 void PixelBufferTileTaskWorkerPool::CheckForCompletedTasks() {
286 TRACE_EVENT0("cc", "PixelBufferTileTaskWorkerPool::CheckForCompletedTasks");
288 CheckForCompletedRasterizerTasks();
289 CheckForCompletedUploads();
292 for (TileTask::Vector::const_iterator it
=
293 completed_image_decode_tasks_
.begin();
294 it
!= completed_image_decode_tasks_
.end(); ++it
) {
295 TileTask
* task
= it
->get();
296 task
->RunReplyOnOriginThread();
298 completed_image_decode_tasks_
.clear();
300 for (RasterTask::Vector::const_iterator it
= completed_raster_tasks_
.begin();
301 it
!= completed_raster_tasks_
.end(); ++it
) {
302 RasterTask
* task
= it
->get();
303 RasterTaskState::Vector::iterator state_it
=
304 std::find_if(raster_task_states_
.begin(), raster_task_states_
.end(),
305 RasterTaskState::TaskComparator(task
));
306 DCHECK(state_it
!= raster_task_states_
.end());
307 DCHECK_EQ(RasterTaskState::COMPLETED
, state_it
->type
);
309 std::swap(*state_it
, raster_task_states_
.back());
310 raster_task_states_
.pop_back();
312 task
->RunReplyOnOriginThread();
314 completed_raster_tasks_
.clear();
317 ResourceFormat
PixelBufferTileTaskWorkerPool::GetResourceFormat() const {
318 return resource_provider_
->memory_efficient_texture_format();
321 bool PixelBufferTileTaskWorkerPool::GetResourceRequiresSwizzle() const {
322 return !PlatformColor::SameComponentOrder(GetResourceFormat());
325 scoped_ptr
<RasterBuffer
> PixelBufferTileTaskWorkerPool::AcquireBufferForRaster(
326 const Resource
* resource
,
327 uint64_t resource_content_id
,
328 uint64_t previous_content_id
) {
329 return make_scoped_ptr
<RasterBuffer
>(
330 new RasterBufferImpl(resource_provider_
, resource
));
333 void PixelBufferTileTaskWorkerPool::ReleaseBufferForRaster(
334 scoped_ptr
<RasterBuffer
> buffer
) {
335 // Nothing to do here. RasterBufferImpl destructor cleans up after itself.
338 void PixelBufferTileTaskWorkerPool::OnTaskSetFinished(TaskSet task_set
) {
339 TRACE_EVENT2("cc", "PixelBufferTileTaskWorkerPool::OnTaskSetFinished",
340 "task_set", task_set
,
341 "should_notify_client_if_no_tasks_are_pending",
342 should_notify_client_if_no_tasks_are_pending_
[task_set
]);
344 // There's no need to call CheckForCompletedRasterTasks() if the client has
345 // already been notified.
346 if (!should_notify_client_if_no_tasks_are_pending_
[task_set
])
348 task_set_finished_tasks_pending_
[task_set
] = false;
350 // This reduces latency between the time when all tasks required for
351 // activation have finished running and the time when the client is
353 CheckForCompletedRasterTasks();
356 void PixelBufferTileTaskWorkerPool::FlushUploads() {
357 if (!has_performed_uploads_since_last_flush_
)
360 context_provider_
->ContextGL()->ShallowFlushCHROMIUM();
361 has_performed_uploads_since_last_flush_
= false;
364 void PixelBufferTileTaskWorkerPool::CheckForCompletedUploads() {
365 RasterTask::Vector tasks_with_completed_uploads
;
367 // First check if any have completed.
368 while (!raster_tasks_with_pending_upload_
.empty()) {
369 RasterTask
* task
= raster_tasks_with_pending_upload_
.front().get();
370 DCHECK(std::find_if(raster_task_states_
.begin(), raster_task_states_
.end(),
371 RasterTaskState::TaskComparator(task
)) !=
372 raster_task_states_
.end());
374 RasterTaskState::UPLOADING
,
375 std::find_if(raster_task_states_
.begin(), raster_task_states_
.end(),
376 RasterTaskState::TaskComparator(task
))->type
);
378 // Uploads complete in the order they are issued.
379 if (!resource_provider_
->DidSetPixelsComplete(task
->resource()->id()))
382 tasks_with_completed_uploads
.push_back(task
);
383 raster_tasks_with_pending_upload_
.pop_front();
387 TaskSetCollection tasks_that_should_be_forced_to_complete
=
388 client_
->TasksThatShouldBeForcedToComplete();
389 bool should_force_some_uploads_to_complete
=
390 shutdown_
|| tasks_that_should_be_forced_to_complete
.any();
392 if (should_force_some_uploads_to_complete
) {
393 RasterTask::Vector tasks_with_uploads_to_force
;
394 RasterTaskDeque::iterator it
= raster_tasks_with_pending_upload_
.begin();
395 while (it
!= raster_tasks_with_pending_upload_
.end()) {
396 RasterTask
* task
= it
->get();
397 RasterTaskState::Vector::const_iterator state_it
=
398 std::find_if(raster_task_states_
.begin(), raster_task_states_
.end(),
399 RasterTaskState::TaskComparator(task
));
400 DCHECK(state_it
!= raster_task_states_
.end());
401 const RasterTaskState
& state
= *state_it
;
403 // Force all uploads to complete for which the client requests to do so.
404 // During shutdown, force all pending uploads to complete.
406 (state
.task_sets
& tasks_that_should_be_forced_to_complete
).any()) {
407 tasks_with_uploads_to_force
.push_back(task
);
408 tasks_with_completed_uploads
.push_back(task
);
409 it
= raster_tasks_with_pending_upload_
.erase(it
);
416 // Force uploads in reverse order. Since forcing can cause a wait on
417 // all previous uploads, we would rather wait only once downstream.
418 for (RasterTask::Vector::reverse_iterator it
=
419 tasks_with_uploads_to_force
.rbegin();
420 it
!= tasks_with_uploads_to_force
.rend(); ++it
) {
421 RasterTask
* task
= it
->get();
423 resource_provider_
->ForceSetPixelsToComplete(task
->resource()->id());
424 has_performed_uploads_since_last_flush_
= true;
428 // Release shared memory and move tasks with completed uploads
429 // to |completed_raster_tasks_|.
430 for (RasterTask::Vector::const_iterator it
=
431 tasks_with_completed_uploads
.begin();
432 it
!= tasks_with_completed_uploads
.end(); ++it
) {
433 RasterTask
* task
= it
->get();
434 RasterTaskState::Vector::iterator state_it
=
435 std::find_if(raster_task_states_
.begin(), raster_task_states_
.end(),
436 RasterTaskState::TaskComparator(task
));
437 DCHECK(state_it
!= raster_task_states_
.end());
438 RasterTaskState
& state
= *state_it
;
440 // We can use UncheckedSizeInBytes here, since these tasks come from tiles,
441 // the size of which is controlled by the compositor.
442 bytes_pending_upload_
-= ResourceUtil::UncheckedSizeInBytes
<size_t>(
443 task
->resource()->size(), task
->resource()->format());
445 task
->WillComplete();
446 task
->CompleteOnOriginThread(this);
449 DCHECK(std::find(completed_raster_tasks_
.begin(),
450 completed_raster_tasks_
.end(),
451 task
) == completed_raster_tasks_
.end());
452 completed_raster_tasks_
.push_back(task
);
453 state
.type
= RasterTaskState::COMPLETED
;
454 // Triggers if the current task belongs to a set that should be empty.
455 DCHECK((state
.task_sets
& ~NonEmptyTaskSetsFromTaskCounts(task_counts_
))
457 RemoveTaskSetsFromTaskCounts(task_counts_
, state
.task_sets
);
461 void PixelBufferTileTaskWorkerPool::CheckForCompletedRasterTasks() {
463 "PixelBufferTileTaskWorkerPool::CheckForCompletedRasterTasks");
465 // Since this function can be called directly, cancel any pending checks.
466 check_for_completed_raster_task_notifier_
.Cancel();
468 DCHECK(should_notify_client_if_no_tasks_are_pending_
.any());
470 CheckForCompletedRasterizerTasks();
471 CheckForCompletedUploads();
474 // Determine what client notifications to generate.
475 TaskSetCollection will_notify_client_that_no_tasks_are_pending
=
476 should_notify_client_if_no_tasks_are_pending_
&
477 ~task_set_finished_tasks_pending_
& ~PendingTasks();
479 // Adjust the need to generate notifications before scheduling more tasks.
480 should_notify_client_if_no_tasks_are_pending_
&=
481 ~will_notify_client_that_no_tasks_are_pending
;
483 scheduled_raster_task_count_
= 0;
484 if (PendingRasterTaskCount())
487 TRACE_EVENT_ASYNC_STEP_INTO1("cc", "ScheduledTasks", this, StateName(),
488 "state", StateAsValue());
490 // Schedule another check for completed raster tasks while there are
491 // pending raster tasks or pending uploads.
492 if (PendingTasks().any())
493 check_for_completed_raster_task_notifier_
.Schedule();
495 if (should_notify_client_if_no_tasks_are_pending_
.none())
496 TRACE_EVENT_ASYNC_END0("cc", "ScheduledTasks", this);
498 // Generate client notifications.
499 for (TaskSet task_set
= 0; task_set
< kNumberOfTaskSets
; ++task_set
) {
500 if (will_notify_client_that_no_tasks_are_pending
[task_set
]) {
501 DCHECK(!PendingTasks()[task_set
]);
502 client_
->DidFinishRunningTileTasks(task_set
);
507 void PixelBufferTileTaskWorkerPool::ScheduleMoreTasks() {
508 TRACE_EVENT0("cc", "PixelBufferTileTaskWorkerPool::ScheduleMoreTasks");
510 RasterTaskVector tasks
[kNumberOfTaskSets
];
512 size_t priority
= kTileTaskPriorityBase
;
516 size_t bytes_pending_upload
= bytes_pending_upload_
;
517 TaskSetCollection did_throttle_raster_tasks
;
518 size_t scheduled_raster_task_count
= 0;
520 for (TileTaskQueue::Item::Vector::const_iterator it
=
521 raster_tasks_
.items
.begin();
522 it
!= raster_tasks_
.items
.end(); ++it
) {
523 const TileTaskQueue::Item
& item
= *it
;
524 RasterTask
* task
= item
.task
;
525 DCHECK(item
.task_sets
.any());
527 // |raster_task_states_| contains the state of all tasks that we have not
528 // yet run reply callbacks for.
529 RasterTaskState::Vector::iterator state_it
=
530 std::find_if(raster_task_states_
.begin(), raster_task_states_
.end(),
531 RasterTaskState::TaskComparator(task
));
532 if (state_it
== raster_task_states_
.end())
535 RasterTaskState
& state
= *state_it
;
537 // Skip task if completed.
538 if (state
.type
== RasterTaskState::COMPLETED
) {
539 DCHECK(std::find(completed_raster_tasks_
.begin(),
540 completed_raster_tasks_
.end(),
541 task
) != completed_raster_tasks_
.end());
545 // All raster tasks need to be throttled by bytes of pending uploads,
546 // but if it's the only task allow it to complete no matter what its size,
547 // to prevent starvation of the task queue.
548 size_t new_bytes_pending_upload
= bytes_pending_upload
;
549 // We can use UncheckedSizeInBytes here, since these tasks come from tiles,
550 // the size of which is controlled by the compositor.
551 new_bytes_pending_upload
+= ResourceUtil::UncheckedSizeInBytes
<size_t>(
552 task
->resource()->size(), task
->resource()->format());
553 if (new_bytes_pending_upload
> max_bytes_pending_upload_
&&
554 bytes_pending_upload
) {
555 did_throttle_raster_tasks
|= item
.task_sets
;
559 // If raster has finished, just update |bytes_pending_upload|.
560 if (state
.type
== RasterTaskState::UPLOADING
) {
561 DCHECK(!task
->HasCompleted());
562 bytes_pending_upload
= new_bytes_pending_upload
;
566 // Throttle raster tasks based on kMaxScheduledRasterTasks.
567 if (scheduled_raster_task_count
>= kMaxScheduledRasterTasks
) {
568 did_throttle_raster_tasks
|= item
.task_sets
;
572 // Update |bytes_pending_upload| now that task has cleared all
573 // throttling limits.
574 bytes_pending_upload
= new_bytes_pending_upload
;
576 DCHECK(state
.type
== RasterTaskState::UNSCHEDULED
||
577 state
.type
== RasterTaskState::SCHEDULED
);
578 state
.type
= RasterTaskState::SCHEDULED
;
580 InsertNodesForRasterTask(&graph_
, task
, task
->dependencies(), priority
++);
582 ++scheduled_raster_task_count
;
583 for (TaskSet task_set
= 0; task_set
< kNumberOfTaskSets
; ++task_set
) {
584 if (item
.task_sets
[task_set
])
585 tasks
[task_set
].container().push_back(task
);
589 // Cancel existing OnTaskSetFinished callbacks.
590 task_set_finished_weak_ptr_factory_
.InvalidateWeakPtrs();
592 scoped_refptr
<TileTask
> new_task_set_finished_tasks
[kNumberOfTaskSets
];
593 size_t scheduled_task_counts
[kNumberOfTaskSets
] = {0};
595 for (TaskSet task_set
= 0; task_set
< kNumberOfTaskSets
; ++task_set
) {
596 scheduled_task_counts
[task_set
] = tasks
[task_set
].container().size();
597 DCHECK_LE(scheduled_task_counts
[task_set
], task_counts_
[task_set
]);
598 // Schedule OnTaskSetFinished call for task set only when notification is
599 // pending and throttling is not preventing all pending tasks in the set
600 // from being scheduled.
601 if (!did_throttle_raster_tasks
[task_set
] &&
602 should_notify_client_if_no_tasks_are_pending_
[task_set
]) {
603 new_task_set_finished_tasks
[task_set
] = CreateTaskSetFinishedTask(
605 base::Bind(&PixelBufferTileTaskWorkerPool::OnTaskSetFinished
,
606 task_set_finished_weak_ptr_factory_
.GetWeakPtr(),
608 task_set_finished_tasks_pending_
[task_set
] = true;
609 InsertNodeForTask(&graph_
, new_task_set_finished_tasks
[task_set
].get(),
610 kTaskSetFinishedTaskPriorityBase
+ task_set
,
611 scheduled_task_counts
[task_set
]);
612 for (RasterTaskVector::ContainerType::const_iterator it
=
613 tasks
[task_set
].container().begin();
614 it
!= tasks
[task_set
].container().end(); ++it
) {
615 graph_
.edges
.push_back(
616 TaskGraph::Edge(*it
, new_task_set_finished_tasks
[task_set
].get()));
621 DCHECK_LE(scheduled_raster_task_count
, PendingRasterTaskCount());
623 ScheduleTasksOnOriginThread(this, &graph_
);
624 task_graph_runner_
->ScheduleTasks(namespace_token_
, &graph_
);
626 scheduled_raster_task_count_
= scheduled_raster_task_count
;
628 std::copy(new_task_set_finished_tasks
,
629 new_task_set_finished_tasks
+ kNumberOfTaskSets
,
630 task_set_finished_tasks_
);
633 size_t PixelBufferTileTaskWorkerPool::PendingRasterTaskCount() const {
634 size_t num_completed_raster_tasks
=
635 raster_tasks_with_pending_upload_
.size() + completed_raster_tasks_
.size();
636 DCHECK_GE(raster_task_states_
.size(), num_completed_raster_tasks
);
637 return raster_task_states_
.size() - num_completed_raster_tasks
;
640 TaskSetCollection
PixelBufferTileTaskWorkerPool::PendingTasks() const {
641 return NonEmptyTaskSetsFromTaskCounts(task_counts_
);
644 const char* PixelBufferTileTaskWorkerPool::StateName() const {
645 if (scheduled_raster_task_count_
)
646 return "rasterizing";
647 if (PendingRasterTaskCount())
649 if (!raster_tasks_with_pending_upload_
.empty())
650 return "waiting_for_uploads";
655 void PixelBufferTileTaskWorkerPool::CheckForCompletedRasterizerTasks() {
657 "cc", "PixelBufferTileTaskWorkerPool::CheckForCompletedRasterizerTasks");
659 task_graph_runner_
->CollectCompletedTasks(namespace_token_
,
661 for (Task::Vector::const_iterator it
= completed_tasks_
.begin();
662 it
!= completed_tasks_
.end(); ++it
) {
663 TileTask
* task
= static_cast<TileTask
*>(it
->get());
665 RasterTask
* raster_task
= task
->AsRasterTask();
667 task
->WillComplete();
668 task
->CompleteOnOriginThread(this);
671 completed_image_decode_tasks_
.push_back(task
);
675 RasterTaskState::Vector::iterator state_it
=
676 std::find_if(raster_task_states_
.begin(), raster_task_states_
.end(),
677 RasterTaskState::TaskComparator(raster_task
));
678 DCHECK(state_it
!= raster_task_states_
.end());
680 RasterTaskState
& state
= *state_it
;
681 DCHECK_EQ(RasterTaskState::SCHEDULED
, state
.type
);
683 resource_provider_
->UnmapPixelBuffer(raster_task
->resource()->id());
685 if (!raster_task
->HasFinishedRunning()) {
686 // When priorites change, a raster task can be canceled as a result of
687 // no longer being of high enough priority to fit in our throttled
688 // raster task budget. The task has not yet completed in this case.
689 raster_task
->WillComplete();
690 raster_task
->CompleteOnOriginThread(this);
691 raster_task
->DidComplete();
693 TileTaskQueue::Item::Vector::const_iterator item_it
=
694 std::find_if(raster_tasks_
.items
.begin(), raster_tasks_
.items
.end(),
695 TileTaskQueue::Item::TaskComparator(raster_task
));
696 if (item_it
!= raster_tasks_
.items
.end()) {
697 state
.type
= RasterTaskState::UNSCHEDULED
;
701 DCHECK(std::find(completed_raster_tasks_
.begin(),
702 completed_raster_tasks_
.end(),
703 raster_task
) == completed_raster_tasks_
.end());
704 completed_raster_tasks_
.push_back(raster_task
);
705 state
.type
= RasterTaskState::COMPLETED
;
706 // Triggers if the current task belongs to a set that should be empty.
707 DCHECK((state
.task_sets
& ~NonEmptyTaskSetsFromTaskCounts(task_counts_
))
709 RemoveTaskSetsFromTaskCounts(task_counts_
, state
.task_sets
);
713 resource_provider_
->BeginSetPixels(raster_task
->resource()->id());
714 has_performed_uploads_since_last_flush_
= true;
716 // We can use UncheckedSizeInBytes here, since these tasks come from tiles,
717 // the size of which is controlled by the compositor.
718 bytes_pending_upload_
+= ResourceUtil::UncheckedSizeInBytes
<size_t>(
719 raster_task
->resource()->size(), raster_task
->resource()->format());
720 raster_tasks_with_pending_upload_
.push_back(raster_task
);
721 state
.type
= RasterTaskState::UPLOADING
;
723 completed_tasks_
.clear();
726 scoped_refptr
<base::trace_event::ConvertableToTraceFormat
>
727 PixelBufferTileTaskWorkerPool::StateAsValue() const {
728 scoped_refptr
<base::trace_event::TracedValue
> state
=
729 new base::trace_event::TracedValue();
730 state
->SetInteger("completed_count",
731 static_cast<int>(completed_raster_tasks_
.size()));
732 state
->BeginArray("pending_count");
733 for (TaskSet task_set
= 0; task_set
< kNumberOfTaskSets
; ++task_set
)
734 state
->AppendInteger(static_cast<int>(task_counts_
[task_set
]));
736 state
->SetInteger("pending_upload_count",
737 static_cast<int>(raster_tasks_with_pending_upload_
.size()));
738 state
->BeginDictionary("throttle_state");
739 ThrottleStateAsValueInto(state
.get());
740 state
->EndDictionary();
744 void PixelBufferTileTaskWorkerPool::ThrottleStateAsValueInto(
745 base::trace_event::TracedValue
* throttle_state
) const {
746 throttle_state
->SetInteger(
747 "bytes_available_for_upload",
748 static_cast<int>(max_bytes_pending_upload_
- bytes_pending_upload_
));
749 throttle_state
->SetInteger("bytes_pending_upload",
750 static_cast<int>(bytes_pending_upload_
));
751 throttle_state
->SetInteger("scheduled_raster_task_count",
752 static_cast<int>(scheduled_raster_task_count_
));