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.
4
5 #include "ui/gl/gl_implementation.h"
6
7 #include <algorithm>
8 #include <string>
9
10 #include "base/at_exit.h"
11 #include "base/command_line.h"
12 #include "base/logging.h"
13 #include "ui/gl/gl_bindings.h"
14
15 namespace gfx {
16
17 namespace {
18
19 const struct {
20 const char* name;
21 GLImplementation implementation;
22 } kGLImplementationNamePairs[] = {
23 { kGLImplementationDesktopName, kGLImplementationDesktopGL },
24 { kGLImplementationOSMesaName, kGLImplementationOSMesaGL },
25 #if defined(OS_MACOSX)
26 { kGLImplementationAppleName, kGLImplementationAppleGL },
27 #endif
28 { kGLImplementationEGLName, kGLImplementationEGLGLES2 },
29 { kGLImplementationMockName, kGLImplementationMockGL }
30 };
31
32 typedef std::vector<base::NativeLibrary> LibraryArray;
33
34 GLImplementation g_gl_implementation = kGLImplementationNone;
35 LibraryArray* g_libraries;
36 GLGetProcAddressProc g_get_proc_address;
37
CleanupNativeLibraries(void * unused)38 void CleanupNativeLibraries(void* unused) {
39 if (g_libraries) {
40 // We do not call base::UnloadNativeLibrary() for these libraries as
41 // unloading libGL without closing X display is not allowed. See
42 // crbug.com/250813 for details.
43 delete g_libraries;
44 g_libraries = NULL;
45 }
46 }
47
ExportsCoreFunctionsFromGetProcAddress(GLImplementation implementation)48 bool ExportsCoreFunctionsFromGetProcAddress(GLImplementation implementation) {
49 switch (GetGLImplementation()) {
50 case kGLImplementationDesktopGL:
51 case kGLImplementationOSMesaGL:
52 case kGLImplementationAppleGL:
53 case kGLImplementationMockGL:
54 return true;
55 case kGLImplementationEGLGLES2:
56 return false;
57 default:
58 NOTREACHED();
59 return true;
60 }
61 }
62
63 }
64
65 base::ThreadLocalPointer<GLApi>* g_current_gl_context_tls = NULL;
66 OSMESAApi* g_current_osmesa_context;
67
68 #if defined(OS_WIN)
69
70 EGLApi* g_current_egl_context;
71 WGLApi* g_current_wgl_context;
72
73 #elif defined(USE_X11)
74
75 EGLApi* g_current_egl_context;
76 GLXApi* g_current_glx_context;
77
78 #elif defined(USE_OZONE)
79
80 EGLApi* g_current_egl_context;
81
82 #elif defined(OS_ANDROID)
83
84 EGLApi* g_current_egl_context;
85
86 #endif
87
GetNamedGLImplementation(const std::string & name)88 GLImplementation GetNamedGLImplementation(const std::string& name) {
89 for (size_t i = 0; i < ARRAYSIZE_UNSAFE(kGLImplementationNamePairs); ++i) {
90 if (name == kGLImplementationNamePairs[i].name)
91 return kGLImplementationNamePairs[i].implementation;
92 }
93
94 return kGLImplementationNone;
95 }
96
GetGLImplementationName(GLImplementation implementation)97 const char* GetGLImplementationName(GLImplementation implementation) {
98 for (size_t i = 0; i < ARRAYSIZE_UNSAFE(kGLImplementationNamePairs); ++i) {
99 if (implementation == kGLImplementationNamePairs[i].implementation)
100 return kGLImplementationNamePairs[i].name;
101 }
102
103 return "unknown";
104 }
105
SetGLImplementation(GLImplementation implementation)106 void SetGLImplementation(GLImplementation implementation) {
107 g_gl_implementation = implementation;
108 }
109
GetGLImplementation()110 GLImplementation GetGLImplementation() {
111 return g_gl_implementation;
112 }
113
HasDesktopGLFeatures()114 bool HasDesktopGLFeatures() {
115 return kGLImplementationDesktopGL == g_gl_implementation ||
116 kGLImplementationOSMesaGL == g_gl_implementation ||
117 kGLImplementationAppleGL == g_gl_implementation;
118 }
119
AddGLNativeLibrary(base::NativeLibrary library)120 void AddGLNativeLibrary(base::NativeLibrary library) {
121 DCHECK(library);
122
123 if (!g_libraries) {
124 g_libraries = new LibraryArray;
125 base::AtExitManager::RegisterCallback(CleanupNativeLibraries, NULL);
126 }
127
128 g_libraries->push_back(library);
129 }
130
UnloadGLNativeLibraries()131 void UnloadGLNativeLibraries() {
132 CleanupNativeLibraries(NULL);
133 }
134
SetGLGetProcAddressProc(GLGetProcAddressProc proc)135 void SetGLGetProcAddressProc(GLGetProcAddressProc proc) {
136 DCHECK(proc);
137 g_get_proc_address = proc;
138 }
139
GetGLCoreProcAddress(const char * name)140 void* GetGLCoreProcAddress(const char* name) {
141 DCHECK(g_gl_implementation != kGLImplementationNone);
142
143 if (g_libraries) {
144 for (size_t i = 0; i < g_libraries->size(); ++i) {
145 void* proc = base::GetFunctionPointerFromNativeLibrary((*g_libraries)[i],
146 name);
147 if (proc)
148 return proc;
149 }
150 }
151 if (ExportsCoreFunctionsFromGetProcAddress(g_gl_implementation) &&
152 g_get_proc_address) {
153 void* proc = g_get_proc_address(name);
154 if (proc)
155 return proc;
156 }
157
158 return NULL;
159 }
160
GetGLProcAddress(const char * name)161 void* GetGLProcAddress(const char* name) {
162 DCHECK(g_gl_implementation != kGLImplementationNone);
163
164 void* proc = GetGLCoreProcAddress(name);
165 if (!proc && g_get_proc_address) {
166 proc = g_get_proc_address(name);
167 if (proc)
168 return proc;
169 }
170
171 return proc;
172 }
173
174 } // namespace gfx
175