Quelle dispatch_common.c
Sprache: C
/*
* Copyright © 2013 - 2014 Intel Corporation
*
* Permission is hereby granted , free of charge , to any person obtaining a
* copy of this software and associated documentation files ( the " Software " ) ,
* to deal in the Software without restriction , including without limitation
* the rights to use , copy , modify , merge , publish , distribute , sublicense ,
* and / or sell copies of the Software , and to permit persons to whom the
* Software is furnished to do so , subject to the following conditions :
*
* The above copyright notice and this permission notice ( including the next
* paragraph ) shall be included in all copies or substantial portions of the
* Software .
*
* THE SOFTWARE IS PROVIDED " AS IS " , WITHOUT WARRANTY OF ANY KIND , EXPRESS OR
* IMPLIED , INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY ,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT . IN NO EVENT SHALL
* THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM , DAMAGES OR OTHER
* LIABILITY , WHETHER IN AN ACTION OF CONTRACT , TORT OR OTHERWISE , ARISING
* FROM , OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
* IN THE SOFTWARE .
*/
/**
* \ mainpage Epoxy
*
* \ section intro_sec Introduction
*
* Epoxy is a library for handling OpenGL function pointer management for
* you .
*
* It hides the complexity of ` dlopen ( ) ` , ` dlsym ( ) ` , ` glXGetProcAddress ( ) ` ,
* ` eglGetProcAddress ( ) ` , etc . from the app developer , with very little
* knowledge needed on their part . They get to read GL specs and write
* code using undecorated function names like ` glCompileShader ( ) ` .
*
* Don ' t forget to check for your extensions or versions being present
* before you use them , just like before ! We ' ll tell you what you forgot
* to check for instead of just segfaulting , though .
*
* \ section features_sec Features
*
* - Automatically initializes as new GL functions are used .
* - GL 4 . 6 core and compatibility context support .
* - GLES 1 / 2 / 3 context support .
* - Knows about function aliases so ( e . g . ) ` glBufferData ( ) ` can be
* used with ` GL_ARB_vertex_buffer_object ` implementations , along
* with GL 1 . 5 + implementations .
* - EGL , GLX , and WGL support .
* - Can be mixed with non - epoxy GL usage .
*
* \ section using_sec Using Epoxy
*
* Using Epoxy should be as easy as replacing :
*
* ` ` ` cpp
* # include < GL / gl . h >
* # include < GL / glx . h >
* # include < GL / glext . h >
* ` ` `
*
* with :
*
* ` ` ` cpp
* # include < epoxy / gl . h >
* # include < epoxy / glx . h >
* ` ` `
*
* \ subsection using_include_sec Headers
*
* Epoxy comes with the following public headers :
*
* - ` epoxy / gl . h ` - For GL API
* - ` epoxy / egl . h ` - For EGL API
* - ` epoxy / glx . h ` - For GLX API
* - ` epoxy / wgl . h ` - For WGL API
*
* \ section links_sec Additional links
*
* The latest version of the Epoxy code is available on [ GitHub ] ( https : //github.com/anholt/libepoxy).
*
* For bug reports and enhancements , please use the [ Issues ] ( https : //github.com/anholt/libepoxy/issues)
* link .
*
* The scope of this API reference does not include the documentation for
* OpenGL and OpenGL ES . For more information on those programming interfaces
* please visit :
*
* - [ Khronos ] ( https : //www.khronos.org/)
* - [ OpenGL page on Khronos . org ] ( https : //www.khronos.org/opengl/)
* - [ OpenGL ES page on Khronos . org ] ( https : //www.khronos.org/opengles/)
* - [ docs . GL ] ( http : //docs.gl/)
*/
/**
* @ file dispatch_common . c
*
* @ brief Implements common code shared by the generated GL / EGL / GLX dispatch code .
*
* A collection of some important specs on getting GL function pointers .
*
* From the linux GL ABI ( http : //www.opengl.org/registry/ABI/):
*
* " 3 . 4 . The libraries must export all OpenGL 1 . 2 , GLU 1 . 3 , GLX 1 . 3 , and
* ARB_multitexture entry points statically .
*
* 3 . 5 . Because non - ARB extensions vary so widely and are constantly
* increasing in number , it ' s infeasible to require that they all be
* supported , and extensions can always be added to hardware drivers
* after the base link libraries are released . These drivers are
* dynamically loaded by libGL , so extensions not in the base
* library must also be obtained dynamically .
*
* 3 . 6 . To perform the dynamic query , libGL also must export an entry
* point called
*
* void ( * glXGetProcAddressARB ( const GLubyte * ) ) ( ) ;
*
* The full specification of this function is available separately . It
* takes the string name of a GL or GLX entry point and returns a pointer
* to a function implementing that entry point . It is functionally
* identical to the wglGetProcAddress query defined by the Windows OpenGL
* library , except that the function pointers returned are context
* independent , unlike the WGL query . "
*
* From the EGL 1 . 4 spec :
*
* " Client API function pointers returned by eglGetProcAddress are
* independent of the display and the currently bound client API context ,
* and may be used by any client API context which supports the extension .
*
* eglGetProcAddress may be queried for all of the following functions :
*
* • All EGL and client API extension functions supported by the
* implementation ( whether those extensions are supported by the current
* client API context or not ) . This includes any mandatory OpenGL ES
* extensions .
*
* eglGetProcAddress may not be queried for core ( non - extension ) functions
* in EGL or client APIs 20 .
*
* For functions that are queryable with eglGetProcAddress ,
* implementations may choose to also export those functions statically
* from the object libraries im - plementing those functions . However ,
* portable clients cannot rely on this behavior .
*
* From the GLX 1 . 4 spec :
*
* " glXGetProcAddress may be queried for all of the following functions :
*
* • All GL and GLX extension functions supported by the implementation
* ( whether those extensions are supported by the current context or
* not ) .
*
* • All core ( non - extension ) functions in GL and GLX from version 1 . 0 up
* to and including the versions of those specifications supported by
* the implementation , as determined by glGetString ( GL VERSION ) and
* glXQueryVersion queries . "
*/
#include <assert.h>
#include <stdlib.h>
#ifdef _WIN32
#include <windows.h>
#else
#include <dlfcn.h>
#include <err.h>
#include <pthread.h>
#endif
#include <string.h>
#include <ctype.h>
#include <stdio.h>
#include "dispatch_common.h"
#if defined (__APPLE__)
#define GLX_LIB
"/opt/X11/lib/libGL.1.dylib"
#define EGL_LIB
"libEGL.dylib"
#define OPENGL_LIB
"/System/Library/Frameworks/OpenGL.framework/Versions/Current/OpenGL"
#define GLES1_LIB
"libGLESv1_CM.dylib"
#define GLES2_LIB
"libGLESv2.dylib"
#elif defined (__ANDROID__)
#define GLX_LIB
"libGLESv2.so"
#define EGL_LIB
"libEGL.so"
#define GLES1_LIB
"libGLESv1_CM.so"
#define GLES2_LIB
"libGLESv2.so"
#elif defined (_WIN32)
#define EGL_LIB
"libEGL.dll"
#define GLES1_LIB
"libGLES_CM.dll"
#define GLES2_LIB
"libGLESv2.dll"
#define OPENGL_LIB
"OPENGL32"
#else
#define GLVND_GLX_LIB
"libGLX.so.1"
#define GLX_LIB
"libGL.so.1"
#define EGL_LIB
"libEGL.so.1"
#define GLES1_LIB
"libGLESv1_CM.so.1"
#define GLES2_LIB
"libGLESv2.so.2"
#define OPENGL_LIB
"libOpenGL.so.0"
#endif
#ifdef __GNUC__
#define CONSTRUCT(_func)
static void _func (
void ) __attribute__((constructor));
#define DESTRUCT(_func)
static void _func (
void ) __attribute__((destructor));
#elif defined (_MSC_VER) && (_MSC_VER >=
1500 )
#define CONSTRUCT(_func) \
static void _func(
void ); \
static int _func
## _wrapper(
void ) { _func();
return 0 ; } \
__pragma(section(
".CRT$XCU" ,read)) \
__declspec(allocate(
".CRT$XCU" ))
static int (* _array
## _func)(
void ) = _func
## _wrapper;
#define DESTRUCT(_func) \
static void _func(
void ); \
static int _func
## _constructor(
void ) { atexit (_func);
return 0 ; } \
__pragma(section(
".CRT$XCU" ,read)) \
__declspec(allocate(
".CRT$XCU" ))
static int (* _array
## _func)(
void ) = _func
## _construc
tor;
#else
#error "You will need constructor support for your compiler"
#endif
struct api {
#ifndef _WIN32
/*
* Locking for making sure we don ' t double - dlopen ( ) .
*/
pthread_mutex_t mutex;
#endif
/*
* dlopen ( ) return value for the GLX API . This is libGLX . so . 1 if the
* runtime is glvnd - enabled , else libGL . so . 1
*/
void *glx_handle;
/*
* dlopen ( ) return value for the desktop GL library .
*
* On Windows this is OPENGL32 . On OSX this is classic libGL . On Linux
* this is either libOpenGL ( if the runtime is glvnd - enabled ) or
* classic libGL . so . 1
*/
void *gl_handle;
/* dlopen() return value for libEGL.so.1 */
void *egl_handle;
/* dlopen() return value for libGLESv1_CM.so.1 */
void *gles1_handle;
/* dlopen() return value for libGLESv2.so.2 */
void *gles2_handle;
/*
* This value gets incremented when any thread is in
* glBegin ( ) / glEnd ( ) called through epoxy .
*
* We ' re not guaranteed to be called through our wrapper , so the
* conservative paths also try to handle the failure cases they ' ll
* see if begin_count didn ' t reflect reality . It ' s also a bit of
* a bug that the conservative paths might return success because
* some other thread was in epoxy glBegin / glEnd while our thread
* is trying to resolve , but given that it ' s basically just for
* informative error messages , we shouldn ' t need to care .
*/
long begin_count;
};
static struct api api = {
#ifndef _WIN32
.mutex = PTHREAD_MUTEX_INITIALIZER,
#else
0 ,
#endif
};
static bool library_initialized;
static bool epoxy_current_context_is_glx(void );
#if PLATFORM_HAS_EGL
static EGLenum
epoxy_egl_get_current_gl_context_api(void );
#endif
CONSTRUCT (library_init)
static void
library_init(void )
{
library_initialized = true ;
}
static bool
get_dlopen_handle(void **handle, const char *lib_name, bool exit_on_fail, bool load)
{
if (*handle)
return true ;
if (!library_initialized) {
fputs("Attempting to dlopen() while in the dynamic linker.\n" , stderr);
abort();
}
#ifdef _WIN32
*handle = LoadLibraryA(lib_name);
#else
pthread_mutex_lock(&api.mutex);
if (!*handle) {
int flags = RTLD_LAZY | RTLD_LOCAL;
if (!load)
flags |= RTLD_NOLOAD;
*handle = dlopen(lib_name, flags);
if (!*handle) {
if (exit_on_fail) {
fprintf(stderr, "Couldn't open %s: %s\n" , lib_name, dlerror());
abort();
} else {
(void )dlerror();
}
}
}
pthread_mutex_unlock(&api.mutex);
#endif
return *handle != NULL;
}
static void *
do_dlsym(void **handle, const char *name, bool exit_on_fail)
{
void *result;
const char *error = "" ;
#ifdef _WIN32
result = GetProcAddress(*handle, name);
#else
result = dlsym(*handle, name);
if (!result)
error = dlerror();
#endif
if (!result && exit_on_fail) {
fprintf(stderr, "%s() not found: %s\n" , name, error);
abort();
}
return result;
}
/**
* @ brief Checks whether we ' re using OpenGL or OpenGL ES
*
* @ return ` true ` if we ' re using OpenGL
*/
bool
epoxy_is_desktop_gl(void )
{
const char *es_prefix = "OpenGL ES" ;
const char *version;
#if PLATFORM_HAS_EGL
/* PowerVR's OpenGL ES implementation (and perhaps other) don't
* comply with the standard , which states that
* " glGetString ( GL_VERSION ) " should return a string starting with
* " OpenGL ES " . Therefore , to distinguish desktop OpenGL from
* OpenGL ES , we must also check the context type through EGL ( we
* can do that as PowerVR is only usable through EGL ) .
*/
if (!epoxy_current_context_is_glx()) {
switch (epoxy_egl_get_current_gl_context_api()) {
case EGL_OPENGL_API: return true ;
case EGL_OPENGL_ES_API: return false ;
case EGL_NONE:
default : break ;
}
}
#endif
if (api.begin_count)
return true ;
version = (const char *)glGetString(GL_VERSION);
/* If we didn't get a version back, there are only two things that
* could have happened : either malloc failure ( which basically
* doesn ' t exist ) , or we were called within a glBegin ( ) / glEnd ( ) .
* Assume the second , which only exists for desktop GL .
*/
if (!version)
return true ;
return strncmp(es_prefix, version, strlen(es_prefix));
}
static int
epoxy_internal_gl_version(GLenum version_string, int error_version, int factor)
{
const char *version = (const char *)glGetString(version_string);
GLint major, minor;
int scanf_count;
if (!version)
return error_version;
/* skip to version number */
while (!isdigit(*version) && *version != '\0' )
version++;
/* Interpret version number */
scanf_count = sscanf(version, "%i.%i" , &major, &minor);
if (scanf_count != 2 ) {
fprintf(stderr, "Unable to interpret GL_VERSION string: %s\n" ,
version);
abort();
}
return factor * major + minor;
}
/**
* @ brief Returns the version of OpenGL we are using
*
* The version is encoded as :
*
* ` ` `
*
* version = major * 10 + minor
*
* ` ` `
*
* So it can be easily used for version comparisons .
*
* @ return The encoded version of OpenGL we are using
*/
int
epoxy_gl_version(void )
{
return epoxy_internal_gl_version(GL_VERSION, 0 , 10 );
}
int
epoxy_conservative_gl_version(void )
{
if (api.begin_count)
return 100 ;
return epoxy_internal_gl_version(GL_VERSION, 100 , 10 );
}
/**
* @ brief Returns the version of the GL Shading Language we are using
*
* The version is encoded as :
*
* ` ` `
*
* version = major * 100 + minor
*
* ` ` `
*
* So it can be easily used for version comparisons .
*
* @ return The encoded version of the GL Shading Language we are using
*/
int
epoxy_glsl_version(void )
{
if (epoxy_gl_version() >= 20 ||
epoxy_has_gl_extension ("GL_ARB_shading_language_100" ))
return epoxy_internal_gl_version(GL_SHADING_LANGUAGE_VERSION, 0 , 100 );
return 0 ;
}
/**
* @ brief Checks for the presence of an extension in an OpenGL extension string
*
* @ param extension_list The string containing the list of extensions to check
* @ param ext The name of the GL extension
* @ return ` true ` if the extension is available '
*
* @ note If you are looking to check whether a normal GL , EGL or GLX extension
* is supported by the client , this probably isn ' t the function you want .
*
* Some parts of the spec for OpenGL and friends will return an OpenGL formatted
* extension string that is separate from the usual extension strings for the
* spec . This function provides easy parsing of those strings .
*
* @ see epoxy_has_gl_extension ( )
* @ see epoxy_has_egl_extension ( )
* @ see epoxy_has_glx_extension ( )
*/
bool
epoxy_extension_in_string(const char *extension_list, const char *ext)
{
const char *ptr = extension_list;
int len;
if (!ext)
return false ;
len = strlen(ext);
if (extension_list == NULL || *extension_list == '\0' )
return false ;
/* Make sure that don't just find an extension with our name as a prefix. */
while (true ) {
ptr = strstr(ptr, ext);
if (!ptr)
return false ;
if (ptr[len] == ' ' || ptr[len] == 0 )
return true ;
ptr += len;
}
}
static bool
epoxy_internal_has_gl_extension(const char *ext, bool invalid_op_mode)
{
if (epoxy_gl_version() < 30 ) {
const char *exts = (const char *)glGetString(GL_EXTENSIONS);
if (!exts)
return invalid_op_mode;
return epoxy_extension_in_string(exts, ext);
} else {
int num_extensions;
int i;
glGetIntegerv(GL_NUM_EXTENSIONS, &num_extensions);
if (num_extensions == 0 )
return invalid_op_mode;
for (i = 0 ; i < num_extensions; i++) {
const char *gl_ext = (const char *)glGetStringi(GL_EXTENSIONS, i);
if (!gl_ext)
return false ;
if (strcmp(ext, gl_ext) == 0 )
return true ;
}
return false ;
}
}
bool
epoxy_load_glx(bool exit_if_fails, bool load)
{
#if PLATFORM_HAS_GLX
# ifdef GLVND_GLX_LIB
/* prefer the glvnd library if it exists */
if (!api.glx_handle)
get_dlopen_handle(&api.glx_handle, GLVND_GLX_LIB, false , load);
# endif
if (!api.glx_handle)
get_dlopen_handle(&api.glx_handle, GLX_LIB, exit_if_fails, load);
#endif
return api.glx_handle != NULL;
}
void *
epoxy_conservative_glx_dlsym(const char *name, bool exit_if_fails)
{
#if PLATFORM_HAS_GLX
if (epoxy_load_glx(exit_if_fails, exit_if_fails))
return do_dlsym(&api.glx_handle, name, exit_if_fails);
#endif
return NULL;
}
/**
* Tests whether the currently bound context is EGL or GLX , trying to
* avoid loading libraries unless necessary .
*/
static bool
epoxy_current_context_is_glx(void )
{
#if !PLATFORM_HAS_GLX
return false ;
#else
void *sym;
sym = epoxy_conservative_glx_dlsym("glXGetCurrentContext" , false );
if (sym) {
if (glXGetCurrentContext())
return true ;
} else {
(void )dlerror();
}
#if PLATFORM_HAS_EGL
sym = epoxy_conservative_egl_dlsym("eglGetCurrentContext" , false );
if (sym) {
if (epoxy_egl_get_current_gl_context_api() != EGL_NONE)
return false ;
} else {
(void )dlerror();
}
#endif /* PLATFORM_HAS_EGL */
return false ;
#endif /* PLATFORM_HAS_GLX */
}
/**
* @ brief Returns true if the given GL extension is supported in the current context .
*
* @ param ext The name of the GL extension
* @ return ` true ` if the extension is available
*
* @ note that this function can ' t be called from within ` glBegin ( ) ` and ` glEnd ( ) ` .
*
* @ see epoxy_has_egl_extension ( )
* @ see epoxy_has_glx_extension ( )
*/
bool
epoxy_has_gl_extension(const char *ext)
{
return epoxy_internal_has_gl_extension(ext, false );
}
bool
epoxy_conservative_has_gl_extension(const char *ext)
{
if (api.begin_count)
return true ;
return epoxy_internal_has_gl_extension(ext, true );
}
bool
epoxy_load_egl(bool exit_if_fails, bool load)
{
#if PLATFORM_HAS_EGL
return get_dlopen_handle(&api.egl_handle, EGL_LIB, exit_if_fails, load);
#else
return false ;
#endif
}
void *
epoxy_conservative_egl_dlsym(const char *name, bool exit_if_fails)
{
#if PLATFORM_HAS_EGL
if (epoxy_load_egl(exit_if_fails, exit_if_fails))
return do_dlsym(&api.egl_handle, name, exit_if_fails);
#endif
return NULL;
}
void *
epoxy_egl_dlsym(const char *name)
{
return epoxy_conservative_egl_dlsym(name, true );
}
void *
epoxy_glx_dlsym(const char *name)
{
return epoxy_conservative_glx_dlsym(name, true );
}
static void
epoxy_load_gl(void )
{
if (api.gl_handle)
return ;
#if defined (_WIN32) || defined (__APPLE__)
get_dlopen_handle(&api.gl_handle, OPENGL_LIB, true , true );
#else
// Prefer GLX_LIB over OPENGL_LIB to maintain existing behavior.
// Using the inverse ordering OPENGL_LIB -> GLX_LIB, causes issues such as:
// https://github.com/anholt/libepoxy/issues/240 (apitrace missing calls)
// https://github.com/anholt/libepoxy/issues/252 (Xorg boot crash)
get_dlopen_handle(&api.glx_handle, GLX_LIB, false , true );
api.gl_handle = api.glx_handle;
#if defined (OPENGL_LIB)
if (!api.gl_handle)
get_dlopen_handle(&api.gl_handle, OPENGL_LIB, false , true );
#endif
if (!api.gl_handle) {
#if defined (OPENGL_LIB)
fprintf(stderr, "Couldn't open %s or %s\n" , GLX_LIB, OPENGL_LIB);
#else
fprintf(stderr, "Couldn't open %s\n" , GLX_LIB);
#endif
abort();
}
#endif
}
void *
epoxy_gl_dlsym(const char *name)
{
epoxy_load_gl();
return do_dlsym(&api.gl_handle, name, true );
}
void *
epoxy_gles1_dlsym(const char *name)
{
if (epoxy_current_context_is_glx()) {
return epoxy_get_proc_address(name);
} else {
get_dlopen_handle(&api.gles1_handle, GLES1_LIB, true , true );
return do_dlsym(&api.gles1_handle, name, true );
}
}
void *
epoxy_gles2_dlsym(const char *name)
{
if (epoxy_current_context_is_glx()) {
return epoxy_get_proc_address(name);
} else {
get_dlopen_handle(&api.gles2_handle, GLES2_LIB, true , true );
return do_dlsym(&api.gles2_handle, name, true );
}
}
/**
* Does the appropriate dlsym ( ) or eglGetProcAddress ( ) for GLES3
* functions .
*
* Mesa interpreted GLES as intending that the GLES3 functions were
* available only through eglGetProcAddress ( ) and not dlsym ( ) , while
* ARM ' s Mali drivers interpreted GLES as intending that GLES3
* functions were available only through dlsym ( ) and not
* eglGetProcAddress ( ) . Thanks , Khronos .
*/
void *
epoxy_gles3_dlsym(const char *name)
{
if (epoxy_current_context_is_glx()) {
return epoxy_get_proc_address(name);
} else {
if (get_dlopen_handle(&api.gles2_handle, GLES2_LIB, false , true )) {
void *func = do_dlsym(&api.gles2_handle, name, false );
if (func)
return func;
}
return epoxy_get_proc_address(name);
}
}
/**
* Performs either the dlsym or glXGetProcAddress ( ) - equivalent for
* core functions in desktop GL .
*/
void *
epoxy_get_core_proc_address(const char *name, int core_version)
{
#ifdef _WIN32
int core_symbol_support = 11 ;
#elif defined (__ANDROID__)
/**
* All symbols must be resolved through eglGetProcAddress
* on Android
*/
int core_symbol_support = 0 ;
#else
int core_symbol_support = 12 ;
#endif
if (core_version <= core_symbol_support) {
return epoxy_gl_dlsym(name);
} else {
return epoxy_get_proc_address(name);
}
}
#if PLATFORM_HAS_EGL
static EGLenum
epoxy_egl_get_current_gl_context_api(void )
{
EGLint curapi;
if (!api.egl_handle)
return EGL_NONE;
if (eglQueryContext(eglGetCurrentDisplay(), eglGetCurrentContext(),
EGL_CONTEXT_CLIENT_TYPE, &curapi) == EGL_FALSE) {
(void )eglGetError();
return EGL_NONE;
}
return (EGLenum) curapi;
}
#endif /* PLATFORM_HAS_EGL */
/**
* Performs the dlsym ( ) for the core GL 1 . 0 functions that we use for
* determining version and extension support for deciding on dlsym
* versus glXGetProcAddress ( ) for all other functions .
*
* This needs to succeed on implementations without GLX ( since
* glGetString ( ) and glGetIntegerv ( ) are both in GLES1 / 2 as well , and
* at call time we don ' t know for sure what API they ' re trying to use
* without inspecting contexts ourselves ) .
*/
void *
epoxy_get_bootstrap_proc_address(const char *name)
{
/* If we already have a library that links to libglapi loaded,
* use that .
*/
#if PLATFORM_HAS_GLX
if (api.glx_handle && glXGetCurrentContext())
return epoxy_gl_dlsym(name);
#endif
/* If epoxy hasn't loaded any API-specific library yet, try to
* figure out what API the context is using and use that library ,
* since future calls will also use that API ( this prevents a
* non - X11 ES2 context from loading a bunch of X11 junk ) .
*/
#if PLATFORM_HAS_EGL
get_dlopen_handle(&api.egl_handle, EGL_LIB, false , true );
if (api.egl_handle) {
int version = 0 ;
switch (epoxy_egl_get_current_gl_context_api()) {
case EGL_OPENGL_API:
return epoxy_gl_dlsym(name);
case EGL_OPENGL_ES_API:
if (eglQueryContext(eglGetCurrentDisplay(),
eglGetCurrentContext(),
EGL_CONTEXT_CLIENT_VERSION,
&version)) {
if (version >= 2 )
return epoxy_gles2_dlsym(name);
else
return epoxy_gles1_dlsym(name);
}
}
}
#endif /* PLATFORM_HAS_EGL */
/* Fall back to GLX */
return epoxy_gl_dlsym(name);
}
void *
epoxy_get_proc_address(const char *name)
{
#if PLATFORM_HAS_EGL
GLenum egl_api = EGL_NONE;
if (!epoxy_current_context_is_glx())
egl_api = epoxy_egl_get_current_gl_context_api();
switch (egl_api) {
case EGL_OPENGL_API:
case EGL_OPENGL_ES_API:
return eglGetProcAddress(name);
case EGL_NONE:
break ;
}
#endif
#if defined (_WIN32)
return wglGetProcAddress(name);
#elif defined (__APPLE__)
return epoxy_gl_dlsym(name);
#elif PLATFORM_HAS_GLX
if (epoxy_current_context_is_glx())
return glXGetProcAddressARB((const GLubyte *)name);
assert(0 && "Couldn't find current GLX or EGL context.\n" );
#endif
return NULL;
}
WRAPPER_VISIBILITY (void )
WRAPPER(epoxy_glBegin)(GLenum primtype)
{
#ifdef _WIN32
InterlockedIncrement(&api.begin_count);
#else
pthread_mutex_lock(&api.mutex);
api.begin_count++;
pthread_mutex_unlock(&api.mutex);
#endif
epoxy_glBegin_unwrapped(primtype);
}
WRAPPER_VISIBILITY (void )
WRAPPER(epoxy_glEnd)(void )
{
epoxy_glEnd_unwrapped();
#ifdef _WIN32
InterlockedDecrement(&api.begin_count);
#else
pthread_mutex_lock(&api.mutex);
api.begin_count--;
pthread_mutex_unlock(&api.mutex);
#endif
}
PFNGLBEGINPROC epoxy_glBegin = epoxy_glBegin_wrapped;
PFNGLENDPROC epoxy_glEnd = epoxy_glEnd_wrapped;
epoxy_resolver_failure_handler_t epoxy_resolver_failure_handler;
/**
* Sets the function that will be called every time Epoxy fails to
* resolve a symbol .
*
* @ param handler The new handler function
* @ return The previous handler function
*/
epoxy_resolver_failure_handler_t
epoxy_set_resolver_failure_handler(epoxy_resolver_failure_handler_t handler)
{
#ifdef _WIN32
return InterlockedExchangePointer((void **)&epoxy_resolver_failure_handler,
handler);
#else
epoxy_resolver_failure_handler_t old;
pthread_mutex_lock(&api.mutex);
old = epoxy_resolver_failure_handler;
epoxy_resolver_failure_handler = handler;
pthread_mutex_unlock(&api.mutex);
return old;
#endif
}
Messung V0.5 in Prozent C=96 H=99 G=97
¤ Diese beiden folgenden Angebotsgruppen bietet das Unternehmen0.26Angebot
(Wie Sie bei der Firma Beratungs- und Dienstleistungen beauftragen können 2026-10-02)
¤
*Eine klare Vorstellung vom Zielzustand
2026-10-10
Neuigkeiten
Aktuelles
Motto des Tages
Open Source Software
Jenseits des Üblichen ....
Besucherstatistik
Statistik
#Sources=1126864
#Domains=1897691