From 5569357a9fc7189c2bae43773f44ba576583ec2b Mon Sep 17 00:00:00 2001 From: Carl Worth Date: Fri, 21 Jun 2013 17:10:03 -0700 Subject: [PATCH] Add dynamic dispatch for any calls to OpenGL functions. Previously, fips code was making direct calls to OpenGL functions, (such as glGenQueries, glBeinQuery, etc. within metrics.c). Some OpenGL implementations do not export these symbols directly, (expecting the application to instead look the symbols up via a call to glXGetProcAddressARB or eglGetProcAddress). The new fips-dispatch code added here does precisely that, (and adds wrapper for both glXMakeCurrent and eglMakeCurrent in order to know which GetProcAddress function should be called). The dispatch code follows the model of piglit-dispatch, (available under the same license as fips). Thanks to Eric Anholt for suggesting following the same approach as piglit. --- Makefile.local | 1 + eglwrap.c | 15 ++++ fips-dispatch.c | 177 ++++++++++++++++++++++++++++++++++++++++++++++++ fips-dispatch.h | 51 ++++++++++++++ fips.h | 1 + glwrap.c | 14 ++-- glxwrap.c | 14 ++++ metrics.c | 4 +- 8 files changed, 266 insertions(+), 11 deletions(-) create mode 100644 fips-dispatch.c create mode 100644 fips-dispatch.h diff --git a/Makefile.local b/Makefile.local index 7914718..9b54011 100644 --- a/Makefile.local +++ b/Makefile.local @@ -94,6 +94,7 @@ extra_cflags += -I$(srcdir) -fPIC libfips_srcs = \ dlwrap.c \ + fips-dispatch.c \ glwrap.c \ glxwrap.c \ metrics.c diff --git a/eglwrap.c b/eglwrap.c index 6f009c3..913fd48 100644 --- a/eglwrap.c +++ b/eglwrap.c @@ -21,6 +21,8 @@ #include "fips.h" +#include "fips-dispatch.h" + #include #include "dlwrap.h" @@ -74,3 +76,16 @@ eglSwapBuffers (EGLDisplay dpy, EGLSurface surface) return ret; } + +EGLBoolean +eglMakeCurrent (EGLDisplay display, EGLSurface draw, EGLSurface read, + EGLContext context) +{ + EGLBoolean ret; + + fips_dispatch_init (FIPS_API_EGL); + + EGLWRAP_DEFER_WITH_RETURN (ret, eglMakeCurrent, display, draw, read, context); + + return ret; +} diff --git a/fips-dispatch.c b/fips-dispatch.c new file mode 100644 index 0000000..c5f767c --- /dev/null +++ b/fips-dispatch.c @@ -0,0 +1,177 @@ +/* Copyright © 2012, 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 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. + */ + +#include "fips.h" + +#include "fips-dispatch.h" + +#define GL_GLEXT_PROTOTYPES +#include +#include + +#include + +static bool fips_initialized; +static fips_api_t fips_api; + +void +fips_dispatch_init (fips_api_t api) +{ + fips_api = api; + + fips_initialized = true; +} + +static void +check_initialized (void) +{ + if (fips_initialized) + return; + + fprintf (stderr, + "Internal error: fips_dispatch_init must be called before\n" + "any OpenGL function supported via fips_dispatch.\n"); + exit (1); +} + +static void +unsupported (const char *name) +{ + fprintf (stderr, "Error: fips failed to find support for %s\n", name); + + exit (1); +} + +static void * +lookup (const char *name) +{ + if (fips_api == FIPS_API_GLX) + return glXGetProcAddressARB ((const GLubyte *)name); + else + return eglGetProcAddress (name); +} + +static void +resolve_glGenQueries (void) +{ + fips_dispatch_glGenQueries = lookup ("glGenQueries"); + + if (! fips_dispatch_glGenQueries) + fips_dispatch_glGenQueries = lookup ("glGenQueriesARB"); + + if (! fips_dispatch_glGenQueries) + unsupported ("GenQueries"); +} + +static void +stub_glGenQueries (GLsizei n, GLuint *ids) +{ + check_initialized (); + resolve_glGenQueries (); + fips_dispatch_glGenQueries (n, ids); +} + +PFNGLGENQUERIESPROC fips_dispatch_glGenQueries = stub_glGenQueries; + +static void +resolve_glDeleteQueries (void) +{ + fips_dispatch_glDeleteQueries = lookup ("glDeleteQueries"); + + if (! fips_dispatch_glDeleteQueries) + fips_dispatch_glDeleteQueries = lookup ("glDeleteQueriesARB"); + + if (! fips_dispatch_glDeleteQueries) + unsupported ("DeleteQueries"); +} + +static void +stub_glDeleteQueries (GLsizei n, const GLuint * ids) +{ + check_initialized (); + resolve_glDeleteQueries (); + fips_dispatch_glDeleteQueries (n, ids); +} + +PFNGLDELETEQUERIESPROC fips_dispatch_glDeleteQueries = stub_glDeleteQueries; + +static void +resolve_glBeginQuery (void) +{ + fips_dispatch_glBeginQuery = lookup ("glBeginQuery"); + + if (! fips_dispatch_glBeginQuery) + fips_dispatch_glBeginQuery = lookup ("glBeginQueryARB"); + + if (! fips_dispatch_glBeginQuery) + unsupported ("BeginQuery"); +} + +static void +stub_glBeginQuery (GLenum target, GLuint id) +{ + check_initialized (); + resolve_glBeginQuery (); + fips_dispatch_glBeginQuery (target, id); +} + +PFNGLBEGINQUERYPROC fips_dispatch_glBeginQuery = stub_glBeginQuery; + +static void +resolve_glEndQuery (void) +{ + fips_dispatch_glEndQuery = lookup ("glEndQuery"); + + if (! fips_dispatch_glEndQuery) + fips_dispatch_glEndQuery = lookup ("glEndQueryARB"); + + if (! fips_dispatch_glEndQuery) + unsupported ("EndQuery"); +} + +static void +stub_glEndQuery (GLenum target) +{ + check_initialized (); + resolve_glEndQuery (); + fips_dispatch_glEndQuery (target); +} + +PFNGLENDQUERYPROC fips_dispatch_glEndQuery = stub_glEndQuery; + +static void +resolve_glGetQueryObjectuiv (void) +{ + fips_dispatch_glGetQueryObjectuiv = (PFNGLGETQUERYOBJECTUIVARBPROC) lookup("glGetQueryObjectuivARB"); + + if (! fips_dispatch_glGetQueryObjectuiv) + unsupported ("GetQueryObjectuiv"); +} + +static void +stub_glGetQueryObjectuiv (GLuint id, GLenum pname, GLuint * params) +{ + check_initialized (); + resolve_glGetQueryObjectuiv (); + fips_dispatch_glGetQueryObjectuiv (id, pname, params); +} + +PFNGLGETQUERYOBJECTUIVPROC fips_dispatch_glGetQueryObjectuiv = stub_glGetQueryObjectuiv; diff --git a/fips-dispatch.h b/fips-dispatch.h new file mode 100644 index 0000000..a371703 --- /dev/null +++ b/fips-dispatch.h @@ -0,0 +1,51 @@ +/* Copyright © 2012, 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 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. + */ + +#ifndef FIPS_DISPATCH_H +#define FIPS_DISPATCH_H + +#define GL_GLEXT_PROTOTYPES +#include + +extern PFNGLGENQUERIESPROC fips_dispatch_glGenQueries; +#define glGenQueries fips_dispatch_glGenQueries + +extern PFNGLDELETEQUERIESPROC fips_dispatch_glDeleteQueries; +#define glDeleteQueries fips_dispatch_glDeleteQueries + +extern PFNGLBEGINQUERYPROC fips_dispatch_glBeginQuery; +#define glBeginQuery fips_dispatch_glBeginQuery + +extern PFNGLENDQUERYPROC fips_dispatch_glEndQuery; +#define glEndQuery fips_dispatch_glEndQuery + +extern PFNGLGETQUERYOBJECTUIVPROC fips_dispatch_glGetQueryObjectuiv; +#define glGetQueryObjectuiv fips_dispatch_glGetQueryObjectuiv + +typedef enum { + FIPS_API_GLX, + FIPS_API_EGL +} fips_api_t; + +void +fips_dispatch_init (fips_api_t api); + +#endif /* FIPS_DISPATCH_H */ diff --git a/fips.h b/fips.h index 4c6c5bd..306ea1b 100644 --- a/fips.h +++ b/fips.h @@ -26,6 +26,7 @@ #include #include +#include #include diff --git a/glwrap.c b/glwrap.c index 323c321..e92889a 100644 --- a/glwrap.c +++ b/glwrap.c @@ -19,12 +19,6 @@ * THE SOFTWARE. */ -#include "fips.h" - -#include "glwrap.h" - -#include "metrics.h" - /* The prototypes for some OpenGL functions changed at one point from: * * const void* *indices @@ -42,8 +36,12 @@ */ #define const -#define GL_GLEXT_PROTOTYPES -#include +#include "fips.h" +#include "fips-dispatch.h" + +#include "glwrap.h" + +#include "metrics.h" #include "dlwrap.h" diff --git a/glxwrap.c b/glxwrap.c index 84bf485..799a019 100644 --- a/glxwrap.c +++ b/glxwrap.c @@ -21,6 +21,8 @@ #include "fips.h" +#include "fips-dispatch.h" + #include #include #include @@ -57,3 +59,15 @@ void (*glXGetProcAddressARB (const GLubyte *func))(void) return ret; } + +Bool +glXMakeCurrent (Display *dpy, GLXDrawable drawable, GLXContext ctx) +{ + Bool ret; + + fips_dispatch_init (FIPS_API_GLX); + + GLWRAP_DEFER_WITH_RETURN (ret, glXMakeCurrent, dpy, drawable, ctx); + + return ret; +} diff --git a/metrics.c b/metrics.c index b6dbbd0..cbfe52e 100644 --- a/metrics.c +++ b/metrics.c @@ -24,9 +24,7 @@ #include -#define GL_GLEXT_PROTOTYPES -#include - +#include "fips-dispatch.h" #include "metrics.h" typedef struct counter -- 2.43.0