mesa: allocate gl_debug_state on demand
authorBrian Paul <brianp@vmware.com>
Fri, 7 Feb 2014 01:21:58 +0000 (18:21 -0700)
committerBrian Paul <brianp@vmware.com>
Sat, 8 Feb 2014 18:27:58 +0000 (11:27 -0700)
We don't need to allocate all the state related to GL_ARB_debug_output
until some aspect of that extension is actually needed.

The sizeof(gl_debug_state) is huge (~285KB on 64-bit systems), not even
counting the 54(!) hash tables and lists that it contains.  This change
reduces the size of gl_context alone from 431KB bytes to 145KB bytes on
64-bit systems and from 277KB bytes to 78KB bytes on 32-bit systems.

Reviewed-by: Reviewed-by: Kenneth Graunke <kenneth@whitecape.org>
src/mesa/drivers/dri/common/dri_util.c
src/mesa/main/enable.c
src/mesa/main/errors.c
src/mesa/main/errors.h
src/mesa/main/get.c
src/mesa/main/get_hash_params.py
src/mesa/main/getstring.c
src/mesa/main/mtypes.h
src/mesa/state_tracker/st_manager.c

index 83841def596b07e8f341b15228c60fde5cf12c7c..d09d50ad1dd7657a63833fdb701c29a71a4cce3c 100644 (file)
@@ -49,6 +49,7 @@
 #include "../glsl/glsl_parser_extras.h"
 #include "main/mtypes.h"
 #include "main/version.h"
+#include "main/errors.h"
 #include "main/macros.h"
 
 PUBLIC const char __dri2ConfigOptions[] =
@@ -448,8 +449,11 @@ driContextSetFlags(struct gl_context *ctx, uint32_t flags)
     if ((flags & __DRI_CTX_FLAG_FORWARD_COMPATIBLE) != 0)
         ctx->Const.ContextFlags |= GL_CONTEXT_FLAG_FORWARD_COMPATIBLE_BIT;
     if ((flags & __DRI_CTX_FLAG_DEBUG) != 0) {
+        struct gl_debug_state *debug = _mesa_get_debug_state(ctx);
+        if (debug) {
+            debug->DebugOutput = GL_TRUE;
+        }
         ctx->Const.ContextFlags |= GL_CONTEXT_FLAG_DEBUG_BIT;
-        ctx->Debug.DebugOutput = GL_TRUE;
     }
 }
 
index 40508a4564347f33b10dc0b49152a4810a356dc5..edd4751e1adea13cd87b58961348e2a4e92088f1 100644 (file)
@@ -32,6 +32,7 @@
 #include "clip.h"
 #include "context.h"
 #include "enable.h"
+#include "errors.h"
 #include "light.h"
 #include "simple_list.h"
 #include "mtypes.h"
@@ -367,14 +368,26 @@ _mesa_set_enable(struct gl_context *ctx, GLenum cap, GLboolean state)
          ctx->Depth.Test = state;
          break;
       case GL_DEBUG_OUTPUT:
-         if (!_mesa_is_desktop_gl(ctx))
+         if (!_mesa_is_desktop_gl(ctx)) {
             goto invalid_enum_error;
-         ctx->Debug.DebugOutput = state;
+         }
+         else {
+            struct gl_debug_state *debug = _mesa_get_debug_state(ctx);
+            if (debug) {
+               debug->DebugOutput = state;
+            }
+         }
          break;
       case GL_DEBUG_OUTPUT_SYNCHRONOUS_ARB:
-         if (!_mesa_is_desktop_gl(ctx))
+         if (!_mesa_is_desktop_gl(ctx)) {
             goto invalid_enum_error;
-         ctx->Debug.SyncOutput = state;
+         }
+         else {
+            struct gl_debug_state *debug = _mesa_get_debug_state(ctx);
+            if (debug) {
+               debug->SyncOutput = state;
+            }
+         }
          break;
       case GL_DITHER:
          if (ctx->Color.DitherFlag == state)
