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

Side by Side Diff: ui/accelerated_widget_mac/io_surface_ns_gl_surface.mm

Issue 1164363005: Mac: Only allow NSOpenGLContext displaying on the main display (Closed) Base URL: https://chromium.googlesource.com/chromium/src.git@master
Patch Set: Add GPU switch Created 5 years, 6 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
OLDNEW
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), needs_to_be_recreated_(false) {
61 [[view_ layer] setContentsGravity:kCAGravityTopLeft]; 70 [[view_ layer] setContentsGravity:kCAGravityTopLeft];
71 ui::GpuSwitchingManager::GetInstance()->AddObserver(this);
62 } 72 }
63 73
64 IOSurfaceNSGLSurface::~IOSurfaceNSGLSurface() { 74 IOSurfaceNSGLSurface::~IOSurfaceNSGLSurface() {
75 ui::GpuSwitchingManager::GetInstance()->RemoveObserver(this);
65 DoPendingDrawIfNeeded(); 76 DoPendingDrawIfNeeded();
66 [ns_gl_context_ makeCurrentContext]; 77 [ns_gl_context_ makeCurrentContext];
67 iosurface_ = NULL; 78 iosurface_ = NULL;
68 [NSOpenGLContext clearCurrentContext]; 79 [NSOpenGLContext clearCurrentContext];
69 [ns_gl_context_ clearDrawable]; 80 [ns_gl_context_ clearDrawable];
70 81
71 ScopedCAActionDisabler disabler; 82 ScopedCAActionDisabler disabler;
72 [[view_ layer] setContents:nil]; 83 [[view_ layer] setContents:nil];
73 } 84 }
74 85
75 bool IOSurfaceNSGLSurface::GotFrame(IOSurfaceID io_surface_id, 86 bool IOSurfaceNSGLSurface::GotFrame(IOSurfaceID io_surface_id,
76 gfx::Size frame_pixel_size, 87 gfx::Size frame_pixel_size,
77 float frame_scale_factor, 88 float frame_scale_factor,
78 gfx::Rect pixel_damage_rect) { 89 gfx::Rect pixel_damage_rect) {
90 TRACE_EVENT0("ui", "IOSurfaceNSGLSurface::GotFrame");
79 pending_draw_exists_ = true; 91 pending_draw_exists_ = true;
80 pending_draw_damage_rect_.Union(pixel_damage_rect); 92 pending_draw_damage_rect_.Union(pixel_damage_rect);
81 93
82 // If the OpenGL framebuffer does not match the frame in scale factor or 94 // 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 95 // 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. 96 // bounds, which will not necessarily match the frame's pixel size.
85 if (!iosurface_->IsUpToDate(io_surface_id, frame_pixel_size) || 97 if (!iosurface_->IsUpToDate(io_surface_id, frame_pixel_size) ||
86 [ns_gl_context_ view] != view_ || 98 [ns_gl_context_ view] != view_ ||
87 frame_pixel_size != contents_pixel_size_ || 99 frame_pixel_size != contents_pixel_size_ ||
88 frame_scale_factor != contents_scale_factor_) { 100 frame_scale_factor != contents_scale_factor_) {
(...skipping 13 matching lines...) Expand all
102 glClear(GL_COLOR_BUFFER_BIT); 114 glClear(GL_COLOR_BUFFER_BIT);
103 115
104 // Retrieve the backbuffer's size from the GL viewport state. 116 // Retrieve the backbuffer's size from the GL viewport state.
105 GLint viewport[4]; 117 GLint viewport[4];
106 glGetIntegerv(GL_VIEWPORT, viewport); 118 glGetIntegerv(GL_VIEWPORT, viewport);
107 contents_pixel_size_ = gfx::Size(viewport[2], viewport[3]); 119 contents_pixel_size_ = gfx::Size(viewport[2], viewport[3]);
108 contents_scale_factor_ = frame_scale_factor; 120 contents_scale_factor_ = frame_scale_factor;
109 121
110 bool result = iosurface_->SetIOSurface(io_surface_id, frame_pixel_size); 122 bool result = iosurface_->SetIOSurface(io_surface_id, frame_pixel_size);
111 [NSOpenGLContext clearCurrentContext]; 123 [NSOpenGLContext clearCurrentContext];
112 if (!result) 124 if (!result) {
125 LOG(ERROR) << "Failed to set IOSurface, poisoning NSOpenGLContext.";
126 needs_to_be_recreated_ = true;
113 return false; 127 return false;
128 }
114 129
115 pending_draw_damage_rect_ = gfx::Rect(frame_pixel_size); 130 pending_draw_damage_rect_ = gfx::Rect(frame_pixel_size);
116 } 131 }
117 132
118 DoPendingDrawIfNeeded(); 133 DoPendingDrawIfNeeded();
119 return true; 134 return true;
120 } 135 }
121 136
122 void IOSurfaceNSGLSurface::DoPendingDrawIfNeeded() { 137 void IOSurfaceNSGLSurface::DoPendingDrawIfNeeded() {
123 if (!pending_draw_exists_) 138 if (!pending_draw_exists_)
124 return; 139 return;
125 140
126 { 141 {
127 TRACE_EVENT0("ui", "IOSurfaceNSGLSurface::Draw"); 142 TRACE_EVENT0("ui", "IOSurfaceNSGLSurface::Draw");
128 [ns_gl_context_ makeCurrentContext]; 143 [ns_gl_context_ makeCurrentContext];
129 ignore_result(iosurface_->DrawIOSurfaceWithDamageRect( 144 bool result = iosurface_->DrawIOSurfaceWithDamageRect(
130 pending_draw_damage_rect_)); 145 pending_draw_damage_rect_);
146 if (!result) {
147 LOG(ERROR) << "Failed to draw IOSurface, poisoning NSOpenGLContext.";
148 needs_to_be_recreated_ = true;
149 }
131 glFlush(); 150 glFlush();
132 [NSOpenGLContext clearCurrentContext]; 151 [NSOpenGLContext clearCurrentContext];
133 } 152 }
134 153
135 pending_draw_exists_ = false; 154 pending_draw_exists_ = false;
136 pending_draw_damage_rect_ = gfx::Rect(); 155 pending_draw_damage_rect_ = gfx::Rect();
137 156
138 client_->IOSurfaceNSGLSurfaceDidDrawFrame(); 157 client_->IOSurfaceNSGLSurfaceDidDrawFrame();
139 } 158 }
140 159
141 }; 160 int IOSurfaceNSGLSurface::GetRendererID() {
161 GLint current_renderer_id = -1;
162 CGLContextObj cgl_context = static_cast<CGLContextObj>(
163 [ns_gl_context_ CGLContextObj]);
164 if (CGLGetParameter(cgl_context,
165 kCGLCPCurrentRendererID,
166 &current_renderer_id) == kCGLNoError) {
167 return current_renderer_id & kCGLRendererIDMatchingMask;
168 }
169 return -1;
170 }
171
172 void IOSurfaceNSGLSurface::OnGpuSwitched() {
173 needs_to_be_recreated_ = true;
174 }
175
176 // static
177 bool IOSurfaceNSGLSurface::CanUseNSGLSurfaceForView(NSView* view) {
178 // This must be explicitly enabled at the command line.
179 static bool use_ns_gl_surfaces =
180 base::CommandLine::ForCurrentProcess()->HasSwitch(
181 switches::kEnableNSGLSurfaces);
182 if (!use_ns_gl_surfaces)
183 return false;
184
185 // Do not attempt this before 10.9. The power savings are not worth the
186 // stability risk and testing burden.
187 if (!base::mac::IsOSMavericksOrLater())
188 return false;
189
190 // If the NSView being attached to the NSOpenGLContext is not on the main
191 // monitor, then, due to an OS X bug, the IOSurface will be thrashed,
192 // resulting in hangs of 50 msec or more.
193 CGDirectDisplayID main_display = CGMainDisplayID();
194 NSScreen* screen = [[view window] screen];
195 NSDictionary* screen_description = [screen deviceDescription];
196 NSNumber* screen_number = [screen_description objectForKey:@"NSScreenNumber"];
197 CGDirectDisplayID display_id = [screen_number unsignedIntValue];
198 if (display_id != main_display)
199 return false;
200
201 return true;
202 }
203
204 } // namespace ui
OLDNEW
« no previous file with comments | « ui/accelerated_widget_mac/io_surface_ns_gl_surface.h ('k') | ui/accelerated_widget_mac/io_surface_texture.h » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698