1 // Copyright (c) 2012 The Chromium Authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file.
7 #include "base/at_exit.h"
8 #include "base/base_paths.h"
10 #include "base/command_line.h"
11 #include "base/files/file_path.h"
12 #include "base/logging.h"
13 #include "base/native_library.h"
14 #include "base/path_service.h"
15 #include "base/stringprintf.h"
16 #include "base/threading/thread_restrictions.h"
17 #include "base/win/windows_version.h"
18 #include "ui/gl/gl_bindings.h"
19 #include "ui/gl/gl_egl_api_implementation.h"
20 #include "ui/gl/gl_gl_api_implementation.h"
21 #include "ui/gl/gl_implementation.h"
22 #include "ui/gl/gl_osmesa_api_implementation.h"
23 #include "ui/gl/gl_wgl_api_implementation.h"
25 #if defined(ENABLE_SWIFTSHADER)
26 #include "software_renderer.h"
33 // Version 43 is the latest version of D3DCompiler_nn.dll that works prior to
35 const wchar_t kPreVistaD3DCompiler
[] = L
"D3DCompiler_43.dll";
36 const wchar_t kPostVistaD3DCompiler
[] = L
"D3DCompiler_46.dll";
38 void GL_BINDING_CALL
MarshalClearDepthToClearDepthf(GLclampd depth
) {
39 glClearDepthf(static_cast<GLclampf
>(depth
));
42 void GL_BINDING_CALL
MarshalDepthRangeToDepthRangef(GLclampd z_near
,
44 glDepthRangef(static_cast<GLclampf
>(z_near
), static_cast<GLclampf
>(z_far
));
47 bool LoadD3DXLibrary(const base::FilePath
& module_path
,
48 const base::FilePath::StringType
& name
) {
49 base::NativeLibrary library
=
50 base::LoadNativeLibrary(base::FilePath(name
), NULL
);
52 library
= base::LoadNativeLibrary(module_path
.Append(name
), NULL
);
54 DVLOG(1) << name
<< " not found.";
63 void GetAllowedGLImplementations(std::vector
<GLImplementation
>* impls
) {
64 impls
->push_back(kGLImplementationEGLGLES2
);
65 impls
->push_back(kGLImplementationDesktopGL
);
66 impls
->push_back(kGLImplementationOSMesaGL
);
69 bool InitializeGLBindings(GLImplementation implementation
) {
70 // Prevent reinitialization with a different implementation. Once the gpu
71 // unit tests have initialized with kGLImplementationMock, we don't want to
72 // later switch to another GL implementation.
73 if (GetGLImplementation() != kGLImplementationNone
)
76 // Allow the main thread or another to initialize these bindings
77 // after instituting restrictions on I/O. Going forward they will
78 // likely be used in the browser process on most platforms. The
79 // one-time initialization cost is small, between 2 and 5 ms.
80 base::ThreadRestrictions::ScopedAllowIO allow_io
;
82 switch (implementation
) {
83 case kGLImplementationOSMesaGL
: {
84 base::FilePath module_path
;
85 if (!PathService::Get(base::DIR_MODULE
, &module_path
)) {
86 LOG(ERROR
) << "PathService::Get failed.";
90 base::NativeLibrary library
= base::LoadNativeLibrary(
91 module_path
.Append(L
"osmesa.dll"), NULL
);
93 DVLOG(1) << "osmesa.dll not found";
97 GLGetProcAddressProc get_proc_address
=
98 reinterpret_cast<GLGetProcAddressProc
>(
99 base::GetFunctionPointerFromNativeLibrary(
100 library
, "OSMesaGetProcAddress"));
101 if (!get_proc_address
) {
102 DLOG(ERROR
) << "OSMesaGetProcAddress not found.";
103 base::UnloadNativeLibrary(library
);
107 SetGLGetProcAddressProc(get_proc_address
);
108 AddGLNativeLibrary(library
);
109 SetGLImplementation(kGLImplementationOSMesaGL
);
111 InitializeGLBindingsGL();
112 InitializeGLBindingsOSMESA();
115 case kGLImplementationEGLGLES2
: {
116 base::FilePath module_path
;
117 if (!PathService::Get(base::DIR_MODULE
, &module_path
))
120 // Attempt to load the D3DX shader compiler using the default search path
121 // and if that fails, using an absolute path. This is to ensure these DLLs
122 // are loaded before ANGLE is loaded in case they are not in the default
123 // search path. Prefer the post vista version.
124 if (base::win::GetVersion() < base::win::VERSION_VISTA
||
125 !LoadD3DXLibrary(module_path
, kPostVistaD3DCompiler
)) {
126 LoadD3DXLibrary(module_path
, kPreVistaD3DCompiler
);
129 base::FilePath gles_path
;
130 const CommandLine
* command_line
= CommandLine::ForCurrentProcess();
131 bool using_swift_shader
=
132 command_line
->GetSwitchValueASCII(switches::kUseGL
) == "swiftshader";
133 if (using_swift_shader
) {
134 if (!command_line
->HasSwitch(switches::kSwiftShaderPath
))
137 command_line
->GetSwitchValuePath(switches::kSwiftShaderPath
);
139 LoadLibrary(L
"ddraw.dll");
141 gles_path
= module_path
;
144 // Load libglesv2.dll before libegl.dll because the latter is dependent on
145 // the former and if there is another version of libglesv2.dll in the dll
146 // search path, it will get loaded instead.
147 base::NativeLibrary gles_library
= base::LoadNativeLibrary(
148 gles_path
.Append(L
"libglesv2.dll"), NULL
);
150 DVLOG(1) << "libglesv2.dll not found";
154 // When using EGL, first try eglGetProcAddress and then Windows
155 // GetProcAddress on both the EGL and GLES2 DLLs.
156 base::NativeLibrary egl_library
= base::LoadNativeLibrary(
157 gles_path
.Append(L
"libegl.dll"), NULL
);
159 DVLOG(1) << "libegl.dll not found.";
160 base::UnloadNativeLibrary(gles_library
);
164 #if defined(ENABLE_SWIFTSHADER)
165 if (using_swift_shader
) {
166 SetupSoftwareRenderer(gles_library
);
170 GLGetProcAddressProc get_proc_address
=
171 reinterpret_cast<GLGetProcAddressProc
>(
172 base::GetFunctionPointerFromNativeLibrary(
173 egl_library
, "eglGetProcAddress"));
174 if (!get_proc_address
) {
175 LOG(ERROR
) << "eglGetProcAddress not found.";
176 base::UnloadNativeLibrary(egl_library
);
177 base::UnloadNativeLibrary(gles_library
);
181 SetGLGetProcAddressProc(get_proc_address
);
182 AddGLNativeLibrary(egl_library
);
183 AddGLNativeLibrary(gles_library
);
184 SetGLImplementation(kGLImplementationEGLGLES2
);
186 InitializeGLBindingsGL();
187 InitializeGLBindingsEGL();
189 // These two functions take single precision float rather than double
190 // precision float parameters in GLES.
191 ::gfx::g_driver_gl
.fn
.glClearDepthFn
= MarshalClearDepthToClearDepthf
;
192 ::gfx::g_driver_gl
.fn
.glDepthRangeFn
= MarshalDepthRangeToDepthRangef
;
195 case kGLImplementationDesktopGL
: {
196 // When using Windows OpenGL, first try wglGetProcAddress and then
197 // Windows GetProcAddress.
198 base::NativeLibrary library
= base::LoadNativeLibrary(
199 base::FilePath(L
"opengl32.dll"), NULL
);
201 DVLOG(1) << "opengl32.dll not found";
205 GLGetProcAddressProc get_proc_address
=
206 reinterpret_cast<GLGetProcAddressProc
>(
207 base::GetFunctionPointerFromNativeLibrary(
208 library
, "wglGetProcAddress"));
209 if (!get_proc_address
) {
210 LOG(ERROR
) << "wglGetProcAddress not found.";
211 base::UnloadNativeLibrary(library
);
215 SetGLGetProcAddressProc(get_proc_address
);
216 AddGLNativeLibrary(library
);
217 SetGLImplementation(kGLImplementationDesktopGL
);
219 InitializeGLBindingsGL();
220 InitializeGLBindingsWGL();
223 case kGLImplementationMockGL
: {
224 SetGLGetProcAddressProc(GetMockGLProcAddress
);
225 SetGLImplementation(kGLImplementationMockGL
);
226 InitializeGLBindingsGL();
236 bool InitializeGLExtensionBindings(GLImplementation implementation
,
237 GLContext
* context
) {
238 switch (implementation
) {
239 case kGLImplementationOSMesaGL
:
240 InitializeGLExtensionBindingsGL(context
);
241 InitializeGLExtensionBindingsOSMESA(context
);
243 case kGLImplementationEGLGLES2
:
244 InitializeGLExtensionBindingsGL(context
);
245 InitializeGLExtensionBindingsEGL(context
);
247 case kGLImplementationDesktopGL
:
248 InitializeGLExtensionBindingsGL(context
);
249 InitializeGLExtensionBindingsWGL(context
);
251 case kGLImplementationMockGL
:
252 InitializeGLExtensionBindingsGL(context
);
261 void InitializeDebugGLBindings() {
262 InitializeDebugGLBindingsEGL();
263 InitializeDebugGLBindingsGL();
264 InitializeDebugGLBindingsOSMESA();
265 InitializeDebugGLBindingsWGL();
268 void ClearGLBindings() {
269 ClearGLBindingsEGL();
271 ClearGLBindingsOSMESA();
272 ClearGLBindingsWGL();
273 SetGLImplementation(kGLImplementationNone
);
274 UnloadGLNativeLibraries();