OLD | NEW |
1 // Copyright 2013 The Chromium Authors. All rights reserved. | 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 | 2 // Use of this source code is governed by a BSD-style license that can be |
3 // found in the LICENSE file. | 3 // found in the LICENSE file. |
4 | 4 |
5 #include "cc/resources/pixel_buffer_raster_worker_pool.h" | 5 #include "cc/resources/pixel_buffer_raster_worker_pool.h" |
6 | 6 |
| 7 #include "base/containers/stack_container.h" |
7 #include "base/debug/trace_event.h" | 8 #include "base/debug/trace_event.h" |
| 9 #include "base/values.h" |
| 10 #include "cc/debug/traced_value.h" |
8 #include "cc/resources/resource.h" | 11 #include "cc/resources/resource.h" |
9 #include "third_party/skia/include/core/SkDevice.h" | 12 #include "third_party/skia/include/core/SkDevice.h" |
10 | 13 |
11 namespace cc { | 14 namespace cc { |
12 | 15 |
13 namespace { | 16 namespace { |
14 | 17 |
15 class PixelBufferWorkerPoolTaskImpl : public internal::WorkerPoolTask { | 18 class PixelBufferWorkerPoolTaskImpl : public internal::WorkerPoolTask { |
16 public: | 19 public: |
17 typedef base::Callback<void(bool was_canceled, bool needs_upload)> Reply; | 20 typedef base::Callback<void(bool was_canceled, bool needs_upload)> Reply; |
(...skipping 52 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
70 #else | 73 #else |
71 // For reference Chromebook Pixel can upload 1MB in about 0.5ms. | 74 // For reference Chromebook Pixel can upload 1MB in about 0.5ms. |
72 const size_t kMaxBytesUploadedPerMs = 1024 * 1024 * 2; | 75 const size_t kMaxBytesUploadedPerMs = 1024 * 1024 * 2; |
73 #endif | 76 #endif |
74 | 77 |
75 // Assuming a two frame deep pipeline. | 78 // Assuming a two frame deep pipeline. |
76 const size_t kMaxPendingUploadBytes = 16 * 2 * kMaxBytesUploadedPerMs; | 79 const size_t kMaxPendingUploadBytes = 16 * 2 * kMaxBytesUploadedPerMs; |
77 | 80 |
78 const int kCheckForCompletedRasterTasksDelayMs = 6; | 81 const int kCheckForCompletedRasterTasksDelayMs = 6; |
79 | 82 |
80 const size_t kMaxPendingRasterBytes = | 83 const size_t kMaxScheduledRasterTasks = 48; |
81 kMaxBytesUploadedPerMs * kCheckForCompletedRasterTasksDelayMs; | 84 |
| 85 typedef base::StackVector<internal::GraphNode*, |
| 86 kMaxScheduledRasterTasks> NodeVector; |
| 87 |
| 88 void AddDependenciesToGraphNode( |
| 89 internal::GraphNode* node, |
| 90 const NodeVector::ContainerType& dependencies) { |
| 91 for (NodeVector::ContainerType::const_iterator it = dependencies.begin(); |
| 92 it != dependencies.end(); ++it) { |
| 93 internal::GraphNode* dependency = *it; |
| 94 |
| 95 node->add_dependency(); |
| 96 dependency->add_dependent(node); |
| 97 } |
| 98 } |
82 | 99 |
83 } // namespace | 100 } // namespace |
84 | 101 |
85 PixelBufferRasterWorkerPool::PixelBufferRasterWorkerPool( | 102 PixelBufferRasterWorkerPool::PixelBufferRasterWorkerPool( |
86 ResourceProvider* resource_provider, | 103 ResourceProvider* resource_provider, |
87 size_t num_threads) : RasterWorkerPool(resource_provider, num_threads), | 104 size_t num_threads) |
88 shutdown_(false), | 105 : RasterWorkerPool(resource_provider, num_threads), |
89 bytes_pending_upload_(0), | 106 shutdown_(false), |
90 has_performed_uploads_since_last_flush_(false), | 107 scheduled_raster_task_count_(0), |
91 check_for_completed_raster_tasks_pending_(false) { | 108 bytes_pending_upload_(0), |
| 109 has_performed_uploads_since_last_flush_(false), |
| 110 check_for_completed_raster_tasks_pending_(false), |
| 111 should_notify_client_if_no_tasks_are_pending_(false), |
| 112 should_notify_client_if_no_tasks_required_for_activation_are_pending_( |
| 113 false) { |
92 } | 114 } |
93 | 115 |
94 PixelBufferRasterWorkerPool::~PixelBufferRasterWorkerPool() { | 116 PixelBufferRasterWorkerPool::~PixelBufferRasterWorkerPool() { |
95 DCHECK(shutdown_); | 117 DCHECK(shutdown_); |
96 DCHECK(!check_for_completed_raster_tasks_pending_); | 118 DCHECK(!check_for_completed_raster_tasks_pending_); |
97 DCHECK_EQ(0u, pixel_buffer_tasks_.size()); | 119 DCHECK_EQ(0u, pixel_buffer_tasks_.size()); |
98 DCHECK_EQ(0u, tasks_with_pending_upload_.size()); | 120 DCHECK_EQ(0u, tasks_with_pending_upload_.size()); |
99 DCHECK_EQ(0u, completed_tasks_.size()); | 121 DCHECK_EQ(0u, completed_tasks_.size()); |
100 } | 122 } |
101 | 123 |
102 void PixelBufferRasterWorkerPool::Shutdown() { | 124 void PixelBufferRasterWorkerPool::Shutdown() { |
103 shutdown_ = true; | 125 shutdown_ = true; |
104 RasterWorkerPool::Shutdown(); | 126 RasterWorkerPool::Shutdown(); |
105 CheckForCompletedRasterTasks(); | 127 RasterWorkerPool::CheckForCompletedTasks(); |
| 128 CheckForCompletedUploads(); |
| 129 check_for_completed_raster_tasks_callback_.Cancel(); |
| 130 check_for_completed_raster_tasks_pending_ = false; |
106 for (TaskMap::iterator it = pixel_buffer_tasks_.begin(); | 131 for (TaskMap::iterator it = pixel_buffer_tasks_.begin(); |
107 it != pixel_buffer_tasks_.end(); ++it) { | 132 it != pixel_buffer_tasks_.end(); ++it) { |
108 internal::RasterWorkerPoolTask* task = it->first; | 133 internal::RasterWorkerPoolTask* task = it->first; |
109 internal::WorkerPoolTask* pixel_buffer_task = it->second.get(); | 134 internal::WorkerPoolTask* pixel_buffer_task = it->second.get(); |
110 | 135 |
111 // All inactive tasks needs to be canceled. | 136 // All inactive tasks needs to be canceled. |
112 if (!pixel_buffer_task && !task->HasFinishedRunning()) { | 137 if (!pixel_buffer_task && !task->HasFinishedRunning()) { |
113 task->DidRun(true); | 138 task->DidRun(true); |
114 completed_tasks_.push_back(task); | 139 completed_tasks_.push_back(task); |
115 } | 140 } |
116 } | 141 } |
| 142 DCHECK_EQ(completed_tasks_.size(), pixel_buffer_tasks_.size()); |
117 } | 143 } |
118 | 144 |
119 void PixelBufferRasterWorkerPool::ScheduleTasks(RasterTask::Queue* queue) { | 145 void PixelBufferRasterWorkerPool::ScheduleTasks(RasterTask::Queue* queue) { |
120 TRACE_EVENT0("cc", "PixelBufferRasterWorkerPool::ScheduleTasks"); | 146 TRACE_EVENT0("cc", "PixelBufferRasterWorkerPool::ScheduleTasks"); |
121 | 147 |
122 RasterWorkerPool::SetRasterTasks(queue); | 148 RasterWorkerPool::SetRasterTasks(queue); |
123 | 149 |
| 150 if (!should_notify_client_if_no_tasks_are_pending_) |
| 151 TRACE_EVENT_ASYNC_BEGIN0("cc", "ScheduledTasks", this); |
| 152 |
| 153 should_notify_client_if_no_tasks_are_pending_ = true; |
| 154 should_notify_client_if_no_tasks_required_for_activation_are_pending_ = true; |
| 155 |
124 // Build new pixel buffer task set. | 156 // Build new pixel buffer task set. |
125 TaskMap new_pixel_buffer_tasks; | 157 TaskMap new_pixel_buffer_tasks; |
126 for (RasterTaskVector::const_iterator it = raster_tasks().begin(); | 158 for (RasterTaskVector::const_iterator it = raster_tasks().begin(); |
127 it != raster_tasks().end(); ++it) { | 159 it != raster_tasks().end(); ++it) { |
128 internal::RasterWorkerPoolTask* task = it->get(); | 160 internal::RasterWorkerPoolTask* task = it->get(); |
129 DCHECK(new_pixel_buffer_tasks.find(task) == new_pixel_buffer_tasks.end()); | 161 DCHECK(new_pixel_buffer_tasks.find(task) == new_pixel_buffer_tasks.end()); |
130 DCHECK(!task->HasCompleted()); | 162 DCHECK(!task->HasCompleted()); |
131 | 163 |
132 // Use existing pixel buffer task if available. | 164 // Use existing pixel buffer task if available. |
133 TaskMap::iterator pixel_buffer_it = pixel_buffer_tasks_.find(task); | 165 TaskMap::iterator pixel_buffer_it = pixel_buffer_tasks_.find(task); |
(...skipping 19 matching lines...) Expand all Loading... |
153 // Inactive task can be canceled. | 185 // Inactive task can be canceled. |
154 if (!pixel_buffer_task && !task->HasFinishedRunning()) { | 186 if (!pixel_buffer_task && !task->HasFinishedRunning()) { |
155 task->DidRun(true); | 187 task->DidRun(true); |
156 DCHECK(std::find(completed_tasks_.begin(), | 188 DCHECK(std::find(completed_tasks_.begin(), |
157 completed_tasks_.end(), | 189 completed_tasks_.end(), |
158 task) == completed_tasks_.end()); | 190 task) == completed_tasks_.end()); |
159 completed_tasks_.push_back(task); | 191 completed_tasks_.push_back(task); |
160 } | 192 } |
161 } | 193 } |
162 | 194 |
| 195 tasks_required_for_activation_.clear(); |
| 196 for (TaskMap::iterator it = new_pixel_buffer_tasks.begin(); |
| 197 it != new_pixel_buffer_tasks.end(); ++it) { |
| 198 internal::RasterWorkerPoolTask* task = it->first; |
| 199 if (IsRasterTaskRequiredForActivation(task)) |
| 200 tasks_required_for_activation_.insert(task); |
| 201 } |
| 202 |
163 pixel_buffer_tasks_.swap(new_pixel_buffer_tasks); | 203 pixel_buffer_tasks_.swap(new_pixel_buffer_tasks); |
164 | 204 |
165 // This will schedule more tasks after checking for completed raster | 205 // Check for completed tasks when ScheduleTasks() is called as |
166 // tasks. It's worth checking for completed tasks when ScheduleTasks() | 206 // priorities might have changed and this maximizes the number |
167 // is called as priorities might have changed and this allows us to | 207 // of top priority tasks that are scheduled. |
168 // schedule as many new top priority tasks as possible. | 208 RasterWorkerPool::CheckForCompletedTasks(); |
169 CheckForCompletedRasterTasks(); | 209 CheckForCompletedUploads(); |
| 210 FlushUploads(); |
| 211 |
| 212 // Schedule new tasks. |
| 213 ScheduleMoreTasks(); |
| 214 |
| 215 // Cancel any pending check for completed raster tasks and schedule |
| 216 // another check. |
| 217 check_for_completed_raster_tasks_callback_.Cancel(); |
| 218 check_for_completed_raster_tasks_pending_ = false; |
| 219 ScheduleCheckForCompletedRasterTasks(); |
| 220 |
| 221 TRACE_EVENT_ASYNC_STEP1( |
| 222 "cc", "ScheduledTasks", this, StateName(), |
| 223 "state", TracedValue::FromValue(StateAsValue().release())); |
170 } | 224 } |
171 | 225 |
172 void PixelBufferRasterWorkerPool::CheckForCompletedTasks() { | 226 void PixelBufferRasterWorkerPool::CheckForCompletedTasks() { |
173 TRACE_EVENT0("cc", "PixelBufferRasterWorkerPool::CheckForCompletedTasks"); | 227 TRACE_EVENT0("cc", "PixelBufferRasterWorkerPool::CheckForCompletedTasks"); |
174 | 228 |
175 RasterWorkerPool::CheckForCompletedTasks(); | 229 RasterWorkerPool::CheckForCompletedTasks(); |
176 CheckForCompletedUploads(); | 230 CheckForCompletedUploads(); |
177 FlushUploads(); | 231 FlushUploads(); |
178 | 232 |
179 while (!completed_tasks_.empty()) { | 233 TaskDeque completed_tasks; |
180 internal::RasterWorkerPoolTask* task = completed_tasks_.front().get(); | 234 completed_tasks_.swap(completed_tasks); |
| 235 |
| 236 while (!completed_tasks.empty()) { |
| 237 internal::RasterWorkerPoolTask* task = completed_tasks.front().get(); |
181 DCHECK(pixel_buffer_tasks_.find(task) != pixel_buffer_tasks_.end()); | 238 DCHECK(pixel_buffer_tasks_.find(task) != pixel_buffer_tasks_.end()); |
182 | 239 |
183 pixel_buffer_tasks_.erase(task); | 240 pixel_buffer_tasks_.erase(task); |
184 | 241 |
185 task->WillComplete(); | 242 task->WillComplete(); |
186 task->CompleteOnOriginThread(); | 243 task->CompleteOnOriginThread(); |
187 task->DidComplete(); | 244 task->DidComplete(); |
188 | 245 |
189 completed_tasks_.pop_front(); | 246 completed_tasks.pop_front(); |
190 } | 247 } |
191 } | 248 } |
192 | 249 |
193 void PixelBufferRasterWorkerPool::OnRasterTasksFinished() { | 250 void PixelBufferRasterWorkerPool::OnRasterTasksFinished() { |
194 // Call CheckForCompletedTasks() when we've finished running all raster | 251 // |should_notify_client_if_no_tasks_are_pending_| can be set to false as |
195 // tasks needed since last time ScheduleMoreTasks() was called. This | 252 // a result of a scheduled CheckForCompletedRasterTasks() call. No need to |
196 // reduces latency when processing only a small number of raster tasks. | 253 // perform another check in that case as we've already notified the client. |
| 254 if (!should_notify_client_if_no_tasks_are_pending_) |
| 255 return; |
| 256 |
| 257 // Call CheckForCompletedRasterTasks() when we've finished running all |
| 258 // raster tasks needed since last time ScheduleTasks() was called. |
| 259 // This reduces latency between the time when all tasks have finished |
| 260 // running and the time when the client is notified. |
197 CheckForCompletedRasterTasks(); | 261 CheckForCompletedRasterTasks(); |
198 } | 262 } |
199 | 263 |
| 264 void PixelBufferRasterWorkerPool::OnRasterTasksRequiredForActivationFinished() { |
| 265 // Analogous to OnRasterTasksFinished(), there's no need to call |
| 266 // CheckForCompletedRasterTasks() if the client has already been notified. |
| 267 if (!should_notify_client_if_no_tasks_required_for_activation_are_pending_) |
| 268 return; |
| 269 |
| 270 // This reduces latency between the time when all tasks required for |
| 271 // activation have finished running and the time when the client is |
| 272 // notified. |
| 273 CheckForCompletedRasterTasks(); |
| 274 } |
| 275 |
200 void PixelBufferRasterWorkerPool::FlushUploads() { | 276 void PixelBufferRasterWorkerPool::FlushUploads() { |
201 if (!has_performed_uploads_since_last_flush_) | 277 if (!has_performed_uploads_since_last_flush_) |
202 return; | 278 return; |
203 | 279 |
204 resource_provider()->ShallowFlushIfSupported(); | 280 resource_provider()->ShallowFlushIfSupported(); |
205 has_performed_uploads_since_last_flush_ = false; | 281 has_performed_uploads_since_last_flush_ = false; |
206 } | 282 } |
207 | 283 |
208 void PixelBufferRasterWorkerPool::CheckForCompletedUploads() { | 284 void PixelBufferRasterWorkerPool::CheckForCompletedUploads() { |
209 TaskDeque tasks_with_completed_uploads; | 285 TaskDeque tasks_with_completed_uploads; |
(...skipping 55 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
265 | 341 |
266 bytes_pending_upload_ -= task->resource()->bytes(); | 342 bytes_pending_upload_ -= task->resource()->bytes(); |
267 | 343 |
268 task->DidRun(false); | 344 task->DidRun(false); |
269 | 345 |
270 DCHECK(std::find(completed_tasks_.begin(), | 346 DCHECK(std::find(completed_tasks_.begin(), |
271 completed_tasks_.end(), | 347 completed_tasks_.end(), |
272 task) == completed_tasks_.end()); | 348 task) == completed_tasks_.end()); |
273 completed_tasks_.push_back(task); | 349 completed_tasks_.push_back(task); |
274 | 350 |
| 351 tasks_required_for_activation_.erase(task); |
| 352 |
275 tasks_with_completed_uploads.pop_front(); | 353 tasks_with_completed_uploads.pop_front(); |
276 } | 354 } |
277 } | 355 } |
278 | 356 |
279 void PixelBufferRasterWorkerPool::ScheduleCheckForCompletedRasterTasks() { | 357 void PixelBufferRasterWorkerPool::ScheduleCheckForCompletedRasterTasks() { |
280 if (check_for_completed_raster_tasks_pending_) | 358 if (check_for_completed_raster_tasks_pending_) |
281 return; | 359 return; |
282 | 360 |
283 check_for_completed_raster_tasks_callback_.Reset( | 361 check_for_completed_raster_tasks_callback_.Reset( |
284 base::Bind(&PixelBufferRasterWorkerPool::CheckForCompletedRasterTasks, | 362 base::Bind(&PixelBufferRasterWorkerPool::CheckForCompletedRasterTasks, |
285 base::Unretained(this))); | 363 base::Unretained(this))); |
286 base::MessageLoopProxy::current()->PostDelayedTask( | 364 base::MessageLoopProxy::current()->PostDelayedTask( |
287 FROM_HERE, | 365 FROM_HERE, |
288 check_for_completed_raster_tasks_callback_.callback(), | 366 check_for_completed_raster_tasks_callback_.callback(), |
289 base::TimeDelta::FromMilliseconds(kCheckForCompletedRasterTasksDelayMs)); | 367 base::TimeDelta::FromMilliseconds(kCheckForCompletedRasterTasksDelayMs)); |
290 check_for_completed_raster_tasks_pending_ = true; | 368 check_for_completed_raster_tasks_pending_ = true; |
291 } | 369 } |
292 | 370 |
293 void PixelBufferRasterWorkerPool::CheckForCompletedRasterTasks() { | 371 void PixelBufferRasterWorkerPool::CheckForCompletedRasterTasks() { |
294 TRACE_EVENT0( | 372 TRACE_EVENT0( |
295 "cc", "PixelBufferRasterWorkerPool::CheckForCompletedRasterTasks"); | 373 "cc", "PixelBufferRasterWorkerPool::CheckForCompletedRasterTasks"); |
296 | 374 |
| 375 DCHECK(should_notify_client_if_no_tasks_are_pending_); |
| 376 |
297 check_for_completed_raster_tasks_callback_.Cancel(); | 377 check_for_completed_raster_tasks_callback_.Cancel(); |
298 check_for_completed_raster_tasks_pending_ = false; | 378 check_for_completed_raster_tasks_pending_ = false; |
299 | 379 |
300 RasterWorkerPool::CheckForCompletedTasks(); | 380 RasterWorkerPool::CheckForCompletedTasks(); |
301 CheckForCompletedUploads(); | 381 CheckForCompletedUploads(); |
302 FlushUploads(); | 382 FlushUploads(); |
303 | 383 |
304 ScheduleMoreTasks(); | 384 // Determine what client notifications to generate. |
| 385 bool will_notify_client_that_no_tasks_required_for_activation_are_pending = |
| 386 (should_notify_client_if_no_tasks_required_for_activation_are_pending_ && |
| 387 !HasPendingTasksRequiredForActivation()); |
| 388 bool will_notify_client_that_no_tasks_are_pending = |
| 389 (should_notify_client_if_no_tasks_are_pending_ && |
| 390 !HasPendingTasks()); |
305 | 391 |
306 // Make sure another check for completed uploads is scheduled | 392 // Adjust the need to generate notifications before scheduling more tasks. |
307 // while there is still pending uploads left. | 393 should_notify_client_if_no_tasks_required_for_activation_are_pending_ &= |
308 if (!tasks_with_pending_upload_.empty()) | 394 !will_notify_client_that_no_tasks_required_for_activation_are_pending; |
| 395 should_notify_client_if_no_tasks_are_pending_ &= |
| 396 !will_notify_client_that_no_tasks_are_pending; |
| 397 |
| 398 if (PendingRasterTaskCount()) |
| 399 ScheduleMoreTasks(); |
| 400 |
| 401 TRACE_EVENT_ASYNC_STEP1( |
| 402 "cc", "ScheduledTasks", this, StateName(), |
| 403 "state", TracedValue::FromValue(StateAsValue().release())); |
| 404 |
| 405 // Schedule another check for completed raster tasks while there are |
| 406 // pending raster tasks or pending uploads. |
| 407 if (HasPendingTasks()) |
309 ScheduleCheckForCompletedRasterTasks(); | 408 ScheduleCheckForCompletedRasterTasks(); |
| 409 |
| 410 // Generate client notifications. |
| 411 if (will_notify_client_that_no_tasks_required_for_activation_are_pending) |
| 412 client()->DidFinishedRunningTasksRequiredForActivation(); |
| 413 if (will_notify_client_that_no_tasks_are_pending) { |
| 414 TRACE_EVENT_ASYNC_END0("cc", "ScheduledTasks", this); |
| 415 client()->DidFinishedRunningTasks(); |
| 416 } |
310 } | 417 } |
311 | 418 |
312 void PixelBufferRasterWorkerPool::ScheduleMoreTasks() { | 419 void PixelBufferRasterWorkerPool::ScheduleMoreTasks() { |
313 TRACE_EVENT0("cc", "PixelBufferRasterWorkerPool::ScheduleMoreTasks"); | 420 TRACE_EVENT0("cc", "PixelBufferRasterWorkerPool::ScheduleMoreTasks"); |
314 | 421 |
| 422 enum RasterTaskType { |
| 423 PREPAINT_TYPE = 0, |
| 424 REQUIRED_FOR_ACTIVATION_TYPE = 1, |
| 425 NUM_TYPES = 2 |
| 426 }; |
| 427 NodeVector tasks[NUM_TYPES]; |
| 428 unsigned priority = 2u; // 0-1 reserved for RasterFinished tasks. |
| 429 TaskGraph graph; |
| 430 |
315 size_t bytes_pending_upload = bytes_pending_upload_; | 431 size_t bytes_pending_upload = bytes_pending_upload_; |
316 size_t bytes_pending_raster = 0; | |
317 | 432 |
318 RasterTaskGraph graph; | |
319 for (RasterTaskVector::const_iterator it = raster_tasks().begin(); | 433 for (RasterTaskVector::const_iterator it = raster_tasks().begin(); |
320 it != raster_tasks().end(); ++it) { | 434 it != raster_tasks().end(); ++it) { |
321 internal::RasterWorkerPoolTask* task = it->get(); | 435 internal::RasterWorkerPoolTask* task = it->get(); |
322 | 436 |
323 // |pixel_buffer_tasks_| contains all tasks that have not yet completed. | 437 // |pixel_buffer_tasks_| contains all tasks that have not yet completed. |
324 TaskMap::iterator pixel_buffer_it = pixel_buffer_tasks_.find(task); | 438 TaskMap::iterator pixel_buffer_it = pixel_buffer_tasks_.find(task); |
325 if (pixel_buffer_it == pixel_buffer_tasks_.end()) | 439 if (pixel_buffer_it == pixel_buffer_tasks_.end()) |
326 continue; | 440 continue; |
327 | 441 |
328 // HasFinishedRunning() will return true when set pixels has completed. | 442 // HasFinishedRunning() will return true when set pixels has completed. |
(...skipping 11 matching lines...) Expand all Loading... |
340 break; | 454 break; |
341 | 455 |
342 internal::WorkerPoolTask* pixel_buffer_task = pixel_buffer_it->second.get(); | 456 internal::WorkerPoolTask* pixel_buffer_task = pixel_buffer_it->second.get(); |
343 | 457 |
344 // If raster has finished, just update |bytes_pending_upload|. | 458 // If raster has finished, just update |bytes_pending_upload|. |
345 if (pixel_buffer_task && pixel_buffer_task->HasCompleted()) { | 459 if (pixel_buffer_task && pixel_buffer_task->HasCompleted()) { |
346 bytes_pending_upload = new_bytes_pending_upload; | 460 bytes_pending_upload = new_bytes_pending_upload; |
347 continue; | 461 continue; |
348 } | 462 } |
349 | 463 |
350 // Throttle raster tasks based on bytes pending if raster has not | 464 // Throttle raster tasks based on kMaxScheduledRasterTasks. |
351 // finished. | 465 size_t scheduled_raster_task_count = |
352 size_t new_bytes_pending_raster = bytes_pending_raster; | 466 tasks[PREPAINT_TYPE].container().size() + |
353 new_bytes_pending_raster += task->resource()->bytes(); | 467 tasks[REQUIRED_FOR_ACTIVATION_TYPE].container().size(); |
354 if (new_bytes_pending_raster > kMaxPendingRasterBytes) | 468 if (scheduled_raster_task_count >= kMaxScheduledRasterTasks) |
355 break; | 469 break; |
356 | 470 |
357 // Update both |bytes_pending_raster| and |bytes_pending_upload| | 471 // Update |bytes_pending_upload| now that task has cleared all |
358 // now that task has cleared all throttling limits. | 472 // throttling limits. |
359 bytes_pending_raster = new_bytes_pending_raster; | |
360 bytes_pending_upload = new_bytes_pending_upload; | 473 bytes_pending_upload = new_bytes_pending_upload; |
361 | 474 |
| 475 RasterTaskType type = IsRasterTaskRequiredForActivation(task) ? |
| 476 REQUIRED_FOR_ACTIVATION_TYPE : |
| 477 PREPAINT_TYPE; |
| 478 |
362 // Use existing pixel buffer task if available. | 479 // Use existing pixel buffer task if available. |
363 if (pixel_buffer_task) { | 480 if (pixel_buffer_task) { |
364 graph.InsertRasterTask(pixel_buffer_task, task->dependencies()); | 481 tasks[type].container().push_back( |
| 482 CreateGraphNodeForRasterTask(pixel_buffer_task, |
| 483 task->dependencies(), |
| 484 priority++, |
| 485 &graph)); |
365 continue; | 486 continue; |
366 } | 487 } |
367 | 488 |
368 // Request a pixel buffer. This will reserve shared memory. | 489 // Request a pixel buffer. This will reserve shared memory. |
369 resource_provider()->AcquirePixelBuffer(task->resource()->id()); | 490 resource_provider()->AcquirePixelBuffer(task->resource()->id()); |
370 | 491 |
371 // MapPixelBuffer() returns NULL if context was lost at the time | 492 // MapPixelBuffer() returns NULL if context was lost at the time |
372 // AcquirePixelBuffer() was called. For simplicity we still post | 493 // AcquirePixelBuffer() was called. For simplicity we still post |
373 // a raster task that is essentially a noop in these situations. | 494 // a raster task that is essentially a noop in these situations. |
374 uint8* buffer = resource_provider()->MapPixelBuffer( | 495 uint8* buffer = resource_provider()->MapPixelBuffer( |
375 task->resource()->id()); | 496 task->resource()->id()); |
376 | 497 |
377 scoped_refptr<internal::WorkerPoolTask> new_pixel_buffer_task( | 498 scoped_refptr<internal::WorkerPoolTask> new_pixel_buffer_task( |
378 new PixelBufferWorkerPoolTaskImpl( | 499 new PixelBufferWorkerPoolTaskImpl( |
379 task, | 500 task, |
380 buffer, | 501 buffer, |
381 base::Bind(&PixelBufferRasterWorkerPool::OnRasterTaskCompleted, | 502 base::Bind(&PixelBufferRasterWorkerPool::OnRasterTaskCompleted, |
382 base::Unretained(this), | 503 base::Unretained(this), |
383 make_scoped_refptr(task)))); | 504 make_scoped_refptr(task)))); |
384 pixel_buffer_tasks_[task] = new_pixel_buffer_task; | 505 pixel_buffer_tasks_[task] = new_pixel_buffer_task; |
385 graph.InsertRasterTask(new_pixel_buffer_task.get(), task->dependencies()); | 506 tasks[type].container().push_back( |
| 507 CreateGraphNodeForRasterTask(new_pixel_buffer_task.get(), |
| 508 task->dependencies(), |
| 509 priority++, |
| 510 &graph)); |
386 } | 511 } |
387 | 512 |
388 SetRasterTaskGraph(&graph); | 513 scoped_refptr<internal::WorkerPoolTask> |
| 514 new_raster_required_for_activation_finished_task; |
389 | 515 |
390 // At least one task that could need an upload is now pending, schedule | 516 size_t scheduled_raster_task_required_for_activation_count = |
391 // a check for completed raster tasks to ensure this upload is dispatched | 517 tasks[REQUIRED_FOR_ACTIVATION_TYPE].container().size(); |
392 // without too much latency. | 518 DCHECK_LE(scheduled_raster_task_required_for_activation_count, |
393 if (bytes_pending_raster) | 519 tasks_required_for_activation_.size()); |
394 ScheduleCheckForCompletedRasterTasks(); | 520 // Schedule OnRasterTasksRequiredForActivationFinished call only when |
| 521 // notification is pending and throttling is not preventing all pending |
| 522 // tasks required for activation from being scheduled. |
| 523 if (scheduled_raster_task_required_for_activation_count == |
| 524 tasks_required_for_activation_.size() && |
| 525 should_notify_client_if_no_tasks_required_for_activation_are_pending_) { |
| 526 new_raster_required_for_activation_finished_task = |
| 527 CreateRasterRequiredForActivationFinishedTask(); |
| 528 internal::GraphNode* raster_required_for_activation_finished_node = |
| 529 CreateGraphNodeForTask( |
| 530 new_raster_required_for_activation_finished_task.get(), |
| 531 0u, // Priority 0 |
| 532 &graph); |
| 533 AddDependenciesToGraphNode( |
| 534 raster_required_for_activation_finished_node, |
| 535 tasks[REQUIRED_FOR_ACTIVATION_TYPE].container()); |
| 536 } |
| 537 |
| 538 scoped_refptr<internal::WorkerPoolTask> new_raster_finished_task; |
| 539 |
| 540 size_t scheduled_raster_task_count = |
| 541 tasks[PREPAINT_TYPE].container().size() + |
| 542 tasks[REQUIRED_FOR_ACTIVATION_TYPE].container().size(); |
| 543 DCHECK_LE(scheduled_raster_task_count, PendingRasterTaskCount()); |
| 544 // Schedule OnRasterTasksFinished call only when notification is pending |
| 545 // and throttling is not preventing all pending tasks from being scheduled. |
| 546 if (scheduled_raster_task_count == PendingRasterTaskCount() && |
| 547 should_notify_client_if_no_tasks_are_pending_) { |
| 548 new_raster_finished_task = CreateRasterFinishedTask(); |
| 549 internal::GraphNode* raster_finished_node = |
| 550 CreateGraphNodeForTask(new_raster_finished_task.get(), |
| 551 1u, // Priority 1 |
| 552 &graph); |
| 553 for (unsigned type = 0; type < NUM_TYPES; ++type) { |
| 554 AddDependenciesToGraphNode( |
| 555 raster_finished_node, |
| 556 tasks[type].container()); |
| 557 } |
| 558 } |
| 559 |
| 560 SetTaskGraph(&graph); |
| 561 |
| 562 scheduled_raster_task_count_ = scheduled_raster_task_count; |
| 563 |
| 564 set_raster_finished_task(new_raster_finished_task); |
| 565 set_raster_required_for_activation_finished_task( |
| 566 new_raster_required_for_activation_finished_task); |
395 } | 567 } |
396 | 568 |
397 void PixelBufferRasterWorkerPool::OnRasterTaskCompleted( | 569 void PixelBufferRasterWorkerPool::OnRasterTaskCompleted( |
398 scoped_refptr<internal::RasterWorkerPoolTask> task, | 570 scoped_refptr<internal::RasterWorkerPoolTask> task, |
399 bool was_canceled, | 571 bool was_canceled, |
400 bool needs_upload) { | 572 bool needs_upload) { |
401 TRACE_EVENT2("cc", "PixelBufferRasterWorkerPool::OnRasterTaskCompleted", | 573 TRACE_EVENT2("cc", "PixelBufferRasterWorkerPool::OnRasterTaskCompleted", |
402 "was_canceled", was_canceled, | 574 "was_canceled", was_canceled, |
403 "needs_upload", needs_upload); | 575 "needs_upload", needs_upload); |
404 | 576 |
405 DCHECK(pixel_buffer_tasks_.find(task.get()) != pixel_buffer_tasks_.end()); | 577 DCHECK(pixel_buffer_tasks_.find(task.get()) != pixel_buffer_tasks_.end()); |
406 | 578 |
407 // Balanced with MapPixelBuffer() call in ScheduleMoreTasks(). | 579 // Balanced with MapPixelBuffer() call in ScheduleMoreTasks(). |
408 resource_provider()->UnmapPixelBuffer(task->resource()->id()); | 580 resource_provider()->UnmapPixelBuffer(task->resource()->id()); |
409 | 581 |
410 if (!needs_upload) { | 582 if (!needs_upload) { |
411 resource_provider()->ReleasePixelBuffer(task->resource()->id()); | 583 resource_provider()->ReleasePixelBuffer(task->resource()->id()); |
412 task->DidRun(was_canceled); | 584 task->DidRun(was_canceled); |
413 DCHECK(std::find(completed_tasks_.begin(), | 585 DCHECK(std::find(completed_tasks_.begin(), |
414 completed_tasks_.end(), | 586 completed_tasks_.end(), |
415 task) == completed_tasks_.end()); | 587 task) == completed_tasks_.end()); |
416 completed_tasks_.push_back(task); | 588 completed_tasks_.push_back(task); |
| 589 tasks_required_for_activation_.erase(task); |
417 return; | 590 return; |
418 } | 591 } |
419 | 592 |
420 resource_provider()->BeginSetPixels(task->resource()->id()); | 593 resource_provider()->BeginSetPixels(task->resource()->id()); |
421 has_performed_uploads_since_last_flush_ = true; | 594 has_performed_uploads_since_last_flush_ = true; |
422 | 595 |
423 bytes_pending_upload_ += task->resource()->bytes(); | 596 bytes_pending_upload_ += task->resource()->bytes(); |
424 tasks_with_pending_upload_.push_back(task); | 597 tasks_with_pending_upload_.push_back(task); |
425 } | 598 } |
426 | 599 |
| 600 unsigned PixelBufferRasterWorkerPool::PendingRasterTaskCount() const { |
| 601 unsigned num_completed_raster_tasks = |
| 602 tasks_with_pending_upload_.size() + completed_tasks_.size(); |
| 603 DCHECK_GE(pixel_buffer_tasks_.size(), num_completed_raster_tasks); |
| 604 return pixel_buffer_tasks_.size() - num_completed_raster_tasks; |
| 605 } |
| 606 |
| 607 bool PixelBufferRasterWorkerPool::HasPendingTasks() const { |
| 608 return PendingRasterTaskCount() || !tasks_with_pending_upload_.empty(); |
| 609 } |
| 610 |
| 611 bool PixelBufferRasterWorkerPool::HasPendingTasksRequiredForActivation() const { |
| 612 return !tasks_required_for_activation_.empty(); |
| 613 } |
| 614 |
| 615 const char* PixelBufferRasterWorkerPool::StateName() const { |
| 616 if (scheduled_raster_task_count_) |
| 617 return "rasterizing"; |
| 618 if (PendingRasterTaskCount()) |
| 619 return "throttled"; |
| 620 if (!tasks_with_pending_upload_.empty()) |
| 621 return "waiting_for_uploads"; |
| 622 |
| 623 return "finishing"; |
| 624 } |
| 625 |
| 626 scoped_ptr<base::Value> PixelBufferRasterWorkerPool::StateAsValue() const { |
| 627 scoped_ptr<base::DictionaryValue> state(new base::DictionaryValue); |
| 628 |
| 629 state->SetInteger("completed_count", completed_tasks_.size()); |
| 630 state->SetInteger("pending_count", pixel_buffer_tasks_.size()); |
| 631 state->SetInteger("pending_upload_count", tasks_with_pending_upload_.size()); |
| 632 state->SetInteger("required_for_activation_count", |
| 633 tasks_required_for_activation_.size()); |
| 634 state->Set("scheduled_state", ScheduledStateAsValue().release()); |
| 635 state->Set("throttle_state", ThrottleStateAsValue().release()); |
| 636 return state.PassAs<base::Value>(); |
| 637 } |
| 638 |
| 639 scoped_ptr<base::Value> PixelBufferRasterWorkerPool::ThrottleStateAsValue() |
| 640 const { |
| 641 scoped_ptr<base::DictionaryValue> throttle_state(new base::DictionaryValue); |
| 642 |
| 643 throttle_state->SetInteger("bytes_available_for_upload", |
| 644 kMaxPendingUploadBytes - bytes_pending_upload_); |
| 645 throttle_state->SetInteger("bytes_pending_upload", bytes_pending_upload_); |
| 646 throttle_state->SetInteger("scheduled_raster_task_count", |
| 647 scheduled_raster_task_count_); |
| 648 return throttle_state.PassAs<base::Value>(); |
| 649 } |
| 650 |
427 } // namespace cc | 651 } // namespace cc |
OLD | NEW |