| OLD | NEW |
| 1 // Copyright 2013 The Chromium Authors. All rights reserved. | 1 // Copyright 2013 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 "gpu/command_buffer/service/async_pixel_transfer_manager_egl.h" | 5 #include "gpu/command_buffer/service/async_pixel_transfer_manager_egl.h" |
| 6 | 6 |
| 7 #include <list> | 7 #include <list> |
| 8 #include <string> | 8 #include <string> |
| 9 | 9 |
| 10 #include "base/bind.h" | 10 #include "base/bind.h" |
| 11 #include "base/debug/trace_event.h" | 11 #include "base/debug/trace_event.h" |
| 12 #include "base/debug/trace_event_synthetic_delay.h" |
| 12 #include "base/lazy_instance.h" | 13 #include "base/lazy_instance.h" |
| 13 #include "base/logging.h" | 14 #include "base/logging.h" |
| 14 #include "base/memory/ref_counted.h" | 15 #include "base/memory/ref_counted.h" |
| 15 #include "base/synchronization/waitable_event.h" | 16 #include "base/synchronization/waitable_event.h" |
| 16 #include "base/threading/thread.h" | 17 #include "base/threading/thread.h" |
| 17 #include "gpu/command_buffer/service/async_pixel_transfer_delegate.h" | 18 #include "gpu/command_buffer/service/async_pixel_transfer_delegate.h" |
| 18 #include "gpu/command_buffer/service/safe_shared_memory_pool.h" | 19 #include "gpu/command_buffer/service/safe_shared_memory_pool.h" |
| 19 #include "ui/gl/gl_context.h" | 20 #include "ui/gl/gl_context.h" |
| 20 #include "ui/gl/gl_surface_egl.h" | 21 #include "ui/gl/gl_surface_egl.h" |
| 21 #include "ui/gl/scoped_binders.h" | 22 #include "ui/gl/scoped_binders.h" |
| (...skipping 208 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 230 if (wait_for_uploads_) { | 231 if (wait_for_uploads_) { |
| 231 TRACE_EVENT0("gpu", "glFinish"); | 232 TRACE_EVENT0("gpu", "glFinish"); |
| 232 glFinish(); | 233 glFinish(); |
| 233 } | 234 } |
| 234 } | 235 } |
| 235 | 236 |
| 236 void MarkAsTransferIsInProgress() { | 237 void MarkAsTransferIsInProgress() { |
| 237 transfer_completion_.Reset(); | 238 transfer_completion_.Reset(); |
| 238 } | 239 } |
| 239 | 240 |
| 240 void MarkAsCompleted() { | 241 void MarkAsCompleted(base::AtomicRefCount* pending_uploads) { |
| 242 if (!base::AtomicRefCountDec(pending_uploads)) |
| 243 TRACE_EVENT_SYNTHETIC_DELAY_APPLY("gpu.AsyncTexImage"); |
| 241 transfer_completion_.Signal(); | 244 transfer_completion_.Signal(); |
| 242 } | 245 } |
| 243 | 246 |
| 244 void WaitForTransferCompletion() { | 247 void WaitForTransferCompletion() { |
| 245 TRACE_EVENT0("gpu", "WaitForTransferCompletion"); | 248 TRACE_EVENT0("gpu", "WaitForTransferCompletion"); |
| 246 // TODO(backer): Deschedule the channel rather than blocking the main GPU | 249 // TODO(backer): Deschedule the channel rather than blocking the main GPU |
| 247 // thread (crbug.com/240265). | 250 // thread (crbug.com/240265). |
| 248 transfer_completion_.Wait(); | 251 transfer_completion_.Wait(); |
| 249 } | 252 } |
| 250 | 253 |
| 251 void PerformAsyncTexImage2D( | 254 void PerformAsyncTexImage2D( |
| 252 AsyncTexImage2DParams tex_params, | 255 AsyncTexImage2DParams tex_params, |
| 253 AsyncMemoryParams mem_params, | 256 AsyncMemoryParams mem_params, |
| 254 ScopedSafeSharedMemory* safe_shared_memory, | 257 ScopedSafeSharedMemory* safe_shared_memory, |
| 255 scoped_refptr<AsyncPixelTransferUploadStats> texture_upload_stats) { | 258 scoped_refptr<AsyncPixelTransferUploadStats> texture_upload_stats, |
| 259 base::AtomicRefCount* pending_uploads) { |
| 256 TRACE_EVENT2("gpu", | 260 TRACE_EVENT2("gpu", |
| 257 "PerformAsyncTexImage", | 261 "PerformAsyncTexImage", |
| 258 "width", | 262 "width", |
| 259 tex_params.width, | 263 tex_params.width, |
| 260 "height", | 264 "height", |
| 261 tex_params.height); | 265 tex_params.height); |
| 266 TRACE_EVENT_SYNTHETIC_DELAY_ACTIVATE("gpu.AsyncTexImage"); |
| 262 DCHECK(!thread_texture_id_); | 267 DCHECK(!thread_texture_id_); |
| 263 DCHECK_EQ(0, tex_params.level); | 268 DCHECK_EQ(0, tex_params.level); |
| 264 if (EGL_NO_IMAGE_KHR != egl_image_) { | 269 if (EGL_NO_IMAGE_KHR != egl_image_) { |
| 265 MarkAsCompleted(); | 270 MarkAsCompleted(pending_uploads); |
| 266 return; | 271 return; |
| 267 } | 272 } |
| 268 | 273 |
| 269 void* data = | 274 void* data = |
| 270 AsyncPixelTransferDelegate::GetAddress(safe_shared_memory, mem_params); | 275 AsyncPixelTransferDelegate::GetAddress(safe_shared_memory, mem_params); |
| 271 | 276 |
| 272 base::TimeTicks begin_time; | 277 base::TimeTicks begin_time; |
| 273 if (texture_upload_stats.get()) | 278 if (texture_upload_stats.get()) |
| 274 begin_time = base::TimeTicks::HighResNow(); | 279 begin_time = base::TimeTicks::HighResNow(); |
| 275 | 280 |
| (...skipping 19 matching lines...) Expand all Loading... |
| 295 { | 300 { |
| 296 TRACE_EVENT0("gpu", "glTexSubImage2D with data"); | 301 TRACE_EVENT0("gpu", "glTexSubImage2D with data"); |
| 297 | 302 |
| 298 // If we didn't use image_preserved, we haven't uploaded | 303 // If we didn't use image_preserved, we haven't uploaded |
| 299 // the data yet, so we do this with a full texSubImage. | 304 // the data yet, so we do this with a full texSubImage. |
| 300 if (!use_image_preserved_) | 305 if (!use_image_preserved_) |
| 301 DoFullTexSubImage2D(tex_params, data); | 306 DoFullTexSubImage2D(tex_params, data); |
| 302 } | 307 } |
| 303 | 308 |
| 304 WaitForLastUpload(); | 309 WaitForLastUpload(); |
| 305 MarkAsCompleted(); | 310 MarkAsCompleted(pending_uploads); |
| 306 | 311 |
| 307 DCHECK(CHECK_GL()); | 312 DCHECK(CHECK_GL()); |
| 308 if (texture_upload_stats.get()) { | 313 if (texture_upload_stats.get()) { |
| 309 texture_upload_stats->AddUpload(base::TimeTicks::HighResNow() - | 314 texture_upload_stats->AddUpload(base::TimeTicks::HighResNow() - |
| 310 begin_time); | 315 begin_time); |
| 311 } | 316 } |
| 312 } | 317 } |
| 313 | 318 |
| 314 void PerformAsyncTexSubImage2D( | 319 void PerformAsyncTexSubImage2D( |
| 315 AsyncTexSubImage2DParams tex_params, | 320 AsyncTexSubImage2DParams tex_params, |
| 316 AsyncMemoryParams mem_params, | 321 AsyncMemoryParams mem_params, |
| 317 ScopedSafeSharedMemory* safe_shared_memory, | 322 ScopedSafeSharedMemory* safe_shared_memory, |
| 318 scoped_refptr<AsyncPixelTransferUploadStats> texture_upload_stats) { | 323 scoped_refptr<AsyncPixelTransferUploadStats> texture_upload_stats, |
| 324 base::AtomicRefCount* pending_uploads ) { |
| 319 TRACE_EVENT2("gpu", | 325 TRACE_EVENT2("gpu", |
| 320 "PerformAsyncTexSubImage2D", | 326 "PerformAsyncTexSubImage2D", |
| 321 "width", | 327 "width", |
| 322 tex_params.width, | 328 tex_params.width, |
| 323 "height", | 329 "height", |
| 324 tex_params.height); | 330 tex_params.height); |
| 331 TRACE_EVENT_SYNTHETIC_DELAY_ACTIVATE("gpu.AsyncTexImage"); |
| 325 | 332 |
| 326 DCHECK_NE(EGL_NO_IMAGE_KHR, egl_image_); | 333 DCHECK_NE(EGL_NO_IMAGE_KHR, egl_image_); |
| 327 DCHECK_EQ(0, tex_params.level); | 334 DCHECK_EQ(0, tex_params.level); |
| 328 | 335 |
| 329 void* data = | 336 void* data = |
| 330 AsyncPixelTransferDelegate::GetAddress(safe_shared_memory, mem_params); | 337 AsyncPixelTransferDelegate::GetAddress(safe_shared_memory, mem_params); |
| 331 | 338 |
| 332 base::TimeTicks begin_time; | 339 base::TimeTicks begin_time; |
| 333 if (texture_upload_stats.get()) | 340 if (texture_upload_stats.get()) |
| 334 begin_time = base::TimeTicks::HighResNow(); | 341 begin_time = base::TimeTicks::HighResNow(); |
| 335 | 342 |
| 336 if (!thread_texture_id_) { | 343 if (!thread_texture_id_) { |
| 337 TRACE_EVENT0("gpu", "glEGLImageTargetTexture2DOES"); | 344 TRACE_EVENT0("gpu", "glEGLImageTargetTexture2DOES"); |
| 338 glGenTextures(1, &thread_texture_id_); | 345 glGenTextures(1, &thread_texture_id_); |
| 339 glActiveTexture(GL_TEXTURE0); | 346 glActiveTexture(GL_TEXTURE0); |
| 340 glBindTexture(GL_TEXTURE_2D, thread_texture_id_); | 347 glBindTexture(GL_TEXTURE_2D, thread_texture_id_); |
| 341 glEGLImageTargetTexture2DOES(GL_TEXTURE_2D, egl_image_); | 348 glEGLImageTargetTexture2DOES(GL_TEXTURE_2D, egl_image_); |
| 342 } else { | 349 } else { |
| 343 glActiveTexture(GL_TEXTURE0); | 350 glActiveTexture(GL_TEXTURE0); |
| 344 glBindTexture(GL_TEXTURE_2D, thread_texture_id_); | 351 glBindTexture(GL_TEXTURE_2D, thread_texture_id_); |
| 345 } | 352 } |
| 346 { | 353 { |
| 347 TRACE_EVENT0("gpu", "glTexSubImage2D"); | 354 TRACE_EVENT0("gpu", "glTexSubImage2D"); |
| 348 DoTexSubImage2D(tex_params, data); | 355 DoTexSubImage2D(tex_params, data); |
| 349 } | 356 } |
| 350 WaitForLastUpload(); | 357 WaitForLastUpload(); |
| 351 MarkAsCompleted(); | 358 MarkAsCompleted(pending_uploads); |
| 352 | 359 |
| 353 DCHECK(CHECK_GL()); | 360 DCHECK(CHECK_GL()); |
| 354 if (texture_upload_stats.get()) { | 361 if (texture_upload_stats.get()) { |
| 355 texture_upload_stats->AddUpload(base::TimeTicks::HighResNow() - | 362 texture_upload_stats->AddUpload(base::TimeTicks::HighResNow() - |
| 356 begin_time); | 363 begin_time); |
| 357 } | 364 } |
| 358 } | 365 } |
| 359 | 366 |
| 360 protected: | 367 protected: |
| 361 friend class base::RefCountedThreadSafe<TransferStateInternal>; | 368 friend class base::RefCountedThreadSafe<TransferStateInternal>; |
| (...skipping 151 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 513 DCHECK_EQ(state_->egl_image_, EGL_NO_IMAGE_KHR); | 520 DCHECK_EQ(state_->egl_image_, EGL_NO_IMAGE_KHR); |
| 514 DCHECK_EQ(static_cast<GLenum>(GL_TEXTURE_2D), tex_params.target); | 521 DCHECK_EQ(static_cast<GLenum>(GL_TEXTURE_2D), tex_params.target); |
| 515 DCHECK_EQ(tex_params.level, 0); | 522 DCHECK_EQ(tex_params.level, 0); |
| 516 | 523 |
| 517 // Mark the transfer in progress and save the late bind | 524 // Mark the transfer in progress and save the late bind |
| 518 // callback, so we can notify the client when it is bound. | 525 // callback, so we can notify the client when it is bound. |
| 519 shared_state_->pending_allocations.push_back(AsWeakPtr()); | 526 shared_state_->pending_allocations.push_back(AsWeakPtr()); |
| 520 state_->bind_callback_ = bind_callback; | 527 state_->bind_callback_ = bind_callback; |
| 521 | 528 |
| 522 // Mark the transfer in progress. | 529 // Mark the transfer in progress. |
| 530 base::AtomicRefCountInc(&shared_state_->pending_uploads); |
| 523 state_->MarkAsTransferIsInProgress(); | 531 state_->MarkAsTransferIsInProgress(); |
| 524 | 532 |
| 525 // Duplicate the shared memory so there is no way we can get | 533 // Duplicate the shared memory so there is no way we can get |
| 526 // a use-after-free of the raw pixels. | 534 // a use-after-free of the raw pixels. |
| 527 transfer_message_loop_proxy()->PostTask(FROM_HERE, | 535 transfer_message_loop_proxy()->PostTask(FROM_HERE, |
| 528 base::Bind( | 536 base::Bind( |
| 529 &TransferStateInternal::PerformAsyncTexImage2D, | 537 &TransferStateInternal::PerformAsyncTexImage2D, |
| 530 state_, | 538 state_, |
| 531 tex_params, | 539 tex_params, |
| 532 mem_params, | 540 mem_params, |
| 533 base::Owned(new ScopedSafeSharedMemory(safe_shared_memory_pool(), | 541 base::Owned(new ScopedSafeSharedMemory(safe_shared_memory_pool(), |
| 534 mem_params.shared_memory, | 542 mem_params.shared_memory, |
| 535 mem_params.shm_size)), | 543 mem_params.shm_size)), |
| 536 shared_state_->texture_upload_stats)); | 544 shared_state_->texture_upload_stats, |
| 545 &shared_state_->pending_uploads)); |
| 537 | 546 |
| 538 DCHECK(CHECK_GL()); | 547 DCHECK(CHECK_GL()); |
| 539 } | 548 } |
| 540 | 549 |
| 541 void AsyncPixelTransferDelegateEGL::AsyncTexSubImage2D( | 550 void AsyncPixelTransferDelegateEGL::AsyncTexSubImage2D( |
| 542 const AsyncTexSubImage2DParams& tex_params, | 551 const AsyncTexSubImage2DParams& tex_params, |
| 543 const AsyncMemoryParams& mem_params) { | 552 const AsyncMemoryParams& mem_params) { |
| 544 TRACE_EVENT2("gpu", "AsyncTexSubImage2D", | 553 TRACE_EVENT2("gpu", "AsyncTexSubImage2D", |
| 545 "width", tex_params.width, | 554 "width", tex_params.width, |
| 546 "height", tex_params.height); | 555 "height", tex_params.height); |
| 547 if (WorkAroundAsyncTexSubImage2D(tex_params, mem_params)) | 556 if (WorkAroundAsyncTexSubImage2D(tex_params, mem_params)) |
| 548 return; | 557 return; |
| 549 DCHECK(!state_->TransferIsInProgress()); | 558 DCHECK(!state_->TransferIsInProgress()); |
| 550 DCHECK(mem_params.shared_memory); | 559 DCHECK(mem_params.shared_memory); |
| 551 DCHECK_LE(mem_params.shm_data_offset + mem_params.shm_data_size, | 560 DCHECK_LE(mem_params.shm_data_offset + mem_params.shm_data_size, |
| 552 mem_params.shm_size); | 561 mem_params.shm_size); |
| 553 DCHECK_EQ(static_cast<GLenum>(GL_TEXTURE_2D), tex_params.target); | 562 DCHECK_EQ(static_cast<GLenum>(GL_TEXTURE_2D), tex_params.target); |
| 554 DCHECK_EQ(tex_params.level, 0); | 563 DCHECK_EQ(tex_params.level, 0); |
| 555 | 564 |
| 556 // Mark the transfer in progress. | 565 // Mark the transfer in progress. |
| 566 base::AtomicRefCountInc(&shared_state_->pending_uploads); |
| 557 state_->MarkAsTransferIsInProgress(); | 567 state_->MarkAsTransferIsInProgress(); |
| 558 | 568 |
| 559 // If this wasn't async allocated, we don't have an EGLImage yet. | 569 // If this wasn't async allocated, we don't have an EGLImage yet. |
| 560 // Create the EGLImage if it hasn't already been created. | 570 // Create the EGLImage if it hasn't already been created. |
| 561 state_->CreateEglImageOnMainThreadIfNeeded(); | 571 state_->CreateEglImageOnMainThreadIfNeeded(); |
| 562 | 572 |
| 563 // Duplicate the shared memory so there are no way we can get | 573 // Duplicate the shared memory so there are no way we can get |
| 564 // a use-after-free of the raw pixels. | 574 // a use-after-free of the raw pixels. |
| 565 transfer_message_loop_proxy()->PostTask(FROM_HERE, | 575 transfer_message_loop_proxy()->PostTask(FROM_HERE, |
| 566 base::Bind( | 576 base::Bind( |
| 567 &TransferStateInternal::PerformAsyncTexSubImage2D, | 577 &TransferStateInternal::PerformAsyncTexSubImage2D, |
| 568 state_, | 578 state_, |
| 569 tex_params, | 579 tex_params, |
| 570 mem_params, | 580 mem_params, |
| 571 base::Owned(new ScopedSafeSharedMemory(safe_shared_memory_pool(), | 581 base::Owned(new ScopedSafeSharedMemory(safe_shared_memory_pool(), |
| 572 mem_params.shared_memory, | 582 mem_params.shared_memory, |
| 573 mem_params.shm_size)), | 583 mem_params.shm_size)), |
| 574 shared_state_->texture_upload_stats)); | 584 shared_state_->texture_upload_stats, |
| 585 &shared_state_->pending_uploads)); |
| 575 | 586 |
| 576 DCHECK(CHECK_GL()); | 587 DCHECK(CHECK_GL()); |
| 577 } | 588 } |
| 578 | 589 |
| 579 namespace { | 590 namespace { |
| 580 bool IsPowerOfTwo (unsigned int x) { | 591 bool IsPowerOfTwo (unsigned int x) { |
| 581 return ((x != 0) && !(x & (x - 1))); | 592 return ((x != 0) && !(x & (x - 1))); |
| 582 } | 593 } |
| 583 | 594 |
| 584 bool IsMultipleOfEight(unsigned int x) { | 595 bool IsMultipleOfEight(unsigned int x) { |
| (...skipping 98 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 683 shared_state_->texture_upload_stats | 694 shared_state_->texture_upload_stats |
| 684 ->AddUpload(base::TimeTicks::HighResNow() - begin_time); | 695 ->AddUpload(base::TimeTicks::HighResNow() - begin_time); |
| 685 } | 696 } |
| 686 | 697 |
| 687 DCHECK(CHECK_GL()); | 698 DCHECK(CHECK_GL()); |
| 688 return true; | 699 return true; |
| 689 } | 700 } |
| 690 | 701 |
| 691 AsyncPixelTransferManagerEGL::SharedState::SharedState() | 702 AsyncPixelTransferManagerEGL::SharedState::SharedState() |
| 692 // TODO(reveman): Skip this if --enable-gpu-benchmarking is not present. | 703 // TODO(reveman): Skip this if --enable-gpu-benchmarking is not present. |
| 693 : texture_upload_stats(new AsyncPixelTransferUploadStats) { | 704 : texture_upload_stats(new AsyncPixelTransferUploadStats), |
| 705 pending_uploads(0) { |
| 694 std::string vendor; | 706 std::string vendor; |
| 695 vendor = reinterpret_cast<const char*>(glGetString(GL_VENDOR)); | 707 vendor = reinterpret_cast<const char*>(glGetString(GL_VENDOR)); |
| 696 is_imagination = vendor.find("Imagination") != std::string::npos; | 708 is_imagination = vendor.find("Imagination") != std::string::npos; |
| 697 is_qualcomm = vendor.find("Qualcomm") != std::string::npos; | 709 is_qualcomm = vendor.find("Qualcomm") != std::string::npos; |
| 698 } | 710 } |
| 699 | 711 |
| 700 AsyncPixelTransferManagerEGL::SharedState::~SharedState() {} | 712 AsyncPixelTransferManagerEGL::SharedState::~SharedState() {} |
| 701 | 713 |
| 702 AsyncPixelTransferManagerEGL::AsyncPixelTransferManagerEGL() {} | 714 AsyncPixelTransferManagerEGL::AsyncPixelTransferManagerEGL() {} |
| 703 | 715 |
| (...skipping 61 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 765 | 777 |
| 766 AsyncPixelTransferDelegate* | 778 AsyncPixelTransferDelegate* |
| 767 AsyncPixelTransferManagerEGL::CreatePixelTransferDelegateImpl( | 779 AsyncPixelTransferManagerEGL::CreatePixelTransferDelegateImpl( |
| 768 gles2::TextureRef* ref, | 780 gles2::TextureRef* ref, |
| 769 const AsyncTexImage2DParams& define_params) { | 781 const AsyncTexImage2DParams& define_params) { |
| 770 return new AsyncPixelTransferDelegateEGL( | 782 return new AsyncPixelTransferDelegateEGL( |
| 771 &shared_state_, ref->service_id(), define_params); | 783 &shared_state_, ref->service_id(), define_params); |
| 772 } | 784 } |
| 773 | 785 |
| 774 } // namespace gpu | 786 } // namespace gpu |
| OLD | NEW |