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