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 |