[Mesa-dev] [PATCH 06/11] mesa: add some GL_ARB_debug_output functions

Brian Paul brianp at vmware.com
Tue May 3 16:35:24 PDT 2011


On 05/02/2011 05:00 PM, nobled wrote:
> They're not actually exported yet.
> ---
>   src/mesa/main/api_exec.c |   12 ++-
>   src/mesa/main/errors.c   |  262 ++++++++++++++++++++++++++++++++++++++++++++++
>   src/mesa/main/errors.h   |    4 +
>   3 files changed, 274 insertions(+), 4 deletions(-)
>
> diff --git a/src/mesa/main/api_exec.c b/src/mesa/main/api_exec.c
> index 93214dd..dbbed56 100644
> --- a/src/mesa/main/api_exec.c
> +++ b/src/mesa/main/api_exec.c
> @@ -57,6 +57,7 @@
>   #include "drawpix.h"
>   #include "rastpos.h"
>   #include "enable.h"
> +#include "errors.h"
>   #include "eval.h"
>   #include "get.h"
>   #include "feedback.h"
> @@ -600,15 +601,18 @@ _mesa_create_exec_table(void)
>      SET_DrawBuffersARB(exec, _mesa_DrawBuffersARB);
>   #endif
>
> -   /* ARB 104. GL_ARB_robustness */
> +   /* ARB 66. GL_ARB_sync */
> +   _mesa_init_sync_dispatch(exec);
> +
> +   /* ARB 104. GL_ARB_debug_output */
> +   _mesa_init_errors_dispatch(exec);
> +
> +   /* ARB 105. GL_ARB_robustness */
>      SET_GetGraphicsResetStatusARB(exec, _mesa_GetGraphicsResetStatusARB);
>      SET_GetnPolygonStippleARB(exec, _mesa_GetnPolygonStippleARB);
>      SET_GetnTexImageARB(exec, _mesa_GetnTexImageARB);
>      SET_ReadnPixelsARB(exec, _mesa_ReadnPixelsARB);
>
> -   /* GL_ARB_sync */
> -   _mesa_init_sync_dispatch(exec);
> -
>     /* GL_ATI_fragment_shader */
>      _mesa_init_ati_fragment_shader_dispatch(exec);
>
> diff --git a/src/mesa/main/errors.c b/src/mesa/main/errors.c
> index bb6270b..c953fbf 100644
> --- a/src/mesa/main/errors.c
> +++ b/src/mesa/main/errors.c
> @@ -38,6 +38,268 @@
>
>   #define MAXSTRING _MESA_MAX_DEBUG_MESSAGE_LENGTH
>
> +
> +static char out_of_memory[] = "Debugging error: out of memory";
> +
> +/* 'buf' is not necessarily a null-terminated string. When logging, copy
> + * 'len' characters from it, store them in a new, null-terminated string,
> + * and remember the number of bytes used by that string, *including*
> + * the null terminator this time.
> + */

I don't think anyone's running doxygen on a regular basis, but to stay 
consistant with the rest of core Mesa, the function comment should 
look more like this:

/**
  * 'buf' is not necessarily...
  */


