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 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 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 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 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 106 void SetGLImplementation(GLImplementation implementation) { 107 g_gl_implementation = implementation; 108 } 109 110 GLImplementation GetGLImplementation() { 111 return g_gl_implementation; 112 } 113 114 bool HasDesktopGLFeatures() { 115 return kGLImplementationDesktopGL == g_gl_implementation || 116 kGLImplementationOSMesaGL == g_gl_implementation || 117 kGLImplementationAppleGL == g_gl_implementation; 118 } 119 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 131 void UnloadGLNativeLibraries() { 132 CleanupNativeLibraries(NULL); 133 } 134 135 void SetGLGetProcAddressProc(GLGetProcAddressProc proc) { 136 DCHECK(proc); 137 g_get_proc_address = proc; 138 } 139 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 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