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
set_label(struct gl_context * ctx,char ** labelPtr,const char * label,int length,const char * caller)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
copy_label(const GLchar * src,GLchar * dst,GLsizei * length,GLsizei bufSize)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 **
get_label_pointer(struct gl_context * ctx,GLenum identifier,GLuint name,const char * caller)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
_mesa_ObjectLabel(GLenum identifier,GLuint name,GLsizei length,const GLchar * label)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
_mesa_GetObjectLabel(GLenum identifier,GLuint name,GLsizei bufSize,GLsizei * length,GLchar * label)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
_mesa_ObjectPtrLabel(const void * ptr,GLsizei length,const GLchar * label)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
_mesa_GetObjectPtrLabel(const void * ptr,GLsizei bufSize,GLsizei * length,GLchar * label)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