Chromium Code Reviews| Index: cc/resources/image_copy_raster_worker_pool.cc |
| diff --git a/cc/resources/image_copy_raster_worker_pool.cc b/cc/resources/image_copy_raster_worker_pool.cc |
| new file mode 100644 |
| index 0000000000000000000000000000000000000000..0d4f7441e5222be3b78646df74e05dd6e98dbbae |
| --- /dev/null |
| +++ b/cc/resources/image_copy_raster_worker_pool.cc |
| @@ -0,0 +1,260 @@ |
| +// Copyright 2014 The Chromium Authors. All rights reserved. |
| +// Use of this source code is governed by a BSD-style license that can be |
| +// found in the LICENSE file. |
| + |
| +#include "cc/resources/image_copy_raster_worker_pool.h" |
| + |
| +#include <algorithm> |
| + |
| +#include "base/debug/trace_event.h" |
| +#include "cc/debug/traced_value.h" |
| +#include "cc/resources/resource_pool.h" |
| +#include "cc/resources/scoped_resource.h" |
| + |
| +namespace cc { |
| + |
| +// static |
| +scoped_ptr<RasterWorkerPool> ImageCopyRasterWorkerPool::Create( |
| + base::SequencedTaskRunner* task_runner, |
| + TaskGraphRunner* task_graph_runner, |
| + ResourceProvider* resource_provider, |
| + ResourcePool* resource_pool) { |
| + return make_scoped_ptr<RasterWorkerPool>(new ImageCopyRasterWorkerPool( |
| + task_runner, task_graph_runner, resource_provider, resource_pool)); |
| +} |
| + |
| +ImageCopyRasterWorkerPool::ImageCopyRasterWorkerPool( |
| + base::SequencedTaskRunner* task_runner, |
| + TaskGraphRunner* task_graph_runner, |
| + ResourceProvider* resource_provider, |
| + ResourcePool* resource_pool) |
| + : task_runner_(task_runner), |
| + task_graph_runner_(task_graph_runner), |
| + namespace_token_(task_graph_runner->GetNamespaceToken()), |
| + resource_provider_(resource_provider), |
| + resource_pool_(resource_pool), |
| + has_performed_copy_since_last_flush_(false), |
| + raster_tasks_pending_(false), |
| + raster_tasks_required_for_activation_pending_(false), |
| + raster_finished_weak_ptr_factory_(this) {} |
| + |
| +ImageCopyRasterWorkerPool::~ImageCopyRasterWorkerPool() { |
| + DCHECK_EQ(0u, raster_task_states_.size()); |
| +} |
| + |
| +Rasterizer* ImageCopyRasterWorkerPool::AsRasterizer() { return this; } |
| + |
| +void ImageCopyRasterWorkerPool::SetClient(RasterizerClient* client) { |
| + client_ = client; |
| +} |
| + |
| +void ImageCopyRasterWorkerPool::Shutdown() { |
| + TRACE_EVENT0("cc", "ImageCopyRasterWorkerPool::Shutdown"); |
| + |
| + TaskGraph empty; |
| + task_graph_runner_->ScheduleTasks(namespace_token_, &empty); |
| + task_graph_runner_->WaitForTasksToFinishRunning(namespace_token_); |
| +} |
| + |
| +void ImageCopyRasterWorkerPool::ScheduleTasks(RasterTaskQueue* queue) { |
| + TRACE_EVENT0("cc", "ImageCopyRasterWorkerPool::ScheduleTasks"); |
| + |
| + DCHECK_EQ(queue->required_for_activation_count, |
| + static_cast<size_t>( |
| + std::count_if(queue->items.begin(), |
| + queue->items.end(), |
| + RasterTaskQueue::Item::IsRequiredForActivation))); |
| + |
| + if (!raster_tasks_pending_) |
| + TRACE_EVENT_ASYNC_BEGIN0("cc", "ScheduledTasks", this); |
| + |
| + raster_tasks_pending_ = true; |
| + raster_tasks_required_for_activation_pending_ = true; |
| + |
| + unsigned priority = kRasterTaskPriorityBase; |
| + |
| + graph_.Reset(); |
| + |
| + // Cancel existing OnRasterFinished callbacks. |
| + raster_finished_weak_ptr_factory_.InvalidateWeakPtrs(); |
| + |
| + scoped_refptr<RasterizerTask> |
| + new_raster_required_for_activation_finished_task( |
| + CreateRasterRequiredForActivationFinishedTask( |
| + queue->required_for_activation_count, |
| + task_runner_.get(), |
| + base::Bind(&ImageCopyRasterWorkerPool:: |
| + OnRasterRequiredForActivationFinished, |
| + raster_finished_weak_ptr_factory_.GetWeakPtr()))); |
| + scoped_refptr<RasterizerTask> new_raster_finished_task( |
| + CreateRasterFinishedTask( |
| + task_runner_.get(), |
| + base::Bind(&ImageCopyRasterWorkerPool::OnRasterFinished, |
| + raster_finished_weak_ptr_factory_.GetWeakPtr()))); |
| + |
| + resource_pool_->CheckBusyResources(); |
| + |
| + for (RasterTaskQueue::Item::Vector::const_iterator it = queue->items.begin(); |
| + it != queue->items.end(); |
| + ++it) { |
| + const RasterTaskQueue::Item& item = *it; |
| + RasterTask* task = item.task; |
| + DCHECK(!task->HasCompleted()); |
| + |
| + if (item.required_for_activation) { |
| + graph_.edges.push_back(TaskGraph::Edge( |
| + task, new_raster_required_for_activation_finished_task.get())); |
| + } |
| + |
| + InsertNodesForRasterTask(&graph_, task, task->dependencies(), priority++); |
| + |
| + graph_.edges.push_back( |
| + TaskGraph::Edge(task, new_raster_finished_task.get())); |
| + } |
| + |
| + InsertNodeForTask(&graph_, |
| + new_raster_required_for_activation_finished_task.get(), |
| + kRasterRequiredForActivationFinishedTaskPriority, |
| + queue->required_for_activation_count); |
| + InsertNodeForTask(&graph_, |
| + new_raster_finished_task.get(), |
| + kRasterFinishedTaskPriority, |
| + queue->items.size()); |
| + |
| + ScheduleTasksOnOriginThread(this, &graph_); |
| + task_graph_runner_->ScheduleTasks(namespace_token_, &graph_); |
| + |
| + raster_finished_task_ = new_raster_finished_task; |
| + raster_required_for_activation_finished_task_ = |
| + new_raster_required_for_activation_finished_task; |
| + |
| + resource_pool_->ReduceResourceUsage(); |
| + |
| + TRACE_EVENT_ASYNC_STEP_INTO1( |
| + "cc", |
| + "ScheduledTasks", |
| + this, |
| + "rasterizing", |
| + "state", |
| + TracedValue::FromValue(StateAsValue().release())); |
| +} |
| + |
| +void ImageCopyRasterWorkerPool::CheckForCompletedTasks() { |
| + TRACE_EVENT0("cc", "ImageCopyRasterWorkerPool::CheckForCompletedTasks"); |
| + |
| + task_graph_runner_->CollectCompletedTasks(namespace_token_, |
| + &completed_tasks_); |
| + for (Task::Vector::const_iterator it = completed_tasks_.begin(); |
| + it != completed_tasks_.end(); |
| + ++it) { |
| + RasterizerTask* task = static_cast<RasterizerTask*>(it->get()); |
| + |
| + task->WillComplete(); |
| + task->CompleteOnOriginThread(this); |
| + task->DidComplete(); |
| + |
| + task->RunReplyOnOriginThread(); |
| + } |
| + completed_tasks_.clear(); |
| + |
| + FlushCopies(); |
| +} |
| + |
| +SkCanvas* ImageCopyRasterWorkerPool::AcquireCanvasForRaster(RasterTask* task) { |
| + DCHECK_EQ(task->resource()->format(), resource_pool_->resource_format()); |
| + scoped_ptr<ScopedResource> resource( |
| + resource_pool_->AcquireResource(task->resource()->size())); |
| + SkCanvas* canvas = resource_provider_->MapImageRasterBuffer(resource->id()); |
| + DCHECK(std::find_if(raster_task_states_.begin(), |
| + raster_task_states_.end(), |
| + RasterTaskState::TaskComparator(task)) == |
| + raster_task_states_.end()); |
| + raster_task_states_.push_back(RasterTaskState(task, resource.release())); |
| + return canvas; |
| +} |
| + |
| +void ImageCopyRasterWorkerPool::ReleaseCanvasForRaster(RasterTask* task) { |
| + RasterTaskState::Vector::iterator it = |
| + std::find_if(raster_task_states_.begin(), |
| + raster_task_states_.end(), |
| + RasterTaskState::TaskComparator(task)); |
| + DCHECK(it != raster_task_states_.end()); |
| + scoped_ptr<ScopedResource> resource(it->resource); |
| + std::swap(*it, raster_task_states_.back()); |
| + raster_task_states_.pop_back(); |
| + |
| + bool content_has_changed = |
| + resource_provider_->UnmapImageRasterBuffer(resource->id()); |
| + |
| + // |content_has_changed| can be false as result of task being canceled or |
| + // task implementation deciding not to modify bitmap (ie. analysis of raster |
| + // commands detected content as a solid color). |
| + if (content_has_changed) { |
| + resource_provider_->CopyResource(resource->id(), task->resource()->id()); |
| + has_performed_copy_since_last_flush_ = true; |
| + } |
| + |
| + resource_pool_->ReleaseResource(resource.Pass()); |
|
vmpstr
2014/04/23 17:25:46
Will this do the right thing if copy is in progres
reveman
2014/04/24 19:20:43
Yes, the resource will be busy until the sync quer
|
| +} |
| + |
| +void ImageCopyRasterWorkerPool::OnRasterFinished() { |
| + TRACE_EVENT0("cc", "ImageCopyRasterWorkerPool::OnRasterFinished"); |
| + |
| + DCHECK(raster_tasks_pending_); |
| + raster_tasks_pending_ = false; |
| + TRACE_EVENT_ASYNC_END0("cc", "ScheduledTasks", this); |
| + client_->DidFinishRunningTasks(); |
| +} |
| + |
| +void ImageCopyRasterWorkerPool::OnRasterRequiredForActivationFinished() { |
| + TRACE_EVENT0( |
| + "cc", "ImageCopyRasterWorkerPool::OnRasterRequiredForActivationFinished"); |
| + |
| + DCHECK(raster_tasks_required_for_activation_pending_); |
| + raster_tasks_required_for_activation_pending_ = false; |
| + TRACE_EVENT_ASYNC_STEP_INTO1( |
| + "cc", |
| + "ScheduledTasks", |
| + this, |
| + "rasterizing", |
| + "state", |
| + TracedValue::FromValue(StateAsValue().release())); |
| + client_->DidFinishRunningTasksRequiredForActivation(); |
| +} |
| + |
| +void ImageCopyRasterWorkerPool::FlushCopies() { |
| + if (!has_performed_copy_since_last_flush_) |
| + return; |
| + |
| + resource_provider_->ShallowFlushIfSupported(); |
| + has_performed_copy_since_last_flush_ = false; |
| +} |
| + |
| +scoped_ptr<base::Value> ImageCopyRasterWorkerPool::StateAsValue() const { |
| + scoped_ptr<base::DictionaryValue> state(new base::DictionaryValue); |
| + |
| + state->SetInteger("pending_count", raster_task_states_.size()); |
| + state->SetBoolean("tasks_required_for_activation_pending", |
| + raster_tasks_required_for_activation_pending_); |
| + state->Set("staging_state", StagingStateAsValue().release()); |
| + |
| + return state.PassAs<base::Value>(); |
| +} |
| +scoped_ptr<base::Value> ImageCopyRasterWorkerPool::StagingStateAsValue() const { |
| + scoped_ptr<base::DictionaryValue> staging_state(new base::DictionaryValue); |
| + |
| + staging_state->SetInteger("staging_resource_count", |
| + resource_pool_->total_resource_count()); |
| + staging_state->SetInteger("bytes_used_for_staging_resources", |
| + resource_pool_->total_memory_usage_bytes()); |
| + staging_state->SetInteger("pending_copy_count", |
| + resource_pool_->total_resource_count() - |
| + resource_pool_->acquired_resource_count()); |
| + staging_state->SetInteger("bytes_pending_copy", |
| + resource_pool_->total_memory_usage_bytes() - |
| + resource_pool_->acquired_memory_usage_bytes()); |
| + |
| + return staging_state.PassAs<base::Value>(); |
| +} |
| + |
| +} // namespace cc |