OLD | NEW |
1 // Copyright (c) 2013 The Chromium Authors. All rights reserved. | 1 // Copyright (c) 2013 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_context_mac.h" | 5 #include "content/browser/renderer_host/compositing_iosurface_context_mac.h" |
6 | 6 |
7 #include <OpenGL/gl.h> | 7 #include <OpenGL/gl.h> |
8 #include <OpenGL/OpenGL.h> | 8 #include <OpenGL/OpenGL.h> |
9 #include <vector> | 9 #include <vector> |
10 | 10 |
11 #include "base/command_line.h" | 11 #include "base/command_line.h" |
12 #include "base/debug/trace_event.h" | 12 #include "base/debug/trace_event.h" |
13 #include "base/logging.h" | 13 #include "base/logging.h" |
14 #include "content/browser/renderer_host/compositing_iosurface_shader_programs_ma
c.h" | 14 #include "content/browser/renderer_host/compositing_iosurface_shader_programs_ma
c.h" |
15 #include "content/public/common/content_switches.h" | 15 #include "content/public/common/content_switches.h" |
16 #include "ui/gl/gl_switches.h" | 16 #include "ui/gl/gl_switches.h" |
17 #include "ui/gl/gpu_switching_manager.h" | 17 #include "ui/gl/gpu_switching_manager.h" |
18 | 18 |
19 namespace { | |
20 | |
21 template<typename T, void Release(T)> | |
22 class ScopedCGLTypeRef { | |
23 public: | |
24 ScopedCGLTypeRef() : object_(NULL) {} | |
25 | |
26 ~ScopedCGLTypeRef() { | |
27 if (object_) | |
28 Release(object_); | |
29 object_ = NULL; | |
30 } | |
31 | |
32 // Only to be used for pass-by-pointer initialization. The object must have | |
33 // been reset to NULL prior to calling. | |
34 T* operator&() { | |
35 DCHECK(object_ == NULL); | |
36 return &object_; | |
37 } | |
38 | |
39 operator T() const { | |
40 return object_; | |
41 } | |
42 | |
43 T release() WARN_UNUSED_RESULT { | |
44 T object = object_; | |
45 object_ = NULL; | |
46 return object; | |
47 } | |
48 | |
49 private: | |
50 T object_; | |
51 DISALLOW_COPY_AND_ASSIGN(ScopedCGLTypeRef); | |
52 }; | |
53 | |
54 } | |
55 | |
56 namespace content { | 19 namespace content { |
57 | 20 |
58 CoreAnimationStatus GetCoreAnimationStatus() { | 21 CoreAnimationStatus GetCoreAnimationStatus() { |
59 static CoreAnimationStatus status = | 22 static CoreAnimationStatus status = |
60 CommandLine::ForCurrentProcess()->HasSwitch(switches::kUseCoreAnimation) ? | 23 CommandLine::ForCurrentProcess()->HasSwitch(switches::kUseCoreAnimation) ? |
61 CORE_ANIMATION_ENABLED : CORE_ANIMATION_DISABLED; | 24 CORE_ANIMATION_ENABLED : CORE_ANIMATION_DISABLED; |
62 return status; | 25 return status; |
63 } | 26 } |
64 | 27 |
65 // static | 28 // static |
66 scoped_refptr<CompositingIOSurfaceContext> | 29 scoped_refptr<CompositingIOSurfaceContext> |
67 CompositingIOSurfaceContext::Get(int window_number) { | 30 CompositingIOSurfaceContext::Get(int window_number) { |
68 TRACE_EVENT0("browser", "CompositingIOSurfaceContext::Get"); | 31 TRACE_EVENT0("browser", "CompositingIOSurfaceContext::Get"); |
69 | 32 |
70 // Return the context for this window_number, if it exists. | 33 // Return the context for this window_number, if it exists. |
71 WindowMap::iterator found = window_map()->find(window_number); | 34 WindowMap::iterator found = window_map()->find(window_number); |
72 if (found != window_map()->end()) { | 35 if (found != window_map()->end()) { |
73 DCHECK(found->second->can_be_shared_); | 36 DCHECK(found->second->can_be_shared_); |
74 return found->second; | 37 return found->second; |
75 } | 38 } |
76 | 39 |
77 bool is_vsync_disabled = | 40 bool is_vsync_disabled = |
78 CommandLine::ForCurrentProcess()->HasSwitch(switches::kDisableGpuVsync); | 41 CommandLine::ForCurrentProcess()->HasSwitch(switches::kDisableGpuVsync); |
79 | 42 |
80 base::scoped_nsobject<NSOpenGLContext> nsgl_context; | 43 base::scoped_nsobject<NSOpenGLContext> nsgl_context; |
81 ScopedCGLTypeRef<CGLContextObj, CGLReleaseContext> cgl_context_strong; | 44 base::ScopedTypeRef<CGLContextObj> cgl_context_strong; |
82 CGLContextObj cgl_context = NULL; | 45 CGLContextObj cgl_context = NULL; |
83 if (GetCoreAnimationStatus() == CORE_ANIMATION_DISABLED) { | 46 if (GetCoreAnimationStatus() == CORE_ANIMATION_DISABLED) { |
84 std::vector<NSOpenGLPixelFormatAttribute> attributes; | 47 std::vector<NSOpenGLPixelFormatAttribute> attributes; |
85 attributes.push_back(NSOpenGLPFADoubleBuffer); | 48 attributes.push_back(NSOpenGLPFADoubleBuffer); |
86 // We don't need a depth buffer - try setting its size to 0... | 49 // We don't need a depth buffer - try setting its size to 0... |
87 attributes.push_back(NSOpenGLPFADepthSize); attributes.push_back(0); | 50 attributes.push_back(NSOpenGLPFADepthSize); attributes.push_back(0); |
88 if (ui::GpuSwitchingManager::GetInstance()->SupportsDualGpus()) | 51 if (ui::GpuSwitchingManager::GetInstance()->SupportsDualGpus()) |
89 attributes.push_back(NSOpenGLPFAAllowOfflineRenderers); | 52 attributes.push_back(NSOpenGLPFAAllowOfflineRenderers); |
90 attributes.push_back(0); | 53 attributes.push_back(0); |
91 | 54 |
(...skipping 35 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
127 // Create the pixel format object for the context. | 90 // Create the pixel format object for the context. |
128 std::vector<CGLPixelFormatAttribute> attribs; | 91 std::vector<CGLPixelFormatAttribute> attribs; |
129 attribs.push_back(kCGLPFADepthSize); | 92 attribs.push_back(kCGLPFADepthSize); |
130 attribs.push_back(static_cast<CGLPixelFormatAttribute>(0)); | 93 attribs.push_back(static_cast<CGLPixelFormatAttribute>(0)); |
131 if (ui::GpuSwitchingManager::GetInstance()->SupportsDualGpus()) { | 94 if (ui::GpuSwitchingManager::GetInstance()->SupportsDualGpus()) { |
132 attribs.push_back(kCGLPFAAllowOfflineRenderers); | 95 attribs.push_back(kCGLPFAAllowOfflineRenderers); |
133 attribs.push_back(static_cast<CGLPixelFormatAttribute>(1)); | 96 attribs.push_back(static_cast<CGLPixelFormatAttribute>(1)); |
134 } | 97 } |
135 attribs.push_back(static_cast<CGLPixelFormatAttribute>(0)); | 98 attribs.push_back(static_cast<CGLPixelFormatAttribute>(0)); |
136 GLint number_virtual_screens = 0; | 99 GLint number_virtual_screens = 0; |
137 ScopedCGLTypeRef<CGLPixelFormatObj, CGLReleasePixelFormat> pixel_format; | 100 base::ScopedTypeRef<CGLPixelFormatObj> pixel_format; |
138 error = CGLChoosePixelFormat( | 101 error = CGLChoosePixelFormat(&attribs.front(), |
139 &attribs.front(), &pixel_format, &number_virtual_screens); | 102 pixel_format.InitializeInto(), |
| 103 &number_virtual_screens); |
140 if (error != kCGLNoError) { | 104 if (error != kCGLNoError) { |
141 LOG(ERROR) << "Failed to create pixel format object."; | 105 LOG(ERROR) << "Failed to create pixel format object."; |
142 return NULL; | 106 return NULL; |
143 } | 107 } |
144 | 108 |
145 // Create all contexts in the same share group so that the textures don't | 109 // Create all contexts in the same share group so that the textures don't |
146 // need to be recreated when transitioning contexts. | 110 // need to be recreated when transitioning contexts. |
147 CGLContextObj share_context = NULL; | 111 CGLContextObj share_context = NULL; |
148 if (!window_map()->empty()) | 112 if (!window_map()->empty()) |
149 share_context = window_map()->begin()->second->cgl_context(); | 113 share_context = window_map()->begin()->second->cgl_context(); |
150 error = CGLCreateContext( | 114 error = CGLCreateContext( |
151 pixel_format, share_context, &cgl_context_strong); | 115 pixel_format, share_context, cgl_context_strong.InitializeInto()); |
152 if (error != kCGLNoError) { | 116 if (error != kCGLNoError) { |
153 LOG(ERROR) << "Failed to create context object."; | 117 LOG(ERROR) << "Failed to create context object."; |
154 return NULL; | 118 return NULL; |
155 } | 119 } |
156 cgl_context = cgl_context_strong; | 120 cgl_context = cgl_context_strong; |
157 | 121 |
158 // Note that VSync is ignored because CoreAnimation will automatically | 122 // Note that VSync is ignored because CoreAnimation will automatically |
159 // rate limit draws. | 123 // rate limit draws. |
160 } | 124 } |
161 | 125 |
162 // Prepare the shader program cache. Precompile the shader programs | 126 // Prepare the shader program cache. Precompile the shader programs |
163 // needed to draw the IO Surface for non-offscreen contexts. | 127 // needed to draw the IO Surface for non-offscreen contexts. |
164 CGLSetCurrentContext(cgl_context); | |
165 scoped_ptr<CompositingIOSurfaceShaderPrograms> shader_program_cache( | |
166 new CompositingIOSurfaceShaderPrograms()); | |
167 bool prepared = false; | 128 bool prepared = false; |
168 if (window_number == kOffscreenContextWindowNumber) { | 129 scoped_ptr<CompositingIOSurfaceShaderPrograms> shader_program_cache; |
169 prepared = true; | 130 { |
170 } else { | 131 gfx::ScopedCGLSetCurrentContext scoped_set_current_context(cgl_context); |
171 prepared = ( | 132 shader_program_cache.reset(new CompositingIOSurfaceShaderPrograms()); |
172 shader_program_cache->UseBlitProgram() && | 133 if (window_number == kOffscreenContextWindowNumber) { |
173 shader_program_cache->UseSolidWhiteProgram()); | 134 prepared = true; |
| 135 } else { |
| 136 prepared = ( |
| 137 shader_program_cache->UseBlitProgram() && |
| 138 shader_program_cache->UseSolidWhiteProgram()); |
| 139 } |
| 140 glUseProgram(0u); |
174 } | 141 } |
175 glUseProgram(0u); | |
176 CGLSetCurrentContext(0); | |
177 if (!prepared) { | 142 if (!prepared) { |
178 LOG(ERROR) << "IOSurface failed to compile/link required shader programs."; | 143 LOG(ERROR) << "IOSurface failed to compile/link required shader programs."; |
179 return NULL; | 144 return NULL; |
180 } | 145 } |
181 | 146 |
182 scoped_refptr<DisplayLinkMac> display_link = DisplayLinkMac::Create(); | 147 scoped_refptr<DisplayLinkMac> display_link = DisplayLinkMac::Create(); |
183 if (!display_link) { | 148 if (!display_link) { |
184 LOG(ERROR) << "Failed to create display link for GL context."; | 149 LOG(ERROR) << "Failed to create display link for GL context."; |
185 return NULL; | 150 return NULL; |
186 } | 151 } |
187 | 152 |
188 return new CompositingIOSurfaceContext( | 153 return new CompositingIOSurfaceContext( |
189 window_number, | 154 window_number, |
190 nsgl_context.release(), | 155 nsgl_context.release(), |
191 cgl_context_strong.release(), | 156 cgl_context_strong, |
192 cgl_context, | 157 cgl_context, |
193 is_vsync_disabled, | 158 is_vsync_disabled, |
194 display_link, | 159 display_link, |
195 shader_program_cache.Pass()); | 160 shader_program_cache.Pass()); |
196 } | 161 } |
197 | 162 |
198 // static | 163 // static |
199 void CompositingIOSurfaceContext::MarkExistingContextsAsNotShareable() { | 164 void CompositingIOSurfaceContext::MarkExistingContextsAsNotShareable() { |
200 for (WindowMap::iterator it = window_map()->begin(); | 165 for (WindowMap::iterator it = window_map()->begin(); |
201 it != window_map()->end(); | 166 it != window_map()->end(); |
202 ++it) { | 167 ++it) { |
203 it->second->can_be_shared_ = false; | 168 it->second->can_be_shared_ = false; |
204 } | 169 } |
205 window_map()->clear(); | 170 window_map()->clear(); |
206 } | 171 } |
207 | 172 |
208 CompositingIOSurfaceContext::CompositingIOSurfaceContext( | 173 CompositingIOSurfaceContext::CompositingIOSurfaceContext( |
209 int window_number, | 174 int window_number, |
210 NSOpenGLContext* nsgl_context, | 175 NSOpenGLContext* nsgl_context, |
211 CGLContextObj cgl_context_strong, | 176 base::ScopedTypeRef<CGLContextObj> cgl_context_strong, |
212 CGLContextObj cgl_context, | 177 CGLContextObj cgl_context, |
213 bool is_vsync_disabled, | 178 bool is_vsync_disabled, |
214 scoped_refptr<DisplayLinkMac> display_link, | 179 scoped_refptr<DisplayLinkMac> display_link, |
215 scoped_ptr<CompositingIOSurfaceShaderPrograms> shader_program_cache) | 180 scoped_ptr<CompositingIOSurfaceShaderPrograms> shader_program_cache) |
216 : window_number_(window_number), | 181 : window_number_(window_number), |
217 nsgl_context_(nsgl_context), | 182 nsgl_context_(nsgl_context), |
218 cgl_context_strong_(cgl_context_strong), | 183 cgl_context_strong_(cgl_context_strong), |
219 cgl_context_(cgl_context), | 184 cgl_context_(cgl_context), |
220 is_vsync_disabled_(is_vsync_disabled), | 185 is_vsync_disabled_(is_vsync_disabled), |
221 shader_program_cache_(shader_program_cache.Pass()), | 186 shader_program_cache_(shader_program_cache.Pass()), |
222 can_be_shared_(true), | 187 can_be_shared_(true), |
223 initialized_is_intel_(false), | 188 initialized_is_intel_(false), |
224 is_intel_(false), | 189 is_intel_(false), |
225 screen_(0), | 190 screen_(0), |
226 display_link_(display_link) { | 191 display_link_(display_link) { |
227 DCHECK(window_map()->find(window_number_) == window_map()->end()); | 192 DCHECK(window_map()->find(window_number_) == window_map()->end()); |
228 window_map()->insert(std::make_pair(window_number_, this)); | 193 window_map()->insert(std::make_pair(window_number_, this)); |
229 } | 194 } |
230 | 195 |
231 CompositingIOSurfaceContext::~CompositingIOSurfaceContext() { | 196 CompositingIOSurfaceContext::~CompositingIOSurfaceContext() { |
232 CGLSetCurrentContext(cgl_context_); | 197 { |
233 shader_program_cache_->Reset(); | 198 gfx::ScopedCGLSetCurrentContext scoped_set_current_context(cgl_context_); |
234 CGLSetCurrentContext(0); | 199 shader_program_cache_->Reset(); |
| 200 } |
235 if (can_be_shared_) { | 201 if (can_be_shared_) { |
236 DCHECK(window_map()->find(window_number_) != window_map()->end()); | 202 DCHECK(window_map()->find(window_number_) != window_map()->end()); |
237 DCHECK(window_map()->find(window_number_)->second == this); | 203 DCHECK(window_map()->find(window_number_)->second == this); |
238 window_map()->erase(window_number_); | 204 window_map()->erase(window_number_); |
239 } else { | 205 } else { |
240 WindowMap::const_iterator found = window_map()->find(window_number_); | 206 WindowMap::const_iterator found = window_map()->find(window_number_); |
241 if (found != window_map()->end()) | 207 if (found != window_map()->end()) |
242 DCHECK(found->second != this); | 208 DCHECK(found->second != this); |
243 } | 209 } |
244 if (cgl_context_strong_) | |
245 CGLReleaseContext(cgl_context_strong_); | |
246 } | 210 } |
247 | 211 |
248 NSOpenGLContext* CompositingIOSurfaceContext::nsgl_context() const { | 212 NSOpenGLContext* CompositingIOSurfaceContext::nsgl_context() const { |
249 // This should not be called from any CoreAnimation paths. | 213 // This should not be called from any CoreAnimation paths. |
250 CHECK(GetCoreAnimationStatus() == CORE_ANIMATION_DISABLED); | 214 CHECK(GetCoreAnimationStatus() == CORE_ANIMATION_DISABLED); |
251 return nsgl_context_; | 215 return nsgl_context_; |
252 } | 216 } |
253 | 217 |
254 bool CompositingIOSurfaceContext::IsVendorIntel() { | 218 bool CompositingIOSurfaceContext::IsVendorIntel() { |
255 GLint screen; | 219 GLint screen; |
(...skipping 13 matching lines...) Expand all Loading... |
269 CompositingIOSurfaceContext::WindowMap* | 233 CompositingIOSurfaceContext::WindowMap* |
270 CompositingIOSurfaceContext::window_map() { | 234 CompositingIOSurfaceContext::window_map() { |
271 return window_map_.Pointer(); | 235 return window_map_.Pointer(); |
272 } | 236 } |
273 | 237 |
274 // static | 238 // static |
275 base::LazyInstance<CompositingIOSurfaceContext::WindowMap> | 239 base::LazyInstance<CompositingIOSurfaceContext::WindowMap> |
276 CompositingIOSurfaceContext::window_map_; | 240 CompositingIOSurfaceContext::window_map_; |
277 | 241 |
278 } // namespace content | 242 } // namespace content |
OLD | NEW |