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 |