mesa: use accessors for struct gl_debug_state

When GL_DEBUG_OUTPUT_SYNCHRONOUS is GL_TRUE, drivers are allowed to log debug
messages from other threads.  That requires gl_debug_state to be protected by
a mutex, even when it is a context state.  While we do not spawn threads in
Mesa yet, this commit makes it easier to do when we want to.

Since the definition of struct gl_debug_state is no longer needed by the rest
of the driver, move it to main/errors.c.  This should make it even harder to
use the struct incorrectly.

v2: add comments for the accessors

Signed-off-by: Chia-I Wu <olv@lunarg.com>
Reviewed-by: Brian Paul <brianp@vmware.com>
This commit is contained in:
Chia-I Wu
2014-04-22 14:22:49 +08:00
parent 94e45c98e1
commit cf61ea3029
8 changed files with 156 additions and 108 deletions

View File

@@ -449,10 +449,7 @@ driContextSetFlags(struct gl_context *ctx, uint32_t flags)
if ((flags & __DRI_CTX_FLAG_FORWARD_COMPATIBLE) != 0) if ((flags & __DRI_CTX_FLAG_FORWARD_COMPATIBLE) != 0)
ctx->Const.ContextFlags |= GL_CONTEXT_FLAG_FORWARD_COMPATIBLE_BIT; ctx->Const.ContextFlags |= GL_CONTEXT_FLAG_FORWARD_COMPATIBLE_BIT;
if ((flags & __DRI_CTX_FLAG_DEBUG) != 0) { if ((flags & __DRI_CTX_FLAG_DEBUG) != 0) {
struct gl_debug_state *debug = _mesa_get_debug_state(ctx); _mesa_set_debug_state_int(ctx, GL_DEBUG_OUTPUT, GL_TRUE);
if (debug) {
debug->DebugOutput = GL_TRUE;
}
ctx->Const.ContextFlags |= GL_CONTEXT_FLAG_DEBUG_BIT; ctx->Const.ContextFlags |= GL_CONTEXT_FLAG_DEBUG_BIT;
} }
} }

View File

@@ -368,26 +368,11 @@ _mesa_set_enable(struct gl_context *ctx, GLenum cap, GLboolean state)
ctx->Depth.Test = state; ctx->Depth.Test = state;
break; break;
case GL_DEBUG_OUTPUT: case GL_DEBUG_OUTPUT:
if (!_mesa_is_desktop_gl(ctx)) {
goto invalid_enum_error;
}
else {
struct gl_debug_state *debug = _mesa_get_debug_state(ctx);
if (debug) {
debug->DebugOutput = state;
}
}
break;
case GL_DEBUG_OUTPUT_SYNCHRONOUS_ARB: case GL_DEBUG_OUTPUT_SYNCHRONOUS_ARB:
if (!_mesa_is_desktop_gl(ctx)) { if (!_mesa_is_desktop_gl(ctx))
goto invalid_enum_error; goto invalid_enum_error;
} else
else { _mesa_set_debug_state_int(ctx, cap, state);
struct gl_debug_state *debug = _mesa_get_debug_state(ctx);
if (debug) {
debug->SyncOutput = state;
}
}
break; break;
case GL_DITHER: case GL_DITHER:
if (ctx->Color.DitherFlag == state) if (ctx->Color.DitherFlag == state)
@@ -1239,21 +1224,11 @@ _mesa_IsEnabled( GLenum cap )
case GL_CULL_FACE: case GL_CULL_FACE:
return ctx->Polygon.CullFlag; return ctx->Polygon.CullFlag;
case GL_DEBUG_OUTPUT: case GL_DEBUG_OUTPUT:
if (!_mesa_is_desktop_gl(ctx))
goto invalid_enum_error;
if (ctx->Debug) {
return ctx->Debug->DebugOutput;
} else {
return GL_FALSE;
}
case GL_DEBUG_OUTPUT_SYNCHRONOUS_ARB: case GL_DEBUG_OUTPUT_SYNCHRONOUS_ARB:
if (!_mesa_is_desktop_gl(ctx)) if (!_mesa_is_desktop_gl(ctx))
goto invalid_enum_error; goto invalid_enum_error;
if (ctx->Debug) { else
return ctx->Debug->SyncOutput; return (GLboolean) _mesa_get_debug_state_int(ctx, cap);
} else {
return GL_FALSE;
}
case GL_DEPTH_TEST: case GL_DEPTH_TEST:
return ctx->Depth.Test; return ctx->Depth.Test;
case GL_DITHER: case GL_DITHER:

