[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