blob: 5f96ed15860065719ebfebbefe31d22e37d9473a [file] [log] [blame]
[email protected]991c5682012-01-30 13:32:341// Copyright (c) 2012 The Chromium Authors. All rights reserved.
[email protected]b9363b22010-06-09 22:06:152// Use of this source code is governed by a BSD-style license that can be
3// found in the LICENSE file.
4
[email protected]0bec8e22010-06-21 22:20:025#include <vector>
[email protected]b9363b22010-06-09 22:06:156
[email protected]30aa5c1a2010-07-14 20:47:047#include "base/base_paths.h"
8#include "base/command_line.h"
9#include "base/file_path.h"
10#include "base/logging.h"
11#include "base/native_library.h"
12#include "base/path_service.h"
[email protected]6e318e0e2011-10-14 23:08:2013#include "base/threading/thread_restrictions.h"
[email protected]5ae0b282011-03-28 19:24:4914#include "ui/gfx/gl/gl_bindings.h"
15#include "ui/gfx/gl/gl_implementation.h"
[email protected]991c5682012-01-30 13:32:3416#include "ui/gfx/gl/gl_switches.h"
[email protected]b9363b22010-06-09 22:06:1517
18namespace gfx {
19namespace {
[email protected]0bec8e22010-06-21 22:20:0220
21// TODO(piman): it should be Desktop GL marshalling from double to float. Today
22// on native GLES, we do float->double->float.
23void GL_BINDING_CALL MarshalClearDepthToClearDepthf(GLclampd depth) {
24 glClearDepthf(static_cast<GLclampf>(depth));
25}
26
27void GL_BINDING_CALL MarshalDepthRangeToDepthRangef(GLclampd z_near,
28 GLclampd z_far) {
29 glDepthRangef(static_cast<GLclampf>(z_near), static_cast<GLclampf>(z_far));
30}
31
[email protected]84479322011-04-18 22:06:2232// Load a library, printing an error message on failure.
[email protected]a246122752011-04-19 01:10:4833base::NativeLibrary LoadLibrary(const FilePath& filename) {
[email protected]84479322011-04-18 22:06:2234 std::string error;
[email protected]a246122752011-04-19 01:10:4835 base::NativeLibrary library = base::LoadNativeLibrary(filename,
[email protected]84479322011-04-18 22:06:2236 &error);
37 if (!library) {
[email protected]a246122752011-04-19 01:10:4838 VLOG(1) << "Failed to load " << filename.MaybeAsASCII() << ": " << error;
[email protected]84479322011-04-18 22:06:2239 return NULL;
40 }
41 return library;
42}
43
[email protected]a246122752011-04-19 01:10:4844base::NativeLibrary LoadLibrary(const char* filename) {
45 return LoadLibrary(FilePath(filename));
46}
47
[email protected]b9363b22010-06-09 22:06:1548} // namespace anonymous
49
[email protected]0f5e8882011-11-08 22:29:3850void GetAllowedGLImplementations(std::vector<GLImplementation>* impls) {
[email protected]3c4b7ef2011-11-21 22:24:4951#if !defined(USE_WAYLAND)
[email protected]3c4b7ef2011-11-21 22:24:4952 impls->push_back(kGLImplementationDesktopGL);
53#endif
54 impls->push_back(kGLImplementationEGLGLES2);
[email protected]70518b12011-11-22 01:39:1255#if !defined(USE_WAYLAND)
56 impls->push_back(kGLImplementationOSMesaGL);
57#endif
[email protected]0f5e8882011-11-08 22:29:3858}
59
[email protected]b9363b22010-06-09 22:06:1560bool InitializeGLBindings(GLImplementation implementation) {
61 // Prevent reinitialization with a different implementation. Once the gpu
62 // unit tests have initialized with kGLImplementationMock, we don't want to
63 // later switch to another GL implementation.
[email protected]30aa5c1a2010-07-14 20:47:0464 if (GetGLImplementation() != kGLImplementationNone)
[email protected]b9363b22010-06-09 22:06:1565 return true;
66
[email protected]6e318e0e2011-10-14 23:08:2067 // Allow the main thread or another to initialize these bindings
68 // after instituting restrictions on I/O. Going forward they will
69 // likely be used in the browser process on most platforms. The
70 // one-time initialization cost is small, between 2 and 5 ms.
71 base::ThreadRestrictions::ScopedAllowIO allow_io;
72
[email protected]b9363b22010-06-09 22:06:1573 switch (implementation) {
[email protected]f1b2cd02011-08-10 16:50:4474#if !defined(USE_WAYLAND)
[email protected]30aa5c1a2010-07-14 20:47:0475 case kGLImplementationOSMesaGL: {
[email protected]36a09792010-09-10 02:31:3976 FilePath module_path;
[email protected]d0498742010-09-20 20:27:0177 if (!PathService::Get(base::DIR_MODULE, &module_path)) {
78 LOG(ERROR) << "PathService::Get failed.";
[email protected]30aa5c1a2010-07-14 20:47:0479 return false;
[email protected]d0498742010-09-20 20:27:0180 }
[email protected]30aa5c1a2010-07-14 20:47:0481
[email protected]a246122752011-04-19 01:10:4882 base::NativeLibrary library = LoadLibrary(
83 module_path.Append("libosmesa.so"));
[email protected]84479322011-04-18 22:06:2284 if (!library)
[email protected]b9363b22010-06-09 22:06:1585 return false;
[email protected]0bec8e22010-06-21 22:20:0286
[email protected]30aa5c1a2010-07-14 20:47:0487 GLGetProcAddressProc get_proc_address =
88 reinterpret_cast<GLGetProcAddressProc>(
89 base::GetFunctionPointerFromNativeLibrary(
90 library, "OSMesaGetProcAddress"));
[email protected]1b2707bb2010-10-06 19:37:1691 if (!get_proc_address) {
[email protected]363b20d2011-01-14 22:54:1692 LOG(ERROR) << "OSMesaGetProcAddress not found.";
[email protected]1b2707bb2010-10-06 19:37:1693 base::UnloadNativeLibrary(library);
94 return false;
95 }
[email protected]b9363b22010-06-09 22:06:1596
[email protected]30aa5c1a2010-07-14 20:47:0497 SetGLGetProcAddressProc(get_proc_address);
98 AddGLNativeLibrary(library);
99 SetGLImplementation(kGLImplementationOSMesaGL);
[email protected]b9363b22010-06-09 22:06:15100
[email protected]30aa5c1a2010-07-14 20:47:04101 InitializeGLBindingsGL();
102 InitializeGLBindingsOSMESA();
103 break;
104 }
105 case kGLImplementationDesktopGL: {
[email protected]991c5682012-01-30 13:32:34106 base::NativeLibrary library = NULL;
107 const CommandLine* command_line = CommandLine::ForCurrentProcess();
108
109 if (command_line->HasSwitch(switches::kTestGLLib))
110 library = LoadLibrary(command_line->GetSwitchValueASCII(
111 switches::kTestGLLib).c_str());
112
113 if (!library) {
[email protected]7f4115e2011-10-26 20:09:45114#if defined(OS_OPENBSD)
[email protected]991c5682012-01-30 13:32:34115 library = LoadLibrary("libGL.so");
[email protected]7f4115e2011-10-26 20:09:45116#else
[email protected]991c5682012-01-30 13:32:34117 library = LoadLibrary("libGL.so.1");
[email protected]7f4115e2011-10-26 20:09:45118#endif
[email protected]991c5682012-01-30 13:32:34119 }
120
[email protected]84479322011-04-18 22:06:22121 if (!library)
[email protected]30aa5c1a2010-07-14 20:47:04122 return false;
[email protected]30aa5c1a2010-07-14 20:47:04123
124 GLGetProcAddressProc get_proc_address =
125 reinterpret_cast<GLGetProcAddressProc>(
126 base::GetFunctionPointerFromNativeLibrary(
127 library, "glXGetProcAddress"));
[email protected]1b2707bb2010-10-06 19:37:16128 if (!get_proc_address) {
129 LOG(ERROR) << "glxGetProcAddress not found.";
130 base::UnloadNativeLibrary(library);
131 return false;
132 }
[email protected]30aa5c1a2010-07-14 20:47:04133
134 SetGLGetProcAddressProc(get_proc_address);
135 AddGLNativeLibrary(library);
136 SetGLImplementation(kGLImplementationDesktopGL);
[email protected]b9363b22010-06-09 22:06:15137
138 InitializeGLBindingsGL();
139 InitializeGLBindingsGLX();
140 break;
[email protected]30aa5c1a2010-07-14 20:47:04141 }
[email protected]f1b2cd02011-08-10 16:50:44142#endif // !defined(USE_WAYLAND)
[email protected]30aa5c1a2010-07-14 20:47:04143 case kGLImplementationEGLGLES2: {
[email protected]84479322011-04-18 22:06:22144 base::NativeLibrary gles_library = LoadLibrary("libGLESv2.so");
145 if (!gles_library)
[email protected]1b2707bb2010-10-06 19:37:16146 return false;
[email protected]84479322011-04-18 22:06:22147 base::NativeLibrary egl_library = LoadLibrary("libEGL.so");
[email protected]91ac84f72011-06-22 19:48:02148 if (!egl_library) {
149 base::UnloadNativeLibrary(gles_library);
[email protected]0bec8e22010-06-21 22:20:02150 return false;
[email protected]91ac84f72011-06-22 19:48:02151 }
[email protected]0bec8e22010-06-21 22:20:02152
[email protected]30aa5c1a2010-07-14 20:47:04153 GLGetProcAddressProc get_proc_address =
154 reinterpret_cast<GLGetProcAddressProc>(
155 base::GetFunctionPointerFromNativeLibrary(
156 egl_library, "eglGetProcAddress"));
[email protected]1b2707bb2010-10-06 19:37:16157 if (!get_proc_address) {
158 LOG(ERROR) << "eglGetProcAddress not found.";
[email protected]30aa5c1a2010-07-14 20:47:04159 base::UnloadNativeLibrary(egl_library);
[email protected]1b2707bb2010-10-06 19:37:16160 base::UnloadNativeLibrary(gles_library);
[email protected]0bec8e22010-06-21 22:20:02161 return false;
162 }
163
[email protected]30aa5c1a2010-07-14 20:47:04164 SetGLGetProcAddressProc(get_proc_address);
165 AddGLNativeLibrary(egl_library);
166 AddGLNativeLibrary(gles_library);
167 SetGLImplementation(kGLImplementationEGLGLES2);
[email protected]0bec8e22010-06-21 22:20:02168
169 InitializeGLBindingsGL();
170 InitializeGLBindingsEGL();
171
172 // These two functions take single precision float rather than double
173 // precision float parameters in GLES.
174 ::gfx::g_glClearDepth = MarshalClearDepthToClearDepthf;
175 ::gfx::g_glDepthRange = MarshalDepthRangeToDepthRangef;
176 break;
[email protected]30aa5c1a2010-07-14 20:47:04177 }
178 case kGLImplementationMockGL: {
179 SetGLGetProcAddressProc(GetMockGLProcAddress);
180 SetGLImplementation(kGLImplementationMockGL);
[email protected]b9363b22010-06-09 22:06:15181 InitializeGLBindingsGL();
182 break;
[email protected]30aa5c1a2010-07-14 20:47:04183 }
[email protected]b9363b22010-06-09 22:06:15184 default:
185 return false;
186 }
187
188
189 return true;
190}
191
[email protected]6494823b2011-10-27 18:30:44192bool InitializeGLExtensionBindings(GLImplementation implementation,
193 GLContext* context) {
194 switch (implementation) {
[email protected]3c4b7ef2011-11-21 22:24:49195#if !defined(USE_WAYLAND)
[email protected]6494823b2011-10-27 18:30:44196 case kGLImplementationOSMesaGL:
197 InitializeGLExtensionBindingsGL(context);
198 InitializeGLExtensionBindingsOSMESA(context);
199 break;
200 case kGLImplementationDesktopGL:
201 InitializeGLExtensionBindingsGL(context);
202 InitializeGLExtensionBindingsGLX(context);
203 break;
[email protected]3c4b7ef2011-11-21 22:24:49204#endif
[email protected]6494823b2011-10-27 18:30:44205 case kGLImplementationEGLGLES2:
206 InitializeGLExtensionBindingsGL(context);
207 InitializeGLExtensionBindingsEGL(context);
208 break;
209 case kGLImplementationMockGL:
210 InitializeGLExtensionBindingsGL(context);
211 break;
212 default:
213 return false;
214 }
215
216 return true;
217}
218
[email protected]218a5a22010-11-04 19:27:49219void InitializeDebugGLBindings() {
220 InitializeDebugGLBindingsEGL();
221 InitializeDebugGLBindingsGL();
[email protected]f1b2cd02011-08-10 16:50:44222#if !defined(USE_WAYLAND)
[email protected]218a5a22010-11-04 19:27:49223 InitializeDebugGLBindingsGLX();
224 InitializeDebugGLBindingsOSMESA();
[email protected]f1b2cd02011-08-10 16:50:44225#endif
[email protected]218a5a22010-11-04 19:27:49226}
227
[email protected]0f5e8882011-11-08 22:29:38228void ClearGLBindings() {
229 ClearGLBindingsEGL();
230 ClearGLBindingsGL();
231#if !defined(USE_WAYLAND)
232 ClearGLBindingsGLX();
233 ClearGLBindingsOSMESA();
234#endif
235 SetGLImplementation(kGLImplementationNone);
236
237 UnloadGLNativeLibraries();
238}
239
[email protected]b9363b22010-06-09 22:06:15240} // namespace gfx