View File

@@ -47,6 +47,45 @@ struct gl_debug_severity
GLuint ID; GLuint ID;
}; };
/**
* An error, warning, or other piece of debug information for an application
* to consume via GL_ARB_debug_output/GL_KHR_debug.
*/
struct gl_debug_msg
{
enum mesa_debug_source source;
enum mesa_debug_type type;
GLuint id;
enum mesa_debug_severity severity;
GLsizei length;
GLcharARB *message;
};
struct gl_debug_namespace
{
struct _mesa_HashTable *IDs;
unsigned ZeroID; /* a HashTable won't take zero, so store its state here */
/** lists of IDs in the hash table at each severity */
struct simple_node Severity[MESA_DEBUG_SEVERITY_COUNT];
};
struct gl_debug_state
{
GLDEBUGPROC Callback;
const void *CallbackData;
GLboolean SyncOutput;
GLboolean DebugOutput;
GLboolean Defaults[MAX_DEBUG_GROUP_STACK_DEPTH][MESA_DEBUG_SEVERITY_COUNT][MESA_DEBUG_SOURCE_COUNT][MESA_DEBUG_TYPE_COUNT];
struct gl_debug_namespace Namespaces[MAX_DEBUG_GROUP_STACK_DEPTH][MESA_DEBUG_SOURCE_COUNT][MESA_DEBUG_TYPE_COUNT];
struct gl_debug_msg Log[MAX_DEBUG_LOGGED_MESSAGES];
struct gl_debug_msg DebugGroupMsgs[MAX_DEBUG_GROUP_STACK_DEPTH];
GLint GroupStackDepth;
GLint NumMessages;
GLint NextMsg;
GLint NextMsgLength; /* redundant, but copied here from Log[NextMsg].length
for the sake of the offsetof() code in get.c */
};
static char out_of_memory[] = "Debugging error: out of memory"; static char out_of_memory[] = "Debugging error: out of memory";
static const GLenum debug_source_enums[] = { static const GLenum debug_source_enums[] = {
@@ -597,7 +636,7 @@ debug_pop_group(struct gl_debug_state *debug)
* Return debug state for the context. The debug state will be allocated * Return debug state for the context. The debug state will be allocated
* and initialized upon the first call. * and initialized upon the first call.
*/ */
struct gl_debug_state * static struct gl_debug_state *
_mesa_get_debug_state(struct gl_context *ctx) _mesa_get_debug_state(struct gl_context *ctx)
{ {
if (!ctx->Debug) { if (!ctx->Debug) {
@@ -610,6 +649,102 @@ _mesa_get_debug_state(struct gl_context *ctx)
return ctx->Debug; return ctx->Debug;
} }
/**
* Set the integer debug state specified by \p pname. This can be called from
* _mesa_set_enable for example.
*/
bool
_mesa_set_debug_state_int(struct gl_context *ctx, GLenum pname, GLint val)
{
struct gl_debug_state *debug = _mesa_get_debug_state(ctx);
if (!debug)
return false;
switch (pname) {
case GL_DEBUG_OUTPUT:
debug->DebugOutput = (val != 0);
break;
case GL_DEBUG_OUTPUT_SYNCHRONOUS_ARB:
debug->SyncOutput = (val != 0);
break;
default:
assert(!"unknown debug output param");
break;
}
return true;
}
/**
* Query the integer debug state specified by \p pname. This can be called
* _mesa_GetIntegerv for example.
*/
GLint
_mesa_get_debug_state_int(struct gl_context *ctx, GLenum pname)
{
struct gl_debug_state *debug;
GLint val;
debug = ctx->Debug;
if (!debug)
return 0;
switch (pname) {
case GL_DEBUG_OUTPUT:
val = debug->DebugOutput;
break;
case GL_DEBUG_OUTPUT_SYNCHRONOUS_ARB:
val = debug->SyncOutput;
break;
case GL_DEBUG_LOGGED_MESSAGES:
val = debug->NumMessages;
break;
case GL_DEBUG_NEXT_LOGGED_MESSAGE_LENGTH:
val = debug->NextMsgLength;
break;
case GL_DEBUG_GROUP_STACK_DEPTH:
val = debug->GroupStackDepth;
break;
default:
assert(!"unknown debug output param");
val = 0;
break;
}
return val;
}
/**
* Query the pointer debug state specified by \p pname. This can be called
* _mesa_GetPointerv for example.
*/
void *
_mesa_get_debug_state_ptr(struct gl_context *ctx, GLenum pname)
{
struct gl_debug_state *debug;
void *val;
debug = ctx->Debug;
if (!debug)
return NULL;
switch (pname) {
case GL_DEBUG_CALLBACK_FUNCTION_ARB:
val = (void *) debug->Callback;
break;
case GL_DEBUG_CALLBACK_USER_PARAM_ARB:
val = (void *) debug->CallbackData;
break;
default:
assert(!"unknown debug output param");
val = NULL;
break;
}
return val;
}
/** /**
* Log a client or driver debug message. * Log a client or driver debug message.

View File

@@ -83,8 +83,14 @@ _mesa_gl_debug(struct gl_context *ctx,
} \ } \
} while (0) } while (0)
struct gl_debug_state * bool
_mesa_get_debug_state(struct gl_context *ctx); _mesa_set_debug_state_int(struct gl_context *ctx, GLenum pname, GLint val);
GLint
_mesa_get_debug_state_int(struct gl_context *ctx, GLenum pname);
void *
_mesa_get_debug_state_ptr(struct gl_context *ctx, GLenum pname);
extern void extern void
_mesa_shader_debug(struct gl_context *ctx, GLenum type, GLuint *id, _mesa_shader_debug(struct gl_context *ctx, GLenum type, GLuint *id,

View File

@@ -989,24 +989,10 @@ find_custom_value(struct gl_context *ctx, const struct value_desc *d, union valu
break; break;
/* GL_KHR_DEBUG */ /* GL_KHR_DEBUG */
case GL_DEBUG_LOGGED_MESSAGES: case GL_DEBUG_LOGGED_MESSAGES:
{
struct gl_debug_state *debug = _mesa_get_debug_state(ctx);
v->value_int = debug ? debug->NumMessages : 0;
}
break;
case GL_DEBUG_NEXT_LOGGED_MESSAGE_LENGTH: case GL_DEBUG_NEXT_LOGGED_MESSAGE_LENGTH:
{
struct gl_debug_state *debug = _mesa_get_debug_state(ctx);
v->value_int = debug ? debug->NextMsgLength : 0;
}
break;
case GL_DEBUG_GROUP_STACK_DEPTH: case GL_DEBUG_GROUP_STACK_DEPTH:
{ v->value_int = _mesa_get_debug_state_int(ctx, d->pname);
struct gl_debug_state *debug = _mesa_get_debug_state(ctx);
v->value_int = debug ? debug->GroupStackDepth : 0;
}
break; break;
/* GL_ARB_shader_atomic_counters */ /* GL_ARB_shader_atomic_counters */
case GL_ATOMIC_COUNTER_BUFFER_BINDING: case GL_ATOMIC_COUNTER_BUFFER_BINDING:
v->value_int = ctx->AtomicBuffer->Name; v->value_int = ctx->AtomicBuffer->Name;

View File

@@ -253,22 +253,11 @@ _mesa_GetPointerv( GLenum pname, GLvoid **params )
*params = (GLvoid *) ctx->Array.VAO->VertexAttrib[VERT_ATTRIB_POINT_SIZE].Ptr; *params = (GLvoid *) ctx->Array.VAO->VertexAttrib[VERT_ATTRIB_POINT_SIZE].Ptr;
break; break;
case GL_DEBUG_CALLBACK_FUNCTION_ARB: case GL_DEBUG_CALLBACK_FUNCTION_ARB:
if (!_mesa_is_desktop_gl(ctx)) {
goto invalid_pname;
}
else {
struct gl_debug_state *debug = _mesa_get_debug_state(ctx);
*params = debug ? (void *) debug->Callback : NULL;
}
break;
case GL_DEBUG_CALLBACK_USER_PARAM_ARB: case GL_DEBUG_CALLBACK_USER_PARAM_ARB:
if (!_mesa_is_desktop_gl(ctx)) { if (!_mesa_is_desktop_gl(ctx))
goto invalid_pname; goto invalid_pname;
} else
else { *params = _mesa_get_debug_state_ptr(ctx, pname);
struct gl_debug_state *debug = _mesa_get_debug_state(ctx);
*params = debug ? (void *) debug->CallbackData : NULL;
}
break; break;
default: default:
goto invalid_pname; goto invalid_pname;

View File

@@ -76,6 +76,7 @@ struct gl_list_extensions;
struct gl_meta_state; struct gl_meta_state;
struct gl_program_cache; struct gl_program_cache;
struct gl_texture_object; struct gl_texture_object;
struct gl_debug_state;
struct gl_context; struct gl_context;
struct st_context; struct st_context;
struct gl_uniform_storage; struct gl_uniform_storage;
@@ -3821,45 +3822,6 @@ enum mesa_debug_severity {
/** @} */ /** @} */
/**
* An error, warning, or other piece of debug information for an application
* to consume via GL_ARB_debug_output/GL_KHR_debug.
*/
struct gl_debug_msg
{
enum mesa_debug_source source;
enum mesa_debug_type type;
GLuint id;
enum mesa_debug_severity severity;
GLsizei length;
GLcharARB *message;
};
struct gl_debug_namespace
{
struct _mesa_HashTable *IDs;
unsigned ZeroID; /* a HashTable won't take zero, so store its state here */
/** lists of IDs in the hash table at each severity */
struct simple_node Severity[MESA_DEBUG_SEVERITY_COUNT];
};
struct gl_debug_state
{
GLDEBUGPROC Callback;
const void *CallbackData;
GLboolean SyncOutput;
GLboolean DebugOutput;
GLboolean Defaults[MAX_DEBUG_GROUP_STACK_DEPTH][MESA_DEBUG_SEVERITY_COUNT][MESA_DEBUG_SOURCE_COUNT][MESA_DEBUG_TYPE_COUNT];
struct gl_debug_namespace Namespaces[MAX_DEBUG_GROUP_STACK_DEPTH][MESA_DEBUG_SOURCE_COUNT][MESA_DEBUG_TYPE_COUNT];
struct gl_debug_msg Log[MAX_DEBUG_LOGGED_MESSAGES];
struct gl_debug_msg DebugGroupMsgs[MAX_DEBUG_GROUP_STACK_DEPTH];
GLint GroupStackDepth;
GLint NumMessages;
GLint NextMsg;
GLint NextMsgLength; /* redundant, but copied here from Log[NextMsg].length
for the sake of the offsetof() code in get.c */
};
/** /**
* Enum for the OpenGL APIs we know about and may support. * Enum for the OpenGL APIs we know about and may support.
* *

View File

@@ -663,13 +663,11 @@ st_api_create_context(struct st_api *stapi, struct st_manager *smapi,
} }
if (attribs->flags & ST_CONTEXT_FLAG_DEBUG){ if (attribs->flags & ST_CONTEXT_FLAG_DEBUG){
struct gl_debug_state *debug = _mesa_get_debug_state(st->ctx); if (!_mesa_set_debug_state_int(st->ctx, GL_DEBUG_OUTPUT, GL_TRUE)) {
if (!debug) {
*error = ST_CONTEXT_ERROR_NO_MEMORY; *error = ST_CONTEXT_ERROR_NO_MEMORY;
return NULL; return NULL;
} }
st->ctx->Const.ContextFlags |= GL_CONTEXT_FLAG_DEBUG_BIT; st->ctx->Const.ContextFlags |= GL_CONTEXT_FLAG_DEBUG_BIT;
debug->DebugOutput = GL_TRUE;
} }
if (attribs->flags & ST_CONTEXT_FLAG_FORWARD_COMPATIBLE) if (attribs->flags & ST_CONTEXT_FLAG_FORWARD_COMPATIBLE)