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  */
41 static const GLubyte *
shading_language_version(struct gl_context * ctx)42 shading_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  */
115 const GLubyte * GLAPIENTRY
_mesa_GetString(GLenum name)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  */
182 const GLubyte * GLAPIENTRY
_mesa_GetStringi(GLenum name,GLuint index)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 
237 void
_get_vao_pointerv(GLenum pname,struct gl_vertex_array_object * vao,GLvoid ** params,const char * callerstr)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 
316 invalid_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  */
333 void GLAPIENTRY
_mesa_GetPointerv(GLenum pname,GLvoid ** params)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 
351 void GLAPIENTRY
_mesa_GetPointerIndexedvEXT(GLenum pname,GLuint index,GLvoid ** params)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 
372 invalid_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  */
383 GLenum GLAPIENTRY
_mesa_GetError(void)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