mesa: update fallthrough comment so gcc can see it
[mesa.git] / src / mesa / main / debug_output.c
index c2b9f0533528eb3c95363530e3bee47977800564..3f1ca8bf3403109505f6da7eb9b9227ae6984ce3 100644 (file)
 #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;
 
 
@@ -46,7 +46,7 @@ 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 */
@@ -56,7 +56,7 @@ struct gl_debug_element
 
 struct gl_debug_namespace
 {
-   struct simple_node Elements;
+   struct list_head Elements;
    GLbitfield DefaultState;
 };
 
@@ -99,6 +99,7 @@ struct gl_debug_state
    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];
@@ -193,10 +194,10 @@ void
 _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);
    }
 }
 
@@ -250,7 +251,7 @@ debug_message_store(struct gl_debug_message *msg,
 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 ) |
@@ -261,24 +262,18 @@ debug_namespace_init(struct gl_debug_namespace *ns)
 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));
@@ -289,7 +284,7 @@ debug_namespace_copy(struct gl_debug_namespace *dst,
 
       copy->ID = elem->ID;
       copy->State = elem->State;
-      insert_at_tail(&dst->Elements, &copy->link);
+      list_addtail(&copy->link, &dst->Elements);
    }
 
    return true;
@@ -305,11 +300,9 @@ debug_namespace_set(struct gl_debug_namespace *ns,
    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;
@@ -319,7 +312,7 @@ debug_namespace_set(struct gl_debug_namespace *ns,
    /* 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;
@@ -331,7 +324,7 @@ debug_namespace_set(struct gl_debug_namespace *ns,
          return false;
 
       elem->ID = id;
-      insert_at_tail(&ns->Elements, &elem->link);
+      list_addtail(&elem->link, &ns->Elements);
    }
 
    elem->State = state;
@@ -349,14 +342,13 @@ debug_namespace_set_all(struct gl_debug_namespace *ns,
                         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;
    }
 
@@ -365,13 +357,12 @@ debug_namespace_set_all(struct gl_debug_namespace *ns,
 
    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);
       }
    }
 }
@@ -383,13 +374,10 @@ static bool
 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;
@@ -500,6 +488,28 @@ debug_clear_group(struct gl_debug_state *debug)
    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.
@@ -513,6 +523,7 @@ debug_destroy(struct gl_debug_state *debug)
    }
 
    debug_clear_group(debug);
+   debug_delete_messages(debug, debug->Log.NumMessages);
    free(debug);
 }
 
@@ -617,6 +628,10 @@ debug_log_message(struct gl_debug_state *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)
@@ -643,28 +658,6 @@ debug_fetch_message(const struct gl_debug_state *debug)
    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)
 {
@@ -697,13 +690,13 @@ debug_pop_group(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
@@ -722,7 +715,7 @@ _mesa_lock_debug_state(struct gl_context *ctx)
 static void
 _mesa_unlock_debug_state(struct gl_context *ctx)
 {
-   mtx_unlock(&ctx->DebugMutex);
+   simple_mtx_unlock(&ctx->DebugMutex);
 }
 
 /**
@@ -779,7 +772,7 @@ _mesa_get_debug_state_int(struct gl_context *ctx, GLenum pname)
       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;
@@ -845,6 +838,7 @@ log_msg_locked_and_unlock(struct gl_context *ctx,
    }
 
    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];
@@ -860,6 +854,7 @@ log_msg_locked_and_unlock(struct gl_context *ctx,
       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);
    }
@@ -1009,15 +1004,16 @@ _mesa_DebugMessageInsert(GLenum source, GLenum type, GLuint id,
    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);
    }
 }
@@ -1188,6 +1184,9 @@ _mesa_PushDebugGroup(GLenum source, GLuint id, GLsizei 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;
@@ -1262,7 +1261,22 @@ _mesa_PopDebugGroup(void)
 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);
+   }
 }
 
 
@@ -1275,7 +1289,7 @@ _mesa_free_errors_data(struct gl_context *ctx)
       ctx->Debug = NULL;
    }
 
-   mtx_destroy(&ctx->DebugMutex);
+   simple_mtx_destroy(&ctx->DebugMutex);
 }
 
 void GLAPIENTRY