[Mesa-dev] [PATCH 1/4] mapi: add new _glapi_new_nop_table() and _glapi_set_nop_handler()

Brian Paul brianp at vmware.com
Tue Mar 17 19:35:20 PDT 2015


Ping - on this series.

-Brian

On 03/13/2015 01:22 PM, Brian Paul wrote:
> _glapi_new_nop_table() creates a new dispatch table populated with
> pointers to no-op functions.
>
> _glapi_set_nop_handler() is used to register a callback function which
> will be called from each of the no-op functions.
>
> Now we always generate a separate no-op function for each GL entrypoint.
> This allows us to do proper stack clean-up for Windows __stdcall and
> lets us report the actual function name in error messages.  Before this
> change, for non-Windows release builds we used a single no-op function
> for all entrypoints.
> ---
>   src/mapi/glapi/glapi.h     | 11 ++++++
>   src/mapi/glapi/glapi_nop.c | 84 ++++++++++++++++++++++++++--------------------
>   src/mapi/mapi_glapi.c      | 23 +++++++++++++
>   src/mapi/table.c           | 23 ++++++++++---
>   src/mapi/table.h           |  8 +++++
>   5 files changed, 108 insertions(+), 41 deletions(-)
>
> diff --git a/src/mapi/glapi/glapi.h b/src/mapi/glapi/glapi.h
> index 8d991fb..673295b 100644
> --- a/src/mapi/glapi/glapi.h
> +++ b/src/mapi/glapi/glapi.h
> @@ -80,6 +80,9 @@ extern "C" {
>   #endif
>
>   typedef void (*_glapi_proc)(void);
> +
> +typedef void (*_glapi_nop_handler_proc)(const char *name);
> +
>   struct _glapi_table;
>
>
> @@ -159,6 +162,14 @@ _GLAPI_EXPORT struct _glapi_table *
>   _glapi_create_table_from_handle(void *handle, const char *symbol_prefix);
>
>
> +_GLAPI_EXPORT void
> +_glapi_set_nop_handler(_glapi_nop_handler_proc func);
> +
> +/** Return pointer to new dispatch table filled with no-op functions */
> +_GLAPI_EXPORT struct _glapi_table *
> +_glapi_new_nop_table(unsigned num_entries);
> +
> +
>   /** Deprecated function */
>   _GLAPI_EXPORT unsigned long
>   _glthread_GetID(void);
> diff --git a/src/mapi/glapi/glapi_nop.c b/src/mapi/glapi/glapi_nop.c
> index 628276e..0041ed5 100644
> --- a/src/mapi/glapi/glapi_nop.c
> +++ b/src/mapi/glapi/glapi_nop.c
> @@ -30,14 +30,21 @@
>    * This file defines a special dispatch table which is loaded with no-op
>    * functions.
>    *
> - * When there's no current rendering context, calling a GL function like
> - * glBegin() is a no-op.  Apps should never normally do this.  So as a
> - * debugging aid, each of the no-op functions will emit a warning to
> - * stderr if the MESA_DEBUG or LIBGL_DEBUG env var is set.
> + * Mesa can register a "no-op handler function" which will be called in
> + * the event that a no-op function is called.
> + *
> + * In the past, the dispatch table was loaded with pointers to a single
> + * no-op function.  But that broke on Windows because the GL entrypoints
> + * use __stdcall convention.  __stdcall means the callee cleans up the
> + * stack.  So one no-op function can't properly clean up the stack.  This
> + * would lead to crashes.
> + *
> + * Another benefit of unique no-op functions is we can accurately report
> + * the function's name in an error message.
>    */
>
>
> -
> +#include <string.h>
>   #include "glapi/glapi_priv.h"
>
>
> @@ -51,25 +58,32 @@ _glapi_set_warning_func(_glapi_proc func)
>   {
>   }
>
> -/*
> - * When GLAPIENTRY is __stdcall (i.e. Windows), the stack is popped by the
> - * callee making the number/type of arguments significant.
> +
> +/**
> + * We'll jump though this function pointer whenever a no-op function
> + * is called.
>    */
> -#if defined(_WIN32) || defined(DEBUG)
> +static _glapi_nop_handler_proc nop_handler = NULL;
> +
> +
> +/**
> + * Register the no-op handler call-back function.
> + */
> +void
> +_glapi_set_nop_handler(_glapi_nop_handler_proc func)
> +{
> +   nop_handler = func;
> +}
> +
>
>   /**
>    * Called by each of the no-op GL entrypoints.
>    */
> -static int
> -Warn(const char *func)
> +static void
> +nop(const char *func)
>   {
> -#if defined(DEBUG)
> -   if (getenv("MESA_DEBUG") || getenv("LIBGL_DEBUG")) {
> -      fprintf(stderr, "GL User Error: gl%s called without a rendering context\n",
> -              func);
> -   }
> -#endif
> -   return 0;
> +   if (nop_handler)
> +      nop_handler(func);
>   }
>
>
> @@ -79,7 +93,8 @@ Warn(const char *func)
>   static GLint
>   NoOpUnused(void)
>   {
> -   return Warn(" function");
> +   nop("unused GL entry point");
> +   return 0;
>   }
>
>   /*
> @@ -89,31 +104,28 @@ NoOpUnused(void)
>   #define KEYWORD1_ALT static
>   #define KEYWORD2 GLAPIENTRY
>   #define NAME(func)  NoOp##func
> -#define DISPATCH(func, args, msg)  Warn(#func);
> -#define RETURN_DISPATCH(func, args, msg)  Warn(#func); return 0
> +#define DISPATCH(func, args, msg)  nop(#func);
> +#define RETURN_DISPATCH(func, args, msg)  nop(#func); return 0
>
>
>   /*
>    * Defines for the table of no-op entry points.
>    */
>   #define TABLE_ENTRY(name) (_glapi_proc) NoOp##name
> +#define DISPATCH_TABLE_NAME __glapi_noop_table
> +#define UNUSED_TABLE_NAME __unused_noop_functions
> +
> +#include "glapi/glapitemp.h"
>
> -#else
>
> -static int
> -NoOpGeneric(void)
> +/** Return pointer to new dispatch table filled with no-op functions */
> +struct _glapi_table *
> +_glapi_new_nop_table(unsigned num_entries)
>   {
> -   if (getenv("MESA_DEBUG") || getenv("LIBGL_DEBUG")) {
> -      fprintf(stderr, "GL User Error: calling GL function without a rendering context\n");
> +   struct _glapi_table *table = malloc(num_entries * sizeof(_glapi_proc));
> +   if (table) {
> +      memcpy(table, __glapi_noop_table,
> +             num_entries * sizeof(_glapi_proc));
>      }
> -   return 0;
> +   return table;
>   }
> -
> -#define TABLE_ENTRY(name) (_glapi_proc) NoOpGeneric
> -
> -#endif
> -
> -#define DISPATCH_TABLE_NAME __glapi_noop_table
> -#define UNUSED_TABLE_NAME __unused_noop_functions
> -
> -#include "glapi/glapitemp.h"
> diff --git a/src/mapi/mapi_glapi.c b/src/mapi/mapi_glapi.c
> index 127dfaf..70605f3 100644
> --- a/src/mapi/mapi_glapi.c
> +++ b/src/mapi/mapi_glapi.c
> @@ -27,6 +27,7 @@
>    */
>
>   #include <string.h>
> +#include <stdlib.h>
>   #include "glapi/glapi.h"
>   #include "u_current.h"
>   #include "table.h" /* for MAPI_TABLE_NUM_SLOTS */
> @@ -222,6 +223,28 @@ _glapi_get_proc_name(unsigned int offset)
>      return stub ? stub_get_name(stub) : NULL;
>   }
>
> +/** Return pointer to new dispatch table filled with no-op functions */
> +struct _glapi_table *
> +_glapi_new_nop_table(unsigned num_entries)
> +{
> +   struct _glapi_table *table;
> +
> +   if (num_entries > MAPI_TABLE_NUM_SLOTS)
> +      num_entries = MAPI_TABLE_NUM_SLOTS;
> +
> +   table = malloc(num_entries * sizeof(mapi_func));
> +   if (table) {
> +      memcpy(table, table_noop_array, num_entries * sizeof(mapi_func));
> +   }
> +   return table;
> +}
> +
> +void
> +_glapi_set_nop_handler(_glapi_nop_handler_proc func)
> +{
> +   table_set_noop_handler(func);
> +}
> +
>   /**
>    * This is a deprecated function which should not be used anymore.
>    * It's only present to satisfy linking with older versions of libGL.
> diff --git a/src/mapi/table.c b/src/mapi/table.c
> index 0d28666..7487501 100644
> --- a/src/mapi/table.c
> +++ b/src/mapi/table.c
> @@ -30,16 +30,29 @@
>
>   #include "table.h"
>
> +static nop_handler_proc nop_handler = NULL;
> +
> +void
> +table_set_noop_handler(nop_handler_proc func)
> +{
> +   nop_handler = func;
> +}
> +
>   static void
>   noop_warn(const char *name)
>   {
> -   static int debug = -1;
> +   if (nop_handler) {
> +      nop_handler(name);
> +   }
> +   else {
> +      static int debug = -1;
>
> -   if (debug < 0)
> -      debug = (getenv("MESA_DEBUG") || getenv("LIBGL_DEBUG"));
> +      if (debug < 0)
> +         debug = (getenv("MESA_DEBUG") || getenv("LIBGL_DEBUG"));
>
> -   if (debug)
> -      fprintf(stderr, "%s is no-op\n", name);
> +      if (debug)
> +         fprintf(stderr, "%s is no-op\n", name);
> +   }
>   }
>
>   static int
> diff --git a/src/mapi/table.h b/src/mapi/table.h
> index e2d6ef0..a1af40c 100644
> --- a/src/mapi/table.h
> +++ b/src/mapi/table.h
> @@ -41,6 +41,14 @@ struct mapi_table;
>
>   extern const mapi_func table_noop_array[];
>
> +
> +typedef void (*nop_handler_proc)(const char *name);
> +
> +
> +void
> +table_set_noop_handler(nop_handler_proc func);
> +
> +
>   /**
>    * Get the no-op dispatch table.
>    */
>



More information about the mesa-dev mailing list