@@ -1228,11 +1241,19 @@ _mesa_IsEnabled( GLenum cap )
       case GL_DEBUG_OUTPUT:
          if (!_mesa_is_desktop_gl(ctx))
             goto invalid_enum_error;
-         return ctx->Debug.DebugOutput;
+         if (ctx->Debug) {
+            return ctx->Debug->DebugOutput;
+         } else {
+            return GL_FALSE;
+         }
       case GL_DEBUG_OUTPUT_SYNCHRONOUS_ARB:
          if (!_mesa_is_desktop_gl(ctx))
             goto invalid_enum_error;
-         return ctx->Debug.SyncOutput;
+         if (ctx->Debug) {
+            return ctx->Debug->SyncOutput;
+         } else {
+            return GL_FALSE;
+         }
       case GL_DEPTH_TEST:
          return ctx->Depth.Test;
       case GL_DITHER:
index dcae2f538dcf53a09c35acb6aaa42b5fc4812067..5f4eac6eb4fd3330b6f0fb68a77731e3ec17ef07 100644 (file)
@@ -118,6 +118,7 @@ gl_enum_to_debug_severity(GLenum e)
    return i;
 }
 
+
 /**
  * Handles generating a GL_ARB_debug_output message ID generated by the GL or
  * GLSL compiler.
@@ -185,6 +186,49 @@ enum {
 };
 
 
+/**
+ * Return debug state for the context.  The debug state will be allocated
+ * and initialized upon the first call.
+ */
+struct gl_debug_state *
+_mesa_get_debug_state(struct gl_context *ctx)
+{
+   if (!ctx->Debug) {
+      ctx->Debug = CALLOC_STRUCT(gl_debug_state);
+      if (!ctx->Debug) {
+         _mesa_error(ctx, GL_OUT_OF_MEMORY, "allocating debug state");
+      }
+      else {
+         struct gl_debug_state *debug = ctx->Debug;
+         int s, t, sev;
+
+         /* Enable all the messages with severity HIGH or MEDIUM by default. */
+         memset(debug->Defaults[0][MESA_DEBUG_SEVERITY_HIGH], GL_TRUE,
+                sizeof debug->Defaults[0][MESA_DEBUG_SEVERITY_HIGH]);
+         memset(debug->Defaults[0][MESA_DEBUG_SEVERITY_MEDIUM], GL_TRUE,
+                sizeof debug->Defaults[0][MESA_DEBUG_SEVERITY_MEDIUM]);
+         memset(debug->Defaults[0][MESA_DEBUG_SEVERITY_LOW], GL_FALSE,
+                sizeof 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++) {
+               debug->Namespaces[0][s][t].IDs = _mesa_NewHashTable();
+               assert(debug->Namespaces[0][s][t].IDs);
+
+               for (sev = 0; sev < MESA_DEBUG_SEVERITY_COUNT; sev++) {
+                  make_empty_list(&debug->Namespaces[0][s][t].Severity[sev]);
+               }
+            }
+         }
+      }
+   }
+
+   return ctx->Debug;
+}
+
+
+
 /**
  * Returns the state of the given message source/type/ID tuple.
  */
@@ -195,50 +239,59 @@ 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[gstack][source][type];
-   uintptr_t state;
+   struct gl_debug_state *debug;
+   uintptr_t state = 0;
 
-   if (!ctx->Debug.DebugOutput)
+   if (!ctx->Debug) {
+      /* no debug state set so far */
       return GL_FALSE;
+   }
 
