There's a useful feature buried in glapi to log all API calls to stderr.
Unfortunately it requires editing the code and then it's enabled
unconditionally for that build. This patch builds in API logging for
debug builds and makes it run-time switchable by setting MESA_DEBUG=dispatch.
_GLAPI_EXPORT extern const struct _glapi_table *_glapi_Dispatch;
_GLAPI_EXPORT extern const void *_glapi_Context;
-# define GET_DISPATCH() _glapi_tls_Dispatch
+# define GET_DISPATCH(t) _glapi_tls_Dispatch
# define GET_CURRENT_CONTEXT(C) GLcontext *C = (GLcontext *) _glapi_tls_Context
#else
_GLAPI_EXPORT unsigned long
_glthread_GetID(void);
+_GLAPI_EXPORT int
+_glapi_logging_available(void);
+
+_GLAPI_EXPORT void
+_glapi_enable_logging(void (*func)(void *data, const char *fmt, ...),
+ void *data);
/*
* These stubs are kept so that the old DRI drivers still load.
#include "glapi/glapitable.h"
#include "glapi/glapidispatch.h"
-
#if !(defined(USE_X86_ASM) || defined(USE_X86_64_ASM) || defined(USE_SPARC_ASM))
#if defined(WIN32)
#define NAME(func) gl##func
#endif
-#if 0 /* Use this to log GL calls to stdout (for DEBUG only!) */
-
-#define F stdout
-#define DISPATCH(FUNC, ARGS, MESSAGE) \
- fprintf MESSAGE; \
- CALL_ ## FUNC(GET_DISPATCH(), ARGS);
-
-#define RETURN_DISPATCH(FUNC, ARGS, MESSAGE) \
- fprintf MESSAGE; \
- return CALL_ ## FUNC(GET_DISPATCH(), ARGS);
-
-#else
-
#define DISPATCH(FUNC, ARGS, MESSAGE) \
CALL_ ## FUNC(GET_DISPATCH(), ARGS);
#define RETURN_DISPATCH(FUNC, ARGS, MESSAGE) \
return CALL_ ## FUNC(GET_DISPATCH(), ARGS);
-#endif /* logging */
-
#ifndef GLAPIENTRY
#define GLAPIENTRY
#include "glapi/glapitemp.h"
#endif /* USE_X86_ASM */
+
+
+#ifdef DEBUG
+
+static void *logger_data;
+static void (*logger_func)(void *data, const char *fmt, ...);
+static struct _glapi_table *real_dispatch; /* FIXME: This need to be TLS etc */
+
+#define KEYWORD1 static
+#define KEYWORD1_ALT static
+#define KEYWORD2
+#define NAME(func) log_##func
+#define F logger_data
+
+static void
+log_Unused(void)
+{
+}
+
+#define DISPATCH(FUNC, ARGS, MESSAGE) \
+ logger_func MESSAGE; \
+ CALL_ ## FUNC(real_dispatch, ARGS);
+
+#define RETURN_DISPATCH(FUNC, ARGS, MESSAGE) \
+ logger_func MESSAGE; \
+ return CALL_ ## FUNC(real_dispatch, ARGS);
+
+#define DISPATCH_TABLE_NAME __glapi_logging_table
+
+#define TABLE_ENTRY(func) (_glapi_proc) log_##func
+
+#include "glapi/glapitemp.h"
+
+int
+_glapi_logging_available(void)
+{
+ return 1;
+}
+
+void
+_glapi_enable_logging(void (*func)(void *data, const char *fmt, ...),
+ void *data)
+{
+ real_dispatch = GET_DISPATCH();
+ logger_func = func;
+ logger_data = data;
+ _glapi_set_dispatch(&__glapi_logging_table);
+}
+
+#else
+
+int
+_glapi_logging_available(void)
+{
+ return 0
+}
+
+void
+_glapi_enable_logging(void (*func)(void *data, const char *fmt, ...),
+ void *data)
+{
+}
+
+#endif
return 0;
}
+PUBLIC int
+_glapi_logging_available(void)
+{
+ return 0;
+}
+
+PUBLIC void
+_glapi_enable_logging(void (*func)(void *data, const char *fmt, ...),
+ void *data)
+{
+}
+
int main(int argc, char** argv)
{
void* p = __driDriverExtensions;
}
}
+static void
+dispatch_logger(void *data, const char *fmt, ...)
+{
+ va_list ap;
+
+ va_start(ap, fmt);
+ vfprintf(stderr, fmt, ap);
+ va_end(ap);
+}
+
+void
+_mesa_set_dispatch(void *table)
+{
+ if (table && (MESA_VERBOSE & VERBOSE_DISPATCH)) {
+ _glapi_set_dispatch(table);
+ _glapi_enable_logging(dispatch_logger, stderr);
+ } else {
+ _glapi_set_dispatch(table);
+ }
+}
/**
* Bind the given context to the given drawBuffer and readBuffer and
ASSERT(_mesa_get_current_context() == newCtx);
if (!newCtx) {
- _glapi_set_dispatch(NULL); /* none current */
+ _mesa_set_dispatch(NULL); /* none current */
}
else {
- _glapi_set_dispatch(newCtx->CurrentDispatch);
+ _mesa_set_dispatch(newCtx->CurrentDispatch);
if (drawBuffer && readBuffer) {
/* TODO: check if newCtx and buffer's visual match??? */
_mesa_make_current( GLcontext *ctx, GLframebuffer *drawBuffer,
GLframebuffer *readBuffer );
+extern void
+_mesa_set_dispatch(void *table);
+
extern GLboolean
_mesa_share_state(GLcontext *ctx, GLcontext *ctxToShare);
{ "lighting", VERBOSE_LIGHTING },
{ "disassem", VERBOSE_DISASSEM },
{ "draw", VERBOSE_DRAW },
- { "swap", VERBOSE_SWAPBUFFERS }
+ { "swap", VERBOSE_SWAPBUFFERS },
+ { "dispatch", VERBOSE_DISPATCH }
};
GLuint i;
MESA_VERBOSE |= debug_opt[i].flag;
}
+ if ((MESA_VERBOSE & VERBOSE_DISPATCH) && !_glapi_logging_available())
+ _mesa_debug(NULL, "dispatch logging not available in this buidl\n");
+
/* Debug flag:
*/
if (strstr(debug, "flush"))
ctx->Driver.NewList(ctx, name, mode);
ctx->CurrentDispatch = ctx->Save;
- _glapi_set_dispatch(ctx->CurrentDispatch);
+ _mesa_set_dispatch(ctx->CurrentDispatch);
}
ctx->CompileFlag = GL_FALSE;
ctx->CurrentDispatch = ctx->Exec;
- _glapi_set_dispatch(ctx->CurrentDispatch);
+ _mesa_set_dispatch(ctx->CurrentDispatch);
}
/* also restore API function pointers to point to "save" versions */
if (save_compile_flag) {
ctx->CurrentDispatch = ctx->Save;
- _glapi_set_dispatch(ctx->CurrentDispatch);
+ _mesa_set_dispatch(ctx->CurrentDispatch);
}
}
/* also restore API function pointers to point to "save" versions */
if (save_compile_flag) {
ctx->CurrentDispatch = ctx->Save;
- _glapi_set_dispatch(ctx->CurrentDispatch);
+ _mesa_set_dispatch(ctx->CurrentDispatch);
}
}
VERBOSE_VERTS = 0x0800,
VERBOSE_DISASSEM = 0x1000,
VERBOSE_DRAW = 0x2000,
- VERBOSE_SWAPBUFFERS = 0x4000
+ VERBOSE_SWAPBUFFERS = 0x4000,
+ VERBOSE_DISPATCH = 0x8000
};