Fix build break
[chromium-blink-merge.git] / ui / gl / gl_implementation_win.cc
blobf0c562648bccbce37f5e111b785b669d67597423
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.
5 #include <vector>
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/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"
27 #endif
29 namespace gfx {
31 namespace {
33 // Version 43 is the latest version of D3DCompiler_nn.dll that works prior to
34 // Windows Vista.
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,
43 GLclampd z_far) {
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);
51 if (!library) {
52 library = base::LoadNativeLibrary(module_path.Append(name), NULL);
53 if (!library) {
54 DVLOG(1) << name << " not found.";
55 return false;
58 return true;
61 } // namespace
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)
74 return true;
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.";
87 return false;
90 base::NativeLibrary library = base::LoadNativeLibrary(
91 module_path.Append(L"osmesa.dll"), NULL);
92 if (!library) {
93 DVLOG(1) << "osmesa.dll not found";
94 return false;
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);
104 return false;
107 SetGLGetProcAddressProc(get_proc_address);
108 AddGLNativeLibrary(library);
109 SetGLImplementation(kGLImplementationOSMesaGL);
111 InitializeGLBindingsGL();
112 InitializeGLBindingsOSMESA();
113 break;
115 case kGLImplementationEGLGLES2: {
116 base::FilePath module_path;
117 if (!PathService::Get(base::DIR_MODULE, &module_path))
118 return false;
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))
135 return false;
136 gles_path =
137 command_line->GetSwitchValuePath(switches::kSwiftShaderPath);
138 // Preload library
139 LoadLibrary(L"ddraw.dll");
140 } else {
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);
149 if (!gles_library) {
150 DVLOG(1) << "libglesv2.dll not found";
151 return false;
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);
158 if (!egl_library) {
159 DVLOG(1) << "libegl.dll not found.";
160 base::UnloadNativeLibrary(gles_library);
161 return false;
164 #if defined(ENABLE_SWIFTSHADER)
165 if (using_swift_shader) {
166 SetupSoftwareRenderer(gles_library);
168 #endif
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);
178 return false;
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;
193 break;
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);
200 if (!library) {
201 DVLOG(1) << "opengl32.dll not found";
202 return false;
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);
212 return false;
215 SetGLGetProcAddressProc(get_proc_address);
216 AddGLNativeLibrary(library);
217 SetGLImplementation(kGLImplementationDesktopGL);
219 InitializeGLBindingsGL();
220 InitializeGLBindingsWGL();
221 break;
223 case kGLImplementationMockGL: {
224 SetGLGetProcAddressProc(GetMockGLProcAddress);
225 SetGLImplementation(kGLImplementationMockGL);
226 InitializeGLBindingsGL();
227 break;
229 default:
230 return false;
233 return true;
236 bool InitializeGLExtensionBindings(GLImplementation implementation,
237 GLContext* context) {
238 switch (implementation) {
239 case kGLImplementationOSMesaGL:
240 InitializeGLExtensionBindingsGL(context);
241 InitializeGLExtensionBindingsOSMESA(context);
242 break;
243 case kGLImplementationEGLGLES2:
244 InitializeGLExtensionBindingsGL(context);
245 InitializeGLExtensionBindingsEGL(context);
246 break;
247 case kGLImplementationDesktopGL:
248 InitializeGLExtensionBindingsGL(context);
249 InitializeGLExtensionBindingsWGL(context);
250 break;
251 case kGLImplementationMockGL:
252 InitializeGLExtensionBindingsGL(context);
253 break;
254 default:
255 return false;
258 return true;
261 void InitializeDebugGLBindings() {
262 InitializeDebugGLBindingsEGL();
263 InitializeDebugGLBindingsGL();
264 InitializeDebugGLBindingsOSMESA();
265 InitializeDebugGLBindingsWGL();
268 void ClearGLBindings() {
269 ClearGLBindingsEGL();
270 ClearGLBindingsGL();
271 ClearGLBindingsOSMESA();
272 ClearGLBindingsWGL();
273 SetGLImplementation(kGLImplementationNone);
274 UnloadGLNativeLibraries();
277 } // namespace gfx