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

Side by Side Diff: ui/gl/init/gl_initializer_win.cc

Issue 2094513002: Move static GL binding initialization to //ui/gl/init. (Closed) Base URL: https://chromium.googlesource.com/chromium/src.git@master
Patch Set: Working and cleaned up. Created 4 years, 5 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 2016 The Chromium Authors. All rights reserved. 1 // Copyright 2016 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/gl/init/gl_initializer.h" 5 #include "ui/gl/init/gl_initializer.h"
6 6
7 #include "base/at_exit.h"
8 #include "base/base_paths.h"
9 #include "base/bind.h"
10 #include "base/command_line.h"
11 #include "base/files/file_path.h"
12 #include "base/lazy_instance.h"
7 #include "base/logging.h" 13 #include "base/logging.h"
8 #include "ui/gl/gl_implementation.h" 14 #include "base/native_library.h"
15 #include "base/path_service.h"
16 #include "base/strings/stringprintf.h"
17 #include "base/threading/thread_restrictions.h"
18 #include "base/trace_event/trace_event.h"
19 #include "base/win/windows_version.h"
20 // TODO(jmadill): Apply to all platforms eventually
21 #include "ui/gl/angle_platform_impl.h"
22 #include "ui/gl/gl_bindings.h"
23 #include "ui/gl/gl_egl_api_implementation.h"
24 #include "ui/gl/gl_gl_api_implementation.h"
25 #include "ui/gl/gl_osmesa_api_implementation.h"
9 #include "ui/gl/gl_surface_egl.h" 26 #include "ui/gl/gl_surface_egl.h"
10 #include "ui/gl/gl_surface_wgl.h" 27 #include "ui/gl/gl_surface_wgl.h"
28 #include "ui/gl/gl_wgl_api_implementation.h"
11 #include "ui/gl/vsync_provider_win.h" 29 #include "ui/gl/vsync_provider_win.h"
12 30
31 #if defined(ENABLE_SWIFTSHADER)
32 #include "software_renderer.h"
33 #endif
34
13 namespace gl { 35 namespace gl {
14 namespace init { 36 namespace init {
15 37
38 namespace {
39
40 const wchar_t kD3DCompiler[] = L"D3DCompiler_47.dll";
41
42 // TODO(jmadill): Apply to all platforms eventually
43 base::LazyInstance<ANGLEPlatformImpl> g_angle_platform_impl =
44 LAZY_INSTANCE_INITIALIZER;
45
46 ANGLEPlatformShutdownFunc g_angle_platform_shutdown = nullptr;
47
48 void GL_BINDING_CALL MarshalClearDepthToClearDepthf(GLclampd depth) {
49 glClearDepthf(static_cast<GLclampf>(depth));
50 }
51
52 void GL_BINDING_CALL MarshalDepthRangeToDepthRangef(GLclampd z_near,
53 GLclampd z_far) {
54 glDepthRangef(static_cast<GLclampf>(z_near), static_cast<GLclampf>(z_far));
55 }
56
57 bool LoadD3DXLibrary(const base::FilePath& module_path,
58 const base::FilePath::StringType& name) {
59 base::NativeLibrary library =
60 base::LoadNativeLibrary(base::FilePath(name), nullptr);
61 if (!library) {
62 library = base::LoadNativeLibrary(module_path.Append(name), nullptr);
63 if (!library) {
64 DVLOG(1) << name << " not found.";
65 return false;
66 }
67 }
68 return true;
69 }
70
71 bool InitializeStaticOSMesaInternal() {
72 base::FilePath module_path;
73 PathService::Get(base::DIR_MODULE, &module_path);
74 base::NativeLibrary library =
75 base::LoadNativeLibrary(module_path.Append(L"osmesa.dll"), nullptr);
76 if (!library) {
77 PathService::Get(base::DIR_EXE, &module_path);
78 library =
79 base::LoadNativeLibrary(module_path.Append(L"osmesa.dll"), nullptr);
80 if (!library) {
81 DVLOG(1) << "osmesa.dll not found";
82 return false;
83 }
84 }
85
86 GLGetProcAddressProc get_proc_address =
87 reinterpret_cast<GLGetProcAddressProc>(
88 base::GetFunctionPointerFromNativeLibrary(library,
89 "OSMesaGetProcAddress"));
90 if (!get_proc_address) {
91 DLOG(ERROR) << "OSMesaGetProcAddress not found.";
92 base::UnloadNativeLibrary(library);
93 return false;
94 }
95
96 SetGLGetProcAddressProc(get_proc_address);
97 AddGLNativeLibrary(library);
98 SetGLImplementation(kGLImplementationOSMesaGL);
99
100 InitializeStaticGLBindingsGL();
101 InitializeStaticGLBindingsOSMESA();
102
103 return true;
104 }
105
106 bool InitializeStaticEGLInternal() {
107 base::FilePath module_path;
108 if (!PathService::Get(base::DIR_MODULE, &module_path))
109 return false;
110
111 // Attempt to load the D3DX shader compiler using the default search path
112 // and if that fails, using an absolute path. This is to ensure these DLLs
113 // are loaded before ANGLE is loaded in case they are not in the default
114 // search path.
115 LoadD3DXLibrary(module_path, kD3DCompiler);
116
117 base::FilePath gles_path;
118 const base::CommandLine* command_line =
119 base::CommandLine::ForCurrentProcess();
120 bool using_swift_shader =
121 command_line->GetSwitchValueASCII(switches::kUseGL) ==
122 kGLImplementationSwiftShaderName;
123 if (using_swift_shader) {
124 if (!command_line->HasSwitch(switches::kSwiftShaderPath))
125 return false;
126 gles_path = command_line->GetSwitchValuePath(switches::kSwiftShaderPath);
127 // Preload library
128 LoadLibrary(L"ddraw.dll");
129 } else {
130 gles_path = module_path;
131 }
132
133 // Load libglesv2.dll before libegl.dll because the latter is dependent on
134 // the former and if there is another version of libglesv2.dll in the dll
135 // search path, it will get loaded instead.
136 base::NativeLibrary gles_library =
137 base::LoadNativeLibrary(gles_path.Append(L"libglesv2.dll"), nullptr);
138 if (!gles_library) {
139 DVLOG(1) << "libglesv2.dll not found";
140 return false;
141 }
142
143 // When using EGL, first try eglGetProcAddress and then Windows
144 // GetProcAddress on both the EGL and GLES2 DLLs.
145 base::NativeLibrary egl_library =
146 base::LoadNativeLibrary(gles_path.Append(L"libegl.dll"), nullptr);
147 if (!egl_library) {
148 DVLOG(1) << "libegl.dll not found.";
149 base::UnloadNativeLibrary(gles_library);
150 return false;
151 }
152
153 #if defined(ENABLE_SWIFTSHADER)
154 if (using_swift_shader) {
155 SetupSoftwareRenderer(gles_library);
156 }
157 #endif
158
159 if (!using_swift_shader) {
160 // Init ANGLE platform here, before we call GetPlatformDisplay().
161 // TODO(jmadill): Apply to all platforms eventually
162 ANGLEPlatformInitializeFunc angle_platform_init =
163 reinterpret_cast<ANGLEPlatformInitializeFunc>(
164 base::GetFunctionPointerFromNativeLibrary(
165 gles_library, "ANGLEPlatformInitialize"));
166 if (angle_platform_init) {
167 angle_platform_init(&g_angle_platform_impl.Get());
168
169 g_angle_platform_shutdown = reinterpret_cast<ANGLEPlatformShutdownFunc>(
170 base::GetFunctionPointerFromNativeLibrary(gles_library,
171 "ANGLEPlatformShutdown"));
172 }
173 }
174
175 GLGetProcAddressProc get_proc_address =
176 reinterpret_cast<GLGetProcAddressProc>(
177 base::GetFunctionPointerFromNativeLibrary(egl_library,
178 "eglGetProcAddress"));
179 if (!get_proc_address) {
180 LOG(ERROR) << "eglGetProcAddress not found.";
181 base::UnloadNativeLibrary(egl_library);
182 base::UnloadNativeLibrary(gles_library);
183 return false;
184 }
185
186 SetGLGetProcAddressProc(get_proc_address);
187 AddGLNativeLibrary(egl_library);
188 AddGLNativeLibrary(gles_library);
189 SetGLImplementation(kGLImplementationEGLGLES2);
190
191 InitializeStaticGLBindingsGL();
192 InitializeStaticGLBindingsEGL();
193
194 // These two functions take single precision float rather than double
195 // precision float parameters in GLES.
196 ::gl::g_driver_gl.fn.glClearDepthFn = MarshalClearDepthToClearDepthf;
197 ::gl::g_driver_gl.fn.glDepthRangeFn = MarshalDepthRangeToDepthRangef;
198 return true;
199 }
200
201 bool InitializeStaticWGLInternal() {
202 base::NativeLibrary library =
203 base::LoadNativeLibrary(base::FilePath(L"opengl32.dll"), nullptr);
204 if (!library) {
205 DVLOG(1) << "opengl32.dll not found";
206 return false;
207 }
208
209 GLGetProcAddressProc get_proc_address =
210 reinterpret_cast<GLGetProcAddressProc>(
211 base::GetFunctionPointerFromNativeLibrary(library,
212 "wglGetProcAddress"));
213 if (!get_proc_address) {
214 LOG(ERROR) << "wglGetProcAddress not found.";
215 base::UnloadNativeLibrary(library);
216 return false;
217 }
218
219 SetGLGetProcAddressProc(get_proc_address);
220 AddGLNativeLibrary(library);
221 SetGLImplementation(kGLImplementationDesktopGL);
222
223 // Initialize GL surface and get some functions needed for the context
224 // creation below.
225 if (!GLSurfaceWGL::InitializeOneOff()) {
226 LOG(ERROR) << "GLSurfaceWGL::InitializeOneOff failed.";
227 return false;
228 }
229 wglCreateContextProc wglCreateContextFn =
230 reinterpret_cast<wglCreateContextProc>(
231 GetGLProcAddress("wglCreateContext"));
232 wglDeleteContextProc wglDeleteContextFn =
233 reinterpret_cast<wglDeleteContextProc>(
234 GetGLProcAddress("wglDeleteContext"));
235 wglMakeCurrentProc wglMakeCurrentFn =
236 reinterpret_cast<wglMakeCurrentProc>(GetGLProcAddress("wglMakeCurrent"));
237
238 // Create a temporary GL context to bind to entry points. This is needed
239 // because wglGetProcAddress is specified to return nullptr for all queries
240 // if a context is not current in MSDN documentation, and the static
241 // bindings may contain functions that need to be queried with
242 // wglGetProcAddress. OpenGL wiki further warns that other error values
243 // than nullptr could also be returned from wglGetProcAddress on some
244 // implementations, so we need to clear the WGL bindings and reinitialize
245 // them after the context creation.
246 HGLRC gl_context = wglCreateContextFn(GLSurfaceWGL::GetDisplayDC());
247 if (!gl_context) {
248 LOG(ERROR) << "Failed to create temporary context.";
249 return false;
250 }
251 if (!wglMakeCurrentFn(GLSurfaceWGL::GetDisplayDC(), gl_context)) {
252 LOG(ERROR) << "Failed to make temporary GL context current.";
253 wglDeleteContextFn(gl_context);
254 return false;
255 }
256
257 InitializeStaticGLBindingsGL();
258 InitializeStaticGLBindingsWGL();
259
260 wglMakeCurrent(nullptr, nullptr);
261 wglDeleteContext(gl_context);
262
263 return true;
264 }
265
266 } // namespace
267
16 bool InitializeGLOneOffPlatform() { 268 bool InitializeGLOneOffPlatform() {
17 VSyncProviderWin::InitializeOneOff(); 269 VSyncProviderWin::InitializeOneOff();
18 270
19 switch (GetGLImplementation()) { 271 switch (GetGLImplementation()) {
20 case kGLImplementationDesktopGL: 272 case kGLImplementationDesktopGL:
21 if (!GLSurfaceWGL::InitializeOneOff()) { 273 if (!GLSurfaceWGL::InitializeOneOff()) {
22 LOG(ERROR) << "GLSurfaceWGL::InitializeOneOff failed."; 274 LOG(ERROR) << "GLSurfaceWGL::InitializeOneOff failed.";
23 return false; 275 return false;
24 } 276 }
25 break; 277 break;
26 case kGLImplementationEGLGLES2: 278 case kGLImplementationEGLGLES2:
27 if (!GLSurfaceEGL::InitializeOneOff()) { 279 if (!GLSurfaceEGL::InitializeOneOff()) {
28 LOG(ERROR) << "GLSurfaceEGL::InitializeOneOff failed."; 280 LOG(ERROR) << "GLSurfaceEGL::InitializeOneOff failed.";
29 return false; 281 return false;
30 } 282 }
31 break; 283 break;
32 case kGLImplementationOSMesaGL: 284 case kGLImplementationOSMesaGL:
33 case kGLImplementationMockGL: 285 case kGLImplementationMockGL:
34 break; 286 break;
35 default: 287 default:
36 NOTREACHED(); 288 NOTREACHED();
37 } 289 }
38 return true; 290 return true;
39 } 291 }
40 292
293 bool InitializeStaticGLBindings(GLImplementation implementation) {
294 // Prevent reinitialization with a different implementation. Once the gpu
295 // unit tests have initialized with kGLImplementationMock, we don't want to
296 // later switch to another GL implementation.
297 DCHECK_EQ(kGLImplementationNone, GetGLImplementation());
298
299 // Allow the main thread or another to initialize these bindings
300 // after instituting restrictions on I/O. Going forward they will
301 // likely be used in the browser process on most platforms. The
302 // one-time initialization cost is small, between 2 and 5 ms.
303 base::ThreadRestrictions::ScopedAllowIO allow_io;
304
305 switch (implementation) {
306 case kGLImplementationOSMesaGL:
307 return InitializeStaticOSMesaInternal();
308 case kGLImplementationEGLGLES2:
309 return InitializeStaticEGLInternal();
310 case kGLImplementationDesktopGL:
311 return InitializeStaticWGLInternal();
312 case kGLImplementationMockGL:
313 SetGLImplementation(kGLImplementationMockGL);
314 InitializeStaticGLBindingsGL();
315 return true;
316 default:
317 NOTREACHED();
318 }
319
320 return false;
321 }
322
323 void InitializeDebugGLBindings() {
324 InitializeDebugGLBindingsEGL();
325 InitializeDebugGLBindingsGL();
326 InitializeDebugGLBindingsOSMESA();
327 InitializeDebugGLBindingsWGL();
328 }
329
330 void ClearGLBindingsPlatform() {
331 // TODO(jmadill): Apply to all platforms eventually
332 if (g_angle_platform_shutdown) {
333 g_angle_platform_shutdown();
334 }
335
336 ClearGLBindingsEGL();
337 ClearGLBindingsGL();
338 ClearGLBindingsOSMESA();
339 ClearGLBindingsWGL();
340 }
341
41 } // namespace init 342 } // namespace init
42 } // namespace gl 343 } // namespace gl
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698