-   /* 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(nspace->IDs, id);
-   else
-      state = nspace->ZeroID;
+   debug = _mesa_get_debug_state(ctx);
+   if (debug) {
+      const GLint gstack = debug->GroupStackDepth;
+      struct gl_debug_namespace *nspace =
+         &debug->Namespaces[gstack][source][type];
 
-   /* 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 (!debug->DebugOutput)
+         return GL_FALSE;
 
-      if (state == NOT_FOUND) {
-         if (ctx->Debug.Defaults[gstack][severity][source][type])
-            state = ENABLED;
-         else
-            state = DISABLED;
-      }
+      /* 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(nspace->IDs, id);
+      else
+         state = nspace->ZeroID;
 
-      entry = malloc(sizeof *entry);
-      if (!entry)
-         goto out;
+      /* 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 (debug->Defaults[gstack][severity][source][type])
+               state = ENABLED;
+            else
+               state = DISABLED;
+         }
 
-      state |= KNOWN_SEVERITY;
+         entry = malloc(sizeof *entry);
+         if (!entry)
+            goto out;
 
-      if (id)
-         _mesa_HashInsert(nspace->IDs, id, (void*)state);
-      else
-         nspace->ZeroID = state;
+         state |= KNOWN_SEVERITY;
 
-      entry->ID = id;
-      insert_at_tail(&nspace->Severity[severity], &entry->link);
-   }
+         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);
 }
@@ -253,32 +306,36 @@ 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[gstack][source][type];
-   uintptr_t state;
+   struct gl_debug_state *debug = _mesa_get_debug_state(ctx);
 
-   /* 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(nspace->IDs, id);
-   else
-      state = nspace->ZeroID;
-
-   if (state == NOT_FOUND)
-      state = enabled ? ENABLED : DISABLED;
-   else {
-      if (enabled)
-         state |= ENABLED_BIT;
+   if (debug) {
+      GLint gstack = debug->GroupStackDepth;
+      struct gl_debug_namespace *nspace =
+         &debug->Namespaces[gstack][source][type];
+      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(nspace->IDs, id);
       else
-         state &= ~ENABLED_BIT;
-   }
+         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;
+      if (id)
+         _mesa_HashInsert(nspace->IDs, id, (void*)state);
+      else
+         nspace->ZeroID = state;
+   }
 }
 
 
@@ -361,40 +418,44 @@ 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);
    GLint nextEmpty;
    struct gl_debug_msg *emptySlot;
 
+   if (!debug)
+      return;
+
    assert(len >= 0 && len < MAX_DEBUG_MESSAGE_LENGTH);
 
    if (!should_log(ctx, source, type, id, severity))
       return;
 
-   if (ctx->Debug.Callback) {
+   if (debug->Callback) {
        GLenum gl_type = debug_type_enums[type];
        GLenum gl_severity = debug_severity_enums[severity];
 
-       if (ctx->Debug.ARBCallback) {
+       if (debug->ARBCallback) {
           gl_severity = remap_severity(gl_severity);
           gl_type = remap_type(gl_type);
       }
-      ctx->Debug.Callback(debug_source_enums[source], gl_type, id, gl_severity,
-                          len, buf, ctx->Debug.CallbackData);
+      debug->Callback(debug_source_enums[source], gl_type, id, gl_severity,
+                      len, buf, debug->CallbackData);
       return;
    }
 
-   if (ctx->Debug.NumMessages == MAX_DEBUG_LOGGED_MESSAGES)
+   if (debug->NumMessages == MAX_DEBUG_LOGGED_MESSAGES)
       return;
 
-   nextEmpty = (ctx->Debug.NextMsg + ctx->Debug.NumMessages)
+   nextEmpty = (debug->NextMsg + debug->NumMessages)
                           % MAX_DEBUG_LOGGED_MESSAGES;
-   emptySlot = &ctx->Debug.Log[nextEmpty];
+   emptySlot = &debug->Log[nextEmpty];
 
    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;
+   if (debug->NumMessages == 0)
+      debug->NextMsgLength = debug->Log[debug->NextMsg].length;
 
-   ctx->Debug.NumMessages++;
+   debug->NumMessages++;
 }
 
 
@@ -413,16 +474,17 @@ get_msg(struct gl_context *ctx, GLenum *source, GLenum *type,
         GLuint *id, GLenum *severity, GLsizei bufSize, char *buf,
         unsigned caller)
 {
+   struct gl_debug_state *debug = _mesa_get_debug_state(ctx);
    struct gl_debug_msg *msg;
    GLsizei length;
 
-   if (ctx->Debug.NumMessages == 0)
+   if (!debug || debug->NumMessages == 0)
       return 0;
 
-   msg = &ctx->Debug.Log[ctx->Debug.NextMsg];
+   msg = &debug->Log[debug->NextMsg];
    length = msg->length;
 
-   assert(length > 0 && length == ctx->Debug.NextMsgLength);
+   assert(length > 0 && length == debug->NextMsgLength);
 
    if (bufSize < length && buf != NULL)
       return 0;
@@ -457,10 +519,10 @@ get_msg(struct gl_context *ctx, GLenum *source, GLenum *type,
    msg->message = NULL;
    msg->length = 0;
 
-   ctx->Debug.NumMessages--;
-   ctx->Debug.NextMsg++;
-   ctx->Debug.NextMsg %= MAX_DEBUG_LOGGED_MESSAGES;
-   ctx->Debug.NextMsgLength = ctx->Debug.Log[ctx->Debug.NextMsg].length;
+   debug->NumMessages--;
+   debug->NextMsg++;
+   debug->NextMsg %= MAX_DEBUG_LOGGED_MESSAGES;
+   debug->NextMsgLength = debug->Log[debug->NextMsg].length;
 
    return length;
 }
@@ -564,8 +626,12 @@ control_messages(struct gl_context *ctx,
                  enum mesa_debug_severity severity,
                  GLboolean enabled)
 {
+   struct gl_debug_state *debug = _mesa_get_debug_state(ctx);
    int s, t, sev, smax, tmax, sevmax;
-   GLint gstack = ctx->Debug.GroupStackDepth;
+   const GLint gstack = debug ? debug->GroupStackDepth : 0;
+
+   if (!debug)
+      return;
 
    if (source == MESA_DEBUG_SOURCE_COUNT) {
       source = 0;
@@ -595,10 +661,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[gstack][sev][s][t] = enabled;
+            debug->Defaults[gstack][sev][s][t] = enabled;
 
             /* Now change the state of IDs we *have* seen... */
