diff options
Diffstat (limited to 'mesalib/src/mesa/main')
25 files changed, 954 insertions, 189 deletions
diff --git a/mesalib/src/mesa/main/arrayobj.c b/mesalib/src/mesa/main/arrayobj.c index 922605034..5d50d29f8 100644 --- a/mesalib/src/mesa/main/arrayobj.c +++ b/mesalib/src/mesa/main/arrayobj.c @@ -60,8 +60,8 @@ * non-existent. */ -static inline struct gl_array_object * -lookup_arrayobj(struct gl_context *ctx, GLuint id) +struct gl_array_object * +_mesa_lookup_arrayobj(struct gl_context *ctx, GLuint id) { if (id == 0) return NULL; @@ -115,6 +115,7 @@ _mesa_delete_array_object( struct gl_context *ctx, struct gl_array_object *obj ) unbind_array_object_vbos(ctx, obj); _mesa_reference_buffer_object(ctx, &obj->ElementArrayBufferObj, NULL); _glthread_DESTROY_MUTEX(obj->Mutex); + free(obj->Label); free(obj); } @@ -353,7 +354,7 @@ bind_vertex_array(struct gl_context *ctx, GLuint id, GLboolean genRequired) } else { /* non-default array object */ - newObj = lookup_arrayobj(ctx, id); + newObj = _mesa_lookup_arrayobj(ctx, id); if (!newObj) { if (genRequired) { _mesa_error(ctx, GL_INVALID_OPERATION, "glBindVertexArray(non-gen name)"); @@ -439,7 +440,7 @@ _mesa_DeleteVertexArrays(GLsizei n, const GLuint *ids) } for (i = 0; i < n; i++) { - struct gl_array_object *obj = lookup_arrayobj(ctx, ids[i]); + struct gl_array_object *obj = _mesa_lookup_arrayobj(ctx, ids[i]); if ( obj != NULL ) { ASSERT( obj->Name == ids[i] ); @@ -545,7 +546,7 @@ _mesa_IsVertexArray( GLuint id ) if (id == 0) return GL_FALSE; - obj = lookup_arrayobj(ctx, id); + obj = _mesa_lookup_arrayobj(ctx, id); if (obj == NULL) return GL_FALSE; diff --git a/mesalib/src/mesa/main/arrayobj.h b/mesalib/src/mesa/main/arrayobj.h index 6dee1af69..492ef3501 100644 --- a/mesalib/src/mesa/main/arrayobj.h +++ b/mesalib/src/mesa/main/arrayobj.h @@ -46,6 +46,9 @@ struct gl_context; */ extern struct gl_array_object * +_mesa_lookup_arrayobj(struct gl_context *ctx, GLuint id); + +extern struct gl_array_object * _mesa_new_array_object( struct gl_context *ctx, GLuint name ); extern void diff --git a/mesalib/src/mesa/main/bufferobj.c b/mesalib/src/mesa/main/bufferobj.c index bba061916..ab5bbbf6d 100644 --- a/mesalib/src/mesa/main/bufferobj.c +++ b/mesalib/src/mesa/main/bufferobj.c @@ -265,6 +265,7 @@ _mesa_delete_buffer_object(struct gl_context *ctx, bufObj->Name = ~0; _glthread_DESTROY_MUTEX(bufObj->Mutex); + free(bufObj->Label); free(bufObj); } diff --git a/mesalib/src/mesa/main/config.h b/mesalib/src/mesa/main/config.h index f84461263..fcb8952ff 100644 --- a/mesalib/src/mesa/main/config.h +++ b/mesalib/src/mesa/main/config.h @@ -253,12 +253,17 @@ #define MAX_GEOMETRY_TOTAL_OUTPUT_COMPONENTS 1024 /*@}*/ -/** For GL_ARB_debug_output */ +/** For GL_ARB_debug_output and GL_KHR_debug */ /*@{*/ #define MAX_DEBUG_LOGGED_MESSAGES 10 #define MAX_DEBUG_MESSAGE_LENGTH 4096 /*@}*/ +/** For GL_KHR_debug */ +/*@{*/ +#define MAX_LABEL_LENGTH 256 +#define MAX_DEBUG_GROUP_STACK_DEPTH 64 +/*@}*/ /* * Color channel component order diff --git a/mesalib/src/mesa/main/dlist.c b/mesalib/src/mesa/main/dlist.c index af2b468c5..595641915 100644 --- a/mesalib/src/mesa/main/dlist.c +++ b/mesalib/src/mesa/main/dlist.c @@ -561,8 +561,8 @@ make_list(GLuint name, GLuint count) /** * Lookup function to just encapsulate casting. */ -static inline struct gl_display_list * -lookup_list(struct gl_context *ctx, GLuint list) +struct gl_display_list * +_mesa_lookup_list(struct gl_context *ctx, GLuint list) { return (struct gl_display_list *) _mesa_HashLookup(ctx->Shared->DisplayList, list); @@ -769,6 +769,7 @@ _mesa_delete_list(struct gl_context *ctx, struct gl_display_list *dlist) } } + free(dlist->Label); free(dlist); } @@ -785,7 +786,7 @@ destroy_list(struct gl_context *ctx, GLuint list) if (list == 0) return; - dlist = lookup_list(ctx, list); + dlist = _mesa_lookup_list(ctx, list); if (!dlist) return; @@ -7278,7 +7279,7 @@ _mesa_compile_error(struct gl_context *ctx, GLenum error, const char *s) static GLboolean islist(struct gl_context *ctx, GLuint list) { - if (list > 0 && lookup_list(ctx, list)) { + if (list > 0 && _mesa_lookup_list(ctx, list)) { return GL_TRUE; } else { @@ -7314,7 +7315,7 @@ execute_list(struct gl_context *ctx, GLuint list) return; } - dlist = lookup_list(ctx, list); + dlist = _mesa_lookup_list(ctx, list); if (!dlist) return; @@ -9309,7 +9310,7 @@ print_list(struct gl_context *ctx, GLuint list) return; } - dlist = lookup_list(ctx, list); + dlist = _mesa_lookup_list(ctx, list); if (!dlist) return; diff --git a/mesalib/src/mesa/main/dlist.h b/mesalib/src/mesa/main/dlist.h index cd0b5235b..7726e77d8 100644 --- a/mesalib/src/mesa/main/dlist.h +++ b/mesalib/src/mesa/main/dlist.h @@ -53,6 +53,8 @@ _mesa_CallLists( GLsizei n, GLenum type, const GLvoid *lists ); void GLAPIENTRY _mesa_ListBase(GLuint base); +extern struct gl_display_list * +_mesa_lookup_list(struct gl_context *ctx, GLuint list); extern void _mesa_compile_error( struct gl_context *ctx, GLenum error, const char *s ); diff --git a/mesalib/src/mesa/main/enable.c b/mesalib/src/mesa/main/enable.c index 21e593117..5e2fd80d2 100644 --- a/mesalib/src/mesa/main/enable.c +++ b/mesalib/src/mesa/main/enable.c @@ -364,6 +364,11 @@ _mesa_set_enable(struct gl_context *ctx, GLenum cap, GLboolean state) FLUSH_VERTICES(ctx, _NEW_DEPTH); ctx->Depth.Test = state; break; + case GL_DEBUG_OUTPUT: + if (!_mesa_is_desktop_gl(ctx)) + goto invalid_enum_error; + ctx->Debug.DebugOutput = state; + break; case GL_DEBUG_OUTPUT_SYNCHRONOUS_ARB: if (!_mesa_is_desktop_gl(ctx)) goto invalid_enum_error; @@ -1201,6 +1206,10 @@ _mesa_IsEnabled( GLenum cap ) return ctx->Light.ColorMaterialEnabled; case GL_CULL_FACE: return ctx->Polygon.CullFlag; + case GL_DEBUG_OUTPUT: + if (!_mesa_is_desktop_gl(ctx)) + goto invalid_enum_error; + return ctx->Debug.DebugOutput; case GL_DEBUG_OUTPUT_SYNCHRONOUS_ARB: if (!_mesa_is_desktop_gl(ctx)) goto invalid_enum_error; diff --git a/mesalib/src/mesa/main/errors.c b/mesalib/src/mesa/main/errors.c index cc93d3bd6..e1a9fe2f5 100644 --- a/mesalib/src/mesa/main/errors.c +++ b/mesalib/src/mesa/main/errors.c @@ -39,6 +39,9 @@ #include "hash_table.h" #include "glapi/glthread.h" +#define MESSAGE_LOG 1 +#define MESSAGE_LOG_ARB 2 + _glthread_DECLARE_STATIC_MUTEX(DynamicIDMutex); static GLuint NextDynamicID = 1; @@ -66,12 +69,16 @@ static const GLenum debug_type_enums[] = { GL_DEBUG_TYPE_PORTABILITY, GL_DEBUG_TYPE_PERFORMANCE, GL_DEBUG_TYPE_OTHER, + GL_DEBUG_TYPE_MARKER, + GL_DEBUG_TYPE_PUSH_GROUP, + GL_DEBUG_TYPE_POP_GROUP, }; static const GLenum debug_severity_enums[] = { GL_DEBUG_SEVERITY_LOW, GL_DEBUG_SEVERITY_MEDIUM, GL_DEBUG_SEVERITY_HIGH, + GL_DEBUG_SEVERITY_NOTIFICATION, }; static enum mesa_debug_source @@ -185,10 +192,14 @@ 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[source][type]; + &ctx->Debug.Namespaces[gstack][source][type]; uintptr_t state; + if (!ctx->Debug.DebugOutput) + 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) @@ -202,7 +213,7 @@ should_log(struct gl_context *ctx, struct gl_debug_severity *entry; if (state == NOT_FOUND) { - if (ctx->Debug.Defaults[severity][source][type]) + if (ctx->Debug.Defaults[gstack][severity][source][type]) state = ENABLED; else state = DISABLED; @@ -236,8 +247,9 @@ 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[source][type]; + &ctx->Debug.Namespaces[gstack][source][type]; uintptr_t state; /* In addition to not being able to store zero as a value, HashTable also @@ -262,6 +274,71 @@ set_message_state(struct gl_context *ctx, nspace->ZeroID = state; } +static void +store_message_details(struct gl_debug_msg *emptySlot, + enum mesa_debug_source source, + enum mesa_debug_type type, GLuint id, + enum mesa_debug_severity severity, GLint len, + const char *buf) +{ + assert(!emptySlot->message && !emptySlot->length); + + emptySlot->message = malloc(len+1); + if (emptySlot->message) { + (void) strncpy(emptySlot->message, buf, (size_t)len); + emptySlot->message[len] = '\0'; + + emptySlot->length = len+1; + emptySlot->source = source; + emptySlot->type = type; + emptySlot->id = id; + emptySlot->severity = severity; + } else { + static GLuint oom_msg_id = 0; + debug_get_id(&oom_msg_id); + + /* malloc failed! */ + emptySlot->message = out_of_memory; + emptySlot->length = strlen(out_of_memory)+1; + emptySlot->source = MESA_DEBUG_SOURCE_OTHER; + emptySlot->type = MESA_DEBUG_TYPE_ERROR; + emptySlot->id = oom_msg_id; + emptySlot->severity = MESA_DEBUG_SEVERITY_HIGH; + } +} + + /** + * Remap any type exclusive to KHR_debug to something suitable + * for ARB_debug_output + */ +inline static int +remap_type(GLenum type) { + + switch(type) { + case GL_DEBUG_TYPE_MARKER: + case GL_DEBUG_TYPE_PUSH_GROUP: + case GL_DEBUG_TYPE_POP_GROUP: + type = GL_DEBUG_TYPE_OTHER; + default: + ; + } + + return type; +} + +/** + * Remap severity exclusive to KHR_debug to something suitable + * for ARB_debug_output + */ +inline static int +remap_severity(GLenum severity) { + + if (GL_DEBUG_SEVERITY_NOTIFICATION == severity) + severity = GL_DEBUG_SEVERITY_LOW; + + return severity; +} + /** * 'buf' is not necessarily a null-terminated string. When logging, copy * 'len' characters from it, store them in a new, null-terminated string, @@ -282,10 +359,17 @@ _mesa_log_msg(struct gl_context *ctx, enum mesa_debug_source source, return; if (ctx->Debug.Callback) { + GLenum gl_type = debug_type_enums[type]; + GLenum gl_severity = debug_severity_enums[severity]; + + if (ctx->Debug.ARBCallback) { + gl_severity = remap_severity(gl_severity); + gl_type = remap_type(gl_type); + } ctx->Debug.Callback(debug_source_enums[source], - debug_type_enums[type], + gl_type, id, - debug_severity_enums[severity], + gl_severity, len, buf, ctx->Debug.CallbackData); return; } @@ -297,30 +381,7 @@ _mesa_log_msg(struct gl_context *ctx, enum mesa_debug_source source, % MAX_DEBUG_LOGGED_MESSAGES; emptySlot = &ctx->Debug.Log[nextEmpty]; - assert(!emptySlot->message && !emptySlot->length); - - emptySlot->message = malloc(len+1); - if (emptySlot->message) { - (void) strncpy(emptySlot->message, buf, (size_t)len); - emptySlot->message[len] = '\0'; - - emptySlot->length = len+1; - emptySlot->source = source; - emptySlot->type = type; - emptySlot->id = id; - emptySlot->severity = severity; - } else { - static GLuint oom_msg_id = 0; - debug_get_id(&oom_msg_id); - - /* malloc failed! */ - emptySlot->message = out_of_memory; - emptySlot->length = strlen(out_of_memory)+1; - emptySlot->source = MESA_DEBUG_SOURCE_OTHER; - emptySlot->type = MESA_DEBUG_TYPE_ERROR; - emptySlot->id = oom_msg_id; - emptySlot->severity = MESA_DEBUG_SEVERITY_HIGH; - } + 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; @@ -340,7 +401,8 @@ _mesa_log_msg(struct gl_context *ctx, enum mesa_debug_source source, */ static GLsizei _mesa_get_msg(struct gl_context *ctx, GLenum *source, GLenum *type, - GLuint *id, GLenum *severity, GLsizei bufSize, char *buf) + GLuint *id, GLenum *severity, GLsizei bufSize, char *buf, + unsigned caller) { struct gl_debug_msg *msg; GLsizei length; @@ -356,12 +418,18 @@ _mesa_get_msg(struct gl_context *ctx, GLenum *source, GLenum *type, if (bufSize < length && buf != NULL) return 0; - if (severity) + if (severity) { *severity = debug_severity_enums[msg->severity]; + if (caller == MESSAGE_LOG_ARB) + *severity = remap_severity(*severity); + } if (source) *source = debug_source_enums[msg->source]; - if (type) + if (type) { *type = debug_type_enums[msg->type]; + if (caller == MESSAGE_LOG_ARB) + *type = remap_type(*type); + } if (id) *id = msg->id; @@ -388,13 +456,19 @@ _mesa_get_msg(struct gl_context *ctx, GLenum *source, GLenum *type, * glDebugMessageInsertARB only accepts two values for 'source', * and glDebugMessageControlARB will additionally accept GL_DONT_CARE * in any parameter, so handle those cases specially. + * + * There is also special cases for handling values available in + * GL_KHR_debug that are not avaliable in GL_ARB_debug_output */ static GLboolean validate_params(struct gl_context *ctx, unsigned caller, - GLenum source, GLenum type, GLenum severity) + const char *callerstr, GLenum source, GLenum type, + GLenum severity) { #define INSERT 1 #define CONTROL 2 +#define INSERT_ARB 3 +#define CONTROL_ARB 4 switch(source) { case GL_DEBUG_SOURCE_APPLICATION_ARB: case GL_DEBUG_SOURCE_THIRD_PARTY_ARB: @@ -403,10 +477,10 @@ validate_params(struct gl_context *ctx, unsigned caller, case GL_DEBUG_SOURCE_SHADER_COMPILER_ARB: case GL_DEBUG_SOURCE_WINDOW_SYSTEM_ARB: case GL_DEBUG_SOURCE_OTHER_ARB: - if (caller != INSERT) + if (caller != INSERT || caller == INSERT_ARB) break; case GL_DONT_CARE: - if (caller == CONTROL) + if (caller == CONTROL || caller == CONTROL_ARB) break; default: goto error; @@ -420,8 +494,12 @@ validate_params(struct gl_context *ctx, unsigned caller, case GL_DEBUG_TYPE_PORTABILITY_ARB: case GL_DEBUG_TYPE_OTHER_ARB: break; + case GL_DEBUG_TYPE_MARKER: + /* this value is only valid for GL_KHR_debug functions */ + if (caller == CONTROL || caller == INSERT) + break; case GL_DONT_CARE: - if (caller == CONTROL) + if (caller == CONTROL || caller == CONTROL_ARB) break; default: goto error; @@ -432,8 +510,12 @@ validate_params(struct gl_context *ctx, unsigned caller, case GL_DEBUG_SEVERITY_MEDIUM_ARB: case GL_DEBUG_SEVERITY_LOW_ARB: break; + case GL_DEBUG_SEVERITY_NOTIFICATION: + /* this value is only valid for GL_KHR_debug functions */ + if (caller == CONTROL || caller == INSERT) + break; case GL_DONT_CARE: - if (caller == CONTROL) + if (caller == CONTROL || caller == CONTROL_ARB) break; default: goto error; @@ -442,93 +524,13 @@ validate_params(struct gl_context *ctx, unsigned caller, error: { - const char *callerstr; - if (caller == INSERT) - callerstr = "glDebugMessageInsertARB"; - else if (caller == CONTROL) - callerstr = "glDebugMessageControlARB"; - else - return GL_FALSE; - - _mesa_error( ctx, GL_INVALID_ENUM, "bad values passed to %s" + _mesa_error(ctx, GL_INVALID_ENUM, "bad values passed to %s" "(source=0x%x, type=0x%x, severity=0x%x)", callerstr, source, type, severity); } return GL_FALSE; } -void GLAPIENTRY -_mesa_DebugMessageInsertARB(GLenum source, GLenum type, GLuint id, - GLenum severity, GLint length, - const GLcharARB* buf) -{ - GET_CURRENT_CONTEXT(ctx); - - if (!validate_params(ctx, INSERT, source, type, severity)) - return; /* GL_INVALID_ENUM */ - - if (length < 0) - length = strlen(buf); - - if (length >= MAX_DEBUG_MESSAGE_LENGTH) { - _mesa_error(ctx, GL_INVALID_VALUE, "glDebugMessageInsertARB" - "(length=%d, which is not less than " - "GL_MAX_DEBUG_MESSAGE_LENGTH_ARB=%d)", length, - MAX_DEBUG_MESSAGE_LENGTH); - return; - } - - _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); -} - -GLuint GLAPIENTRY -_mesa_GetDebugMessageLogARB(GLuint count, GLsizei logSize, GLenum* sources, - GLenum* types, GLenum* ids, GLenum* severities, - GLsizei* lengths, GLcharARB* messageLog) -{ - GET_CURRENT_CONTEXT(ctx); - GLuint ret; - - if (!messageLog) - logSize = 0; - - if (logSize < 0) { - _mesa_error(ctx, GL_INVALID_VALUE, "glGetDebugMessageLogARB" - "(logSize=%d : logSize must not be negative)", logSize); - return 0; - } - - for (ret = 0; ret < count; ret++) { - GLsizei written = _mesa_get_msg(ctx, sources, types, ids, severities, - logSize, messageLog); - if (!written) - break; - - if (messageLog) { - messageLog += written; - logSize -= written; - } - if (lengths) { - *lengths = written; - lengths++; - } - - if (severities) - severities++; - if (sources) - sources++; - if (types) - types++; - if (ids) - ids++; - } - - return ret; -} - /** * Set the state of all message IDs found in the given intersection of * 'source', 'type', and 'severity'. The _COUNT enum can be used for @@ -548,6 +550,7 @@ control_messages(struct gl_context *ctx, GLboolean enabled) { int s, t, sev, smax, tmax, sevmax; + GLint gstack = ctx->Debug.GroupStackDepth; if (source == MESA_DEBUG_SOURCE_COUNT) { source = 0; @@ -577,10 +580,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[sev][s][t] = enabled; + ctx->Debug.Defaults[gstack][sev][s][t] = enabled; /* Now change the state of IDs we *have* seen... */ - foreach(node, &ctx->Debug.Namespaces[s][t].Severity[sev]) { + foreach(node, &ctx->Debug.Namespaces[gstack][s][t].Severity[sev]) { entry = (struct gl_debug_severity *)node; set_message_state(ctx, s, t, entry->ID, enabled); } @@ -618,28 +621,36 @@ control_app_messages(struct gl_context *ctx, GLenum esource, GLenum etype, control_messages(ctx, source, type, severity, enabled); } -void GLAPIENTRY -_mesa_DebugMessageControlARB(GLenum gl_source, GLenum gl_type, - GLenum gl_severity, - GLsizei count, const GLuint *ids, - GLboolean enabled) +/** + * This is a generic message control function for use by both + * glDebugMessageControlARB and glDebugMessageControl. + */ +static void +message_control(GLenum gl_source, GLenum gl_type, + GLenum gl_severity, + GLsizei count, const GLuint *ids, + GLboolean enabled, + unsigned caller, const char *callerstr) { GET_CURRENT_CONTEXT(ctx); if (count < 0) { - _mesa_error(ctx, GL_INVALID_VALUE, "glDebugMessageControlARB" - "(count=%d : count must not be negative)", count); + _mesa_error(ctx, GL_INVALID_VALUE, + "%s(count=%d : count must not be negative)", callerstr, + count); return; } - if (!validate_params(ctx, CONTROL, gl_source, gl_type, gl_severity)) + if (!validate_params(ctx, caller, callerstr, gl_source, gl_type, + gl_severity)) return; /* GL_INVALID_ENUM */ if (count && (gl_severity != GL_DONT_CARE || gl_type == GL_DONT_CARE || gl_source == GL_DONT_CARE)) { - _mesa_error(ctx, GL_INVALID_OPERATION, "glDebugMessageControlARB" - "(When passing an array of ids, severity must be" - " GL_DONT_CARE, and source and type must not be GL_DONT_CARE."); + _mesa_error(ctx, GL_INVALID_OPERATION, + "%s(When passing an array of ids, severity must be" + " GL_DONT_CARE, and source and type must not be GL_DONT_CARE.", + callerstr); return; } @@ -647,43 +658,84 @@ _mesa_DebugMessageControlARB(GLenum gl_source, GLenum gl_type, count, ids, enabled); } -void GLAPIENTRY -_mesa_DebugMessageCallbackARB(GLDEBUGPROCARB callback, const void *userParam) +/** + * This is a generic message insert function. + * Validation of source, type and severity parameters should be done + * before calling this funtion. + */ +static void +message_insert(GLenum source, GLenum type, GLuint id, + GLenum severity, GLint length, const GLchar* buf, + const char *callerstr) { GET_CURRENT_CONTEXT(ctx); - ctx->Debug.Callback = callback; - ctx->Debug.CallbackData = userParam; + + if (length < 0) + length = strlen(buf); + + if (length >= MAX_DEBUG_MESSAGE_LENGTH) { + _mesa_error(ctx, GL_INVALID_VALUE, + "%s(length=%d, which is not less than " + "GL_MAX_DEBUG_MESSAGE_LENGTH=%d)", callerstr, length, + MAX_DEBUG_MESSAGE_LENGTH); + return; + } + + _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); } -void -_mesa_init_errors(struct gl_context *ctx) +/** + * This is a generic message insert function for use by both + * glGetDebugMessageLogARB and glGetDebugMessageLog. + */ +static GLuint +get_message_log(GLuint count, GLsizei logSize, GLenum* sources, + GLenum* types, GLenum* ids, GLenum* severities, + GLsizei* lengths, GLchar* messageLog, + unsigned caller, const char *callerstr) { - int s, t, sev; + GET_CURRENT_CONTEXT(ctx); + GLuint ret; - 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; + if (!messageLog) + logSize = 0; - /* Enable all the messages with severity HIGH or MEDIUM by default. */ - memset(ctx->Debug.Defaults[MESA_DEBUG_SEVERITY_HIGH], GL_TRUE, - sizeof ctx->Debug.Defaults[MESA_DEBUG_SEVERITY_HIGH]); - memset(ctx->Debug.Defaults[MESA_DEBUG_SEVERITY_MEDIUM], GL_TRUE, - sizeof ctx->Debug.Defaults[MESA_DEBUG_SEVERITY_MEDIUM]); - memset(ctx->Debug.Defaults[MESA_DEBUG_SEVERITY_LOW], GL_FALSE, - sizeof ctx->Debug.Defaults[MESA_DEBUG_SEVERITY_LOW]); + if (logSize < 0) { + _mesa_error(ctx, GL_INVALID_VALUE, + "%s(logSize=%d : logSize must not be negative)", callerstr, + logSize); + return 0; + } - /* 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[s][t].IDs = _mesa_NewHashTable(); - assert(ctx->Debug.Namespaces[s][t].IDs); + for (ret = 0; ret < count; ret++) { + GLsizei written = _mesa_get_msg(ctx, sources, types, ids, severities, + logSize, messageLog, caller); + if (!written) + break; - for (sev = 0; sev < MESA_DEBUG_SEVERITY_COUNT; sev++) - make_empty_list(&ctx->Debug.Namespaces[s][t].Severity[sev]); + if (messageLog) { + messageLog += written; + logSize -= written; } + if (lengths) { + *lengths = written; + lengths++; + } + + if (severities) + severities++; + if (sources) + sources++; + if (types) + types++; + if (ids) + ids++; + } + + return ret; } static void @@ -691,8 +743,8 @@ do_nothing(GLuint key, void *data, void *userData) { } -void -_mesa_free_errors_data(struct gl_context *ctx) +static void +free_errors_data(struct gl_context *ctx, GLint gstack) { enum mesa_debug_type t; enum mesa_debug_source s; @@ -701,13 +753,15 @@ _mesa_free_errors_data(struct gl_context *ctx) /* 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[s][t].IDs, do_nothing, NULL); - _mesa_DeleteHashTable(ctx->Debug.Namespaces[s][t].IDs); + _mesa_HashDeleteAll(ctx->Debug.Namespaces[gstack][s][t].IDs, + do_nothing, NULL); + _mesa_DeleteHashTable(ctx->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[s][t].Severity[sev]) { + foreach_s(node, tmp, + &ctx->Debug.Namespaces[gstack][s][t].Severity[sev]) { entry = (struct gl_debug_severity *)node; free(entry); } @@ -715,6 +769,259 @@ _mesa_free_errors_data(struct gl_context *ctx) } } +void GLAPIENTRY +_mesa_DebugMessageInsert(GLenum source, GLenum type, GLuint id, + GLenum severity, GLint length, + const GLchar* buf) +{ + const char *callerstr = "glDebugMessageInsert"; + + GET_CURRENT_CONTEXT(ctx); + + if (!validate_params(ctx, INSERT, callerstr, source, type, severity)) + return; /* GL_INVALID_ENUM */ + + message_insert(source, type, id, severity, length, buf, + callerstr); +} + +GLuint GLAPIENTRY +_mesa_GetDebugMessageLog(GLuint count, GLsizei logSize, GLenum* sources, + GLenum* types, GLenum* ids, GLenum* severities, + GLsizei* lengths, GLchar* messageLog) +{ + const char *callerstr = "glGetDebugMessageLog"; + + return get_message_log(count, logSize, sources, types, ids, severities, + lengths, messageLog, MESSAGE_LOG, callerstr); +} + +void GLAPIENTRY +_mesa_DebugMessageControl(GLenum source, GLenum type, GLenum severity, + GLsizei count, const GLuint *ids, + GLboolean enabled) +{ + const char *callerstr = "glDebugMessageControl"; + + message_control(source, type, severity, count, ids, + enabled, CONTROL, callerstr); +} + +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; +} + +void GLAPIENTRY +_mesa_PushDebugGroup(GLenum source, GLuint id, GLsizei length, + const GLchar *message) +{ + const char *callerstr = "glPushDebugGroup"; + int s, t, sev; + GLint prevStackDepth; + GLint currStackDepth; + struct gl_debug_msg *emptySlot; + + GET_CURRENT_CONTEXT(ctx); + + if (ctx->Debug.GroupStackDepth >= MAX_DEBUG_GROUP_STACK_DEPTH-1) { + _mesa_error(ctx, GL_STACK_OVERFLOW, "%s", callerstr); + return; + } + + switch(source) { + case GL_DEBUG_SOURCE_APPLICATION: + case GL_DEBUG_SOURCE_THIRD_PARTY: + break; + default: + _mesa_error(ctx, GL_INVALID_ENUM, "bad value passed to %s" + "(source=0x%x)", callerstr, source); + return; + } + + message_insert(source, GL_DEBUG_TYPE_PUSH_GROUP, id, + GL_DEBUG_SEVERITY_NOTIFICATION, length, + message, callerstr); + + prevStackDepth = ctx->Debug.GroupStackDepth; + ctx->Debug.GroupStackDepth++; + currStackDepth = ctx->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]; + store_message_details(emptySlot, gl_enum_to_debug_source(source), + gl_enum_to_debug_source(GL_DEBUG_TYPE_PUSH_GROUP), + id, + gl_enum_to_debug_severity(GL_DEBUG_SEVERITY_NOTIFICATION), + length, message); + + /* inherit the control volume of the debug group previously residing on + * the top of the debug group stack + */ + 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); + + 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]; + + /* 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]) { + 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); + } + } + } +} + +void GLAPIENTRY +_mesa_PopDebugGroup() +{ + const char *callerstr = "glPopDebugGroup"; + struct gl_debug_msg *gdmessage; + GLint prevStackDepth; + + GET_CURRENT_CONTEXT(ctx); + + if (ctx->Debug.GroupStackDepth <= 0) { + _mesa_error(ctx, GL_STACK_UNDERFLOW, "%s", callerstr); + return; + } + + prevStackDepth = ctx->Debug.GroupStackDepth; + ctx->Debug.GroupStackDepth--; + + gdmessage = &ctx->Debug.DebugGroupMsgs[prevStackDepth]; + /* using _mesa_log_msg() directly here as verification of parameters + * already done in push + */ + _mesa_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); + + if (gdmessage->message != (char*)out_of_memory) + free(gdmessage->message); + gdmessage->message = NULL; + gdmessage->length = 0; + + /* free popped debug group data */ + free_errors_data(ctx, prevStackDepth); +} + +void GLAPIENTRY +_mesa_DebugMessageInsertARB(GLenum source, GLenum type, GLuint id, + GLenum severity, GLint length, + const GLcharARB* buf) +{ + const char *callerstr = "glDebugMessageInsertARB"; + + GET_CURRENT_CONTEXT(ctx); + + if (!validate_params(ctx, INSERT_ARB, callerstr, source, type, severity)) + return; /* GL_INVALID_ENUM */ + + message_insert(source, type, id, severity, length, buf, + callerstr); +} + +GLuint GLAPIENTRY +_mesa_GetDebugMessageLogARB(GLuint count, GLsizei logSize, GLenum* sources, + GLenum* types, GLenum* ids, GLenum* severities, + GLsizei* lengths, GLcharARB* messageLog) +{ + const char *callerstr = "glGetDebugMessageLogARB"; + + return get_message_log(count, logSize, sources, types, ids, severities, + lengths, messageLog, MESSAGE_LOG_ARB, callerstr); +} + +void GLAPIENTRY +_mesa_DebugMessageControlARB(GLenum gl_source, GLenum gl_type, + GLenum gl_severity, + GLsizei count, const GLuint *ids, + GLboolean enabled) +{ + const char *callerstr = "glDebugMessageControlARB"; + + message_control(gl_source, gl_type, gl_severity, count, ids, + enabled, CONTROL_ARB, callerstr); +} + +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; +} + +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]); + } +} + +/** + * Loop through debug group stack tearing down states for + * filtering debug messages. + */ +void +_mesa_free_errors_data(struct gl_context *ctx) +{ + GLint i; + + for (i = 0; i <= ctx->Debug.GroupStackDepth; i++) { + free_errors_data(ctx, i); + } +} + /**********************************************************************/ /** \name Diagnostics */ /*@{*/ diff --git a/mesalib/src/mesa/main/errors.h b/mesalib/src/mesa/main/errors.h index 5b4f36f55..a837dc8e1 100644 --- a/mesalib/src/mesa/main/errors.h +++ b/mesalib/src/mesa/main/errors.h @@ -102,6 +102,26 @@ _mesa_DebugMessageControlARB(GLenum source, GLenum type, GLenum severity, void GLAPIENTRY _mesa_DebugMessageCallbackARB(GLDEBUGPROCARB callback, const void *userParam); +void GLAPIENTRY +_mesa_DebugMessageInsert(GLenum source, GLenum type, GLuint id, + GLenum severity, GLint length, + const GLchar* buf); +GLuint GLAPIENTRY +_mesa_GetDebugMessageLog(GLuint count, GLsizei logSize, GLenum* sources, + GLenum* types, GLenum* ids, GLenum* severities, + GLsizei* lengths, GLchar* messageLog); +void GLAPIENTRY +_mesa_DebugMessageControl(GLenum source, GLenum type, GLenum severity, + GLsizei count, const GLuint *ids, + GLboolean enabled); +void GLAPIENTRY +_mesa_DebugMessageCallback(GLDEBUGPROC callback, + const void *userParam); +void GLAPIENTRY +_mesa_PushDebugGroup(GLenum source, GLuint id, GLsizei length, + const GLchar *message); +void GLAPIENTRY +_mesa_PopDebugGroup(void); #ifdef __cplusplus } diff --git a/mesalib/src/mesa/main/extensions.c b/mesalib/src/mesa/main/extensions.c index 1a040ee3b..f60157f8c 100644 --- a/mesalib/src/mesa/main/extensions.c +++ b/mesalib/src/mesa/main/extensions.c @@ -283,6 +283,9 @@ static const struct extension extension_table[] = { { "GL_OES_texture_npot", o(ARB_texture_non_power_of_two), ES1 | ES2, 2005 }, { "GL_OES_vertex_array_object", o(dummy_true), ES1 | ES2, 2010 }, + /* KHR extensions */ + { "GL_KHR_debug", o(dummy_true), GL, 2012 }, + /* Vendor extensions */ { "GL_3DFX_texture_compression_FXT1", o(TDFX_texture_compression_FXT1), GL, 1999 }, { "GL_AMD_conservative_depth", o(ARB_conservative_depth), GL, 2009 }, diff --git a/mesalib/src/mesa/main/framebuffer.c b/mesalib/src/mesa/main/framebuffer.c index 4ec4118c5..2fad45880 100644 --- a/mesalib/src/mesa/main/framebuffer.c +++ b/mesalib/src/mesa/main/framebuffer.c @@ -195,6 +195,7 @@ _mesa_destroy_framebuffer(struct gl_framebuffer *fb) { if (fb) { _mesa_free_framebuffer_data(fb); + free(fb->Label); free(fb); } } diff --git a/mesalib/src/mesa/main/get_hash_params.py b/mesalib/src/mesa/main/get_hash_params.py index fde45379a..30855c37b 100644 --- a/mesalib/src/mesa/main/get_hash_params.py +++ b/mesalib/src/mesa/main/get_hash_params.py @@ -695,11 +695,15 @@ descriptor=[ # GL_ARB_robustness [ "RESET_NOTIFICATION_STRATEGY_ARB", "CONTEXT_ENUM(Const.ResetStrategy), NO_EXTRA" ], -# GL_ARB_debug_output - [ "DEBUG_LOGGED_MESSAGES_ARB", "CONTEXT_INT(Debug.NumMessages), NO_EXTRA" ], - [ "DEBUG_NEXT_LOGGED_MESSAGE_LENGTH_ARB", "CONTEXT_INT(Debug.NextMsgLength), NO_EXTRA" ], - [ "MAX_DEBUG_LOGGED_MESSAGES_ARB", "CONST(MAX_DEBUG_LOGGED_MESSAGES), NO_EXTRA" ], - [ "MAX_DEBUG_MESSAGE_LENGTH_ARB", "CONST(MAX_DEBUG_MESSAGE_LENGTH), 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" ], + [ "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" ], + [ "MAX_DUAL_SOURCE_DRAW_BUFFERS", "CONTEXT_INT(Const.MaxDualSourceDrawBuffers), extra_ARB_blend_func_extended" ], # GL_ARB_uniform_buffer_object diff --git a/mesalib/src/mesa/main/hash.c b/mesalib/src/mesa/main/hash.c index 6591af9a6..b31fd4839 100644 --- a/mesalib/src/mesa/main/hash.c +++ b/mesalib/src/mesa/main/hash.c @@ -302,6 +302,34 @@ _mesa_HashDeleteAll(struct _mesa_HashTable *table, /** + * Clone all entries in a hash table, into a new table. + * + * \param table the hash table to clone + */ +struct _mesa_HashTable * +_mesa_HashClone(const struct _mesa_HashTable *table) +{ + /* cast-away const */ + struct _mesa_HashTable *table2 = (struct _mesa_HashTable *) table; + struct hash_entry *entry; + struct _mesa_HashTable *clonetable; + + ASSERT(table); + _glthread_LOCK_MUTEX(table2->Mutex); + + clonetable = _mesa_NewHashTable(); + assert(clonetable); + hash_table_foreach(table->ht, entry) { + _mesa_HashInsert(clonetable, (GLint)(uintptr_t)entry->key, entry->data); + } + + _glthread_UNLOCK_MUTEX(table2->Mutex); + + return clonetable; +} + + +/** * Walk over all entries in a hash table, calling callback function for each. * Note: we use a separate mutex in this function to avoid a recursive * locking deadlock (in case the callback calls _mesa_HashRemove()) and to diff --git a/mesalib/src/mesa/main/hash.h b/mesalib/src/mesa/main/hash.h index 142d2842c..b34f32848 100644 --- a/mesalib/src/mesa/main/hash.h +++ b/mesalib/src/mesa/main/hash.h @@ -50,6 +50,9 @@ _mesa_HashDeleteAll(struct _mesa_HashTable *table, void (*callback)(GLuint key, void *data, void *userData), void *userData); +extern struct _mesa_HashTable * +_mesa_HashClone(const struct _mesa_HashTable *table); + extern void _mesa_HashWalk(const struct _mesa_HashTable *table, void (*callback)(GLuint key, void *data, void *userData), diff --git a/mesalib/src/mesa/main/mtypes.h b/mesalib/src/mesa/main/mtypes.h index 22bb58c5f..ef16c5910 100644 --- a/mesalib/src/mesa/main/mtypes.h +++ b/mesalib/src/mesa/main/mtypes.h @@ -80,6 +80,7 @@ struct prog_instruction; struct gl_program_parameter_list; struct set; struct set_entry; +struct vbo_context; /*@}*/ @@ -1128,6 +1129,7 @@ struct gl_sampler_object { GLuint Name; GLint RefCount; + GLchar *Label; /**< GL_KHR_debug */ GLenum WrapS; /**< S-axis texture image wrap mode */ GLenum WrapT; /**< T-axis texture image wrap mode */ @@ -1155,6 +1157,7 @@ struct gl_texture_object _glthread_Mutex Mutex; /**< for thread safety */ GLint RefCount; /**< reference count */ GLuint Name; /**< the user-visible texture object ID */ + GLchar *Label; /**< GL_KHR_debug */ GLenum Target; /**< GL_TEXTURE_1D, GL_TEXTURE_2D, etc. */ struct gl_sampler_object Sampler; @@ -1403,6 +1406,7 @@ struct gl_buffer_object _glthread_Mutex Mutex; GLint RefCount; GLuint Name; + GLchar *Label; /**< GL_KHR_debug */ GLenum Usage; /**< GL_STREAM_DRAW_ARB, GL_STREAM_READ_ARB, etc. */ GLsizeiptrARB Size; /**< Size of buffer storage in bytes */ GLubyte *Data; /**< Location of storage either in RAM or VRAM. */ @@ -1467,6 +1471,7 @@ struct gl_array_object { /** Name of the array object as received from glGenVertexArrayAPPLE. */ GLuint Name; + GLchar *Label; /**< GL_KHR_debug */ GLint RefCount; _glthread_Mutex Mutex; @@ -1704,6 +1709,7 @@ struct gl_transform_feedback_info struct gl_transform_feedback_object { GLuint Name; /**< AKA the object ID */ + GLchar *Label; /**< GL_KHR_debug */ GLint RefCount; GLboolean Active; /**< Is transform feedback enabled? */ GLboolean Paused; /**< Is transform feedback paused? */ @@ -2108,6 +2114,7 @@ struct gl_shader */ GLenum Type; GLuint Name; /**< AKA the handle */ + GLchar *Label; /**< GL_KHR_debug */ GLint RefCount; /**< Reference count */ GLboolean DeletePending; GLboolean CompileStatus; @@ -2279,6 +2286,7 @@ struct gl_shader_program { GLenum Type; /**< Always GL_SHADER_PROGRAM (internal token) */ GLuint Name; /**< aka handle or ID */ + GLchar *Label; /**< GL_KHR_debug */ GLint RefCount; /**< Reference count */ GLboolean DeletePending; @@ -2515,6 +2523,7 @@ struct gl_query_object { GLenum Target; /**< The query target, when active */ GLuint Id; /**< hash table ID/name */ + GLchar *Label; /**< GL_KHR_debug */ GLuint64EXT Result; /**< the counter */ GLboolean Active; /**< inside Begin/EndQuery */ GLboolean Ready; /**< result is ready? */ @@ -2550,6 +2559,7 @@ struct gl_sync_object { GLenum Type; /**< GL_SYNC_FENCE */ GLuint Name; /**< Fence name */ + GLchar *Label; /**< GL_KHR_debug */ GLint RefCount; /**< Reference count */ GLboolean DeletePending; /**< Object was deleted while there were still * live references (e.g., sync not yet finished) @@ -2632,6 +2642,7 @@ struct gl_renderbuffer _glthread_Mutex Mutex; /**< for thread safety */ GLuint ClassID; /**< Useful for drivers */ GLuint Name; + GLchar *Label; /**< GL_KHR_debug */ GLint RefCount; GLuint Width, Height; GLuint Depth; @@ -2715,6 +2726,7 @@ struct gl_framebuffer * polygon face orientation, and polygon stipple will have to be inverted. */ GLuint Name; + GLchar *Label; /**< GL_KHR_debug */ GLint RefCount; GLboolean DeletePending; @@ -3280,6 +3292,7 @@ union gl_dlist_node; struct gl_display_list { GLuint Name; + GLchar *Label; /**< GL_KHR_debug */ GLbitfield Flags; /**< DLIST_x flags */ /** The dlist commands are in a linked list of nodes */ union gl_dlist_node *Head; @@ -3315,8 +3328,8 @@ struct gl_dlist_state /** @{ * - * These are a mapping of the GL_ARB_debug_output enums to small enums - * suitable for use as an array index. + * These are a mapping of the GL_ARB_debug_output/GL_KHR_debug enums + * to small enums suitable for use as an array index. */ enum mesa_debug_source { @@ -3336,6 +3349,9 @@ enum mesa_debug_type { MESA_DEBUG_TYPE_PORTABILITY, MESA_DEBUG_TYPE_PERFORMANCE, MESA_DEBUG_TYPE_OTHER, + MESA_DEBUG_TYPE_MARKER, + MESA_DEBUG_TYPE_PUSH_GROUP, + MESA_DEBUG_TYPE_POP_GROUP, MESA_DEBUG_TYPE_COUNT }; @@ -3343,6 +3359,7 @@ enum mesa_debug_severity { MESA_DEBUG_SEVERITY_LOW, MESA_DEBUG_SEVERITY_MEDIUM, MESA_DEBUG_SEVERITY_HIGH, + MESA_DEBUG_SEVERITY_NOTIFICATION, MESA_DEBUG_SEVERITY_COUNT }; @@ -3350,7 +3367,7 @@ enum mesa_debug_severity { /** * An error, warning, or other piece of debug information for an application - * to consume via GL_ARB_debug_output. + * to consume via GL_ARB_debug_output/GL_KHR_debug. */ struct gl_debug_msg { @@ -3372,12 +3389,16 @@ struct gl_debug_namespace struct gl_debug_state { - GLDEBUGPROCARB Callback; + GLDEBUGPROC Callback; const void *CallbackData; GLboolean SyncOutput; - GLboolean Defaults[MESA_DEBUG_SEVERITY_COUNT][MESA_DEBUG_SOURCE_COUNT][MESA_DEBUG_TYPE_COUNT]; - struct gl_debug_namespace Namespaces[MESA_DEBUG_SOURCE_COUNT][MESA_DEBUG_TYPE_COUNT]; + GLboolean DebugOutput; + GLboolean ARBCallback; /* Used to track if current callback is of type ARB_debug_output or KHR_debug */ + GLboolean Defaults[MAX_DEBUG_GROUP_STACK_DEPTH][MESA_DEBUG_SEVERITY_COUNT][MESA_DEBUG_SOURCE_COUNT][MESA_DEBUG_TYPE_COUNT]; + struct gl_debug_namespace Namespaces[MAX_DEBUG_GROUP_STACK_DEPTH][MESA_DEBUG_SOURCE_COUNT][MESA_DEBUG_TYPE_COUNT]; struct gl_debug_msg Log[MAX_DEBUG_LOGGED_MESSAGES]; + struct gl_debug_msg DebugGroupMsgs[MAX_DEBUG_GROUP_STACK_DEPTH]; + GLint GroupStackDepth; GLint NumMessages; GLint NextMsg; GLint NextMsgLength; /* redundant, but copied here from Log[NextMsg].length @@ -3624,7 +3645,7 @@ struct gl_context const char *ErrorDebugFmtString; GLuint ErrorDebugCount; - /* GL_ARB_debug_output */ + /* GL_ARB_debug_output/GL_KHR_debug */ struct gl_debug_state Debug; GLenum RenderMode; /**< either GL_RENDER, GL_SELECT, GL_FEEDBACK */ @@ -3669,7 +3690,7 @@ struct gl_context void *swrast_context; void *swsetup_context; void *swtnl_context; - void *swtnl_im; + struct vbo_context *vbo_context; struct st_context *st; void *aelt_context; /*@}*/ diff --git a/mesalib/src/mesa/main/objectlabel.c b/mesalib/src/mesa/main/objectlabel.c new file mode 100644 index 000000000..90d9e09f5 --- /dev/null +++ b/mesalib/src/mesa/main/objectlabel.c @@ -0,0 +1,282 @@ +/* + * Mesa 3-D graphics library + * + * Copyright (C) 2013 Timothy Arceri All Rights Reserved. + * + * Permission is hereby granted, free of charge, to any person obtaining a + * copy of this software and associated documentation files (the "Software"), + * to deal in the Software without restriction, including without limitation + * the rights to use, copy, modify, merge, publish, distribute, sublicense, + * and/or sell copies of the Software, and to permit persons to whom the + * Software is furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included + * in all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS + * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL + * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR + * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, + * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR + * OTHER DEALINGS IN THE SOFTWARE. + */ + + +#include "arrayobj.h" +#include "bufferobj.h" +#include "context.h" +#include "dlist.h" +#include "enums.h" +#include "fbobject.h" +#include "objectlabel.h" +#include "queryobj.h" +#include "samplerobj.h" +#include "shaderobj.h" +#include "syncobj.h" +#include "texobj.h" +#include "transformfeedback.h" + + +/** + * Helper for _mesa_ObjectLabel() and _mesa_ObjectPtrLabel(). + */ +static void +set_label(struct gl_context *ctx, char **labelPtr, const char *label, + int length, const char *caller) +{ + if (*labelPtr) { + /* free old label string */ + free(*labelPtr); + *labelPtr = NULL; + } + + /* set new label string */ + if (label) { + if (length >= 0) { + if (length >= MAX_LABEL_LENGTH) + _mesa_error(ctx, GL_INVALID_VALUE, + "%s(length=%d, which is not less than " + "GL_MAX_LABEL_LENGTH=%d)", caller, length, + MAX_LABEL_LENGTH); + + /* explicit length */ + *labelPtr = (char *) malloc(length+1); + if (*labelPtr) { + memcpy(*labelPtr, label, length); + /* length is not required to include the null terminator so + * add one just in case + */ + (*labelPtr)[length] = '\0'; + } + } + else { + int len = strlen(label); + if (len >= MAX_LABEL_LENGTH) + _mesa_error(ctx, GL_INVALID_VALUE, + "%s(label length=%d, which is not less than " + "GL_MAX_LABEL_LENGTH=%d)", caller, len, + MAX_LABEL_LENGTH); + + /* null-terminated string */ + *labelPtr = _mesa_strdup(label); + } + } +} + +/** + * Helper for _mesa_GetObjectLabel() and _mesa_GetObjectPtrLabel(). + */ +static void +copy_label(char **labelPtr, char *label, int *length, int bufSize) +{ + int labelLen = 0; + + if (*labelPtr) + labelLen = strlen(*labelPtr); + + if (label) { + if (bufSize <= labelLen) + labelLen = bufSize-1; + + memcpy(label, *labelPtr, labelLen); + label[labelLen] = '\0'; + } + + if (length) + *length = labelLen; +} + +/** + * Helper for _mesa_ObjectLabel() and _mesa_GetObjectLabel(). + */ +static char ** +get_label_pointer(struct gl_context *ctx, GLenum identifier, GLuint name, + const char *caller) +{ + char **labelPtr = NULL; + + switch (identifier) { + case GL_BUFFER: + { + struct gl_buffer_object *bufObj = _mesa_lookup_bufferobj(ctx, name); + if (bufObj) + labelPtr = &bufObj->Label; + } + break; + case GL_SHADER: + { + struct gl_shader *shader = _mesa_lookup_shader(ctx, name); + if (shader) + labelPtr = &shader->Label; + } + break; + case GL_PROGRAM: + { + struct gl_shader_program *program = + _mesa_lookup_shader_program(ctx, name); + if (program) + labelPtr = &program->Label; + } + break; + case GL_VERTEX_ARRAY: + { + struct gl_array_object *obj = _mesa_lookup_arrayobj(ctx, name); + if (obj) + labelPtr = &obj->Label; + } + break; + case GL_QUERY: + { + struct gl_query_object *query = _mesa_lookup_query_object(ctx, name); + if (query) + labelPtr = &query->Label; + } + break; + case GL_TRANSFORM_FEEDBACK: + { + struct gl_transform_feedback_object *tfo = + _mesa_lookup_transform_feedback_object(ctx, name); + if (tfo) + labelPtr = &tfo->Label; + } + break; + case GL_SAMPLER: + { + struct gl_sampler_object *so = _mesa_lookup_samplerobj(ctx, name); + if (so) + labelPtr = &so->Label; + } + break; + case GL_TEXTURE: + { + struct gl_texture_object *texObj = _mesa_lookup_texture(ctx, name); + if (texObj) + labelPtr = &texObj->Label; + } + break; + case GL_RENDERBUFFER: + { + struct gl_renderbuffer *rb = _mesa_lookup_renderbuffer(ctx, name); + if (rb) + labelPtr = &rb->Label; + } + break; + case GL_FRAMEBUFFER: + { + struct gl_framebuffer *rb = _mesa_lookup_framebuffer(ctx, name); + if (rb) + labelPtr = &rb->Label; + } + break; + case GL_DISPLAY_LIST: + if (ctx->API == API_OPENGL_COMPAT) { + struct gl_display_list *list = _mesa_lookup_list(ctx, name); + if (list) + labelPtr = &list->Label; + } + else { + goto invalid_enum; + } + break; + case GL_PROGRAM_PIPELINE: + /* requires GL 4.2 */ + goto invalid_enum; + default: + goto invalid_enum; + } + + if (NULL == labelPtr) { + _mesa_error(ctx, GL_INVALID_VALUE, "glObjectLabel(name = %u)", name); + } + + return labelPtr; + +invalid_enum: + _mesa_error(ctx, GL_INVALID_ENUM, "%s(identifier = %s)", + caller, _mesa_lookup_enum_by_nr(identifier)); + return NULL; +} + +void GLAPIENTRY +_mesa_ObjectLabel(GLenum identifier, GLuint name, GLsizei length, + const GLchar *label) +{ + GET_CURRENT_CONTEXT(ctx); + char **labelPtr; + + labelPtr = get_label_pointer(ctx, identifier, name, "glObjectLabel"); + if (!labelPtr) + return; + + set_label(ctx, labelPtr, label, length, "glObjectLabel"); +} + +void GLAPIENTRY +_mesa_GetObjectLabel(GLenum identifier, GLuint name, GLsizei bufSize, + GLsizei *length, GLchar *label) +{ + GET_CURRENT_CONTEXT(ctx); + char **labelPtr; + + labelPtr = get_label_pointer(ctx, identifier, name, "glGetObjectLabel"); + if (!labelPtr) + return; + + copy_label(labelPtr, label, length, bufSize); +} + +void GLAPIENTRY +_mesa_ObjectPtrLabel(const void *ptr, GLsizei length, const GLchar *label) +{ + GET_CURRENT_CONTEXT(ctx); + char **labelPtr; + struct gl_sync_object *const syncObj = (struct gl_sync_object *) ptr; + + if (!_mesa_validate_sync(ctx, syncObj)) { + _mesa_error(ctx, GL_INVALID_VALUE, "glObjectPtrLabel (not a valid sync object)"); + return; + } + + labelPtr = &syncObj->Label; + + set_label(ctx, labelPtr, label, length, "glObjectPtrLabel"); +} + +void GLAPIENTRY +_mesa_GetObjectPtrLabel(const void *ptr, GLsizei bufSize, GLsizei *length, + GLchar *label) +{ + GET_CURRENT_CONTEXT(ctx); + char **labelPtr; + struct gl_sync_object *const syncObj = (struct gl_sync_object *) ptr; + + if (!_mesa_validate_sync(ctx, syncObj)) { + _mesa_error(ctx, GL_INVALID_VALUE, "glGetObjectPtrLabel (not a valid sync object)"); + return; + } + + labelPtr = &syncObj->Label; + + copy_label(labelPtr, label, length, bufSize); +} diff --git a/mesalib/src/mesa/main/objectlabel.h b/mesalib/src/mesa/main/objectlabel.h new file mode 100644 index 000000000..f57d5f7b5 --- /dev/null +++ b/mesalib/src/mesa/main/objectlabel.h @@ -0,0 +1,61 @@ +/* + * Mesa 3-D graphics library + * + * Copyright (C) 2013 Timothy Arceri All Rights Reserved. + * + * Permission is hereby granted, free of charge, to any person obtaining a + * copy of this software and associated documentation files (the "Software"), + * to deal in the Software without restriction, including without limitation + * the rights to use, copy, modify, merge, publish, distribute, sublicense, + * and/or sell copies of the Software, and to permit persons to whom the + * Software is furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included + * in all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS + * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL + * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR + * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, + * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR + * OTHER DEALINGS IN THE SOFTWARE. + */ + + +/** + * \file objectlabel.h + * Mesa object label functions. + * + * This file provides functions to assign and retrieve object labels. + */ + +#ifndef OBJECTLABEL_H +#define OBJECTLABEL_H + + +#include "glheader.h" + + +#ifdef __cplusplus +extern "C" { +#endif + +void GLAPIENTRY +_mesa_ObjectLabel(GLenum identifier, GLuint name, GLsizei length, + const GLchar *label); +void GLAPIENTRY +_mesa_GetObjectLabel(GLenum identifier, GLuint name, GLsizei bufSize, + GLsizei *length, GLchar *label); +void GLAPIENTRY +_mesa_ObjectPtrLabel(const void *ptr, GLsizei length, const GLchar *label); +void GLAPIENTRY +_mesa_GetObjectPtrLabel(const void *ptr, GLsizei bufSize, GLsizei *length, + GLchar *label); + +#ifdef __cplusplus +} +#endif + + +#endif /* OBJECTLABEL_H */ diff --git a/mesalib/src/mesa/main/queryobj.c b/mesalib/src/mesa/main/queryobj.c index ccd5b0179..eb79e457e 100644 --- a/mesalib/src/mesa/main/queryobj.c +++ b/mesalib/src/mesa/main/queryobj.c @@ -126,6 +126,7 @@ _mesa_check_query(struct gl_context *ctx, struct gl_query_object *q) void _mesa_delete_query(struct gl_context *ctx, struct gl_query_object *q) { + free(q->Label); free(q); } diff --git a/mesalib/src/mesa/main/renderbuffer.c b/mesalib/src/mesa/main/renderbuffer.c index d2bde803f..2ff96e548 100644 --- a/mesalib/src/mesa/main/renderbuffer.c +++ b/mesalib/src/mesa/main/renderbuffer.c @@ -84,6 +84,7 @@ void _mesa_delete_renderbuffer(struct gl_context *ctx, struct gl_renderbuffer *rb) { _glthread_DESTROY_MUTEX(rb->Mutex); + free(rb->Label); free(rb); } diff --git a/mesalib/src/mesa/main/samplerobj.c b/mesalib/src/mesa/main/samplerobj.c index 3857eda06..39cfcd086 100644 --- a/mesalib/src/mesa/main/samplerobj.c +++ b/mesalib/src/mesa/main/samplerobj.c @@ -155,6 +155,7 @@ static void _mesa_delete_sampler_object(struct gl_context *ctx, struct gl_sampler_object *sampObj) { + free(sampObj->Label); free(sampObj); } diff --git a/mesalib/src/mesa/main/shaderobj.c b/mesalib/src/mesa/main/shaderobj.c index a62ad0413..0d794ad96 100644 --- a/mesalib/src/mesa/main/shaderobj.c +++ b/mesalib/src/mesa/main/shaderobj.c @@ -125,6 +125,7 @@ static void _mesa_delete_shader(struct gl_context *ctx, struct gl_shader *sh) { free((void *)sh->Source); + free(sh->Label); _mesa_reference_program(ctx, &sh->Program, NULL); ralloc_free(sh); } @@ -351,6 +352,8 @@ _mesa_free_shader_program_data(struct gl_context *ctx, shProg->_LinkedShaders[sh] = NULL; } } + + free(shProg->Label); } diff --git a/mesalib/src/mesa/main/syncobj.c b/mesalib/src/mesa/main/syncobj.c index 5fa548d0d..f9736938a 100644 --- a/mesalib/src/mesa/main/syncobj.c +++ b/mesalib/src/mesa/main/syncobj.c @@ -83,6 +83,7 @@ static void _mesa_delete_sync_object(struct gl_context *ctx, struct gl_sync_object *syncObj) { (void) ctx; + free(syncObj->Label); free(syncObj); } @@ -160,7 +161,7 @@ _mesa_free_sync_data(struct gl_context *ctx) } -static int +int _mesa_validate_sync(struct gl_context *ctx, struct gl_sync_object *syncObj) { return (syncObj != NULL) diff --git a/mesalib/src/mesa/main/syncobj.h b/mesalib/src/mesa/main/syncobj.h index adb5060b1..a6563b09d 100644 --- a/mesalib/src/mesa/main/syncobj.h +++ b/mesalib/src/mesa/main/syncobj.h @@ -53,6 +53,9 @@ _mesa_ref_sync_object(struct gl_context *ctx, struct gl_sync_object *syncObj); extern void GLAPIENTRY _mesa_unref_sync_object(struct gl_context *ctx, struct gl_sync_object *syncObj); +extern int +_mesa_validate_sync(struct gl_context *ctx, struct gl_sync_object *syncObj); + extern GLboolean GLAPIENTRY _mesa_IsSync(GLsync sync); diff --git a/mesalib/src/mesa/main/texobj.c b/mesalib/src/mesa/main/texobj.c index 7c8f04db9..cc2c786bb 100644 --- a/mesalib/src/mesa/main/texobj.c +++ b/mesalib/src/mesa/main/texobj.c @@ -238,6 +238,8 @@ _mesa_delete_texture_object(struct gl_context *ctx, /* destroy the mutex -- it may have allocated memory (eg on bsd) */ _glthread_DESTROY_MUTEX(texObj->Mutex); + free(texObj->Label); + /* free this object */ free(texObj); } diff --git a/mesalib/src/mesa/main/transformfeedback.c b/mesalib/src/mesa/main/transformfeedback.c index 03f188300..3f8a7f48d 100644 --- a/mesalib/src/mesa/main/transformfeedback.c +++ b/mesalib/src/mesa/main/transformfeedback.c @@ -195,6 +195,7 @@ delete_transform_feedback(struct gl_context *ctx, _mesa_reference_buffer_object(ctx, &obj->Buffers[i], NULL); } + free(obj->Label); free(obj); } |