mesa: remove unused var in _mesa_PushDebugGroup()
[mesa.git] / src / mesa / main / errors.c
index 995fc8205069ec1648d5471337d91214449535b2..366b119aba348a6a2b225ebaf794172dc0474c50 100644 (file)
@@ -28,6 +28,8 @@
  */
 
 
+#include <stdarg.h>
+#include <stdio.h>
 #include "errors.h"
 #include "enums.h"
 #include "imports.h"
@@ -37,6 +39,7 @@
 #include "mtypes.h"
 #include "version.h"
 #include "util/hash_table.h"
+#include "util/simple_list.h"
 
 static mtx_t DynamicIDMutex = _MTX_INITIALIZER_NP;
 static GLuint NextDynamicID = 1;
@@ -134,9 +137,9 @@ static const GLenum debug_severity_enums[] = {
 static enum mesa_debug_source
 gl_enum_to_debug_source(GLenum e)
 {
-   int i;
+   unsigned i;
 
-   for (i = 0; i < Elements(debug_source_enums); i++) {
+   for (i = 0; i < ARRAY_SIZE(debug_source_enums); i++) {
       if (debug_source_enums[i] == e)
          break;
    }
@@ -146,9 +149,9 @@ gl_enum_to_debug_source(GLenum e)
 static enum mesa_debug_type
 gl_enum_to_debug_type(GLenum e)
 {
-   int i;
+   unsigned i;
 
-   for (i = 0; i < Elements(debug_type_enums); i++) {
+   for (i = 0; i < ARRAY_SIZE(debug_type_enums); i++) {
       if (debug_type_enums[i] == e)
          break;
    }
@@ -158,9 +161,9 @@ gl_enum_to_debug_type(GLenum e)
 static enum mesa_debug_severity
 gl_enum_to_debug_severity(GLenum e)
 {
-   int i;
+   unsigned i;
 
-   for (i = 0; i < Elements(debug_severity_enums); i++) {
+   for (i = 0; i < ARRAY_SIZE(debug_severity_enums); i++) {
       if (debug_severity_enums[i] == e)
          break;
    }
@@ -633,7 +636,7 @@ debug_fetch_message(const struct gl_debug_state *debug)
  * Delete the oldest debug messages out of the log.
  */
 static void
-debug_delete_messages(struct gl_debug_state *debug, unsigned count)
+debug_delete_messages(struct gl_debug_state *debug, int count)
 {
    struct gl_debug_log *log = &debug->Log;
 
@@ -676,22 +679,41 @@ debug_pop_group(struct gl_debug_state *debug)
 
 
 /**
- * Return debug state for the context.  The debug state will be allocated
- * and initialized upon the first call.
+ * Lock and return debug state for the context.  The debug state will be
+ * allocated and initialized upon the first call.  When NULL is returned, the
+ * debug state is not locked.
  */
 static struct gl_debug_state *
-_mesa_get_debug_state(struct gl_context *ctx)
+_mesa_lock_debug_state(struct gl_context *ctx)
 {
+   mtx_lock(&ctx->DebugMutex);
+
    if (!ctx->Debug) {
       ctx->Debug = debug_create();
       if (!ctx->Debug) {
-         _mesa_error(ctx, GL_OUT_OF_MEMORY, "allocating debug state");
+         GET_CURRENT_CONTEXT(cur);
+         mtx_unlock(&ctx->DebugMutex);
+
+         /*
+          * This function may be called from other threads.  When that is the
+          * case, we cannot record this OOM error.
+          */
+         if (ctx == cur)
+            _mesa_error(ctx, GL_OUT_OF_MEMORY, "allocating debug state");
+
+         return NULL;
       }
    }
 
    return ctx->Debug;
 }
 
+static void
+_mesa_unlock_debug_state(struct gl_context *ctx)
+{
+   mtx_unlock(&ctx->DebugMutex);
+}
+
 /**
  * Set the integer debug state specified by \p pname.  This can be called from
  * _mesa_set_enable for example.
@@ -699,7 +721,7 @@ _mesa_get_debug_state(struct gl_context *ctx)
 bool
 _mesa_set_debug_state_int(struct gl_context *ctx, GLenum pname, GLint val)
 {
-   struct gl_debug_state *debug = _mesa_get_debug_state(ctx);
+   struct gl_debug_state *debug = _mesa_lock_debug_state(ctx);
 
    if (!debug)
       return false;
@@ -716,6 +738,8 @@ _mesa_set_debug_state_int(struct gl_context *ctx, GLenum pname, GLint val)
       break;
    }
 
+   _mesa_unlock_debug_state(ctx);
+
    return true;
 }
 
@@ -729,9 +753,12 @@ _mesa_get_debug_state_int(struct gl_context *ctx, GLenum pname)
    struct gl_debug_state *debug;
    GLint val;
 
+   mtx_lock(&ctx->DebugMutex);
    debug = ctx->Debug;
-   if (!debug)
+   if (!debug) {
+      mtx_unlock(&ctx->DebugMutex);
       return 0;
+   }
 
    switch (pname) {
    case GL_DEBUG_OUTPUT:
@@ -756,6 +783,8 @@ _mesa_get_debug_state_int(struct gl_context *ctx, GLenum pname)
       break;
    }
 
+   mtx_unlock(&ctx->DebugMutex);
+
    return val;
 }
 
@@ -769,9 +798,12 @@ _mesa_get_debug_state_ptr(struct gl_context *ctx, GLenum pname)
    struct gl_debug_state *debug;
    void *val;
 
+   mtx_lock(&ctx->DebugMutex);
    debug = ctx->Debug;
-   if (!debug)
+   if (!debug) {
+      mtx_unlock(&ctx->DebugMutex);
       return NULL;
+   }
 
    switch (pname) {
    case GL_DEBUG_CALLBACK_FUNCTION_ARB:
@@ -786,9 +818,49 @@ _mesa_get_debug_state_ptr(struct gl_context *ctx, GLenum pname)
       break;
    }
 
+   mtx_unlock(&ctx->DebugMutex);
+
    return val;
 }
 
+/**
+ * Insert a debug message.  The mutex is assumed to be locked, and will be
+ * unlocked by this call.
+ */
+static void
+log_msg_locked_and_unlock(struct gl_context *ctx,
+                          enum mesa_debug_source source,
+                          enum mesa_debug_type type, GLuint id,
+                          enum mesa_debug_severity severity,
+                          GLint len, const char *buf)
+{
+   struct gl_debug_state *debug = ctx->Debug;
+
+   if (!debug_is_message_enabled(debug, source, type, id, severity)) {
+      _mesa_unlock_debug_state(ctx);
+      return;
+   }
+
+   if (ctx->Debug->Callback) {
+      GLenum gl_source = debug_source_enums[source];
+      GLenum gl_type = debug_type_enums[type];
+      GLenum gl_severity = debug_severity_enums[severity];
+      GLDEBUGPROC callback = ctx->Debug->Callback;
+      const void *data = ctx->Debug->CallbackData;
+
+      /*
+       * When ctx->Debug->SyncOutput is GL_FALSE, the client is prepared for
+       * unsynchronous calls.  When it is GL_TRUE, we will not spawn threads.
+       * In either case, we can call the callback unlocked.
+       */
+      _mesa_unlock_debug_state(ctx);
+      callback(gl_source, gl_type, id, gl_severity, len, buf, data);
+   }
+   else {
+      debug_log_message(ctx->Debug, source, type, id, severity, len, buf);
+      _mesa_unlock_debug_state(ctx);
+   }
+}
 
 /**
  * Log a client or driver debug message.
@@ -798,24 +870,12 @@ log_msg(struct gl_context *ctx, enum mesa_debug_source source,
         enum mesa_debug_type type, GLuint id,
         enum mesa_debug_severity severity, GLint len, const char *buf)
 {
-   struct gl_debug_state *debug = _mesa_get_debug_state(ctx);
+   struct gl_debug_state *debug = _mesa_lock_debug_state(ctx);
 
    if (!debug)
       return;
 
-   if (!debug_is_message_enabled(debug, source, type, id, severity))
-      return;
-
-   if (debug->Callback) {
-       GLenum gl_type = debug_type_enums[type];
-       GLenum gl_severity = debug_severity_enums[severity];
-
-      debug->Callback(debug_source_enums[source], gl_type, id, gl_severity,
-                      len, buf, debug->CallbackData);
-      return;
-   }
-
-   debug_log_message(debug, source, type, id, severity, len, buf);
+   log_msg_locked_and_unlock(ctx, source, type, id, severity, len, buf);
 }
 
 
@@ -918,9 +978,13 @@ _mesa_DebugMessageInsert(GLenum source, GLenum type, GLuint id,
                          GLenum severity, GLint length,
                          const GLchar *buf)
 {
-   const char *callerstr = "glDebugMessageInsert";
-
    GET_CURRENT_CONTEXT(ctx);
+   const char *callerstr;
+
+   if (_mesa_is_desktop_gl(ctx))
+      callerstr = "glDebugMessageInsert";
+   else
+      callerstr = "glDebugMessageInsertKHR";
 
    if (!validate_params(ctx, INSERT, callerstr, source, type, severity))
       return; /* GL_INVALID_ENUM */
@@ -944,19 +1008,25 @@ _mesa_GetDebugMessageLog(GLuint count, GLsizei logSize, GLenum *sources,
 {
    GET_CURRENT_CONTEXT(ctx);
    struct gl_debug_state *debug;
+   const char *callerstr;
    GLuint ret;
 
+   if (_mesa_is_desktop_gl(ctx))
+      callerstr = "glGetDebugMessageLog";
+   else
+      callerstr = "glGetDebugMessageLogKHR";
+
    if (!messageLog)
       logSize = 0;
 
    if (logSize < 0) {
       _mesa_error(ctx, GL_INVALID_VALUE,
-                  "glGetDebugMessageLog(logSize=%d : logSize must not be"
-                  " negative)", logSize);
+                  "%s(logSize=%d : logSize must not be negative)",
+                  callerstr, logSize);
       return 0;
    }
 
-   debug = _mesa_get_debug_state(ctx);
+   debug = _mesa_lock_debug_state(ctx);
    if (!debug)
       return 0;
 
@@ -991,6 +1061,8 @@ _mesa_GetDebugMessageLog(GLuint count, GLsizei logSize, GLenum *sources,
       debug_delete_messages(debug, 1);
    }
 
+   _mesa_unlock_debug_state(ctx);
+
    return ret;
 }
 
@@ -1004,9 +1076,14 @@ _mesa_DebugMessageControl(GLenum gl_source, GLenum gl_type,
    enum mesa_debug_source source = gl_enum_to_debug_source(gl_source);
    enum mesa_debug_type type = gl_enum_to_debug_type(gl_type);
    enum mesa_debug_severity severity = gl_enum_to_debug_severity(gl_severity);
-   const char *callerstr = "glDebugMessageControl";
+   const char *callerstr;
    struct gl_debug_state *debug;
 
+   if (_mesa_is_desktop_gl(ctx))
+      callerstr = "glDebugMessageControl";
+   else
+      callerstr = "glDebugMessageControlKHR";
+
    if (count < 0) {
       _mesa_error(ctx, GL_INVALID_VALUE,
                   "%s(count=%d : count must not be negative)", callerstr,
@@ -1027,7 +1104,7 @@ _mesa_DebugMessageControl(GLenum gl_source, GLenum gl_type,
       return;
    }
 
-   debug = _mesa_get_debug_state(ctx);
+   debug = _mesa_lock_debug_state(ctx);
    if (!debug)
       return;
 
@@ -1039,6 +1116,8 @@ _mesa_DebugMessageControl(GLenum gl_source, GLenum gl_type,
    else {
       debug_set_message_enable_all(debug, source, type, severity, enabled);
    }
+
+   _mesa_unlock_debug_state(ctx);
 }
 
 
@@ -1046,10 +1125,11 @@ void GLAPIENTRY
 _mesa_DebugMessageCallback(GLDEBUGPROC callback, const void *userParam)
 {
    GET_CURRENT_CONTEXT(ctx);
-   struct gl_debug_state *debug = _mesa_get_debug_state(ctx);
+   struct gl_debug_state *debug = _mesa_lock_debug_state(ctx);
    if (debug) {
       debug->Callback = callback;
       debug->CallbackData = userParam;
+      _mesa_unlock_debug_state(ctx);
    }
 }
 
@@ -1059,17 +1139,14 @@ _mesa_PushDebugGroup(GLenum source, GLuint id, GLsizei length,
                      const GLchar *message)
 {
    GET_CURRENT_CONTEXT(ctx);
-   struct gl_debug_state *debug = _mesa_get_debug_state(ctx);
-   const char *callerstr = "glPushDebugGroup";
+   const char *callerstr;
+   struct gl_debug_state *debug;
    struct gl_debug_message *emptySlot;
 
-   if (!debug)
-      return;
-
-   if (debug->GroupStackDepth >= MAX_DEBUG_GROUP_STACK_DEPTH-1) {
-      _mesa_error(ctx, GL_STACK_OVERFLOW, "%s", callerstr);
-      return;
-   }
+   if (_mesa_is_desktop_gl(ctx))
+      callerstr = "glPushDebugGroup";
+   else
+      callerstr = "glPushDebugGroupKHR";
 
    switch(source) {
    case GL_DEBUG_SOURCE_APPLICATION:
@@ -1086,10 +1163,15 @@ _mesa_PushDebugGroup(GLenum source, GLuint id, GLsizei length,
    if (!validate_length(ctx, callerstr, length))
       return; /* GL_INVALID_VALUE */
 
-   log_msg(ctx, gl_enum_to_debug_source(source),
-           MESA_DEBUG_TYPE_PUSH_GROUP, id,
-           MESA_DEBUG_SEVERITY_NOTIFICATION, length,
-           message);
+   debug = _mesa_lock_debug_state(ctx);
+   if (!debug)
+      return;
+
+   if (debug->GroupStackDepth >= MAX_DEBUG_GROUP_STACK_DEPTH-1) {
+      _mesa_unlock_debug_state(ctx);
+      _mesa_error(ctx, GL_STACK_OVERFLOW, "%s", callerstr);
+      return;
+   }
 
    /* pop reuses the message details from push so we store this */
    emptySlot = debug_get_group_message(debug);
@@ -1101,6 +1183,12 @@ _mesa_PushDebugGroup(GLenum source, GLuint id, GLsizei length,
                        length, message);
 
    debug_push_group(debug);
+
+   log_msg_locked_and_unlock(ctx,
+         gl_enum_to_debug_source(source),
+         MESA_DEBUG_TYPE_PUSH_GROUP, id,
+         MESA_DEBUG_SEVERITY_NOTIFICATION, length,
+         message);
 }
 
 
@@ -1108,35 +1196,48 @@ void GLAPIENTRY
 _mesa_PopDebugGroup(void)
 {
    GET_CURRENT_CONTEXT(ctx);
-   struct gl_debug_state *debug = _mesa_get_debug_state(ctx);
-   const char *callerstr = "glPopDebugGroup";
-   struct gl_debug_message *gdmessage;
+   const char *callerstr;
+   struct gl_debug_state *debug;
+   struct gl_debug_message *gdmessage, msg;
+
+   if (_mesa_is_desktop_gl(ctx))
+      callerstr = "glPopDebugGroup";
+   else
+      callerstr = "glPopDebugGroupKHR";
 
+   debug = _mesa_lock_debug_state(ctx);
    if (!debug)
       return;
 
    if (debug->GroupStackDepth <= 0) {
+      _mesa_unlock_debug_state(ctx);
       _mesa_error(ctx, GL_STACK_UNDERFLOW, "%s", callerstr);
       return;
    }
 
    debug_pop_group(debug);
 
+   /* make a shallow copy */
    gdmessage = debug_get_group_message(debug);
-   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);
-
-   debug_message_clear(gdmessage);
+   msg = *gdmessage;
+   gdmessage->message = NULL;
+   gdmessage->length = 0;
+
+   log_msg_locked_and_unlock(ctx,
+         msg.source,
+         gl_enum_to_debug_type(GL_DEBUG_TYPE_POP_GROUP),
+         msg.id,
+         gl_enum_to_debug_severity(GL_DEBUG_SEVERITY_NOTIFICATION),
+         msg.length, msg.message);
+
+   debug_message_clear(&msg);
 }
 
 
 void
 _mesa_init_errors(struct gl_context *ctx)
 {
-   /* no-op */
+   mtx_init(&ctx->DebugMutex, mtx_plain);
 }
 
 
@@ -1148,6 +1249,8 @@ _mesa_free_errors_data(struct gl_context *ctx)
       /* set to NULL just in case it is used before context is completely gone. */
       ctx->Debug = NULL;
    }
+
+   mtx_destroy(&ctx->DebugMutex);
 }
 
 
@@ -1155,12 +1258,14 @@ _mesa_free_errors_data(struct gl_context *ctx)
 /** \name Diagnostics */
 /*@{*/
 
+static FILE *LogFile = NULL;
+
+
 static void
 output_if_debug(const char *prefixString, const char *outputString,
                 GLboolean newline)
 {
    static int debug = -1;
-   static FILE *fout = NULL;
 
    /* Init the local 'debug' var once.
     * Note: the _mesa_init_debug() function should have been called
@@ -1170,11 +1275,11 @@ output_if_debug(const char *prefixString, const char *outputString,
       /* If MESA_LOG_FILE env var is set, log Mesa errors, warnings,
        * etc to the named file.  Otherwise, output to stderr.
        */
-      const char *logFile = _mesa_getenv("MESA_LOG_FILE");
+      const char *logFile = getenv("MESA_LOG_FILE");
       if (logFile)
-         fout = fopen(logFile, "w");
-      if (!fout)
-         fout = stderr;
+         LogFile = fopen(logFile, "w");
+      if (!LogFile)
+         LogFile = stderr;
 #ifdef DEBUG
       /* in debug builds, print messages unless MESA_DEBUG="silent" */
       if (MESA_DEBUG_FLAGS & DEBUG_SILENT)
@@ -1183,16 +1288,19 @@ output_if_debug(const char *prefixString, const char *outputString,
          debug = 1;
 #else
       /* in release builds, be silent unless MESA_DEBUG is set */
-      debug = _mesa_getenv("MESA_DEBUG") != NULL;
+      debug = getenv("MESA_DEBUG") != NULL;
 #endif
    }
 
    /* Now only print the string if we're required to do so. */
    if (debug) {
-      fprintf(fout, "%s: %s", prefixString, outputString);
+      if (prefixString)
+         fprintf(LogFile, "%s: %s", prefixString, outputString);
+      else
+         fprintf(LogFile, "%s", outputString);
       if (newline)
-         fprintf(fout, "\n");
-      fflush(fout);
+         fprintf(LogFile, "\n");
+      fflush(LogFile);
 
 #if defined(_WIN32)
       /* stderr from windows applications without console is not usually 
@@ -1207,6 +1315,18 @@ output_if_debug(const char *prefixString, const char *outputString,
 }
 
 
+/**
+ * Return the file handle to use for debug/logging.  Defaults to stderr
+ * unless MESA_LOG_FILE is defined.
+ */
+FILE *
+_mesa_get_log_file(void)
+{
+   assert(LogFile);
+   return LogFile;
+}
+
+
 /**
  * When a new type of error is recorded, print a message describing
  * previous errors which were accumulated.
@@ -1219,7 +1339,7 @@ flush_delayed_errors( struct gl_context *ctx )
    if (ctx->ErrorDebugCount) {
       _mesa_snprintf(s, MAX_DEBUG_MESSAGE_LENGTH, "%d similar %s errors", 
                      ctx->ErrorDebugCount,
-                     _mesa_lookup_enum_by_nr(ctx->ErrorValue));
+                     _mesa_enum_to_string(ctx->ErrorValue));
 
       output_if_debug("Mesa", s, GL_TRUE);
 
@@ -1288,7 +1408,7 @@ should_output(struct gl_context *ctx, GLenum error, const char *fmtString)
    /* Check debug environment variable only once:
     */
    if (debug == -1) {
-      const char *debugEnv = _mesa_getenv("MESA_DEBUG");
+      const char *debugEnv = getenv("MESA_DEBUG");
 
 #ifdef DEBUG
       if (debugEnv && strstr(debugEnv, "silent"))
@@ -1317,24 +1437,38 @@ should_output(struct gl_context *ctx, GLenum error, const char *fmtString)
 }
 
 
+void
+_mesa_gl_vdebug(struct gl_context *ctx,
+                GLuint *id,
+                enum mesa_debug_source source,
+                enum mesa_debug_type type,
+                enum mesa_debug_severity severity,
+                const char *fmtString,
+                va_list args)
+{
+   char s[MAX_DEBUG_MESSAGE_LENGTH];
+   int len;
+
+   debug_get_id(id);
+
+   len = _mesa_vsnprintf(s, MAX_DEBUG_MESSAGE_LENGTH, fmtString, args);
+
+   log_msg(ctx, source, type, *id, severity, len, s);
+}
+
+
 void
 _mesa_gl_debug(struct gl_context *ctx,
                GLuint *id,
+               enum mesa_debug_source source,
                enum mesa_debug_type type,
                enum mesa_debug_severity severity,
                const char *fmtString, ...)
 {
-   char s[MAX_DEBUG_MESSAGE_LENGTH];
-   int len;
    va_list args;
-
-   debug_get_id(id);
-
    va_start(args, fmtString);
-   len = _mesa_vsnprintf(s, MAX_DEBUG_MESSAGE_LENGTH, fmtString, args);
+   _mesa_gl_vdebug(ctx, id, source, type, severity, fmtString, args);
    va_end(args);
-
-   log_msg(ctx, MESA_DEBUG_SOURCE_API, type, *id, severity, len, s);
 }
 
 
@@ -1362,6 +1496,8 @@ _mesa_error( struct gl_context *ctx, GLenum error, const char *fmtString, ... )
    debug_get_id(&error_msg_id);
 
    do_output = should_output(ctx, error, fmtString);
+
+   mtx_lock(&ctx->DebugMutex);
    if (ctx->Debug) {
       do_log = debug_is_message_enabled(ctx->Debug,
                                         MESA_DEBUG_SOURCE_API,
@@ -1372,6 +1508,7 @@ _mesa_error( struct gl_context *ctx, GLenum error, const char *fmtString, ... )
    else {
       do_log = GL_FALSE;
    }
+   mtx_unlock(&ctx->DebugMutex);
 
    if (do_output || do_log) {
       char s[MAX_DEBUG_MESSAGE_LENGTH], s2[MAX_DEBUG_MESSAGE_LENGTH];
@@ -1386,15 +1523,15 @@ _mesa_error( struct gl_context *ctx, GLenum error, const char *fmtString, ... )
          /* Too long error message. Whoever calls _mesa_error should use
           * shorter strings.
           */
-         ASSERT(0);
+         assert(0);
          return;
       }
 
       len = _mesa_snprintf(s2, MAX_DEBUG_MESSAGE_LENGTH, "%s in %s",
-                           _mesa_lookup_enum_by_nr(error), s);
+                           _mesa_enum_to_string(error), s);
       if (len >= MAX_DEBUG_MESSAGE_LENGTH) {
          /* Same as above. */
-         ASSERT(0);
+         assert(0);
          return;
       }
 
@@ -1444,6 +1581,18 @@ _mesa_debug( const struct gl_context *ctx, const char *fmtString, ... )
 }
 
 
+void
+_mesa_log(const char *fmtString, ...)
+{
+   char s[MAX_DEBUG_MESSAGE_LENGTH];
+   va_list args;
+   va_start(args, fmtString);
+   _mesa_vsnprintf(s, MAX_DEBUG_MESSAGE_LENGTH, fmtString, args);
+   va_end(args);
+   output_if_debug("", s, GL_FALSE);
+}
+
+
 /**
  * Report debug information from the shader compiler via GL_ARB_debug_output.
  *