-            foreach(node, &ctx->Debug.Namespaces[gstack][s][t].Severity[sev]) {
+            foreach(node, &debug->Namespaces[gstack][s][t].Severity[sev]) {
                entry = (struct gl_debug_severity *)node;
                set_message_state(ctx, s, t, entry->ID, enabled);
             }
@@ -766,25 +832,32 @@ do_nothing(GLuint key, void *data, void *userData)
 }
 
 
+/**
+ * Free context state pertaining to error/debug state for the given stack
+ * depth.
+ */
 static void
 free_errors_data(struct gl_context *ctx, GLint gstack)
 {
+   struct gl_debug_state *debug = ctx->Debug;
    enum mesa_debug_type t;
    enum mesa_debug_source s;
    enum mesa_debug_severity sev;
 
+   assert(debug);
+
    /* 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,
+         _mesa_HashDeleteAll(debug->Namespaces[gstack][s][t].IDs,
                              do_nothing, NULL);
-         _mesa_DeleteHashTable(ctx->Debug.Namespaces[gstack][s][t].IDs);
+         _mesa_DeleteHashTable(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]) {
+                      &debug->Namespaces[gstack][s][t].Severity[sev]) {
                entry = (struct gl_debug_severity *)node;
                free(entry);
             }
@@ -838,9 +911,12 @@ void GLAPIENTRY
 _mesa_DebugMessageCallback(GLDEBUGPROC callback, const void *userParam)
 {
    GET_CURRENT_CONTEXT(ctx);
-   ctx->Debug.Callback = callback;
-   ctx->Debug.CallbackData = userParam;
-   ctx->Debug.ARBCallback = GL_FALSE;
+   struct gl_debug_state *debug = _mesa_get_debug_state(ctx);
+   if (debug) {
+      debug->Callback = callback;
+      debug->CallbackData = userParam;
+      debug->ARBCallback = GL_FALSE;
+   }
 }
 
 
@@ -848,15 +924,18 @@ void GLAPIENTRY
 _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";
    int s, t, sev;
    GLint prevStackDepth;
    GLint currStackDepth;
    struct gl_debug_msg *emptySlot;
 
-   GET_CURRENT_CONTEXT(ctx);
+   if (!debug)
+      return;
 
-   if (ctx->Debug.GroupStackDepth >= MAX_DEBUG_GROUP_STACK_DEPTH-1) {
+   if (debug->GroupStackDepth >= MAX_DEBUG_GROUP_STACK_DEPTH-1) {
       _mesa_error(ctx, GL_STACK_OVERFLOW, "%s", callerstr);
       return;
    }
@@ -875,14 +954,14 @@ _mesa_PushDebugGroup(GLenum source, GLuint id, GLsizei length,
                   GL_DEBUG_SEVERITY_NOTIFICATION, length,
                   message, callerstr);
 
-   prevStackDepth = ctx->Debug.GroupStackDepth;
-   ctx->Debug.GroupStackDepth++;
-   currStackDepth = ctx->Debug.GroupStackDepth;
+   prevStackDepth = debug->GroupStackDepth;
+   debug->GroupStackDepth++;
+   currStackDepth = 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];
+   emptySlot = &debug->DebugGroupMsgs[debug->GroupStackDepth];
    store_message_details(emptySlot, gl_enum_to_debug_source(source),
                          gl_enum_to_debug_type(GL_DEBUG_TYPE_PUSH_GROUP),
                          id,
@@ -895,27 +974,27 @@ _mesa_PushDebugGroup(GLenum source, GLuint id, GLsizei length,
    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);
+         debug->Namespaces[currStackDepth][s][t].IDs =
+            _mesa_HashClone(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];
+            debug->Defaults[currStackDepth][sev][s][t] =
+               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]) {
+            make_empty_list(&debug->Namespaces[currStackDepth][s][t].Severity[sev]);
+            foreach(node, &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);
+               insert_at_tail(&debug->Namespaces[currStackDepth][s][t].Severity[sev], &entry->link);
             }
          }
       }
@@ -926,21 +1005,24 @@ _mesa_PushDebugGroup(GLenum source, GLuint id, GLsizei length,
 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_msg *gdmessage;
    GLint prevStackDepth;
 
-   GET_CURRENT_CONTEXT(ctx);
+   if (!debug)
+      return;
 
-   if (ctx->Debug.GroupStackDepth <= 0) {
+   if (debug->GroupStackDepth <= 0) {
       _mesa_error(ctx, GL_STACK_UNDERFLOW, "%s", callerstr);
       return;
    }
 
-   prevStackDepth = ctx->Debug.GroupStackDepth;
-   ctx->Debug.GroupStackDepth--;
+   prevStackDepth = debug->GroupStackDepth;
+   debug->GroupStackDepth--;
 
-   gdmessage = &ctx->Debug.DebugGroupMsgs[prevStackDepth];
+   gdmessage = &debug->DebugGroupMsgs[prevStackDepth];
    /* using log_msg() directly here as verification of parameters
     * already done in push
     */
@@ -1005,44 +1087,19 @@ void GLAPIENTRY
 _mesa_DebugMessageCallbackARB(GLDEBUGPROCARB callback, const void *userParam)
 {
    GET_CURRENT_CONTEXT(ctx);
-   ctx->Debug.Callback = callback;
-   ctx->Debug.CallbackData = userParam;
-   ctx->Debug.ARBCallback = GL_TRUE;
+   struct gl_debug_state *debug = _mesa_get_debug_state(ctx);
+   if (debug) {
+      debug->Callback = callback;
+      debug->CallbackData = userParam;
+      debug->ARBCallback = GL_TRUE;
+   }
 }
 
 
 void
 _mesa_init_errors(struct gl_context *ctx)
 {
-   int s, t, sev;
-
-   ctx->Debug.Callback = NULL;
-   ctx->Debug.SyncOutput = GL_FALSE;
-   ctx->Debug.Log[0].length = 0;
-   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[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[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[0][s][t].Severity[sev]);
-         }
-      }
-   }
+   /* no-op */
 }
 
 
