mesa: clean up debug output namespace handling
Add functions to provide these operations on a struct gl_debug_namespace: init(): initialize the namespace copy(): copy all elements from one namespace to another clear(): clear all elements (to free the memories) set(): set the value of an element set_all(): set the value of all elements get(): get the value of an element A debug namespace is like a sparse array. The length of the array is huge, 2^sizeof(GLuint), but most of the elements assume the same value sepcified by set_all(). Signed-off-by: Chia-I Wu <olv@lunarg.com> Reviewed-by: Brian Paul <brianp@vmware.com>
This commit is contained in:
@@ -274,6 +274,207 @@ debug_message_store(struct gl_debug_message *msg,
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static void
|
||||||
|
debug_namespace_init(struct gl_debug_namespace *ns)
|
||||||
|
{
|
||||||
|
int sev;
|
||||||
|
|
||||||
|
memset(ns, 0, sizeof(*ns));
|
||||||
|
|
||||||
|
ns->IDs = _mesa_NewHashTable();
|
||||||
|
assert(ns->IDs);
|
||||||
|
|
||||||
|
for (sev = 0; sev < Elements(ns->Severity); sev++)
|
||||||
|
make_empty_list(&ns->Severity[sev]);
|
||||||
|
|
||||||
|
/* Enable all the messages with severity HIGH or MEDIUM by default */
|
||||||
|
ns->Defaults[MESA_DEBUG_SEVERITY_HIGH] = GL_TRUE;
|
||||||
|
ns->Defaults[MESA_DEBUG_SEVERITY_MEDIUM] = GL_TRUE;
|
||||||
|
}
|
||||||
|
|
||||||
|
static void
|
||||||
|
debug_namespace_clear_cb(GLuint key, void *data, void *userData)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
static void
|
||||||
|
debug_namespace_clear(struct gl_debug_namespace *ns)
|
||||||
|
{
|
||||||
|
int sev;
|
||||||
|
|
||||||
|
_mesa_HashDeleteAll(ns->IDs, debug_namespace_clear_cb, NULL);
|
||||||
|
_mesa_DeleteHashTable(ns->IDs);
|
||||||
|
|
||||||
|
for (sev = 0; sev < Elements(ns->Severity); sev++) {
|
||||||
|
struct simple_node *node, *tmp;
|
||||||
|
|
||||||
|
foreach_s(node, tmp, &ns->Severity[sev])
|
||||||
|
free(node);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
static bool
|
||||||
|
debug_namespace_copy(struct gl_debug_namespace *dst,
|
||||||
|
const struct gl_debug_namespace *src)
|
||||||
|
{
|
||||||
|
bool err = false;
|
||||||
|
int sev;
|
||||||
|
|
||||||
|
/* copy id settings */
|
||||||
|
dst->IDs = _mesa_HashClone(src->IDs);
|
||||||
|
if (!dst->IDs)
|
||||||
|
return false;
|
||||||
|
|
||||||
|
for (sev = 0; sev < Elements(dst->Severity); sev++) {
|
||||||
|
struct simple_node *node;
|
||||||
|
|
||||||
|
/* copy default settings for unknown ids */
|
||||||
|
dst->Defaults[sev] = src->Defaults[sev];
|
||||||
|
|
||||||
|
make_empty_list(&dst->Severity[sev]);
|
||||||
|
if (err)
|
||||||
|
continue;
|
||||||
|
|
||||||
|
/* copy known id severity settings */
|
||||||
|
foreach(node, &src->Severity[sev]) {
|
||||||
|
const struct gl_debug_severity *entry =
|
||||||
|
(const struct gl_debug_severity *) node;
|
||||||
|
struct gl_debug_severity *copy;
|
||||||
|
|
||||||
|
copy = malloc(sizeof(*copy));
|
||||||
|
if (!copy) {
|
||||||
|
err = true;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
copy->ID = entry->ID;
|
||||||
|
insert_at_tail(&dst->Severity[sev], ©->link);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (err) {
|
||||||
|
debug_namespace_clear(dst);
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Set the state of \p id in the namespace.
|
||||||
|
*/
|
||||||
|
static bool
|
||||||
|
debug_namespace_set(struct gl_debug_namespace *ns,
|
||||||
|
GLuint id, bool enabled)
|
||||||
|
{
|
||||||
|
uintptr_t state;
|
||||||
|
|
||||||
|
/* In addition to not being able to store zero as a value, HashTable also
|
||||||
|
* can't use zero as a key.
|
||||||
|
*/
|
||||||
|
if (id)
|
||||||
|
state = (uintptr_t) _mesa_HashLookup(ns->IDs, id);
|
||||||
|
else
|
||||||
|
state = ns->ZeroID;
|
||||||
|
|
||||||
|
if (state == NOT_FOUND)
|
||||||
|
state = enabled ? ENABLED : DISABLED;
|
||||||
|
else {
|
||||||
|
if (enabled)
|
||||||
|
state |= ENABLED_BIT;
|
||||||
|
else
|
||||||
|
state &= ~ENABLED_BIT;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (id)
|
||||||
|
_mesa_HashInsert(ns->IDs, id, (void *) state);
|
||||||
|
else
|
||||||
|
ns->ZeroID = state;
|
||||||
|
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Set the default state of the namespace for \p severity. When \p severity
|
||||||
|
* is MESA_DEBUG_SEVERITY_COUNT, the default values for all severities are
|
||||||
|
* updated.
|
||||||
|
*/
|
||||||
|
static void
|
||||||
|
debug_namespace_set_all(struct gl_debug_namespace *ns,
|
||||||
|
enum mesa_debug_severity severity,
|
||||||
|
bool enabled)
|
||||||
|
{
|
||||||
|
int sev, end;
|
||||||
|
|
||||||
|
if (severity >= Elements(ns->Severity)) {
|
||||||
|
end = severity;
|
||||||
|
severity = 0;
|
||||||
|
} else {
|
||||||
|
end = severity + 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
for (sev = severity; sev < end; sev++) {
|
||||||
|
struct simple_node *node;
|
||||||
|
struct gl_debug_severity *entry;
|
||||||
|
|
||||||
|
/* change the default for IDs we've never seen before. */
|
||||||
|
ns->Defaults[sev] = enabled;
|
||||||
|
|
||||||
|
/* Now change the state of IDs we *have* seen... */
|
||||||
|
foreach(node, &ns->Severity[sev]) {
|
||||||
|
entry = (struct gl_debug_severity *) node;
|
||||||
|
debug_namespace_set(ns, entry->ID, enabled);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Get the state of \p id in the namespace.
|
||||||
|
*/
|
||||||
|
static bool
|
||||||
|
debug_namespace_get(struct gl_debug_namespace *ns, GLuint id,
|
||||||
|
enum mesa_debug_severity severity)
|
||||||
|
{
|
||||||
|
uintptr_t state = 0;
|
||||||
|
|
||||||
|
/* In addition to not being able to store zero as a value, HashTable also
|
||||||
|
* can't use zero as a key.
|
||||||
|
*/
|
||||||
|
if (id)
|
||||||
|
state = (uintptr_t) _mesa_HashLookup(ns->IDs, id);
|
||||||
|
else
|
||||||
|
state = ns->ZeroID;
|
||||||
|
|
||||||
|
/* Only do this once for each ID. This makes sure the ID exists in,
|
||||||
|
* at most, one list, and does not pointlessly appear multiple times.
|
||||||
|
*/
|
||||||
|
if (!(state & KNOWN_SEVERITY)) {
|
||||||
|
struct gl_debug_severity *entry;
|
||||||
|
|
||||||
|
if (state == NOT_FOUND) {
|
||||||
|
if (ns->Defaults[severity])
|
||||||
|
state = ENABLED;
|
||||||
|
else
|
||||||
|
state = DISABLED;
|
||||||
|
}
|
||||||
|
|
||||||
|
entry = malloc(sizeof *entry);
|
||||||
|
if (entry) {
|
||||||
|
state |= KNOWN_SEVERITY;
|
||||||
|
|
||||||
|
if (id)
|
||||||
|
_mesa_HashInsert(ns->IDs, id, (void *) state);
|
||||||
|
else
|
||||||
|
ns->ZeroID = state;
|
||||||
|
|
||||||
|
entry->ID = id;
|
||||||
|
insert_at_tail(&ns->Severity[severity], &entry->link);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return (state & ENABLED_BIT);
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Allocate and initialize context debug state.
|
* Allocate and initialize context debug state.
|
||||||
*/
|
*/
|
||||||
@@ -281,7 +482,7 @@ static struct gl_debug_state *
|
|||||||
debug_create(void)
|
debug_create(void)
|
||||||
{
|
{
|
||||||
struct gl_debug_state *debug;
|
struct gl_debug_state *debug;
|
||||||
int s, t, sev;
|
int s, t;
|
||||||
|
|
||||||
debug = CALLOC_STRUCT(gl_debug_state);
|
debug = CALLOC_STRUCT(gl_debug_state);
|
||||||
if (!debug)
|
if (!debug)
|
||||||
@@ -290,29 +491,13 @@ debug_create(void)
|
|||||||
/* Initialize state for filtering known debug messages. */
|
/* Initialize state for filtering known debug messages. */
|
||||||
for (s = 0; s < MESA_DEBUG_SOURCE_COUNT; s++) {
|
for (s = 0; s < MESA_DEBUG_SOURCE_COUNT; s++) {
|
||||||
for (t = 0; t < MESA_DEBUG_TYPE_COUNT; t++) {
|
for (t = 0; t < MESA_DEBUG_TYPE_COUNT; t++) {
|
||||||
struct gl_debug_namespace *nspace =
|
debug_namespace_init(&debug->Groups[0].Namespaces[s][t]);
|
||||||
&debug->Groups[0].Namespaces[s][t];
|
|
||||||
|
|
||||||
nspace->IDs = _mesa_NewHashTable();
|
|
||||||
assert(nspace->IDs);
|
|
||||||
|
|
||||||
for (sev = 0; sev < MESA_DEBUG_SEVERITY_COUNT; sev++)
|
|
||||||
make_empty_list(&nspace->Severity[sev]);
|
|
||||||
|
|
||||||
/* Enable all the messages with severity HIGH or MEDIUM by default */
|
|
||||||
nspace->Defaults[MESA_DEBUG_SEVERITY_HIGH] = GL_TRUE;
|
|
||||||
nspace->Defaults[MESA_DEBUG_SEVERITY_MEDIUM] = GL_TRUE;
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
return debug;
|
return debug;
|
||||||
}
|
}
|
||||||
|
|
||||||
static void
|
|
||||||
debug_clear_group_cb(GLuint key, void *data, void *userData)
|
|
||||||
{
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Free debug state for the given stack depth.
|
* Free debug state for the given stack depth.
|
||||||
*/
|
*/
|
||||||
@@ -322,24 +507,11 @@ debug_clear_group(struct gl_debug_state *debug, GLint gstack)
|
|||||||
struct gl_debug_group *grp = &debug->Groups[gstack];
|
struct gl_debug_group *grp = &debug->Groups[gstack];
|
||||||
enum mesa_debug_type t;
|
enum mesa_debug_type t;
|
||||||
enum mesa_debug_source s;
|
enum mesa_debug_source s;
|
||||||
enum mesa_debug_severity sev;
|
|
||||||
|
|
||||||
/* Tear down state for filtering debug messages. */
|
/* Tear down state for filtering debug messages. */
|
||||||
for (s = 0; s < MESA_DEBUG_SOURCE_COUNT; s++) {
|
for (s = 0; s < MESA_DEBUG_SOURCE_COUNT; s++) {
|
||||||
for (t = 0; t < MESA_DEBUG_TYPE_COUNT; t++) {
|
for (t = 0; t < MESA_DEBUG_TYPE_COUNT; t++) {
|
||||||
struct gl_debug_namespace *nspace = &grp->Namespaces[s][t];
|
debug_namespace_clear(&grp->Namespaces[s][t]);
|
||||||
|
|
||||||
_mesa_HashDeleteAll(nspace->IDs, debug_clear_group_cb, NULL);
|
|
||||||
_mesa_DeleteHashTable(nspace->IDs);
|
|
||||||
for (sev = 0; sev < MESA_DEBUG_SEVERITY_COUNT; sev++) {
|
|
||||||
struct simple_node *node, *tmp;
|
|
||||||
struct gl_debug_severity *entry;
|
|
||||||
|
|
||||||
foreach_s(node, tmp, &nspace->Severity[sev]) {
|
|
||||||
entry = (struct gl_debug_severity *)node;
|
|
||||||
free(entry);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -371,29 +543,8 @@ debug_set_message_enable(struct gl_debug_state *debug,
|
|||||||
const GLint gstack = debug->GroupStackDepth;
|
const GLint gstack = debug->GroupStackDepth;
|
||||||
struct gl_debug_namespace *nspace =
|
struct gl_debug_namespace *nspace =
|
||||||
&debug->Groups[gstack].Namespaces[source][type];
|
&debug->Groups[gstack].Namespaces[source][type];
|
||||||
uintptr_t state;
|
|
||||||
|
|
||||||
/* In addition to not being able to store zero as a value, HashTable also
|
debug_namespace_set(nspace, id, enabled);
|
||||||
* can't use zero as a key.
|
|
||||||
*/
|
|
||||||
if (id)
|
|
||||||
state = (uintptr_t)_mesa_HashLookup(nspace->IDs, id);
|
|
||||||
else
|
|
||||||
state = nspace->ZeroID;
|
|
||||||
|
|
||||||
if (state == NOT_FOUND)
|
|
||||||
state = enabled ? ENABLED : DISABLED;
|
|
||||||
else {
|
|
||||||
if (enabled)
|
|
||||||
state |= ENABLED_BIT;
|
|
||||||
else
|
|
||||||
state &= ~ENABLED_BIT;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (id)
|
|
||||||
_mesa_HashInsert(nspace->IDs, id, (void*)state);
|
|
||||||
else
|
|
||||||
nspace->ZeroID = state;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
@@ -415,7 +566,7 @@ debug_set_message_enable_all(struct gl_debug_state *debug,
|
|||||||
GLboolean enabled)
|
GLboolean enabled)
|
||||||
{
|
{
|
||||||
const GLint gstack = debug->GroupStackDepth;
|
const GLint gstack = debug->GroupStackDepth;
|
||||||
int s, t, sev, smax, tmax, sevmax;
|
int s, t, smax, tmax;
|
||||||
|
|
||||||
if (source == MESA_DEBUG_SOURCE_COUNT) {
|
if (source == MESA_DEBUG_SOURCE_COUNT) {
|
||||||
source = 0;
|
source = 0;
|
||||||
@@ -431,31 +582,11 @@ debug_set_message_enable_all(struct gl_debug_state *debug,
|
|||||||
tmax = type+1;
|
tmax = type+1;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (severity == MESA_DEBUG_SEVERITY_COUNT) {
|
|
||||||
severity = 0;
|
|
||||||
sevmax = MESA_DEBUG_SEVERITY_COUNT;
|
|
||||||
} else {
|
|
||||||
sevmax = severity+1;
|
|
||||||
}
|
|
||||||
|
|
||||||
for (s = source; s < smax; s++) {
|
for (s = source; s < smax; s++) {
|
||||||
for (t = type; t < tmax; t++) {
|
for (t = type; t < tmax; t++) {
|
||||||
struct gl_debug_namespace *nspace =
|
struct gl_debug_namespace *nspace =
|
||||||
&debug->Groups[gstack].Namespaces[s][t];
|
&debug->Groups[gstack].Namespaces[s][t];
|
||||||
|
debug_namespace_set_all(nspace, severity, enabled);
|
||||||
for (sev = severity; sev < sevmax; sev++) {
|
|
||||||
struct simple_node *node;
|
|
||||||
struct gl_debug_severity *entry;
|
|
||||||
|
|
||||||
/* change the default for IDs we've never seen before. */
|
|
||||||
nspace->Defaults[sev] = enabled;
|
|
||||||
|
|
||||||
/* Now change the state of IDs we *have* seen... */
|
|
||||||
foreach(node, &nspace->Severity[sev]) {
|
|
||||||
entry = (struct gl_debug_severity *)node;
|
|
||||||
debug_set_message_enable(debug, s, t, entry->ID, enabled);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -473,48 +604,11 @@ debug_is_message_enabled(struct gl_debug_state *debug,
|
|||||||
const GLint gstack = debug->GroupStackDepth;
|
const GLint gstack = debug->GroupStackDepth;
|
||||||
struct gl_debug_group *grp = &debug->Groups[gstack];
|
struct gl_debug_group *grp = &debug->Groups[gstack];
|
||||||
struct gl_debug_namespace *nspace = &grp->Namespaces[source][type];
|
struct gl_debug_namespace *nspace = &grp->Namespaces[source][type];
|
||||||
uintptr_t state = 0;
|
|
||||||
|
|
||||||
if (!debug->DebugOutput)
|
if (!debug->DebugOutput)
|
||||||
return false;
|
return false;
|
||||||
|
|
||||||
/* In addition to not being able to store zero as a value, HashTable also
|
return debug_namespace_get(nspace, id, severity);
|
||||||
* can't use zero as a key.
|
|
||||||
*/
|
|
||||||
if (id)
|
|
||||||
state = (uintptr_t)_mesa_HashLookup(nspace->IDs, id);
|
|
||||||
else
|
|
||||||
state = nspace->ZeroID;
|
|
||||||
|
|
||||||
/* Only do this once for each ID. This makes sure the ID exists in,
|
|
||||||
* at most, one list, and does not pointlessly appear multiple times.
|
|
||||||
*/
|
|
||||||
if (!(state & KNOWN_SEVERITY)) {
|
|
||||||
struct gl_debug_severity *entry;
|
|
||||||
|
|
||||||
if (state == NOT_FOUND) {
|
|
||||||
if (nspace->Defaults[severity])
|
|
||||||
state = ENABLED;
|
|
||||||
else
|
|
||||||
state = DISABLED;
|
|
||||||
}
|
|
||||||
|
|
||||||
entry = malloc(sizeof *entry);
|
|
||||||
if (!entry)
|
|
||||||
goto out;
|
|
||||||
|
|
||||||
state |= KNOWN_SEVERITY;
|
|
||||||
|
|
||||||
if (id)
|
|
||||||
_mesa_HashInsert(nspace->IDs, id, (void*)state);
|
|
||||||
else
|
|
||||||
nspace->ZeroID = state;
|
|
||||||
|
|
||||||
entry->ID = id;
|
|
||||||
insert_at_tail(&nspace->Severity[severity], &entry->link);
|
|
||||||
}
|
|
||||||
out:
|
|
||||||
return (state & ENABLED_BIT);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -592,7 +686,7 @@ static void
|
|||||||
debug_push_group(struct gl_debug_state *debug)
|
debug_push_group(struct gl_debug_state *debug)
|
||||||
{
|
{
|
||||||
const GLint gstack = debug->GroupStackDepth;
|
const GLint gstack = debug->GroupStackDepth;
|
||||||
int s, t, sev;
|
int s, t;
|
||||||
|
|
||||||
/* inherit the control volume of the debug group previously residing on
|
/* inherit the control volume of the debug group previously residing on
|
||||||
* the top of the debug group stack
|
* the top of the debug group stack
|
||||||
@@ -604,30 +698,8 @@ debug_push_group(struct gl_debug_state *debug)
|
|||||||
struct gl_debug_namespace *next =
|
struct gl_debug_namespace *next =
|
||||||
&debug->Groups[gstack + 1].Namespaces[s][t];
|
&debug->Groups[gstack + 1].Namespaces[s][t];
|
||||||
|
|
||||||
/* copy id settings */
|
if (!debug_namespace_copy(next, nspace))
|
||||||
next->IDs = _mesa_HashClone(nspace->IDs);
|
goto out;
|
||||||
|
|
||||||
for (sev = 0; sev < MESA_DEBUG_SEVERITY_COUNT; sev++) {
|
|
||||||
struct simple_node *node;
|
|
||||||
|
|
||||||
/* copy default settings for unknown ids */
|
|
||||||
next->Defaults[sev] = nspace->Defaults[sev];
|
|
||||||
|
|
||||||
/* copy known id severity settings */
|
|
||||||
make_empty_list(&next->Severity[sev]);
|
|
||||||
foreach(node, &nspace->Severity[sev]) {
|
|
||||||
const struct gl_debug_severity *entry =
|
|
||||||
(const struct gl_debug_severity *) node;
|
|
||||||
struct gl_debug_severity *copy;
|
|
||||||
|
|
||||||
copy = malloc(sizeof *entry);
|
|
||||||
if (!copy)
|
|
||||||
goto out;
|
|
||||||
|
|
||||||
copy->ID = entry->ID;
|
|
||||||
insert_at_tail(&next->Severity[sev], ©->link);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Reference in New Issue
Block a user