blob: 17575cdcb30e92f0f38a8ea885be7489f9c3d698 [file] [log] [blame]
[email protected]5ae0b282011-03-28 19:24:491// Copyright (c) 2011 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"
[email protected]5826d0502011-08-31 20:31:2710#include "base/lazy_instance.h"
[email protected]30aa5c1a2010-07-14 20:47:0411#include "base/logging.h"
12#include "base/native_library.h"
13#include "base/path_service.h"
[email protected]25f06af2011-08-25 20:14:2314#include "base/synchronization/lock.h"
[email protected]6e318e0e2011-10-14 23:08:2015#include "base/threading/thread_restrictions.h"
[email protected]5ae0b282011-03-28 19:24:4916#include "ui/gfx/gl/gl_bindings.h"
17#include "ui/gfx/gl/gl_implementation.h"
[email protected]b9363b22010-06-09 22:06:1518
19namespace gfx {
20namespace {
[email protected]0bec8e22010-06-21 22:20:0221
22// TODO(piman): it should be Desktop GL marshalling from double to float. Today
23// on native GLES, we do float->double->float.
24void GL_BINDING_CALL MarshalClearDepthToClearDepthf(GLclampd depth) {
25 glClearDepthf(static_cast<GLclampf>(depth));
26}
27
28void GL_BINDING_CALL MarshalDepthRangeToDepthRangef(GLclampd z_near,
29 GLclampd z_far) {
30 glDepthRangef(static_cast<GLclampf>(z_near), static_cast<GLclampf>(z_far));
31}
32
[email protected]84479322011-04-18 22:06:2233// Load a library, printing an error message on failure.
[email protected]a246122752011-04-19 01:10:4834base::NativeLibrary LoadLibrary(const FilePath& filename) {
[email protected]84479322011-04-18 22:06:2235 std::string error;
[email protected]a246122752011-04-19 01:10:4836 base::NativeLibrary library = base::LoadNativeLibrary(filename,
[email protected]84479322011-04-18 22:06:2237 &error);
38 if (!library) {
[email protected]a246122752011-04-19 01:10:4839 VLOG(1) << "Failed to load " << filename.MaybeAsASCII() << ": " << error;
[email protected]84479322011-04-18 22:06:2240 return NULL;
41 }
42 return library;
43}
44
[email protected]a246122752011-04-19 01:10:4845base::NativeLibrary LoadLibrary(const char* filename) {
46 return LoadLibrary(FilePath(filename));
47}
48
[email protected]25f06af2011-08-25 20:14:2349// TODO(backer): Find a more principled (less heavy handed) way to prevent a
50// race in the bindings initialization.
51#if (defined(TOOLKIT_VIEWS) && !defined(OS_CHROMEOS)) || defined(TOUCH_UI)
[email protected]8cdcca3a42011-11-01 20:27:3752base::LazyInstance<base::Lock,
53 base::LeakyLazyInstanceTraits<base::Lock> >
[email protected]6de0fd1d2011-11-15 13:31:4954 g_lock = LAZY_INSTANCE_INITIALIZER;
[email protected]25f06af2011-08-25 20:14:2355#endif
56
[email protected]b9363b22010-06-09 22:06:1557} // namespace anonymous
58
[email protected]0f5e8882011-11-08 22:29:3859void GetAllowedGLImplementations(std::vector<GLImplementation>* impls) {
[email protected]3c4b7ef2011-11-21 22:24:4960#if !defined(USE_WAYLAND)
[email protected]3c4b7ef2011-11-21 22:24:4961 impls->push_back(kGLImplementationDesktopGL);
62#endif
63 impls->push_back(kGLImplementationEGLGLES2);
[email protected]70518b12011-11-22 01:39:1264#if !defined(USE_WAYLAND)
65 impls->push_back(kGLImplementationOSMesaGL);
66#endif
[email protected]0f5e8882011-11-08 22:29:3867}
68
[email protected]b9363b22010-06-09 22:06:1569bool InitializeGLBindings(GLImplementation implementation) {
[email protected]25f06af2011-08-25 20:14:2370#if (defined(TOOLKIT_VIEWS) && !defined(OS_CHROMEOS)) || defined(TOUCH_UI)
[email protected]5826d0502011-08-31 20:31:2771 base::AutoLock locked(g_lock.Get());
[email protected]25f06af2011-08-25 20:14:2372#endif
[email protected]b9363b22010-06-09 22:06:1573 // Prevent reinitialization with a different implementation. Once the gpu
74 // unit tests have initialized with kGLImplementationMock, we don't want to
75 // later switch to another GL implementation.
[email protected]30aa5c1a2010-07-14 20:47:0476 if (GetGLImplementation() != kGLImplementationNone)
[email protected]b9363b22010-06-09 22:06:1577 return true;
78
[email protected]6e318e0e2011-10-14 23:08:2079 // Allow the main thread or another to initialize these bindings
80 // after instituting restrictions on I/O. Going forward they will
81 // likely be used in the browser process on most platforms. The
82 // one-time initialization cost is small, between 2 and 5 ms.
83 base::ThreadRestrictions::ScopedAllowIO allow_io;
84
[email protected]b9363b22010-06-09 22:06:1585 switch (implementation) {
[email protected]f1b2cd02011-08-10 16:50:4486#if !defined(USE_WAYLAND)
[email protected]30aa5c1a2010-07-14 20:47:0487 case kGLImplementationOSMesaGL: {
[email protected]36a09792010-09-10 02:31:3988 FilePath module_path;
[email protected]d0498742010-09-20 20:27:0189 if (!PathService::Get(base::DIR_MODULE, &module_path)) {
90 LOG(ERROR) << "PathService::Get failed.";
[email protected]30aa5c1a2010-07-14 20:47:0491 return false;
[email protected]d0498742010-09-20 20:27:0192 }
[email protected]30aa5c1a2010-07-14 20:47:0493
[email protected]a246122752011-04-19 01:10:4894 base::NativeLibrary library = LoadLibrary(
95 module_path.Append("libosmesa.so"));
[email protected]84479322011-04-18 22:06:2296 if (!library)
[email protected]b9363b22010-06-09 22:06:1597 return false;
[email protected]0bec8e22010-06-21 22:20:0298
[email protected]30aa5c1a2010-07-14 20:47:0499 GLGetProcAddressProc get_proc_address =
100 reinterpret_cast<GLGetProcAddressProc>(
101 base::GetFunctionPointerFromNativeLibrary(
102 library, "OSMesaGetProcAddress"));
[email protected]1b2707bb2010-10-06 19:37:16103 if (!get_proc_address) {
[email protected]363b20d2011-01-14 22:54:16104 LOG(ERROR) << "OSMesaGetProcAddress not found.";
[email protected]1b2707bb2010-10-06 19:37:16105 base::UnloadNativeLibrary(library);
106 return false;
107 }
[email protected]b9363b22010-06-09 22:06:15108
[email protected]30aa5c1a2010-07-14 20:47:04109 SetGLGetProcAddressProc(get_proc_address);
110 AddGLNativeLibrary(library);
111 SetGLImplementation(kGLImplementationOSMesaGL);
[email protected]b9363b22010-06-09 22:06:15112
[email protected]30aa5c1a2010-07-14 20:47:04113 InitializeGLBindingsGL();
114 InitializeGLBindingsOSMESA();
115 break;
116 }
117 case kGLImplementationDesktopGL: {
[email protected]7f4115e2011-10-26 20:09:45118#if defined(OS_OPENBSD)
119 base::NativeLibrary library = LoadLibrary("libGL.so");
120#else
[email protected]84479322011-04-18 22:06:22121 base::NativeLibrary library = LoadLibrary("libGL.so.1");
[email protected]7f4115e2011-10-26 20:09:45122#endif
[email protected]84479322011-04-18 22:06:22123 if (!library)
[email protected]30aa5c1a2010-07-14 20:47:04124 return false;
[email protected]30aa5c1a2010-07-14 20:47:04125
126 GLGetProcAddressProc get_proc_address =
127 reinterpret_cast<GLGetProcAddressProc>(
128 base::GetFunctionPointerFromNativeLibrary(
129 library, "glXGetProcAddress"));
[email protected]1b2707bb2010-10-06 19:37:16130 if (!get_proc_address) {
131 LOG(ERROR) << "glxGetProcAddress not found.";
132 base::UnloadNativeLibrary(library);
133 return false;
134 }
[email protected]30aa5c1a2010-07-14 20:47:04135
136 SetGLGetProcAddressProc(get_proc_address);
137 AddGLNativeLibrary(library);
138 SetGLImplementation(kGLImplementationDesktopGL);
[email protected]b9363b22010-06-09 22:06:15139
140 InitializeGLBindingsGL();
141 InitializeGLBindingsGLX();
142 break;
[email protected]30aa5c1a2010-07-14 20:47:04143 }
[email protected]f1b2cd02011-08-10 16:50:44144#endif // !defined(USE_WAYLAND)
[email protected]30aa5c1a2010-07-14 20:47:04145 case kGLImplementationEGLGLES2: {
[email protected]84479322011-04-18 22:06:22146 base::NativeLibrary gles_library = LoadLibrary("libGLESv2.so");
147 if (!gles_library)
[email protected]1b2707bb2010-10-06 19:37:16148 return false;
[email protected]84479322011-04-18 22:06:22149 base::NativeLibrary egl_library = LoadLibrary("libEGL.so");
[email protected]91ac84f72011-06-22 19:48:02150 if (!egl_library) {
151 base::UnloadNativeLibrary(gles_library);
[email protected]0bec8e22010-06-21 22:20:02152 return false;
[email protected]91ac84f72011-06-22 19:48:02153 }
[email protected]0bec8e22010-06-21 22:20:02154
[email protected]30aa5c1a2010-07-14 20:47:04155 GLGetProcAddressProc get_proc_address =
156 reinterpret_cast<GLGetProcAddressProc>(
157 base::GetFunctionPointerFromNativeLibrary(
158 egl_library, "eglGetProcAddress"));
[email protected]1b2707bb2010-10-06 19:37:16159 if (!get_proc_address) {
160 LOG(ERROR) << "eglGetProcAddress not found.";
[email protected]30aa5c1a2010-07-14 20:47:04161 base::UnloadNativeLibrary(egl_library);
[email protected]1b2707bb2010-10-06 19:37:16162 base::UnloadNativeLibrary(gles_library);
[email protected]0bec8e22010-06-21 22:20:02163 return false;
164 }
165
[email protected]30aa5c1a2010-07-14 20:47:04166 SetGLGetProcAddressProc(get_proc_address);
167 AddGLNativeLibrary(egl_library);
168 AddGLNativeLibrary(gles_library);
169 SetGLImplementation(kGLImplementationEGLGLES2);
[email protected]0bec8e22010-06-21 22:20:02170
171 InitializeGLBindingsGL();
172 InitializeGLBindingsEGL();
173
174 // These two functions take single precision float rather than double
175 // precision float parameters in GLES.
176 ::gfx::g_glClearDepth = MarshalClearDepthToClearDepthf;
177 ::gfx::g_glDepthRange = MarshalDepthRangeToDepthRangef;
178 break;
[email protected]30aa5c1a2010-07-14 20:47:04179 }
180 case kGLImplementationMockGL: {
181 SetGLGetProcAddressProc(GetMockGLProcAddress);
182 SetGLImplementation(kGLImplementationMockGL);
[email protected]b9363b22010-06-09 22:06:15183 InitializeGLBindingsGL();
184 break;
[email protected]30aa5c1a2010-07-14 20:47:04185 }
[email protected]b9363b22010-06-09 22:06:15186 default:
187 return false;
188 }
189
190
191 return true;
192}
193
[email protected]6494823b2011-10-27 18:30:44194bool InitializeGLExtensionBindings(GLImplementation implementation,
195 GLContext* context) {
196 switch (implementation) {
[email protected]3c4b7ef2011-11-21 22:24:49197#if !defined(USE_WAYLAND)
[email protected]6494823b2011-10-27 18:30:44198 case kGLImplementationOSMesaGL:
199 InitializeGLExtensionBindingsGL(context);
200 InitializeGLExtensionBindingsOSMESA(context);
201 break;
202 case kGLImplementationDesktopGL:
203 InitializeGLExtensionBindingsGL(context);
204 InitializeGLExtensionBindingsGLX(context);
205 break;
[email protected]3c4b7ef2011-11-21 22:24:49206#endif
[email protected]6494823b2011-10-27 18:30:44207 case kGLImplementationEGLGLES2:
208 InitializeGLExtensionBindingsGL(context);
209 InitializeGLExtensionBindingsEGL(context);
210 break;
211 case kGLImplementationMockGL:
212 InitializeGLExtensionBindingsGL(context);
213 break;
214 default:
215 return false;
216 }
217
218 return true;
219}
220
[email protected]218a5a22010-11-04 19:27:49221void InitializeDebugGLBindings() {
222 InitializeDebugGLBindingsEGL();
223 InitializeDebugGLBindingsGL();
[email protected]f1b2cd02011-08-10 16:50:44224#if !defined(USE_WAYLAND)
[email protected]218a5a22010-11-04 19:27:49225 InitializeDebugGLBindingsGLX();
226 InitializeDebugGLBindingsOSMESA();
[email protected]f1b2cd02011-08-10 16:50:44227#endif
[email protected]218a5a22010-11-04 19:27:49228}
229
[email protected]0f5e8882011-11-08 22:29:38230void ClearGLBindings() {
231 ClearGLBindingsEGL();
232 ClearGLBindingsGL();
233#if !defined(USE_WAYLAND)
234 ClearGLBindingsGLX();
235 ClearGLBindingsOSMESA();
236#endif
237 SetGLImplementation(kGLImplementationNone);
238
239 UnloadGLNativeLibraries();
240}
241
[email protected]b9363b22010-06-09 22:06:15242} // namespace gfx