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 |