dispatch_common.c revision 82f995d3
1e52adb7bSmrg/* 2e52adb7bSmrg * Copyright © 2013-2014 Intel Corporation 3e52adb7bSmrg * 4e52adb7bSmrg * Permission is hereby granted, free of charge, to any person obtaining a 5e52adb7bSmrg * copy of this software and associated documentation files (the "Software"), 6e52adb7bSmrg * to deal in the Software without restriction, including without limitation 7e52adb7bSmrg * the rights to use, copy, modify, merge, publish, distribute, sublicense, 8e52adb7bSmrg * and/or sell copies of the Software, and to permit persons to whom the 9e52adb7bSmrg * Software is furnished to do so, subject to the following conditions: 10e52adb7bSmrg * 11e52adb7bSmrg * The above copyright notice and this permission notice (including the next 12e52adb7bSmrg * paragraph) shall be included in all copies or substantial portions of the 13e52adb7bSmrg * Software. 14e52adb7bSmrg * 15e52adb7bSmrg * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16e52adb7bSmrg * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17e52adb7bSmrg * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL 18e52adb7bSmrg * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19e52adb7bSmrg * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING 20e52adb7bSmrg * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS 21e52adb7bSmrg * IN THE SOFTWARE. 22e52adb7bSmrg */ 23e52adb7bSmrg 24e52adb7bSmrg/** 25e52adb7bSmrg * @file dispatch_common.c 26e52adb7bSmrg * 27e52adb7bSmrg * Implements common code shared by the generated GL/EGL/GLX dispatch code. 28e52adb7bSmrg * 29e52adb7bSmrg * A collection of some important specs on getting GL function pointers. 30e52adb7bSmrg * 31e52adb7bSmrg * From the linux GL ABI (http://www.opengl.org/registry/ABI/): 32e52adb7bSmrg * 33e52adb7bSmrg * "3.4. The libraries must export all OpenGL 1.2, GLU 1.3, GLX 1.3, and 34e52adb7bSmrg * ARB_multitexture entry points statically. 35e52adb7bSmrg * 36e52adb7bSmrg * 3.5. Because non-ARB extensions vary so widely and are constantly 37e52adb7bSmrg * increasing in number, it's infeasible to require that they all be 38e52adb7bSmrg * supported, and extensions can always be added to hardware drivers 39e52adb7bSmrg * after the base link libraries are released. These drivers are 40e52adb7bSmrg * dynamically loaded by libGL, so extensions not in the base 41e52adb7bSmrg * library must also be obtained dynamically. 42e52adb7bSmrg * 43e52adb7bSmrg * 3.6. To perform the dynamic query, libGL also must export an entry 44e52adb7bSmrg * point called 45e52adb7bSmrg * 46e52adb7bSmrg * void (*glXGetProcAddressARB(const GLubyte *))(); 47e52adb7bSmrg * 48e52adb7bSmrg * The full specification of this function is available separately. It 49e52adb7bSmrg * takes the string name of a GL or GLX entry point and returns a pointer 50e52adb7bSmrg * to a function implementing that entry point. It is functionally 51e52adb7bSmrg * identical to the wglGetProcAddress query defined by the Windows OpenGL 52e52adb7bSmrg * library, except that the function pointers returned are context 53e52adb7bSmrg * independent, unlike the WGL query." 54e52adb7bSmrg * 55e52adb7bSmrg * From the EGL 1.4 spec: 56e52adb7bSmrg * 57e52adb7bSmrg * "Client API function pointers returned by eglGetProcAddress are 58e52adb7bSmrg * independent of the display and the currently bound client API context, 59e52adb7bSmrg * and may be used by any client API context which supports the extension. 60e52adb7bSmrg * 61e52adb7bSmrg * eglGetProcAddress may be queried for all of the following functions: 62e52adb7bSmrg * 63e52adb7bSmrg * • All EGL and client API extension functions supported by the 64e52adb7bSmrg * implementation (whether those extensions are supported by the current 65e52adb7bSmrg * client API context or not). This includes any mandatory OpenGL ES 66e52adb7bSmrg * extensions. 67e52adb7bSmrg * 68e52adb7bSmrg * eglGetProcAddress may not be queried for core (non-extension) functions 69e52adb7bSmrg * in EGL or client APIs 20 . 70e52adb7bSmrg * 71e52adb7bSmrg * For functions that are queryable with eglGetProcAddress, 72e52adb7bSmrg * implementations may choose to also export those functions statically 73e52adb7bSmrg * from the object libraries im- plementing those functions. However, 74e52adb7bSmrg * portable clients cannot rely on this behavior. 75e52adb7bSmrg * 76e52adb7bSmrg * From the GLX 1.4 spec: 77e52adb7bSmrg * 78e52adb7bSmrg * "glXGetProcAddress may be queried for all of the following functions: 79e52adb7bSmrg * 80e52adb7bSmrg * • All GL and GLX extension functions supported by the implementation 81e52adb7bSmrg * (whether those extensions are supported by the current context or 82e52adb7bSmrg * not). 83e52adb7bSmrg * 84e52adb7bSmrg * • All core (non-extension) functions in GL and GLX from version 1.0 up 85e52adb7bSmrg * to and including the versions of those specifications supported by 86e52adb7bSmrg * the implementation, as determined by glGetString(GL VERSION) and 87e52adb7bSmrg * glXQueryVersion queries." 88e52adb7bSmrg */ 89e52adb7bSmrg 90e52adb7bSmrg#include <assert.h> 91e52adb7bSmrg#include <stdlib.h> 92e52adb7bSmrg#ifdef _WIN32 93e52adb7bSmrg#include <windows.h> 94e52adb7bSmrg#else 95e52adb7bSmrg#include <dlfcn.h> 96e52adb7bSmrg#include <err.h> 97e52adb7bSmrg#include <pthread.h> 98e52adb7bSmrg#endif 99e52adb7bSmrg#include <string.h> 100e52adb7bSmrg#include <ctype.h> 101e52adb7bSmrg#include <stdio.h> 102e52adb7bSmrg 103e52adb7bSmrg#include "dispatch_common.h" 104e52adb7bSmrg 105e52adb7bSmrg#ifdef __APPLE__ 106e52adb7bSmrg#define GLX_LIB "/opt/X11/lib/libGL.1.dylib" 107e52adb7bSmrg#elif defined(ANDROID) 108e52adb7bSmrg#define GLX_LIB "libGLESv2.so" 109e52adb7bSmrg#else 110b795ef6aSmrg#ifdef __NetBSD__ 111b795ef6aSmrg#define GLX_LIB "libGL.so" 112b795ef6aSmrg#else 113e52adb7bSmrg#define GLX_LIB "libGL.so.1" 114e52adb7bSmrg#endif 115b795ef6aSmrg#endif 116e52adb7bSmrg 117b795ef6aSmrg#if defined(ANDROID) || defined(__NetBSD__) 118e52adb7bSmrg#define EGL_LIB "libEGL.so" 119e52adb7bSmrg#define GLES1_LIB "libGLESv1_CM.so" 120e52adb7bSmrg#define GLES2_LIB "libGLESv2.so" 121e52adb7bSmrg#else 122e52adb7bSmrg#define EGL_LIB "libEGL.so.1" 123e52adb7bSmrg#define GLES1_LIB "libGLESv1_CM.so.1" 124e52adb7bSmrg#define GLES2_LIB "libGLESv2.so.2" 125e52adb7bSmrg#endif 126e52adb7bSmrg 127e52adb7bSmrg#ifdef __GNUC__ 128e52adb7bSmrg#define CONSTRUCT(_func) static void _func (void) __attribute__((constructor)); 129e52adb7bSmrg#define DESTRUCT(_func) static void _func (void) __attribute__((destructor)); 130e52adb7bSmrg#elif defined (_MSC_VER) && (_MSC_VER >= 1500) 131e52adb7bSmrg#define CONSTRUCT(_func) \ 132e52adb7bSmrg static void _func(void); \ 133e52adb7bSmrg static int _func ## _wrapper(void) { _func(); return 0; } \ 134e52adb7bSmrg __pragma(section(".CRT$XCU",read)) \ 135e52adb7bSmrg __declspec(allocate(".CRT$XCU")) static int (* _array ## _func)(void) = _func ## _wrapper; 136e52adb7bSmrg 137e52adb7bSmrg#define DESTRUCT(_func) \ 138e52adb7bSmrg static void _func(void); \ 139e52adb7bSmrg static int _func ## _constructor(void) { atexit (_func); return 0; } \ 140e52adb7bSmrg __pragma(section(".CRT$XCU",read)) \ 141e52adb7bSmrg __declspec(allocate(".CRT$XCU")) static int (* _array ## _func)(void) = _func ## _constructor; 142e52adb7bSmrg 14382f995d3Schristos#elif defined(__lint__) 14482f995d3Schristos#define CONSTRUCT(_func) 14582f995d3Schristos#define DESTRUCT(_func) 146e52adb7bSmrg#else 147e52adb7bSmrg#error "You will need constructor support for your compiler" 148e52adb7bSmrg#endif 149e52adb7bSmrg 150e52adb7bSmrgstruct api { 151e52adb7bSmrg#ifndef _WIN32 152e52adb7bSmrg /** 153e52adb7bSmrg * Locking for making sure we don't double-dlopen(). 154e52adb7bSmrg */ 155e52adb7bSmrg pthread_mutex_t mutex; 156e52adb7bSmrg#endif 157e52adb7bSmrg 158e52adb7bSmrg /** dlopen() return value for libGL.so.1. */ 159e52adb7bSmrg void *glx_handle; 160e52adb7bSmrg 161e52adb7bSmrg /** 162e52adb7bSmrg * dlopen() return value for OS X's GL library. 163e52adb7bSmrg * 164e52adb7bSmrg * On linux, glx_handle is used instead. 165e52adb7bSmrg */ 166e52adb7bSmrg void *gl_handle; 167e52adb7bSmrg 168e52adb7bSmrg /** dlopen() return value for libEGL.so.1 */ 169e52adb7bSmrg void *egl_handle; 170e52adb7bSmrg 171e52adb7bSmrg /** dlopen() return value for libGLESv1_CM.so.1 */ 172e52adb7bSmrg void *gles1_handle; 173e52adb7bSmrg 174e52adb7bSmrg /** dlopen() return value for libGLESv2.so.2 */ 175e52adb7bSmrg void *gles2_handle; 176e52adb7bSmrg 177e52adb7bSmrg /** 178e52adb7bSmrg * This value gets incremented when any thread is in 179e52adb7bSmrg * glBegin()/glEnd() called through epoxy. 180e52adb7bSmrg * 181e52adb7bSmrg * We're not guaranteed to be called through our wrapper, so the 182e52adb7bSmrg * conservative paths also try to handle the failure cases they'll 183e52adb7bSmrg * see if begin_count didn't reflect reality. It's also a bit of 184e52adb7bSmrg * a bug that the conservative paths might return success because 185e52adb7bSmrg * some other thread was in epoxy glBegin/glEnd while our thread 186e52adb7bSmrg * is trying to resolve, but given that it's basically just for 187e52adb7bSmrg * informative error messages, we shouldn't need to care. 188e52adb7bSmrg */ 189e52adb7bSmrg long begin_count; 190e52adb7bSmrg}; 191e52adb7bSmrg 192e52adb7bSmrgstatic struct api api = { 193e52adb7bSmrg#ifndef _WIN32 194e52adb7bSmrg .mutex = PTHREAD_MUTEX_INITIALIZER, 195e52adb7bSmrg#else 196e52adb7bSmrg 0, 197e52adb7bSmrg#endif 198e52adb7bSmrg}; 199e52adb7bSmrg 200e52adb7bSmrgstatic bool library_initialized; 201e52adb7bSmrg 202e52adb7bSmrgstatic bool epoxy_current_context_is_glx(void); 203e52adb7bSmrg 204e52adb7bSmrg#if PLATFORM_HAS_EGL 205e52adb7bSmrgstatic EGLenum 206e52adb7bSmrgepoxy_egl_get_current_gl_context_api(void); 207e52adb7bSmrg#endif 208e52adb7bSmrg 209e52adb7bSmrgCONSTRUCT (library_init) 210e52adb7bSmrg 211e52adb7bSmrgstatic void 212e52adb7bSmrglibrary_init(void) 213e52adb7bSmrg{ 214e52adb7bSmrg library_initialized = true; 215e52adb7bSmrg} 216e52adb7bSmrg 217e52adb7bSmrgstatic bool 218e52adb7bSmrgget_dlopen_handle(void **handle, const char *lib_name, bool exit_on_fail) 219e52adb7bSmrg{ 220e52adb7bSmrg if (*handle) 221e52adb7bSmrg return true; 222e52adb7bSmrg 223e52adb7bSmrg if (!library_initialized) { 224e52adb7bSmrg fprintf(stderr, 225e52adb7bSmrg "Attempting to dlopen() while in the dynamic linker.\n"); 226e52adb7bSmrg abort(); 227e52adb7bSmrg } 228e52adb7bSmrg 229e52adb7bSmrg#ifdef _WIN32 230e52adb7bSmrg *handle = LoadLibraryA(lib_name); 231e52adb7bSmrg#else 232e52adb7bSmrg pthread_mutex_lock(&api.mutex); 233e52adb7bSmrg if (!*handle) { 234e52adb7bSmrg *handle = dlopen(lib_name, RTLD_LAZY | RTLD_LOCAL); 235e52adb7bSmrg if (!*handle) { 236e52adb7bSmrg if (exit_on_fail) { 237e52adb7bSmrg fprintf(stderr, "Couldn't open %s: %s\n", lib_name, dlerror()); 238e52adb7bSmrg exit(1); 239e52adb7bSmrg } else { 240e52adb7bSmrg (void)dlerror(); 241e52adb7bSmrg } 242e52adb7bSmrg } 243e52adb7bSmrg } 244e52adb7bSmrg pthread_mutex_unlock(&api.mutex); 245e52adb7bSmrg#endif 246e52adb7bSmrg 247e52adb7bSmrg return *handle != NULL; 248e52adb7bSmrg} 249e52adb7bSmrg 250e52adb7bSmrgstatic void * 251e52adb7bSmrgdo_dlsym(void **handle, const char *lib_name, const char *name, 252e52adb7bSmrg bool exit_on_fail) 253e52adb7bSmrg{ 254e52adb7bSmrg void *result; 255e52adb7bSmrg const char *error = ""; 256e52adb7bSmrg 257e52adb7bSmrg if (!get_dlopen_handle(handle, lib_name, exit_on_fail)) 258e52adb7bSmrg return NULL; 259e52adb7bSmrg 260e52adb7bSmrg#ifdef _WIN32 261e52adb7bSmrg result = GetProcAddress(*handle, name); 262e52adb7bSmrg#else 263e52adb7bSmrg result = dlsym(*handle, name); 264e52adb7bSmrg if (!result) 265e52adb7bSmrg error = dlerror(); 266e52adb7bSmrg#endif 267e52adb7bSmrg if (!result && exit_on_fail) { 268e52adb7bSmrg fprintf(stderr,"%s() not found in %s: %s\n", name, lib_name, error); 269e52adb7bSmrg exit(1); 270e52adb7bSmrg } 271e52adb7bSmrg 272e52adb7bSmrg return result; 273e52adb7bSmrg} 274e52adb7bSmrg 275e52adb7bSmrgPUBLIC bool 276e52adb7bSmrgepoxy_is_desktop_gl(void) 277e52adb7bSmrg{ 278e52adb7bSmrg const char *es_prefix = "OpenGL ES"; 279e52adb7bSmrg const char *version; 280e52adb7bSmrg 281e52adb7bSmrg#if PLATFORM_HAS_EGL 282e52adb7bSmrg /* PowerVR's OpenGL ES implementation (and perhaps other) don't 283e52adb7bSmrg * comply with the standard, which states that 284e52adb7bSmrg * "glGetString(GL_VERSION)" should return a string starting with 285e52adb7bSmrg * "OpenGL ES". Therefore, to distinguish desktop OpenGL from 286e52adb7bSmrg * OpenGL ES, we must also check the context type through EGL (we 287e52adb7bSmrg * can do that as PowerVR is only usable through EGL). 288e52adb7bSmrg */ 289e52adb7bSmrg if (!epoxy_current_context_is_glx()) { 290e52adb7bSmrg switch (epoxy_egl_get_current_gl_context_api()) { 291e52adb7bSmrg case EGL_OPENGL_API: return true; 292e52adb7bSmrg case EGL_OPENGL_ES_API: return false; 293e52adb7bSmrg case EGL_NONE: 294e52adb7bSmrg default: break; 295e52adb7bSmrg } 296e52adb7bSmrg } 297e52adb7bSmrg#endif 298e52adb7bSmrg 299e52adb7bSmrg if (api.begin_count) 300e52adb7bSmrg return true; 301e52adb7bSmrg 302e52adb7bSmrg version = (const char *)glGetString(GL_VERSION); 303e52adb7bSmrg 304e52adb7bSmrg /* If we didn't get a version back, there are only two things that 305e52adb7bSmrg * could have happened: either malloc failure (which basically 306e52adb7bSmrg * doesn't exist), or we were called within a glBegin()/glEnd(). 307e52adb7bSmrg * Assume the second, which only exists for desktop GL. 308e52adb7bSmrg */ 309e52adb7bSmrg if (!version) 310e52adb7bSmrg return true; 311e52adb7bSmrg 312e52adb7bSmrg return strncmp(es_prefix, version, strlen(es_prefix)); 313e52adb7bSmrg} 314e52adb7bSmrg 315e52adb7bSmrgstatic int 316e52adb7bSmrgepoxy_internal_gl_version(int error_version) 317e52adb7bSmrg{ 318e52adb7bSmrg const char *version = (const char *)glGetString(GL_VERSION); 319e52adb7bSmrg GLint major, minor; 320e52adb7bSmrg int scanf_count; 321e52adb7bSmrg 322e52adb7bSmrg if (!version) 323e52adb7bSmrg return error_version; 324e52adb7bSmrg 325e52adb7bSmrg /* skip to version number */ 326e52adb7bSmrg while (!isdigit(*version) && *version != '\0') 327e52adb7bSmrg version++; 328e52adb7bSmrg 329e52adb7bSmrg /* Interpret version number */ 330e52adb7bSmrg scanf_count = sscanf(version, "%i.%i", &major, &minor); 331e52adb7bSmrg if (scanf_count != 2) { 332e52adb7bSmrg fprintf(stderr, "Unable to interpret GL_VERSION string: %s\n", 333e52adb7bSmrg version); 334e52adb7bSmrg exit(1); 335e52adb7bSmrg } 336e52adb7bSmrg return 10 * major + minor; 337e52adb7bSmrg} 338e52adb7bSmrg 339e52adb7bSmrgPUBLIC int 340e52adb7bSmrgepoxy_gl_version(void) 341e52adb7bSmrg{ 342e52adb7bSmrg return epoxy_internal_gl_version(0); 343e52adb7bSmrg} 344e52adb7bSmrg 345e52adb7bSmrgint 346e52adb7bSmrgepoxy_conservative_gl_version(void) 347e52adb7bSmrg{ 348e52adb7bSmrg if (api.begin_count) 349e52adb7bSmrg return 100; 350e52adb7bSmrg 351e52adb7bSmrg return epoxy_internal_gl_version(100); 352e52adb7bSmrg} 353e52adb7bSmrg 354e52adb7bSmrgbool 355e52adb7bSmrgepoxy_extension_in_string(const char *extension_list, const char *ext) 356e52adb7bSmrg{ 357e52adb7bSmrg const char *ptr = extension_list; 358e52adb7bSmrg int len = strlen(ext); 359e52adb7bSmrg 360e52adb7bSmrg /* Make sure that don't just find an extension with our name as a prefix. */ 361e52adb7bSmrg while (true) { 362e52adb7bSmrg ptr = strstr(ptr, ext); 363e52adb7bSmrg if (!ptr) 364e52adb7bSmrg return false; 365e52adb7bSmrg 366e52adb7bSmrg if (ptr[len] == ' ' || ptr[len] == 0) 367e52adb7bSmrg return true; 368e52adb7bSmrg ptr += len; 369e52adb7bSmrg } 370e52adb7bSmrg} 371e52adb7bSmrg 372e52adb7bSmrgstatic bool 373e52adb7bSmrgepoxy_internal_has_gl_extension(const char *ext, bool invalid_op_mode) 374e52adb7bSmrg{ 375e52adb7bSmrg if (epoxy_gl_version() < 30) { 376e52adb7bSmrg const char *exts = (const char *)glGetString(GL_EXTENSIONS); 377e52adb7bSmrg if (!exts) 378e52adb7bSmrg return invalid_op_mode; 379e52adb7bSmrg return epoxy_extension_in_string(exts, ext); 380e52adb7bSmrg } else { 381e52adb7bSmrg int num_extensions; 382e52adb7bSmrg int i; 383e52adb7bSmrg 384e52adb7bSmrg glGetIntegerv(GL_NUM_EXTENSIONS, &num_extensions); 385e52adb7bSmrg if (num_extensions == 0) 386e52adb7bSmrg return invalid_op_mode; 387e52adb7bSmrg 388e52adb7bSmrg for (i = 0; i < num_extensions; i++) { 389e52adb7bSmrg const char *gl_ext = (const char *)glGetStringi(GL_EXTENSIONS, i); 390e52adb7bSmrg if (strcmp(ext, gl_ext) == 0) 391e52adb7bSmrg return true; 392e52adb7bSmrg } 393e52adb7bSmrg 394e52adb7bSmrg return false; 395e52adb7bSmrg } 396e52adb7bSmrg} 397e52adb7bSmrg 398e52adb7bSmrg/** 399e52adb7bSmrg * Tests whether the currently bound context is EGL or GLX, trying to 400e52adb7bSmrg * avoid loading libraries unless necessary. 401e52adb7bSmrg */ 402e52adb7bSmrgstatic bool 403e52adb7bSmrgepoxy_current_context_is_glx(void) 404e52adb7bSmrg{ 405e52adb7bSmrg#if !PLATFORM_HAS_GLX 406e52adb7bSmrg return false; 407e52adb7bSmrg#else 408e52adb7bSmrg /* If the application hasn't explicitly called some of our GLX 409e52adb7bSmrg * or EGL code but has presumably set up a context on its own, 410e52adb7bSmrg * then we need to figure out how to getprocaddress anyway. 411e52adb7bSmrg * 412e52adb7bSmrg * If there's a public GetProcAddress loaded in the 413e52adb7bSmrg * application's namespace, then use that. 414e52adb7bSmrg */ 415e52adb7bSmrg void *sym; 416e52adb7bSmrg 417e52adb7bSmrg sym = dlsym(NULL, "glXGetCurrentContext"); 418e52adb7bSmrg if (sym) { 419e52adb7bSmrg if (glXGetCurrentContext()) 420e52adb7bSmrg return true; 421e52adb7bSmrg } else { 422e52adb7bSmrg (void)dlerror(); 423e52adb7bSmrg } 424e52adb7bSmrg 425e52adb7bSmrg#if PLATFORM_HAS_EGL 426e52adb7bSmrg sym = dlsym(NULL, "eglGetCurrentContext"); 427e52adb7bSmrg if (sym) { 428e52adb7bSmrg if (epoxy_egl_get_current_gl_context_api() != EGL_NONE) 429e52adb7bSmrg return false; 430e52adb7bSmrg } else { 431e52adb7bSmrg (void)dlerror(); 432e52adb7bSmrg } 433e52adb7bSmrg#endif /* PLATFORM_HAS_EGL */ 434e52adb7bSmrg 435e52adb7bSmrg /* OK, couldn't find anything in the app's address space. 436e52adb7bSmrg * Presumably they dlopened with RTLD_LOCAL, which hides it 437e52adb7bSmrg * from us. Just go dlopen()ing likely libraries and try them. 438e52adb7bSmrg */ 439e52adb7bSmrg sym = do_dlsym(&api.glx_handle, GLX_LIB, "glXGetCurrentContext", false); 440e52adb7bSmrg if (sym && glXGetCurrentContext()) 441e52adb7bSmrg return true; 442e52adb7bSmrg 443e52adb7bSmrg#if PLATFORM_HAS_EGL 444e52adb7bSmrg sym = do_dlsym(&api.egl_handle, EGL_LIB, "eglGetCurrentContext", 445e52adb7bSmrg false); 446e52adb7bSmrg if (sym && epoxy_egl_get_current_gl_context_api() != EGL_NONE) 447e52adb7bSmrg return false; 448e52adb7bSmrg#endif /* PLATFORM_HAS_EGL */ 449e52adb7bSmrg 450e52adb7bSmrg return false; 451e52adb7bSmrg#endif /* PLATFORM_HAS_GLX */ 452e52adb7bSmrg} 453e52adb7bSmrg 454e52adb7bSmrg/** 455e52adb7bSmrg * Returns true if the given GL extension is supported in the current context. 456e52adb7bSmrg * 457e52adb7bSmrg * Note that this function can't be called from within glBegin()/glEnd(). 458e52adb7bSmrg * 459e52adb7bSmrg * \sa epoxy_has_egl_extension() 460e52adb7bSmrg * \sa epoxy_has_glx_extension() 461e52adb7bSmrg */ 462e52adb7bSmrgPUBLIC bool 463e52adb7bSmrgepoxy_has_gl_extension(const char *ext) 464e52adb7bSmrg{ 465e52adb7bSmrg return epoxy_internal_has_gl_extension(ext, false); 466e52adb7bSmrg} 467e52adb7bSmrg 468e52adb7bSmrgbool 469e52adb7bSmrgepoxy_conservative_has_gl_extension(const char *ext) 470e52adb7bSmrg{ 471e52adb7bSmrg if (api.begin_count) 472e52adb7bSmrg return true; 473e52adb7bSmrg 474e52adb7bSmrg return epoxy_internal_has_gl_extension(ext, true); 475e52adb7bSmrg} 476e52adb7bSmrg 477e52adb7bSmrgvoid * 478e52adb7bSmrgepoxy_egl_dlsym(const char *name) 479e52adb7bSmrg{ 480e52adb7bSmrg return do_dlsym(&api.egl_handle, EGL_LIB, name, true); 481e52adb7bSmrg} 482e52adb7bSmrg 483e52adb7bSmrgvoid * 484e52adb7bSmrgepoxy_glx_dlsym(const char *name) 485e52adb7bSmrg{ 486e52adb7bSmrg return do_dlsym(&api.glx_handle, GLX_LIB, name, true); 487e52adb7bSmrg} 488e52adb7bSmrg 489e52adb7bSmrgvoid * 490e52adb7bSmrgepoxy_gl_dlsym(const char *name) 491e52adb7bSmrg{ 492e52adb7bSmrg#ifdef _WIN32 493e52adb7bSmrg return do_dlsym(&api.gl_handle, "OPENGL32", name, true); 494e52adb7bSmrg#elif defined(__APPLE__) 495e52adb7bSmrg return do_dlsym(&api.gl_handle, 496e52adb7bSmrg "/System/Library/Frameworks/OpenGL.framework/Versions/Current/OpenGL", 497e52adb7bSmrg name, true); 498e52adb7bSmrg#else 499e52adb7bSmrg /* There's no library for desktop GL support independent of GLX. */ 500e52adb7bSmrg return epoxy_glx_dlsym(name); 501e52adb7bSmrg#endif 502e52adb7bSmrg} 503e52adb7bSmrg 504e52adb7bSmrgvoid * 505e52adb7bSmrgepoxy_gles1_dlsym(const char *name) 506e52adb7bSmrg{ 507e52adb7bSmrg if (epoxy_current_context_is_glx()) { 508e52adb7bSmrg return epoxy_get_proc_address(name); 509e52adb7bSmrg } else { 510e52adb7bSmrg return do_dlsym(&api.gles1_handle, GLES1_LIB, name, true); 511e52adb7bSmrg } 512e52adb7bSmrg} 513e52adb7bSmrg 514e52adb7bSmrgvoid * 515e52adb7bSmrgepoxy_gles2_dlsym(const char *name) 516e52adb7bSmrg{ 517e52adb7bSmrg if (epoxy_current_context_is_glx()) { 518e52adb7bSmrg return epoxy_get_proc_address(name); 519e52adb7bSmrg } else { 520e52adb7bSmrg return do_dlsym(&api.gles2_handle, GLES2_LIB, name, true); 521e52adb7bSmrg } 522e52adb7bSmrg} 523e52adb7bSmrg 524e52adb7bSmrg/** 525e52adb7bSmrg * Does the appropriate dlsym() or eglGetProcAddress() for GLES3 526e52adb7bSmrg * functions. 527e52adb7bSmrg * 528e52adb7bSmrg * Mesa interpreted GLES as intending that the GLES3 functions were 529e52adb7bSmrg * available only through eglGetProcAddress() and not dlsym(), while 530e52adb7bSmrg * ARM's Mali drivers interpreted GLES as intending that GLES3 531e52adb7bSmrg * functions were available only through dlsym() and not 532e52adb7bSmrg * eglGetProcAddress(). Thanks, Khronos. 533e52adb7bSmrg */ 534e52adb7bSmrgvoid * 535e52adb7bSmrgepoxy_gles3_dlsym(const char *name) 536e52adb7bSmrg{ 537e52adb7bSmrg if (epoxy_current_context_is_glx()) { 538e52adb7bSmrg return epoxy_get_proc_address(name); 539e52adb7bSmrg } else { 540e52adb7bSmrg void *func = do_dlsym(&api.gles2_handle, GLES2_LIB, name, false); 541e52adb7bSmrg 542e52adb7bSmrg if (func) 543e52adb7bSmrg return func; 544e52adb7bSmrg 545e52adb7bSmrg return epoxy_get_proc_address(name); 546e52adb7bSmrg } 547e52adb7bSmrg} 548e52adb7bSmrg 549e52adb7bSmrg/** 550e52adb7bSmrg * Performs either the dlsym or glXGetProcAddress()-equivalent for 551e52adb7bSmrg * core functions in desktop GL. 552e52adb7bSmrg */ 553e52adb7bSmrgvoid * 554e52adb7bSmrgepoxy_get_core_proc_address(const char *name, int core_version) 555e52adb7bSmrg{ 556e52adb7bSmrg#ifdef _WIN32 557e52adb7bSmrg int core_symbol_support = 11; 558e52adb7bSmrg#elif defined(ANDROID) 559e52adb7bSmrg /** 560e52adb7bSmrg * All symbols must be resolved through eglGetProcAddress 561e52adb7bSmrg * on Android 562e52adb7bSmrg */ 563e52adb7bSmrg int core_symbol_support = 0; 564e52adb7bSmrg#else 565e52adb7bSmrg int core_symbol_support = 12; 566e52adb7bSmrg#endif 567e52adb7bSmrg 568e52adb7bSmrg if (core_version <= core_symbol_support) { 569e52adb7bSmrg return epoxy_gl_dlsym(name); 570e52adb7bSmrg } else { 571e52adb7bSmrg return epoxy_get_proc_address(name); 572e52adb7bSmrg } 573e52adb7bSmrg} 574e52adb7bSmrg 575e52adb7bSmrg#if PLATFORM_HAS_EGL 576e52adb7bSmrgstatic EGLenum 577e52adb7bSmrgepoxy_egl_get_current_gl_context_api(void) 578e52adb7bSmrg{ 579e52adb7bSmrg EGLenum save_api = eglQueryAPI(); 580e52adb7bSmrg EGLContext ctx; 581e52adb7bSmrg 582e52adb7bSmrg if (eglBindAPI(EGL_OPENGL_API)) { 583e52adb7bSmrg ctx = eglGetCurrentContext(); 584e52adb7bSmrg if (ctx) { 585e52adb7bSmrg eglBindAPI(save_api); 586e52adb7bSmrg return EGL_OPENGL_API; 587e52adb7bSmrg } 588e52adb7bSmrg } else { 589e52adb7bSmrg (void)eglGetError(); 590e52adb7bSmrg } 591e52adb7bSmrg 592e52adb7bSmrg if (eglBindAPI(EGL_OPENGL_ES_API)) { 593e52adb7bSmrg ctx = eglGetCurrentContext(); 594e52adb7bSmrg eglBindAPI(save_api); 595e52adb7bSmrg if (ctx) { 596e52adb7bSmrg eglBindAPI(save_api); 597e52adb7bSmrg return EGL_OPENGL_ES_API; 598e52adb7bSmrg } 599e52adb7bSmrg } else { 600e52adb7bSmrg (void)eglGetError(); 601e52adb7bSmrg } 602e52adb7bSmrg 603e52adb7bSmrg return EGL_NONE; 604e52adb7bSmrg} 605e52adb7bSmrg#endif /* PLATFORM_HAS_EGL */ 606e52adb7bSmrg 607e52adb7bSmrg/** 608e52adb7bSmrg * Performs the dlsym() for the core GL 1.0 functions that we use for 609e52adb7bSmrg * determining version and extension support for deciding on dlsym 610e52adb7bSmrg * versus glXGetProcAddress() for all other functions. 611e52adb7bSmrg * 612e52adb7bSmrg * This needs to succeed on implementations without GLX (since 613e52adb7bSmrg * glGetString() and glGetIntegerv() are both in GLES1/2 as well, and 614e52adb7bSmrg * at call time we don't know for sure what API they're trying to use 615e52adb7bSmrg * without inspecting contexts ourselves). 616e52adb7bSmrg */ 617e52adb7bSmrgvoid * 618e52adb7bSmrgepoxy_get_bootstrap_proc_address(const char *name) 619e52adb7bSmrg{ 620e52adb7bSmrg /* If we already have a library that links to libglapi loaded, 621e52adb7bSmrg * use that. 622e52adb7bSmrg */ 623e52adb7bSmrg#if PLATFORM_HAS_GLX 624e52adb7bSmrg if (api.glx_handle && glXGetCurrentContext()) 625e52adb7bSmrg return epoxy_gl_dlsym(name); 626e52adb7bSmrg#endif 627e52adb7bSmrg 628e52adb7bSmrg /* If epoxy hasn't loaded any API-specific library yet, try to 629e52adb7bSmrg * figure out what API the context is using and use that library, 630e52adb7bSmrg * since future calls will also use that API (this prevents a 631e52adb7bSmrg * non-X11 ES2 context from loading a bunch of X11 junk). 632e52adb7bSmrg */ 633e52adb7bSmrg#if PLATFORM_HAS_EGL 634e52adb7bSmrg get_dlopen_handle(&api.egl_handle, EGL_LIB, false); 635e52adb7bSmrg if (api.egl_handle) { 636e52adb7bSmrg switch (epoxy_egl_get_current_gl_context_api()) { 637e52adb7bSmrg case EGL_OPENGL_API: 638e52adb7bSmrg return epoxy_gl_dlsym(name); 639e52adb7bSmrg case EGL_OPENGL_ES_API: 640e52adb7bSmrg /* We can't resolve the GL version, because 641e52adb7bSmrg * epoxy_glGetString() is one of the two things calling 642e52adb7bSmrg * us. Try the GLES2 implementation first, and fall back 643e52adb7bSmrg * to GLES1 otherwise. 644e52adb7bSmrg */ 645e52adb7bSmrg get_dlopen_handle(&api.gles2_handle, GLES2_LIB, false); 646e52adb7bSmrg if (api.gles2_handle) 647e52adb7bSmrg return epoxy_gles2_dlsym(name); 648e52adb7bSmrg else 649e52adb7bSmrg return epoxy_gles1_dlsym(name); 650e52adb7bSmrg } 651e52adb7bSmrg } 652e52adb7bSmrg#endif /* PLATFORM_HAS_EGL */ 653e52adb7bSmrg 654e52adb7bSmrg /* Fall back to GLX */ 655e52adb7bSmrg return epoxy_gl_dlsym(name); 656e52adb7bSmrg} 657e52adb7bSmrg 658e52adb7bSmrgvoid * 659e52adb7bSmrgepoxy_get_proc_address(const char *name) 660e52adb7bSmrg{ 661e52adb7bSmrg#ifdef _WIN32 662e52adb7bSmrg return wglGetProcAddress(name); 663e52adb7bSmrg#elif defined(__APPLE__) 664e52adb7bSmrg return epoxy_gl_dlsym(name); 665e52adb7bSmrg#else 666e52adb7bSmrg if (epoxy_current_context_is_glx()) { 667e52adb7bSmrg return glXGetProcAddressARB((const GLubyte *)name); 668e52adb7bSmrg } else { 669e52adb7bSmrg#if PLATFORM_HAS_EGL 670e52adb7bSmrg GLenum egl_api = epoxy_egl_get_current_gl_context_api(); 671e52adb7bSmrg 672e52adb7bSmrg switch (egl_api) { 673e52adb7bSmrg case EGL_OPENGL_API: 674e52adb7bSmrg case EGL_OPENGL_ES_API: 675e52adb7bSmrg return eglGetProcAddress(name); 676e52adb7bSmrg case EGL_NONE: 677e52adb7bSmrg break; 678e52adb7bSmrg } 679e52adb7bSmrg#endif 680e52adb7bSmrg } 681e52adb7bSmrg errx(1, "Couldn't find current GLX or EGL context.\n"); 682e52adb7bSmrg#endif 683e52adb7bSmrg} 684e52adb7bSmrg 685e52adb7bSmrgWRAPPER_VISIBILITY (void) 686e52adb7bSmrgWRAPPER(epoxy_glBegin)(GLenum primtype) 687e52adb7bSmrg{ 688e52adb7bSmrg#ifdef _WIN32 689e52adb7bSmrg InterlockedIncrement(&api.begin_count); 690e52adb7bSmrg#else 691e52adb7bSmrg pthread_mutex_lock(&api.mutex); 692e52adb7bSmrg api.begin_count++; 693e52adb7bSmrg pthread_mutex_unlock(&api.mutex); 694e52adb7bSmrg#endif 695e52adb7bSmrg 696e52adb7bSmrg epoxy_glBegin_unwrapped(primtype); 697e52adb7bSmrg} 698e52adb7bSmrg 699e52adb7bSmrgWRAPPER_VISIBILITY (void) 700e52adb7bSmrgWRAPPER(epoxy_glEnd)(void) 701e52adb7bSmrg{ 702e52adb7bSmrg epoxy_glEnd_unwrapped(); 703e52adb7bSmrg 704e52adb7bSmrg#ifdef _WIN32 705e52adb7bSmrg InterlockedDecrement(&api.begin_count); 706e52adb7bSmrg#else 707e52adb7bSmrg pthread_mutex_lock(&api.mutex); 708e52adb7bSmrg api.begin_count--; 709e52adb7bSmrg pthread_mutex_unlock(&api.mutex); 710e52adb7bSmrg#endif 711e52adb7bSmrg} 712e52adb7bSmrg 713e52adb7bSmrgPUBLIC PFNGLBEGINPROC epoxy_glBegin = epoxy_glBegin_wrapped; 714e52adb7bSmrgPUBLIC PFNGLENDPROC epoxy_glEnd = epoxy_glEnd_wrapped; 715