Use int64 time stamp when storing metadata to the HTTP cache.
[chromium-blink-merge.git] / ui / gl / gl_implementation_win.cc
blob477f5a5b4b3118a5e4f66ddcc80ecbbc0e7cbe64
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/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"
30 #endif
32 namespace gfx {
34 namespace {
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,
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 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,
67 const char* name,
68 unsigned long long id,
69 int num_args,
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,
76 name,
77 id,
78 num_args,
79 arg_names,
80 arg_types,
81 arg_values,
82 NULL,
83 flags);
86 typedef const unsigned char* (*GetCategoryEnabledFlagFunc)(const char* name);
87 typedef void (*AddTraceEventFunc)(char phase,
88 const unsigned char* categoryGroupEnabled,
89 const char* name,
90 unsigned long long id,
91 int numArgs,
92 const char** argNames,
93 const unsigned char* argTypes,
94 const unsigned long long* argValues,
95 unsigned char flags);
96 typedef void (__stdcall *SetTraceFunctionPointersFunc)(
97 GetCategoryEnabledFlagFunc get_category_enabled_flag,
98 AddTraceEventFunc add_trace_event_func);
100 } // namespace
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.";
125 return false;
128 base::NativeLibrary library = base::LoadNativeLibrary(
129 module_path.Append(L"osmesa.dll"), NULL);
130 if (!library) {
131 DVLOG(1) << "osmesa.dll not found";
132 return false;
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);
142 return false;
145 SetGLGetProcAddressProc(get_proc_address);
146 AddGLNativeLibrary(library);
147 SetGLImplementation(kGLImplementationOSMesaGL);
149 InitializeStaticGLBindingsGL();
150 InitializeStaticGLBindingsOSMESA();
151 break;
153 case kGLImplementationEGLGLES2: {
154 base::FilePath module_path;
155 if (!PathService::Get(base::DIR_MODULE, &module_path))
156 return false;
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
161 // search path.
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))
171 return false;
172 gles_path =
173 command_line->GetSwitchValuePath(switches::kSwiftShaderPath);
174 // Preload library
175 LoadLibrary(L"ddraw.dll");
176 } else {
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);
185 if (!gles_library) {
186 DVLOG(1) << "libglesv2.dll not found";
187 return false;
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);
194 if (!egl_library) {
195 DVLOG(1) << "libegl.dll not found.";
196 base::UnloadNativeLibrary(gles_library);
197 return false;
200 #if defined(ENABLE_SWIFTSHADER)
201 if (using_swift_shader) {
202 SetupSoftwareRenderer(gles_library);
204 #endif
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);
225 return false;
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;
240 break;
242 case kGLImplementationDesktopGL: {
243 base::NativeLibrary library = base::LoadNativeLibrary(
244 base::FilePath(L"opengl32.dll"), NULL);
245 if (!library) {
246 DVLOG(1) << "opengl32.dll not found";
247 return false;
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);
257 return false;
260 SetGLGetProcAddressProc(get_proc_address);
261 AddGLNativeLibrary(library);
262 SetGLImplementation(kGLImplementationDesktopGL);
264 // Initialize GL surface and get some functions needed for the context
265 // creation below.
266 if (!GLSurfaceWGL::InitializeOneOff()) {
267 LOG(ERROR) << "GLSurfaceWGL::InitializeOneOff failed.";
268 return false;
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());
289 if (!gl_context) {
290 LOG(ERROR) << "Failed to create temporary context.";
291 return false;
293 if (!wglMakeCurrentFn(GLSurfaceWGL::GetDisplayDC(), gl_context)) {
294 LOG(ERROR) << "Failed to make temporary GL context current.";
295 wglDeleteContextFn(gl_context);
296 return false;
299 InitializeStaticGLBindingsGL();
300 InitializeStaticGLBindingsWGL();
302 wglMakeCurrent(NULL, NULL);
303 wglDeleteContext(gl_context);
305 break;
307 case kGLImplementationMockGL: {
308 SetGLImplementation(kGLImplementationMockGL);
309 InitializeStaticGLBindingsGL();
310 break;
312 default:
313 return false;
316 return true;
319 bool InitializeDynamicGLBindings(GLImplementation implementation,
320 GLContext* context) {
321 switch (implementation) {
322 case kGLImplementationOSMesaGL:
323 case kGLImplementationEGLGLES2:
324 case kGLImplementationDesktopGL:
325 InitializeDynamicGLBindingsGL(context);
326 break;
327 case kGLImplementationMockGL:
328 if (!context) {
329 scoped_refptr<GLContextStubWithExtensions> mock_context(
330 new GLContextStubWithExtensions());
331 mock_context->SetGLVersionString("3.0");
332 InitializeDynamicGLBindingsGL(mock_context.get());
333 } else
334 InitializeDynamicGLBindingsGL(context);
335 break;
336 default:
337 return false;
340 return true;
343 void InitializeDebugGLBindings() {
344 InitializeDebugGLBindingsEGL();
345 InitializeDebugGLBindingsGL();
346 InitializeDebugGLBindingsOSMESA();
347 InitializeDebugGLBindingsWGL();
350 void ClearGLBindings() {
351 ClearGLBindingsEGL();
352 ClearGLBindingsGL();
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);
365 default:
366 return false;
370 } // namespace gfx