| 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 141 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 152 | 152 |
| 153 base::MessageLoopProxy* transfer_message_loop_proxy() { | 153 base::MessageLoopProxy* transfer_message_loop_proxy() { |
| 154 return g_transfer_thread.Pointer()->message_loop_proxy(); | 154 return g_transfer_thread.Pointer()->message_loop_proxy(); |
| 155 } | 155 } |
| 156 | 156 |
| 157 } // namespace | 157 } // namespace |
| 158 | 158 |
| 159 // Class which holds async pixel transfers state (EGLImage). | 159 // Class which holds async pixel transfers state (EGLImage). |
| 160 // The EGLImage is accessed by either thread, but everything | 160 // The EGLImage is accessed by either thread, but everything |
| 161 // else accessed only on the main thread. | 161 // else accessed only on the main thread. |
| 162 class TransferStateInternal : public base::RefCounted<TransferStateInternal> { | 162 class TransferStateInternal |
| 163 : public base::RefCountedThreadSafe<TransferStateInternal> { |
| 163 public: | 164 public: |
| 164 explicit TransferStateInternal(GLuint texture_id, | 165 explicit TransferStateInternal(GLuint texture_id, |
| 165 bool wait_for_uploads, | 166 bool wait_for_uploads, |
| 166 bool use_image_preserved) | 167 bool use_image_preserved) |
| 167 : texture_id_(texture_id), | 168 : texture_id_(texture_id), |
| 168 thread_texture_id_(0), | 169 thread_texture_id_(0), |
| 169 needs_late_bind_(false), | 170 needs_late_bind_(false), |
| 170 transfer_in_progress_(false), | 171 transfer_in_progress_(false), |
| 171 egl_image_(EGL_NO_IMAGE_KHR), | 172 egl_image_(EGL_NO_IMAGE_KHR), |
| 172 wait_for_uploads_(wait_for_uploads), | 173 wait_for_uploads_(wait_for_uploads), |
| (...skipping 70 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 243 // GPU action that needs to occur. We could use fences and try | 244 // GPU action that needs to occur. We could use fences and try |
| 244 // to do this less often. However, on older drivers fences are | 245 // to do this less often. However, on older drivers fences are |
| 245 // not always reliable (eg. Mali-400 just blocks forever). | 246 // not always reliable (eg. Mali-400 just blocks forever). |
| 246 if (wait_for_uploads_) { | 247 if (wait_for_uploads_) { |
| 247 TRACE_EVENT0("gpu", "glFinish"); | 248 TRACE_EVENT0("gpu", "glFinish"); |
| 248 glFinish(); | 249 glFinish(); |
| 249 } | 250 } |
| 250 } | 251 } |
| 251 | 252 |
| 252 protected: | 253 protected: |
| 253 friend class base::RefCounted<TransferStateInternal>; | 254 friend class base::RefCountedThreadSafe<TransferStateInternal>; |
| 254 friend class AsyncPixelTransferDelegateAndroid; | 255 friend class AsyncPixelTransferDelegateAndroid; |
| 255 | 256 |
| 256 static void DeleteTexture(GLuint id) { | 257 static void DeleteTexture(GLuint id) { |
| 257 glDeleteTextures(1, &id); | 258 glDeleteTextures(1, &id); |
| 258 } | 259 } |
| 259 | 260 |
| 260 virtual ~TransferStateInternal() { | 261 virtual ~TransferStateInternal() { |
| 261 if (egl_image_ != EGL_NO_IMAGE_KHR) { | 262 if (egl_image_ != EGL_NO_IMAGE_KHR) { |
| 262 EGLDisplay display = eglGetCurrentDisplay(); | 263 EGLDisplay display = eglGetCurrentDisplay(); |
| 263 eglDestroyImageKHR(display, egl_image_); | 264 eglDestroyImageKHR(display, egl_image_); |
| (...skipping 58 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 322 // EGLImageKHR and another upload thread) | 323 // EGLImageKHR and another upload thread) |
| 323 class AsyncPixelTransferDelegateAndroid | 324 class AsyncPixelTransferDelegateAndroid |
| 324 : public AsyncPixelTransferDelegate, | 325 : public AsyncPixelTransferDelegate, |
| 325 public base::SupportsWeakPtr<AsyncPixelTransferDelegateAndroid> { | 326 public base::SupportsWeakPtr<AsyncPixelTransferDelegateAndroid> { |
| 326 public: | 327 public: |
| 327 AsyncPixelTransferDelegateAndroid(); | 328 AsyncPixelTransferDelegateAndroid(); |
| 328 virtual ~AsyncPixelTransferDelegateAndroid(); | 329 virtual ~AsyncPixelTransferDelegateAndroid(); |
| 329 | 330 |
| 330 // implement AsyncPixelTransferDelegate: | 331 // implement AsyncPixelTransferDelegate: |
| 331 virtual void AsyncNotifyCompletion( | 332 virtual void AsyncNotifyCompletion( |
| 332 const AsyncMemoryParams& mem_params, | 333 const base::Closure& task) OVERRIDE; |
| 333 const CompletionCallback& callback) OVERRIDE; | |
| 334 virtual void AsyncTexImage2D( | 334 virtual void AsyncTexImage2D( |
| 335 AsyncPixelTransferState* state, | 335 AsyncPixelTransferState* state, |
| 336 const AsyncTexImage2DParams& tex_params, | 336 const AsyncTexImage2DParams& tex_params, |
| 337 const AsyncMemoryParams& mem_params) OVERRIDE; | 337 const AsyncMemoryParams& mem_params) OVERRIDE; |
| 338 virtual void AsyncTexSubImage2D( | 338 virtual void AsyncTexSubImage2D( |
| 339 AsyncPixelTransferState* state, | 339 AsyncPixelTransferState* state, |
| 340 const AsyncTexSubImage2DParams& tex_params, | 340 const AsyncTexSubImage2DParams& tex_params, |
| 341 const AsyncMemoryParams& mem_params) OVERRIDE; | 341 const AsyncMemoryParams& mem_params) OVERRIDE; |
| 342 virtual uint32 GetTextureUploadCount() OVERRIDE; | 342 virtual uint32 GetTextureUploadCount() OVERRIDE; |
| 343 virtual base::TimeDelta GetTotalTextureUploadTime() OVERRIDE; | 343 virtual base::TimeDelta GetTotalTextureUploadTime() OVERRIDE; |
| 344 | 344 |
| 345 private: | 345 private: |
| 346 // implement AsyncPixelTransferDelegate: | 346 // implement AsyncPixelTransferDelegate: |
| 347 virtual AsyncPixelTransferState* | 347 virtual AsyncPixelTransferState* |
| 348 CreateRawPixelTransferState(GLuint texture_id) OVERRIDE; | 348 CreateRawPixelTransferState(GLuint texture_id) OVERRIDE; |
| 349 | 349 |
| 350 void AsyncTexImage2DCompleted(scoped_refptr<TransferStateInternal> state); | 350 void AsyncTexImage2DCompleted(scoped_refptr<TransferStateInternal> state); |
| 351 void AsyncTexSubImage2DCompleted(scoped_refptr<TransferStateInternal> state); | 351 void AsyncTexSubImage2DCompleted(scoped_refptr<TransferStateInternal> state); |
| 352 | 352 |
| 353 static void PerformAsyncTexImage2D( | 353 static void PerformAsyncTexImage2D( |
| 354 TransferStateInternal* state, | 354 TransferStateInternal* state, |
| 355 AsyncTexImage2DParams tex_params, | 355 AsyncTexImage2DParams tex_params, |
| 356 base::SharedMemory* shared_memory, | 356 base::SharedMemory* shared_memory, |
| 357 uint32 shared_memory_data_offset); | 357 uint32 shared_memory_data_offset); |
| 358 static void PerformAsyncTexSubImage2D( | 358 static void PerformAsyncTexSubImage2D( |
| 359 TransferStateInternal* state, | 359 TransferStateInternal* state, |
| 360 AsyncTexSubImage2DParams tex_params, | 360 AsyncTexSubImage2DParams tex_params, |
| 361 base::SharedMemory* shared_memory, | 361 base::SharedMemory* shared_memory, |
| 362 uint32 shared_memory_data_offset); | 362 uint32 shared_memory_data_offset); |
| 363 static void PerformNotifyCompletion( | |
| 364 base::SharedMemory* shared_memory, | |
| 365 uint32 shared_memory_size, | |
| 366 uint32 shared_memory_data_offset, | |
| 367 uint32 shared_memory_data_size, | |
| 368 const CompletionCallback& callback); | |
| 369 | 363 |
| 370 // Returns true if a work-around was used. | 364 // Returns true if a work-around was used. |
| 371 bool WorkAroundAsyncTexImage2D( | 365 bool WorkAroundAsyncTexImage2D( |
| 372 TransferStateInternal* state, | 366 TransferStateInternal* state, |
| 373 const AsyncTexImage2DParams& tex_params, | 367 const AsyncTexImage2DParams& tex_params, |
| 374 const AsyncMemoryParams& mem_params); | 368 const AsyncMemoryParams& mem_params); |
| 375 bool WorkAroundAsyncTexSubImage2D( | 369 bool WorkAroundAsyncTexSubImage2D( |
| 376 TransferStateInternal* state, | 370 TransferStateInternal* state, |
| 377 const AsyncTexSubImage2DParams& tex_params, | 371 const AsyncTexSubImage2DParams& tex_params, |
| 378 const AsyncMemoryParams& mem_params); | 372 const AsyncMemoryParams& mem_params); |
| (...skipping 64 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 443 // but Qualcomm itself doesn't seem to get any performance benefit, | 437 // but Qualcomm itself doesn't seem to get any performance benefit, |
| 444 // we just using image_preservedd=TRUE on Qualcomm as a work-around. | 438 // we just using image_preservedd=TRUE on Qualcomm as a work-around. |
| 445 bool use_image_preserved = is_qualcomm_ || is_imagination_; | 439 bool use_image_preserved = is_qualcomm_ || is_imagination_; |
| 446 | 440 |
| 447 return static_cast<AsyncPixelTransferState*>( | 441 return static_cast<AsyncPixelTransferState*>( |
| 448 new AsyncTransferStateAndroid(texture_id, | 442 new AsyncTransferStateAndroid(texture_id, |
| 449 wait_for_uploads, | 443 wait_for_uploads, |
| 450 use_image_preserved)); | 444 use_image_preserved)); |
| 451 } | 445 } |
| 452 | 446 |
| 447 namespace { |
| 448 // Dummy function to measure completion on |
| 449 // the upload thread. |
| 450 void NoOp() {} |
| 451 } // namespace |
| 452 |
| 453 void AsyncPixelTransferDelegateAndroid::AsyncNotifyCompletion( | 453 void AsyncPixelTransferDelegateAndroid::AsyncNotifyCompletion( |
| 454 const AsyncMemoryParams& mem_params, | 454 const base::Closure& task) { |
| 455 const CompletionCallback& callback) { | 455 // Post a no-op task to the upload thread followed |
| 456 DCHECK(mem_params.shared_memory); | 456 // by a reply to the callback. The reply will then occur after |
| 457 DCHECK_LE(mem_params.shm_data_offset + mem_params.shm_data_size, | 457 // all async transfers are complete. |
| 458 mem_params.shm_size); | 458 transfer_message_loop_proxy()->PostTaskAndReply(FROM_HERE, |
| 459 // Post a PerformNotifyCompletion task to the upload thread. This task | 459 base::Bind(&NoOp), task); |
| 460 // will run after all async transfers are complete. | |
| 461 transfer_message_loop_proxy()->PostTask( | |
| 462 FROM_HERE, | |
| 463 base::Bind(&AsyncPixelTransferDelegateAndroid::PerformNotifyCompletion, | |
| 464 base::Owned(DuplicateSharedMemory(mem_params.shared_memory, | |
| 465 mem_params.shm_size)), | |
| 466 mem_params.shm_size, | |
| 467 mem_params.shm_data_offset, | |
| 468 mem_params.shm_data_size, | |
| 469 callback)); | |
| 470 } | 460 } |
| 471 | 461 |
| 472 void AsyncPixelTransferDelegateAndroid::AsyncTexImage2D( | 462 void AsyncPixelTransferDelegateAndroid::AsyncTexImage2D( |
| 473 AsyncPixelTransferState* transfer_state, | 463 AsyncPixelTransferState* transfer_state, |
| 474 const AsyncTexImage2DParams& tex_params, | 464 const AsyncTexImage2DParams& tex_params, |
| 475 const AsyncMemoryParams& mem_params) { | 465 const AsyncMemoryParams& mem_params) { |
| 476 scoped_refptr<TransferStateInternal> state = | 466 scoped_refptr<TransferStateInternal> state = |
| 477 static_cast<AsyncTransferStateAndroid*>(transfer_state)->internal_.get(); | 467 static_cast<AsyncTransferStateAndroid*>(transfer_state)->internal_.get(); |
| 478 DCHECK(mem_params.shared_memory); | 468 DCHECK(mem_params.shared_memory); |
| 479 DCHECK_LE(mem_params.shm_data_offset + mem_params.shm_data_size, | 469 DCHECK_LE(mem_params.shm_data_offset + mem_params.shm_data_size, |
| (...skipping 183 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 663 { | 653 { |
| 664 TRACE_EVENT0("gpu", "glTexSubImage2D"); | 654 TRACE_EVENT0("gpu", "glTexSubImage2D"); |
| 665 DoTexSubImage2D(tex_params, data); | 655 DoTexSubImage2D(tex_params, data); |
| 666 } | 656 } |
| 667 state->WaitForLastUpload(); | 657 state->WaitForLastUpload(); |
| 668 | 658 |
| 669 DCHECK(CHECK_GL()); | 659 DCHECK(CHECK_GL()); |
| 670 state->last_transfer_time_ = base::TimeTicks::HighResNow() - begin_time; | 660 state->last_transfer_time_ = base::TimeTicks::HighResNow() - begin_time; |
| 671 } | 661 } |
| 672 | 662 |
| 673 void AsyncPixelTransferDelegateAndroid::PerformNotifyCompletion( | |
| 674 base::SharedMemory* shared_memory, | |
| 675 uint32 shared_memory_size, | |
| 676 uint32 shared_memory_data_offset, | |
| 677 uint32 shared_memory_data_size, | |
| 678 const CompletionCallback& callback) { | |
| 679 TRACE_EVENT0("gpu", "PerformNotifyCompletion"); | |
| 680 gfx::AsyncMemoryParams mem_params; | |
| 681 mem_params.shared_memory = shared_memory; | |
| 682 mem_params.shm_size = shared_memory_size; | |
| 683 mem_params.shm_data_offset = shared_memory_data_offset; | |
| 684 mem_params.shm_data_size = shared_memory_data_size; | |
| 685 callback.Run(mem_params); | |
| 686 } | |
| 687 | 663 |
| 688 namespace { | 664 namespace { |
| 689 bool IsPowerOfTwo (unsigned int x) { | 665 bool IsPowerOfTwo (unsigned int x) { |
| 690 return ((x != 0) && !(x & (x - 1))); | 666 return ((x != 0) && !(x & (x - 1))); |
| 691 } | 667 } |
| 692 | 668 |
| 693 bool IsMultipleOfEight(unsigned int x) { | 669 bool IsMultipleOfEight(unsigned int x) { |
| 694 return (x & 7) == 0; | 670 return (x & 7) == 0; |
| 695 } | 671 } |
| 696 | 672 |
| (...skipping 78 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 775 DoTexSubImage2D(tex_params, data); | 751 DoTexSubImage2D(tex_params, data); |
| 776 } | 752 } |
| 777 texture_upload_count_++; | 753 texture_upload_count_++; |
| 778 total_texture_upload_time_ += base::TimeTicks::HighResNow() - begin_time; | 754 total_texture_upload_time_ += base::TimeTicks::HighResNow() - begin_time; |
| 779 | 755 |
| 780 DCHECK(CHECK_GL()); | 756 DCHECK(CHECK_GL()); |
| 781 return true; | 757 return true; |
| 782 } | 758 } |
| 783 | 759 |
| 784 } // namespace gfx | 760 } // namespace gfx |
| OLD | NEW |