| Index: ui/accelerated_widget_mac/io_surface_ns_gl_surface.mm
|
| diff --git a/ui/accelerated_widget_mac/io_surface_ns_gl_surface.mm b/ui/accelerated_widget_mac/io_surface_ns_gl_surface.mm
|
| index 46132a1eac2720c0f24d7628839a4800aca1ee16..9d1c26cd8f7578d8b53f9162e8e7cf69370dd0e5 100644
|
| --- a/ui/accelerated_widget_mac/io_surface_ns_gl_surface.mm
|
| +++ b/ui/accelerated_widget_mac/io_surface_ns_gl_surface.mm
|
| @@ -4,14 +4,18 @@
|
|
|
| #include "ui/accelerated_widget_mac/io_surface_ns_gl_surface.h"
|
|
|
| +#include <OpenGL/CGLRenderers.h>
|
| #include <OpenGL/GL.h>
|
|
|
| #include "base/callback_helpers.h"
|
| +#include "base/command_line.h"
|
| #include "base/mac/bind_objc_block.h"
|
| +#include "base/mac/mac_util.h"
|
| #include "base/mac/sdk_forward_declarations.h"
|
| #include "base/message_loop/message_loop.h"
|
| #include "base/trace_event/trace_event.h"
|
| #include "ui/base/cocoa/animation_utils.h"
|
| +#include "ui/base/ui_base_switches.h"
|
| #include "ui/gfx/geometry/dip_util.h"
|
| #include "ui/gfx/geometry/rect.h"
|
| #include "ui/gl/gpu_switching_manager.h"
|
| @@ -19,8 +23,11 @@
|
| namespace ui {
|
|
|
| IOSurfaceNSGLSurface* IOSurfaceNSGLSurface::Create(
|
| - IOSurfaceNSGLSurfaceClient* client, NSView* view) {
|
| - scoped_refptr<IOSurfaceTexture> iosurface = IOSurfaceTexture::Create(false);
|
| + IOSurfaceNSGLSurfaceClient* client,
|
| + NSView* view,
|
| + bool needs_gl_finish_workaround) {
|
| + scoped_refptr<IOSurfaceTexture> iosurface =
|
| + IOSurfaceTexture::Create(needs_gl_finish_workaround, true);
|
| if (!iosurface)
|
| return NULL;
|
|
|
| @@ -47,21 +54,25 @@ IOSurfaceNSGLSurface* IOSurfaceNSGLSurface::Create(
|
| return NULL;
|
| }
|
|
|
| - return new IOSurfaceNSGLSurface(client, view, ns_gl_context, iosurface);
|
| + return new IOSurfaceNSGLSurface(
|
| + client, view, needs_gl_finish_workaround, ns_gl_context, iosurface);
|
| }
|
|
|
| IOSurfaceNSGLSurface::IOSurfaceNSGLSurface(
|
| IOSurfaceNSGLSurfaceClient* client,
|
| NSView* view,
|
| + bool needs_gl_finish_workaround,
|
| base::scoped_nsobject<NSOpenGLContext> ns_gl_context,
|
| scoped_refptr<ui::IOSurfaceTexture> iosurface)
|
| : client_(client), view_(view), iosurface_(iosurface),
|
| ns_gl_context_(ns_gl_context), contents_scale_factor_(1),
|
| - pending_draw_exists_(false) {
|
| + pending_draw_exists_(false), needs_to_be_recreated_(false) {
|
| [[view_ layer] setContentsGravity:kCAGravityTopLeft];
|
| + ui::GpuSwitchingManager::GetInstance()->AddObserver(this);
|
| }
|
|
|
| IOSurfaceNSGLSurface::~IOSurfaceNSGLSurface() {
|
| + ui::GpuSwitchingManager::GetInstance()->RemoveObserver(this);
|
| DoPendingDrawIfNeeded();
|
| [ns_gl_context_ makeCurrentContext];
|
| iosurface_ = NULL;
|
| @@ -76,6 +87,7 @@ bool IOSurfaceNSGLSurface::GotFrame(IOSurfaceID io_surface_id,
|
| gfx::Size frame_pixel_size,
|
| float frame_scale_factor,
|
| gfx::Rect pixel_damage_rect) {
|
| + TRACE_EVENT0("ui", "IOSurfaceNSGLSurface::GotFrame");
|
| pending_draw_exists_ = true;
|
| pending_draw_damage_rect_.Union(pixel_damage_rect);
|
|
|
| @@ -109,8 +121,11 @@ bool IOSurfaceNSGLSurface::GotFrame(IOSurfaceID io_surface_id,
|
|
|
| bool result = iosurface_->SetIOSurface(io_surface_id, frame_pixel_size);
|
| [NSOpenGLContext clearCurrentContext];
|
| - if (!result)
|
| + if (!result) {
|
| + LOG(ERROR) << "Failed to set IOSurface, poisoning NSOpenGLContext.";
|
| + needs_to_be_recreated_ = true;
|
| return false;
|
| + }
|
|
|
| pending_draw_damage_rect_ = gfx::Rect(frame_pixel_size);
|
| }
|
| @@ -126,8 +141,12 @@ void IOSurfaceNSGLSurface::DoPendingDrawIfNeeded() {
|
| {
|
| TRACE_EVENT0("ui", "IOSurfaceNSGLSurface::Draw");
|
| [ns_gl_context_ makeCurrentContext];
|
| - ignore_result(iosurface_->DrawIOSurfaceWithDamageRect(
|
| - pending_draw_damage_rect_));
|
| + bool result = iosurface_->DrawIOSurfaceWithDamageRect(
|
| + pending_draw_damage_rect_);
|
| + if (!result) {
|
| + LOG(ERROR) << "Failed to draw IOSurface, poisoning NSOpenGLContext.";
|
| + needs_to_be_recreated_ = true;
|
| + }
|
| glFlush();
|
| [NSOpenGLContext clearCurrentContext];
|
| }
|
| @@ -138,4 +157,48 @@ void IOSurfaceNSGLSurface::DoPendingDrawIfNeeded() {
|
| client_->IOSurfaceNSGLSurfaceDidDrawFrame();
|
| }
|
|
|
| -};
|
| +int IOSurfaceNSGLSurface::GetRendererID() {
|
| + GLint current_renderer_id = -1;
|
| + CGLContextObj cgl_context = static_cast<CGLContextObj>(
|
| + [ns_gl_context_ CGLContextObj]);
|
| + if (CGLGetParameter(cgl_context,
|
| + kCGLCPCurrentRendererID,
|
| + ¤t_renderer_id) == kCGLNoError) {
|
| + return current_renderer_id & kCGLRendererIDMatchingMask;
|
| + }
|
| + return -1;
|
| +}
|
| +
|
| +void IOSurfaceNSGLSurface::OnGpuSwitched() {
|
| + needs_to_be_recreated_ = true;
|
| +}
|
| +
|
| +// static
|
| +bool IOSurfaceNSGLSurface::CanUseNSGLSurfaceForView(NSView* view) {
|
| + // This must be explicitly enabled at the command line.
|
| + static bool use_ns_gl_surfaces =
|
| + base::CommandLine::ForCurrentProcess()->HasSwitch(
|
| + switches::kEnableNSGLSurfaces);
|
| + if (!use_ns_gl_surfaces)
|
| + return false;
|
| +
|
| + // Do not attempt this before 10.9. The power savings are not worth the
|
| + // stability risk and testing burden.
|
| + if (!base::mac::IsOSMavericksOrLater())
|
| + return false;
|
| +
|
| + // If the NSView being attached to the NSOpenGLContext is not on the main
|
| + // monitor, then, due to an OS X bug, the IOSurface will be thrashed,
|
| + // resulting in hangs of 50 msec or more.
|
| + CGDirectDisplayID main_display = CGMainDisplayID();
|
| + NSScreen* screen = [[view window] screen];
|
| + NSDictionary* screen_description = [screen deviceDescription];
|
| + NSNumber* screen_number = [screen_description objectForKey:@"NSScreenNumber"];
|
| + CGDirectDisplayID display_id = [screen_number unsignedIntValue];
|
| + if (display_id != main_display)
|
| + return false;
|
| +
|
| + return true;
|
| +}
|
| +
|
| +} // namespace ui
|
|
|