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 |