> +static void
> +_mesa_log_msg(struct gl_context *ctx, GLenum source, GLenum type,
> +              GLuint id, GLenum severity, GLint len, const char *buf)
> +{
> +   GLint nextEmpty;
> +   struct gl_debug_msg *emptySlot;
> +
> +   assert(len>= 0&&  len<  _MESA_MAX_DEBUG_MESSAGE_LENGTH);
> +
> +   if (ctx->Debug.Callback) {
> +      ctx->Debug.Callback(source, type, id, severity,
> +                          len, buf, ctx->Debug.CallbackData);
> +      return;
> +   }
> +
> +   if (ctx->Debug.NumMessages == _MESA_MAX_DEBUG_LOGGED_MESSAGES)
> +      return;
> +
> +   nextEmpty = (ctx->Debug.NextMsg + ctx->Debug.NumMessages)
> +                          % _MESA_MAX_DEBUG_LOGGED_MESSAGES;
> +   emptySlot =&ctx->Debug.Log[nextEmpty];
> +
> +   assert(!emptySlot->message&&  !emptySlot->length);
> +
> +   emptySlot->message = MALLOC(len+1);
> +   if (emptySlot->message) {
> +      (void) strncpy(emptySlot->message, buf, (size_t)len);
> +      emptySlot->message[len] = '\0';
> +
> +      emptySlot->length = len+1;
> +      emptySlot->source = source;
> +      emptySlot->type = type;
> +      emptySlot->id = id;
> +      emptySlot->severity = severity;
> +   } else {
> +      /* malloc failed! */
> +      emptySlot->message = out_of_memory;
> +      emptySlot->length = strlen(out_of_memory)+1;
> +      emptySlot->source = GL_DEBUG_SOURCE_OTHER_ARB;
> +      emptySlot->type = GL_DEBUG_TYPE_ERROR_ARB;
> +      emptySlot->id = 1; /* TODO: proper id namespace */
> +      emptySlot->severity = GL_DEBUG_SEVERITY_HIGH_ARB;
> +   }
> +
> +   if (ctx->Debug.NumMessages == 0)
> +      ctx->Debug.NextMsgLength = ctx->Debug.Log[ctx->Debug.NextMsg].length;
> +
> +   ctx->Debug.NumMessages++;
> +}
> +
> +/** Pop the oldest debug message out of the log.
> + *  Writes the message string, including the null terminator, into 'buf',
> + *  using up to 'bufSize' bytes. If 'bufSize' is too small, or
> + *  if 'buf' is NULL, nothing is written.
> + *
> + *  Returns the number of bytes written on success, or when 'buf' is NULL,
> + *  the number that would have been written. A return value of 0
> + *  indicates failure.
> + */
> +static GLsizei
> +_mesa_get_msg(struct gl_context *ctx, GLenum *source, GLenum *type,
> +              GLuint *id, GLenum *severity, GLsizei bufSize, char *buf)
> +{
> +   struct gl_debug_msg *msg;
> +   GLsizei length;
> +
> +   if (ctx->Debug.NumMessages == 0)
> +      return 0;
> +
> +   msg =&ctx->Debug.Log[ctx->Debug.NextMsg];
> +   length = msg->length;
> +
> +   assert(length>  0&&  length == ctx->Debug.NextMsgLength);
> +
> +   if (bufSize<  length&&  buf != NULL)
> +      return 0;
> +
> +   if (severity)
> +      *severity = msg->severity;
> +   if (source)
> +      *source = msg->source;
> +   if (type)
> +      *type = msg->type;
> +   if (id)
> +      *id = msg->id;
> +
> +   if (buf) {
> +      assert(msg->message[length-1] == '\0');
> +      (void) strncpy(buf, msg->message, (size_t)length);
> +   }
> +
> +   if (msg->message != (char*)out_of_memory)
> +      FREE(msg->message);
> +   msg->message = NULL;
> +   msg->length = 0;
> +
> +   ctx->Debug.NumMessages--;
> +   ctx->Debug.NextMsg++;
> +   ctx->Debug.NextMsg %= _MESA_MAX_DEBUG_LOGGED_MESSAGES;
> +   ctx->Debug.NextMsgLength = ctx->Debug.Log[ctx->Debug.NextMsg].length;
> +
> +   return length;
> +}
> +
> +static GLboolean
> +validate_params(struct gl_context *ctx, unsigned caller,
> +                GLenum source, GLenum type, GLenum severity)
> +{
> +#define INSERT 1
> +#define CONTROL 2
> +   switch(source) {
> +      case GL_DEBUG_SOURCE_APPLICATION_ARB:
> +      case GL_DEBUG_SOURCE_THIRD_PARTY_ARB:
> +         break;
> +      case GL_DEBUG_SOURCE_API_ARB:
> +      case GL_DEBUG_SOURCE_SHADER_COMPILER_ARB:
> +      case GL_DEBUG_SOURCE_WINDOW_SYSTEM_ARB:
> +      case GL_DEBUG_SOURCE_OTHER_ARB:
> +         if (caller != INSERT)
> +            break;
> +      case GL_DONT_CARE:
> +         if (caller == CONTROL)
> +            break;
> +      default:
> +         goto error;
> +   }
> +   switch(type) {
> +      case GL_DEBUG_TYPE_ERROR_ARB:
> +      case GL_DEBUG_TYPE_DEPRECATED_BEHAVIOR_ARB:
> +      case GL_DEBUG_TYPE_UNDEFINED_BEHAVIOR_ARB:
> +      case GL_DEBUG_TYPE_PERFORMANCE_ARB:
> +      case GL_DEBUG_TYPE_PORTABILITY_ARB:
> +      case GL_DEBUG_TYPE_OTHER_ARB:
> +         break;
> +      case GL_DONT_CARE:
> +         if (caller == CONTROL)
> +            break;
> +      default:
> +         goto error;
> +   }
> +   switch(severity) {
> +      case GL_DEBUG_SEVERITY_HIGH_ARB:
> +      case GL_DEBUG_SEVERITY_MEDIUM_ARB:
> +      case GL_DEBUG_SEVERITY_LOW_ARB:
> +         break;
> +      case GL_DONT_CARE:
> +         if (caller == CONTROL)
> +            break;
> +      default:
> +         goto error;
> +   }
> +   return GL_TRUE;
> +
> +error:
> +   {
> +      const char *callerstr;
> +      if (caller == INSERT)
> +         callerstr = "glDebugMessageInsertARB";
> +      else if (caller == CONTROL)
> +         callerstr = "glDebugMessageControlARB";
> +      else
> +         return GL_FALSE;
> +
> +      _mesa_error( ctx, GL_INVALID_ENUM, "bad values passed to %s"
> +                  "(source=0x%x, type=0x%x, severity=0x%x)", callerstr,
> +                  source, type, severity);
> +   }
> +   return GL_FALSE;
> +}
> +
> +static void GLAPIENTRY
> +_mesa_DebugMessageInsertARB(GLenum source, GLenum type, GLuint id,
> +                            GLenum severity, GLint length,
> +                            const GLcharARB* buf)
> +{
> +   GET_CURRENT_CONTEXT(ctx);
> +
> +   if (!validate_params(ctx, INSERT, source, type, severity))
> +      return; /* GL_INVALID_ENUM */
> +
> +   if (length<  0)
> +      length = strlen(buf);
> +
> +   if (length>= _MESA_MAX_DEBUG_MESSAGE_LENGTH) {
> +      _mesa_error(ctx, GL_INVALID_VALUE, "glDebugMessageInsertARB"
> +                 "(length=%d, which is not less than "
> +                 "GL_MAX_DEBUG_MESSAGE_LENGTH_ARB=%d)", length,
> +                 _MESA_MAX_DEBUG_MESSAGE_LENGTH);
> +      return;
> +   }
> +
> +   _mesa_log_msg(ctx, source, type, id, severity, length, buf);
> +}
> +
> +static GLuint GLAPIENTRY
> +_mesa_GetDebugMessageLogARB(GLuint count, GLsizei logSize, GLenum* sources,
> +                            GLenum* types, GLenum* ids, GLenum* severities,
> +                            GLsizei* lengths, GLcharARB* messageLog)
> +{
> +   GET_CURRENT_CONTEXT(ctx);
> +   GLuint ret;
> +
> +   if (!messageLog)
> +      logSize = 0;
> +
> +   if (logSize<  0) {
> +      _mesa_error(ctx, GL_INVALID_VALUE, "glGetDebugMessageLogARB"
> +                 "(logSize=%d : logSize must not be negative)", logSize);
> +      return 0;
> +   }
> +
> +   for (ret = 0; ret<  count; ret++) {
> +      GLsizei written = _mesa_get_msg(ctx, sources, types, ids, severities,
> +                                      logSize, messageLog);
> +      if (!written)
> +         break;
> +
> +      if (messageLog) {
> +         messageLog += written;
> +         logSize -= written;
> +      }
> +      if (lengths) {
> +         *lengths = written;
> +         lengths++;
> +      }
> +
> +      if (severities) severities++;
> +      if (sources) sources++;
> +      if (types) types++;
> +      if (ids) ids++;

I'd prefer to see these as

    if (severities)
       severities++;

etc.  It's not a big deal here, but other times this is really 
important so that you can set a debugger breakpoint on the increment 
statement.


> +   }
> +
> +   return ret;
> +}
> +
> +static void GLAPIENTRY
> +_mesa_DebugMessageCallbackARB(GLDEBUGPROCARB callback, GLvoid* userParam)
> +{
> +   GET_CURRENT_CONTEXT(ctx);
> +   ctx->Debug.Callback = callback;
> +   ctx->Debug.CallbackData = userParam;
> +}
> +
> +void
> +_mesa_init_errors_dispatch(struct _glapi_table *disp)
> +{
> +#if 0
> +   SET_DebugMessageCallbackARB(disp, _mesa_DebugMessageCallbackARB);
> +   SET_DebugMessageControlARB(disp, _mesa_DebugMessageControlARB);
> +   SET_DebugMessageInsertARB(disp, _mesa_DebugMessageInsertARB);
> +   SET_GetDebugMessageLogARB(disp, _mesa_GetDebugMessageLogARB);
> +#endif
> +}
> +
>   void
>   _mesa_init_errors(struct gl_context *ctx)
>   {
> diff --git a/src/mesa/main/errors.h b/src/mesa/main/errors.h
> index e467f5d..6ab9b5e 100644
> --- a/src/mesa/main/errors.h
> +++ b/src/mesa/main/errors.h
> @@ -44,9 +44,13 @@
>   extern "C" {
>   #endif
>
> +struct _glapi_table;
>   struct gl_context;
>
>   extern void
> +_mesa_init_errors_dispatch(struct _glapi_table *disp);
> +
> +extern void
>   _mesa_init_errors( struct gl_context *ctx );
>
>   extern void
>
>
>
> _______________________________________________
> mesa-dev mailing list
> mesa-dev at lists.freedesktop.org
> http://lists.freedesktop.org/mailman/listinfo/mesa-dev



More information about the mesa-dev mailing list