#include <stdio.h>
#include "context.h"
#include "debug_output.h"
-#include "dispatch.h"
#include "enums.h"
-#include "imports.h"
+
#include "hash.h"
#include "mtypes.h"
#include "version.h"
#include "util/hash_table.h"
-#include "util/simple_list.h"
+#include "util/list.h"
+#include "util/u_memory.h"
-static mtx_t DynamicIDMutex = _MTX_INITIALIZER_NP;
+static simple_mtx_t DynamicIDMutex = _SIMPLE_MTX_INITIALIZER_NP;
static GLuint NextDynamicID = 1;
*/
struct gl_debug_element
{
- struct simple_node link;
+ struct list_head link;
GLuint ID;
/* at which severity levels (mesa_debug_severity) is the message enabled */
struct gl_debug_namespace
{
- struct simple_node Elements;
+ struct list_head Elements;
GLbitfield DefaultState;
};
const void *CallbackData;
GLboolean SyncOutput;
GLboolean DebugOutput;
+ GLboolean LogToStderr;
struct gl_debug_group *Groups[MAX_DEBUG_GROUP_STACK_DEPTH];
struct gl_debug_message GroupMessages[MAX_DEBUG_GROUP_STACK_DEPTH];
_mesa_debug_get_id(GLuint *id)
{
if (!(*id)) {
- mtx_lock(&DynamicIDMutex);
+ simple_mtx_lock(&DynamicIDMutex);
if (!(*id))
*id = NextDynamicID++;
- mtx_unlock(&DynamicIDMutex);
+ simple_mtx_unlock(&DynamicIDMutex);
}
}
static void
debug_namespace_init(struct gl_debug_namespace *ns)
{
- make_empty_list(&ns->Elements);
+ list_inithead(&ns->Elements);
/* Enable all the messages with severity HIGH or MEDIUM by default */
ns->DefaultState = (1 << MESA_DEBUG_SEVERITY_MEDIUM ) |
static void
debug_namespace_clear(struct gl_debug_namespace *ns)
{
- struct simple_node *node, *tmp;
-
- foreach_s(node, tmp, &ns->Elements)
- free(node);
+ list_for_each_entry_safe(struct gl_debug_element, elem, &ns->Elements, link)
+ free(elem);
}
static bool
debug_namespace_copy(struct gl_debug_namespace *dst,
const struct gl_debug_namespace *src)
{
- struct simple_node *node;
-
dst->DefaultState = src->DefaultState;
- make_empty_list(&dst->Elements);
- foreach(node, &src->Elements) {
- const struct gl_debug_element *elem =
- (const struct gl_debug_element *) node;
+ list_inithead(&dst->Elements);
+ list_for_each_entry(struct gl_debug_element, elem, &src->Elements, link) {
struct gl_debug_element *copy;
copy = malloc(sizeof(*copy));
copy->ID = elem->ID;
copy->State = elem->State;
- insert_at_tail(&dst->Elements, ©->link);
+ list_addtail(©->link, &dst->Elements);
}
return true;
const uint32_t state = (enabled) ?
((1 << MESA_DEBUG_SEVERITY_COUNT) - 1) : 0;
struct gl_debug_element *elem = NULL;
- struct simple_node *node;
/* find the element */
- foreach(node, &ns->Elements) {
- struct gl_debug_element *tmp = (struct gl_debug_element *) node;
+ list_for_each_entry(struct gl_debug_element, tmp, &ns->Elements, link) {
if (tmp->ID == id) {
elem = tmp;
break;
/* we do not need the element if it has the default state */
if (ns->DefaultState == state) {
if (elem) {
- remove_from_list(&elem->link);
+ list_del(&elem->link);
free(elem);
}
return true;
return false;
elem->ID = id;
- insert_at_tail(&ns->Elements, &elem->link);
+ list_addtail(&elem->link, &ns->Elements);
}
elem->State = state;
enum mesa_debug_severity severity,
bool enabled)
{
- struct simple_node *node, *tmp;
uint32_t mask, val;
/* set all elements to the same state */
if (severity == MESA_DEBUG_SEVERITY_COUNT) {
ns->DefaultState = (enabled) ? ((1 << severity) - 1) : 0;
debug_namespace_clear(ns);
- make_empty_list(&ns->Elements);
+ list_inithead(&ns->Elements);
return;
}
ns->DefaultState = (ns->DefaultState & ~mask) | val;
- foreach_s(node, tmp, &ns->Elements) {
- struct gl_debug_element *elem = (struct gl_debug_element *) node;
-
+ list_for_each_entry_safe(struct gl_debug_element, elem, &ns->Elements,
+ link) {
elem->State = (elem->State & ~mask) | val;
if (elem->State == ns->DefaultState) {
- remove_from_list(node);
- free(node);
+ list_del(&elem->link);
+ free(elem);
}
}
}
debug_namespace_get(const struct gl_debug_namespace *ns, GLuint id,
enum mesa_debug_severity severity)
{
- struct simple_node *node;
uint32_t state;
state = ns->DefaultState;
- foreach(node, &ns->Elements) {
- struct gl_debug_element *elem = (struct gl_debug_element *) node;
-
+ list_for_each_entry(struct gl_debug_element, elem, &ns->Elements, link) {
if (elem->ID == id) {
state = elem->State;
break;
debug->Groups[gstack] = NULL;
}
+/**
+ * Delete the oldest debug messages out of the log.
+ */
+static void
+debug_delete_messages(struct gl_debug_state *debug, int count)
+{
+ struct gl_debug_log *log = &debug->Log;
+
+ if (count > log->NumMessages)
+ count = log->NumMessages;
+
+ while (count--) {
+ struct gl_debug_message *msg = &log->Messages[log->NextMessage];
+
+ debug_message_clear(msg);
+
+ log->NumMessages--;
+ log->NextMessage++;
+ log->NextMessage %= MAX_DEBUG_LOGGED_MESSAGES;
+ }
+}
+
/**
* Loop through debug group stack tearing down states for
* filtering debug messages. Then free debug output state.
}
debug_clear_group(debug);
+ debug_delete_messages(debug, debug->Log.NumMessages);
free(debug);
}
GLint nextEmpty;
struct gl_debug_message *emptySlot;
+ if (debug->LogToStderr) {
+ _mesa_log("Mesa debug output: %.*s\n", len, buf);
+ }
+
assert(len < MAX_DEBUG_MESSAGE_LENGTH);
if (log->NumMessages == MAX_DEBUG_LOGGED_MESSAGES)
return (log->NumMessages) ? &log->Messages[log->NextMessage] : NULL;
}
-/**
- * Delete the oldest debug messages out of the log.
- */
-static void
-debug_delete_messages(struct gl_debug_state *debug, int count)
-{
- struct gl_debug_log *log = &debug->Log;
-
- if (count > log->NumMessages)
- count = log->NumMessages;
-
- while (count--) {
- struct gl_debug_message *msg = &log->Messages[log->NextMessage];
-
- debug_message_clear(msg);
-
- log->NumMessages--;
- log->NextMessage++;
- log->NextMessage %= MAX_DEBUG_LOGGED_MESSAGES;
- }
-}
-
static struct gl_debug_message *
debug_get_group_message(struct gl_debug_state *debug)
{
static struct gl_debug_state *
_mesa_lock_debug_state(struct gl_context *ctx)
{
- mtx_lock(&ctx->DebugMutex);
+ simple_mtx_lock(&ctx->DebugMutex);
if (!ctx->Debug) {
ctx->Debug = debug_create();
if (!ctx->Debug) {
GET_CURRENT_CONTEXT(cur);
- mtx_unlock(&ctx->DebugMutex);
+ simple_mtx_unlock(&ctx->DebugMutex);
/*
* This function may be called from other threads. When that is the
static void
_mesa_unlock_debug_state(struct gl_context *ctx)
{
- mtx_unlock(&ctx->DebugMutex);
+ simple_mtx_unlock(&ctx->DebugMutex);
}
/**
break;
case GL_DEBUG_NEXT_LOGGED_MESSAGE_LENGTH:
val = (debug->Log.NumMessages) ?
- debug->Log.Messages[debug->Log.NextMessage].length : 0;
+ debug->Log.Messages[debug->Log.NextMessage].length + 1 : 0;
break;
case GL_DEBUG_GROUP_STACK_DEPTH:
val = debug->CurrentGroup + 1;
}
if (ctx->Debug->Callback) {
+ /* Call the user's callback function */
GLenum gl_source = debug_source_enums[source];
GLenum gl_type = debug_type_enums[type];
GLenum gl_severity = debug_severity_enums[severity];
callback(gl_source, gl_type, id, gl_severity, len, buf, data);
}
else {
+ /* add debug message to queue */
debug_log_message(ctx->Debug, source, type, id, severity, len, buf);
_mesa_unlock_debug_state(ctx);
}
if (!validate_length(ctx, callerstr, length, buf))
return; /* GL_INVALID_VALUE */
+ /* if length not specified, string will be null terminated: */
+ if (length < 0)
+ length = strlen(buf);
+
_mesa_log_msg(ctx, gl_enum_to_debug_source(source),
gl_enum_to_debug_type(type), id,
gl_enum_to_debug_severity(severity),
length, buf);
if (type == GL_DEBUG_TYPE_MARKER && ctx->Driver.EmitStringMarker) {
- /* if length not specified, string will be null terminated: */
- if (length < 0)
- length = strlen(buf);
ctx->Driver.EmitStringMarker(ctx, buf, length);
}
}
if (!validate_length(ctx, callerstr, length, message))
return; /* GL_INVALID_VALUE */
+ if (length < 0)
+ length = strlen(message);
+
debug = _mesa_lock_debug_state(ctx);
if (!debug)
return;
void
_mesa_init_debug_output(struct gl_context *ctx)
{
- mtx_init(&ctx->DebugMutex, mtx_plain);
+ simple_mtx_init(&ctx->DebugMutex, mtx_plain);
+
+ if (MESA_DEBUG_FLAGS & DEBUG_CONTEXT) {
+ /* If the MESA_DEBUG env is set to "context", we'll turn on the
+ * GL_CONTEXT_FLAG_DEBUG_BIT context flag and log debug output
+ * messages to stderr (or whatever MESA_LOG_FILE points at).
+ */
+ struct gl_debug_state *debug = _mesa_lock_debug_state(ctx);
+ if (!debug) {
+ return;
+ }
+ debug->DebugOutput = GL_TRUE;
+ debug->LogToStderr = GL_TRUE;
+ ctx->Const.ContextFlags |= GL_CONTEXT_FLAG_DEBUG_BIT;
+ _mesa_unlock_debug_state(ctx);
+ }
}
ctx->Debug = NULL;
}
- mtx_destroy(&ctx->DebugMutex);
+ simple_mtx_destroy(&ctx->DebugMutex);
}
void GLAPIENTRY