1 // Copyright 2014 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/one_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_pool.h" 15 #include "cc/resources/scoped_resource.h" 16 #include "gpu/command_buffer/client/gles2_interface.h" 17 #include "third_party/skia/include/utils/SkNullCanvas.h" 18 19 namespace cc { 20 namespace { 21 22 class RasterBufferImpl : public RasterBuffer { 23 public: 24 RasterBufferImpl(ResourceProvider* resource_provider, 25 ResourcePool* resource_pool, 26 const Resource* resource) 27 : resource_provider_(resource_provider), 28 resource_pool_(resource_pool), 29 resource_(resource), 30 raster_resource_(resource_pool->AcquireResource(resource->size())), 31 buffer_(NULL), 32 stride_(0) { 33 // Acquire and map image for raster resource. 34 resource_provider_->AcquireImage(raster_resource_->id()); 35 buffer_ = resource_provider_->MapImage(raster_resource_->id(), &stride_); 36 } 37 38 virtual ~RasterBufferImpl() { 39 // First unmap image for raster resource. 40 resource_provider_->UnmapImage(raster_resource_->id()); 41 42 // Copy contents of raster resource to |resource_|. 43 resource_provider_->CopyResource(raster_resource_->id(), resource_->id()); 44 45 // This RasterBuffer implementation provides direct access to the memory 46 // used by the GPU. Read lock fences are required to ensure that we're not 47 // trying to map a resource that is currently in-use by the GPU. 48 resource_provider_->EnableReadLockFences(raster_resource_->id()); 49 50 // Return raster resource to pool so it can be used by another RasterBuffer 51 // instance. 52 resource_pool_->ReleaseResource(raster_resource_.Pass()); 53 } 54 55 // Overridden from RasterBuffer: 56 virtual skia::RefPtr<SkCanvas> AcquireSkCanvas() OVERRIDE { 57 if (!buffer_) 58 return skia::AdoptRef(SkCreateNullCanvas()); 59 60 RasterWorkerPool::AcquireBitmapForBuffer( 61 &bitmap_, buffer_, resource_->format(), resource_->size(), stride_); 62 return skia::AdoptRef(new SkCanvas(bitmap_)); 63 } 64 virtual void ReleaseSkCanvas(const skia::RefPtr<SkCanvas>& canvas) OVERRIDE { 65 if (!buffer_) 66 return; 67 68 RasterWorkerPool::ReleaseBitmapForBuffer( 69 &bitmap_, buffer_, resource_->format()); 70 } 71 72 private: 73 ResourceProvider* resource_provider_; 74 ResourcePool* resource_pool_; 75 const Resource* resource_; 76 scoped_ptr<ScopedResource> raster_resource_; 77 uint8_t* buffer_; 78 int stride_; 79 SkBitmap bitmap_; 80 81 DISALLOW_COPY_AND_ASSIGN(RasterBufferImpl); 82 }; 83 84 } // namespace 85 86 // static 87 scoped_ptr<RasterWorkerPool> OneCopyRasterWorkerPool::Create( 88 base::SequencedTaskRunner* task_runner, 89 TaskGraphRunner* task_graph_runner, 90 ContextProvider* context_provider, 91 ResourceProvider* resource_provider, 92 ResourcePool* resource_pool) { 93 return make_scoped_ptr<RasterWorkerPool>( 94 new OneCopyRasterWorkerPool(task_runner, 95 task_graph_runner, 96 context_provider, 97 resource_provider, 98 resource_pool)); 99 } 100 101 OneCopyRasterWorkerPool::OneCopyRasterWorkerPool( 102 base::SequencedTaskRunner* task_runner, 103 TaskGraphRunner* task_graph_runner, 104 ContextProvider* context_provider, 105 ResourceProvider* resource_provider, 106 ResourcePool* resource_pool) 107 : task_runner_(task_runner), 108 task_graph_runner_(task_graph_runner), 109 namespace_token_(task_graph_runner->GetNamespaceToken()), 110 context_provider_(context_provider), 111 resource_provider_(resource_provider), 112 resource_pool_(resource_pool), 113 raster_finished_weak_ptr_factory_(this) { 114 DCHECK(context_provider_); 115 } 116 117 OneCopyRasterWorkerPool::~OneCopyRasterWorkerPool() { 118 } 119 120 Rasterizer* OneCopyRasterWorkerPool::AsRasterizer() { 121 return this; 122 } 123 124 void OneCopyRasterWorkerPool::SetClient(RasterizerClient* client) { 125 client_ = client; 126 } 127 128 void OneCopyRasterWorkerPool::Shutdown() { 129 TRACE_EVENT0("cc", "OneCopyRasterWorkerPool::Shutdown"); 130 131 TaskGraph empty; 132 task_graph_runner_->ScheduleTasks(namespace_token_, &empty); 133 task_graph_runner_->WaitForTasksToFinishRunning(namespace_token_); 134 } 135 136 void OneCopyRasterWorkerPool::ScheduleTasks(RasterTaskQueue* queue) { 137 TRACE_EVENT0("cc", "OneCopyRasterWorkerPool::ScheduleTasks"); 138 139 if (raster_pending_.none()) 140 TRACE_EVENT_ASYNC_BEGIN0("cc", "ScheduledTasks", this); 141 142 // Mark all task sets as pending. 143 raster_pending_.set(); 144 145 unsigned priority = kRasterTaskPriorityBase; 146 147 graph_.Reset(); 148 149 // Cancel existing OnRasterFinished callbacks. 150 raster_finished_weak_ptr_factory_.InvalidateWeakPtrs(); 151 152 scoped_refptr<RasterizerTask> new_raster_finished_tasks[kNumberOfTaskSets]; 153 154 size_t task_count[kNumberOfTaskSets] = {0}; 155 156 for (TaskSet task_set = 0; task_set < kNumberOfTaskSets; ++task_set) { 157 new_raster_finished_tasks[task_set] = CreateRasterFinishedTask( 158 task_runner_.get(), 159 base::Bind(&OneCopyRasterWorkerPool::OnRasterFinished, 160 raster_finished_weak_ptr_factory_.GetWeakPtr(), 161 task_set)); 162 } 163 164 resource_pool_->CheckBusyResources(); 165 166 for (RasterTaskQueue::Item::Vector::const_iterator it = queue->items.begin(); 167 it != queue->items.end(); 168 ++it) { 169 const RasterTaskQueue::Item& item = *it; 170 RasterTask* task = item.task; 171 DCHECK(!task->HasCompleted()); 172 173 for (TaskSet task_set = 0; task_set < kNumberOfTaskSets; ++task_set) { 174 if (!item.task_sets[task_set]) 175 continue; 176 177 ++task_count[task_set]; 178 179 graph_.edges.push_back( 180 TaskGraph::Edge(task, new_raster_finished_tasks[task_set].get())); 181 } 182 183 InsertNodesForRasterTask(&graph_, task, task->dependencies(), priority++); 184 } 185 186 for (TaskSet task_set = 0; task_set < kNumberOfTaskSets; ++task_set) { 187 InsertNodeForTask(&graph_, 188 new_raster_finished_tasks[task_set].get(), 189 kRasterFinishedTaskPriority, 190 task_count[task_set]); 191 } 192 193 ScheduleTasksOnOriginThread(this, &graph_); 194 task_graph_runner_->ScheduleTasks(namespace_token_, &graph_); 195 196 std::copy(new_raster_finished_tasks, 197 new_raster_finished_tasks + kNumberOfTaskSets, 198 raster_finished_tasks_); 199 200 resource_pool_->ReduceResourceUsage(); 201 202 TRACE_EVENT_ASYNC_STEP_INTO1( 203 "cc", "ScheduledTasks", this, "rasterizing", "state", StateAsValue()); 204 } 205 206 void OneCopyRasterWorkerPool::CheckForCompletedTasks() { 207 TRACE_EVENT0("cc", "OneCopyRasterWorkerPool::CheckForCompletedTasks"); 208 209 task_graph_runner_->CollectCompletedTasks(namespace_token_, 210 &completed_tasks_); 211 for (Task::Vector::const_iterator it = completed_tasks_.begin(); 212 it != completed_tasks_.end(); 213 ++it) { 214 RasterizerTask* task = static_cast<RasterizerTask*>(it->get()); 215 216 task->WillComplete(); 217 task->CompleteOnOriginThread(this); 218 task->DidComplete(); 219 220 task->RunReplyOnOriginThread(); 221 } 222 completed_tasks_.clear(); 223 224 context_provider_->ContextGL()->ShallowFlushCHROMIUM(); 225 } 226 227 scoped_ptr<RasterBuffer> OneCopyRasterWorkerPool::AcquireBufferForRaster( 228 const Resource* resource) { 229 DCHECK_EQ(resource->format(), resource_pool_->resource_format()); 230 return make_scoped_ptr<RasterBuffer>( 231 new RasterBufferImpl(resource_provider_, resource_pool_, resource)); 232 } 233 234 void OneCopyRasterWorkerPool::ReleaseBufferForRaster( 235 scoped_ptr<RasterBuffer> buffer) { 236 // Nothing to do here. RasterBufferImpl destructor cleans up after itself. 237 } 238 239 void OneCopyRasterWorkerPool::OnRasterFinished(TaskSet task_set) { 240 TRACE_EVENT1( 241 "cc", "OneCopyRasterWorkerPool::OnRasterFinished", "task_set", task_set); 242 243 DCHECK(raster_pending_[task_set]); 244 raster_pending_[task_set] = false; 245 if (raster_pending_.any()) { 246 TRACE_EVENT_ASYNC_STEP_INTO1( 247 "cc", "ScheduledTasks", this, "rasterizing", "state", StateAsValue()); 248 } else { 249 TRACE_EVENT_ASYNC_END0("cc", "ScheduledTasks", this); 250 } 251 client_->DidFinishRunningTasks(task_set); 252 } 253 254 scoped_refptr<base::debug::ConvertableToTraceFormat> 255 OneCopyRasterWorkerPool::StateAsValue() const { 256 scoped_refptr<base::debug::TracedValue> state = 257 new base::debug::TracedValue(); 258 259 state->BeginArray("tasks_pending"); 260 for (TaskSet task_set = 0; task_set < kNumberOfTaskSets; ++task_set) 261 state->AppendBoolean(raster_pending_[task_set]); 262 state->EndArray(); 263 state->BeginDictionary("staging_state"); 264 StagingStateAsValueInto(state.get()); 265 state->EndDictionary(); 266 267 return state; 268 } 269 void OneCopyRasterWorkerPool::StagingStateAsValueInto( 270 base::debug::TracedValue* staging_state) const { 271 staging_state->SetInteger("staging_resource_count", 272 resource_pool_->total_resource_count()); 273 staging_state->SetInteger("bytes_used_for_staging_resources", 274 resource_pool_->total_memory_usage_bytes()); 275 staging_state->SetInteger("pending_copy_count", 276 resource_pool_->total_resource_count() - 277 resource_pool_->acquired_resource_count()); 278 staging_state->SetInteger("bytes_pending_copy", 279 resource_pool_->total_memory_usage_bytes() - 280 resource_pool_->acquired_memory_usage_bytes()); 281 } 282 283 } // namespace cc 284