@@ -1053,10 +1110,12 @@ _mesa_init_errors(struct gl_context *ctx)
 void
 _mesa_free_errors_data(struct gl_context *ctx)
 {
-   GLint i;
+   if (ctx->Debug) {
+      GLint i;
 
-   for (i = 0; i <= ctx->Debug.GroupStackDepth; i++) {
-      free_errors_data(ctx, i);
+      for (i = 0; i <= ctx->Debug->GroupStackDepth; i++) {
+         free_errors_data(ctx, i);
+      }
    }
 }
 
index a837dc8e1b07c765f42b3cfc1eedde8e5b5d175b..cd414e6b68b27e944e0d3101a54c6fc831763681 100644 (file)
@@ -83,6 +83,9 @@ _mesa_gl_debug(struct gl_context *ctx,
    }                                                                      \
 } while (0)
 
+struct gl_debug_state *
+_mesa_get_debug_state(struct gl_context *ctx);
+
 extern void
 _mesa_shader_debug(struct gl_context *ctx, GLenum type, GLuint *id,
                    const char *msg, int len);
index 54f7d77456a304a65b7563bea6f94ea8380b8ab6..b1908515c25095d16c390e37534278c0f91d017b 100644 (file)
@@ -28,6 +28,7 @@
 #include "blend.h"
 #include "enable.h"
 #include "enums.h"
