| OLD | NEW |
| 1 // Copyright (c) 2012 The Chromium Authors. All rights reserved. | 1 // Copyright (c) 2012 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 "ui/gl/async_pixel_transfer_delegate_android.h" | 5 #include "ui/gl/async_pixel_transfer_delegate_android.h" |
| 6 | 6 |
| 7 #include <string> | 7 #include <string> |
| 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 130 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 141 SafeSharedMemoryPool* safe_shared_memory_pool() { | 141 SafeSharedMemoryPool* safe_shared_memory_pool() { |
| 142 return g_transfer_thread.Pointer()->safe_shared_memory_pool(); | 142 return g_transfer_thread.Pointer()->safe_shared_memory_pool(); |
| 143 } | 143 } |
| 144 | 144 |
| 145 | 145 |
| 146 } // namespace | 146 } // namespace |
| 147 | 147 |
| 148 // Class which holds async pixel transfers state (EGLImage). | 148 // Class which holds async pixel transfers state (EGLImage). |
| 149 // The EGLImage is accessed by either thread, but everything | 149 // The EGLImage is accessed by either thread, but everything |
| 150 // else accessed only on the main thread. | 150 // else accessed only on the main thread. |
| 151 class TransferStateInternal | 151 class TransferStateInternal : public base::RefCounted<TransferStateInternal> { |
| 152 : public base::RefCountedThreadSafe<TransferStateInternal> { | |
| 153 public: | 152 public: |
| 154 explicit TransferStateInternal(GLuint texture_id, | 153 explicit TransferStateInternal(GLuint texture_id, |
| 155 bool wait_for_uploads, | 154 bool wait_for_uploads, |
| 156 bool use_image_preserved) | 155 bool use_image_preserved) |
| 157 : texture_id_(texture_id), | 156 : texture_id_(texture_id), |
| 158 thread_texture_id_(0), | 157 thread_texture_id_(0), |
| 159 needs_late_bind_(false), | 158 needs_late_bind_(false), |
| 160 transfer_in_progress_(false), | 159 transfer_in_progress_(false), |
| 161 egl_image_(EGL_NO_IMAGE_KHR), | 160 egl_image_(EGL_NO_IMAGE_KHR), |
| 162 wait_for_uploads_(wait_for_uploads), | 161 wait_for_uploads_(wait_for_uploads), |
| (...skipping 69 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 232 // GPU action that needs to occur. We could use fences and try | 231 // GPU action that needs to occur. We could use fences and try |
| 233 // to do this less often. However, on older drivers fences are | 232 // to do this less often. However, on older drivers fences are |
| 234 // not always reliable (eg. Mali-400 just blocks forever). | 233 // not always reliable (eg. Mali-400 just blocks forever). |
| 235 if (wait_for_uploads_) { | 234 if (wait_for_uploads_) { |
| 236 TRACE_EVENT0("gpu", "glFinish"); | 235 TRACE_EVENT0("gpu", "glFinish"); |
| 237 glFinish(); | 236 glFinish(); |
| 238 } | 237 } |
| 239 } | 238 } |
| 240 | 239 |
| 241 protected: | 240 protected: |
| 242 friend class base::RefCountedThreadSafe<TransferStateInternal>; | 241 friend class base::RefCounted<TransferStateInternal>; |
| 243 friend class AsyncPixelTransferDelegateAndroid; | 242 friend class AsyncPixelTransferDelegateAndroid; |
| 244 | 243 |
| 245 static void DeleteTexture(GLuint id) { | 244 static void DeleteTexture(GLuint id) { |
| 246 glDeleteTextures(1, &id); | 245 glDeleteTextures(1, &id); |
| 247 } | 246 } |
| 248 | 247 |
| 249 virtual ~TransferStateInternal() { | 248 virtual ~TransferStateInternal() { |
| 250 if (egl_image_ != EGL_NO_IMAGE_KHR) { | 249 if (egl_image_ != EGL_NO_IMAGE_KHR) { |
| 251 EGLDisplay display = eglGetCurrentDisplay(); | 250 EGLDisplay display = eglGetCurrentDisplay(); |
| 252 eglDestroyImageKHR(display, egl_image_); | 251 eglDestroyImageKHR(display, egl_image_); |
| (...skipping 58 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 311 // EGLImageKHR and another upload thread) | 310 // EGLImageKHR and another upload thread) |
| 312 class AsyncPixelTransferDelegateAndroid | 311 class AsyncPixelTransferDelegateAndroid |
| 313 : public AsyncPixelTransferDelegate, | 312 : public AsyncPixelTransferDelegate, |
| 314 public base::SupportsWeakPtr<AsyncPixelTransferDelegateAndroid> { | 313 public base::SupportsWeakPtr<AsyncPixelTransferDelegateAndroid> { |
| 315 public: | 314 public: |
| 316 AsyncPixelTransferDelegateAndroid(); | 315 AsyncPixelTransferDelegateAndroid(); |
| 317 virtual ~AsyncPixelTransferDelegateAndroid(); | 316 virtual ~AsyncPixelTransferDelegateAndroid(); |
| 318 | 317 |
| 319 // implement AsyncPixelTransferDelegate: | 318 // implement AsyncPixelTransferDelegate: |
| 320 virtual void AsyncNotifyCompletion( | 319 virtual void AsyncNotifyCompletion( |
| 321 const base::Closure& task) OVERRIDE; | 320 const AsyncMemoryParams& mem_params, |
| 321 const CompletionCallback& callback) OVERRIDE; |
| 322 virtual void AsyncTexImage2D( | 322 virtual void AsyncTexImage2D( |
| 323 AsyncPixelTransferState* state, | 323 AsyncPixelTransferState* state, |
| 324 const AsyncTexImage2DParams& tex_params, | 324 const AsyncTexImage2DParams& tex_params, |
| 325 const AsyncMemoryParams& mem_params) OVERRIDE; | 325 const AsyncMemoryParams& mem_params) OVERRIDE; |
| 326 virtual void AsyncTexSubImage2D( | 326 virtual void AsyncTexSubImage2D( |
| 327 AsyncPixelTransferState* state, | 327 AsyncPixelTransferState* state, |
| 328 const AsyncTexSubImage2DParams& tex_params, | 328 const AsyncTexSubImage2DParams& tex_params, |
| 329 const AsyncMemoryParams& mem_params) OVERRIDE; | 329 const AsyncMemoryParams& mem_params) OVERRIDE; |
| 330 virtual uint32 GetTextureUploadCount() OVERRIDE; | 330 virtual uint32 GetTextureUploadCount() OVERRIDE; |
| 331 virtual base::TimeDelta GetTotalTextureUploadTime() OVERRIDE; | 331 virtual base::TimeDelta GetTotalTextureUploadTime() OVERRIDE; |
| 332 | 332 |
| 333 private: | 333 private: |
| 334 // implement AsyncPixelTransferDelegate: | 334 // implement AsyncPixelTransferDelegate: |
| 335 virtual AsyncPixelTransferState* | 335 virtual AsyncPixelTransferState* |
| 336 CreateRawPixelTransferState(GLuint texture_id) OVERRIDE; | 336 CreateRawPixelTransferState(GLuint texture_id) OVERRIDE; |
| 337 | 337 |
| 338 void AsyncTexImage2DCompleted(scoped_refptr<TransferStateInternal> state); | 338 void AsyncTexImage2DCompleted(scoped_refptr<TransferStateInternal> state); |
| 339 void AsyncTexSubImage2DCompleted(scoped_refptr<TransferStateInternal> state); | 339 void AsyncTexSubImage2DCompleted(scoped_refptr<TransferStateInternal> state); |
| 340 | 340 |
| 341 static void PerformNotifyCompletion( |
| 342 AsyncMemoryParams mem_params, |
| 343 ScopedSafeSharedMemory* safe_shared_memory, |
| 344 const CompletionCallback& callback); |
| 341 static void PerformAsyncTexImage2D( | 345 static void PerformAsyncTexImage2D( |
| 342 TransferStateInternal* state, | 346 TransferStateInternal* state, |
| 343 AsyncTexImage2DParams tex_params, | 347 AsyncTexImage2DParams tex_params, |
| 344 AsyncMemoryParams mem_params, | 348 AsyncMemoryParams mem_params, |
| 345 ScopedSafeSharedMemory* safe_shared_memory); | 349 ScopedSafeSharedMemory* safe_shared_memory); |
| 346 static void PerformAsyncTexSubImage2D( | 350 static void PerformAsyncTexSubImage2D( |
| 347 TransferStateInternal* state, | 351 TransferStateInternal* state, |
| 348 AsyncTexSubImage2DParams tex_params, | 352 AsyncTexSubImage2DParams tex_params, |
| 349 AsyncMemoryParams mem_params, | 353 AsyncMemoryParams mem_params, |
| 350 ScopedSafeSharedMemory* safe_shared_memory); | 354 ScopedSafeSharedMemory* safe_shared_memory); |
| (...skipping 48 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 399 } | 403 } |
| 400 | 404 |
| 401 AsyncPixelTransferDelegateAndroid::~AsyncPixelTransferDelegateAndroid() { | 405 AsyncPixelTransferDelegateAndroid::~AsyncPixelTransferDelegateAndroid() { |
| 402 } | 406 } |
| 403 | 407 |
| 404 AsyncPixelTransferState* | 408 AsyncPixelTransferState* |
| 405 AsyncPixelTransferDelegateAndroid:: | 409 AsyncPixelTransferDelegateAndroid:: |
| 406 CreateRawPixelTransferState(GLuint texture_id) { | 410 CreateRawPixelTransferState(GLuint texture_id) { |
| 407 | 411 |
| 408 // We can't wait on uploads on imagination (it can take 200ms+). | 412 // We can't wait on uploads on imagination (it can take 200ms+). |
| 409 // In practice, they are complete when the CPU glSubTexImage2D completes. | 413 // In practice, they are complete when the CPU glTexSubImage2D completes. |
| 410 bool wait_for_uploads = !is_imagination_; | 414 bool wait_for_uploads = !is_imagination_; |
| 411 | 415 |
| 412 // Qualcomm has a race when using image_preserved=FALSE, | 416 // Qualcomm has a race when using image_preserved=FALSE, |
| 413 // which can result in black textures even after the first upload. | 417 // which can result in black textures even after the first upload. |
| 414 // Since using FALSE is mainly for performance (to avoid layout changes), | 418 // Since using FALSE is mainly for performance (to avoid layout changes), |
| 415 // but Qualcomm itself doesn't seem to get any performance benefit, | 419 // but Qualcomm itself doesn't seem to get any performance benefit, |
| 416 // we just using image_preservedd=TRUE on Qualcomm as a work-around. | 420 // we just using image_preservedd=TRUE on Qualcomm as a work-around. |
| 417 bool use_image_preserved = is_qualcomm_ || is_imagination_; | 421 bool use_image_preserved = is_qualcomm_ || is_imagination_; |
| 418 | 422 |
| 419 return static_cast<AsyncPixelTransferState*>( | 423 return static_cast<AsyncPixelTransferState*>( |
| 420 new AsyncTransferStateAndroid(texture_id, | 424 new AsyncTransferStateAndroid(texture_id, |
| 421 wait_for_uploads, | 425 wait_for_uploads, |
| 422 use_image_preserved)); | 426 use_image_preserved)); |
| 423 } | 427 } |
| 424 | 428 |
| 425 namespace { | |
| 426 // Dummy function to measure completion on | |
| 427 // the upload thread. | |
| 428 void NoOp() {} | |
| 429 } // namespace | |
| 430 | |
| 431 void AsyncPixelTransferDelegateAndroid::AsyncNotifyCompletion( | 429 void AsyncPixelTransferDelegateAndroid::AsyncNotifyCompletion( |
| 432 const base::Closure& task) { | 430 const AsyncMemoryParams& mem_params, |
| 433 // Post a no-op task to the upload thread followed | 431 const CompletionCallback& callback) { |
| 434 // by a reply to the callback. The reply will then occur after | 432 DCHECK(mem_params.shared_memory); |
| 435 // all async transfers are complete. | 433 DCHECK_LE(mem_params.shm_data_offset + mem_params.shm_data_size, |
| 436 transfer_message_loop_proxy()->PostTaskAndReply(FROM_HERE, | 434 mem_params.shm_size); |
| 437 base::Bind(&NoOp), task); | 435 // Post a PerformNotifyCompletion task to the upload thread. This task |
| 436 // will run after all async transfers are complete. |
| 437 transfer_message_loop_proxy()->PostTask( |
| 438 FROM_HERE, |
| 439 base::Bind(&AsyncPixelTransferDelegateAndroid::PerformNotifyCompletion, |
| 440 mem_params, |
| 441 base::Owned( |
| 442 new ScopedSafeSharedMemory(safe_shared_memory_pool(), |
| 443 mem_params.shared_memory, |
| 444 mem_params.shm_size)), |
| 445 callback)); |
| 438 } | 446 } |
| 439 | 447 |
| 440 void AsyncPixelTransferDelegateAndroid::AsyncTexImage2D( | 448 void AsyncPixelTransferDelegateAndroid::AsyncTexImage2D( |
| 441 AsyncPixelTransferState* transfer_state, | 449 AsyncPixelTransferState* transfer_state, |
| 442 const AsyncTexImage2DParams& tex_params, | 450 const AsyncTexImage2DParams& tex_params, |
| 443 const AsyncMemoryParams& mem_params) { | 451 const AsyncMemoryParams& mem_params) { |
| 444 scoped_refptr<TransferStateInternal> state = | 452 scoped_refptr<TransferStateInternal> state = |
| 445 static_cast<AsyncTransferStateAndroid*>(transfer_state)->internal_.get(); | 453 static_cast<AsyncTransferStateAndroid*>(transfer_state)->internal_.get(); |
| 446 DCHECK(mem_params.shared_memory); | 454 DCHECK(mem_params.shared_memory); |
| 447 DCHECK_LE(mem_params.shm_data_offset + mem_params.shm_data_size, | 455 DCHECK_LE(mem_params.shm_data_offset + mem_params.shm_data_size, |
| (...skipping 103 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 551 void SetGlParametersForEglImageTexture() { | 559 void SetGlParametersForEglImageTexture() { |
| 552 // These params are needed for EGLImage creation to succeed on several | 560 // These params are needed for EGLImage creation to succeed on several |
| 553 // Android devices. I couldn't find this requirement in the EGLImage | 561 // Android devices. I couldn't find this requirement in the EGLImage |
| 554 // extension spec, but several devices fail without it. | 562 // extension spec, but several devices fail without it. |
| 555 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR); | 563 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR); |
| 556 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE); | 564 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE); |
| 557 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE); | 565 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE); |
| 558 } | 566 } |
| 559 } // namespace | 567 } // namespace |
| 560 | 568 |
| 569 void AsyncPixelTransferDelegateAndroid::PerformNotifyCompletion( |
| 570 AsyncMemoryParams mem_params, |
| 571 ScopedSafeSharedMemory* safe_shared_memory, |
| 572 const CompletionCallback& callback) { |
| 573 TRACE_EVENT0("gpu", "PerformNotifyCompletion"); |
| 574 gfx::AsyncMemoryParams safe_mem_params = mem_params; |
| 575 safe_mem_params.shared_memory = safe_shared_memory->shared_memory(); |
| 576 callback.Run(safe_mem_params); |
| 577 } |
| 578 |
| 561 void AsyncPixelTransferDelegateAndroid::PerformAsyncTexImage2D( | 579 void AsyncPixelTransferDelegateAndroid::PerformAsyncTexImage2D( |
| 562 TransferStateInternal* state, | 580 TransferStateInternal* state, |
| 563 AsyncTexImage2DParams tex_params, | 581 AsyncTexImage2DParams tex_params, |
| 564 AsyncMemoryParams mem_params, | 582 AsyncMemoryParams mem_params, |
| 565 ScopedSafeSharedMemory* safe_shared_memory) { | 583 ScopedSafeSharedMemory* safe_shared_memory) { |
| 566 TRACE_EVENT2("gpu", "PerformAsyncTexImage", | 584 TRACE_EVENT2("gpu", "PerformAsyncTexImage", |
| 567 "width", tex_params.width, | 585 "width", tex_params.width, |
| 568 "height", tex_params.height); | 586 "height", tex_params.height); |
| 569 DCHECK(state); | 587 DCHECK(state); |
| 570 DCHECK(!state->thread_texture_id_); | 588 DCHECK(!state->thread_texture_id_); |
| (...skipping 64 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 635 { | 653 { |
| 636 TRACE_EVENT0("gpu", "glTexSubImage2D"); | 654 TRACE_EVENT0("gpu", "glTexSubImage2D"); |
| 637 DoTexSubImage2D(tex_params, data); | 655 DoTexSubImage2D(tex_params, data); |
| 638 } | 656 } |
| 639 state->WaitForLastUpload(); | 657 state->WaitForLastUpload(); |
| 640 | 658 |
| 641 DCHECK(CHECK_GL()); | 659 DCHECK(CHECK_GL()); |
| 642 state->last_transfer_time_ = base::TimeTicks::HighResNow() - begin_time; | 660 state->last_transfer_time_ = base::TimeTicks::HighResNow() - begin_time; |
| 643 } | 661 } |
| 644 | 662 |
| 645 | |
| 646 namespace { | 663 namespace { |
| 647 bool IsPowerOfTwo (unsigned int x) { | 664 bool IsPowerOfTwo (unsigned int x) { |
| 648 return ((x != 0) && !(x & (x - 1))); | 665 return ((x != 0) && !(x & (x - 1))); |
| 649 } | 666 } |
| 650 | 667 |
| 651 bool IsMultipleOfEight(unsigned int x) { | 668 bool IsMultipleOfEight(unsigned int x) { |
| 652 return (x & 7) == 0; | 669 return (x & 7) == 0; |
| 653 } | 670 } |
| 654 | 671 |
| 655 bool DimensionsSupportImgFastPath(int width, int height) { | 672 bool DimensionsSupportImgFastPath(int width, int height) { |
| (...skipping 93 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 749 DoTexImage2D(state->late_bind_define_params_, data); | 766 DoTexImage2D(state->late_bind_define_params_, data); |
| 750 } | 767 } |
| 751 texture_upload_count_++; | 768 texture_upload_count_++; |
| 752 total_texture_upload_time_ += base::TimeTicks::HighResNow() - begin_time; | 769 total_texture_upload_time_ += base::TimeTicks::HighResNow() - begin_time; |
| 753 | 770 |
| 754 DCHECK(CHECK_GL()); | 771 DCHECK(CHECK_GL()); |
| 755 return true; | 772 return true; |
| 756 } | 773 } |
| 757 | 774 |
| 758 } // namespace gfx | 775 } // namespace gfx |
| OLD | NEW |