1848b8605Smrg/*
2848b8605Smrg * Mesa 3-D graphics library
3848b8605Smrg *
4848b8605Smrg * Copyright (C) 2013  Timothy Arceri   All Rights Reserved.
5848b8605Smrg *
6848b8605Smrg * Permission is hereby granted, free of charge, to any person obtaining a
7848b8605Smrg * copy of this software and associated documentation files (the "Software"),
8848b8605Smrg * to deal in the Software without restriction, including without limitation
9848b8605Smrg * the rights to use, copy, modify, merge, publish, distribute, sublicense,
10848b8605Smrg * and/or sell copies of the Software, and to permit persons to whom the
11848b8605Smrg * Software is furnished to do so, subject to the following conditions:
12848b8605Smrg *
13848b8605Smrg * The above copyright notice and this permission notice shall be included
14848b8605Smrg * in all copies or substantial portions of the Software.
15848b8605Smrg *
16848b8605Smrg * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
17848b8605Smrg * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
18848b8605Smrg * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL
19848b8605Smrg * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR
20848b8605Smrg * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
21848b8605Smrg * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
22848b8605Smrg * OTHER DEALINGS IN THE SOFTWARE.
23848b8605Smrg */
24848b8605Smrg
25848b8605Smrg
26848b8605Smrg#include "arrayobj.h"
27848b8605Smrg#include "bufferobj.h"
28848b8605Smrg#include "context.h"
29848b8605Smrg#include "dlist.h"
30848b8605Smrg#include "enums.h"
31848b8605Smrg#include "fbobject.h"
32848b8605Smrg#include "objectlabel.h"
33b8e80941Smrg#include "pipelineobj.h"
34848b8605Smrg#include "queryobj.h"
35848b8605Smrg#include "samplerobj.h"
36848b8605Smrg#include "shaderobj.h"
37848b8605Smrg#include "syncobj.h"
38848b8605Smrg#include "texobj.h"
39848b8605Smrg#include "transformfeedback.h"
40848b8605Smrg
41848b8605Smrg
42848b8605Smrg/**
43848b8605Smrg * Helper for _mesa_ObjectLabel() and _mesa_ObjectPtrLabel().
44848b8605Smrg */
45848b8605Smrgstatic void
46848b8605Smrgset_label(struct gl_context *ctx, char **labelPtr, const char *label,
47848b8605Smrg          int length, const char *caller)
48848b8605Smrg{
49b8e80941Smrg   free(*labelPtr);
50b8e80941Smrg   *labelPtr = NULL;
51848b8605Smrg
52848b8605Smrg   /* set new label string */
53848b8605Smrg   if (label) {
54848b8605Smrg      if (length >= 0) {
55848b8605Smrg         if (length >= MAX_LABEL_LENGTH)
56848b8605Smrg            _mesa_error(ctx, GL_INVALID_VALUE,
57848b8605Smrg                        "%s(length=%d, which is not less than "
58848b8605Smrg                        "GL_MAX_LABEL_LENGTH=%d)", caller, length,
59848b8605Smrg                        MAX_LABEL_LENGTH);
60848b8605Smrg
61848b8605Smrg         /* explicit length */
62b8e80941Smrg         *labelPtr = malloc(length+1);
63848b8605Smrg         if (*labelPtr) {
64848b8605Smrg            memcpy(*labelPtr, label, length);
65848b8605Smrg            /* length is not required to include the null terminator so
66848b8605Smrg             * add one just in case
67848b8605Smrg             */
68848b8605Smrg            (*labelPtr)[length] = '\0';
69848b8605Smrg         }
70848b8605Smrg      }
71848b8605Smrg      else {
72848b8605Smrg         int len = strlen(label);
73848b8605Smrg         if (len >= MAX_LABEL_LENGTH)
74848b8605Smrg            _mesa_error(ctx, GL_INVALID_VALUE,
75848b8605Smrg                "%s(label length=%d, which is not less than "
76848b8605Smrg                "GL_MAX_LABEL_LENGTH=%d)", caller, len,
77848b8605Smrg                MAX_LABEL_LENGTH);
78848b8605Smrg
79848b8605Smrg         /* null-terminated string */
80b8e80941Smrg         *labelPtr = strdup(label);
81848b8605Smrg      }
82848b8605Smrg   }
83848b8605Smrg}
84848b8605Smrg
85848b8605Smrg/**
86848b8605Smrg * Helper for _mesa_GetObjectLabel() and _mesa_GetObjectPtrLabel().
87848b8605Smrg * \param src  the src label (may be null)
88848b8605Smrg * \param dst  pointer to dest buffer (may be null)
89848b8605Smrg * \param length  returns length of label (may be null)
90848b8605Smrg * \param bufsize  size of dst buffer
91848b8605Smrg */
92848b8605Smrgstatic void
93848b8605Smrgcopy_label(const GLchar *src, GLchar *dst, GLsizei *length, GLsizei bufSize)
94848b8605Smrg{
95848b8605Smrg   int labelLen = 0;
96848b8605Smrg
97848b8605Smrg   /* From http://www.opengl.org/registry/specs/KHR/debug.txt:
98848b8605Smrg    * "If <length> is NULL, no length is returned. The maximum number of
99848b8605Smrg    * characters that may be written into <label>, including the null
100848b8605Smrg    * terminator, is specified by <bufSize>. If no debug label was specified
101848b8605Smrg    * for the object then <label> will contain a null-terminated empty string,
102848b8605Smrg    * and zero will be returned in <length>. If <label> is NULL and <length>
103848b8605Smrg    * is non-NULL then no string will be returned and the length of the label
104848b8605Smrg    * will be returned in <length>."
105848b8605Smrg    */
106848b8605Smrg
107848b8605Smrg   if (src)
108848b8605Smrg      labelLen = strlen(src);
109848b8605Smrg
110b8e80941Smrg   if (bufSize == 0) {
111b8e80941Smrg      if (length)
112b8e80941Smrg         *length = labelLen;
113b8e80941Smrg      return;
114b8e80941Smrg   }
115b8e80941Smrg
116848b8605Smrg   if (dst) {
117848b8605Smrg      if (src) {
118848b8605Smrg         if (bufSize <= labelLen)
119848b8605Smrg            labelLen = bufSize - 1;
120848b8605Smrg
121848b8605Smrg         memcpy(dst, src, labelLen);
122848b8605Smrg      }
123848b8605Smrg
124848b8605Smrg      dst[labelLen] = '\0';
125848b8605Smrg   }
126848b8605Smrg
127848b8605Smrg   if (length)
128848b8605Smrg      *length = labelLen;
129848b8605Smrg}
130848b8605Smrg
131848b8605Smrg/**
132848b8605Smrg * Helper for _mesa_ObjectLabel() and _mesa_GetObjectLabel().
133848b8605Smrg */
134848b8605Smrgstatic char **
135848b8605Smrgget_label_pointer(struct gl_context *ctx, GLenum identifier, GLuint name,
136848b8605Smrg                  const char *caller)
137848b8605Smrg{
138848b8605Smrg   char **labelPtr = NULL;
139848b8605Smrg
140848b8605Smrg   switch (identifier) {
141848b8605Smrg   case GL_BUFFER:
142848b8605Smrg      {
143848b8605Smrg         struct gl_buffer_object *bufObj = _mesa_lookup_bufferobj(ctx, name);
144848b8605Smrg         if (bufObj)
145848b8605Smrg            labelPtr = &bufObj->Label;
146848b8605Smrg      }
147848b8605Smrg      break;
148848b8605Smrg   case GL_SHADER:
149848b8605Smrg      {
150848b8605Smrg         struct gl_shader *shader = _mesa_lookup_shader(ctx, name);
151848b8605Smrg         if (shader)
152848b8605Smrg            labelPtr = &shader->Label;
153848b8605Smrg      }
154848b8605Smrg      break;
155848b8605Smrg   case GL_PROGRAM:
156848b8605Smrg      {
157848b8605Smrg         struct gl_shader_program *program =
158848b8605Smrg            _mesa_lookup_shader_program(ctx, name);
159848b8605Smrg         if (program)
160848b8605Smrg            labelPtr = &program->Label;
161848b8605Smrg      }
162848b8605Smrg      break;
163848b8605Smrg   case GL_VERTEX_ARRAY:
164848b8605Smrg      {
165848b8605Smrg         struct gl_vertex_array_object *obj = _mesa_lookup_vao(ctx, name);
166848b8605Smrg         if (obj)
167848b8605Smrg            labelPtr = &obj->Label;
168848b8605Smrg      }
169848b8605Smrg      break;
170848b8605Smrg   case GL_QUERY:
171848b8605Smrg      {
172848b8605Smrg         struct gl_query_object *query = _mesa_lookup_query_object(ctx, name);
173848b8605Smrg         if (query)
174848b8605Smrg            labelPtr = &query->Label;
175848b8605Smrg      }
176848b8605Smrg      break;
177848b8605Smrg   case GL_TRANSFORM_FEEDBACK:
178848b8605Smrg      {
179b8e80941Smrg         /* From the GL 4.5 specification, page 536:
180b8e80941Smrg          * "An INVALID_VALUE error is generated if name is not the name of a
181b8e80941Smrg          *  valid object of the type specified by identifier."
182b8e80941Smrg          */
183848b8605Smrg         struct gl_transform_feedback_object *tfo =
184848b8605Smrg            _mesa_lookup_transform_feedback_object(ctx, name);
185b8e80941Smrg         if (tfo && tfo->EverBound)
186848b8605Smrg            labelPtr = &tfo->Label;
187848b8605Smrg      }
188848b8605Smrg      break;
189848b8605Smrg   case GL_SAMPLER:
190848b8605Smrg      {
191848b8605Smrg         struct gl_sampler_object *so = _mesa_lookup_samplerobj(ctx, name);
192848b8605Smrg         if (so)
193848b8605Smrg            labelPtr = &so->Label;
194848b8605Smrg      }
195848b8605Smrg      break;
196848b8605Smrg   case GL_TEXTURE:
197848b8605Smrg      {
198848b8605Smrg         struct gl_texture_object *texObj = _mesa_lookup_texture(ctx, name);
199b8e80941Smrg         if (texObj && texObj->Target)
200848b8605Smrg            labelPtr = &texObj->Label;
201848b8605Smrg      }
202848b8605Smrg      break;
203848b8605Smrg   case GL_RENDERBUFFER:
204848b8605Smrg      {
205848b8605Smrg         struct gl_renderbuffer *rb = _mesa_lookup_renderbuffer(ctx, name);
206848b8605Smrg         if (rb)
207848b8605Smrg            labelPtr = &rb->Label;
208848b8605Smrg      }
209848b8605Smrg      break;
210848b8605Smrg   case GL_FRAMEBUFFER:
211848b8605Smrg      {
212848b8605Smrg         struct gl_framebuffer *rb = _mesa_lookup_framebuffer(ctx, name);
213848b8605Smrg         if (rb)
214848b8605Smrg            labelPtr = &rb->Label;
215848b8605Smrg      }
216848b8605Smrg      break;
217848b8605Smrg   case GL_DISPLAY_LIST:
218848b8605Smrg      if (ctx->API == API_OPENGL_COMPAT) {
219848b8605Smrg         struct gl_display_list *list = _mesa_lookup_list(ctx, name);
220848b8605Smrg         if (list)
221848b8605Smrg            labelPtr = &list->Label;
222848b8605Smrg      }
223848b8605Smrg      else {
224848b8605Smrg         goto invalid_enum;
225848b8605Smrg      }
226848b8605Smrg      break;
227848b8605Smrg   case GL_PROGRAM_PIPELINE:
228b8e80941Smrg      {
229b8e80941Smrg         struct gl_pipeline_object *pipe =
230b8e80941Smrg            _mesa_lookup_pipeline_object(ctx, name);
231b8e80941Smrg         if (pipe)
232b8e80941Smrg            labelPtr = &pipe->Label;
233b8e80941Smrg      }
234b8e80941Smrg      break;
235848b8605Smrg   default:
236848b8605Smrg      goto invalid_enum;
237848b8605Smrg   }
238848b8605Smrg
239848b8605Smrg   if (NULL == labelPtr) {
240848b8605Smrg      _mesa_error(ctx, GL_INVALID_VALUE, "%s(name = %u)", caller, name);
241848b8605Smrg   }
242848b8605Smrg
243848b8605Smrg   return labelPtr;
244848b8605Smrg
245848b8605Smrginvalid_enum:
246848b8605Smrg   _mesa_error(ctx, GL_INVALID_ENUM, "%s(identifier = %s)",
247b8e80941Smrg               caller, _mesa_enum_to_string(identifier));
248848b8605Smrg   return NULL;
249848b8605Smrg}
250848b8605Smrg
251848b8605Smrgvoid GLAPIENTRY
252848b8605Smrg_mesa_ObjectLabel(GLenum identifier, GLuint name, GLsizei length,
253848b8605Smrg                  const GLchar *label)
254848b8605Smrg{
255848b8605Smrg   GET_CURRENT_CONTEXT(ctx);
256b8e80941Smrg   const char *callerstr;
257848b8605Smrg   char **labelPtr;
258848b8605Smrg
259b8e80941Smrg   if (_mesa_is_desktop_gl(ctx))
260b8e80941Smrg      callerstr = "glObjectLabel";
261b8e80941Smrg   else
262b8e80941Smrg      callerstr = "glObjectLabelKHR";
263b8e80941Smrg
264b8e80941Smrg   labelPtr = get_label_pointer(ctx, identifier, name, callerstr);
265848b8605Smrg   if (!labelPtr)
266848b8605Smrg      return;
267848b8605Smrg
268b8e80941Smrg   set_label(ctx, labelPtr, label, length, callerstr);
269848b8605Smrg}
270848b8605Smrg
271848b8605Smrgvoid GLAPIENTRY
272848b8605Smrg_mesa_GetObjectLabel(GLenum identifier, GLuint name, GLsizei bufSize,
273848b8605Smrg                     GLsizei *length, GLchar *label)
274848b8605Smrg{
275848b8605Smrg   GET_CURRENT_CONTEXT(ctx);
276b8e80941Smrg   const char *callerstr;
277848b8605Smrg   char **labelPtr;
278848b8605Smrg
279b8e80941Smrg   if (_mesa_is_desktop_gl(ctx))
280b8e80941Smrg      callerstr = "glGetObjectLabel";
281b8e80941Smrg   else
282b8e80941Smrg      callerstr = "glGetObjectLabelKHR";
283b8e80941Smrg
284848b8605Smrg   if (bufSize < 0) {
285b8e80941Smrg      _mesa_error(ctx, GL_INVALID_VALUE, "%s(bufSize = %d)", callerstr,
286848b8605Smrg                  bufSize);
287848b8605Smrg      return;
288848b8605Smrg   }
289848b8605Smrg
290b8e80941Smrg   labelPtr = get_label_pointer(ctx, identifier, name, callerstr);
291848b8605Smrg   if (!labelPtr)
292848b8605Smrg      return;
293848b8605Smrg
294848b8605Smrg   copy_label(*labelPtr, label, length, bufSize);
295848b8605Smrg}
296848b8605Smrg
297848b8605Smrgvoid GLAPIENTRY
298848b8605Smrg_mesa_ObjectPtrLabel(const void *ptr, GLsizei length, const GLchar *label)
299848b8605Smrg{
300848b8605Smrg   GET_CURRENT_CONTEXT(ctx);
301b8e80941Smrg   struct gl_sync_object *syncObj;
302b8e80941Smrg   const char *callerstr;
303848b8605Smrg   char **labelPtr;
304848b8605Smrg
305b8e80941Smrg   syncObj = _mesa_get_and_ref_sync(ctx, (void*)ptr, true);
306b8e80941Smrg
307b8e80941Smrg   if (_mesa_is_desktop_gl(ctx))
308b8e80941Smrg      callerstr = "glObjectPtrLabel";
309b8e80941Smrg   else
310b8e80941Smrg      callerstr = "glObjectPtrLabelKHR";
311b8e80941Smrg
312b8e80941Smrg   if (!syncObj) {
313b8e80941Smrg      _mesa_error(ctx, GL_INVALID_VALUE, "%s (not a valid sync object)",
314b8e80941Smrg                  callerstr);
315848b8605Smrg      return;
316848b8605Smrg   }
317848b8605Smrg
318848b8605Smrg   labelPtr = &syncObj->Label;
319848b8605Smrg
320b8e80941Smrg   set_label(ctx, labelPtr, label, length, callerstr);
321b8e80941Smrg   _mesa_unref_sync_object(ctx, syncObj, 1);
322848b8605Smrg}
323848b8605Smrg
324848b8605Smrgvoid GLAPIENTRY
325848b8605Smrg_mesa_GetObjectPtrLabel(const void *ptr, GLsizei bufSize, GLsizei *length,
326848b8605Smrg                        GLchar *label)
327848b8605Smrg{
328848b8605Smrg   GET_CURRENT_CONTEXT(ctx);
329b8e80941Smrg   struct gl_sync_object *syncObj;
330b8e80941Smrg   const char *callerstr;
331848b8605Smrg   char **labelPtr;
332b8e80941Smrg
333b8e80941Smrg   if (_mesa_is_desktop_gl(ctx))
334b8e80941Smrg      callerstr = "glGetObjectPtrLabel";
335b8e80941Smrg   else
336b8e80941Smrg      callerstr = "glGetObjectPtrLabelKHR";
337848b8605Smrg
338848b8605Smrg   if (bufSize < 0) {
339b8e80941Smrg      _mesa_error(ctx, GL_INVALID_VALUE, "%s(bufSize = %d)", callerstr,
340848b8605Smrg                  bufSize);
341848b8605Smrg      return;
342848b8605Smrg   }
343848b8605Smrg
344b8e80941Smrg   syncObj = _mesa_get_and_ref_sync(ctx, (void*)ptr, true);
345b8e80941Smrg   if (!syncObj) {
346b8e80941Smrg      _mesa_error(ctx, GL_INVALID_VALUE, "%s (not a valid sync object)",
347b8e80941Smrg                  callerstr);
348848b8605Smrg      return;
349848b8605Smrg   }
350848b8605Smrg
351848b8605Smrg   labelPtr = &syncObj->Label;
352848b8605Smrg
353848b8605Smrg   copy_label(*labelPtr, label, length, bufSize);
354b8e80941Smrg   _mesa_unref_sync_object(ctx, syncObj, 1);
355848b8605Smrg}
356