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

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: kTarget and linear Created 8 years, 3 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 90 matching lines...) Expand 10 before | Expand all | Expand 10 after
112 const CVTimeStamp* output_time, 113 const CVTimeStamp* output_time,
113 CVOptionFlags flags_in, 114 CVOptionFlags flags_in,
114 CVOptionFlags* flags_out, 115 CVOptionFlags* flags_out,
115 void* context) { 116 void* context) {
116 CompositingIOSurfaceMac* surface = 117 CompositingIOSurfaceMac* surface =
117 static_cast<CompositingIOSurfaceMac*>(context); 118 static_cast<CompositingIOSurfaceMac*>(context);
118 surface->DisplayLinkTick(display_link, output_time); 119 surface->DisplayLinkTick(display_link, output_time);
119 return kCVReturnSuccess; 120 return kCVReturnSuccess;
120 } 121 }
121 122
123 CompositingIOSurfaceMac::CopyContext::CopyContext() {
124 Reset();
125 }
126
127 CompositingIOSurfaceMac::CopyContext::~CopyContext() {
128 }
129
122 CompositingIOSurfaceMac* CompositingIOSurfaceMac::Create() { 130 CompositingIOSurfaceMac* CompositingIOSurfaceMac::Create() {
123 TRACE_EVENT0("browser", "CompositingIOSurfaceMac::Create"); 131 TRACE_EVENT0("browser", "CompositingIOSurfaceMac::Create");
124 IOSurfaceSupport* io_surface_support = IOSurfaceSupport::Initialize(); 132 IOSurfaceSupport* io_surface_support = IOSurfaceSupport::Initialize();
125 if (!io_surface_support) { 133 if (!io_surface_support) {
126 LOG(WARNING) << "No IOSurface support"; 134 LOG(WARNING) << "No IOSurface support";
127 return NULL; 135 return NULL;
128 } 136 }
129 137
130 std::vector<NSOpenGLPixelFormatAttribute> attributes; 138 std::vector<NSOpenGLPixelFormatAttribute> attributes;
131 attributes.push_back(NSOpenGLPFADoubleBuffer); 139 attributes.push_back(NSOpenGLPFADoubleBuffer);
(...skipping 82 matching lines...) Expand 10 before | Expand all | Expand 10 after
214 222
215 CompositingIOSurfaceMac::CompositingIOSurfaceMac( 223 CompositingIOSurfaceMac::CompositingIOSurfaceMac(
216 IOSurfaceSupport* io_surface_support, 224 IOSurfaceSupport* io_surface_support,
217 NSOpenGLContext* glContext, 225 NSOpenGLContext* glContext,
218 CGLContextObj cglContext, 226 CGLContextObj cglContext,
219 GLuint shader_program_blit_rgb, 227 GLuint shader_program_blit_rgb,
220 GLint blit_rgb_sampler_location, 228 GLint blit_rgb_sampler_location,
221 GLuint shader_program_white, 229 GLuint shader_program_white,
222 bool is_vsync_disabled, 230 bool is_vsync_disabled,
223 CVDisplayLinkRef display_link) 231 CVDisplayLinkRef display_link)
224 : io_surface_support_(io_surface_support), 232 : ALLOW_THIS_IN_INITIALIZER_LIST(weak_factory_(this)),
233 io_surface_support_(io_surface_support),
225 glContext_(glContext), 234 glContext_(glContext),
226 cglContext_(cglContext), 235 cglContext_(cglContext),
227 io_surface_handle_(0), 236 io_surface_handle_(0),
228 texture_(0), 237 texture_(0),
229 shader_program_blit_rgb_(shader_program_blit_rgb), 238 shader_program_blit_rgb_(shader_program_blit_rgb),
230 blit_rgb_sampler_location_(blit_rgb_sampler_location), 239 blit_rgb_sampler_location_(blit_rgb_sampler_location),
231 shader_program_white_(shader_program_white), 240 shader_program_white_(shader_program_white),
232 is_vsync_disabled_(is_vsync_disabled), 241 is_vsync_disabled_(is_vsync_disabled),
233 display_link_(display_link), 242 display_link_(display_link),
234 display_link_stop_timer_(FROM_HERE, base::TimeDelta::FromSeconds(1), 243 display_link_stop_timer_(FROM_HERE, base::TimeDelta::FromSeconds(1),
(...skipping 27 matching lines...) Expand all
262 uint32* interval_numerator, 271 uint32* interval_numerator,
263 uint32* interval_denominator) { 272 uint32* interval_denominator) {
264 base::AutoLock lock(lock_); 273 base::AutoLock lock(lock_);
265 *timebase = vsync_timebase_; 274 *timebase = vsync_timebase_;
266 *interval_numerator = vsync_interval_numerator_; 275 *interval_numerator = vsync_interval_numerator_;
267 *interval_denominator = vsync_interval_denominator_; 276 *interval_denominator = vsync_interval_denominator_;
268 } 277 }
269 278
270 CompositingIOSurfaceMac::~CompositingIOSurfaceMac() { 279 CompositingIOSurfaceMac::~CompositingIOSurfaceMac() {
271 CVDisplayLinkRelease(display_link_); 280 CVDisplayLinkRelease(display_link_);
272 UnrefIOSurface(); 281 CGLSetCurrentContext(cglContext_);
282 CleanupResourcesForCopy();
283 UnrefIOSurfaceWithContextCurrent();
284 CGLSetCurrentContext(0);
273 } 285 }
274 286
275 void CompositingIOSurfaceMac::SetIOSurface(uint64 io_surface_handle, 287 void CompositingIOSurfaceMac::SetIOSurface(uint64 io_surface_handle,
276 const gfx::Size& size) { 288 const gfx::Size& size) {
277 pixel_io_surface_size_ = size; 289 pixel_io_surface_size_ = size;
278 CGLSetCurrentContext(cglContext_); 290 CGLSetCurrentContext(cglContext_);
279 MapIOSurfaceToTexture(io_surface_handle); 291 MapIOSurfaceToTexture(io_surface_handle);
280 CGLSetCurrentContext(0); 292 CGLSetCurrentContext(0);
281 } 293 }
282 294
283 void CompositingIOSurfaceMac::DrawIOSurface(NSView* view, float scale_factor) { 295 void CompositingIOSurfaceMac::DrawIOSurface(NSView* view, float scale_factor) {
284 CGLSetCurrentContext(cglContext_); 296 CGLSetCurrentContext(cglContext_);
285
286 bool has_io_surface = MapIOSurfaceToTexture(io_surface_handle_); 297 bool has_io_surface = MapIOSurfaceToTexture(io_surface_handle_);
298 if (!has_io_surface)
299 return;
287 300
288 TRACE_EVENT1("browser", "CompositingIOSurfaceMac::DrawIOSurface", 301 TRACE_EVENT1("browser", "CompositingIOSurfaceMac::DrawIOSurface",
289 "has_io_surface", has_io_surface); 302 "has_io_surface", has_io_surface);
290 303
291 [glContext_ setView:view]; 304 [glContext_ setView:view];
292 gfx::Size window_size(NSSizeToCGSize([view frame].size)); 305 gfx::Size window_size(NSSizeToCGSize([view frame].size));
293 gfx::Size pixel_window_size = window_size.Scale(scale_factor); 306 gfx::Size pixel_window_size = window_size.Scale(scale_factor);
294 glViewport(0, 0, pixel_window_size.width(), pixel_window_size.height()); 307 glViewport(0, 0, pixel_window_size.width(), pixel_window_size.height());
295 308
296 // TODO: After a resolution change, the DPI-ness of the view and the 309 // TODO: After a resolution change, the DPI-ness of the view and the
(...skipping 81 matching lines...) Expand 10 before | Expand all | Expand 10 after
378 UNSHIPPED_TRACE_EVENT_INSTANT0("test_gpu", "CompositorSwapBuffersComplete"); 391 UNSHIPPED_TRACE_EVENT_INSTANT0("test_gpu", "CompositorSwapBuffersComplete");
379 392
380 CGLSetCurrentContext(0); 393 CGLSetCurrentContext(0);
381 394
382 StartOrContinueDisplayLink(); 395 StartOrContinueDisplayLink();
383 396
384 if (!is_vsync_disabled_) 397 if (!is_vsync_disabled_)
385 RateLimitDraws(); 398 RateLimitDraws();
386 } 399 }
387 400
388 bool CompositingIOSurfaceMac::CopyTo( 401 void CompositingIOSurfaceMac::CopyTo(
389 const gfx::Rect& src_pixel_subrect, 402 const gfx::Rect& src_pixel_subrect,
390 const gfx::Size& dst_pixel_size, 403 const gfx::Size& dst_pixel_size,
391 void* out) { 404 void* out,
392 if (!MapIOSurfaceToTexture(io_surface_handle_)) 405 const base::Callback<void(bool)>& callback) {
393 return false; 406 if (copy_context_.started) {
407 callback.Run(false);
408 return;
409 }
410
411 TRACE_EVENT0("browser", "CompositingIOSurfaceMac::CopyTo()");
394 412
395 CGLSetCurrentContext(cglContext_); 413 CGLSetCurrentContext(cglContext_);
396 GLuint target = GL_TEXTURE_RECTANGLE_ARB; 414 if (!MapIOSurfaceToTexture(io_surface_handle_)) {
415 CGLSetCurrentContext(0);
416 callback.Run(false);
417 return;
418 }
397 419
398 GLuint dst_texture = 0; 420 copy_context_.started = true;
399 glGenTextures(1, &dst_texture); CHECK_GL_ERROR(); 421 copy_context_.src_rect = src_pixel_subrect;
400 glBindTexture(target, dst_texture); CHECK_GL_ERROR(); 422 copy_context_.dest_size = dst_pixel_size;
423 copy_context_.out_buf = out;
424 copy_context_.callback = callback;
401 425
402 GLuint dst_framebuffer = 0; 426 // Create an offscreen framebuffer.
403 glGenFramebuffersEXT(1, &dst_framebuffer); CHECK_GL_ERROR(); 427 // This is used to render and scale a subrect of IOSurface.
404 glBindFramebufferEXT(GL_FRAMEBUFFER_EXT, dst_framebuffer); CHECK_GL_ERROR(); 428 const GLenum kTarget = GL_TEXTURE_RECTANGLE_ARB;
429 const int kDestWidth = copy_context_.dest_size.width();
430 const int kDestHeight = copy_context_.dest_size.height();
405 431
406 glTexImage2D(target, 432 glGenTextures(1, &copy_context_.frame_buffer_texture); CHECK_GL_ERROR();
433 glBindTexture(kTarget, copy_context_.frame_buffer_texture); CHECK_GL_ERROR();
434 glGenFramebuffersEXT(1, &copy_context_.frame_buffer); CHECK_GL_ERROR();
435 glBindFramebufferEXT(GL_FRAMEBUFFER_EXT, copy_context_.frame_buffer);
436 CHECK_GL_ERROR();
437
438 glTexImage2D(kTarget,
407 0, 439 0,
408 GL_RGBA, 440 GL_RGBA,
409 dst_pixel_size.width(), 441 kDestWidth,
410 dst_pixel_size.height(), 442 kDestHeight,
411 0, 443 0,
412 GL_BGRA, 444 GL_BGRA,
413 GL_UNSIGNED_INT_8_8_8_8_REV, 445 GL_UNSIGNED_INT_8_8_8_8_REV,
414 NULL); CHECK_GL_ERROR(); 446 NULL); CHECK_GL_ERROR();
415 glFramebufferTexture2DEXT(GL_FRAMEBUFFER_EXT, 447 glFramebufferTexture2DEXT(GL_FRAMEBUFFER_EXT,
416 GL_COLOR_ATTACHMENT0_EXT, 448 GL_COLOR_ATTACHMENT0_EXT,
417 target, 449 kTarget,
418 dst_texture, 450 copy_context_.frame_buffer_texture,
419 0); CHECK_GL_ERROR(); 451 0); CHECK_GL_ERROR();
420 glBindTexture(target, 0); CHECK_GL_ERROR();
421 452
422 glViewport(0, 0, dst_pixel_size.width(), dst_pixel_size.height()); 453 glViewport(0, 0, kDestWidth, kDestHeight); CHECK_GL_ERROR();
454 glMatrixMode(GL_PROJECTION); CHECK_GL_ERROR();
455 glLoadIdentity(); CHECK_GL_ERROR();
456 glOrtho(0, kDestWidth, 0, kDestHeight, -1, 1); CHECK_GL_ERROR();
457 glMatrixMode(GL_MODELVIEW); CHECK_GL_ERROR();
458 glLoadIdentity(); CHECK_GL_ERROR();
423 459
424 glMatrixMode(GL_PROJECTION); 460 glDisable(GL_DEPTH_TEST); CHECK_GL_ERROR();
425 glLoadIdentity(); 461 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 462
430 glDisable(GL_DEPTH_TEST); 463 glUseProgram(shader_program_blit_rgb_); CHECK_GL_ERROR();
431 glDisable(GL_BLEND);
432 464
433 glUseProgram(shader_program_blit_rgb_); 465 const int kTextureUnit = 0;
434 466 glUniform1i(blit_rgb_sampler_location_, kTextureUnit); CHECK_GL_ERROR();
435 int texture_unit = 0; 467 glActiveTexture(GL_TEXTURE0 + kTextureUnit); CHECK_GL_ERROR();
436 glUniform1i(blit_rgb_sampler_location_, texture_unit); 468 glBindTexture(kTarget, texture_); CHECK_GL_ERROR();
437 glActiveTexture(GL_TEXTURE0 + texture_unit); 469 glTexParameterf(kTarget, GL_TEXTURE_MIN_FILTER, GL_LINEAR); CHECK_GL_ERROR();
438 glBindTexture(GL_TEXTURE_RECTANGLE_ARB, texture_); 470 glTexParameterf(kTarget, GL_TEXTURE_MAG_FILTER, GL_NEAREST); CHECK_GL_ERROR();
439 471
440 SurfaceQuad quad; 472 SurfaceQuad quad;
441 quad.set_rect(0.0f, 0.0f, dst_pixel_size.width(), dst_pixel_size.height()); 473 quad.set_rect(0.0f, 0.0f, kDestWidth, kDestHeight); CHECK_GL_ERROR();
442 quad.set_texcoord_rect(src_pixel_subrect.x(), src_pixel_subrect.y(), 474 quad.set_texcoord_rect(
443 src_pixel_subrect.right(), src_pixel_subrect.bottom()); 475 copy_context_.src_rect.x(), copy_context_.src_rect.y(),
476 copy_context_.src_rect.right(), copy_context_.src_rect.bottom());
444 DrawQuad(quad); 477 DrawQuad(quad);
445 478
446 glBindTexture(GL_TEXTURE_RECTANGLE_ARB, 0); CHECK_GL_ERROR(); 479 glBindTexture(kTarget, 0); CHECK_GL_ERROR();
447 glUseProgram(0); 480 glUseProgram(0); CHECK_GL_ERROR();
448 481
449 CGLFlushDrawable(cglContext_); 482 // Copy the offscreen framebuffer to a PBO.
483 glGenBuffersARB(1, &copy_context_.pixel_buffer); CHECK_GL_ERROR();
484 glBindBufferARB(GL_PIXEL_PACK_BUFFER_ARB, copy_context_.pixel_buffer);
485 CHECK_GL_ERROR();
486 glBufferDataARB(GL_PIXEL_PACK_BUFFER_ARB,
487 kDestWidth * kDestHeight * 4,
488 NULL, GL_STREAM_READ_ARB); CHECK_GL_ERROR();
489 glReadPixels(0, 0, kDestWidth, kDestHeight, GL_BGRA,
490 GL_UNSIGNED_INT_8_8_8_8_REV, 0); CHECK_GL_ERROR();
450 491
451 glReadPixels(0, 0, dst_pixel_size.width(), dst_pixel_size.height(), 492 glBindBufferARB(GL_PIXEL_PACK_BUFFER_ARB, 0); CHECK_GL_ERROR();
452 GL_BGRA, GL_UNSIGNED_INT_8_8_8_8_REV, out); 493 glBindFramebufferEXT(GL_FRAMEBUFFER_EXT, 0); CHECK_GL_ERROR();
494 CGLSetCurrentContext(0);
453 495
454 glBindFramebufferEXT(GL_FRAMEBUFFER_EXT, 0); CHECK_GL_ERROR(); 496 // 30ms is an estimate assuming most hardware can complete asynchronous
497 // readback within this time limit.
498 const int kDelayMilliseconds = 30;
Ken Russell (switch to Gerrit) 2012/09/18 07:57:42 Please figure out some way to avoid having a heuri
455 499
456 glDeleteFramebuffersEXT(1, &dst_framebuffer); 500 MessageLoop::current()->PostDelayedTask(
457 glDeleteTextures(1, &dst_texture); 501 FROM_HERE,
458 502 base::Bind(&CompositingIOSurfaceMac::FinishCopy,
459 CGLSetCurrentContext(0); 503 weak_factory_.GetWeakPtr()),
460 return true; 504 base::TimeDelta::FromMilliseconds(kDelayMilliseconds)
505 );
461 } 506 }
462 507
463 bool CompositingIOSurfaceMac::MapIOSurfaceToTexture( 508 bool CompositingIOSurfaceMac::MapIOSurfaceToTexture(
464 uint64 io_surface_handle) { 509 uint64 io_surface_handle) {
465 if (io_surface_.get() && io_surface_handle == io_surface_handle_) 510 if (io_surface_.get() && io_surface_handle == io_surface_handle_)
466 return true; 511 return true;
467 512
468 TRACE_EVENT0("browser", "CompositingIOSurfaceMac::MapIOSurfaceToTexture"); 513 TRACE_EVENT0("browser", "CompositingIOSurfaceMac::MapIOSurfaceToTexture");
469 UnrefIOSurfaceWithContextCurrent(); 514 UnrefIOSurfaceWithContextCurrent();
470 515
(...skipping 139 matching lines...) Expand 10 before | Expand all | Expand 10 after
610 CVDisplayLinkStart(display_link_); 655 CVDisplayLinkStart(display_link_);
611 } 656 }
612 display_link_stop_timer_.Reset(); 657 display_link_stop_timer_.Reset();
613 } 658 }
614 659
615 void CompositingIOSurfaceMac::StopDisplayLink() { 660 void CompositingIOSurfaceMac::StopDisplayLink() {
616 if (CVDisplayLinkIsRunning(display_link_)) 661 if (CVDisplayLinkIsRunning(display_link_))
617 CVDisplayLinkStop(display_link_); 662 CVDisplayLinkStop(display_link_);
618 } 663 }
619 664
665 void CompositingIOSurfaceMac::FinishCopy() {
666 CHECK(copy_context_.started);
667 TRACE_EVENT0("browser", "CompositingIOSurfaceMac::FinishCopy()");
668
669 CGLSetCurrentContext(cglContext_);
670
671 const int kDestWidth = copy_context_.dest_size.width();
672 const int kDestHeight = copy_context_.dest_size.height();
673
674 glBindBufferARB(GL_PIXEL_PACK_BUFFER_ARB, copy_context_.pixel_buffer);
675 CHECK_GL_ERROR();
676
677 void* buf = glMapBuffer(GL_PIXEL_PACK_BUFFER_ARB, GL_READ_ONLY_ARB);
678 CHECK_GL_ERROR();
679
680 if (buf) {
681 memcpy(copy_context_.out_buf, buf, kDestWidth * kDestHeight * 4);
682 glUnmapBufferARB(GL_PIXEL_PACK_BUFFER_ARB); CHECK_GL_ERROR();
683 }
684 glBindBufferARB(GL_PIXEL_PACK_BUFFER_ARB, 0); CHECK_GL_ERROR();
685 CGLSetCurrentContext(0);
686
687 base::Callback<void(bool)> callback = copy_context_.callback;
688 CleanupResourcesForCopy();
689
690 callback.Run(buf != NULL);
691 }
692
693 void CompositingIOSurfaceMac::CleanupResourcesForCopy() {
694 if (!copy_context_.started)
695 return;
696
697 glDeleteFramebuffersEXT(1, &copy_context_.frame_buffer); CHECK_GL_ERROR();
698 glDeleteTextures(1, &copy_context_.frame_buffer_texture); CHECK_GL_ERROR();
699 glDeleteBuffers(1, &copy_context_.pixel_buffer); CHECK_GL_ERROR();
700 copy_context_.Reset();
701 }
702
620 } // namespace content 703 } // namespace content
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698