+#include "errors.h"
 #include "extensions.h"
 #include "get.h"
 #include "macros.h"
@@ -973,6 +974,26 @@ find_custom_value(struct gl_context *ctx, const struct value_desc *d, union valu
          _mesa_problem(ctx, "driver doesn't implement GetTimestamp");
       }
       break;
+   /* GL_KHR_DEBUG */
+   case GL_DEBUG_LOGGED_MESSAGES:
+      {
+         struct gl_debug_state *debug = _mesa_get_debug_state(ctx);
+         v->value_int = debug ? debug->NumMessages : 0;
+      }
+      break;
+   case GL_DEBUG_NEXT_LOGGED_MESSAGE_LENGTH:
+      {
+         struct gl_debug_state *debug = _mesa_get_debug_state(ctx);
+         v->value_int = debug ? debug->NextMsgLength : 0;
+      }
+      break;
+   case GL_DEBUG_GROUP_STACK_DEPTH:
+      {
+         struct gl_debug_state *debug = _mesa_get_debug_state(ctx);
+         v->value_int = debug ? debug->GroupStackDepth : 0;
+      }
+      break;
+
    /* GL_ARB_shader_atomic_counters */
    case GL_ATOMIC_COUNTER_BUFFER_BINDING:
       v->value_int = ctx->AtomicBuffer->Name;
