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. 4 5 #include "cc/resources/zero_copy_raster_worker_pool.h" 6 7 #include <algorithm> 8 9 #include "base/debug/trace_event.h" 10 #include "base/debug/trace_event_argument.h" 11 #include "base/strings/stringprintf.h" 12 #include "cc/debug/traced_value.h" 13 #include "cc/resources/raster_buffer.h" 14 #include "cc/resources/resource.h" 15 #include "third_party/skia/include/utils/SkNullCanvas.h" 16 17 namespace cc { 18 namespace { 19 20 class RasterBufferImpl : public RasterBuffer { 21 public: 22 RasterBufferImpl(ResourceProvider* resource_provider, 23 const Resource* resource) 24 : resource_provider_(resource_provider), 25 resource_(resource), 26 stride_(0), 27 buffer_(resource_provider->MapImage(resource->id(), &stride_)) {} 28 29 virtual ~RasterBufferImpl() { 30 resource_provider_->UnmapImage(resource_->id()); 31 32 // This RasterBuffer implementation provides direct access to the memory 33 // used by the GPU. Read lock fences are required to ensure that we're not 34 // trying to map a resource that is currently in-use by the GPU. 35 resource_provider_->EnableReadLockFences(resource_->id()); 36 } 37 38 // Overridden from RasterBuffer: 39 virtual skia::RefPtr<SkCanvas> AcquireSkCanvas() OVERRIDE { 40 if (!buffer_) 41 return skia::AdoptRef(SkCreateNullCanvas()); 42 43 RasterWorkerPool::AcquireBitmapForBuffer( 44 &bitmap_, buffer_, resource_->format(), resource_->size(), stride_); 45 return skia::AdoptRef(new SkCanvas(bitmap_)); 46 } 47 virtual void ReleaseSkCanvas(const skia::RefPtr<SkCanvas>& canvas) OVERRIDE { 48 if (!buffer_) 49 return; 50 51 RasterWorkerPool::ReleaseBitmapForBuffer( 52 &bitmap_, buffer_, resource_->format()); 53 } 54 55 private: 56 ResourceProvider* resource_provider_; 57 const Resource* resource_; 58 int stride_; 59 uint8_t* buffer_; 60 SkBitmap bitmap_; 61 62 DISALLOW_COPY_AND_ASSIGN(RasterBufferImpl); 63 }; 64 65 } // namespace 66 67 // static 68 scoped_ptr<RasterWorkerPool> ZeroCopyRasterWorkerPool::Create( 69 base::SequencedTaskRunner* task_runner, 70 TaskGraphRunner* task_graph_runner, 71 ResourceProvider* resource_provider) { 72 return make_scoped_ptr<RasterWorkerPool>(new ZeroCopyRasterWorkerPool( 73 task_runner, task_graph_runner, resource_provider)); 74 } 75 76 ZeroCopyRasterWorkerPool::ZeroCopyRasterWorkerPool( 77 base::SequencedTaskRunner* task_runner, 78 TaskGraphRunner* task_graph_runner, 79 ResourceProvider* resource_provider) 80 : task_runner_(task_runner), 81 task_graph_runner_(task_graph_runner), 82 namespace_token_(task_graph_runner->GetNamespaceToken()), 83 resource_provider_(resource_provider), 84 raster_finished_weak_ptr_factory_(this) { 85 } 86 87 ZeroCopyRasterWorkerPool::~ZeroCopyRasterWorkerPool() { 88 } 89 90 Rasterizer* ZeroCopyRasterWorkerPool::AsRasterizer() { 91 return this; 92 } 93 94 void ZeroCopyRasterWorkerPool::SetClient(RasterizerClient* client) { 95 client_ = client; 96 } 97 98 void ZeroCopyRasterWorkerPool::Shutdown() { 99 TRACE_EVENT0("cc", "ZeroCopyRasterWorkerPool::Shutdown"); 100 101 TaskGraph empty; 102 task_graph_runner_->ScheduleTasks(namespace_token_, &empty); 103 task_graph_runner_->WaitForTasksToFinishRunning(namespace_token_); 104 } 105 106 void ZeroCopyRasterWorkerPool::ScheduleTasks(RasterTaskQueue* queue) { 107 TRACE_EVENT0("cc", "ZeroCopyRasterWorkerPool::ScheduleTasks"); 108 109 if (raster_pending_.none()) 110 TRACE_EVENT_ASYNC_BEGIN0("cc", "ScheduledTasks", this); 111 112 // Mark all task sets as pending. 113 raster_pending_.set(); 114 115 unsigned priority = kRasterTaskPriorityBase; 116 117 graph_.Reset(); 118 119 // Cancel existing OnRasterFinished callbacks. 120 raster_finished_weak_ptr_factory_.InvalidateWeakPtrs(); 121 122 scoped_refptr<RasterizerTask> new_raster_finished_tasks[kNumberOfTaskSets]; 123 124 size_t task_count[kNumberOfTaskSets] = {0}; 125 126 for (TaskSet task_set = 0; task_set < kNumberOfTaskSets; ++task_set) { 127 new_raster_finished_tasks[task_set] = CreateRasterFinishedTask( 128 task_runner_.get(), 129 base::Bind(&ZeroCopyRasterWorkerPool::OnRasterFinished, 130 raster_finished_weak_ptr_factory_.GetWeakPtr(), 131 task_set)); 132 } 133 134 for (RasterTaskQueue::Item::Vector::const_iterator it = queue->items.begin(); 135 it != queue->items.end(); 136 ++it) { 137 const RasterTaskQueue::Item& item = *it; 138 RasterTask* task = item.task; 139 DCHECK(!task->HasCompleted()); 140 141 for (TaskSet task_set = 0; task_set < kNumberOfTaskSets; ++task_set) { 142 if (!item.task_sets[task_set]) 143 continue; 144 145 ++task_count[task_set]; 146 147 graph_.edges.push_back( 148 TaskGraph::Edge(task, new_raster_finished_tasks[task_set].get())); 149 } 150 151 InsertNodesForRasterTask(&graph_, task, task->dependencies(), priority++); 152 } 153 154 for (TaskSet task_set = 0; task_set < kNumberOfTaskSets; ++task_set) { 155 InsertNodeForTask(&graph_, 156 new_raster_finished_tasks[task_set].get(), 157 kRasterFinishedTaskPriority, 158 task_count[task_set]); 159 } 160 161 ScheduleTasksOnOriginThread(this, &graph_); 162 task_graph_runner_->ScheduleTasks(namespace_token_, &graph_); 163 164 std::copy(new_raster_finished_tasks, 165 new_raster_finished_tasks + kNumberOfTaskSets, 166 raster_finished_tasks_); 167 168 TRACE_EVENT_ASYNC_STEP_INTO1( 169 "cc", "ScheduledTasks", this, "rasterizing", "state", StateAsValue()); 170 } 171 172 void ZeroCopyRasterWorkerPool::CheckForCompletedTasks() { 173 TRACE_EVENT0("cc", "ZeroCopyRasterWorkerPool::CheckForCompletedTasks"); 174 175 task_graph_runner_->CollectCompletedTasks(namespace_token_, 176 &completed_tasks_); 177 for (Task::Vector::const_iterator it = completed_tasks_.begin(); 178 it != completed_tasks_.end(); 179 ++it) { 180 RasterizerTask* task = static_cast<RasterizerTask*>(it->get()); 181 182 task->WillComplete(); 183 task->CompleteOnOriginThread(this); 184 task->DidComplete(); 185 186 task->RunReplyOnOriginThread(); 187 } 188 completed_tasks_.clear(); 189 } 190 191 scoped_ptr<RasterBuffer> ZeroCopyRasterWorkerPool::AcquireBufferForRaster( 192 const Resource* resource) { 193 // RasterBuffer implementation depends on an image having been acquired for 194 // the resource. 195 resource_provider_->AcquireImage(resource->id()); 196 197 return make_scoped_ptr<RasterBuffer>( 198 new RasterBufferImpl(resource_provider_, resource)); 199 } 200 201 void ZeroCopyRasterWorkerPool::ReleaseBufferForRaster( 202 scoped_ptr<RasterBuffer> buffer) { 203 // Nothing to do here. RasterBufferImpl destructor cleans up after itself. 204 } 205 206 void ZeroCopyRasterWorkerPool::OnRasterFinished(TaskSet task_set) { 207 TRACE_EVENT1( 208 "cc", "ZeroCopyRasterWorkerPool::OnRasterFinished", "task_set", task_set); 209 210 DCHECK(raster_pending_[task_set]); 211 raster_pending_[task_set] = false; 212 if (raster_pending_.any()) { 213 TRACE_EVENT_ASYNC_STEP_INTO1( 214 "cc", "ScheduledTasks", this, "rasterizing", "state", StateAsValue()); 215 } else { 216 TRACE_EVENT_ASYNC_END0("cc", "ScheduledTasks", this); 217 } 218 client_->DidFinishRunningTasks(task_set); 219 } 220 221 scoped_refptr<base::debug::ConvertableToTraceFormat> 222 ZeroCopyRasterWorkerPool::StateAsValue() const { 223 scoped_refptr<base::debug::TracedValue> state = 224 new base::debug::TracedValue(); 225 226 state->BeginArray("tasks_pending"); 227 for (TaskSet task_set = 0; task_set < kNumberOfTaskSets; ++task_set) 228 state->AppendBoolean(raster_pending_[task_set]); 229 state->EndArray(); 230 return state; 231 } 232 233 } // namespace cc 234