|
|
|
/*
|
|
|
|
* Copyright © 2013 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.
|
|
|
|
*/
|
|
|
|
|
|
|
|
/**
|
|
|
|
* @file dispatch_common.c
|
|
|
|
*
|
|
|
|
* 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>
|
|
|
|
#include <dlfcn.h>
|
|
|
|
#include <string.h>
|
|
|
|
#include <stdio.h>
|
|
|
|
#include "epoxy/gl.h"
|
|
|
|
#include "epoxy/glx.h"
|
|
|
|
#include "dispatch_common.h"
|
|
|
|
|
|
|
|
/* XXX: Make this thread local */
|
|
|
|
struct api local_api;
|
|
|
|
|
|
|
|
struct api *api = &local_api;
|
|
|
|
|
|
|
|
bool
|
|
|
|
epoxy_is_desktop_gl(void)
|
|
|
|
{
|
|
|
|
const char *es_prefix = "OpenGL ES ";
|
|
|
|
const char *version = (const char *)glGetString(GL_VERSION);
|
|
|
|
|
|
|
|
printf("VERSION %s\n", version);
|
|
|
|
return !strncmp(es_prefix, version, strlen(es_prefix));
|
|
|
|
}
|
|
|
|
|
|
|
|
PUBLIC int
|
|
|
|
epoxy_gl_version(void)
|
|
|
|
{
|
|
|
|
GLint major, minor;
|
|
|
|
|
|
|
|
glGetIntegerv(GL_MAJOR_VERSION, &major);
|
|
|
|
glGetIntegerv(GL_MAJOR_VERSION, &minor);
|
|
|
|
|
|
|
|
return major * 10 + minor;
|
|
|
|
}
|
|
|
|
|
|
|
|
bool
|
|
|
|
epoxy_is_glx(void)
|
|
|
|
{
|
|
|
|
return true; /* XXX */
|
|
|
|
}
|
|
|
|
|
|
|
|
int
|
|
|
|
epoxy_glx_version(void)
|
|
|
|
{
|
|
|
|
return 14; /* XXX */
|
|
|
|
}
|
|
|
|
|
|
|
|
static bool
|
|
|
|
epoxy_extension_in_string(const char *extension_list, const char *ext)
|
|
|
|
{
|
|
|
|
const char *ptr = extension_list;
|
|
|
|
int len = strlen(ext);
|
|
|
|
|
|
|
|
/* Make sure that don't just find an extension with our name as a prefix. */
|
|
|
|
do {
|
|
|
|
ptr = strstr(ptr, ext);
|
|
|
|
} while (ptr && (ptr[len] != ' ' && ptr[len] != 0));
|
|
|
|
|
|
|
|
return ptr != NULL;
|
|
|
|
}
|
|
|
|
|
|
|
|
PUBLIC bool
|
|
|
|
epoxy_has_gl_extension(const char *ext)
|
|
|
|
{
|
|
|
|
return epoxy_extension_in_string((const char *)glGetString(GL_EXTENSIONS),
|
|
|
|
ext);
|
|
|
|
}
|
|
|
|
|
|
|
|
#if 0
|
|
|
|
PUBLIC bool
|
|
|
|
epoxy_has_egl_extension(const char *ext)
|
|
|
|
{
|
|
|
|
return epoxy_extension_in_string(eglQueryString(EGL_EXTENSIONS), ext);
|
|
|
|
}
|
|
|
|
#endif
|
|
|
|
|
|
|
|
PUBLIC bool
|
|
|
|
epoxy_has_glx_extension(const char *ext)
|
|
|
|
{
|
|
|
|
Display *dpy = glXGetCurrentDisplay();
|
|
|
|
int screen = 0;
|
|
|
|
|
|
|
|
if (!dpy) {
|
|
|
|
fprintf(stderr, "waffle needs a display!"); /* XXX */
|
|
|
|
return false;
|
|
|
|
}
|
|
|
|
|
|
|
|
/* No, you can't just use glXGetClientString or glXGetServerString() here.
|
|
|
|
* Those each tell you about one half of what's needed for an extension to
|
|
|
|
* be supported, and glXQueryExtensionsString().
|
|
|
|
*/
|
|
|
|
return epoxy_extension_in_string(glXQueryExtensionsString(dpy, screen), ext);
|
|
|
|
}
|
|
|
|
|
|
|
|
void *
|
|
|
|
epoxy_dlsym(const char *name)
|
|
|
|
{
|
|
|
|
assert(api->gl_handle);
|
|
|
|
return dlsym(api->gl_handle, name);
|
|
|
|
}
|
|
|
|
|
|
|
|
void *
|
|
|
|
epoxy_get_proc_address(const char *name)
|
|
|
|
{
|
|
|
|
return glXGetProcAddress((const GLubyte *)name);
|
|
|
|
}
|
|
|
|
|
|
|
|
void
|
|
|
|
epoxy_glx_autoinit(void)
|
|
|
|
{
|
|
|
|
if (api->gl_handle)
|
|
|
|
return;
|
|
|
|
|
|
|
|
api->gl_handle = dlopen("libGL.so.1", RTLD_LAZY | RTLD_LOCAL);
|
|
|
|
if (!api->gl_handle) {
|
|
|
|
fprintf(stderr, "Couldn't open libGL.so.1: %s", dlerror());
|
|
|
|
exit(1);
|
|
|
|
}
|
|
|
|
|
|
|
|
api->winsys_handle = api->gl_handle;
|
|
|
|
}
|
|
|
|
|
|
|
|
void
|
|
|
|
epoxy_platform_autoinit(void)
|
|
|
|
{
|
|
|
|
epoxy_glx_autoinit();
|
|
|
|
}
|
|
|
|
|