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 "debug_output.h"
30#include "get.h"
31#include "enums.h"
32#include "extensions.h"
33#include "mtypes.h"
34#include "macros.h"
35#include "version.h"
36#include "spirv_extensions.h"
37
38/**
39 * Return the string for a glGetString(GL_SHADING_LANGUAGE_VERSION) query.
40 */
41static const GLubyte *
42shading_language_version(struct gl_context *ctx)
43{
44   switch (ctx->API) {
45   case API_OPENGL_COMPAT:
46   case API_OPENGL_CORE:
47      switch (ctx->Const.GLSLVersion) {
48      case 120:
49         return (const GLubyte *) "1.20";
50      case 130:
51         return (const GLubyte *) "1.30";
52      case 140:
53         return (const GLubyte *) "1.40";
54      case 150:
55         return (const GLubyte *) "1.50";
56      case 330:
57         return (const GLubyte *) "3.30";
58      case 400:
59         return (const GLubyte *) "4.00";
60      case 410:
61         return (const GLubyte *) "4.10";
62      case 420:
63         return (const GLubyte *) "4.20";
64      case 430:
65         return (const GLubyte *) "4.30";
66      case 440:
67         return (const GLubyte *) "4.40";
68      case 450:
69         return (const GLubyte *) "4.50";
70      case 460:
71         return (const GLubyte *) "4.60";
72      default:
73         _mesa_problem(ctx,
74                       "Invalid GLSL version in shading_language_version()");
75         return (const GLubyte *) 0;
76      }
77      break;
78
79   case API_OPENGLES2:
80      switch (ctx->Version) {
81      case 20:
82         return (const GLubyte *) "OpenGL ES GLSL ES 1.0.16";
83      case 30:
84         return (const GLubyte *) "OpenGL ES GLSL ES 3.00";
85      case 31:
86         return (const GLubyte *) "OpenGL ES GLSL ES 3.10";
87      case 32:
88         return (const GLubyte *) "OpenGL ES GLSL ES 3.20";
89      default:
90         _mesa_problem(ctx,
91                       "Invalid OpenGL ES version in shading_language_version()");
92         return (const GLubyte *) 0;
93      }
94   case API_OPENGLES:
95      FALLTHROUGH;
96
97   default:
98      _mesa_problem(ctx, "Unexpected API value in shading_language_version()");
99      return (const GLubyte *) 0;
100   }
101}
102
103
104/**
105 * Query string-valued state.  The return value should _not_ be freed by
106 * the caller.
107 *
108 * \param name  the state variable to query.
109 *
110 * \sa glGetString().
111 *
112 * Tries to get the string from dd_function_table::GetString, otherwise returns
113 * the hardcoded strings.
114 */
115const GLubyte * GLAPIENTRY
116_mesa_GetString( GLenum name )
117{
118   GET_CURRENT_CONTEXT(ctx);
119   static const char *vendor = "Brian Paul";
120   static const char *renderer = "Mesa";
121
122   if (!ctx)
123      return NULL;
124
125   ASSERT_OUTSIDE_BEGIN_END_WITH_RETVAL(ctx, NULL);
126
127   if (ctx->Const.VendorOverride && name == GL_VENDOR) {
128      return (const GLubyte *) ctx->Const.VendorOverride;
129   }
130
131   if (ctx->Const.RendererOverride && name == GL_RENDERER) {
132      return (const GLubyte *) ctx->Const.RendererOverride;
133   }
134
135   /* this is a required driver function */
136   assert(ctx->Driver.GetString);
137   {
138      /* Give the driver the chance to handle this query */
139      const GLubyte *str = ctx->Driver.GetString(ctx, name);
140      if (str)
141         return str;
142   }
143
144   switch (name) {
145      case GL_VENDOR:
146         return (const GLubyte *) vendor;
147      case GL_RENDERER:
148         return (const GLubyte *) renderer;
149      case GL_VERSION:
150         return (const GLubyte *) ctx->VersionString;
151      case GL_EXTENSIONS:
152         if (ctx->API == API_OPENGL_CORE) {
153            _mesa_error(ctx, GL_INVALID_ENUM, "glGetString(GL_EXTENSIONS)");
154            return (const GLubyte *) 0;
155         }
156         if (!ctx->Extensions.String)
157            ctx->Extensions.String = _mesa_make_extension_string(ctx);
158         return (const GLubyte *) ctx->Extensions.String;
159      case GL_SHADING_LANGUAGE_VERSION:
160         if (ctx->API == API_OPENGLES)
161            break;
162	 return shading_language_version(ctx);
163      case GL_PROGRAM_ERROR_STRING_ARB:
164         if (ctx->API == API_OPENGL_COMPAT &&
165             (ctx->Extensions.ARB_fragment_program ||
166              ctx->Extensions.ARB_vertex_program)) {
167            return (const GLubyte *) ctx->Program.ErrorString;
168         }
169         break;
170      default:
171         break;
172   }
173
174   _mesa_error( ctx, GL_INVALID_ENUM, "glGetString" );
175   return (const GLubyte *) 0;
176}
177
178
179/**
180 * GL3
181 */
182const GLubyte * GLAPIENTRY
183_mesa_GetStringi(GLenum name, GLuint index)
184{
185   GET_CURRENT_CONTEXT(ctx);
186
187   if (!ctx)
188      return NULL;
189
190   ASSERT_OUTSIDE_BEGIN_END_WITH_RETVAL(ctx, NULL);
191
192   switch (name) {
193   case GL_EXTENSIONS:
194      if (index >= _mesa_get_extension_count(ctx)) {
195         _mesa_error(ctx, GL_INVALID_VALUE, "glGetStringi(index=%u)", index);
196         return (const GLubyte *) 0;
197      }
198      return _mesa_get_enabled_extension(ctx, index);
199   case GL_SHADING_LANGUAGE_VERSION:
200      {
201         char *version;
202         int num;
203         if (!_mesa_is_desktop_gl(ctx) || ctx->Version < 43) {
204            _mesa_error(ctx, GL_INVALID_ENUM,
205                        "glGetStringi(GL_SHADING_LANGUAGE_VERSION): "
206                        "supported only in GL4.3 and later");
207            return (const GLubyte *) 0;
208         }
209         num = _mesa_get_shading_language_version(ctx, index, &version);
210         if (index >= num) {
211            _mesa_error(ctx, GL_INVALID_VALUE,
212                        "glGetStringi(GL_SHADING_LANGUAGE_VERSION, index=%d)",
213                        index);
214            return (const GLubyte *) 0;
215         }
216         return (const GLubyte *) version;
217      }
218   case GL_SPIR_V_EXTENSIONS:
219      if (!ctx->Extensions.ARB_spirv_extensions) {
220         _mesa_error(ctx, GL_INVALID_ENUM, "glGetStringi");
221         return (const GLubyte *) 0;
222      }
223
224      if (index >= _mesa_get_spirv_extension_count(ctx)) {
225         _mesa_error(ctx, GL_INVALID_VALUE, "glGetStringi(index=%u)", index);
226         return (const GLubyte *) 0;
227      }
228      return _mesa_get_enabled_spirv_extension(ctx, index);
229
230   default:
231      _mesa_error(ctx, GL_INVALID_ENUM, "glGetStringi");
232      return (const GLubyte *) 0;
233   }
234}
235
236
237void
238_get_vao_pointerv(GLenum pname, struct gl_vertex_array_object* vao,
239                  GLvoid **params, const char* callerstr )
240{
241   GET_CURRENT_CONTEXT(ctx);
242   const GLuint clientUnit = ctx->Array.ActiveTexture;
243
244   if (!params)
245      return;
246
247   if (MESA_VERBOSE & VERBOSE_API)
248      _mesa_debug(ctx, "%s %s\n", callerstr, _mesa_enum_to_string(pname));
249
250   switch (pname) {
251      case GL_VERTEX_ARRAY_POINTER:
252         if (ctx->API != API_OPENGL_COMPAT && ctx->API != API_OPENGLES)
253            goto invalid_pname;
254         *params = (GLvoid *) vao->VertexAttrib[VERT_ATTRIB_POS].Ptr;
255         break;
256      case GL_NORMAL_ARRAY_POINTER:
257         if (ctx->API != API_OPENGL_COMPAT && ctx->API != API_OPENGLES)
258            goto invalid_pname;
259         *params = (GLvoid *) vao->VertexAttrib[VERT_ATTRIB_NORMAL].Ptr;
260         break;
261      case GL_COLOR_ARRAY_POINTER:
262         if (ctx->API != API_OPENGL_COMPAT && ctx->API != API_OPENGLES)
263            goto invalid_pname;
264         *params = (GLvoid *) vao->VertexAttrib[VERT_ATTRIB_COLOR0].Ptr;
265         break;
266      case GL_SECONDARY_COLOR_ARRAY_POINTER_EXT:
267         if (ctx->API != API_OPENGL_COMPAT)
268            goto invalid_pname;
269         *params = (GLvoid *) vao->VertexAttrib[VERT_ATTRIB_COLOR1].Ptr;
270         break;
271      case GL_FOG_COORDINATE_ARRAY_POINTER_EXT:
272         if (ctx->API != API_OPENGL_COMPAT)
273            goto invalid_pname;
274         *params = (GLvoid *) vao->VertexAttrib[VERT_ATTRIB_FOG].Ptr;
275         break;
276      case GL_INDEX_ARRAY_POINTER:
277         if (ctx->API != API_OPENGL_COMPAT)
278            goto invalid_pname;
279         *params = (GLvoid *) vao->VertexAttrib[VERT_ATTRIB_COLOR_INDEX].Ptr;
280         break;
281      case GL_TEXTURE_COORD_ARRAY_POINTER:
282         if (ctx->API != API_OPENGL_COMPAT && ctx->API != API_OPENGLES)
283            goto invalid_pname;
284         *params = (GLvoid *) vao->VertexAttrib[VERT_ATTRIB_TEX(clientUnit)].Ptr;
285         break;
286      case GL_EDGE_FLAG_ARRAY_POINTER:
287         if (ctx->API != API_OPENGL_COMPAT)
288            goto invalid_pname;
289         *params = (GLvoid *) vao->VertexAttrib[VERT_ATTRIB_EDGEFLAG].Ptr;
290         break;
291      case GL_FEEDBACK_BUFFER_POINTER:
292         if (ctx->API != API_OPENGL_COMPAT)
293            goto invalid_pname;
294         *params = ctx->Feedback.Buffer;
295         break;
296      case GL_SELECTION_BUFFER_POINTER:
297         if (ctx->API != API_OPENGL_COMPAT)
298            goto invalid_pname;
299         *params = ctx->Select.Buffer;
300         break;
301      case GL_POINT_SIZE_ARRAY_POINTER_OES:
302         if (ctx->API != API_OPENGLES)
303            goto invalid_pname;
304         *params = (GLvoid *) vao->VertexAttrib[VERT_ATTRIB_POINT_SIZE].Ptr;
305         break;
306      case GL_DEBUG_CALLBACK_FUNCTION_ARB:
307      case GL_DEBUG_CALLBACK_USER_PARAM_ARB:
308         *params = _mesa_get_debug_state_ptr(ctx, pname);
309         break;
310      default:
311         goto invalid_pname;
312   }
313
314   return;
315
316invalid_pname:
317   _mesa_error( ctx, GL_INVALID_ENUM, "%s", callerstr);
318   return;
319}
320
321
322/**
323 * Return pointer-valued state, such as a vertex array pointer.
324 *
325 * \param pname  names state to be queried
326 * \param params  returns the pointer value
327 *
328 * \sa glGetPointerv().
329 *
330 * Tries to get the specified pointer via dd_function_table::GetPointerv,
331 * otherwise gets the specified pointer from the current context.
332 */
333void GLAPIENTRY
334_mesa_GetPointerv( GLenum pname, GLvoid **params )
335{
336   GET_CURRENT_CONTEXT(ctx);
337   const char *callerstr;
338
339   if (_mesa_is_desktop_gl(ctx))
340      callerstr = "glGetPointerv";
341   else
342      callerstr = "glGetPointervKHR";
343
344   if (!params)
345      return;
346
347   _get_vao_pointerv(pname, ctx->Array.VAO, params, callerstr);
348}
349
350
351void GLAPIENTRY
352_mesa_GetPointerIndexedvEXT( GLenum pname, GLuint index, GLvoid **params )
353{
354   GET_CURRENT_CONTEXT(ctx);
355
356   if (!params)
357      return;
358
359   if (MESA_VERBOSE & VERBOSE_API)
360      _mesa_debug(ctx, "%s %s\n", "glGetPointerIndexedvEXT", _mesa_enum_to_string(pname));
361
362   switch (pname) {
363      case GL_TEXTURE_COORD_ARRAY_POINTER:
364         *params = (GLvoid *) ctx->Array.VAO->VertexAttrib[VERT_ATTRIB_TEX(index)].Ptr;
365         break;
366      default:
367         goto invalid_pname;
368   }
369
370   return;
371
372invalid_pname:
373   _mesa_error( ctx, GL_INVALID_ENUM, "glGetPointerIndexedvEXT");
374   return;
375}
376
377/**
378 * Returns the current GL error code, or GL_NO_ERROR.
379 * \return current error code
380 *
381 * Returns __struct gl_contextRec::ErrorValue.
382 */
383GLenum GLAPIENTRY
384_mesa_GetError( void )
385{
386   GET_CURRENT_CONTEXT(ctx);
387   GLenum e = ctx->ErrorValue;
388   ASSERT_OUTSIDE_BEGIN_END_WITH_RETVAL(ctx, 0);
389
390   /* From Issue (3) of the KHR_no_error spec:
391    *
392    *    "Should glGetError() always return NO_ERROR or have undefined
393    *    results?
394    *
395    *    RESOLVED: It should for all errors except OUT_OF_MEMORY."
396    */
397   if (_mesa_is_no_error_enabled(ctx) && e != GL_OUT_OF_MEMORY) {
398      e = GL_NO_ERROR;
399   }
400
401   if (MESA_VERBOSE & VERBOSE_API)
402      _mesa_debug(ctx, "glGetError <-- %s\n", _mesa_enum_to_string(e));
403
404   ctx->ErrorValue = (GLenum) GL_NO_ERROR;
405   ctx->ErrorDebugCount = 0;
406   return e;
407}
408