Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(101)

Side by Side Diff: content/browser/renderer_host/compositing_iosurface_mac.mm

Issue 10917307: Implement asynchronous operation for RWHVP::CopyFromCompositingSurface on Mac (Closed) Base URL: svn://svn.chromium.org/chrome/trunk/src
Patch Set: fixed comments Created 8 years, 2 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch | Annotate | Revision Log
OLDNEW
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 "content/browser/renderer_host/compositing_iosurface_mac.h" 5 #include "content/browser/renderer_host/compositing_iosurface_mac.h"
6 6
7 #include <OpenGL/OpenGL.h> 7 #include <OpenGL/OpenGL.h>
8 #include <vector> 8 #include <vector>
9 9
10 #include "base/command_line.h" 10 #include "base/command_line.h"
11 #include "base/debug/trace_event.h" 11 #include "base/debug/trace_event.h"
12 #include "base/message_loop.h"
12 #include "base/threading/platform_thread.h" 13 #include "base/threading/platform_thread.h"
13 #include "content/common/content_constants_internal.h" 14 #include "content/common/content_constants_internal.h"
14 #include "content/public/browser/browser_thread.h" 15 #include "content/public/browser/browser_thread.h"
15 #include "gpu/command_buffer/service/gpu_switches.h" 16 #include "gpu/command_buffer/service/gpu_switches.h"
16 #include "ui/gfx/rect.h" 17 #include "ui/gfx/rect.h"
17 #include "ui/gfx/scoped_ns_graphics_context_save_gstate_mac.h" 18 #include "ui/gfx/scoped_ns_graphics_context_save_gstate_mac.h"
18 #include "ui/gl/gl_context.h" 19 #include "ui/gl/gl_context.h"
19 #include "ui/gl/gl_switches.h" 20 #include "ui/gl/gl_switches.h"
20 #include "ui/surface/io_surface_support_mac.h" 21 #include "ui/surface/io_surface_support_mac.h"
21 22
(...skipping 76 matching lines...) Expand 10 before | Expand all | Expand 10 after
98 99
99 GLint error; 100 GLint error;
100 glGetProgramiv(program, GL_LINK_STATUS, &error); 101 glGetProgramiv(program, GL_LINK_STATUS, &error);
101 if (error != GL_TRUE) { 102 if (error != GL_TRUE) {
102 glDeleteProgram(program); 103 glDeleteProgram(program);
103 return 0; 104 return 0;
104 } 105 }
105 return program; 106 return program;
106 } 107 }
107 108
109 bool HasAppleFenceExtension() {
110 static bool initialized_has_fence = false;
111 static bool has_fence = false;
112
113 if (!initialized_has_fence) {
114 has_fence =
115 strstr(reinterpret_cast<const char*>(glGetString(GL_EXTENSIONS)),
116 "GL_APPLE_fence") != NULL;
117 initialized_has_fence = true;
118 }
119 return has_fence;
120 }
121
108 } // namespace 122 } // namespace
109 123
110 CVReturn DisplayLinkCallback(CVDisplayLinkRef display_link, 124 CVReturn DisplayLinkCallback(CVDisplayLinkRef display_link,
111 const CVTimeStamp* now, 125 const CVTimeStamp* now,
112 const CVTimeStamp* output_time, 126 const CVTimeStamp* output_time,
113 CVOptionFlags flags_in, 127 CVOptionFlags flags_in,
114 CVOptionFlags* flags_out, 128 CVOptionFlags* flags_out,
115 void* context) { 129 void* context) {
116 CompositingIOSurfaceMac* surface = 130 CompositingIOSurfaceMac* surface =
117 static_cast<CompositingIOSurfaceMac*>(context); 131 static_cast<CompositingIOSurfaceMac*>(context);
118 surface->DisplayLinkTick(display_link, output_time); 132 surface->DisplayLinkTick(display_link, output_time);
119 return kCVReturnSuccess; 133 return kCVReturnSuccess;
120 } 134 }
121 135
136 CompositingIOSurfaceMac::CopyContext::CopyContext() {
137 Reset();
138 }
139
140 CompositingIOSurfaceMac::CopyContext::~CopyContext() {
141 }
142
122 CompositingIOSurfaceMac* CompositingIOSurfaceMac::Create() { 143 CompositingIOSurfaceMac* CompositingIOSurfaceMac::Create() {
123 TRACE_EVENT0("browser", "CompositingIOSurfaceMac::Create"); 144 TRACE_EVENT0("browser", "CompositingIOSurfaceMac::Create");
124 IOSurfaceSupport* io_surface_support = IOSurfaceSupport::Initialize(); 145 IOSurfaceSupport* io_surface_support = IOSurfaceSupport::Initialize();
125 if (!io_surface_support) { 146 if (!io_surface_support) {
126 LOG(WARNING) << "No IOSurface support"; 147 LOG(WARNING) << "No IOSurface support";
127 return NULL; 148 return NULL;
128 } 149 }
129 150
130 std::vector<NSOpenGLPixelFormatAttribute> attributes; 151 std::vector<NSOpenGLPixelFormatAttribute> attributes;
131 attributes.push_back(NSOpenGLPFADoubleBuffer); 152 attributes.push_back(NSOpenGLPFADoubleBuffer);
(...skipping 130 matching lines...) Expand 10 before | Expand all | Expand 10 after
262 uint32* interval_numerator, 283 uint32* interval_numerator,
263 uint32* interval_denominator) { 284 uint32* interval_denominator) {
264 base::AutoLock lock(lock_); 285 base::AutoLock lock(lock_);
265 *timebase = vsync_timebase_; 286 *timebase = vsync_timebase_;
266 *interval_numerator = vsync_interval_numerator_; 287 *interval_numerator = vsync_interval_numerator_;
267 *interval_denominator = vsync_interval_denominator_; 288 *interval_denominator = vsync_interval_denominator_;
268 } 289 }
269 290
270 CompositingIOSurfaceMac::~CompositingIOSurfaceMac() { 291 CompositingIOSurfaceMac::~CompositingIOSurfaceMac() {
271 CVDisplayLinkRelease(display_link_); 292 CVDisplayLinkRelease(display_link_);
272 UnrefIOSurface(); 293 CGLSetCurrentContext(cglContext_);
294 CleanupResourcesForCopy();
295 UnrefIOSurfaceWithContextCurrent();
296 CGLSetCurrentContext(0);
273 } 297 }
274 298
275 void CompositingIOSurfaceMac::SetIOSurface(uint64 io_surface_handle, 299 void CompositingIOSurfaceMac::SetIOSurface(uint64 io_surface_handle,
276 const gfx::Size& size) { 300 const gfx::Size& size) {
277 pixel_io_surface_size_ = size; 301 pixel_io_surface_size_ = size;
278 CGLSetCurrentContext(cglContext_); 302 CGLSetCurrentContext(cglContext_);
279 MapIOSurfaceToTexture(io_surface_handle); 303 MapIOSurfaceToTexture(io_surface_handle);
280 CGLSetCurrentContext(0); 304 CGLSetCurrentContext(0);
281 } 305 }
282 306
(...skipping 95 matching lines...) Expand 10 before | Expand all | Expand 10 after
378 UNSHIPPED_TRACE_EVENT_INSTANT0("test_gpu", "CompositorSwapBuffersComplete"); 402 UNSHIPPED_TRACE_EVENT_INSTANT0("test_gpu", "CompositorSwapBuffersComplete");
379 403
380 CGLSetCurrentContext(0); 404 CGLSetCurrentContext(0);
381 405
382 StartOrContinueDisplayLink(); 406 StartOrContinueDisplayLink();
383 407
384 if (!is_vsync_disabled_) 408 if (!is_vsync_disabled_)
385 RateLimitDraws(); 409 RateLimitDraws();
386 } 410 }
387 411
388 bool CompositingIOSurfaceMac::CopyTo( 412 void CompositingIOSurfaceMac::CopyTo(
389 const gfx::Rect& src_pixel_subrect, 413 const gfx::Rect& src_pixel_subrect,
390 const gfx::Size& dst_pixel_size, 414 const gfx::Size& dst_pixel_size,
391 void* out) { 415 void* out,
392 if (!MapIOSurfaceToTexture(io_surface_handle_)) 416 const base::Callback<void(bool)>& callback) {
393 return false; 417 if (copy_context_.started) {
418 callback.Run(false);
419 return;
420 }
394 421
395 CGLSetCurrentContext(cglContext_); 422 CGLSetCurrentContext(cglContext_);
396 GLuint target = GL_TEXTURE_RECTANGLE_ARB; 423 if (!MapIOSurfaceToTexture(io_surface_handle_)) {
424 CGLSetCurrentContext(0);
425 callback.Run(false);
426 return;
427 }
397 428
398 GLuint dst_texture = 0; 429 TRACE_EVENT0("browser", "CompositingIOSurfaceMac::CopyTo()");
399 glGenTextures(1, &dst_texture); CHECK_GL_ERROR();
400 glBindTexture(target, dst_texture); CHECK_GL_ERROR();
401 430
402 GLuint dst_framebuffer = 0; 431 copy_context_.started = true;
403 glGenFramebuffersEXT(1, &dst_framebuffer); CHECK_GL_ERROR(); 432 copy_context_.src_rect = src_pixel_subrect;
404 glBindFramebufferEXT(GL_FRAMEBUFFER_EXT, dst_framebuffer); CHECK_GL_ERROR(); 433 copy_context_.dest_size = dst_pixel_size;
434 copy_context_.out_buf = out;
435 copy_context_.callback = callback;
405 436
406 glTexImage2D(target, 437 const bool use_fence = HasAppleFenceExtension();
438 if (use_fence) {
439 glGenFencesAPPLE(1, &copy_context_.fence); CHECK_GL_ERROR();
440 copy_context_.use_fence = true;
441 copy_context_.cycles_elapsed = 0;
442 }
443
444 // Create an offscreen framebuffer.
445 // This is used to render and scale a subrect of IOSurface.
446 const GLenum kTarget = GL_TEXTURE_RECTANGLE_ARB;
447 const int dest_width = copy_context_.dest_size.width();
448 const int dest_height = copy_context_.dest_size.height();
449
450 glGenTextures(1, &copy_context_.frame_buffer_texture); CHECK_GL_ERROR();
451 glBindTexture(kTarget, copy_context_.frame_buffer_texture); CHECK_GL_ERROR();
452 glGenFramebuffersEXT(1, &copy_context_.frame_buffer); CHECK_GL_ERROR();
453 glBindFramebufferEXT(GL_FRAMEBUFFER_EXT, copy_context_.frame_buffer);
454 CHECK_GL_ERROR();
455
456 glTexImage2D(kTarget,
407 0, 457 0,
408 GL_RGBA, 458 GL_RGBA,
409 dst_pixel_size.width(), 459 dest_width,
410 dst_pixel_size.height(), 460 dest_height,
411 0, 461 0,
412 GL_BGRA, 462 GL_BGRA,
413 GL_UNSIGNED_INT_8_8_8_8_REV, 463 GL_UNSIGNED_INT_8_8_8_8_REV,
414 NULL); CHECK_GL_ERROR(); 464 NULL); CHECK_GL_ERROR();
415 glFramebufferTexture2DEXT(GL_FRAMEBUFFER_EXT, 465 glFramebufferTexture2DEXT(GL_FRAMEBUFFER_EXT,
416 GL_COLOR_ATTACHMENT0_EXT, 466 GL_COLOR_ATTACHMENT0_EXT,
417 target, 467 kTarget,
418 dst_texture, 468 copy_context_.frame_buffer_texture,
419 0); CHECK_GL_ERROR(); 469 0); CHECK_GL_ERROR();
420 glBindTexture(target, 0); CHECK_GL_ERROR();
421 470
422 glViewport(0, 0, dst_pixel_size.width(), dst_pixel_size.height()); 471 glViewport(0, 0, dest_width, dest_height); CHECK_GL_ERROR();
472 glMatrixMode(GL_PROJECTION); CHECK_GL_ERROR();
473 glLoadIdentity(); CHECK_GL_ERROR();
474 glOrtho(0, dest_width, 0, dest_height, -1, 1); CHECK_GL_ERROR();
475 glMatrixMode(GL_MODELVIEW); CHECK_GL_ERROR();
476 glLoadIdentity(); CHECK_GL_ERROR();
423 477
424 glMatrixMode(GL_PROJECTION); 478 glDisable(GL_DEPTH_TEST); CHECK_GL_ERROR();
425 glLoadIdentity(); 479 glDisable(GL_BLEND); CHECK_GL_ERROR();
426 glOrtho(0, dst_pixel_size.width(), 0, dst_pixel_size.height(), -1, 1);
427 glMatrixMode(GL_MODELVIEW);
428 glLoadIdentity();
429 480
430 glDisable(GL_DEPTH_TEST); 481 glUseProgram(shader_program_blit_rgb_); CHECK_GL_ERROR();
431 glDisable(GL_BLEND);
432 482
433 glUseProgram(shader_program_blit_rgb_); 483 const int kTextureUnit = 0;
434 484 glUniform1i(blit_rgb_sampler_location_, kTextureUnit); CHECK_GL_ERROR();
435 int texture_unit = 0; 485 glActiveTexture(GL_TEXTURE0 + kTextureUnit); CHECK_GL_ERROR();
436 glUniform1i(blit_rgb_sampler_location_, texture_unit); 486 glBindTexture(kTarget, texture_); CHECK_GL_ERROR();
437 glActiveTexture(GL_TEXTURE0 + texture_unit); 487 glTexParameterf(kTarget, GL_TEXTURE_MIN_FILTER, GL_LINEAR); CHECK_GL_ERROR();
438 glBindTexture(GL_TEXTURE_RECTANGLE_ARB, texture_); 488 glTexParameterf(kTarget, GL_TEXTURE_MAG_FILTER, GL_NEAREST); CHECK_GL_ERROR();
439 489
440 SurfaceQuad quad; 490 SurfaceQuad quad;
441 quad.set_rect(0.0f, 0.0f, dst_pixel_size.width(), dst_pixel_size.height()); 491 quad.set_rect(0.0f, 0.0f, dest_width, dest_height); CHECK_GL_ERROR();
442 quad.set_texcoord_rect(src_pixel_subrect.x(), src_pixel_subrect.y(), 492 quad.set_texcoord_rect(
443 src_pixel_subrect.right(), src_pixel_subrect.bottom()); 493 copy_context_.src_rect.x(), copy_context_.src_rect.y(),
494 copy_context_.src_rect.right(), copy_context_.src_rect.bottom());
444 DrawQuad(quad); 495 DrawQuad(quad);
445 496
446 glBindTexture(GL_TEXTURE_RECTANGLE_ARB, 0); CHECK_GL_ERROR(); 497 glBindTexture(kTarget, 0); CHECK_GL_ERROR();
447 glUseProgram(0); 498 glUseProgram(0); CHECK_GL_ERROR();
448 499
449 CGLFlushDrawable(cglContext_); 500 // Copy the offscreen framebuffer to a PBO.
501 glGenBuffersARB(1, &copy_context_.pixel_buffer); CHECK_GL_ERROR();
502 glBindBufferARB(GL_PIXEL_PACK_BUFFER_ARB, copy_context_.pixel_buffer);
503 CHECK_GL_ERROR();
504 glBufferDataARB(GL_PIXEL_PACK_BUFFER_ARB,
505 dest_width * dest_height * 4,
506 NULL, GL_STREAM_READ_ARB); CHECK_GL_ERROR();
507 glReadPixels(0, 0, dest_width, dest_height, GL_BGRA,
508 GL_UNSIGNED_INT_8_8_8_8_REV, 0); CHECK_GL_ERROR();
450 509
451 glReadPixels(0, 0, dst_pixel_size.width(), dst_pixel_size.height(), 510 glBindBufferARB(GL_PIXEL_PACK_BUFFER_ARB, 0); CHECK_GL_ERROR();
452 GL_BGRA, GL_UNSIGNED_INT_8_8_8_8_REV, out);
453
454 glBindFramebufferEXT(GL_FRAMEBUFFER_EXT, 0); CHECK_GL_ERROR(); 511 glBindFramebufferEXT(GL_FRAMEBUFFER_EXT, 0); CHECK_GL_ERROR();
455 512
456 glDeleteFramebuffersEXT(1, &dst_framebuffer); 513 if (use_fence) {
457 glDeleteTextures(1, &dst_texture); 514 glSetFenceAPPLE(copy_context_.fence); CHECK_GL_ERROR();
515 }
516 glFlush(); CHECK_GL_ERROR();
517 CGLSetCurrentContext(0);
458 518
459 CGLSetCurrentContext(0); 519 // 20ms is an estimate assuming most hardware can complete asynchronous
460 return true; 520 // readback within this time limit. The timer will keep running until
521 // operation is completed.
522 const int kIntervalMilliseconds = 20;
523 copy_timer_.Start(FROM_HERE,
524 base::TimeDelta::FromMilliseconds(kIntervalMilliseconds),
525 this, &CompositingIOSurfaceMac::FinishCopy);
461 } 526 }
462 527
463 bool CompositingIOSurfaceMac::MapIOSurfaceToTexture( 528 bool CompositingIOSurfaceMac::MapIOSurfaceToTexture(
464 uint64 io_surface_handle) { 529 uint64 io_surface_handle) {
465 if (io_surface_.get() && io_surface_handle == io_surface_handle_) 530 if (io_surface_.get() && io_surface_handle == io_surface_handle_)
466 return true; 531 return true;
467 532
468 TRACE_EVENT0("browser", "CompositingIOSurfaceMac::MapIOSurfaceToTexture"); 533 TRACE_EVENT0("browser", "CompositingIOSurfaceMac::MapIOSurfaceToTexture");
469 UnrefIOSurfaceWithContextCurrent(); 534 UnrefIOSurfaceWithContextCurrent();
470 535
(...skipping 139 matching lines...) Expand 10 before | Expand all | Expand 10 after
610 CVDisplayLinkStart(display_link_); 675 CVDisplayLinkStart(display_link_);
611 } 676 }
612 display_link_stop_timer_.Reset(); 677 display_link_stop_timer_.Reset();
613 } 678 }
614 679
615 void CompositingIOSurfaceMac::StopDisplayLink() { 680 void CompositingIOSurfaceMac::StopDisplayLink() {
616 if (CVDisplayLinkIsRunning(display_link_)) 681 if (CVDisplayLinkIsRunning(display_link_))
617 CVDisplayLinkStop(display_link_); 682 CVDisplayLinkStop(display_link_);
618 } 683 }
619 684
685 void CompositingIOSurfaceMac::FinishCopy() {
686 CHECK(copy_context_.started);
687 TRACE_EVENT0("browser", "CompositingIOSurfaceMac::FinishCopy()");
688
689 CGLSetCurrentContext(cglContext_);
690
691 if (copy_context_.use_fence) {
692 bool copy_completed = glTestFenceAPPLE(copy_context_.fence);
693 CHECK_GL_ERROR();
694
695 // Allow 1s for the operation to complete.
696 const int kRetryCycles = 50;
697
698 if (!copy_completed && copy_context_.cycles_elapsed < kRetryCycles) {
699 ++copy_context_.cycles_elapsed;
700 CGLSetCurrentContext(0);
701 return;
702 }
703 }
704 copy_timer_.Stop();
705
706 glBindBufferARB(GL_PIXEL_PACK_BUFFER_ARB, copy_context_.pixel_buffer);
707 CHECK_GL_ERROR();
708
709 void* buf = glMapBuffer(GL_PIXEL_PACK_BUFFER_ARB, GL_READ_ONLY_ARB);
710 CHECK_GL_ERROR();
711
712 if (buf) {
713 memcpy(copy_context_.out_buf, buf, copy_context_.dest_size.GetArea() * 4);
714 glUnmapBufferARB(GL_PIXEL_PACK_BUFFER_ARB); CHECK_GL_ERROR();
715 }
716 glBindBufferARB(GL_PIXEL_PACK_BUFFER_ARB, 0); CHECK_GL_ERROR();
717
718 base::Callback<void(bool)> callback = copy_context_.callback;
719 CleanupResourcesForCopy();
720 CGLSetCurrentContext(0);
721
722 callback.Run(buf != NULL);
723 }
724
725 void CompositingIOSurfaceMac::CleanupResourcesForCopy() {
726 if (!copy_context_.started)
727 return;
728
729 glDeleteFramebuffersEXT(1, &copy_context_.frame_buffer); CHECK_GL_ERROR();
730 glDeleteTextures(1, &copy_context_.frame_buffer_texture); CHECK_GL_ERROR();
731 glDeleteBuffers(1, &copy_context_.pixel_buffer); CHECK_GL_ERROR();
732 if (copy_context_.use_fence) {
733 glDeleteFencesAPPLE(1, &copy_context_.fence); CHECK_GL_ERROR();
734 }
735 copy_context_.Reset();
736 }
737
620 } // namespace content 738 } // namespace content
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698