[Piglit] [PATCH v2 09/13] piglit-dispatch: Remaining infrastructure.

Paul Berry stereotype441 at gmail.com
Mon Mar 12 14:41:43 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.
---
 tests/util/piglit-dispatch-init.c |  122 +++++++++++++++++++
 tests/util/piglit-dispatch.c      |  238 +++++++++++++++++++++++++++++++++++++
 tests/util/piglit-dispatch.h      |  149 +++++++++++++++++++++++
 3 files changed, 509 insertions(+), 0 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..069475f
--- /dev/null
+++ b/tests/util/piglit-dispatch-init.c
@@ -0,0 +1,122 @@
+/* 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"
+#include "glxew.h"
+
+#ifdef __APPLE__
+#include <stdlib.h>
+#include <string.h>
+#include <AvailabilityMacros.h>
+#include <dlfcn.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);
+}
+
+/**
+ * Generated code calls this function to retrieve the address of a
+ * function from the implementation.
+ *
+ * For the moment we only support GLX and Apple.  In the future there
+ * will be versions of this function for EGL and Windows.
+ */
+static piglit_dispatch_function_ptr
+default_get_proc_address(const char *function_name)
+{
+#ifdef __APPLE__
+
+	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);
+
+#else /* Linux */
+
+	/* TODO: support stuff other than GLX */
+	return glXGetProcAddressARB((const GLubyte *) 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,
+			     default_get_proc_address,
+			     default_get_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..96443b2
--- /dev/null
+++ b/tests/util/piglit-dispatch.c
@@ -0,0 +1,238 @@
+/* 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"
+
+/* Global state maintained by the Piglit dispatch mechanism: */
+
+/**
+ * Which function to call to get the address of a core function.
+ */
+static piglit_get_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_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)
+{
+	void *function_pointer = __get_core_proc_address(name);
+	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)
+{
+	void *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.
+ *
+ * - 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.
+ *
+ * - 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()).
+ *
+ * - 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.
+ *
+ * - 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_proc_address_function_ptr get_core_proc,
+		     piglit_get_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;
+
+	initialize_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..55d9101
--- /dev/null
+++ b/tests/util/piglit-dispatch.h
@@ -0,0 +1,149 @@
+/* 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
+
+/* APIENTRY and GLAPIENTRY are not used on Linux or Mac. */
+#define APIENTRY
+#define GLAPIENTRY
+
+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_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_proc_address_function_ptr get_core_proc,
+			  piglit_get_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__ */
-- 
1.7.7.6



More information about the Piglit mailing list