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/strings/stringprintf.h"
16 #include "base/threading/thread_restrictions.h"
17 #include "base/trace_event/trace_event.h"
18 #include "base/win/windows_version.h"
19 #include "ui/gl/gl_bindings.h"
20 #include "ui/gl/gl_context_stub_with_extensions.h"
21 #include "ui/gl/gl_egl_api_implementation.h"
22 #include "ui/gl/gl_gl_api_implementation.h"
23 #include "ui/gl/gl_implementation.h"
24 #include "ui/gl/gl_osmesa_api_implementation.h"
25 #include "ui/gl/gl_surface_wgl.h"
26 #include "ui/gl/gl_wgl_api_implementation.h"
28 #if defined(ENABLE_SWIFTSHADER)
29 #include "software_renderer.h"
36 const wchar_t kD3DCompiler
[] = L
"D3DCompiler_47.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.";
61 const unsigned char* AngleGetTraceCategoryEnabledFlag(const char* name
) {
62 return TRACE_EVENT_API_GET_CATEGORY_GROUP_ENABLED(name
);
65 void AngleAddTraceEvent(char phase
,
66 const unsigned char* category_group_enabled
,
68 unsigned long long id
,
70 const char** arg_names
,
71 const unsigned char* arg_types
,
72 const unsigned long long* arg_values
,
73 unsigned char flags
) {
74 TRACE_EVENT_API_ADD_TRACE_EVENT(phase
,
75 category_group_enabled
,
86 typedef const unsigned char* (*GetCategoryEnabledFlagFunc
)(const char* name
);
87 typedef void (*AddTraceEventFunc
)(char phase
,
88 const unsigned char* categoryGroupEnabled
,
90 unsigned long long id
,
92 const char** argNames
,
93 const unsigned char* argTypes
,
94 const unsigned long long* argValues
,
96 typedef void (__stdcall
*SetTraceFunctionPointersFunc
)(
97 GetCategoryEnabledFlagFunc get_category_enabled_flag
,
98 AddTraceEventFunc add_trace_event_func
);
102 void GetAllowedGLImplementations(std::vector
<GLImplementation
>* impls
) {
103 impls
->push_back(kGLImplementationEGLGLES2
);
104 impls
->push_back(kGLImplementationDesktopGL
);
105 impls
->push_back(kGLImplementationOSMesaGL
);
108 bool InitializeStaticGLBindings(GLImplementation implementation
) {
109 // Prevent reinitialization with a different implementation. Once the gpu
110 // unit tests have initialized with kGLImplementationMock, we don't want to
111 // later switch to another GL implementation.
112 DCHECK_EQ(kGLImplementationNone
, GetGLImplementation());
114 // Allow the main thread or another to initialize these bindings
115 // after instituting restrictions on I/O. Going forward they will
116 // likely be used in the browser process on most platforms. The
117 // one-time initialization cost is small, between 2 and 5 ms.
118 base::ThreadRestrictions::ScopedAllowIO allow_io
;
120 switch (implementation
) {
121 case kGLImplementationOSMesaGL
: {
122 base::FilePath module_path
;
123 if (!PathService::Get(base::DIR_MODULE
, &module_path
)) {
124 LOG(ERROR
) << "PathService::Get failed.";
128 base::NativeLibrary library
= base::LoadNativeLibrary(
129 module_path
.Append(L
"osmesa.dll"), NULL
);
131 DVLOG(1) << "osmesa.dll not found";
135 GLGetProcAddressProc get_proc_address
=
136 reinterpret_cast<GLGetProcAddressProc
>(
137 base::GetFunctionPointerFromNativeLibrary(
138 library
, "OSMesaGetProcAddress"));
139 if (!get_proc_address
) {
140 DLOG(ERROR
) << "OSMesaGetProcAddress not found.";
141 base::UnloadNativeLibrary(library
);
145 SetGLGetProcAddressProc(get_proc_address
);
146 AddGLNativeLibrary(library
);
147 SetGLImplementation(kGLImplementationOSMesaGL
);
149 InitializeStaticGLBindingsGL();
150 InitializeStaticGLBindingsOSMESA();
153 case kGLImplementationEGLGLES2
: {
154 base::FilePath module_path
;
155 if (!PathService::Get(base::DIR_MODULE
, &module_path
))
158 // Attempt to load the D3DX shader compiler using the default search path
159 // and if that fails, using an absolute path. This is to ensure these DLLs
160 // are loaded before ANGLE is loaded in case they are not in the default
162 LoadD3DXLibrary(module_path
, kD3DCompiler
);
164 base::FilePath gles_path
;
165 const base::CommandLine
* command_line
=
166 base::CommandLine::ForCurrentProcess();
167 bool using_swift_shader
=
168 command_line
->GetSwitchValueASCII(switches::kUseGL
) == "swiftshader";
169 if (using_swift_shader
) {
170 if (!command_line
->HasSwitch(switches::kSwiftShaderPath
))
173 command_line
->GetSwitchValuePath(switches::kSwiftShaderPath
);
175 LoadLibrary(L
"ddraw.dll");
177 gles_path
= module_path
;
180 // Load libglesv2.dll before libegl.dll because the latter is dependent on
181 // the former and if there is another version of libglesv2.dll in the dll
182 // search path, it will get loaded instead.
183 base::NativeLibrary gles_library
= base::LoadNativeLibrary(
184 gles_path
.Append(L
"libglesv2.dll"), NULL
);
186 DVLOG(1) << "libglesv2.dll not found";
190 // When using EGL, first try eglGetProcAddress and then Windows
191 // GetProcAddress on both the EGL and GLES2 DLLs.
192 base::NativeLibrary egl_library
= base::LoadNativeLibrary(
193 gles_path
.Append(L
"libegl.dll"), NULL
);
195 DVLOG(1) << "libegl.dll not found.";
196 base::UnloadNativeLibrary(gles_library
);
200 #if defined(ENABLE_SWIFTSHADER)
201 if (using_swift_shader
) {
202 SetupSoftwareRenderer(gles_library
);
206 if (!using_swift_shader
) {
207 SetTraceFunctionPointersFunc set_trace_function_pointers
=
208 reinterpret_cast<SetTraceFunctionPointersFunc
>(
209 base::GetFunctionPointerFromNativeLibrary(
210 gles_library
, "SetTraceFunctionPointers"));
211 if (set_trace_function_pointers
) {
212 set_trace_function_pointers(&AngleGetTraceCategoryEnabledFlag
,
213 &AngleAddTraceEvent
);
217 GLGetProcAddressProc get_proc_address
=
218 reinterpret_cast<GLGetProcAddressProc
>(
219 base::GetFunctionPointerFromNativeLibrary(
220 egl_library
, "eglGetProcAddress"));
221 if (!get_proc_address
) {
222 LOG(ERROR
) << "eglGetProcAddress not found.";
223 base::UnloadNativeLibrary(egl_library
);
224 base::UnloadNativeLibrary(gles_library
);
228 SetGLGetProcAddressProc(get_proc_address
);
229 AddGLNativeLibrary(egl_library
);
230 AddGLNativeLibrary(gles_library
);
231 SetGLImplementation(kGLImplementationEGLGLES2
);
233 InitializeStaticGLBindingsGL();
234 InitializeStaticGLBindingsEGL();
236 // These two functions take single precision float rather than double
237 // precision float parameters in GLES.
238 ::gfx::g_driver_gl
.fn
.glClearDepthFn
= MarshalClearDepthToClearDepthf
;
239 ::gfx::g_driver_gl
.fn
.glDepthRangeFn
= MarshalDepthRangeToDepthRangef
;
242 case kGLImplementationDesktopGL
: {
243 base::NativeLibrary library
= base::LoadNativeLibrary(
244 base::FilePath(L
"opengl32.dll"), NULL
);
246 DVLOG(1) << "opengl32.dll not found";
250 GLGetProcAddressProc get_proc_address
=
251 reinterpret_cast<GLGetProcAddressProc
>(
252 base::GetFunctionPointerFromNativeLibrary(
253 library
, "wglGetProcAddress"));
254 if (!get_proc_address
) {
255 LOG(ERROR
) << "wglGetProcAddress not found.";
256 base::UnloadNativeLibrary(library
);
260 SetGLGetProcAddressProc(get_proc_address
);
261 AddGLNativeLibrary(library
);
262 SetGLImplementation(kGLImplementationDesktopGL
);
264 // Initialize GL surface and get some functions needed for the context
266 if (!GLSurfaceWGL::InitializeOneOff()) {
267 LOG(ERROR
) << "GLSurfaceWGL::InitializeOneOff failed.";
270 wglCreateContextProc wglCreateContextFn
=
271 reinterpret_cast<wglCreateContextProc
>(
272 GetGLProcAddress("wglCreateContext"));
273 wglDeleteContextProc wglDeleteContextFn
=
274 reinterpret_cast<wglDeleteContextProc
>(
275 GetGLProcAddress("wglDeleteContext"));
276 wglMakeCurrentProc wglMakeCurrentFn
=
277 reinterpret_cast<wglMakeCurrentProc
>(
278 GetGLProcAddress("wglMakeCurrent"));
280 // Create a temporary GL context to bind to entry points. This is needed
281 // because wglGetProcAddress is specified to return NULL for all queries
282 // if a context is not current in MSDN documentation, and the static
283 // bindings may contain functions that need to be queried with
284 // wglGetProcAddress. OpenGL wiki further warns that other error values
285 // than NULL could also be returned from wglGetProcAddress on some
286 // implementations, so we need to clear the WGL bindings and reinitialize
287 // them after the context creation.
288 HGLRC gl_context
= wglCreateContextFn(GLSurfaceWGL::GetDisplayDC());
290 LOG(ERROR
) << "Failed to create temporary context.";
293 if (!wglMakeCurrentFn(GLSurfaceWGL::GetDisplayDC(), gl_context
)) {
294 LOG(ERROR
) << "Failed to make temporary GL context current.";
295 wglDeleteContextFn(gl_context
);
299 InitializeStaticGLBindingsGL();
300 InitializeStaticGLBindingsWGL();
302 wglMakeCurrent(NULL
, NULL
);
303 wglDeleteContext(gl_context
);
307 case kGLImplementationMockGL
: {
308 SetGLImplementation(kGLImplementationMockGL
);
309 InitializeStaticGLBindingsGL();
319 bool InitializeDynamicGLBindings(GLImplementation implementation
,
320 GLContext
* context
) {
321 switch (implementation
) {
322 case kGLImplementationOSMesaGL
:
323 case kGLImplementationEGLGLES2
:
324 case kGLImplementationDesktopGL
:
325 InitializeDynamicGLBindingsGL(context
);
327 case kGLImplementationMockGL
:
329 scoped_refptr
<GLContextStubWithExtensions
> mock_context(
330 new GLContextStubWithExtensions());
331 mock_context
->SetGLVersionString("3.0");
332 InitializeDynamicGLBindingsGL(mock_context
.get());
334 InitializeDynamicGLBindingsGL(context
);
343 void InitializeDebugGLBindings() {
344 InitializeDebugGLBindingsEGL();
345 InitializeDebugGLBindingsGL();
346 InitializeDebugGLBindingsOSMESA();
347 InitializeDebugGLBindingsWGL();
350 void ClearGLBindings() {
351 ClearGLBindingsEGL();
353 ClearGLBindingsOSMESA();
354 ClearGLBindingsWGL();
355 SetGLImplementation(kGLImplementationNone
);
356 UnloadGLNativeLibraries();
359 bool GetGLWindowSystemBindingInfo(GLWindowSystemBindingInfo
* info
) {
360 switch (GetGLImplementation()) {
361 case kGLImplementationDesktopGL
:
362 return GetGLWindowSystemBindingInfoWGL(info
);
363 case kGLImplementationEGLGLES2
:
364 return GetGLWindowSystemBindingInfoEGL(info
);