#include "base/values.h"
#include "cc/debug/traced_value.h"
#include "cc/resources/resource.h"
-#include "third_party/skia/include/core/SkBitmapDevice.h"
-
-#if defined(OS_ANDROID)
-#include "base/android/sys_utils.h"
-#endif
namespace cc {
-
namespace {
-class PixelBufferWorkerPoolTaskImpl : public internal::WorkerPoolTask {
- public:
- typedef base::Callback<void(bool was_canceled, bool needs_upload)> Reply;
-
- PixelBufferWorkerPoolTaskImpl(internal::RasterWorkerPoolTask* task,
- uint8_t* buffer,
- const Reply& reply)
- : task_(task), buffer_(buffer), reply_(reply), needs_upload_(false) {}
-
- // Overridden from internal::Task:
- virtual void RunOnWorkerThread(unsigned thread_index) OVERRIDE {
- // |buffer_| can be NULL in lost context situations.
- if (!buffer_) {
- // |needs_upload_| still needs to be true as task has not
- // been canceled.
- needs_upload_ = true;
- return;
- }
- needs_upload_ = task_->RunOnWorkerThread(
- thread_index, buffer_, task_->resource()->size(), 0);
- }
-
- // Overridden from internal::WorkerPoolTask:
- virtual void CompleteOnOriginThread() OVERRIDE {
- // |needs_upload_| must be be false if task didn't run.
- DCHECK(HasFinishedRunning() || !needs_upload_);
- reply_.Run(!HasFinishedRunning(), needs_upload_);
- }
-
- private:
- virtual ~PixelBufferWorkerPoolTaskImpl() {}
-
- scoped_refptr<internal::RasterWorkerPoolTask> task_;
- uint8_t* buffer_;
- const Reply reply_;
- bool needs_upload_;
-
- DISALLOW_COPY_AND_ASSIGN(PixelBufferWorkerPoolTaskImpl);
-};
-
const int kCheckForCompletedRasterTasksDelayMs = 6;
const size_t kMaxScheduledRasterTasks = 48;
-typedef base::StackVector<internal::GraphNode*, kMaxScheduledRasterTasks>
- NodeVector;
-
-void AddDependenciesToGraphNode(internal::GraphNode* node,
- const NodeVector::ContainerType& dependencies) {
- for (NodeVector::ContainerType::const_iterator it = dependencies.begin();
- it != dependencies.end();
- ++it) {
- internal::GraphNode* dependency = *it;
-
- node->add_dependency();
- dependency->add_dependent(node);
- }
-}
+typedef base::StackVector<internal::WorkerPoolTask*, kMaxScheduledRasterTasks>
+ WorkerPoolTaskVector;
// Only used as std::find_if predicate for DCHECKs.
bool WasCanceled(const internal::RasterWorkerPoolTask* task) {
- return task->WasCanceled();
+ return !task->HasFinishedRunning();
}
} // namespace
+// static
+scoped_ptr<RasterWorkerPool> PixelBufferRasterWorkerPool::Create(
+ ResourceProvider* resource_provider,
+ size_t max_transfer_buffer_usage_bytes) {
+ return make_scoped_ptr<RasterWorkerPool>(
+ new PixelBufferRasterWorkerPool(GetTaskGraphRunner(),
+ resource_provider,
+ max_transfer_buffer_usage_bytes));
+}
+
PixelBufferRasterWorkerPool::PixelBufferRasterWorkerPool(
+ internal::TaskGraphRunner* task_graph_runner,
ResourceProvider* resource_provider,
- ContextProvider* context_provider,
size_t max_transfer_buffer_usage_bytes)
- : RasterWorkerPool(resource_provider, context_provider),
+ : RasterWorkerPool(task_graph_runner, resource_provider),
shutdown_(false),
scheduled_raster_task_count_(0),
bytes_pending_upload_(0),
should_notify_client_if_no_tasks_required_for_activation_are_pending_(
false),
raster_finished_task_pending_(false),
- raster_required_for_activation_finished_task_pending_(false) {}
+ raster_required_for_activation_finished_task_pending_(false),
+ weak_factory_(this) {}
PixelBufferRasterWorkerPool::~PixelBufferRasterWorkerPool() {
DCHECK(shutdown_);
DCHECK(!check_for_completed_raster_tasks_pending_);
- DCHECK_EQ(0u, pixel_buffer_tasks_.size());
- DCHECK_EQ(0u, tasks_with_pending_upload_.size());
- DCHECK_EQ(0u, completed_tasks_.size());
+ DCHECK_EQ(0u, raster_task_states_.size());
+ DCHECK_EQ(0u, raster_tasks_with_pending_upload_.size());
+ DCHECK_EQ(0u, completed_raster_tasks_.size());
+ DCHECK_EQ(0u, completed_image_decode_tasks_.size());
}
void PixelBufferRasterWorkerPool::Shutdown() {
CheckForCompletedWorkerPoolTasks();
CheckForCompletedUploads();
- check_for_completed_raster_tasks_callback_.Cancel();
+
+ weak_factory_.InvalidateWeakPtrs();
check_for_completed_raster_tasks_pending_ = false;
- for (TaskMap::iterator it = pixel_buffer_tasks_.begin();
- it != pixel_buffer_tasks_.end();
+
+ for (RasterTaskStateMap::iterator it = raster_task_states_.begin();
+ it != raster_task_states_.end();
++it) {
internal::RasterWorkerPoolTask* task = it->first;
- internal::WorkerPoolTask* pixel_buffer_task = it->second.get();
- // All inactive tasks needs to be canceled.
- if (!pixel_buffer_task && !task->HasFinishedRunning()) {
- task->DidRun(true);
- completed_tasks_.push_back(task);
+ // All unscheduled tasks need to be canceled.
+ if (it->second == UNSCHEDULED) {
+ completed_raster_tasks_.push_back(task);
+ it->second = COMPLETED;
}
}
- DCHECK_EQ(completed_tasks_.size(), pixel_buffer_tasks_.size());
+ DCHECK_EQ(completed_raster_tasks_.size(), raster_task_states_.size());
}
void PixelBufferRasterWorkerPool::ScheduleTasks(RasterTask::Queue* queue) {
TRACE_EVENT0("cc", "PixelBufferRasterWorkerPool::ScheduleTasks");
- RasterWorkerPool::SetRasterTasks(queue);
-
if (!should_notify_client_if_no_tasks_are_pending_)
TRACE_EVENT_ASYNC_BEGIN0("cc", "ScheduledTasks", this);
should_notify_client_if_no_tasks_are_pending_ = true;
should_notify_client_if_no_tasks_required_for_activation_are_pending_ = true;
- tasks_required_for_activation_.clear();
-
- // Build new pixel buffer task set.
- TaskMap new_pixel_buffer_tasks;
- RasterTaskVector gpu_raster_tasks;
- for (RasterTaskVector::const_iterator it = raster_tasks().begin();
- it != raster_tasks().end();
- ++it) {
- internal::RasterWorkerPoolTask* task = it->get();
- DCHECK(new_pixel_buffer_tasks.find(task) == new_pixel_buffer_tasks.end());
- DCHECK(!task->HasCompleted());
- DCHECK(!task->WasCanceled());
-
- if (task->use_gpu_rasterization()) {
- gpu_raster_tasks.push_back(task);
- continue;
+ raster_tasks_required_for_activation_.clear();
+
+ // Build new raster task state map.
+ RasterTaskStateMap new_raster_task_states;
+ for (RasterTaskQueueIterator it(queue); it; ++it) {
+ internal::RasterWorkerPoolTask* task = *it;
+ DCHECK(new_raster_task_states.find(task) == new_raster_task_states.end());
+
+ RasterTaskStateMap::iterator state_it = raster_task_states_.find(task);
+ if (state_it != raster_task_states_.end()) {
+ RasterTaskState state = state_it->second;
+
+ new_raster_task_states[task] = state;
+ // |raster_tasks_required_for_activation_| contains all tasks that need to
+ // complete before we can send a "ready to activate" signal. Tasks that
+ // have already completed should not be part of this set.
+ if (state != COMPLETED && it.required_for_activation())
+ raster_tasks_required_for_activation_.insert(task);
+
+ raster_task_states_.erase(state_it);
+ } else {
+ DCHECK(!task->HasBeenScheduled());
+ new_raster_task_states[task] = UNSCHEDULED;
+ if (it.required_for_activation())
+ raster_tasks_required_for_activation_.insert(task);
}
-
- new_pixel_buffer_tasks[task] = pixel_buffer_tasks_[task];
- pixel_buffer_tasks_.erase(task);
-
- if (IsRasterTaskRequiredForActivation(task))
- tasks_required_for_activation_.insert(task);
}
- // Transfer remaining pixel buffer tasks to |new_pixel_buffer_tasks|
- // and cancel all remaining inactive tasks.
- for (TaskMap::iterator it = pixel_buffer_tasks_.begin();
- it != pixel_buffer_tasks_.end();
+ // Transfer old raster task state to |new_raster_task_states| and cancel all
+ // remaining unscheduled tasks.
+ for (RasterTaskStateMap::iterator it = raster_task_states_.begin();
+ it != raster_task_states_.end();
++it) {
internal::RasterWorkerPoolTask* task = it->first;
- internal::WorkerPoolTask* pixel_buffer_task = it->second.get();
-
- // Move task to |new_pixel_buffer_tasks|
- new_pixel_buffer_tasks[task] = pixel_buffer_task;
-
- // Inactive task can be canceled.
- if (!pixel_buffer_task && !task->HasFinishedRunning()) {
- task->DidRun(true);
- DCHECK(std::find(completed_tasks_.begin(),
- completed_tasks_.end(),
- task) == completed_tasks_.end());
- completed_tasks_.push_back(task);
- } else if (IsRasterTaskRequiredForActivation(task)) {
- tasks_required_for_activation_.insert(task);
+ DCHECK(new_raster_task_states.find(task) == new_raster_task_states.end());
+
+ // Unscheduled task can be canceled.
+ if (it->second == UNSCHEDULED) {
+ DCHECK(!task->HasBeenScheduled());
+ DCHECK(std::find(completed_raster_tasks_.begin(),
+ completed_raster_tasks_.end(),
+ task) == completed_raster_tasks_.end());
+ completed_raster_tasks_.push_back(task);
+ new_raster_task_states[task] = COMPLETED;
+ continue;
}
- }
- // |tasks_required_for_activation_| contains all tasks that need to
- // complete before we can send a "ready to activate" signal. Tasks
- // that have already completed should not be part of this set.
- for (RasterTaskDeque::const_iterator it = completed_tasks_.begin();
- it != completed_tasks_.end() && !tasks_required_for_activation_.empty();
- ++it) {
- tasks_required_for_activation_.erase(*it);
+ // Move state to |new_raster_task_states|.
+ new_raster_task_states[task] = it->second;
}
- pixel_buffer_tasks_.swap(new_pixel_buffer_tasks);
+ raster_tasks_.Swap(queue);
+ raster_task_states_.swap(new_raster_task_states);
// Check for completed tasks when ScheduleTasks() is called as
// priorities might have changed and this maximizes the number
// Cancel any pending check for completed raster tasks and schedule
// another check.
- check_for_completed_raster_tasks_callback_.Cancel();
- check_for_completed_raster_tasks_pending_ = false;
+ check_for_completed_raster_tasks_time_ = base::TimeTicks();
ScheduleCheckForCompletedRasterTasks();
- RunGpuRasterTasks(gpu_raster_tasks);
-
TRACE_EVENT_ASYNC_STEP_INTO1(
"cc",
"ScheduledTasks",
void PixelBufferRasterWorkerPool::CheckForCompletedTasks() {
TRACE_EVENT0("cc", "PixelBufferRasterWorkerPool::CheckForCompletedTasks");
- RasterWorkerPool::CheckForCompletedTasks();
+ CheckForCompletedWorkerPoolTasks();
CheckForCompletedUploads();
FlushUploads();
- RasterTaskDeque completed_tasks;
- completed_tasks_.swap(completed_tasks);
+ while (!completed_image_decode_tasks_.empty()) {
+ internal::WorkerPoolTask* task =
+ completed_image_decode_tasks_.front().get();
- while (!completed_tasks.empty()) {
- internal::RasterWorkerPoolTask* task = completed_tasks.front().get();
- DCHECK(pixel_buffer_tasks_.find(task) != pixel_buffer_tasks_.end());
+ task->RunReplyOnOriginThread();
- pixel_buffer_tasks_.erase(task);
+ completed_image_decode_tasks_.pop_front();
+ }
- task->WillComplete();
- task->CompleteOnOriginThread();
- task->DidComplete();
+ while (!completed_raster_tasks_.empty()) {
+ internal::RasterWorkerPoolTask* task =
+ completed_raster_tasks_.front().get();
+ DCHECK(raster_task_states_.find(task) != raster_task_states_.end());
+ DCHECK_EQ(COMPLETED, raster_task_states_[task]);
+
+ raster_task_states_.erase(task);
+
+ task->RunReplyOnOriginThread();
+
+ completed_raster_tasks_.pop_front();
+ }
+}
+
+SkCanvas* PixelBufferRasterWorkerPool::AcquireCanvasForRaster(
+ internal::RasterWorkerPoolTask* task) {
+ resource_provider()->AcquirePixelRasterBuffer(task->resource()->id());
+ return resource_provider()->MapPixelRasterBuffer(task->resource()->id());
+}
+
+void PixelBufferRasterWorkerPool::OnRasterCompleted(
+ internal::RasterWorkerPoolTask* task,
+ const PicturePileImpl::Analysis& analysis) {
+ TRACE_EVENT2(TRACE_DISABLED_BY_DEFAULT("cc"),
+ "PixelBufferRasterWorkerPool::OnRasterCompleted",
+ "was_canceled",
+ !task->HasFinishedRunning(),
+ "needs_upload",
+ task->HasFinishedRunning() && !analysis.is_solid_color);
+
+ DCHECK(raster_task_states_.find(task) != raster_task_states_.end());
+ DCHECK_EQ(SCHEDULED, raster_task_states_[task]);
+
+ // Balanced with MapPixelRasterBuffer() call in AcquireCanvasForRaster().
+ resource_provider()->UnmapPixelRasterBuffer(task->resource()->id());
- completed_tasks.pop_front();
+ if (!task->HasFinishedRunning() || analysis.is_solid_color) {
+ resource_provider()->ReleasePixelRasterBuffer(task->resource()->id());
+
+ if (!task->HasFinishedRunning()) {
+ // When priorites change, a raster task can be canceled as a result of
+ // no longer being of high enough priority to fit in our throttled
+ // raster task budget. The task has not yet completed in this case.
+ for (RasterTaskQueueIterator it(&raster_tasks_); it; ++it) {
+ if (*it == task) {
+ raster_task_states_[task] = UNSCHEDULED;
+ return;
+ }
+ }
+ }
+
+ DCHECK(std::find(completed_raster_tasks_.begin(),
+ completed_raster_tasks_.end(),
+ task) == completed_raster_tasks_.end());
+ completed_raster_tasks_.push_back(task);
+ raster_task_states_[task] = COMPLETED;
+ raster_tasks_required_for_activation_.erase(task);
+ return;
}
+
+ DCHECK(task->HasFinishedRunning());
+
+ resource_provider()->BeginSetPixels(task->resource()->id());
+ has_performed_uploads_since_last_flush_ = true;
+
+ bytes_pending_upload_ += task->resource()->bytes();
+ raster_tasks_with_pending_upload_.push_back(task);
+ raster_task_states_[task] = UPLOADING;
+}
+
+void PixelBufferRasterWorkerPool::OnImageDecodeCompleted(
+ internal::WorkerPoolTask* task) {
+ completed_image_decode_tasks_.push_back(task);
}
void PixelBufferRasterWorkerPool::OnRasterTasksFinished() {
RasterTaskDeque tasks_with_completed_uploads;
// First check if any have completed.
- while (!tasks_with_pending_upload_.empty()) {
+ while (!raster_tasks_with_pending_upload_.empty()) {
internal::RasterWorkerPoolTask* task =
- tasks_with_pending_upload_.front().get();
+ raster_tasks_with_pending_upload_.front().get();
+ DCHECK(raster_task_states_.find(task) != raster_task_states_.end());
+ DCHECK_EQ(UPLOADING, raster_task_states_[task]);
// Uploads complete in the order they are issued.
if (!resource_provider()->DidSetPixelsComplete(task->resource()->id()))
break;
tasks_with_completed_uploads.push_back(task);
- tasks_with_pending_upload_.pop_front();
+ raster_tasks_with_pending_upload_.pop_front();
}
DCHECK(client());
if (should_force_some_uploads_to_complete) {
RasterTaskDeque tasks_with_uploads_to_force;
- RasterTaskDeque::iterator it = tasks_with_pending_upload_.begin();
- while (it != tasks_with_pending_upload_.end()) {
+ RasterTaskDeque::iterator it = raster_tasks_with_pending_upload_.begin();
+ while (it != raster_tasks_with_pending_upload_.end()) {
internal::RasterWorkerPoolTask* task = it->get();
- DCHECK(pixel_buffer_tasks_.find(task) != pixel_buffer_tasks_.end());
+ DCHECK(raster_task_states_.find(task) != raster_task_states_.end());
// Force all uploads required for activation to complete.
// During shutdown, force all pending uploads to complete.
if (shutdown_ || IsRasterTaskRequiredForActivation(task)) {
tasks_with_uploads_to_force.push_back(task);
tasks_with_completed_uploads.push_back(task);
- it = tasks_with_pending_upload_.erase(it);
+ it = raster_tasks_with_pending_upload_.erase(it);
continue;
}
}
// Release shared memory and move tasks with completed uploads
- // to |completed_tasks_|.
+ // to |completed_raster_tasks_|.
while (!tasks_with_completed_uploads.empty()) {
internal::RasterWorkerPoolTask* task =
tasks_with_completed_uploads.front().get();
// It's now safe to release the pixel buffer and the shared memory.
- resource_provider()->ReleasePixelBuffer(task->resource()->id());
+ resource_provider()->ReleasePixelRasterBuffer(task->resource()->id());
bytes_pending_upload_ -= task->resource()->bytes();
- task->DidRun(false);
-
- DCHECK(std::find(completed_tasks_.begin(), completed_tasks_.end(), task) ==
- completed_tasks_.end());
- completed_tasks_.push_back(task);
+ DCHECK(std::find(completed_raster_tasks_.begin(),
+ completed_raster_tasks_.end(),
+ task) == completed_raster_tasks_.end());
+ completed_raster_tasks_.push_back(task);
+ raster_task_states_[task] = COMPLETED;
- tasks_required_for_activation_.erase(task);
+ raster_tasks_required_for_activation_.erase(task);
tasks_with_completed_uploads.pop_front();
}
}
void PixelBufferRasterWorkerPool::ScheduleCheckForCompletedRasterTasks() {
+ base::TimeDelta delay =
+ base::TimeDelta::FromMilliseconds(kCheckForCompletedRasterTasksDelayMs);
+ if (check_for_completed_raster_tasks_time_.is_null())
+ check_for_completed_raster_tasks_time_ = base::TimeTicks::Now() + delay;
+
if (check_for_completed_raster_tasks_pending_)
return;
- check_for_completed_raster_tasks_callback_.Reset(
- base::Bind(&PixelBufferRasterWorkerPool::CheckForCompletedRasterTasks,
- base::Unretained(this)));
base::MessageLoopProxy::current()->PostDelayedTask(
FROM_HERE,
- check_for_completed_raster_tasks_callback_.callback(),
- base::TimeDelta::FromMilliseconds(kCheckForCompletedRasterTasksDelayMs));
+ base::Bind(&PixelBufferRasterWorkerPool::OnCheckForCompletedRasterTasks,
+ weak_factory_.GetWeakPtr()),
+ delay);
check_for_completed_raster_tasks_pending_ = true;
}
+void PixelBufferRasterWorkerPool::OnCheckForCompletedRasterTasks() {
+ if (check_for_completed_raster_tasks_time_.is_null()) {
+ check_for_completed_raster_tasks_pending_ = false;
+ return;
+ }
+
+ base::TimeDelta delay =
+ check_for_completed_raster_tasks_time_ - base::TimeTicks::Now();
+
+ // Post another delayed task if it is not yet time to check for completed
+ // raster tasks.
+ if (delay > base::TimeDelta()) {
+ base::MessageLoopProxy::current()->PostDelayedTask(
+ FROM_HERE,
+ base::Bind(&PixelBufferRasterWorkerPool::OnCheckForCompletedRasterTasks,
+ weak_factory_.GetWeakPtr()),
+ delay);
+ return;
+ }
+
+ check_for_completed_raster_tasks_pending_ = false;
+ CheckForCompletedRasterTasks();
+}
+
void PixelBufferRasterWorkerPool::CheckForCompletedRasterTasks() {
TRACE_EVENT0("cc",
"PixelBufferRasterWorkerPool::CheckForCompletedRasterTasks");
DCHECK(should_notify_client_if_no_tasks_are_pending_);
-
- check_for_completed_raster_tasks_callback_.Cancel();
- check_for_completed_raster_tasks_pending_ = false;
+ check_for_completed_raster_tasks_time_ = base::TimeTicks();
CheckForCompletedWorkerPoolTasks();
CheckForCompletedUploads();
!HasPendingTasksRequiredForActivation());
bool will_notify_client_that_no_tasks_are_pending =
(should_notify_client_if_no_tasks_are_pending_ &&
+ !raster_required_for_activation_finished_task_pending_ &&
!raster_finished_task_pending_ && !HasPendingTasks());
// Adjust the need to generate notifications before scheduling more tasks.
// Generate client notifications.
if (will_notify_client_that_no_tasks_required_for_activation_are_pending) {
- DCHECK(std::find_if(raster_tasks_required_for_activation().begin(),
- raster_tasks_required_for_activation().end(),
+ DCHECK(std::find_if(raster_tasks_required_for_activation_.begin(),
+ raster_tasks_required_for_activation_.end(),
WasCanceled) ==
- raster_tasks_required_for_activation().end());
+ raster_tasks_required_for_activation_.end());
client()->DidFinishRunningTasksRequiredForActivation();
}
if (will_notify_client_that_no_tasks_are_pending) {
void PixelBufferRasterWorkerPool::ScheduleMoreTasks() {
TRACE_EVENT0("cc", "PixelBufferRasterWorkerPool::ScheduleMoreTasks");
- enum RasterTaskType {
- PREPAINT_TYPE = 0,
- REQUIRED_FOR_ACTIVATION_TYPE = 1,
- NUM_TYPES = 2
- };
- NodeVector tasks[NUM_TYPES];
- unsigned priority = 2u; // 0-1 reserved for RasterFinished tasks.
- TaskGraph graph;
+ WorkerPoolTaskVector tasks;
+ WorkerPoolTaskVector tasks_required_for_activation;
+
+ unsigned priority = kRasterTaskPriorityBase;
+
+ graph_.Reset();
size_t bytes_pending_upload = bytes_pending_upload_;
bool did_throttle_raster_tasks = false;
- for (RasterTaskVector::const_iterator it = raster_tasks().begin();
- it != raster_tasks().end();
- ++it) {
- internal::RasterWorkerPoolTask* task = it->get();
+ for (RasterTaskQueueIterator it(&raster_tasks_); it; ++it) {
+ internal::RasterWorkerPoolTask* task = *it;
- // |pixel_buffer_tasks_| contains all tasks that have not yet completed.
- TaskMap::iterator pixel_buffer_it = pixel_buffer_tasks_.find(task);
- if (pixel_buffer_it == pixel_buffer_tasks_.end())
+ // |raster_task_states_| contains the state of all tasks that we have not
+ // yet run reply callbacks for.
+ RasterTaskStateMap::iterator state_it = raster_task_states_.find(task);
+ if (state_it == raster_task_states_.end())
continue;
- // HasFinishedRunning() will return true when set pixels has completed.
- if (task->HasFinishedRunning()) {
- DCHECK(std::find(completed_tasks_.begin(),
- completed_tasks_.end(),
- task) != completed_tasks_.end());
+ // Skip task if completed.
+ if (state_it->second == COMPLETED) {
+ DCHECK(std::find(completed_raster_tasks_.begin(),
+ completed_raster_tasks_.end(),
+ task) != completed_raster_tasks_.end());
continue;
}
break;
}
- internal::WorkerPoolTask* pixel_buffer_task = pixel_buffer_it->second.get();
-
// If raster has finished, just update |bytes_pending_upload|.
- if (pixel_buffer_task && pixel_buffer_task->HasCompleted()) {
+ if (state_it->second == UPLOADING) {
+ DCHECK(task->HasCompleted());
bytes_pending_upload = new_bytes_pending_upload;
continue;
}
// Throttle raster tasks based on kMaxScheduledRasterTasks.
- size_t scheduled_raster_task_count =
- tasks[PREPAINT_TYPE].container().size() +
- tasks[REQUIRED_FOR_ACTIVATION_TYPE].container().size();
- if (scheduled_raster_task_count >= kMaxScheduledRasterTasks) {
+ if (tasks.container().size() >= kMaxScheduledRasterTasks) {
did_throttle_raster_tasks = true;
break;
}
// throttling limits.
bytes_pending_upload = new_bytes_pending_upload;
- RasterTaskType type = IsRasterTaskRequiredForActivation(task)
- ? REQUIRED_FOR_ACTIVATION_TYPE
- : PREPAINT_TYPE;
+ DCHECK(state_it->second == UNSCHEDULED || state_it->second == SCHEDULED);
+ state_it->second = SCHEDULED;
- // Use existing pixel buffer task if available.
- if (pixel_buffer_task) {
- tasks[type].container().push_back(CreateGraphNodeForRasterTask(
- pixel_buffer_task, task->dependencies(), priority++, &graph));
- continue;
- }
+ InsertNodeForRasterTask(&graph_, task, task->dependencies(), priority++);
- // Request a pixel buffer. This will reserve shared memory.
- resource_provider()->AcquirePixelBuffer(task->resource()->id());
-
- // MapPixelBuffer() returns NULL if context was lost at the time
- // AcquirePixelBuffer() was called. For simplicity we still post
- // a raster task that is essentially a noop in these situations.
- uint8* buffer = resource_provider()->MapPixelBuffer(task->resource()->id());
-
- scoped_refptr<internal::WorkerPoolTask> new_pixel_buffer_task(
- new PixelBufferWorkerPoolTaskImpl(
- task,
- buffer,
- base::Bind(&PixelBufferRasterWorkerPool::OnRasterTaskCompleted,
- base::Unretained(this),
- make_scoped_refptr(task))));
- pixel_buffer_tasks_[task] = new_pixel_buffer_task;
- tasks[type].container().push_back(CreateGraphNodeForRasterTask(
- new_pixel_buffer_task.get(), task->dependencies(), priority++, &graph));
+ tasks.container().push_back(task);
+ if (it.required_for_activation())
+ tasks_required_for_activation.container().push_back(task);
}
scoped_refptr<internal::WorkerPoolTask>
new_raster_required_for_activation_finished_task;
size_t scheduled_raster_task_required_for_activation_count =
- tasks[REQUIRED_FOR_ACTIVATION_TYPE].container().size();
+ tasks_required_for_activation.container().size();
DCHECK_LE(scheduled_raster_task_required_for_activation_count,
- tasks_required_for_activation_.size());
+ raster_tasks_required_for_activation_.size());
// Schedule OnRasterTasksRequiredForActivationFinished call only when
// notification is pending and throttling is not preventing all pending
// tasks required for activation from being scheduled.
if (scheduled_raster_task_required_for_activation_count ==
- tasks_required_for_activation_.size() &&
+ raster_tasks_required_for_activation_.size() &&
should_notify_client_if_no_tasks_required_for_activation_are_pending_) {
new_raster_required_for_activation_finished_task =
CreateRasterRequiredForActivationFinishedTask(
- tasks_required_for_activation_.size());
+ raster_tasks_required_for_activation_.size());
raster_required_for_activation_finished_task_pending_ = true;
- internal::GraphNode* raster_required_for_activation_finished_node =
- CreateGraphNodeForTask(
- new_raster_required_for_activation_finished_task.get(),
- 0u, // Priority 0
- &graph);
- AddDependenciesToGraphNode(raster_required_for_activation_finished_node,
- tasks[REQUIRED_FOR_ACTIVATION_TYPE].container());
+ InsertNodeForTask(&graph_,
+ new_raster_required_for_activation_finished_task.get(),
+ kRasterRequiredForActivationFinishedTaskPriority,
+ scheduled_raster_task_required_for_activation_count);
+ for (WorkerPoolTaskVector::ContainerType::const_iterator it =
+ tasks_required_for_activation.container().begin();
+ it != tasks_required_for_activation.container().end();
+ ++it) {
+ graph_.edges.push_back(internal::TaskGraph::Edge(
+ *it, new_raster_required_for_activation_finished_task.get()));
+ }
}
scoped_refptr<internal::WorkerPoolTask> new_raster_finished_task;
- size_t scheduled_raster_task_count =
- tasks[PREPAINT_TYPE].container().size() +
- tasks[REQUIRED_FOR_ACTIVATION_TYPE].container().size();
+ size_t scheduled_raster_task_count = tasks.container().size();
DCHECK_LE(scheduled_raster_task_count, PendingRasterTaskCount());
// Schedule OnRasterTasksFinished call only when notification is pending
// and throttling is not preventing all pending tasks from being scheduled.
should_notify_client_if_no_tasks_are_pending_) {
new_raster_finished_task = CreateRasterFinishedTask();
raster_finished_task_pending_ = true;
- internal::GraphNode* raster_finished_node =
- CreateGraphNodeForTask(new_raster_finished_task.get(),
- 1u, // Priority 1
- &graph);
- for (unsigned type = 0; type < NUM_TYPES; ++type) {
- AddDependenciesToGraphNode(raster_finished_node, tasks[type].container());
+ InsertNodeForTask(&graph_,
+ new_raster_finished_task.get(),
+ kRasterFinishedTaskPriority,
+ scheduled_raster_task_count);
+ for (WorkerPoolTaskVector::ContainerType::const_iterator it =
+ tasks.container().begin();
+ it != tasks.container().end();
+ ++it) {
+ graph_.edges.push_back(
+ internal::TaskGraph::Edge(*it, new_raster_finished_task.get()));
}
}
- SetTaskGraph(&graph);
+ SetTaskGraph(&graph_);
scheduled_raster_task_count_ = scheduled_raster_task_count;
new_raster_required_for_activation_finished_task);
}
-void PixelBufferRasterWorkerPool::OnRasterTaskCompleted(
- scoped_refptr<internal::RasterWorkerPoolTask> task,
- bool was_canceled,
- bool needs_upload) {
- TRACE_EVENT2(TRACE_DISABLED_BY_DEFAULT("cc"),
- "PixelBufferRasterWorkerPool::OnRasterTaskCompleted",
- "was_canceled",
- was_canceled,
- "needs_upload",
- needs_upload);
-
- DCHECK(!task->use_gpu_rasterization());
- DCHECK(pixel_buffer_tasks_.find(task.get()) != pixel_buffer_tasks_.end());
-
- // Balanced with MapPixelBuffer() call in ScheduleMoreTasks().
- resource_provider()->UnmapPixelBuffer(task->resource()->id());
-
- if (!needs_upload) {
- resource_provider()->ReleasePixelBuffer(task->resource()->id());
-
- if (was_canceled) {
- // When priorites change, a raster task can be canceled as a result of
- // no longer being of high enough priority to fit in our throttled
- // raster task budget. The task has not yet completed in this case.
- RasterTaskVector::const_iterator it =
- std::find(raster_tasks().begin(), raster_tasks().end(), task);
- if (it != raster_tasks().end()) {
- pixel_buffer_tasks_[task.get()] = NULL;
- return;
- }
- }
-
- task->DidRun(was_canceled);
- DCHECK(std::find(completed_tasks_.begin(), completed_tasks_.end(), task) ==
- completed_tasks_.end());
- completed_tasks_.push_back(task);
- tasks_required_for_activation_.erase(task);
- return;
- }
-
- DCHECK(!was_canceled);
-
- resource_provider()->BeginSetPixels(task->resource()->id());
- has_performed_uploads_since_last_flush_ = true;
-
- bytes_pending_upload_ += task->resource()->bytes();
- tasks_with_pending_upload_.push_back(task);
-}
-
unsigned PixelBufferRasterWorkerPool::PendingRasterTaskCount() const {
unsigned num_completed_raster_tasks =
- tasks_with_pending_upload_.size() + completed_tasks_.size();
- DCHECK_GE(pixel_buffer_tasks_.size(), num_completed_raster_tasks);
- return pixel_buffer_tasks_.size() - num_completed_raster_tasks;
+ raster_tasks_with_pending_upload_.size() + completed_raster_tasks_.size();
+ DCHECK_GE(raster_task_states_.size(), num_completed_raster_tasks);
+ return raster_task_states_.size() - num_completed_raster_tasks;
}
bool PixelBufferRasterWorkerPool::HasPendingTasks() const {
- return PendingRasterTaskCount() || !tasks_with_pending_upload_.empty();
+ return PendingRasterTaskCount() || !raster_tasks_with_pending_upload_.empty();
}
bool PixelBufferRasterWorkerPool::HasPendingTasksRequiredForActivation() const {
- return !tasks_required_for_activation_.empty();
+ return !raster_tasks_required_for_activation_.empty();
}
const char* PixelBufferRasterWorkerPool::StateName() const {
return "rasterizing";
if (PendingRasterTaskCount())
return "throttled";
- if (!tasks_with_pending_upload_.empty())
+ if (!raster_tasks_with_pending_upload_.empty())
return "waiting_for_uploads";
return "finishing";
}
+void PixelBufferRasterWorkerPool::CheckForCompletedWorkerPoolTasks() {
+ CollectCompletedWorkerPoolTasks(&completed_tasks_);
+ for (internal::Task::Vector::const_iterator it = completed_tasks_.begin();
+ it != completed_tasks_.end();
+ ++it) {
+ internal::WorkerPoolTask* task =
+ static_cast<internal::WorkerPoolTask*>(it->get());
+
+ task->WillComplete();
+ task->CompleteOnOriginThread(this);
+ task->DidComplete();
+ }
+ completed_tasks_.clear();
+}
+
+bool PixelBufferRasterWorkerPool::IsRasterTaskRequiredForActivation(
+ internal::RasterWorkerPoolTask* task) const {
+ return raster_tasks_required_for_activation_.find(task) !=
+ raster_tasks_required_for_activation_.end();
+}
+
scoped_ptr<base::Value> PixelBufferRasterWorkerPool::StateAsValue() const {
scoped_ptr<base::DictionaryValue> state(new base::DictionaryValue);
- state->SetInteger("completed_count", completed_tasks_.size());
- state->SetInteger("pending_count", pixel_buffer_tasks_.size());
- state->SetInteger("pending_upload_count", tasks_with_pending_upload_.size());
- state->SetInteger("required_for_activation_count",
- tasks_required_for_activation_.size());
- state->Set("scheduled_state", ScheduledStateAsValue().release());
+ state->SetInteger("completed_count", completed_raster_tasks_.size());
+ state->SetInteger("pending_count", raster_task_states_.size());
+ state->SetInteger("pending_upload_count",
+ raster_tasks_with_pending_upload_.size());
+ state->SetInteger("pending_required_for_activation_count",
+ raster_tasks_required_for_activation_.size());
state->Set("throttle_state", ThrottleStateAsValue().release());
return state.PassAs<base::Value>();
}