mirror of
https://gitlab.freedesktop.org/mesa/mesa.git
synced 2026-01-08 21:30:23 +01:00
mesa: Implement glPushDebugGroup and glPopDebugGroup
V4: fixes _mesa_error() compiler warnings (BrianP). V3: removed C++ style comment V2: fixed spelling typo in comment Signed-off-by: Timothy Arceri <t_arceri@yahoo.com.au> Reviewed-by: Brian Paul <brianp@vmware.com>
This commit is contained in:
parent
60f435319c
commit
797b9dc3ff
3 changed files with 214 additions and 71 deletions
|
|
@ -189,8 +189,9 @@ should_log(struct gl_context *ctx,
|
|||
GLuint id,
|
||||
enum mesa_debug_severity severity)
|
||||
{
|
||||
GLint gstack = ctx->Debug.GroupStackDepth;
|
||||
struct gl_debug_namespace *nspace =
|
||||
&ctx->Debug.Namespaces[source][type];
|
||||
&ctx->Debug.Namespaces[gstack][source][type];
|
||||
uintptr_t state;
|
||||
|
||||
/* In addition to not being able to store zero as a value, HashTable also
|
||||
|
|
@ -206,7 +207,7 @@ should_log(struct gl_context *ctx,
|
|||
struct gl_debug_severity *entry;
|
||||
|
||||
if (state == NOT_FOUND) {
|
||||
if (ctx->Debug.Defaults[severity][source][type])
|
||||
if (ctx->Debug.Defaults[gstack][severity][source][type])
|
||||
state = ENABLED;
|
||||
else
|
||||
state = DISABLED;
|
||||
|
|
@ -240,8 +241,9 @@ set_message_state(struct gl_context *ctx,
|
|||
enum mesa_debug_type type,
|
||||
GLuint id, GLboolean enabled)
|
||||
{
|
||||
GLint gstack = ctx->Debug.GroupStackDepth;
|
||||
struct gl_debug_namespace *nspace =
|
||||
&ctx->Debug.Namespaces[source][type];
|
||||
&ctx->Debug.Namespaces[gstack][source][type];
|
||||
uintptr_t state;
|
||||
|
||||
/* In addition to not being able to store zero as a value, HashTable also
|
||||
|
|
@ -266,6 +268,39 @@ set_message_state(struct gl_context *ctx,
|
|||
nspace->ZeroID = state;
|
||||
}
|
||||
|
||||
static void
|
||||
store_message_details(struct gl_debug_msg *emptySlot,
|
||||
enum mesa_debug_source source,
|
||||
enum mesa_debug_type type, GLuint id,
|
||||
enum mesa_debug_severity severity, GLint len,
|
||||
const char *buf)
|
||||
{
|
||||
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 {
|
||||
static GLuint oom_msg_id = 0;
|
||||
debug_get_id(&oom_msg_id);
|
||||
|
||||
/* malloc failed! */
|
||||
emptySlot->message = out_of_memory;
|
||||
emptySlot->length = strlen(out_of_memory)+1;
|
||||
emptySlot->source = MESA_DEBUG_SOURCE_OTHER;
|
||||
emptySlot->type = MESA_DEBUG_TYPE_ERROR;
|
||||
emptySlot->id = oom_msg_id;
|
||||
emptySlot->severity = MESA_DEBUG_SEVERITY_HIGH;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 'buf' is not necessarily a null-terminated string. When logging, copy
|
||||
* 'len' characters from it, store them in a new, null-terminated string,
|
||||
|
|
@ -301,30 +336,7 @@ _mesa_log_msg(struct gl_context *ctx, enum mesa_debug_source source,
|
|||
% 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 {
|
||||
static GLuint oom_msg_id = 0;
|
||||
debug_get_id(&oom_msg_id);
|
||||
|
||||
/* malloc failed! */
|
||||
emptySlot->message = out_of_memory;
|
||||
emptySlot->length = strlen(out_of_memory)+1;
|
||||
emptySlot->source = MESA_DEBUG_SOURCE_OTHER;
|
||||
emptySlot->type = MESA_DEBUG_TYPE_ERROR;
|
||||
emptySlot->id = oom_msg_id;
|
||||
emptySlot->severity = MESA_DEBUG_SEVERITY_HIGH;
|
||||
}
|
||||
store_message_details(emptySlot, source, type, id, severity, len, buf);
|
||||
|
||||
if (ctx->Debug.NumMessages == 0)
|
||||
ctx->Debug.NextMsgLength = ctx->Debug.Log[ctx->Debug.NextMsg].length;
|
||||
|
|
@ -486,6 +498,7 @@ control_messages(struct gl_context *ctx,
|
|||
GLboolean enabled)
|
||||
{
|
||||
int s, t, sev, smax, tmax, sevmax;
|
||||
GLint gstack = ctx->Debug.GroupStackDepth;
|
||||
|
||||
if (source == MESA_DEBUG_SOURCE_COUNT) {
|
||||
source = 0;
|
||||
|
|
@ -515,10 +528,10 @@ control_messages(struct gl_context *ctx,
|
|||
struct gl_debug_severity *entry;
|
||||
|
||||
/* change the default for IDs we've never seen before. */
|
||||
ctx->Debug.Defaults[sev][s][t] = enabled;
|
||||
ctx->Debug.Defaults[gstack][sev][s][t] = enabled;
|
||||
|
||||
/* Now change the state of IDs we *have* seen... */
|
||||
foreach(node, &ctx->Debug.Namespaces[s][t].Severity[sev]) {
|
||||
foreach(node, &ctx->Debug.Namespaces[gstack][s][t].Severity[sev]) {
|
||||
entry = (struct gl_debug_severity *)node;
|
||||
set_message_state(ctx, s, t, entry->ID, enabled);
|
||||
}
|
||||
|
|
@ -594,19 +607,17 @@ message_control(GLenum gl_source, GLenum gl_type,
|
|||
}
|
||||
|
||||
/**
|
||||
* This is a generic message insert function for use by both
|
||||
* glDebugMessageInsertARB and glDebugMessageInsert.
|
||||
* This is a generic message insert function.
|
||||
* Validation of source, type and severity parameters should be done
|
||||
* before calling this funtion.
|
||||
*/
|
||||
static void
|
||||
message_insert(GLenum source, GLenum type, GLuint id,
|
||||
GLenum severity, GLint length, const GLchar* buf,
|
||||
unsigned caller, const char *callerstr)
|
||||
const char *callerstr)
|
||||
{
|
||||
GET_CURRENT_CONTEXT(ctx);
|
||||
|
||||
if (!validate_params(ctx, caller, callerstr, source, type, severity))
|
||||
return; /* GL_INVALID_ENUM */
|
||||
|
||||
if (length < 0)
|
||||
length = strlen(buf);
|
||||
|
||||
|
|
@ -677,6 +688,37 @@ get_message_log(GLuint count, GLsizei logSize, GLenum* sources,
|
|||
return ret;
|
||||
}
|
||||
|
||||
static void
|
||||
do_nothing(GLuint key, void *data, void *userData)
|
||||
{
|
||||
}
|
||||
|
||||
static void
|
||||
free_errors_data(struct gl_context *ctx, GLint gstack)
|
||||
{
|
||||
enum mesa_debug_type t;
|
||||
enum mesa_debug_source s;
|
||||
enum mesa_debug_severity sev;
|
||||
|
||||
/* Tear down state for filtering debug messages. */
|
||||
for (s = 0; s < MESA_DEBUG_SOURCE_COUNT; s++)
|
||||
for (t = 0; t < MESA_DEBUG_TYPE_COUNT; t++) {
|
||||
_mesa_HashDeleteAll(ctx->Debug.Namespaces[gstack][s][t].IDs,
|
||||
do_nothing, NULL);
|
||||
_mesa_DeleteHashTable(ctx->Debug.Namespaces[gstack][s][t].IDs);
|
||||
for (sev = 0; sev < MESA_DEBUG_SEVERITY_COUNT; sev++) {
|
||||
struct simple_node *node, *tmp;
|
||||
struct gl_debug_severity *entry;
|
||||
|
||||
foreach_s(node, tmp,
|
||||
&ctx->Debug.Namespaces[gstack][s][t].Severity[sev]) {
|
||||
entry = (struct gl_debug_severity *)node;
|
||||
free(entry);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void GLAPIENTRY
|
||||
_mesa_DebugMessageInsert(GLenum source, GLenum type, GLuint id,
|
||||
GLenum severity, GLint length,
|
||||
|
|
@ -684,8 +726,13 @@ _mesa_DebugMessageInsert(GLenum source, GLenum type, GLuint id,
|
|||
{
|
||||
const char *callerstr = "glDebugMessageInsert";
|
||||
|
||||
GET_CURRENT_CONTEXT(ctx);
|
||||
|
||||
if (!validate_params(ctx, INSERT, callerstr, source, type, severity))
|
||||
return; /* GL_INVALID_ENUM */
|
||||
|
||||
message_insert(source, type, id, severity, length, buf,
|
||||
INSERT, callerstr);
|
||||
callerstr);
|
||||
}
|
||||
|
||||
GLuint GLAPIENTRY
|
||||
|
|
@ -722,13 +769,112 @@ void GLAPIENTRY
|
|||
_mesa_PushDebugGroup(GLenum source, GLuint id, GLsizei length,
|
||||
const GLchar *message)
|
||||
{
|
||||
const char *callerstr = "glPushDebugGroup";
|
||||
int s, t, sev;
|
||||
GLint prevStackDepth;
|
||||
GLint currStackDepth;
|
||||
struct gl_debug_msg *emptySlot;
|
||||
|
||||
GET_CURRENT_CONTEXT(ctx);
|
||||
|
||||
if (ctx->Debug.GroupStackDepth >= MAX_DEBUG_GROUP_STACK_DEPTH-1) {
|
||||
_mesa_error(ctx, GL_STACK_OVERFLOW, "%s", callerstr);
|
||||
return;
|
||||
}
|
||||
|
||||
switch(source) {
|
||||
case GL_DEBUG_SOURCE_APPLICATION:
|
||||
case GL_DEBUG_SOURCE_THIRD_PARTY:
|
||||
break;
|
||||
default:
|
||||
_mesa_error(ctx, GL_INVALID_ENUM, "bad value passed to %s"
|
||||
"(source=0x%x)", callerstr, source);
|
||||
return;
|
||||
}
|
||||
|
||||
message_insert(source, GL_DEBUG_TYPE_PUSH_GROUP, id,
|
||||
GL_DEBUG_SEVERITY_NOTIFICATION, length,
|
||||
message, callerstr);
|
||||
|
||||
prevStackDepth = ctx->Debug.GroupStackDepth;
|
||||
ctx->Debug.GroupStackDepth++;
|
||||
currStackDepth = ctx->Debug.GroupStackDepth;
|
||||
|
||||
/* pop reuses the message details from push so we store this */
|
||||
if (length < 0)
|
||||
length = strlen(message);
|
||||
emptySlot = &ctx->Debug.DebugGroupMsgs[ctx->Debug.GroupStackDepth];
|
||||
store_message_details(emptySlot, gl_enum_to_debug_source(source),
|
||||
gl_enum_to_debug_source(GL_DEBUG_TYPE_PUSH_GROUP),
|
||||
id,
|
||||
gl_enum_to_debug_severity(GL_DEBUG_SEVERITY_NOTIFICATION),
|
||||
length, message);
|
||||
|
||||
/* inherit the control volume of the debug group previously residing on
|
||||
* the top of the debug group stack
|
||||
*/
|
||||
for (s = 0; s < MESA_DEBUG_SOURCE_COUNT; s++)
|
||||
for (t = 0; t < MESA_DEBUG_TYPE_COUNT; t++) {
|
||||
/* copy id settings */
|
||||
ctx->Debug.Namespaces[currStackDepth][s][t].IDs =
|
||||
_mesa_HashClone(ctx->Debug.Namespaces[prevStackDepth][s][t].IDs);
|
||||
|
||||
for (sev = 0; sev < MESA_DEBUG_SEVERITY_COUNT; sev++) {
|
||||
struct gl_debug_severity *entry, *prevEntry;
|
||||
struct simple_node *node;
|
||||
|
||||
/* copy default settings for unknown ids */
|
||||
ctx->Debug.Defaults[currStackDepth][sev][s][t] = ctx->Debug.Defaults[prevStackDepth][sev][s][t];
|
||||
|
||||
/* copy known id severity settings */
|
||||
make_empty_list(&ctx->Debug.Namespaces[currStackDepth][s][t].Severity[sev]);
|
||||
foreach(node, &ctx->Debug.Namespaces[prevStackDepth][s][t].Severity[sev]) {
|
||||
prevEntry = (struct gl_debug_severity *)node;
|
||||
entry = malloc(sizeof *entry);
|
||||
if (!entry)
|
||||
return;
|
||||
|
||||
entry->ID = prevEntry->ID;
|
||||
insert_at_tail(&ctx->Debug.Namespaces[currStackDepth][s][t].Severity[sev], &entry->link);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void GLAPIENTRY
|
||||
_mesa_PopDebugGroup()
|
||||
{
|
||||
const char *callerstr = "glPopDebugGroup";
|
||||
struct gl_debug_msg *gdmessage;
|
||||
GLint prevStackDepth;
|
||||
|
||||
GET_CURRENT_CONTEXT(ctx);
|
||||
|
||||
if (ctx->Debug.GroupStackDepth <= 0) {
|
||||
_mesa_error(ctx, GL_STACK_UNDERFLOW, "%s", callerstr);
|
||||
return;
|
||||
}
|
||||
|
||||
prevStackDepth = ctx->Debug.GroupStackDepth;
|
||||
ctx->Debug.GroupStackDepth--;
|
||||
|
||||
gdmessage = &ctx->Debug.DebugGroupMsgs[prevStackDepth];
|
||||
/* using _mesa_log_msg() directly here as verification of parameters
|
||||
* already done in push
|
||||
*/
|
||||
_mesa_log_msg(ctx, gdmessage->source,
|
||||
gl_enum_to_debug_type(GL_DEBUG_TYPE_POP_GROUP),
|
||||
gdmessage->id,
|
||||
gl_enum_to_debug_severity(GL_DEBUG_SEVERITY_NOTIFICATION),
|
||||
gdmessage->length, gdmessage->message);
|
||||
|
||||
if (gdmessage->message != (char*)out_of_memory)
|
||||
free(gdmessage->message);
|
||||
gdmessage->message = NULL;
|
||||
gdmessage->length = 0;
|
||||
|
||||
/* free popped debug group data */
|
||||
free_errors_data(ctx, prevStackDepth);
|
||||
}
|
||||
|
||||
void GLAPIENTRY
|
||||
|
|
@ -738,8 +884,13 @@ _mesa_DebugMessageInsertARB(GLenum source, GLenum type, GLuint id,
|
|||
{
|
||||
const char *callerstr = "glDebugMessageInsertARB";
|
||||
|
||||
GET_CURRENT_CONTEXT(ctx);
|
||||
|
||||
if (!validate_params(ctx, INSERT_ARB, callerstr, source, type, severity))
|
||||
return; /* GL_INVALID_ENUM */
|
||||
|
||||
message_insert(source, type, id, severity, length, buf,
|
||||
INSERT_ARB, callerstr);
|
||||
callerstr);
|
||||
}
|
||||
|
||||
GLuint GLAPIENTRY
|
||||
|
|
@ -784,53 +935,39 @@ _mesa_init_errors(struct gl_context *ctx)
|
|||
ctx->Debug.NumMessages = 0;
|
||||
ctx->Debug.NextMsg = 0;
|
||||
ctx->Debug.NextMsgLength = 0;
|
||||
ctx->Debug.GroupStackDepth = 0;
|
||||
|
||||
/* Enable all the messages with severity HIGH or MEDIUM by default. */
|
||||
memset(ctx->Debug.Defaults[MESA_DEBUG_SEVERITY_HIGH], GL_TRUE,
|
||||
sizeof ctx->Debug.Defaults[MESA_DEBUG_SEVERITY_HIGH]);
|
||||
memset(ctx->Debug.Defaults[MESA_DEBUG_SEVERITY_MEDIUM], GL_TRUE,
|
||||
sizeof ctx->Debug.Defaults[MESA_DEBUG_SEVERITY_MEDIUM]);
|
||||
memset(ctx->Debug.Defaults[MESA_DEBUG_SEVERITY_LOW], GL_FALSE,
|
||||
sizeof ctx->Debug.Defaults[MESA_DEBUG_SEVERITY_LOW]);
|
||||
memset(ctx->Debug.Defaults[0][MESA_DEBUG_SEVERITY_HIGH], GL_TRUE,
|
||||
sizeof ctx->Debug.Defaults[0][MESA_DEBUG_SEVERITY_HIGH]);
|
||||
memset(ctx->Debug.Defaults[0][MESA_DEBUG_SEVERITY_MEDIUM], GL_TRUE,
|
||||
sizeof ctx->Debug.Defaults[0][MESA_DEBUG_SEVERITY_MEDIUM]);
|
||||
memset(ctx->Debug.Defaults[0][MESA_DEBUG_SEVERITY_LOW], GL_FALSE,
|
||||
sizeof ctx->Debug.Defaults[0][MESA_DEBUG_SEVERITY_LOW]);
|
||||
|
||||
/* Initialize state for filtering known debug messages. */
|
||||
for (s = 0; s < MESA_DEBUG_SOURCE_COUNT; s++)
|
||||
for (t = 0; t < MESA_DEBUG_TYPE_COUNT; t++) {
|
||||
ctx->Debug.Namespaces[s][t].IDs = _mesa_NewHashTable();
|
||||
assert(ctx->Debug.Namespaces[s][t].IDs);
|
||||
ctx->Debug.Namespaces[0][s][t].IDs = _mesa_NewHashTable();
|
||||
assert(ctx->Debug.Namespaces[0][s][t].IDs);
|
||||
|
||||
for (sev = 0; sev < MESA_DEBUG_SEVERITY_COUNT; sev++)
|
||||
make_empty_list(&ctx->Debug.Namespaces[s][t].Severity[sev]);
|
||||
make_empty_list(&ctx->Debug.Namespaces[0][s][t].Severity[sev]);
|
||||
}
|
||||
}
|
||||
|
||||
static void
|
||||
do_nothing(GLuint key, void *data, void *userData)
|
||||
{
|
||||
}
|
||||
|
||||
/**
|
||||
* Loop through debug group stack tearing down states for
|
||||
* filtering debug messages.
|
||||
*/
|
||||
void
|
||||
_mesa_free_errors_data(struct gl_context *ctx)
|
||||
{
|
||||
enum mesa_debug_type t;
|
||||
enum mesa_debug_source s;
|
||||
enum mesa_debug_severity sev;
|
||||
GLint i;
|
||||
|
||||
/* Tear down state for filtering debug messages. */
|
||||
for (s = 0; s < MESA_DEBUG_SOURCE_COUNT; s++)
|
||||
for (t = 0; t < MESA_DEBUG_TYPE_COUNT; t++) {
|
||||
_mesa_HashDeleteAll(ctx->Debug.Namespaces[s][t].IDs, do_nothing, NULL);
|
||||
_mesa_DeleteHashTable(ctx->Debug.Namespaces[s][t].IDs);
|
||||
for (sev = 0; sev < MESA_DEBUG_SEVERITY_COUNT; sev++) {
|
||||
struct simple_node *node, *tmp;
|
||||
struct gl_debug_severity *entry;
|
||||
|
||||
foreach_s(node, tmp, &ctx->Debug.Namespaces[s][t].Severity[sev]) {
|
||||
entry = (struct gl_debug_severity *)node;
|
||||
free(entry);
|
||||
}
|
||||
}
|
||||
}
|
||||
for (i = 0; i <= ctx->Debug.GroupStackDepth; i++) {
|
||||
free_errors_data(ctx, i);
|
||||
}
|
||||
}
|
||||
|
||||
/**********************************************************************/
|
||||
|
|
|
|||
|
|
@ -117,6 +117,11 @@ _mesa_DebugMessageControl(GLenum source, GLenum type, GLenum severity,
|
|||
void GLAPIENTRY
|
||||
_mesa_DebugMessageCallback(GLDEBUGPROC callback,
|
||||
const void *userParam);
|
||||
void GLAPIENTRY
|
||||
_mesa_PushDebugGroup(GLenum source, GLuint id, GLsizei length,
|
||||
const GLchar *message);
|
||||
void GLAPIENTRY
|
||||
_mesa_PopDebugGroup(void);
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
|
|
|
|||
|
|
@ -3380,9 +3380,10 @@ struct gl_debug_state
|
|||
GLDEBUGPROC Callback;
|
||||
const void *CallbackData;
|
||||
GLboolean SyncOutput;
|
||||
GLboolean Defaults[MESA_DEBUG_SEVERITY_COUNT][MESA_DEBUG_SOURCE_COUNT][MESA_DEBUG_TYPE_COUNT];
|
||||
struct gl_debug_namespace Namespaces[MESA_DEBUG_SOURCE_COUNT][MESA_DEBUG_TYPE_COUNT];
|
||||
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;
|
||||
|
|
|
|||
Loading…
Add table
Reference in a new issue