objectlabel.c revision af69d88d
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 "queryobj.h"
34#include "samplerobj.h"
35#include "shaderobj.h"
36#include "syncobj.h"
37#include "texobj.h"
38#include "transformfeedback.h"
39
40
41/**
42 * Helper for _mesa_ObjectLabel() and _mesa_ObjectPtrLabel().
43 */
44static void
45set_label(struct gl_context *ctx, char **labelPtr, const char *label,
46          int length, const char *caller)
47{
48   if (*labelPtr) {
49      /* free old label string */
50      free(*labelPtr);
51      *labelPtr = NULL;
52   }
53
54   /* set new label string */
55   if (label) {
56      if (length >= 0) {
57         if (length >= MAX_LABEL_LENGTH)
58            _mesa_error(ctx, GL_INVALID_VALUE,
59                        "%s(length=%d, which is not less than "
60                        "GL_MAX_LABEL_LENGTH=%d)", caller, length,
61                        MAX_LABEL_LENGTH);
62
63         /* explicit length */
64         *labelPtr = (char *) malloc(length+1);
65         if (*labelPtr) {
66            memcpy(*labelPtr, label, length);
67            /* length is not required to include the null terminator so
68             * add one just in case
69             */
70            (*labelPtr)[length] = '\0';
71         }
72      }
73      else {
74         int len = strlen(label);
75         if (len >= MAX_LABEL_LENGTH)
76            _mesa_error(ctx, GL_INVALID_VALUE,
77                "%s(label length=%d, which is not less than "
78                "GL_MAX_LABEL_LENGTH=%d)", caller, len,
79                MAX_LABEL_LENGTH);
80
81         /* null-terminated string */
82         *labelPtr = _mesa_strdup(label);
83      }
84   }
85}
86
87/**
88 * Helper for _mesa_GetObjectLabel() and _mesa_GetObjectPtrLabel().
89 * \param src  the src label (may be null)
90 * \param dst  pointer to dest buffer (may be null)
91 * \param length  returns length of label (may be null)
92 * \param bufsize  size of dst buffer
93 */
94static void
95copy_label(const GLchar *src, GLchar *dst, GLsizei *length, GLsizei bufSize)
96{
97   int labelLen = 0;
98
99   /* From http://www.opengl.org/registry/specs/KHR/debug.txt:
100    * "If <length> is NULL, no length is returned. The maximum number of
101    * characters that may be written into <label>, including the null
102    * terminator, is specified by <bufSize>. If no debug label was specified
103    * for the object then <label> will contain a null-terminated empty string,
104    * and zero will be returned in <length>. If <label> is NULL and <length>
105    * is non-NULL then no string will be returned and the length of the label
106    * will be returned in <length>."
107    */
108
109   if (src)
110      labelLen = strlen(src);
111
112   if (dst) {
113      if (src) {
114         if (bufSize <= labelLen)
115            labelLen = bufSize - 1;
116
117         memcpy(dst, src, labelLen);
118      }
119
120      dst[labelLen] = '\0';
121   }
122
123   if (length)
124      *length = labelLen;
125}
126
127/**
128 * Helper for _mesa_ObjectLabel() and _mesa_GetObjectLabel().
129 */
130static char **
131get_label_pointer(struct gl_context *ctx, GLenum identifier, GLuint name,
132                  const char *caller)
133{
134   char **labelPtr = NULL;
135
136   switch (identifier) {
137   case GL_BUFFER:
138      {
139         struct gl_buffer_object *bufObj = _mesa_lookup_bufferobj(ctx, name);
140         if (bufObj)
141            labelPtr = &bufObj->Label;
142      }
143      break;
144   case GL_SHADER:
145      {
146         struct gl_shader *shader = _mesa_lookup_shader(ctx, name);
147         if (shader)
148            labelPtr = &shader->Label;
149      }
150      break;
151   case GL_PROGRAM:
152      {
153         struct gl_shader_program *program =
154            _mesa_lookup_shader_program(ctx, name);
155         if (program)
156            labelPtr = &program->Label;
157      }
158      break;
159   case GL_VERTEX_ARRAY:
160      {
161         struct gl_vertex_array_object *obj = _mesa_lookup_vao(ctx, name);
162         if (obj)
163            labelPtr = &obj->Label;
164      }
165      break;
166   case GL_QUERY:
167      {
168         struct gl_query_object *query = _mesa_lookup_query_object(ctx, name);
169         if (query)
170            labelPtr = &query->Label;
171      }
172      break;
173   case GL_TRANSFORM_FEEDBACK:
174      {
175         struct gl_transform_feedback_object *tfo =
176            _mesa_lookup_transform_feedback_object(ctx, name);
177         if (tfo)
178            labelPtr = &tfo->Label;
179      }
180      break;
181   case GL_SAMPLER:
182      {
183         struct gl_sampler_object *so = _mesa_lookup_samplerobj(ctx, name);
184         if (so)
185            labelPtr = &so->Label;
186      }
187      break;
188   case GL_TEXTURE:
189      {
190         struct gl_texture_object *texObj = _mesa_lookup_texture(ctx, name);
191         if (texObj)
192            labelPtr = &texObj->Label;
193      }
194      break;
195   case GL_RENDERBUFFER:
196      {
197         struct gl_renderbuffer *rb = _mesa_lookup_renderbuffer(ctx, name);
198         if (rb)
199            labelPtr = &rb->Label;
200      }
201      break;
202   case GL_FRAMEBUFFER:
203      {
204         struct gl_framebuffer *rb = _mesa_lookup_framebuffer(ctx, name);
205         if (rb)
206            labelPtr = &rb->Label;
207      }
208      break;
209   case GL_DISPLAY_LIST:
210      if (ctx->API == API_OPENGL_COMPAT) {
211         struct gl_display_list *list = _mesa_lookup_list(ctx, name);
212         if (list)
213            labelPtr = &list->Label;
214      }
215      else {
216         goto invalid_enum;
217      }
218      break;
219   case GL_PROGRAM_PIPELINE:
220      /* requires GL 4.2 */
221      goto invalid_enum;
222   default:
223      goto invalid_enum;
224   }
225
226   if (NULL == labelPtr) {
227      _mesa_error(ctx, GL_INVALID_VALUE, "%s(name = %u)", caller, name);
228   }
229
230   return labelPtr;
231
232invalid_enum:
233   _mesa_error(ctx, GL_INVALID_ENUM, "%s(identifier = %s)",
234               caller, _mesa_lookup_enum_by_nr(identifier));
235   return NULL;
236}
237
238void GLAPIENTRY
239_mesa_ObjectLabel(GLenum identifier, GLuint name, GLsizei length,
240                  const GLchar *label)
241{
242   GET_CURRENT_CONTEXT(ctx);
243   char **labelPtr;
244
245   labelPtr = get_label_pointer(ctx, identifier, name, "glObjectLabel");
246   if (!labelPtr)
247      return;
248
249   set_label(ctx, labelPtr, label, length, "glObjectLabel");
250}
251
252void GLAPIENTRY
253_mesa_GetObjectLabel(GLenum identifier, GLuint name, GLsizei bufSize,
254                     GLsizei *length, GLchar *label)
255{
256   GET_CURRENT_CONTEXT(ctx);
257   char **labelPtr;
258
259   if (bufSize < 0) {
260      _mesa_error(ctx, GL_INVALID_VALUE, "glGetObjectLabel(bufSize = %d)",
261                  bufSize);
262      return;
263   }
264
265   labelPtr = get_label_pointer(ctx, identifier, name, "glGetObjectLabel");
266   if (!labelPtr)
267      return;
268
269   copy_label(*labelPtr, label, length, bufSize);
270}
271
272void GLAPIENTRY
273_mesa_ObjectPtrLabel(const void *ptr, GLsizei length, const GLchar *label)
274{
275   GET_CURRENT_CONTEXT(ctx);
276   char **labelPtr;
277   struct gl_sync_object *const syncObj = (struct gl_sync_object *) ptr;
278
279   if (!_mesa_validate_sync(ctx, syncObj)) {
280      _mesa_error(ctx, GL_INVALID_VALUE, "glObjectPtrLabel (not a valid sync object)");
281      return;
282   }
283
284   labelPtr = &syncObj->Label;
285
286   set_label(ctx, labelPtr, label, length, "glObjectPtrLabel");
287}
288
289void GLAPIENTRY
290_mesa_GetObjectPtrLabel(const void *ptr, GLsizei bufSize, GLsizei *length,
291                        GLchar *label)
292{
293   GET_CURRENT_CONTEXT(ctx);
294   char **labelPtr;
295   struct gl_sync_object *const syncObj = (struct gl_sync_object *) ptr;
296
297   if (bufSize < 0) {
298      _mesa_error(ctx, GL_INVALID_VALUE, "glGetObjectPtrLabel(bufSize = %d)",
299                  bufSize);
300      return;
301   }
302
303   if (!_mesa_validate_sync(ctx, syncObj)) {
304      _mesa_error(ctx, GL_INVALID_VALUE, "glGetObjectPtrLabel (not a valid sync object)");
305      return;
306   }
307
308   labelPtr = &syncObj->Label;
309
310   copy_label(*labelPtr, label, length, bufSize);
311}
312