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 |