index f47cbd88111917b81f76c3d7380e0dedcd6fd5e1..674d0032af2f6e27663f6ca0c9be3963f9868261 100644 (file)
@@ -698,13 +698,13 @@ descriptor=[
   [ "RESET_NOTIFICATION_STRATEGY_ARB", "CONTEXT_ENUM(Const.ResetStrategy), NO_EXTRA" ],
 
 # GL_KHR_debug (GL 4.3)/ GL_ARB_debug_output
-  [ "DEBUG_LOGGED_MESSAGES", "CONTEXT_INT(Debug.NumMessages), NO_EXTRA" ],
-  [ "DEBUG_NEXT_LOGGED_MESSAGE_LENGTH", "CONTEXT_INT(Debug.NextMsgLength), NO_EXTRA" ],
+  [ "DEBUG_LOGGED_MESSAGES", "LOC_CUSTOM, TYPE_INT, 0, NO_EXTRA" ],
+  [ "DEBUG_NEXT_LOGGED_MESSAGE_LENGTH", "LOC_CUSTOM, TYPE_INT, 0, NO_EXTRA" ],
   [ "MAX_DEBUG_LOGGED_MESSAGES", "CONST(MAX_DEBUG_LOGGED_MESSAGES), NO_EXTRA" ],
   [ "MAX_DEBUG_MESSAGE_LENGTH", "CONST(MAX_DEBUG_MESSAGE_LENGTH), NO_EXTRA" ],
   [ "MAX_LABEL_LENGTH", "CONST(MAX_LABEL_LENGTH), NO_EXTRA" ],
   [ "MAX_DEBUG_GROUP_STACK_DEPTH", "CONST(MAX_DEBUG_GROUP_STACK_DEPTH), NO_EXTRA" ],
-  [ "DEBUG_GROUP_STACK_DEPTH", "CONTEXT_INT(Debug.GroupStackDepth), NO_EXTRA" ],
+  [ "DEBUG_GROUP_STACK_DEPTH", "LOC_CUSTOM, TYPE_INT, 0, NO_EXTRA" ],
 
   [ "MAX_DUAL_SOURCE_DRAW_BUFFERS", "CONTEXT_INT(Const.MaxDualSourceDrawBuffers), extra_ARB_blend_func_extended" ],
 
index 6741267026b716887481f430552a2a2e42920ee2..f8097ef5f27ffc7e2b938b0983a8273d1709058b 100644 (file)
@@ -253,14 +253,22 @@ _mesa_GetPointerv( GLenum pname, GLvoid **params )
          *params = (GLvoid *) ctx->Array.VAO->VertexAttrib[VERT_ATTRIB_POINT_SIZE].Ptr;
          break;
       case GL_DEBUG_CALLBACK_FUNCTION_ARB:
-         if (!_mesa_is_desktop_gl(ctx))
+         if (!_mesa_is_desktop_gl(ctx)) {
             goto invalid_pname;
-         *params = (GLvoid *) ctx->Debug.Callback;
+         }
+         else {
+            struct gl_debug_state *debug = _mesa_get_debug_state(ctx);
+            *params = debug ? (void *) debug->Callback : NULL;
+         }
          break;
       case GL_DEBUG_CALLBACK_USER_PARAM_ARB:
-         if (!_mesa_is_desktop_gl(ctx))
+         if (!_mesa_is_desktop_gl(ctx)) {
             goto invalid_pname;
-         *params = (GLvoid *) ctx->Debug.CallbackData;
+         }
+         else {
+            struct gl_debug_state *debug = _mesa_get_debug_state(ctx);
+            *params = debug ? (void *) debug->CallbackData : NULL;
+         }
          break;
       default:
          goto invalid_pname;
index ceabd9df7fbdbd19254b3a00b54d2a1e6ea60dfb..205b2f2139ef38263abf5f0ecbc8507a66dee433 100644 (file)
@@ -4132,7 +4132,7 @@ struct gl_context
    GLuint ErrorDebugCount;
 
    /* GL_ARB_debug_output/GL_KHR_debug */
-   struct gl_debug_state Debug;
+   struct gl_debug_state *Debug;
 
    GLenum RenderMode;        /**< either GL_RENDER, GL_SELECT, GL_FEEDBACK */
    GLbitfield NewState;      /**< bitwise-or of _NEW_* flags */
index 215b27634f5cc581a9cfeea8cf69e989f67aae0d..6a776a8a236a5883069694345565510613347fee 100644 (file)
@@ -30,6 +30,7 @@
 #include "main/texobj.h"
 #include "main/teximage.h"
 #include "main/texstate.h"
+#include "main/errors.h"
 #include "main/framebuffer.h"
 #include "main/fbobject.h"
 #include "main/renderbuffer.h"
@@ -626,10 +627,14 @@ st_api_create_context(struct st_api *stapi, struct st_manager *smapi,
       return NULL;
    }
 
-   st->ctx->Debug.DebugOutput = GL_FALSE;
    if (attribs->flags & ST_CONTEXT_FLAG_DEBUG){
+      struct gl_debug_state *debug = _mesa_get_debug_state(st->ctx);
+      if (!debug) {
+         *error = ST_CONTEXT_ERROR_NO_MEMORY;
+         return NULL;
+      }
       st->ctx->Const.ContextFlags |= GL_CONTEXT_FLAG_DEBUG_BIT;
-      st->ctx->Debug.DebugOutput = GL_TRUE;
+      debug->DebugOutput = GL_TRUE;
    }
 
    if (attribs->flags & ST_CONTEXT_FLAG_FORWARD_COMPATIBLE)