getstring.c revision 848b8605
1/*
2 * Mesa 3-D graphics library
3 *
4 * Copyright (C) 1999-2008  Brian Paul   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 <stdbool.h>
27#include "glheader.h"
28#include "context.h"
29#include "get.h"
30#include "enums.h"
31#include "extensions.h"
32#include "mtypes.h"
33
34
35/**
36 * Return the string for a glGetString(GL_SHADING_LANGUAGE_VERSION) query.
37 */
38static const GLubyte *
39shading_language_version(struct gl_context *ctx)
40{
41   switch (ctx->API) {
42   case API_OPENGL_COMPAT:
43   case API_OPENGL_CORE:
44      switch (ctx->Const.GLSLVersion) {
45      case 120:
46         return (const GLubyte *) "1.20";
47      case 130:
48         return (const GLubyte *) "1.30";
49      case 140:
50         return (const GLubyte *) "1.40";
51      case 150:
52         return (const GLubyte *) "1.50";
53      case 330:
54         return (const GLubyte *) "3.30";
55      case 400:
56         return (const GLubyte *) "4.00";
57      case 410:
58         return (const GLubyte *) "4.10";
59      case 420:
60         return (const GLubyte *) "4.20";
61      default:
62         _mesa_problem(ctx,
63                       "Invalid GLSL version in shading_language_version()");
64         return (const GLubyte *) 0;
65      }
66      break;
67
68   case API_OPENGLES2:
69      return (ctx->Version < 30)
70         ? (const GLubyte *) "OpenGL ES GLSL ES 1.0.16"
71         : (const GLubyte *) "OpenGL ES GLSL ES 3.0";
72
73   case API_OPENGLES:
74      /* fall-through */
75
76   default:
77      _mesa_problem(ctx, "Unexpected API value in shading_language_version()");
78      return (const GLubyte *) 0;
79   }
80}
81
82
83/**
84 * Query string-valued state.  The return value should _not_ be freed by
85 * the caller.
86 *
87 * \param name  the state variable to query.
88 *
89 * \sa glGetString().
90 *
91 * Tries to get the string from dd_function_table::GetString, otherwise returns
92 * the hardcoded strings.
93 */
94const GLubyte * GLAPIENTRY
95_mesa_GetString( GLenum name )
96{
97   GET_CURRENT_CONTEXT(ctx);
98   static const char *vendor = "Brian Paul";
99   static const char *renderer = "Mesa";
100
101   if (!ctx)
102      return NULL;
103
104   ASSERT_OUTSIDE_BEGIN_END_WITH_RETVAL(ctx, NULL);
105
106   /* this is a required driver function */
107   assert(ctx->Driver.GetString);
108   {
109      /* Give the driver the chance to handle this query */
110      const GLubyte *str = (*ctx->Driver.GetString)(ctx, name);
111      if (str)
112         return str;
113   }
114
115   switch (name) {
116      case GL_VENDOR:
117         return (const GLubyte *) vendor;
118      case GL_RENDERER:
119         return (const GLubyte *) renderer;
120      case GL_VERSION:
121         return (const GLubyte *) ctx->VersionString;
122      case GL_EXTENSIONS:
123         if (ctx->API == API_OPENGL_CORE) {
124            _mesa_error(ctx, GL_INVALID_ENUM, "glGetString(GL_EXTENSIONS)");
125            return (const GLubyte *) 0;
126         }
127         return (const GLubyte *) ctx->Extensions.String;
128      case GL_SHADING_LANGUAGE_VERSION:
129         if (ctx->API == API_OPENGLES)
130            break;
131	 return shading_language_version(ctx);
132      case GL_PROGRAM_ERROR_STRING_ARB:
133         if (ctx->API == API_OPENGL_COMPAT &&
134             (ctx->Extensions.ARB_fragment_program ||
135              ctx->Extensions.ARB_vertex_program)) {
136            return (const GLubyte *) ctx->Program.ErrorString;
137         }
138         break;
139      default:
140         break;
141   }
142
143   _mesa_error( ctx, GL_INVALID_ENUM, "glGetString" );
144   return (const GLubyte *) 0;
145}
146
147
148/**
149 * GL3
150 */
151const GLubyte * GLAPIENTRY
152_mesa_GetStringi(GLenum name, GLuint index)
153{
154   GET_CURRENT_CONTEXT(ctx);
155
156   if (!ctx)
157      return NULL;
158
159   ASSERT_OUTSIDE_BEGIN_END_WITH_RETVAL(ctx, NULL);
160
161   switch (name) {
162   case GL_EXTENSIONS:
163      if (index >= _mesa_get_extension_count(ctx)) {
164         _mesa_error(ctx, GL_INVALID_VALUE, "glGetStringi(index=%u)", index);
165         return (const GLubyte *) 0;
166      }
167      return _mesa_get_enabled_extension(ctx, index);
168   default:
169      _mesa_error(ctx, GL_INVALID_ENUM, "glGetStringi");
170      return (const GLubyte *) 0;
171   }
172}
173
174
175
176/**
177 * Return pointer-valued state, such as a vertex array pointer.
178 *
179 * \param pname  names state to be queried
180 * \param params  returns the pointer value
181 *
182 * \sa glGetPointerv().
183 *
184 * Tries to get the specified pointer via dd_function_table::GetPointerv,
185 * otherwise gets the specified pointer from the current context.
186 */
187void GLAPIENTRY
188_mesa_GetPointerv( GLenum pname, GLvoid **params )
189{
190   GET_CURRENT_CONTEXT(ctx);
191   const GLuint clientUnit = ctx->Array.ActiveTexture;
192
193   if (!params)
194      return;
195
196   if (MESA_VERBOSE & VERBOSE_API)
197      _mesa_debug(ctx, "glGetPointerv %s\n", _mesa_lookup_enum_by_nr(pname));
198
199   switch (pname) {
200      case GL_VERTEX_ARRAY_POINTER:
201         if (ctx->API != API_OPENGL_COMPAT && ctx->API != API_OPENGLES)
202            goto invalid_pname;
203         *params = (GLvoid *) ctx->Array.VAO->VertexAttrib[VERT_ATTRIB_POS].Ptr;
204         break;
205      case GL_NORMAL_ARRAY_POINTER:
206         if (ctx->API != API_OPENGL_COMPAT && ctx->API != API_OPENGLES)
207            goto invalid_pname;
208         *params = (GLvoid *) ctx->Array.VAO->VertexAttrib[VERT_ATTRIB_NORMAL].Ptr;
209         break;
210      case GL_COLOR_ARRAY_POINTER:
211         if (ctx->API != API_OPENGL_COMPAT && ctx->API != API_OPENGLES)
212            goto invalid_pname;
213         *params = (GLvoid *) ctx->Array.VAO->VertexAttrib[VERT_ATTRIB_COLOR0].Ptr;
214         break;
215      case GL_SECONDARY_COLOR_ARRAY_POINTER_EXT:
216         if (ctx->API != API_OPENGL_COMPAT)
217            goto invalid_pname;
218         *params = (GLvoid *) ctx->Array.VAO->VertexAttrib[VERT_ATTRIB_COLOR1].Ptr;
219         break;
220      case GL_FOG_COORDINATE_ARRAY_POINTER_EXT:
221         if (ctx->API != API_OPENGL_COMPAT)
222            goto invalid_pname;
223         *params = (GLvoid *) ctx->Array.VAO->VertexAttrib[VERT_ATTRIB_FOG].Ptr;
224         break;
225      case GL_INDEX_ARRAY_POINTER:
226         if (ctx->API != API_OPENGL_COMPAT)
227            goto invalid_pname;
228         *params = (GLvoid *) ctx->Array.VAO->VertexAttrib[VERT_ATTRIB_COLOR_INDEX].Ptr;
229         break;
230      case GL_TEXTURE_COORD_ARRAY_POINTER:
231         if (ctx->API != API_OPENGL_COMPAT && ctx->API != API_OPENGLES)
232            goto invalid_pname;
233         *params = (GLvoid *) ctx->Array.VAO->VertexAttrib[VERT_ATTRIB_TEX(clientUnit)].Ptr;
234         break;
235      case GL_EDGE_FLAG_ARRAY_POINTER:
236         if (ctx->API != API_OPENGL_COMPAT)
237            goto invalid_pname;
238         *params = (GLvoid *) ctx->Array.VAO->VertexAttrib[VERT_ATTRIB_EDGEFLAG].Ptr;
239         break;
240      case GL_FEEDBACK_BUFFER_POINTER:
241         if (ctx->API != API_OPENGL_COMPAT)
242            goto invalid_pname;
243         *params = ctx->Feedback.Buffer;
244         break;
245      case GL_SELECTION_BUFFER_POINTER:
246         if (ctx->API != API_OPENGL_COMPAT)
247            goto invalid_pname;
248         *params = ctx->Select.Buffer;
249         break;
250      case GL_POINT_SIZE_ARRAY_POINTER_OES:
251         if (ctx->API != API_OPENGLES)
252            goto invalid_pname;
253         *params = (GLvoid *) ctx->Array.VAO->VertexAttrib[VERT_ATTRIB_POINT_SIZE].Ptr;
254         break;
255      case GL_DEBUG_CALLBACK_FUNCTION_ARB:
256      case GL_DEBUG_CALLBACK_USER_PARAM_ARB:
257         if (!_mesa_is_desktop_gl(ctx))
258            goto invalid_pname;
259         else
260            *params = _mesa_get_debug_state_ptr(ctx, pname);
261         break;
262      default:
263         goto invalid_pname;
264   }
265
266   return;
267
268invalid_pname:
269   _mesa_error( ctx, GL_INVALID_ENUM, "glGetPointerv" );
270   return;
271}
272
273
274/**
275 * Returns the current GL error code, or GL_NO_ERROR.
276 * \return current error code
277 *
278 * Returns __struct gl_contextRec::ErrorValue.
279 */
280GLenum GLAPIENTRY
281_mesa_GetError( void )
282{
283   GET_CURRENT_CONTEXT(ctx);
284   GLenum e = ctx->ErrorValue;
285   ASSERT_OUTSIDE_BEGIN_END_WITH_RETVAL(ctx, 0);
286
287   if (MESA_VERBOSE & VERBOSE_API)
288      _mesa_debug(ctx, "glGetError <-- %s\n", _mesa_lookup_enum_by_nr(e));
289
290   ctx->ErrorValue = (GLenum) GL_NO_ERROR;
291   ctx->ErrorDebugCount = 0;
292   return e;
293}
294
295/**
296 * Returns an error code specified by GL_ARB_robustness, or GL_NO_ERROR.
297 * \return current context status
298 */
299GLenum GLAPIENTRY
300_mesa_GetGraphicsResetStatusARB( void )
301{
302   GET_CURRENT_CONTEXT(ctx);
303   GLenum status = GL_NO_ERROR;
304
305   /* The ARB_robustness specification says:
306    *
307    *     "If the reset notification behavior is NO_RESET_NOTIFICATION_ARB,
308    *     then the implementation will never deliver notification of reset
309    *     events, and GetGraphicsResetStatusARB will always return NO_ERROR."
310    */
311   if (ctx->Const.ResetStrategy == GL_NO_RESET_NOTIFICATION_ARB) {
312      if (MESA_VERBOSE & VERBOSE_API)
313         _mesa_debug(ctx,
314                     "glGetGraphicsResetStatusARB always returns GL_NO_ERROR "
315                     "because reset notifictation was not requested at context "
316                     "creation.\n");
317
318      return GL_NO_ERROR;
319   }
320
321   if (ctx->Driver.GetGraphicsResetStatus) {
322      /* Query the reset status of this context from the driver core.
323       */
324      status = ctx->Driver.GetGraphicsResetStatus(ctx);
325
326      mtx_lock(&ctx->Shared->Mutex);
327
328      /* If this context has not been affected by a GPU reset, check to see if
329       * some other context in the share group has been affected by a reset.
330       * If another context saw a reset but this context did not, assume that
331       * this context was not guilty.
332       */
333      if (status != GL_NO_ERROR) {
334         ctx->Shared->ShareGroupReset = true;
335      } else if (ctx->Shared->ShareGroupReset && !ctx->ShareGroupReset) {
336         status = GL_INNOCENT_CONTEXT_RESET_ARB;
337      }
338
339      ctx->ShareGroupReset = ctx->Shared->ShareGroupReset;
340      mtx_unlock(&ctx->Shared->Mutex);
341   }
342
343   if (!ctx->Driver.GetGraphicsResetStatus && (MESA_VERBOSE & VERBOSE_API))
344      _mesa_debug(ctx,
345                  "glGetGraphicsResetStatusARB always returns GL_NO_ERROR "
346                  "because the driver doesn't track reset status.\n");
347
348   return status;
349}
350