| 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_egl.h" | 5 #include "gpu/command_buffer/service/async_pixel_transfer_manager_egl.h" |
| 6 | 6 |
| 7 #include <list> | 7 #include <list> |
| 8 #include <string> | 8 #include <string> |
| 9 | 9 |
| 10 #include "base/bind.h" | 10 #include "base/bind.h" |
| (...skipping 70 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 81 void PerformNotifyCompletion( | 81 void PerformNotifyCompletion( |
| 82 AsyncMemoryParams mem_params, | 82 AsyncMemoryParams mem_params, |
| 83 scoped_refptr<AsyncPixelTransferCompletionObserver> observer) { | 83 scoped_refptr<AsyncPixelTransferCompletionObserver> observer) { |
| 84 TRACE_EVENT0("gpu", "PerformNotifyCompletion"); | 84 TRACE_EVENT0("gpu", "PerformNotifyCompletion"); |
| 85 observer->DidComplete(mem_params); | 85 observer->DidComplete(mem_params); |
| 86 } | 86 } |
| 87 | 87 |
| 88 class TransferThread : public base::Thread { | 88 class TransferThread : public base::Thread { |
| 89 public: | 89 public: |
| 90 TransferThread() : base::Thread(kAsyncTransferThreadName) { | 90 TransferThread() : base::Thread(kAsyncTransferThreadName) { |
| 91 Start(); | 91 base::Thread::Options options; |
| 92 #if defined(OS_ANDROID) || defined(OS_LINUX) | 92 #if defined(OS_ANDROID) || defined(OS_LINUX) |
| 93 SetPriority(base::ThreadPriority::BACKGROUND); | 93 options.priority = base::ThreadPriority::BACKGROUND; |
| 94 #endif | 94 #endif |
| 95 StartWithOptions(options); |
| 95 } | 96 } |
| 96 ~TransferThread() override { Stop(); } | 97 ~TransferThread() override { Stop(); } |
| 97 | 98 |
| 98 void Init() override { | 99 void Init() override { |
| 99 gfx::GLShareGroup* share_group = NULL; | 100 gfx::GLShareGroup* share_group = NULL; |
| 100 surface_ = new gfx::PbufferGLSurfaceEGL(gfx::Size(1, 1), | 101 surface_ = new gfx::PbufferGLSurfaceEGL(gfx::Size(1, 1), |
| 101 gfx::SurfaceConfiguration()); | 102 gfx::SurfaceConfiguration()); |
| 102 surface_->Initialize(); | 103 surface_->Initialize(); |
| 103 context_ = gfx::GLContext::CreateGLContext( | 104 context_ = gfx::GLContext::CreateGLContext( |
| 104 share_group, surface_.get(), gfx::PreferDiscreteGpu); | 105 share_group, surface_.get(), gfx::PreferDiscreteGpu); |
| (...skipping 10 matching lines...) Expand all Loading... |
| 115 private: | 116 private: |
| 116 scoped_refptr<gfx::GLContext> context_; | 117 scoped_refptr<gfx::GLContext> context_; |
| 117 scoped_refptr<gfx::GLSurface> surface_; | 118 scoped_refptr<gfx::GLSurface> surface_; |
| 118 | 119 |
| 119 DISALLOW_COPY_AND_ASSIGN(TransferThread); | 120 DISALLOW_COPY_AND_ASSIGN(TransferThread); |
| 120 }; | 121 }; |
| 121 | 122 |
| 122 base::LazyInstance<TransferThread> | 123 base::LazyInstance<TransferThread> |
| 123 g_transfer_thread = LAZY_INSTANCE_INITIALIZER; | 124 g_transfer_thread = LAZY_INSTANCE_INITIALIZER; |
| 124 | 125 |
| 125 base::MessageLoopProxy* transfer_message_loop_proxy() { | 126 base::TaskRunner* transfer_task_runner() { |
| 126 return g_transfer_thread.Pointer()->message_loop_proxy().get(); | 127 return g_transfer_thread.Pointer()->task_runner().get(); |
| 127 } | 128 } |
| 128 | 129 |
| 129 // Class which holds async pixel transfers state (EGLImage). | 130 // Class which holds async pixel transfers state (EGLImage). |
| 130 // The EGLImage is accessed by either thread, but everything | 131 // The EGLImage is accessed by either thread, but everything |
| 131 // else accessed only on the main thread. | 132 // else accessed only on the main thread. |
| 132 class TransferStateInternal | 133 class TransferStateInternal |
| 133 : public base::RefCountedThreadSafe<TransferStateInternal> { | 134 : public base::RefCountedThreadSafe<TransferStateInternal> { |
| 134 public: | 135 public: |
| 135 TransferStateInternal(GLuint texture_id, | 136 TransferStateInternal(GLuint texture_id, |
| 136 const AsyncTexImage2DParams& define_params, | 137 const AsyncTexImage2DParams& define_params, |
| (...skipping 209 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 346 static void DeleteTexture(GLuint id) { | 347 static void DeleteTexture(GLuint id) { |
| 347 glDeleteTextures(1, &id); | 348 glDeleteTextures(1, &id); |
| 348 } | 349 } |
| 349 | 350 |
| 350 virtual ~TransferStateInternal() { | 351 virtual ~TransferStateInternal() { |
| 351 if (egl_image_ != EGL_NO_IMAGE_KHR) { | 352 if (egl_image_ != EGL_NO_IMAGE_KHR) { |
| 352 EGLDisplay display = eglGetCurrentDisplay(); | 353 EGLDisplay display = eglGetCurrentDisplay(); |
| 353 eglDestroyImageKHR(display, egl_image_); | 354 eglDestroyImageKHR(display, egl_image_); |
| 354 } | 355 } |
| 355 if (thread_texture_id_) { | 356 if (thread_texture_id_) { |
| 356 transfer_message_loop_proxy()->PostTask(FROM_HERE, | 357 transfer_task_runner()->PostTask( |
| 357 base::Bind(&DeleteTexture, thread_texture_id_)); | 358 FROM_HERE, base::Bind(&DeleteTexture, thread_texture_id_)); |
| 358 } | 359 } |
| 359 } | 360 } |
| 360 | 361 |
| 361 // The 'real' texture. | 362 // The 'real' texture. |
| 362 GLuint texture_id_; | 363 GLuint texture_id_; |
| 363 | 364 |
| 364 // The EGLImage sibling on the upload thread. | 365 // The EGLImage sibling on the upload thread. |
| 365 GLuint thread_texture_id_; | 366 GLuint thread_texture_id_; |
| 366 | 367 |
| 367 // Definition params for texture that needs binding. | 368 // Definition params for texture that needs binding. |
| (...skipping 91 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 459 } | 460 } |
| 460 | 461 |
| 461 AsyncPixelTransferDelegateEGL::~AsyncPixelTransferDelegateEGL() {} | 462 AsyncPixelTransferDelegateEGL::~AsyncPixelTransferDelegateEGL() {} |
| 462 | 463 |
| 463 bool AsyncPixelTransferDelegateEGL::TransferIsInProgress() { | 464 bool AsyncPixelTransferDelegateEGL::TransferIsInProgress() { |
| 464 return state_->TransferIsInProgress(); | 465 return state_->TransferIsInProgress(); |
| 465 } | 466 } |
| 466 | 467 |
| 467 void AsyncPixelTransferDelegateEGL::WaitForTransferCompletion() { | 468 void AsyncPixelTransferDelegateEGL::WaitForTransferCompletion() { |
| 468 if (state_->TransferIsInProgress()) { | 469 if (state_->TransferIsInProgress()) { |
| 469 #if defined(OS_ANDROID) || defined(OS_LINUX) | |
| 470 g_transfer_thread.Pointer()->SetPriority(base::ThreadPriority::BACKGROUND); | |
| 471 #endif | |
| 472 | |
| 473 state_->WaitForTransferCompletion(); | 470 state_->WaitForTransferCompletion(); |
| 474 DCHECK(!state_->TransferIsInProgress()); | 471 DCHECK(!state_->TransferIsInProgress()); |
| 475 | |
| 476 #if defined(OS_ANDROID) || defined(OS_LINUX) | |
| 477 g_transfer_thread.Pointer()->SetPriority(base::ThreadPriority::BACKGROUND); | |
| 478 #endif | |
| 479 } | 472 } |
| 480 } | 473 } |
| 481 | 474 |
| 482 void AsyncPixelTransferDelegateEGL::AsyncTexImage2D( | 475 void AsyncPixelTransferDelegateEGL::AsyncTexImage2D( |
| 483 const AsyncTexImage2DParams& tex_params, | 476 const AsyncTexImage2DParams& tex_params, |
| 484 const AsyncMemoryParams& mem_params, | 477 const AsyncMemoryParams& mem_params, |
| 485 const base::Closure& bind_callback) { | 478 const base::Closure& bind_callback) { |
| 486 if (WorkAroundAsyncTexImage2D(tex_params, mem_params, bind_callback)) | 479 if (WorkAroundAsyncTexImage2D(tex_params, mem_params, bind_callback)) |
| 487 return; | 480 return; |
| 488 | 481 |
| 489 DCHECK(!state_->TransferIsInProgress()); | 482 DCHECK(!state_->TransferIsInProgress()); |
| 490 DCHECK_EQ(state_->egl_image_, EGL_NO_IMAGE_KHR); | 483 DCHECK_EQ(state_->egl_image_, EGL_NO_IMAGE_KHR); |
| 491 DCHECK_EQ(static_cast<GLenum>(GL_TEXTURE_2D), tex_params.target); | 484 DCHECK_EQ(static_cast<GLenum>(GL_TEXTURE_2D), tex_params.target); |
| 492 DCHECK_EQ(tex_params.level, 0); | 485 DCHECK_EQ(tex_params.level, 0); |
| 493 | 486 |
| 494 // Mark the transfer in progress and save the late bind | 487 // Mark the transfer in progress and save the late bind |
| 495 // callback, so we can notify the client when it is bound. | 488 // callback, so we can notify the client when it is bound. |
| 496 shared_state_->pending_allocations.push_back(AsWeakPtr()); | 489 shared_state_->pending_allocations.push_back(AsWeakPtr()); |
| 497 state_->bind_callback_ = bind_callback; | 490 state_->bind_callback_ = bind_callback; |
| 498 | 491 |
| 499 // Mark the transfer in progress. | 492 // Mark the transfer in progress. |
| 500 state_->MarkAsTransferIsInProgress(); | 493 state_->MarkAsTransferIsInProgress(); |
| 501 | 494 |
| 502 // Duplicate the shared memory so there is no way we can get | 495 // Duplicate the shared memory so there is no way we can get |
| 503 // a use-after-free of the raw pixels. | 496 // a use-after-free of the raw pixels. |
| 504 transfer_message_loop_proxy()->PostTask(FROM_HERE, | 497 transfer_task_runner()->PostTask( |
| 505 base::Bind( | 498 FROM_HERE, |
| 506 &TransferStateInternal::PerformAsyncTexImage2D, | 499 base::Bind(&TransferStateInternal::PerformAsyncTexImage2D, state_, |
| 507 state_, | 500 tex_params, mem_params, shared_state_->texture_upload_stats)); |
| 508 tex_params, | |
| 509 mem_params, | |
| 510 shared_state_->texture_upload_stats)); | |
| 511 | 501 |
| 512 DCHECK(CHECK_GL()); | 502 DCHECK(CHECK_GL()); |
| 513 } | 503 } |
| 514 | 504 |
| 515 void AsyncPixelTransferDelegateEGL::AsyncTexSubImage2D( | 505 void AsyncPixelTransferDelegateEGL::AsyncTexSubImage2D( |
| 516 const AsyncTexSubImage2DParams& tex_params, | 506 const AsyncTexSubImage2DParams& tex_params, |
| 517 const AsyncMemoryParams& mem_params) { | 507 const AsyncMemoryParams& mem_params) { |
| 518 TRACE_EVENT2("gpu", "AsyncTexSubImage2D", | 508 TRACE_EVENT2("gpu", "AsyncTexSubImage2D", |
| 519 "width", tex_params.width, | 509 "width", tex_params.width, |
| 520 "height", tex_params.height); | 510 "height", tex_params.height); |
| 521 if (WorkAroundAsyncTexSubImage2D(tex_params, mem_params)) | 511 if (WorkAroundAsyncTexSubImage2D(tex_params, mem_params)) |
| 522 return; | 512 return; |
| 523 DCHECK(!state_->TransferIsInProgress()); | 513 DCHECK(!state_->TransferIsInProgress()); |
| 524 DCHECK_EQ(static_cast<GLenum>(GL_TEXTURE_2D), tex_params.target); | 514 DCHECK_EQ(static_cast<GLenum>(GL_TEXTURE_2D), tex_params.target); |
| 525 DCHECK_EQ(tex_params.level, 0); | 515 DCHECK_EQ(tex_params.level, 0); |
| 526 | 516 |
| 527 // Mark the transfer in progress. | 517 // Mark the transfer in progress. |
| 528 state_->MarkAsTransferIsInProgress(); | 518 state_->MarkAsTransferIsInProgress(); |
| 529 | 519 |
| 530 // If this wasn't async allocated, we don't have an EGLImage yet. | 520 // If this wasn't async allocated, we don't have an EGLImage yet. |
| 531 // Create the EGLImage if it hasn't already been created. | 521 // Create the EGLImage if it hasn't already been created. |
| 532 state_->CreateEglImageOnMainThreadIfNeeded(); | 522 state_->CreateEglImageOnMainThreadIfNeeded(); |
| 533 | 523 |
| 534 // Duplicate the shared memory so there are no way we can get | 524 // Duplicate the shared memory so there are no way we can get |
| 535 // a use-after-free of the raw pixels. | 525 // a use-after-free of the raw pixels. |
| 536 transfer_message_loop_proxy()->PostTask(FROM_HERE, | 526 transfer_task_runner()->PostTask( |
| 537 base::Bind( | 527 FROM_HERE, |
| 538 &TransferStateInternal::PerformAsyncTexSubImage2D, | 528 base::Bind(&TransferStateInternal::PerformAsyncTexSubImage2D, state_, |
| 539 state_, | 529 tex_params, mem_params, shared_state_->texture_upload_stats)); |
| 540 tex_params, | |
| 541 mem_params, | |
| 542 shared_state_->texture_upload_stats)); | |
| 543 | 530 |
| 544 DCHECK(CHECK_GL()); | 531 DCHECK(CHECK_GL()); |
| 545 } | 532 } |
| 546 | 533 |
| 547 namespace { | 534 namespace { |
| 548 bool IsPowerOfTwo (unsigned int x) { | 535 bool IsPowerOfTwo (unsigned int x) { |
| 549 return ((x != 0) && !(x & (x - 1))); | 536 return ((x != 0) && !(x & (x - 1))); |
| 550 } | 537 } |
| 551 | 538 |
| 552 bool IsMultipleOfEight(unsigned int x) { | 539 bool IsMultipleOfEight(unsigned int x) { |
| (...skipping 142 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 695 delegate->BindTransfer(); | 682 delegate->BindTransfer(); |
| 696 shared_state_.pending_allocations.pop_front(); | 683 shared_state_.pending_allocations.pop_front(); |
| 697 } | 684 } |
| 698 } | 685 } |
| 699 | 686 |
| 700 void AsyncPixelTransferManagerEGL::AsyncNotifyCompletion( | 687 void AsyncPixelTransferManagerEGL::AsyncNotifyCompletion( |
| 701 const AsyncMemoryParams& mem_params, | 688 const AsyncMemoryParams& mem_params, |
| 702 AsyncPixelTransferCompletionObserver* observer) { | 689 AsyncPixelTransferCompletionObserver* observer) { |
| 703 // Post a PerformNotifyCompletion task to the upload thread. This task | 690 // Post a PerformNotifyCompletion task to the upload thread. This task |
| 704 // will run after all async transfers are complete. | 691 // will run after all async transfers are complete. |
| 705 transfer_message_loop_proxy()->PostTask( | 692 transfer_task_runner()->PostTask( |
| 706 FROM_HERE, | 693 FROM_HERE, base::Bind(&PerformNotifyCompletion, mem_params, |
| 707 base::Bind(&PerformNotifyCompletion, | 694 make_scoped_refptr(observer))); |
| 708 mem_params, | |
| 709 make_scoped_refptr(observer))); | |
| 710 } | 695 } |
| 711 | 696 |
| 712 uint32 AsyncPixelTransferManagerEGL::GetTextureUploadCount() { | 697 uint32 AsyncPixelTransferManagerEGL::GetTextureUploadCount() { |
| 713 return shared_state_.texture_upload_stats->GetStats(NULL); | 698 return shared_state_.texture_upload_stats->GetStats(NULL); |
| 714 } | 699 } |
| 715 | 700 |
| 716 base::TimeDelta AsyncPixelTransferManagerEGL::GetTotalTextureUploadTime() { | 701 base::TimeDelta AsyncPixelTransferManagerEGL::GetTotalTextureUploadTime() { |
| 717 base::TimeDelta total_texture_upload_time; | 702 base::TimeDelta total_texture_upload_time; |
| 718 shared_state_.texture_upload_stats->GetStats(&total_texture_upload_time); | 703 shared_state_.texture_upload_stats->GetStats(&total_texture_upload_time); |
| 719 return total_texture_upload_time; | 704 return total_texture_upload_time; |
| (...skipping 18 matching lines...) Expand all Loading... |
| 738 | 723 |
| 739 AsyncPixelTransferDelegate* | 724 AsyncPixelTransferDelegate* |
| 740 AsyncPixelTransferManagerEGL::CreatePixelTransferDelegateImpl( | 725 AsyncPixelTransferManagerEGL::CreatePixelTransferDelegateImpl( |
| 741 gles2::TextureRef* ref, | 726 gles2::TextureRef* ref, |
| 742 const AsyncTexImage2DParams& define_params) { | 727 const AsyncTexImage2DParams& define_params) { |
| 743 return new AsyncPixelTransferDelegateEGL( | 728 return new AsyncPixelTransferDelegateEGL( |
| 744 &shared_state_, ref->service_id(), define_params); | 729 &shared_state_, ref->service_id(), define_params); |
| 745 } | 730 } |
| 746 | 731 |
| 747 } // namespace gpu | 732 } // namespace gpu |
| OLD | NEW |