Chromium Code Reviews| 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 | 162 class TransferStateInternal : public base::RefCounted<TransferStateInternal> { |
| 163 : public base::RefCountedThreadSafe<TransferStateInternal> { | |
| 164 public: | 163 public: |
| 165 explicit TransferStateInternal(GLuint texture_id, | 164 explicit TransferStateInternal(GLuint texture_id, |
| 166 bool wait_for_uploads, | 165 bool wait_for_uploads, |
| 167 bool use_image_preserved) | 166 bool use_image_preserved) |
| 168 : texture_id_(texture_id), | 167 : texture_id_(texture_id), |
| 169 thread_texture_id_(0), | 168 thread_texture_id_(0), |
| 170 needs_late_bind_(false), | 169 needs_late_bind_(false), |
| 171 transfer_in_progress_(false), | 170 transfer_in_progress_(false), |
| 172 egl_image_(EGL_NO_IMAGE_KHR), | 171 egl_image_(EGL_NO_IMAGE_KHR), |
| 173 wait_for_uploads_(wait_for_uploads), | 172 wait_for_uploads_(wait_for_uploads), |
| (...skipping 70 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 244 // GPU action that needs to occur. We could use fences and try | 243 // GPU action that needs to occur. We could use fences and try |
| 245 // to do this less often. However, on older drivers fences are | 244 // to do this less often. However, on older drivers fences are |
| 246 // not always reliable (eg. Mali-400 just blocks forever). | 245 // not always reliable (eg. Mali-400 just blocks forever). |
| 247 if (wait_for_uploads_) { | 246 if (wait_for_uploads_) { |
| 248 TRACE_EVENT0("gpu", "glFinish"); | 247 TRACE_EVENT0("gpu", "glFinish"); |
| 249 glFinish(); | 248 glFinish(); |
| 250 } | 249 } |
| 251 } | 250 } |
| 252 | 251 |
| 253 protected: | 252 protected: |
| 254 friend class base::RefCountedThreadSafe<TransferStateInternal>; | 253 friend class base::RefCounted<TransferStateInternal>; |
| 255 friend class AsyncPixelTransferDelegateAndroid; | 254 friend class AsyncPixelTransferDelegateAndroid; |
| 256 | 255 |
| 257 static void DeleteTexture(GLuint id) { | 256 static void DeleteTexture(GLuint id) { |
| 258 glDeleteTextures(1, &id); | 257 glDeleteTextures(1, &id); |
| 259 } | 258 } |
| 260 | 259 |
| 261 virtual ~TransferStateInternal() { | 260 virtual ~TransferStateInternal() { |
| 262 if (egl_image_ != EGL_NO_IMAGE_KHR) { | 261 if (egl_image_ != EGL_NO_IMAGE_KHR) { |
| 263 EGLDisplay display = eglGetCurrentDisplay(); | 262 EGLDisplay display = eglGetCurrentDisplay(); |
| 264 eglDestroyImageKHR(display, egl_image_); | 263 eglDestroyImageKHR(display, egl_image_); |
| (...skipping 58 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 323 // EGLImageKHR and another upload thread) | 322 // EGLImageKHR and another upload thread) |
| 324 class AsyncPixelTransferDelegateAndroid | 323 class AsyncPixelTransferDelegateAndroid |
| 325 : public AsyncPixelTransferDelegate, | 324 : public AsyncPixelTransferDelegate, |
| 326 public base::SupportsWeakPtr<AsyncPixelTransferDelegateAndroid> { | 325 public base::SupportsWeakPtr<AsyncPixelTransferDelegateAndroid> { |
| 327 public: | 326 public: |
| 328 AsyncPixelTransferDelegateAndroid(); | 327 AsyncPixelTransferDelegateAndroid(); |
| 329 virtual ~AsyncPixelTransferDelegateAndroid(); | 328 virtual ~AsyncPixelTransferDelegateAndroid(); |
| 330 | 329 |
| 331 // implement AsyncPixelTransferDelegate: | 330 // implement AsyncPixelTransferDelegate: |
| 332 virtual void AsyncNotifyCompletion( | 331 virtual void AsyncNotifyCompletion( |
| 333 const base::Closure& task) OVERRIDE; | 332 const AsyncMemoryParams& mem_params, |
| 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); | |
| 363 | 369 |
| 364 // Returns true if a work-around was used. | 370 // Returns true if a work-around was used. |
| 365 bool WorkAroundAsyncTexImage2D( | 371 bool WorkAroundAsyncTexImage2D( |
| 366 TransferStateInternal* state, | 372 TransferStateInternal* state, |
| 367 const AsyncTexImage2DParams& tex_params, | 373 const AsyncTexImage2DParams& tex_params, |
| 368 const AsyncMemoryParams& mem_params); | 374 const AsyncMemoryParams& mem_params); |
| 369 bool WorkAroundAsyncTexSubImage2D( | 375 bool WorkAroundAsyncTexSubImage2D( |
| 370 TransferStateInternal* state, | 376 TransferStateInternal* state, |
| 371 const AsyncTexSubImage2DParams& tex_params, | 377 const AsyncTexSubImage2DParams& tex_params, |
| 372 const AsyncMemoryParams& mem_params); | 378 const AsyncMemoryParams& mem_params); |
| (...skipping 48 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 421 } | 427 } |
| 422 | 428 |
| 423 AsyncPixelTransferDelegateAndroid::~AsyncPixelTransferDelegateAndroid() { | 429 AsyncPixelTransferDelegateAndroid::~AsyncPixelTransferDelegateAndroid() { |
| 424 } | 430 } |
| 425 | 431 |
| 426 AsyncPixelTransferState* | 432 AsyncPixelTransferState* |
| 427 AsyncPixelTransferDelegateAndroid:: | 433 AsyncPixelTransferDelegateAndroid:: |
| 428 CreateRawPixelTransferState(GLuint texture_id) { | 434 CreateRawPixelTransferState(GLuint texture_id) { |
| 429 | 435 |
| 430 // We can't wait on uploads on imagination (it can take 200ms+). | 436 // We can't wait on uploads on imagination (it can take 200ms+). |
| 431 // In practice, they are complete when the CPU glSubTexImage2D completes. | 437 // In practice, they are complete when the CPU glSubTexImage2D completes. |
|
greggman
2013/02/13 20:31:10
s/SubTex/TexSub/?
reveman
2013/02/13 20:40:55
Done.
| |
| 432 bool wait_for_uploads = !is_imagination_; | 438 bool wait_for_uploads = !is_imagination_; |
| 433 | 439 |
| 434 // Qualcomm has a race when using image_preserved=FALSE, | 440 // Qualcomm has a race when using image_preserved=FALSE, |
| 435 // which can result in black textures even after the first upload. | 441 // which can result in black textures even after the first upload. |
| 436 // Since using FALSE is mainly for performance (to avoid layout changes), | 442 // Since using FALSE is mainly for performance (to avoid layout changes), |
| 437 // but Qualcomm itself doesn't seem to get any performance benefit, | 443 // but Qualcomm itself doesn't seem to get any performance benefit, |
| 438 // we just using image_preservedd=TRUE on Qualcomm as a work-around. | 444 // we just using image_preservedd=TRUE on Qualcomm as a work-around. |
| 439 bool use_image_preserved = is_qualcomm_ || is_imagination_; | 445 bool use_image_preserved = is_qualcomm_ || is_imagination_; |
| 440 | 446 |
| 441 return static_cast<AsyncPixelTransferState*>( | 447 return static_cast<AsyncPixelTransferState*>( |
| 442 new AsyncTransferStateAndroid(texture_id, | 448 new AsyncTransferStateAndroid(texture_id, |
| 443 wait_for_uploads, | 449 wait_for_uploads, |
| 444 use_image_preserved)); | 450 use_image_preserved)); |
| 445 } | 451 } |
| 446 | 452 |
| 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 base::Closure& task) { | 454 const AsyncMemoryParams& mem_params, |
| 455 // Post a no-op task to the upload thread followed | 455 const CompletionCallback& callback) { |
| 456 // by a reply to the callback. The reply will then occur after | 456 DCHECK(mem_params.shared_memory); |
| 457 // all async transfers are complete. | 457 DCHECK_LE(mem_params.shm_data_offset + mem_params.shm_data_size, |
| 458 transfer_message_loop_proxy()->PostTaskAndReply(FROM_HERE, | 458 mem_params.shm_size); |
| 459 base::Bind(&NoOp), task); | 459 // Post a PerformNotifyCompletion task to the upload thread. This 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)); | |
| 460 } | 470 } |
| 461 | 471 |
| 462 void AsyncPixelTransferDelegateAndroid::AsyncTexImage2D( | 472 void AsyncPixelTransferDelegateAndroid::AsyncTexImage2D( |
| 463 AsyncPixelTransferState* transfer_state, | 473 AsyncPixelTransferState* transfer_state, |
| 464 const AsyncTexImage2DParams& tex_params, | 474 const AsyncTexImage2DParams& tex_params, |
| 465 const AsyncMemoryParams& mem_params) { | 475 const AsyncMemoryParams& mem_params) { |
| 466 scoped_refptr<TransferStateInternal> state = | 476 scoped_refptr<TransferStateInternal> state = |
| 467 static_cast<AsyncTransferStateAndroid*>(transfer_state)->internal_.get(); | 477 static_cast<AsyncTransferStateAndroid*>(transfer_state)->internal_.get(); |
| 468 DCHECK(mem_params.shared_memory); | 478 DCHECK(mem_params.shared_memory); |
| 469 DCHECK_LE(mem_params.shm_data_offset + mem_params.shm_data_size, | 479 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... | |
| 653 { | 663 { |
| 654 TRACE_EVENT0("gpu", "glTexSubImage2D"); | 664 TRACE_EVENT0("gpu", "glTexSubImage2D"); |
| 655 DoTexSubImage2D(tex_params, data); | 665 DoTexSubImage2D(tex_params, data); |
| 656 } | 666 } |
| 657 state->WaitForLastUpload(); | 667 state->WaitForLastUpload(); |
| 658 | 668 |
| 659 DCHECK(CHECK_GL()); | 669 DCHECK(CHECK_GL()); |
| 660 state->last_transfer_time_ = base::TimeTicks::HighResNow() - begin_time; | 670 state->last_transfer_time_ = base::TimeTicks::HighResNow() - begin_time; |
| 661 } | 671 } |
| 662 | 672 |
| 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 } | |
| 663 | 687 |
| 664 namespace { | 688 namespace { |
| 665 bool IsPowerOfTwo (unsigned int x) { | 689 bool IsPowerOfTwo (unsigned int x) { |
| 666 return ((x != 0) && !(x & (x - 1))); | 690 return ((x != 0) && !(x & (x - 1))); |
| 667 } | 691 } |
| 668 | 692 |
| 669 bool IsMultipleOfEight(unsigned int x) { | 693 bool IsMultipleOfEight(unsigned int x) { |
| 670 return (x & 7) == 0; | 694 return (x & 7) == 0; |
| 671 } | 695 } |
| 672 | 696 |
| (...skipping 78 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 751 DoTexSubImage2D(tex_params, data); | 775 DoTexSubImage2D(tex_params, data); |
| 752 } | 776 } |
| 753 texture_upload_count_++; | 777 texture_upload_count_++; |
| 754 total_texture_upload_time_ += base::TimeTicks::HighResNow() - begin_time; | 778 total_texture_upload_time_ += base::TimeTicks::HighResNow() - begin_time; |
| 755 | 779 |
| 756 DCHECK(CHECK_GL()); | 780 DCHECK(CHECK_GL()); |
| 757 return true; | 781 return true; |
| 758 } | 782 } |
| 759 | 783 |
| 760 } // namespace gfx | 784 } // namespace gfx |
| OLD | NEW |