Home | History | Annotate | Download | only in main
      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