[Piglit] [PATCH v3 15/19] piglit-dispatch: Remaining infrastructure.
Paul Berry
stereotype441 at gmail.com
Wed Mar 21 08:58:14 PDT 2012
Previous patches introduced code generation for the auto-generated
portions of the piglit-dispatch mechanism. This patch supplies the
remaining hand-written code, which includes:
- Code to initialize piglit-dispatch.
- The actions to be taken when looking up a function, when function
lookup fails, or when a function is unsupported.
- Code to determine whether piglit-dispatch has been initialized,
which GL version is supported, and whether a given extension is
supported.
- Code to look up a function using a name supplied at run-time.
- Definitions of basic GL types.
v2: Make "inline" work in MSVC. Only try to include "glxew.h" on
Linux. Fix MSVC definition of int8_t. Add #include
"piglit-dispatch.h" to piglit-dispatch.c for clarity. Get rid of "__"
in function names. Only call reset_dispatch_pointers() if necessary.
Use "\param" in comments. Define APIENTRY/GLAPIENTRY properly on
Windows. Implement get_core_proc_address() and get_ext_proc_address()
properly for Windows.
---
tests/util/piglit-dispatch-init.c | 191 ++++++++++++++++++++++++++++
tests/util/piglit-dispatch.c | 246 +++++++++++++++++++++++++++++++++++++
tests/util/piglit-dispatch.h | 160 ++++++++++++++++++++++++
tests/util/piglit-util.h | 2 +-
4 files changed, 598 insertions(+), 1 deletions(-)
create mode 100644 tests/util/piglit-dispatch-init.c
create mode 100644 tests/util/piglit-dispatch.c
create mode 100644 tests/util/piglit-dispatch.h
diff --git a/tests/util/piglit-dispatch-init.c b/tests/util/piglit-dispatch-init.c
new file mode 100644
index 0000000..7ad76e2
--- /dev/null
+++ b/tests/util/piglit-dispatch-init.c
@@ -0,0 +1,191 @@
+/* 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 (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.
+ */
+
+#include "piglit-util.h"
+
+#if defined(_WIN32)
+
+#elif defined(__APPLE__)
+
+#include <stdlib.h>
+#include <string.h>
+#include <AvailabilityMacros.h>
+#include <dlfcn.h>
+
+#else /* Linux */
+
+#include "glxew.h"
+
+#endif
+
+/**
+ * Generated code calls this function if the test tries to use a GL
+ * function that is not supported on the current implementation.
+ *
+ * This function terminates the test with a SKIP; this saves the
+ * piglit test from the burden of having to pre-check whether the
+ * implementation supports the functionality being tested.
+ */
+static void
+default_unsupported(const char *name)
+{
+ printf("Function \"%s\" not supported on this implementation\n", name);
+ piglit_report_result(PIGLIT_SKIP);
+}
+
+/**
+ * Generated code calls this function if a call to GetProcAddress()
+ * returns NULL.
+ *
+ * We don't expect this to ever happen, since we only call
+ * GetProcAddress() for functions that the implementation claims to
+ * support. So if it does happen we terminate the test with a FAIL.
+ */
+static void
+default_get_proc_address_failure(const char *function_name)
+{
+ printf("GetProcAddress failed for \"%s\"\n", function_name);
+ piglit_report_result(PIGLIT_FAIL);
+}
+
+#if defined(_WIN32)
+
+/**
+ * This function is used to retrieve the address of GL extension
+ * functions, and core GL functions for GL versions above 1.3, on
+ * Windows.
+ */
+static piglit_dispatch_function_ptr
+get_ext_proc_address(const char *function_name)
+{
+ return (piglit_dispatch_function_ptr) wglGetProcAddress(function_name);
+}
+
+/**
+ * This function is used to retrieve the address of core GL functions
+ * on windows.
+ */
+static piglit_dispatch_function_ptr
+get_core_proc_address(const char *function_name, int gl_10x_version)
+{
+ if (gl_10x_version > 11) {
+ return get_ext_proc_address(function_name);
+ } else {
+ return (piglit_dispatch_function_ptr)
+ GetProcAddress(LoadLibraryA("OPENGL32"), function_name);
+ }
+}
+
+#elif defined(__APPLE__)
+
+/**
+ * This function is used to retrieve the address of all GL functions
+ * on Apple.
+ */
+static piglit_dispatch_function_ptr
+get_ext_proc_address(const char *function_name)
+{
+ static const char *opengl_path =
+ "/System/Library/Frameworks/OpenGL.framework/Versions/Current/OpenGL";
+ static void *opengl_lib = NULL;
+
+ /* Dynamically load lib */
+ if (!opengl_lib)
+ {
+ opengl_lib = dlopen(opengl_path, RTLD_LAZY);
+ if (!opengl_lib)
+ return NULL;
+ }
+
+ return (piglit_dispatch_function_ptr) dlsym(opengl_lib, function_name);
+}
+
+/**
+ * This function is used to retrieve the address of core GL functions
+ * on Apple.
+ */
+static piglit_dispatch_function_ptr
+get_core_proc_address(const char *function_name, int gl_10x_version)
+{
+ /* We don't need to worry about the GL version, since on Apple
+ * we retrieve all proc addresses in the same way.
+ */
+ (void) gl_10x_version;
+
+ return get_ext_proc_address(function_name);
+}
+
+#else /* Linux */
+
+/**
+ * This function is used to retrieve the address of all GL functions
+ * on Linux.
+ */
+static piglit_dispatch_function_ptr
+get_ext_proc_address(const char *function_name)
+{
+ return glXGetProcAddressARB((const GLubyte *) function_name);
+}
+
+/**
+ * This function is used to retrieve the address of core GL functions
+ * on Linux.
+ */
+static piglit_dispatch_function_ptr
+get_core_proc_address(const char *function_name, int gl_10x_version)
+{
+ /* We don't need to worry about the GL version, since on Apple
+ * we retrieve all proc addresses in the same way.
+ */
+ (void) gl_10x_version;
+
+ return get_ext_proc_address(function_name);
+}
+
+#endif
+
+/**
+ * Initialize the GL dispatch mechanism to a default configuration.
+ *
+ * Eventually we will want to replace this with code that initializes
+ * the GL dispatch mechanism based on run-time parameters (e.g. to
+ * select X vs Wayland, or desktop GL vs GLES).
+ *
+ * This function is safe to call multiple times--it only has an effect
+ * on the first call.
+ */
+void
+piglit_dispatch_default_init()
+{
+ static bool already_initialized = false;
+
+ if (already_initialized)
+ return;
+
+ piglit_dispatch_init(PIGLIT_DISPATCH_GL,
+ get_core_proc_address,
+ get_ext_proc_address,
+ default_unsupported,
+ default_get_proc_address_failure);
+
+ already_initialized = true;
+}
diff --git a/tests/util/piglit-dispatch.c b/tests/util/piglit-dispatch.c
new file mode 100644
index 0000000..48e03ff
--- /dev/null
+++ b/tests/util/piglit-dispatch.c
@@ -0,0 +1,246 @@
+/* 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 (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.
+ */
+
+#include "piglit-dispatch.h"
+#include "piglit-util.h"
+
+#ifdef _WIN32
+#define inline __inline
+#endif
+
+/* Global state maintained by the Piglit dispatch mechanism: */
+
+/**
+ * Which function to call to get the address of a core function.
+ */
+static piglit_get_core_proc_address_function_ptr get_core_proc_address = NULL;
+
+/**
+ * Which function to call to get the address of a function defined in
+ * an extension.
+ */
+static piglit_get_ext_proc_address_function_ptr get_ext_proc_address = NULL;
+
+/**
+ * Which function to call if the test attempts to call a function that
+ * is not supported by the implementation.
+ */
+static piglit_error_function_ptr unsupported = NULL;
+
+/**
+ * Which function to call if get_core_proc_address or
+ * get_ext_proc_address returns NULL.
+ */
+static piglit_error_function_ptr get_proc_address_failure = NULL;
+
+/**
+ * The GL version extracted from glGetString(GL_VERSION), times 10.
+ * For example, if the GL version is 2.1, the value 21 is stored here.
+ *
+ * We cache this here because calling glGetString is prohibited
+ * between glBegin and glEnd, and to avoid the inefficiency of
+ * redundant glGetString queries.
+ */
+static int gl_version = 0;
+
+/**
+ * The GL extension string returned by glGetString(GL_EXTENSIONS).
+ *
+ * We cache this here because calling glGetString is prohibited
+ * between glBegin and glEnd, and to avoid the inefficiency of
+ * redundant glGetString queries.
+ */
+static const char *gl_extensions = NULL;
+
+/**
+ * True if piglit_dispatch_init has been called.
+ */
+static bool is_initialized = false;
+
+/**
+ * Generated code calls this function to verify that the dispatch
+ * mechanism has been properly initialized.
+ */
+static void
+check_initialized()
+{
+ if (is_initialized)
+ return;
+
+ printf("piglit_dispatch_init() must be called before GL functions\n");
+ assert(false);
+ exit(1);
+}
+
+/**
+ * Generated code calls this function to retrieve the address of a
+ * core function.
+ */
+static piglit_dispatch_function_ptr
+get_core_proc(const char *name, int gl_10x_version)
+{
+ piglit_dispatch_function_ptr function_pointer = get_core_proc_address(name, gl_10x_version);
+ if (function_pointer == NULL)
+ get_proc_address_failure(name);
+ return function_pointer;
+}
+
+/**
+ * Generated code calls this function to retrieve the address of a
+ * function defined in an extension.
+ */
+static piglit_dispatch_function_ptr
+get_ext_proc(const char *name)
+{
+ piglit_dispatch_function_ptr function_pointer = get_ext_proc_address(name);
+ if (function_pointer == NULL)
+ get_proc_address_failure(name);
+ return function_pointer;
+}
+
+/**
+ * Generated code calls this function to determine whether a given GL
+ * version is supported.
+ */
+static inline bool
+check_version(int required_version)
+{
+ return gl_version >= required_version;
+}
+
+/**
+ * Generated code calls this function to determine whether a given
+ * extension is supported.
+ */
+static inline bool
+check_extension(const char *name)
+{
+ return piglit_is_extension_in_string(gl_extensions, name);
+}
+
+#include "generated_dispatch.c"
+
+/**
+ * Initialize the dispatch mechanism.
+ *
+ * \param api is the API under test. This determines whether
+ * deprecated functionality is supported (since deprecated functions
+ * cannot be used in forward compatible contexts). It also affects
+ * which GL version is queried for (since, for example a function
+ * might be supported in GLES as of version 2.0, but in OpenGL only as
+ * of version 2.1). Not yet implemented.
+ *
+ * \param get_core_proc and get_ext_proc are the functions to call to
+ * retrieve the address of a core GL function or an extension
+ * function. Note that for OpenGL, these can both map to the same
+ * function (e.g. glXGetProcAddressARB). However, in GLES, core
+ * functions are not allowed to be queried using the GetProcAddress
+ * mechanism, so get_core_proc will need to be implemented by looking
+ * up a symbol in a shared library (e.g. using dlsym()).
+ *
+ * \param unsupported_proc is the function to call if a test attempts
+ * to use unsupported GL functionality. It is passed the name of the
+ * function that the test attempted to use.
+ *
+ * \param failure_proc is the function to call if a call to
+ * get_core_proc() or get_ext_proc() unexpectedly returned NULL. It
+ * is passed the name of the function that was passed to
+ * get_core_proc() or get_ext_proc().
+ */
+void
+piglit_dispatch_init(piglit_dispatch_api api,
+ piglit_get_core_proc_address_function_ptr get_core_proc,
+ piglit_get_ext_proc_address_function_ptr get_ext_proc,
+ piglit_error_function_ptr unsupported_proc,
+ piglit_error_function_ptr failure_proc)
+{
+ (void) api; /* Not yet implemented--assume GL. */
+
+ get_core_proc_address = get_core_proc;
+ get_ext_proc_address = get_ext_proc;
+ unsupported = unsupported_proc;
+ get_proc_address_failure = failure_proc;
+
+ /* No need to reset the dispatch pointers the first time */
+ if (is_initialized) {
+ reset_dispatch_pointers();
+ }
+
+ is_initialized = true;
+
+ /* Store the GL version and extension string for use by
+ * check_version() and check_extension(). Note: the
+ * following two calls are safe because the only GL function
+ * they call is glGetString(), and the stub function for
+ * glGetString does not need to call check_version() or
+ * check_extension().
+ */
+ gl_version = piglit_get_gl_version();
+ gl_extensions = (const char *) glGetString(GL_EXTENSIONS);
+}
+
+/**
+ * Compare two strings in the function_names table.
+ */
+static int compare_function_names(const void *x, const void *y)
+{
+ const char *x_str = *(const char * const *) x;
+ const char *y_str = *(const char * const *) y;
+ return strcmp(x_str, y_str);
+}
+
+/**
+ * Retrieve a GL function pointer given the function name.
+ *
+ * This function is similar to glXGetProcAddressARB(), except that:
+ *
+ * - It is platform-independent.
+ *
+ * - It may be called on any supported function, regardless of whether
+ * the function is defined in GL core or an extension, and
+ * regardless of whether desktop GL or GLES is in use.
+ *
+ * - Synonymous function names (e.g. glMapBuffer and glMapBufferARB)
+ * may be used interchangably; the correct function is automatically
+ * chosen based on the GL version and extension string.
+ *
+ * - If the requested function is not supported by the implementation,
+ * the unsupported_proc that was passed to piglit_dispatch_init() is
+ * called.
+ */
+piglit_dispatch_function_ptr
+piglit_dispatch_resolve_function(const char *name)
+{
+ size_t item_size = sizeof(function_names[0]);
+ size_t num_items = ARRAY_SIZE(function_names);
+ const char * const *item = (const char * const *)
+ bsearch(&name, function_names, num_items, item_size,
+ compare_function_names);
+ check_initialized();
+ if (!item) {
+ unsupported(name);
+ return NULL;
+ } else {
+ size_t item_index = item - function_names;
+ return function_resolvers[item_index]();
+ }
+}
diff --git a/tests/util/piglit-dispatch.h b/tests/util/piglit-dispatch.h
new file mode 100644
index 0000000..1eea0e3
--- /dev/null
+++ b/tests/util/piglit-dispatch.h
@@ -0,0 +1,160 @@
+/* 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 (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 piglit-dispatch.h
+ *
+ * Dispatch mechanism providing Piglit with access to:
+ *
+ * - Enum values defined by OpenGL, GLES, and extensions. The enums
+ * are declared as simple #defines.
+ *
+ * - Functions defined by OpenGL, GLES, and extensions. Each function
+ * is represented by a function pointer, which initially points to a
+ * stub function. When the stub function is called, it looks up the
+ * appropriate function in the GL or GLES implementation, and
+ * updates the function pointer to point to it. Then it defers to
+ * that function.
+ *
+ * The dispatch mechanism understands function aliases. So, for
+ * example, since glMapBuffer and glMapBufferARB are synonymous, you
+ * may safely call either function. The dispatch mechanism will
+ * transparently map to whichever function the implementation
+ * supports.
+ *
+ * You may also translate a function name to a function pointer at run
+ * time by calling piglit_dispatch_resolve_function().
+ *
+ * The dispatch mechanism must be initialized before its first use.
+ * The initialization function, piglit_dispatch_init(), allows the
+ * caller to specify which API is in use, how to look up function
+ * pointers, what to do in the event of an error, and what to do if an
+ * unsupported function is requested.
+ */
+
+#ifndef __piglit_dispatch_h__
+#define __piglit_dispatch_h__
+
+#include <stdint.h>
+#include <stddef.h>
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+#ifndef _WIN32
+
+/* APIENTRY and GLAPIENTRY are not used on Linux or Mac. */
+#define APIENTRY
+#define GLAPIENTRY
+
+#else
+
+#define APIENTRY __stdcall
+#define GLAPIENTRY __stdcall
+
+#endif
+
+typedef unsigned int GLenum;
+typedef unsigned int GLbitfield;
+typedef unsigned int GLuint;
+typedef int GLint;
+typedef int GLsizei;
+typedef unsigned char GLboolean;
+typedef signed char GLbyte;
+typedef short GLshort;
+typedef unsigned char GLubyte;
+typedef unsigned short GLushort;
+typedef unsigned long GLulong;
+typedef float GLfloat;
+typedef float GLclampf;
+typedef double GLdouble;
+typedef double GLclampd;
+typedef void GLvoid;
+typedef int64_t GLint64EXT;
+typedef uint64_t GLuint64EXT;
+typedef GLint64EXT GLint64;
+typedef GLuint64EXT GLuint64;
+typedef struct __GLsync *GLsync;
+
+typedef char GLchar;
+
+typedef ptrdiff_t GLintptr;
+typedef ptrdiff_t GLsizeiptr;
+
+typedef ptrdiff_t GLintptrARB;
+typedef ptrdiff_t GLsizeiptrARB;
+
+typedef char GLcharARB;
+typedef unsigned int GLhandleARB;
+
+struct _cl_context;
+struct _cl_event;
+
+typedef GLintptr GLvdpauSurfaceNV;
+typedef unsigned short GLhalfNV;
+
+typedef void (APIENTRY *GLDEBUGPROCARB)(GLenum source,GLenum type,GLuint id,GLenum severity,GLsizei length,const GLchar *message,GLvoid *userParam);
+
+typedef void (APIENTRY *GLDEBUGPROCAMD)(GLuint id,GLenum category,GLenum severity,GLsizei length,const GLchar *message,GLvoid *userParam);
+
+typedef void (APIENTRY *piglit_dispatch_function_ptr)(void);
+
+typedef piglit_dispatch_function_ptr (*piglit_get_core_proc_address_function_ptr)(const char *, int);
+
+typedef piglit_dispatch_function_ptr (*piglit_get_ext_proc_address_function_ptr)(const char *);
+
+typedef piglit_dispatch_function_ptr (*piglit_dispatch_resolver_ptr)();
+
+typedef void (*piglit_error_function_ptr)(const char *);
+
+typedef enum {
+ PIGLIT_DISPATCH_GL,
+ PIGLIT_DISPATCH_GL_FWD,
+ PIGLIT_DISPATCH_ES1,
+ PIGLIT_DISPATCH_ES2
+} piglit_dispatch_api;
+
+void piglit_dispatch_init(piglit_dispatch_api api,
+ piglit_get_core_proc_address_function_ptr get_core_proc,
+ piglit_get_ext_proc_address_function_ptr get_ext_proc,
+ piglit_error_function_ptr unsupported_proc,
+ piglit_error_function_ptr failure_proc);
+
+piglit_dispatch_function_ptr
+piglit_dispatch_resolve_function(const char *name);
+
+#include "generated_dispatch.h"
+
+void piglit_dispatch_default_init();
+
+/* Prevent gl.h from being included, since it will attempt to define
+ * the functions we've already defined.
+ */
+#define __gl_h_
+#define __gltypes_h_
+#define __glext_h_
+
+#ifdef __cplusplus
+} /* end extern "C" */
+#endif
+
+#endif /* __piglit_dispatch_h__ */
diff --git a/tests/util/piglit-util.h b/tests/util/piglit-util.h
index ea15150..dd293bb 100755
--- a/tests/util/piglit-util.h
+++ b/tests/util/piglit-util.h
@@ -34,7 +34,7 @@ extern "C" {
#endif
#if defined(_MSC_VER)
-typedef __int8 int8_t;
+typedef signed char int8_t;
typedef __int16 int16_t;
typedef __int32 int32_t;
typedef __int64 int64_t;
--
1.7.7.6
More information about the Piglit
mailing list