xref: /aosp_15_r20/external/mesa3d/src/mesa/main/objectlabel.c (revision 6104692788411f58d303aa86923a9ff6ecaded22)
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 "pipelineobj.h"
33 #include "queryobj.h"
34 #include "samplerobj.h"
35 #include "shaderobj.h"
36 #include "syncobj.h"
37 #include "texobj.h"
38 #include "transformfeedback.h"
39 #include "api_exec_decl.h"
40 
41 
42 /**
43  * Helper for _mesa_ObjectLabel() and _mesa_ObjectPtrLabel().
44  */
45 static void
set_label(struct gl_context * ctx,char ** labelPtr,const char * label,int length,const char * caller,bool ext_length)46 set_label(struct gl_context *ctx, char **labelPtr, const char *label,
47           int length, const char *caller, bool ext_length)
48 {
49    free(*labelPtr);
50    *labelPtr = NULL;
51 
52    /* set new label string */
53    if (label) {
54       if ((!ext_length && length >= 0) ||
55           (ext_length && length > 0)) {
56          if (length >= MAX_LABEL_LENGTH)
57             _mesa_error(ctx, GL_INVALID_VALUE,
58                         "%s(length=%d, which is not less than "
59                         "GL_MAX_LABEL_LENGTH=%d)", caller, length,
60                         MAX_LABEL_LENGTH);
61 
62          /* explicit length */
63          *labelPtr = malloc(length+1);
64          if (*labelPtr) {
65             memcpy(*labelPtr, label, length);
66             /* length is not required to include the null terminator so
67              * add one just in case
68              */
69             (*labelPtr)[length] = '\0';
70          }
71       }
72       else {
73          if (ext_length && length < 0) {
74             _mesa_error(ctx, GL_INVALID_VALUE,
75                         "%s(label length=%d, is less than zero)", caller,
76                         length);
77             return;
78          }
79 
80          int len = strlen(label);
81          if (len >= MAX_LABEL_LENGTH)
82             _mesa_error(ctx, GL_INVALID_VALUE,
83                 "%s(label length=%d, which is not less than "
84                 "GL_MAX_LABEL_LENGTH=%d)", caller, len,
85                 MAX_LABEL_LENGTH);
86 
87          /* null-terminated string */
88          *labelPtr = strdup(label);
89       }
90    }
91 }
92 
93 /**
94  * Helper for _mesa_GetObjectLabel() and _mesa_GetObjectPtrLabel().
95  * \param src  the src label (may be null)
96  * \param dst  pointer to dest buffer (may be null)
97  * \param length  returns length of label (may be null)
98  * \param bufsize  size of dst buffer
99  */
100 static void
copy_label(const GLchar * src,GLchar * dst,GLsizei * length,GLsizei bufSize)101 copy_label(const GLchar *src, GLchar *dst, GLsizei *length, GLsizei bufSize)
102 {
103    int labelLen = 0;
104 
105    /* From http://www.opengl.org/registry/specs/KHR/debug.txt:
106     * "If <length> is NULL, no length is returned. The maximum number of
107     * characters that may be written into <label>, including the null
108     * terminator, is specified by <bufSize>. If no debug label was specified
109     * for the object then <label> will contain a null-terminated empty string,
110     * and zero will be returned in <length>. If <label> is NULL and <length>
111     * is non-NULL then no string will be returned and the length of the label
112     * will be returned in <length>."
113     */
114 
115    if (src)
116       labelLen = strlen(src);
117 
118    if (bufSize == 0) {
119       if (length)
120          *length = labelLen;
121       return;
122    }
123 
124    if (dst) {
125       if (src) {
126          if (bufSize <= labelLen)
127             labelLen = bufSize - 1;
128 
129          memcpy(dst, src, labelLen);
130       }
131 
132       dst[labelLen] = '\0';
133    }
134 
135    if (length)
136       *length = labelLen;
137 }
138 
139 /**
140  * Helper for _mesa_ObjectLabel() and _mesa_GetObjectLabel().
141  */
142 static char **
get_label_pointer(struct gl_context * ctx,GLenum identifier,GLuint name,const char * caller,bool ext_errors)143 get_label_pointer(struct gl_context *ctx, GLenum identifier, GLuint name,
144                   const char *caller, bool ext_errors)
145 {
146    char **labelPtr = NULL;
147    GLenum no_match_error =
148       ext_errors ? GL_INVALID_OPERATION : GL_INVALID_VALUE;
149 
150    switch (identifier) {
151    case GL_BUFFER:
152    case GL_BUFFER_OBJECT_EXT:
153       {
154          struct gl_buffer_object *bufObj = _mesa_lookup_bufferobj(ctx, name);
155          if (bufObj)
156             labelPtr = &bufObj->Label;
157       }
158       break;
159    case GL_SHADER:
160    case GL_SHADER_OBJECT_EXT:
161       {
162          struct gl_shader *shader = _mesa_lookup_shader(ctx, name);
163          if (shader)
164             labelPtr = &shader->Label;
165       }
166       break;
167    case GL_PROGRAM:
168    case GL_PROGRAM_OBJECT_EXT:
169       {
170          struct gl_shader_program *program =
171             _mesa_lookup_shader_program(ctx, name);
172          if (program)
173             labelPtr = &program->Label;
174       }
175       break;
176    case GL_VERTEX_ARRAY:
177    case GL_VERTEX_ARRAY_OBJECT_EXT:
178       {
179          struct gl_vertex_array_object *obj = _mesa_lookup_vao(ctx, name);
180          if (obj)
181             labelPtr = &obj->Label;
182       }
183       break;
184    case GL_QUERY:
185    case GL_QUERY_OBJECT_EXT:
186       {
187          struct gl_query_object *query = _mesa_lookup_query_object(ctx, name);
188          if (query)
189             labelPtr = &query->Label;
190       }
191       break;
192    case GL_TRANSFORM_FEEDBACK:
193       {
194          /* From the GL 4.5 specification, page 536:
195           * "An INVALID_VALUE error is generated if name is not the name of a
196           *  valid object of the type specified by identifier."
197           */
198          struct gl_transform_feedback_object *tfo =
199             _mesa_lookup_transform_feedback_object(ctx, name);
200          if (tfo && tfo->EverBound)
201             labelPtr = &tfo->Label;
202       }
203       break;
204    case GL_SAMPLER:
205       {
206          struct gl_sampler_object *so = _mesa_lookup_samplerobj(ctx, name);
207          if (so)
208             labelPtr = &so->Label;
209       }
210       break;
211    case GL_TEXTURE:
212       {
213          struct gl_texture_object *texObj = _mesa_lookup_texture(ctx, name);
214          if (texObj && texObj->Target)
215             labelPtr = &texObj->Label;
216       }
217       break;
218    case GL_RENDERBUFFER:
219       {
220          struct gl_renderbuffer *rb = _mesa_lookup_renderbuffer(ctx, name);
221          if (rb)
222             labelPtr = &rb->Label;
223       }
224       break;
225    case GL_FRAMEBUFFER:
226       {
227          struct gl_framebuffer *rb = _mesa_lookup_framebuffer(ctx, name);
228          if (rb)
229             labelPtr = &rb->Label;
230       }
231       break;
232    case GL_DISPLAY_LIST:
233       if (_mesa_is_desktop_gl_compat(ctx)) {
234          struct gl_display_list *list = _mesa_lookup_list(ctx, name, false);
235          if (list)
236             labelPtr = &list->Label;
237       }
238       else {
239          goto invalid_enum;
240       }
241       break;
242    case GL_PROGRAM_PIPELINE:
243    case GL_PROGRAM_PIPELINE_OBJECT_EXT:
244       {
245          struct gl_pipeline_object *pipe =
246             _mesa_lookup_pipeline_object(ctx, name);
247          if (pipe)
248             labelPtr = &pipe->Label;
249       }
250       break;
251    default:
252       goto invalid_enum;
253    }
254 
255    if (NULL == labelPtr) {
256       _mesa_error(ctx, no_match_error, "%s(name = %u)", caller, name);
257    }
258 
259    return labelPtr;
260 
261 invalid_enum:
262    _mesa_error(ctx, GL_INVALID_ENUM, "%s(identifier = %s)",
263                caller, _mesa_enum_to_string(identifier));
264    return NULL;
265 }
266 
267 void GLAPIENTRY
_mesa_LabelObjectEXT(GLenum identifier,GLuint name,GLsizei length,const GLchar * label)268 _mesa_LabelObjectEXT(GLenum identifier, GLuint name, GLsizei length,
269                      const GLchar *label)
270 {
271    GET_CURRENT_CONTEXT(ctx);
272    const char *callerstr = "glLabelObjectEXT";
273    char **labelPtr;
274 
275    labelPtr = get_label_pointer(ctx, identifier, name, callerstr, true);
276    if (!labelPtr)
277       return;
278 
279    set_label(ctx, labelPtr, label, length, callerstr, true);
280 }
281 
282 void GLAPIENTRY
_mesa_GetObjectLabelEXT(GLenum identifier,GLuint name,GLsizei bufSize,GLsizei * length,GLchar * label)283 _mesa_GetObjectLabelEXT(GLenum identifier, GLuint name, GLsizei bufSize,
284                         GLsizei *length, GLchar *label)
285 {
286    GET_CURRENT_CONTEXT(ctx);
287    const char *callerstr = "glGetObjectLabelEXT";
288    char **labelPtr;
289 
290    if (bufSize < 0) {
291       _mesa_error(ctx, GL_INVALID_VALUE, "%s(bufSize = %d)", callerstr,
292                   bufSize);
293       return;
294    }
295 
296    labelPtr = get_label_pointer(ctx, identifier, name, callerstr, true);
297    if (!labelPtr)
298       return;
299 
300    copy_label(*labelPtr, label, length, bufSize);
301 }
302 
303 void GLAPIENTRY
_mesa_ObjectLabel(GLenum identifier,GLuint name,GLsizei length,const GLchar * label)304 _mesa_ObjectLabel(GLenum identifier, GLuint name, GLsizei length,
305                   const GLchar *label)
306 {
307    GET_CURRENT_CONTEXT(ctx);
308    const char *callerstr;
309    char **labelPtr;
310 
311    if (_mesa_is_desktop_gl(ctx))
312       callerstr = "glObjectLabel";
313    else
314       callerstr = "glObjectLabelKHR";
315 
316    labelPtr = get_label_pointer(ctx, identifier, name, callerstr, false);
317    if (!labelPtr)
318       return;
319 
320    set_label(ctx, labelPtr, label, length, callerstr, false);
321 }
322 
323 void GLAPIENTRY
_mesa_GetObjectLabel(GLenum identifier,GLuint name,GLsizei bufSize,GLsizei * length,GLchar * label)324 _mesa_GetObjectLabel(GLenum identifier, GLuint name, GLsizei bufSize,
325                      GLsizei *length, GLchar *label)
326 {
327    GET_CURRENT_CONTEXT(ctx);
328    const char *callerstr;
329    char **labelPtr;
330 
331    if (_mesa_is_desktop_gl(ctx))
332       callerstr = "glGetObjectLabel";
333    else
334       callerstr = "glGetObjectLabelKHR";
335 
336    if (bufSize < 0) {
337       _mesa_error(ctx, GL_INVALID_VALUE, "%s(bufSize = %d)", callerstr,
338                   bufSize);
339       return;
340    }
341 
342    labelPtr = get_label_pointer(ctx, identifier, name, callerstr, false);
343    if (!labelPtr)
344       return;
345 
346    copy_label(*labelPtr, label, length, bufSize);
347 }
348 
349 void GLAPIENTRY
_mesa_ObjectPtrLabel(const void * ptr,GLsizei length,const GLchar * label)350 _mesa_ObjectPtrLabel(const void *ptr, GLsizei length, const GLchar *label)
351 {
352    GET_CURRENT_CONTEXT(ctx);
353    struct gl_sync_object *syncObj;
354    const char *callerstr;
355    char **labelPtr;
356 
357    syncObj = _mesa_get_and_ref_sync(ctx, (void*)ptr, true);
358 
359    if (_mesa_is_desktop_gl(ctx))
360       callerstr = "glObjectPtrLabel";
361    else
362       callerstr = "glObjectPtrLabelKHR";
363 
364    if (!syncObj) {
365       _mesa_error(ctx, GL_INVALID_VALUE, "%s (not a valid sync object)",
366                   callerstr);
367       return;
368    }
369 
370    labelPtr = &syncObj->Label;
371 
372    set_label(ctx, labelPtr, label, length, callerstr, false);
373    _mesa_unref_sync_object(ctx, syncObj, 1);
374 }
375 
376 void GLAPIENTRY
_mesa_GetObjectPtrLabel(const void * ptr,GLsizei bufSize,GLsizei * length,GLchar * label)377 _mesa_GetObjectPtrLabel(const void *ptr, GLsizei bufSize, GLsizei *length,
378                         GLchar *label)
379 {
380    GET_CURRENT_CONTEXT(ctx);
381    struct gl_sync_object *syncObj;
382    const char *callerstr;
383    char **labelPtr;
384 
385    if (_mesa_is_desktop_gl(ctx))
386       callerstr = "glGetObjectPtrLabel";
387    else
388       callerstr = "glGetObjectPtrLabelKHR";
389 
390    if (bufSize < 0) {
391       _mesa_error(ctx, GL_INVALID_VALUE, "%s(bufSize = %d)", callerstr,
392                   bufSize);
393       return;
394    }
395 
396    syncObj = _mesa_get_and_ref_sync(ctx, (void*)ptr, true);
397    if (!syncObj) {
398       _mesa_error(ctx, GL_INVALID_VALUE, "%s (not a valid sync object)",
399                   callerstr);
400       return;
401    }
402 
403    labelPtr = &syncObj->Label;
404 
405    copy_label(*labelPtr, label, length, bufSize);
406    _mesa_unref_sync_object(ctx, syncObj, 1);
407 }
408