Chromium Code Reviews| OLD | NEW |
|---|---|
| 1 // Copyright 2015 The Chromium Authors. All rights reserved. | 1 // Copyright 2015 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 "ui/accelerated_widget_mac/io_surface_ns_gl_surface.h" | 5 #include "ui/accelerated_widget_mac/io_surface_ns_gl_surface.h" |
| 6 | 6 |
| 7 #include <OpenGL/CGLRenderers.h> | |
| 7 #include <OpenGL/GL.h> | 8 #include <OpenGL/GL.h> |
| 8 | 9 |
| 9 #include "base/callback_helpers.h" | 10 #include "base/callback_helpers.h" |
| 11 #include "base/command_line.h" | |
| 10 #include "base/mac/bind_objc_block.h" | 12 #include "base/mac/bind_objc_block.h" |
| 13 #include "base/mac/mac_util.h" | |
| 11 #include "base/mac/sdk_forward_declarations.h" | 14 #include "base/mac/sdk_forward_declarations.h" |
| 12 #include "base/message_loop/message_loop.h" | 15 #include "base/message_loop/message_loop.h" |
| 13 #include "base/trace_event/trace_event.h" | 16 #include "base/trace_event/trace_event.h" |
| 14 #include "ui/base/cocoa/animation_utils.h" | 17 #include "ui/base/cocoa/animation_utils.h" |
| 18 #include "ui/base/ui_base_switches.h" | |
| 15 #include "ui/gfx/geometry/dip_util.h" | 19 #include "ui/gfx/geometry/dip_util.h" |
| 16 #include "ui/gfx/geometry/rect.h" | 20 #include "ui/gfx/geometry/rect.h" |
| 17 #include "ui/gl/gpu_switching_manager.h" | 21 #include "ui/gl/gpu_switching_manager.h" |
| 18 | 22 |
| 19 namespace ui { | 23 namespace ui { |
| 20 | 24 |
| 21 IOSurfaceNSGLSurface* IOSurfaceNSGLSurface::Create( | 25 IOSurfaceNSGLSurface* IOSurfaceNSGLSurface::Create( |
| 22 IOSurfaceNSGLSurfaceClient* client, NSView* view) { | 26 IOSurfaceNSGLSurfaceClient* client, |
| 23 scoped_refptr<IOSurfaceTexture> iosurface = IOSurfaceTexture::Create(false); | 27 NSView* view, |
| 28 bool needs_gl_finish_workaround) { | |
| 29 scoped_refptr<IOSurfaceTexture> iosurface = | |
| 30 IOSurfaceTexture::Create(needs_gl_finish_workaround, true); | |
| 24 if (!iosurface) | 31 if (!iosurface) |
| 25 return NULL; | 32 return NULL; |
| 26 | 33 |
| 27 std::vector<NSOpenGLPixelFormatAttribute> attribs; | 34 std::vector<NSOpenGLPixelFormatAttribute> attribs; |
| 28 attribs.push_back(NSOpenGLPFAColorSize); | 35 attribs.push_back(NSOpenGLPFAColorSize); |
| 29 attribs.push_back(24); | 36 attribs.push_back(24); |
| 30 attribs.push_back(NSOpenGLPFAAlphaSize); | 37 attribs.push_back(NSOpenGLPFAAlphaSize); |
| 31 attribs.push_back(8); | 38 attribs.push_back(8); |
| 32 attribs.push_back(NSOpenGLPFAAccelerated); | 39 attribs.push_back(NSOpenGLPFAAccelerated); |
| 33 if (ui::GpuSwitchingManager::GetInstance()->SupportsDualGpus()) | 40 if (ui::GpuSwitchingManager::GetInstance()->SupportsDualGpus()) |
| 34 attribs.push_back(NSOpenGLPFAAllowOfflineRenderers); | 41 attribs.push_back(NSOpenGLPFAAllowOfflineRenderers); |
| 35 attribs.push_back(0); | 42 attribs.push_back(0); |
| 36 base::scoped_nsobject<NSOpenGLPixelFormat> pixel_format( | 43 base::scoped_nsobject<NSOpenGLPixelFormat> pixel_format( |
| 37 [[NSOpenGLPixelFormat alloc] initWithAttributes:&attribs.front()]); | 44 [[NSOpenGLPixelFormat alloc] initWithAttributes:&attribs.front()]); |
| 38 if (!pixel_format) { | 45 if (!pixel_format) { |
| 39 LOG(ERROR) << "Failed to create pixel format object."; | 46 LOG(ERROR) << "Failed to create pixel format object."; |
| 40 return NULL; | 47 return NULL; |
| 41 } | 48 } |
| 42 | 49 |
| 43 base::scoped_nsobject<NSOpenGLContext> ns_gl_context( | 50 base::scoped_nsobject<NSOpenGLContext> ns_gl_context( |
| 44 [[NSOpenGLContext alloc] initWithFormat:pixel_format shareContext:nil]); | 51 [[NSOpenGLContext alloc] initWithFormat:pixel_format shareContext:nil]); |
| 45 if (!ns_gl_context) { | 52 if (!ns_gl_context) { |
| 46 LOG(ERROR) << "Failed to create context object."; | 53 LOG(ERROR) << "Failed to create context object."; |
| 47 return NULL; | 54 return NULL; |
| 48 } | 55 } |
| 49 | 56 |
| 50 return new IOSurfaceNSGLSurface(client, view, ns_gl_context, iosurface); | 57 return new IOSurfaceNSGLSurface( |
| 58 client, view, needs_gl_finish_workaround, ns_gl_context, iosurface); | |
| 51 } | 59 } |
| 52 | 60 |
| 53 IOSurfaceNSGLSurface::IOSurfaceNSGLSurface( | 61 IOSurfaceNSGLSurface::IOSurfaceNSGLSurface( |
| 54 IOSurfaceNSGLSurfaceClient* client, | 62 IOSurfaceNSGLSurfaceClient* client, |
| 55 NSView* view, | 63 NSView* view, |
| 64 bool needs_gl_finish_workaround, | |
| 56 base::scoped_nsobject<NSOpenGLContext> ns_gl_context, | 65 base::scoped_nsobject<NSOpenGLContext> ns_gl_context, |
| 57 scoped_refptr<ui::IOSurfaceTexture> iosurface) | 66 scoped_refptr<ui::IOSurfaceTexture> iosurface) |
| 58 : client_(client), view_(view), iosurface_(iosurface), | 67 : client_(client), view_(view), iosurface_(iosurface), |
| 59 ns_gl_context_(ns_gl_context), contents_scale_factor_(1), | 68 ns_gl_context_(ns_gl_context), contents_scale_factor_(1), |
| 60 pending_draw_exists_(false) { | 69 pending_draw_exists_(false) { |
| 61 [[view_ layer] setContentsGravity:kCAGravityTopLeft]; | 70 [[view_ layer] setContentsGravity:kCAGravityTopLeft]; |
| 62 } | 71 } |
| 63 | 72 |
| 64 IOSurfaceNSGLSurface::~IOSurfaceNSGLSurface() { | 73 IOSurfaceNSGLSurface::~IOSurfaceNSGLSurface() { |
| 65 DoPendingDrawIfNeeded(); | 74 DoPendingDrawIfNeeded(); |
| 66 [ns_gl_context_ makeCurrentContext]; | 75 [ns_gl_context_ makeCurrentContext]; |
| 67 iosurface_ = NULL; | 76 iosurface_ = NULL; |
| 68 [NSOpenGLContext clearCurrentContext]; | 77 [NSOpenGLContext clearCurrentContext]; |
| 69 [ns_gl_context_ clearDrawable]; | 78 [ns_gl_context_ clearDrawable]; |
| 70 | 79 |
| 71 ScopedCAActionDisabler disabler; | 80 ScopedCAActionDisabler disabler; |
| 72 [[view_ layer] setContents:nil]; | 81 [[view_ layer] setContents:nil]; |
| 73 } | 82 } |
| 74 | 83 |
| 75 bool IOSurfaceNSGLSurface::GotFrame(IOSurfaceID io_surface_id, | 84 bool IOSurfaceNSGLSurface::GotFrame(IOSurfaceID io_surface_id, |
| 76 gfx::Size frame_pixel_size, | 85 gfx::Size frame_pixel_size, |
| 77 float frame_scale_factor, | 86 float frame_scale_factor, |
| 78 gfx::Rect pixel_damage_rect) { | 87 gfx::Rect pixel_damage_rect) { |
| 88 TRACE_EVENT0("ui", "IOSurfaceNSGLSurface::GotFrame"); | |
| 79 pending_draw_exists_ = true; | 89 pending_draw_exists_ = true; |
| 80 pending_draw_damage_rect_.Union(pixel_damage_rect); | 90 pending_draw_damage_rect_.Union(pixel_damage_rect); |
| 81 | 91 |
| 82 // If the OpenGL framebuffer does not match the frame in scale factor or | 92 // If the OpenGL framebuffer does not match the frame in scale factor or |
| 83 // pixel size, then re-latch them. Note that they will latch to the layer's | 93 // pixel size, then re-latch them. Note that they will latch to the layer's |
| 84 // bounds, which will not necessarily match the frame's pixel size. | 94 // bounds, which will not necessarily match the frame's pixel size. |
| 85 if (!iosurface_->IsUpToDate(io_surface_id, frame_pixel_size) || | 95 if (!iosurface_->IsUpToDate(io_surface_id, frame_pixel_size) || |
| 86 [ns_gl_context_ view] != view_ || | 96 [ns_gl_context_ view] != view_ || |
| 87 frame_pixel_size != contents_pixel_size_ || | 97 frame_pixel_size != contents_pixel_size_ || |
| 88 frame_scale_factor != contents_scale_factor_) { | 98 frame_scale_factor != contents_scale_factor_) { |
| (...skipping 42 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 131 glFlush(); | 141 glFlush(); |
| 132 [NSOpenGLContext clearCurrentContext]; | 142 [NSOpenGLContext clearCurrentContext]; |
| 133 } | 143 } |
| 134 | 144 |
| 135 pending_draw_exists_ = false; | 145 pending_draw_exists_ = false; |
| 136 pending_draw_damage_rect_ = gfx::Rect(); | 146 pending_draw_damage_rect_ = gfx::Rect(); |
| 137 | 147 |
| 138 client_->IOSurfaceNSGLSurfaceDidDrawFrame(); | 148 client_->IOSurfaceNSGLSurfaceDidDrawFrame(); |
| 139 } | 149 } |
| 140 | 150 |
| 141 }; | 151 int IOSurfaceNSGLSurface::GetRendererID() { |
| 152 GLint current_renderer_id = -1; | |
| 153 CGLContextObj cgl_context = static_cast<CGLContextObj>( | |
|
Andre
2015/06/10 05:23:39
Why do you need this cast?
ccameron
2015/06/10 21:39:51
-[NSOpenGLContext CGLContextObj] returns a void*,
| |
| 154 [ns_gl_context_ CGLContextObj]); | |
| 155 if (CGLGetParameter(cgl_context, | |
| 156 kCGLCPCurrentRendererID, | |
| 157 ¤t_renderer_id) == kCGLNoError) { | |
| 158 return current_renderer_id & kCGLRendererIDMatchingMask; | |
| 159 } | |
| 160 return -1; | |
| 161 } | |
| 162 | |
| 163 // static | |
| 164 bool IOSurfaceNSGLSurface::CanUseNSGLSurfaceForView(NSView* view) { | |
| 165 // This must be explicitly enabled at the command line. | |
| 166 static bool use_ns_gl_surfaces = | |
| 167 base::CommandLine::ForCurrentProcess()->HasSwitch( | |
| 168 switches::kEnableNSGLSurfaces); | |
| 169 if (!use_ns_gl_surfaces) | |
| 170 return false; | |
| 171 | |
| 172 // Do not attempt this before 10.9. The power savings are not worth the | |
| 173 // stability risk and testing burden. | |
| 174 if (!base::mac::IsOSMavericksOrLater()) | |
| 175 return false; | |
| 176 | |
| 177 // If the NSView being attached to the NSOpenGLContext is not on the main | |
| 178 // monitor, then, due to an OS X bug, the IOSurface will be thrashed, | |
| 179 // resulting in hangs of 50 msec or more. | |
| 180 CGDirectDisplayID main_display = CGMainDisplayID(); | |
| 181 NSScreen* screen = [[view window] screen]; | |
| 182 NSDictionary* screen_description = [screen deviceDescription]; | |
| 183 NSNumber* screen_number = [screen_description objectForKey:@"NSScreenNumber"]; | |
| 184 CGDirectDisplayID display_id = [screen_number unsignedIntValue]; | |
| 185 if (display_id != main_display) | |
| 186 return false; | |
| 187 | |
| 188 return true; | |
| 189 } | |
| 190 | |
| 191 } // namespace ui | |
| OLD | NEW |