1 /* 2 * Mesa 3-D graphics library 3 * 4 * Copyright (C) 2013 Timothy Arceri All Rights Reserved. 5 * 6 * Permission is hereby granted, free of charge, to any person obtaining a 7 * copy of this software and associated documentation files (the "Software"), 8 * to deal in the Software without restriction, including without limitation 9 * the rights to use, copy, modify, merge, publish, distribute, sublicense, 10 * and/or sell copies of the Software, and to permit persons to whom the 11 * Software is furnished to do so, subject to the following conditions: 12 * 13 * The above copyright notice and this permission notice shall be included 14 * in all copies or substantial portions of the Software. 15 * 16 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS 17 * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 18 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL 19 * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR 20 * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, 21 * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR 22 * OTHER DEALINGS IN THE SOFTWARE. 23 */ 24 25 26 #include "arrayobj.h" 27 #include "bufferobj.h" 28 #include "context.h" 29 #include "dlist.h" 30 #include "enums.h" 31 #include "fbobject.h" 32 #include "objectlabel.h" 33 #include "pipelineobj.h" 34 #include "queryobj.h" 35 #include "samplerobj.h" 36 #include "shaderobj.h" 37 #include "syncobj.h" 38 #include "texobj.h" 39 #include "transformfeedback.h" 40 41 42 /** 43 * Helper for _mesa_ObjectLabel() and _mesa_ObjectPtrLabel(). 44 */ 45 static void 46 set_label(struct gl_context *ctx, char **labelPtr, const char *label, 47 int length, const char *caller) 48 { 49 free(*labelPtr); 50 *labelPtr = NULL; 51 52 /* set new label string */ 53 if (label) { 54 if (length >= 0) { 55 if (length >= MAX_LABEL_LENGTH) 56 _mesa_error(ctx, GL_INVALID_VALUE, 57 "%s(length=%d, which is not less than " 58 "GL_MAX_LABEL_LENGTH=%d)", caller, length, 59 MAX_LABEL_LENGTH); 60 61 /* explicit length */ 62 *labelPtr = malloc(length+1); 63 if (*labelPtr) { 64 memcpy(*labelPtr, label, length); 65 /* length is not required to include the null terminator so 66 * add one just in case 67 */ 68 (*labelPtr)[length] = '\0'; 69 } 70 } 71 else { 72 int len = strlen(label); 73 if (len >= MAX_LABEL_LENGTH) 74 _mesa_error(ctx, GL_INVALID_VALUE, 75 "%s(label length=%d, which is not less than " 76 "GL_MAX_LABEL_LENGTH=%d)", caller, len, 77 MAX_LABEL_LENGTH); 78 79 /* null-terminated string */ 80 *labelPtr = strdup(label); 81 } 82 } 83 } 84 85 /** 86 * Helper for _mesa_GetObjectLabel() and _mesa_GetObjectPtrLabel(). 87 * \param src the src label (may be null) 88 * \param dst pointer to dest buffer (may be null) 89 * \param length returns length of label (may be null) 90 * \param bufsize size of dst buffer 91 */ 92 static void 93 copy_label(const GLchar *src, GLchar *dst, GLsizei *length, GLsizei bufSize) 94 { 95 int labelLen = 0; 96 97 /* From http://www.opengl.org/registry/specs/KHR/debug.txt: 98 * "If <length> is NULL, no length is returned. The maximum number of 99 * characters that may be written into <label>, including the null 100 * terminator, is specified by <bufSize>. If no debug label was specified 101 * for the object then <label> will contain a null-terminated empty string, 102 * and zero will be returned in <length>. If <label> is NULL and <length> 103 * is non-NULL then no string will be returned and the length of the label 104 * will be returned in <length>." 105 */ 106 107 if (src) 108 labelLen = strlen(src); 109 110 if (bufSize == 0) { 111 if (length) 112 *length = labelLen; 113 return; 114 } 115 116 if (dst) { 117 if (src) { 118 if (bufSize <= labelLen) 119 labelLen = bufSize - 1; 120 121 memcpy(dst, src, labelLen); 122 } 123 124 dst[labelLen] = '\0'; 125 } 126 127 if (length) 128 *length = labelLen; 129 } 130 131 /** 132 * Helper for _mesa_ObjectLabel() and _mesa_GetObjectLabel(). 133 */ 134 static char ** 135 get_label_pointer(struct gl_context *ctx, GLenum identifier, GLuint name, 136 const char *caller) 137 { 138 char **labelPtr = NULL; 139 140 switch (identifier) { 141 case GL_BUFFER: 142 { 143 struct gl_buffer_object *bufObj = _mesa_lookup_bufferobj(ctx, name); 144 if (bufObj) 145 labelPtr = &bufObj->Label; 146 } 147 break; 148 case GL_SHADER: 149 { 150 struct gl_shader *shader = _mesa_lookup_shader(ctx, name); 151 if (shader) 152 labelPtr = &shader->Label; 153 } 154 break; 155 case GL_PROGRAM: 156 { 157 struct gl_shader_program *program = 158 _mesa_lookup_shader_program(ctx, name); 159 if (program) 160 labelPtr = &program->Label; 161 } 162 break; 163 case GL_VERTEX_ARRAY: 164 { 165 struct gl_vertex_array_object *obj = _mesa_lookup_vao(ctx, name); 166 if (obj) 167 labelPtr = &obj->Label; 168 } 169 break; 170 case GL_QUERY: 171 { 172 struct gl_query_object *query = _mesa_lookup_query_object(ctx, name); 173 if (query) 174 labelPtr = &query->Label; 175 } 176 break; 177 case GL_TRANSFORM_FEEDBACK: 178 { 179 /* From the GL 4.5 specification, page 536: 180 * "An INVALID_VALUE error is generated if name is not the name of a 181 * valid object of the type specified by identifier." 182 */ 183 struct gl_transform_feedback_object *tfo = 184 _mesa_lookup_transform_feedback_object(ctx, name); 185 if (tfo && tfo->EverBound) 186 labelPtr = &tfo->Label; 187 } 188 break; 189 case GL_SAMPLER: 190 { 191 struct gl_sampler_object *so = _mesa_lookup_samplerobj(ctx, name); 192 if (so) 193 labelPtr = &so->Label; 194 } 195 break; 196 case GL_TEXTURE: 197 { 198 struct gl_texture_object *texObj = _mesa_lookup_texture(ctx, name); 199 if (texObj && texObj->Target) 200 labelPtr = &texObj->Label; 201 } 202 break; 203 case GL_RENDERBUFFER: 204 { 205 struct gl_renderbuffer *rb = _mesa_lookup_renderbuffer(ctx, name); 206 if (rb) 207 labelPtr = &rb->Label; 208 } 209 break; 210 case GL_FRAMEBUFFER: 211 { 212 struct gl_framebuffer *rb = _mesa_lookup_framebuffer(ctx, name); 213 if (rb) 214 labelPtr = &rb->Label; 215 } 216 break; 217 case GL_DISPLAY_LIST: 218 if (ctx->API == API_OPENGL_COMPAT) { 219 struct gl_display_list *list = _mesa_lookup_list(ctx, name); 220 if (list) 221 labelPtr = &list->Label; 222 } 223 else { 224 goto invalid_enum; 225 } 226 break; 227 case GL_PROGRAM_PIPELINE: 228 { 229 struct gl_pipeline_object *pipe = 230 _mesa_lookup_pipeline_object(ctx, name); 231 if (pipe) 232 labelPtr = &pipe->Label; 233 } 234 break; 235 default: 236 goto invalid_enum; 237 } 238 239 if (NULL == labelPtr) { 240 _mesa_error(ctx, GL_INVALID_VALUE, "%s(name = %u)", caller, name); 241 } 242 243 return labelPtr; 244 245 invalid_enum: 246 _mesa_error(ctx, GL_INVALID_ENUM, "%s(identifier = %s)", 247 caller, _mesa_enum_to_string(identifier)); 248 return NULL; 249 } 250 251 void GLAPIENTRY 252 _mesa_ObjectLabel(GLenum identifier, GLuint name, GLsizei length, 253 const GLchar *label) 254 { 255 GET_CURRENT_CONTEXT(ctx); 256 const char *callerstr; 257 char **labelPtr; 258 259 if (_mesa_is_desktop_gl(ctx)) 260 callerstr = "glObjectLabel"; 261 else 262 callerstr = "glObjectLabelKHR"; 263 264 labelPtr = get_label_pointer(ctx, identifier, name, callerstr); 265 if (!labelPtr) 266 return; 267 268 set_label(ctx, labelPtr, label, length, callerstr); 269 } 270 271 void GLAPIENTRY 272 _mesa_GetObjectLabel(GLenum identifier, GLuint name, GLsizei bufSize, 273 GLsizei *length, GLchar *label) 274 { 275 GET_CURRENT_CONTEXT(ctx); 276 const char *callerstr; 277 char **labelPtr; 278 279 if (_mesa_is_desktop_gl(ctx)) 280 callerstr = "glGetObjectLabel"; 281 else 282 callerstr = "glGetObjectLabelKHR"; 283 284 if (bufSize < 0) { 285 _mesa_error(ctx, GL_INVALID_VALUE, "%s(bufSize = %d)", callerstr, 286 bufSize); 287 return; 288 } 289 290 labelPtr = get_label_pointer(ctx, identifier, name, callerstr); 291 if (!labelPtr) 292 return; 293 294 copy_label(*labelPtr, label, length, bufSize); 295 } 296 297 void GLAPIENTRY 298 _mesa_ObjectPtrLabel(const void *ptr, GLsizei length, const GLchar *label) 299 { 300 GET_CURRENT_CONTEXT(ctx); 301 struct gl_sync_object *syncObj; 302 const char *callerstr; 303 char **labelPtr; 304 305 syncObj = _mesa_get_and_ref_sync(ctx, (void*)ptr, true); 306 307 if (_mesa_is_desktop_gl(ctx)) 308 callerstr = "glObjectPtrLabel"; 309 else 310 callerstr = "glObjectPtrLabelKHR"; 311 312 if (!syncObj) { 313 _mesa_error(ctx, GL_INVALID_VALUE, "%s (not a valid sync object)", 314 callerstr); 315 return; 316 } 317 318 labelPtr = &syncObj->Label; 319 320 set_label(ctx, labelPtr, label, length, callerstr); 321 _mesa_unref_sync_object(ctx, syncObj, 1); 322 } 323 324 void GLAPIENTRY 325 _mesa_GetObjectPtrLabel(const void *ptr, GLsizei bufSize, GLsizei *length, 326 GLchar *label) 327 { 328 GET_CURRENT_CONTEXT(ctx); 329 struct gl_sync_object *syncObj; 330 const char *callerstr; 331 char **labelPtr; 332 333 if (_mesa_is_desktop_gl(ctx)) 334 callerstr = "glGetObjectPtrLabel"; 335 else 336 callerstr = "glGetObjectPtrLabelKHR"; 337 338 if (bufSize < 0) { 339 _mesa_error(ctx, GL_INVALID_VALUE, "%s(bufSize = %d)", callerstr, 340 bufSize); 341 return; 342 } 343 344 syncObj = _mesa_get_and_ref_sync(ctx, (void*)ptr, true); 345 if (!syncObj) { 346 _mesa_error(ctx, GL_INVALID_VALUE, "%s (not a valid sync object)", 347 callerstr); 348 return; 349 } 350 351 labelPtr = &syncObj->Label; 352 353 copy_label(*labelPtr, label, length, bufSize); 354 _mesa_unref_sync_object(ctx, syncObj, 1); 355 } 356