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 "gpu/command_buffer/service/async_pixel_transfer_manager_share_group.h" | 5 #include "gpu/command_buffer/service/async_pixel_transfer_manager_share_group.h" |
6 | 6 |
7 #include <list> | 7 #include <list> |
8 | 8 |
9 #include "base/bind.h" | 9 #include "base/bind.h" |
10 #include "base/debug/trace_event.h" | 10 #include "base/debug/trace_event.h" |
(...skipping 133 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
144 class TransferStateInternal | 144 class TransferStateInternal |
145 : public base::RefCountedThreadSafe<TransferStateInternal> { | 145 : public base::RefCountedThreadSafe<TransferStateInternal> { |
146 public: | 146 public: |
147 TransferStateInternal(GLuint texture_id, | 147 TransferStateInternal(GLuint texture_id, |
148 const AsyncTexImage2DParams& define_params) | 148 const AsyncTexImage2DParams& define_params) |
149 : texture_id_(texture_id), | 149 : texture_id_(texture_id), |
150 transfer_completion_(true, true) { | 150 transfer_completion_(true, true) { |
151 define_params_ = define_params; | 151 define_params_ = define_params; |
152 } | 152 } |
153 | 153 |
154 // Implement AsyncPixelTransferState: | |
155 bool TransferIsInProgress() { | 154 bool TransferIsInProgress() { |
156 return !transfer_completion_.IsSignaled(); | 155 return !transfer_completion_.IsSignaled(); |
157 } | 156 } |
158 | 157 |
159 void BindTransfer() { | 158 void BindTransfer() { |
160 TRACE_EVENT2("gpu", "BindAsyncTransfer", | 159 TRACE_EVENT2("gpu", "BindAsyncTransfer", |
161 "width", define_params_.width, | 160 "width", define_params_.width, |
162 "height", define_params_.height); | 161 "height", define_params_.height); |
163 DCHECK(texture_id_); | 162 DCHECK(texture_id_); |
164 | 163 |
(...skipping 11 matching lines...) Expand all Loading... |
176 transfer_completion_.Signal(); | 175 transfer_completion_.Signal(); |
177 } | 176 } |
178 | 177 |
179 void WaitForTransferCompletion() { | 178 void WaitForTransferCompletion() { |
180 TRACE_EVENT0("gpu", "WaitForTransferCompletion"); | 179 TRACE_EVENT0("gpu", "WaitForTransferCompletion"); |
181 // TODO(backer): Deschedule the channel rather than blocking the main GPU | 180 // TODO(backer): Deschedule the channel rather than blocking the main GPU |
182 // thread (crbug.com/240265). | 181 // thread (crbug.com/240265). |
183 transfer_completion_.Wait(); | 182 transfer_completion_.Wait(); |
184 } | 183 } |
185 | 184 |
186 GLuint texture_id() { return texture_id_; } | |
187 | |
188 void SetBindCallback(base::Closure bind_callback) { | 185 void SetBindCallback(base::Closure bind_callback) { |
189 bind_callback_ = bind_callback; | 186 bind_callback_ = bind_callback; |
190 } | 187 } |
191 | 188 |
192 void PerformAsyncTexImage2D(AsyncTexImage2DParams tex_params, | 189 void PerformAsyncTexImage2D(AsyncTexImage2DParams tex_params, |
193 AsyncMemoryParams mem_params, | 190 AsyncMemoryParams mem_params, |
194 ScopedSafeSharedMemory* safe_shared_memory) { | 191 ScopedSafeSharedMemory* safe_shared_memory) { |
195 base::AutoLock locked(upload_lock_); | 192 base::AutoLock locked(upload_lock_); |
196 if (cancel_upload_flag_.IsSet()) | 193 if (cancel_upload_flag_.IsSet()) |
197 return; | 194 return; |
(...skipping 96 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
294 base::WaitableEvent transfer_completion_; | 291 base::WaitableEvent transfer_completion_; |
295 | 292 |
296 // Callback to invoke when AsyncTexImage2D is complete | 293 // Callback to invoke when AsyncTexImage2D is complete |
297 // and the client can safely use the texture. This occurs | 294 // and the client can safely use the texture. This occurs |
298 // during BindCompletedAsyncTransfers(). | 295 // during BindCompletedAsyncTransfers(). |
299 base::Closure bind_callback_; | 296 base::Closure bind_callback_; |
300 }; | 297 }; |
301 | 298 |
302 } // namespace | 299 } // namespace |
303 | 300 |
304 // ShareGroup needs thread-safe ref-counting, so this just wraps | 301 class AsyncPixelTransferDelegateShareGroup |
305 // an internal thread-safe ref-counted state object. | 302 : public AsyncPixelTransferDelegate, |
306 class AsyncTransferStateImpl : public AsyncPixelTransferState { | 303 public base::SupportsWeakPtr<AsyncPixelTransferDelegateShareGroup> { |
307 public: | |
308 AsyncTransferStateImpl(GLuint texture_id, | |
309 const AsyncTexImage2DParams& define_params) | |
310 : internal_(new TransferStateInternal(texture_id, define_params)) {} | |
311 | |
312 virtual bool TransferIsInProgress() OVERRIDE { | |
313 return internal_->TransferIsInProgress(); | |
314 } | |
315 | |
316 TransferStateInternal* internal() { return internal_.get(); } | |
317 | |
318 private: | |
319 virtual ~AsyncTransferStateImpl() { | |
320 TRACE_EVENT0("gpu", " ~AsyncTransferStateImpl"); | |
321 base::AutoLock locked(*internal_->upload_lock()); | |
322 internal_->cancel_upload_flag()->Set(); | |
323 } | |
324 | |
325 scoped_refptr<TransferStateInternal> internal_; | |
326 }; | |
327 | |
328 class AsyncPixelTransferDelegateShareGroup : public AsyncPixelTransferDelegate { | |
329 public: | 304 public: |
330 AsyncPixelTransferDelegateShareGroup( | 305 AsyncPixelTransferDelegateShareGroup( |
331 gfx::GLContext* context, | 306 AsyncPixelTransferManagerShareGroup::SharedState* shared_state, |
332 AsyncPixelTransferManagerShareGroup::SharedState* shared_state); | 307 GLuint texture_id, |
| 308 const AsyncTexImage2DParams& define_params); |
333 virtual ~AsyncPixelTransferDelegateShareGroup(); | 309 virtual ~AsyncPixelTransferDelegateShareGroup(); |
334 | 310 |
| 311 void BindTransfer() { state_->BindTransfer(); } |
| 312 |
335 // Implement AsyncPixelTransferDelegate: | 313 // Implement AsyncPixelTransferDelegate: |
336 virtual AsyncPixelTransferState* CreatePixelTransferState( | |
337 GLuint texture_id, | |
338 const AsyncTexImage2DParams& define_params) OVERRIDE; | |
339 virtual void AsyncTexImage2D( | 314 virtual void AsyncTexImage2D( |
340 AsyncPixelTransferState* state, | |
341 const AsyncTexImage2DParams& tex_params, | 315 const AsyncTexImage2DParams& tex_params, |
342 const AsyncMemoryParams& mem_params, | 316 const AsyncMemoryParams& mem_params, |
343 const base::Closure& bind_callback) OVERRIDE; | 317 const base::Closure& bind_callback) OVERRIDE; |
344 virtual void AsyncTexSubImage2D( | 318 virtual void AsyncTexSubImage2D( |
345 AsyncPixelTransferState* state, | |
346 const AsyncTexSubImage2DParams& tex_params, | 319 const AsyncTexSubImage2DParams& tex_params, |
347 const AsyncMemoryParams& mem_params) OVERRIDE; | 320 const AsyncMemoryParams& mem_params) OVERRIDE; |
348 virtual void WaitForTransferCompletion( | 321 virtual bool TransferIsInProgress() OVERRIDE; |
349 AsyncPixelTransferState* state) OVERRIDE; | 322 virtual void WaitForTransferCompletion() OVERRIDE; |
350 | 323 |
351 private: | 324 private: |
352 // A raw pointer is safe because the SharedState is owned by the Manager, | 325 // A raw pointer is safe because the SharedState is owned by the Manager, |
353 // which owns this Delegate. | 326 // which owns this Delegate. |
354 AsyncPixelTransferManagerShareGroup::SharedState* shared_state_; | 327 AsyncPixelTransferManagerShareGroup::SharedState* shared_state_; |
| 328 scoped_refptr<TransferStateInternal> state_; |
355 | 329 |
356 DISALLOW_COPY_AND_ASSIGN(AsyncPixelTransferDelegateShareGroup); | 330 DISALLOW_COPY_AND_ASSIGN(AsyncPixelTransferDelegateShareGroup); |
357 }; | 331 }; |
358 | 332 |
359 AsyncPixelTransferDelegateShareGroup::AsyncPixelTransferDelegateShareGroup( | 333 AsyncPixelTransferDelegateShareGroup::AsyncPixelTransferDelegateShareGroup( |
360 gfx::GLContext* context, | 334 AsyncPixelTransferManagerShareGroup::SharedState* shared_state, |
361 AsyncPixelTransferManagerShareGroup::SharedState* shared_state) | 335 GLuint texture_id, |
362 : shared_state_(shared_state) { | 336 const AsyncTexImage2DParams& define_params) |
363 g_transfer_thread.Pointer()->InitializeOnMainThread(context); | 337 : shared_state_(shared_state), |
| 338 state_(new TransferStateInternal(texture_id, define_params)) {} |
| 339 |
| 340 AsyncPixelTransferDelegateShareGroup::~AsyncPixelTransferDelegateShareGroup() { |
| 341 TRACE_EVENT0("gpu", " ~AsyncPixelTransferDelegateShareGroup"); |
| 342 base::AutoLock locked(*state_->upload_lock()); |
| 343 state_->cancel_upload_flag()->Set(); |
364 } | 344 } |
365 | 345 |
366 AsyncPixelTransferDelegateShareGroup::~AsyncPixelTransferDelegateShareGroup() { | 346 bool AsyncPixelTransferDelegateShareGroup::TransferIsInProgress() { |
| 347 return state_->TransferIsInProgress(); |
367 } | 348 } |
368 | 349 |
369 AsyncPixelTransferState* | 350 void AsyncPixelTransferDelegateShareGroup::WaitForTransferCompletion() { |
370 AsyncPixelTransferDelegateShareGroup:: | 351 if (state_->TransferIsInProgress()) { |
371 CreatePixelTransferState( | |
372 GLuint texture_id, | |
373 const AsyncTexImage2DParams& define_params) { | |
374 return static_cast<AsyncPixelTransferState*>( | |
375 new AsyncTransferStateImpl(texture_id, define_params)); | |
376 } | |
377 | |
378 void AsyncPixelTransferDelegateShareGroup::WaitForTransferCompletion( | |
379 AsyncPixelTransferState* transfer_state) { | |
380 scoped_refptr<TransferStateInternal> state = | |
381 static_cast<AsyncTransferStateImpl*>(transfer_state)->internal(); | |
382 DCHECK(state.get()); | |
383 DCHECK(state->texture_id()); | |
384 | |
385 if (state->TransferIsInProgress()) { | |
386 #if defined(OS_ANDROID) || defined(OS_LINUX) | 352 #if defined(OS_ANDROID) || defined(OS_LINUX) |
387 g_transfer_thread.Pointer()->SetPriority(base::kThreadPriority_Display); | 353 g_transfer_thread.Pointer()->SetPriority(base::kThreadPriority_Display); |
388 #endif | 354 #endif |
389 | 355 |
390 state->WaitForTransferCompletion(); | 356 state_->WaitForTransferCompletion(); |
391 DCHECK(!state->TransferIsInProgress()); | 357 DCHECK(!state_->TransferIsInProgress()); |
392 | 358 |
393 #if defined(OS_ANDROID) || defined(OS_LINUX) | 359 #if defined(OS_ANDROID) || defined(OS_LINUX) |
394 g_transfer_thread.Pointer()->SetPriority(base::kThreadPriority_Background); | 360 g_transfer_thread.Pointer()->SetPriority(base::kThreadPriority_Background); |
395 #endif | 361 #endif |
396 } | 362 } |
397 } | 363 } |
398 | 364 |
399 void AsyncPixelTransferDelegateShareGroup::AsyncTexImage2D( | 365 void AsyncPixelTransferDelegateShareGroup::AsyncTexImage2D( |
400 AsyncPixelTransferState* transfer_state, | |
401 const AsyncTexImage2DParams& tex_params, | 366 const AsyncTexImage2DParams& tex_params, |
402 const AsyncMemoryParams& mem_params, | 367 const AsyncMemoryParams& mem_params, |
403 const base::Closure& bind_callback) { | 368 const base::Closure& bind_callback) { |
404 scoped_refptr<TransferStateInternal> state = | |
405 static_cast<AsyncTransferStateImpl*>(transfer_state)->internal(); | |
406 DCHECK(mem_params.shared_memory); | 369 DCHECK(mem_params.shared_memory); |
407 DCHECK_LE(mem_params.shm_data_offset + mem_params.shm_data_size, | 370 DCHECK_LE(mem_params.shm_data_offset + mem_params.shm_data_size, |
408 mem_params.shm_size); | 371 mem_params.shm_size); |
409 DCHECK(state.get()); | 372 DCHECK(!state_->TransferIsInProgress()); |
410 DCHECK(state->texture_id()); | |
411 DCHECK(!state->TransferIsInProgress()); | |
412 DCHECK_EQ(static_cast<GLenum>(GL_TEXTURE_2D), tex_params.target); | 373 DCHECK_EQ(static_cast<GLenum>(GL_TEXTURE_2D), tex_params.target); |
413 DCHECK_EQ(tex_params.level, 0); | 374 DCHECK_EQ(tex_params.level, 0); |
414 | 375 |
415 // Mark the transfer in progress and save the late bind | 376 // Mark the transfer in progress and save the late bind |
416 // callback, so we can notify the client when it is bound. | 377 // callback, so we can notify the client when it is bound. |
417 shared_state_->pending_allocations.push_back(transfer_state->AsWeakPtr()); | 378 shared_state_->pending_allocations.push_back(AsWeakPtr()); |
418 state->SetBindCallback(bind_callback); | 379 state_->SetBindCallback(bind_callback); |
419 | 380 |
420 // Mark the transfer in progress. | 381 // Mark the transfer in progress. |
421 state->MarkAsTransferIsInProgress(); | 382 state_->MarkAsTransferIsInProgress(); |
422 | 383 |
423 // Duplicate the shared memory so there is no way we can get | 384 // Duplicate the shared memory so there is no way we can get |
424 // a use-after-free of the raw pixels. | 385 // a use-after-free of the raw pixels. |
425 transfer_message_loop_proxy()->PostTask( | 386 transfer_message_loop_proxy()->PostTask( |
426 FROM_HERE, | 387 FROM_HERE, |
427 base::Bind( | 388 base::Bind( |
428 &TransferStateInternal::PerformAsyncTexImage2D, | 389 &TransferStateInternal::PerformAsyncTexImage2D, |
429 state, | 390 state_, |
430 tex_params, | 391 tex_params, |
431 mem_params, | 392 mem_params, |
432 base::Owned(new ScopedSafeSharedMemory(safe_shared_memory_pool(), | 393 base::Owned(new ScopedSafeSharedMemory(safe_shared_memory_pool(), |
433 mem_params.shared_memory, | 394 mem_params.shared_memory, |
434 mem_params.shm_size)))); | 395 mem_params.shm_size)))); |
435 } | 396 } |
436 | 397 |
437 void AsyncPixelTransferDelegateShareGroup::AsyncTexSubImage2D( | 398 void AsyncPixelTransferDelegateShareGroup::AsyncTexSubImage2D( |
438 AsyncPixelTransferState* transfer_state, | |
439 const AsyncTexSubImage2DParams& tex_params, | 399 const AsyncTexSubImage2DParams& tex_params, |
440 const AsyncMemoryParams& mem_params) { | 400 const AsyncMemoryParams& mem_params) { |
441 TRACE_EVENT2("gpu", "AsyncTexSubImage2D", | 401 TRACE_EVENT2("gpu", "AsyncTexSubImage2D", |
442 "width", tex_params.width, | 402 "width", tex_params.width, |
443 "height", tex_params.height); | 403 "height", tex_params.height); |
444 scoped_refptr<TransferStateInternal> state = | 404 DCHECK(!state_->TransferIsInProgress()); |
445 static_cast<AsyncTransferStateImpl*>(transfer_state)->internal(); | |
446 | |
447 DCHECK(state->texture_id()); | |
448 DCHECK(!state->TransferIsInProgress()); | |
449 DCHECK(mem_params.shared_memory); | 405 DCHECK(mem_params.shared_memory); |
450 DCHECK_LE(mem_params.shm_data_offset + mem_params.shm_data_size, | 406 DCHECK_LE(mem_params.shm_data_offset + mem_params.shm_data_size, |
451 mem_params.shm_size); | 407 mem_params.shm_size); |
452 DCHECK_EQ(static_cast<GLenum>(GL_TEXTURE_2D), tex_params.target); | 408 DCHECK_EQ(static_cast<GLenum>(GL_TEXTURE_2D), tex_params.target); |
453 DCHECK_EQ(tex_params.level, 0); | 409 DCHECK_EQ(tex_params.level, 0); |
454 | 410 |
455 // Mark the transfer in progress. | 411 // Mark the transfer in progress. |
456 state->MarkAsTransferIsInProgress(); | 412 state_->MarkAsTransferIsInProgress(); |
457 | 413 |
458 // Duplicate the shared memory so there are no way we can get | 414 // Duplicate the shared memory so there are no way we can get |
459 // a use-after-free of the raw pixels. | 415 // a use-after-free of the raw pixels. |
460 transfer_message_loop_proxy()->PostTask( | 416 transfer_message_loop_proxy()->PostTask( |
461 FROM_HERE, | 417 FROM_HERE, |
462 base::Bind( | 418 base::Bind( |
463 &TransferStateInternal::PerformAsyncTexSubImage2D, | 419 &TransferStateInternal::PerformAsyncTexSubImage2D, |
464 state, | 420 state_, |
465 tex_params, | 421 tex_params, |
466 mem_params, | 422 mem_params, |
467 base::Owned(new ScopedSafeSharedMemory(safe_shared_memory_pool(), | 423 base::Owned(new ScopedSafeSharedMemory(safe_shared_memory_pool(), |
468 mem_params.shared_memory, | 424 mem_params.shared_memory, |
469 mem_params.shm_size)), | 425 mem_params.shm_size)), |
470 shared_state_->texture_upload_stats)); | 426 shared_state_->texture_upload_stats)); |
471 } | 427 } |
472 | 428 |
473 AsyncPixelTransferManagerShareGroup::SharedState::SharedState() | 429 AsyncPixelTransferManagerShareGroup::SharedState::SharedState() |
474 // TODO(reveman): Skip this if --enable-gpu-benchmarking is not present. | 430 // TODO(reveman): Skip this if --enable-gpu-benchmarking is not present. |
475 : texture_upload_stats(new AsyncPixelTransferUploadStats) {} | 431 : texture_upload_stats(new AsyncPixelTransferUploadStats) {} |
476 | 432 |
477 AsyncPixelTransferManagerShareGroup::SharedState::~SharedState() {} | 433 AsyncPixelTransferManagerShareGroup::SharedState::~SharedState() {} |
478 | 434 |
479 AsyncPixelTransferManagerShareGroup::AsyncPixelTransferManagerShareGroup( | 435 AsyncPixelTransferManagerShareGroup::AsyncPixelTransferManagerShareGroup( |
480 gfx::GLContext* context) | 436 gfx::GLContext* context) { |
481 : delegate_(new AsyncPixelTransferDelegateShareGroup(context, | 437 g_transfer_thread.Pointer()->InitializeOnMainThread(context); |
482 &shared_state_)) {} | 438 } |
483 | 439 |
484 AsyncPixelTransferManagerShareGroup::~AsyncPixelTransferManagerShareGroup() {} | 440 AsyncPixelTransferManagerShareGroup::~AsyncPixelTransferManagerShareGroup() {} |
485 | 441 |
486 void AsyncPixelTransferManagerShareGroup::BindCompletedAsyncTransfers() { | 442 void AsyncPixelTransferManagerShareGroup::BindCompletedAsyncTransfers() { |
487 scoped_ptr<gfx::ScopedTextureBinder> texture_binder; | 443 scoped_ptr<gfx::ScopedTextureBinder> texture_binder; |
488 | 444 |
489 while (!shared_state_.pending_allocations.empty()) { | 445 while (!shared_state_.pending_allocations.empty()) { |
490 if (!shared_state_.pending_allocations.front().get()) { | 446 if (!shared_state_.pending_allocations.front().get()) { |
491 shared_state_.pending_allocations.pop_front(); | 447 shared_state_.pending_allocations.pop_front(); |
492 continue; | 448 continue; |
493 } | 449 } |
494 scoped_refptr<TransferStateInternal> state = | 450 AsyncPixelTransferDelegateShareGroup* delegate = |
495 static_cast<AsyncTransferStateImpl*> | 451 shared_state_.pending_allocations.front().get(); |
496 (shared_state_.pending_allocations.front().get())->internal(); | |
497 // Terminate early, as all transfers finish in order, currently. | 452 // Terminate early, as all transfers finish in order, currently. |
498 if (state->TransferIsInProgress()) | 453 if (delegate->TransferIsInProgress()) |
499 break; | 454 break; |
500 | 455 |
501 if (!texture_binder) | 456 if (!texture_binder) |
502 texture_binder.reset(new gfx::ScopedTextureBinder(GL_TEXTURE_2D, 0)); | 457 texture_binder.reset(new gfx::ScopedTextureBinder(GL_TEXTURE_2D, 0)); |
503 | 458 |
504 // Used to set tex info from the gles2 cmd decoder once upload has | 459 // Used to set tex info from the gles2 cmd decoder once upload has |
505 // finished (it'll bind the texture and call a callback). | 460 // finished (it'll bind the texture and call a callback). |
506 state->BindTransfer(); | 461 delegate->BindTransfer(); |
507 | 462 |
508 shared_state_.pending_allocations.pop_front(); | 463 shared_state_.pending_allocations.pop_front(); |
509 } | 464 } |
510 } | 465 } |
511 | 466 |
512 void AsyncPixelTransferManagerShareGroup::AsyncNotifyCompletion( | 467 void AsyncPixelTransferManagerShareGroup::AsyncNotifyCompletion( |
513 const AsyncMemoryParams& mem_params, | 468 const AsyncMemoryParams& mem_params, |
514 const CompletionCallback& callback) { | 469 const CompletionCallback& callback) { |
515 DCHECK(mem_params.shared_memory); | 470 DCHECK(mem_params.shared_memory); |
516 DCHECK_LE(mem_params.shm_data_offset + mem_params.shm_data_size, | 471 DCHECK_LE(mem_params.shm_data_offset + mem_params.shm_data_size, |
(...skipping 23 matching lines...) Expand all Loading... |
540 } | 495 } |
541 | 496 |
542 void AsyncPixelTransferManagerShareGroup::ProcessMorePendingTransfers() { | 497 void AsyncPixelTransferManagerShareGroup::ProcessMorePendingTransfers() { |
543 } | 498 } |
544 | 499 |
545 bool AsyncPixelTransferManagerShareGroup::NeedsProcessMorePendingTransfers() { | 500 bool AsyncPixelTransferManagerShareGroup::NeedsProcessMorePendingTransfers() { |
546 return false; | 501 return false; |
547 } | 502 } |
548 | 503 |
549 AsyncPixelTransferDelegate* | 504 AsyncPixelTransferDelegate* |
550 AsyncPixelTransferManagerShareGroup::GetAsyncPixelTransferDelegate() { | 505 AsyncPixelTransferManagerShareGroup::CreatePixelTransferDelegateImpl( |
551 return delegate_.get(); | 506 gles2::TextureRef* ref, |
| 507 const AsyncTexImage2DParams& define_params) { |
| 508 return new AsyncPixelTransferDelegateShareGroup( |
| 509 &shared_state_, ref->service_id(), define_params); |
552 } | 510 } |
553 | 511 |
554 } // namespace gpu | 512 } // namespace gpu |
OLD | NEW |