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 |