mesa: allocate gl_debug_state on demand
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>
This commit is contained in:
@@ -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;
|
||||
}
|
||||
}
|
||||
|
||||
|
@@ -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:
|
||||
|
@@ -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,12 +239,21 @@ 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;
|
||||
}
|
||||
|
||||
debug = _mesa_get_debug_state(ctx);
|
||||
if (debug) {
|
||||
const GLint gstack = debug->GroupStackDepth;
|
||||
struct gl_debug_namespace *nspace =
|
||||
&debug->Namespaces[gstack][source][type];
|
||||
|
||||
if (!debug->DebugOutput)
|
||||
return GL_FALSE;
|
||||
|
||||
/* In addition to not being able to store zero as a value, HashTable also
|
||||
@@ -218,7 +271,7 @@ should_log(struct gl_context *ctx,
|
||||
struct gl_debug_severity *entry;
|
||||
|
||||
if (state == NOT_FOUND) {
|
||||
if (ctx->Debug.Defaults[gstack][severity][source][type])
|
||||
if (debug->Defaults[gstack][severity][source][type])
|
||||
state = ENABLED;
|
||||
else
|
||||
state = DISABLED;
|
||||
@@ -238,7 +291,7 @@ should_log(struct gl_context *ctx,
|
||||
entry->ID = id;
|
||||
insert_at_tail(&nspace->Severity[severity], &entry->link);
|
||||
}
|
||||
|
||||
}
|
||||
out:
|
||||
return !!(state & ENABLED_BIT);
|
||||
}
|
||||
@@ -253,9 +306,12 @@ set_message_state(struct gl_context *ctx,
|
||||
enum mesa_debug_type type,
|
||||
GLuint id, GLboolean enabled)
|
||||
{
|
||||
GLint gstack = ctx->Debug.GroupStackDepth;
|
||||
struct gl_debug_state *debug = _mesa_get_debug_state(ctx);
|
||||
|
||||
if (debug) {
|
||||
GLint gstack = debug->GroupStackDepth;
|
||||
struct gl_debug_namespace *nspace =
|
||||
&ctx->Debug.Namespaces[gstack][source][type];
|
||||
&debug->Namespaces[gstack][source][type];
|
||||
uintptr_t state;
|
||||
|
||||
/* In addition to not being able to store zero as a value, HashTable also
|
||||
@@ -279,6 +335,7 @@ set_message_state(struct gl_context *ctx,
|
||||
_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,11 +1110,13 @@ _mesa_init_errors(struct gl_context *ctx)
|
||||
void
|
||||
_mesa_free_errors_data(struct gl_context *ctx)
|
||||
{
|
||||
if (ctx->Debug) {
|
||||
GLint i;
|
||||
|
||||
for (i = 0; i <= ctx->Debug.GroupStackDepth; i++) {
|
||||
for (i = 0; i <= ctx->Debug->GroupStackDepth; i++) {
|
||||
free_errors_data(ctx, i);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
@@ -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);
|
||||
|
@@ -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;
|
||||
|
@@ -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" ],
|
||||
|
||||
|
@@ -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;
|
||||
|
@@ -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 */
|
||||
|
@@ -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)
|
||||
|
Reference in New Issue
Block a user