mesa: add GLAPIENTRY to new _context_lost_X functions
[mesa.git] / src / mesa / main / getstring.c
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 "main/dispatch.h" /* for _gloffset_COUNT */
36
37 /**
38 * Return the string for a glGetString(GL_SHADING_LANGUAGE_VERSION) query.
39 */
40 static const GLubyte *
41 shading_language_version(struct gl_context *ctx)
42 {
43 switch (ctx->API) {
44 case API_OPENGL_COMPAT:
45 case API_OPENGL_CORE:
46 switch (ctx->Const.GLSLVersion) {
47 case 120:
48 return (const GLubyte *) "1.20";
49 case 130:
50 return (const GLubyte *) "1.30";
51 case 140:
52 return (const GLubyte *) "1.40";
53 case 150:
54 return (const GLubyte *) "1.50";
55 case 330:
56 return (const GLubyte *) "3.30";
57 case 400:
58 return (const GLubyte *) "4.00";
59 case 410:
60 return (const GLubyte *) "4.10";
61 case 420:
62 return (const GLubyte *) "4.20";
63 case 430:
64 return (const GLubyte *) "4.30";
65 case 440:
66 return (const GLubyte *) "4.40";
67 case 450:
68 return (const GLubyte *) "4.50";
69 default:
70 _mesa_problem(ctx,
71 "Invalid GLSL version in shading_language_version()");
72 return (const GLubyte *) 0;
73 }
74 break;
75
76 case API_OPENGLES2:
77 switch (ctx->Version) {
78 case 20:
79 return (const GLubyte *) "OpenGL ES GLSL ES 1.0.16";
80 case 30:
81 return (const GLubyte *) "OpenGL ES GLSL ES 3.00";
82 case 31:
83 return (const GLubyte *) "OpenGL ES GLSL ES 3.10";
84 default:
85 _mesa_problem(ctx,
86 "Invalid OpenGL ES version in shading_language_version()");
87 return (const GLubyte *) 0;
88 }
89 case API_OPENGLES:
90 /* fall-through */
91
92 default:
93 _mesa_problem(ctx, "Unexpected API value in shading_language_version()");
94 return (const GLubyte *) 0;
95 }
96 }
97
98
99 /**
100 * Query string-valued state. The return value should _not_ be freed by
101 * the caller.
102 *
103 * \param name the state variable to query.
104 *
105 * \sa glGetString().
106 *
107 * Tries to get the string from dd_function_table::GetString, otherwise returns
108 * the hardcoded strings.
109 */
110 const GLubyte * GLAPIENTRY
111 _mesa_GetString( GLenum name )
112 {
113 GET_CURRENT_CONTEXT(ctx);
114 static const char *vendor = "Brian Paul";
115 static const char *renderer = "Mesa";
116
117 if (!ctx)
118 return NULL;
119
120 ASSERT_OUTSIDE_BEGIN_END_WITH_RETVAL(ctx, NULL);
121
122 /* this is a required driver function */
123 assert(ctx->Driver.GetString);
124 {
125 /* Give the driver the chance to handle this query */
126 const GLubyte *str = ctx->Driver.GetString(ctx, name);
127 if (str)
128 return str;
129 }
130
131 switch (name) {
132 case GL_VENDOR:
133 return (const GLubyte *) vendor;
134 case GL_RENDERER:
135 return (const GLubyte *) renderer;
136 case GL_VERSION:
137 return (const GLubyte *) ctx->VersionString;
138 case GL_EXTENSIONS:
139 if (ctx->API == API_OPENGL_CORE) {
140 _mesa_error(ctx, GL_INVALID_ENUM, "glGetString(GL_EXTENSIONS)");
141 return (const GLubyte *) 0;
142 }
143 return (const GLubyte *) ctx->Extensions.String;
144 case GL_SHADING_LANGUAGE_VERSION:
145 if (ctx->API == API_OPENGLES)
146 break;
147 return shading_language_version(ctx);
148 case GL_PROGRAM_ERROR_STRING_ARB:
149 if (ctx->API == API_OPENGL_COMPAT &&
150 (ctx->Extensions.ARB_fragment_program ||
151 ctx->Extensions.ARB_vertex_program)) {
152 return (const GLubyte *) ctx->Program.ErrorString;
153 }
154 break;
155 default:
156 break;
157 }
158
159 _mesa_error( ctx, GL_INVALID_ENUM, "glGetString" );
160 return (const GLubyte *) 0;
161 }
162
163
164 /**
165 * GL3
166 */
167 const GLubyte * GLAPIENTRY
168 _mesa_GetStringi(GLenum name, GLuint index)
169 {
170 GET_CURRENT_CONTEXT(ctx);
171
172 if (!ctx)
173 return NULL;
174
175 ASSERT_OUTSIDE_BEGIN_END_WITH_RETVAL(ctx, NULL);
176
177 switch (name) {
178 case GL_EXTENSIONS:
179 if (index >= _mesa_get_extension_count(ctx)) {
180 _mesa_error(ctx, GL_INVALID_VALUE, "glGetStringi(index=%u)", index);
181 return (const GLubyte *) 0;
182 }
183 return _mesa_get_enabled_extension(ctx, index);
184 default:
185 _mesa_error(ctx, GL_INVALID_ENUM, "glGetStringi");
186 return (const GLubyte *) 0;
187 }
188 }
189
190
191
192 /**
193 * Return pointer-valued state, such as a vertex array pointer.
194 *
195 * \param pname names state to be queried
196 * \param params returns the pointer value
197 *
198 * \sa glGetPointerv().
199 *
200 * Tries to get the specified pointer via dd_function_table::GetPointerv,
201 * otherwise gets the specified pointer from the current context.
202 */
203 void GLAPIENTRY
204 _mesa_GetPointerv( GLenum pname, GLvoid **params )
205 {
206 GET_CURRENT_CONTEXT(ctx);
207 const GLuint clientUnit = ctx->Array.ActiveTexture;
208 const char *callerstr;
209
210 if (_mesa_is_desktop_gl(ctx))
211 callerstr = "glGetPointerv";
212 else
213 callerstr = "glGetPointervKHR";
214
215 if (!params)
216 return;
217
218 if (MESA_VERBOSE & VERBOSE_API)
219 _mesa_debug(ctx, "%s %s\n", callerstr, _mesa_enum_to_string(pname));
220
221 switch (pname) {
222 case GL_VERTEX_ARRAY_POINTER:
223 if (ctx->API != API_OPENGL_COMPAT && ctx->API != API_OPENGLES)
224 goto invalid_pname;
225 *params = (GLvoid *) ctx->Array.VAO->VertexAttrib[VERT_ATTRIB_POS].Ptr;
226 break;
227 case GL_NORMAL_ARRAY_POINTER:
228 if (ctx->API != API_OPENGL_COMPAT && ctx->API != API_OPENGLES)
229 goto invalid_pname;
230 *params = (GLvoid *) ctx->Array.VAO->VertexAttrib[VERT_ATTRIB_NORMAL].Ptr;
231 break;
232 case GL_COLOR_ARRAY_POINTER:
233 if (ctx->API != API_OPENGL_COMPAT && ctx->API != API_OPENGLES)
234 goto invalid_pname;
235 *params = (GLvoid *) ctx->Array.VAO->VertexAttrib[VERT_ATTRIB_COLOR0].Ptr;
236 break;
237 case GL_SECONDARY_COLOR_ARRAY_POINTER_EXT:
238 if (ctx->API != API_OPENGL_COMPAT)
239 goto invalid_pname;
240 *params = (GLvoid *) ctx->Array.VAO->VertexAttrib[VERT_ATTRIB_COLOR1].Ptr;
241 break;
242 case GL_FOG_COORDINATE_ARRAY_POINTER_EXT:
243 if (ctx->API != API_OPENGL_COMPAT)
244 goto invalid_pname;
245 *params = (GLvoid *) ctx->Array.VAO->VertexAttrib[VERT_ATTRIB_FOG].Ptr;
246 break;
247 case GL_INDEX_ARRAY_POINTER:
248 if (ctx->API != API_OPENGL_COMPAT)
249 goto invalid_pname;
250 *params = (GLvoid *) ctx->Array.VAO->VertexAttrib[VERT_ATTRIB_COLOR_INDEX].Ptr;
251 break;
252 case GL_TEXTURE_COORD_ARRAY_POINTER:
253 if (ctx->API != API_OPENGL_COMPAT && ctx->API != API_OPENGLES)
254 goto invalid_pname;
255 *params = (GLvoid *) ctx->Array.VAO->VertexAttrib[VERT_ATTRIB_TEX(clientUnit)].Ptr;
256 break;
257 case GL_EDGE_FLAG_ARRAY_POINTER:
258 if (ctx->API != API_OPENGL_COMPAT)
259 goto invalid_pname;
260 *params = (GLvoid *) ctx->Array.VAO->VertexAttrib[VERT_ATTRIB_EDGEFLAG].Ptr;
261 break;
262 case GL_FEEDBACK_BUFFER_POINTER:
263 if (ctx->API != API_OPENGL_COMPAT)
264 goto invalid_pname;
265 *params = ctx->Feedback.Buffer;
266 break;
267 case GL_SELECTION_BUFFER_POINTER:
268 if (ctx->API != API_OPENGL_COMPAT)
269 goto invalid_pname;
270 *params = ctx->Select.Buffer;
271 break;
272 case GL_POINT_SIZE_ARRAY_POINTER_OES:
273 if (ctx->API != API_OPENGLES)
274 goto invalid_pname;
275 *params = (GLvoid *) ctx->Array.VAO->VertexAttrib[VERT_ATTRIB_POINT_SIZE].Ptr;
276 break;
277 case GL_DEBUG_CALLBACK_FUNCTION_ARB:
278 case GL_DEBUG_CALLBACK_USER_PARAM_ARB:
279 *params = _mesa_get_debug_state_ptr(ctx, pname);
280 break;
281 default:
282 goto invalid_pname;
283 }
284
285 return;
286
287 invalid_pname:
288 _mesa_error( ctx, GL_INVALID_ENUM, "%s", callerstr);
289 return;
290 }
291
292
293 /**
294 * Returns the current GL error code, or GL_NO_ERROR.
295 * \return current error code
296 *
297 * Returns __struct gl_contextRec::ErrorValue.
298 */
299 GLenum GLAPIENTRY
300 _mesa_GetError( void )
301 {
302 GET_CURRENT_CONTEXT(ctx);
303 GLenum e = ctx->ErrorValue;
304 ASSERT_OUTSIDE_BEGIN_END_WITH_RETVAL(ctx, 0);
305
306 if (MESA_VERBOSE & VERBOSE_API)
307 _mesa_debug(ctx, "glGetError <-- %s\n", _mesa_enum_to_string(e));
308
309 ctx->ErrorValue = (GLenum) GL_NO_ERROR;
310 ctx->ErrorDebugCount = 0;
311 return e;
312 }
313
314 static void GLAPIENTRY
315 _context_lost_GetSynciv(GLsync sync, GLenum pname, GLsizei bufSize, GLsizei *length,
316 GLint *values)
317 {
318 GET_CURRENT_CONTEXT(ctx);
319 if (ctx)
320 _mesa_error(ctx, GL_CONTEXT_LOST, "GetSynciv(invalid call)");
321
322 if (pname == GL_SYNC_STATUS && bufSize >= 1)
323 *values = GL_SIGNALED;
324 }
325
326 static void GLAPIENTRY
327 _context_lost_GetQueryObjectuiv(GLuint id, GLenum pname, GLuint *params)
328 {
329 GET_CURRENT_CONTEXT(ctx);
330 if (ctx)
331 _mesa_error(ctx, GL_CONTEXT_LOST, "GetQueryObjectuiv(context lost)");
332
333 if (pname == GL_QUERY_RESULT_AVAILABLE)
334 *params = GL_TRUE;
335 }
336
337 static int
338 context_lost_nop_handler(void)
339 {
340 GET_CURRENT_CONTEXT(ctx);
341 if (ctx)
342 _mesa_error(ctx, GL_CONTEXT_LOST, "context lost");
343
344 return 0;
345 }
346
347 void
348 _mesa_set_context_lost_dispatch(struct gl_context *ctx)
349 {
350 if (ctx->ContextLost == NULL) {
351 int numEntries = MAX2(_glapi_get_dispatch_table_size(), _gloffset_COUNT);
352
353 ctx->ContextLost = malloc(numEntries * sizeof(_glapi_proc));
354 if (!ctx->ContextLost)
355 return;
356
357 _glapi_proc *entry = (_glapi_proc *) ctx->ContextLost;
358 unsigned i;
359 for (i = 0; i < numEntries; i++)
360 entry[i] = (_glapi_proc) context_lost_nop_handler;
361
362 /* The ARB_robustness specification says:
363 *
364 * "* GetError and GetGraphicsResetStatus behave normally following a
365 * graphics reset, so that the application can determine a reset
366 * has occurred, and when it is safe to destroy and recreate the
367 * context.
368 *
369 * * Any commands which might cause a polling application to block
370 * indefinitely will generate a CONTEXT_LOST error, but will also
371 * return a value indicating completion to the application. Such
372 * commands include:
373 *
374 * + GetSynciv with <pname> SYNC_STATUS ignores the other
375 * parameters and returns SIGNALED in <values>.
376 *
377 * + GetQueryObjectuiv with <pname> QUERY_RESULT_AVAILABLE
378 * ignores the other parameters and returns TRUE in <params>."
379 */
380 SET_GetError(ctx->ContextLost, _mesa_GetError);
381 SET_GetGraphicsResetStatusARB(ctx->ContextLost, _mesa_GetGraphicsResetStatusARB);
382 SET_GetSynciv(ctx->ContextLost, _context_lost_GetSynciv);
383 SET_GetQueryObjectuiv(ctx->ContextLost, _context_lost_GetQueryObjectuiv);
384 }
385
386 ctx->CurrentDispatch = ctx->ContextLost;
387 _glapi_set_dispatch(ctx->CurrentDispatch);
388 }
389
390 /**
391 * Returns an error code specified by GL_ARB_robustness, or GL_NO_ERROR.
392 * \return current context status
393 */
394 GLenum GLAPIENTRY
395 _mesa_GetGraphicsResetStatusARB( void )
396 {
397 GET_CURRENT_CONTEXT(ctx);
398 GLenum status = GL_NO_ERROR;
399
400 /* The ARB_robustness specification says:
401 *
402 * "If the reset notification behavior is NO_RESET_NOTIFICATION_ARB,
403 * then the implementation will never deliver notification of reset
404 * events, and GetGraphicsResetStatusARB will always return NO_ERROR."
405 */
406 if (ctx->Const.ResetStrategy == GL_NO_RESET_NOTIFICATION_ARB) {
407 if (MESA_VERBOSE & VERBOSE_API)
408 _mesa_debug(ctx,
409 "glGetGraphicsResetStatusARB always returns GL_NO_ERROR "
410 "because reset notifictation was not requested at context "
411 "creation.\n");
412
413 return GL_NO_ERROR;
414 }
415
416 if (ctx->Driver.GetGraphicsResetStatus) {
417 /* Query the reset status of this context from the driver core.
418 */
419 status = ctx->Driver.GetGraphicsResetStatus(ctx);
420
421 mtx_lock(&ctx->Shared->Mutex);
422
423 /* If this context has not been affected by a GPU reset, check to see if
424 * some other context in the share group has been affected by a reset.
425 * If another context saw a reset but this context did not, assume that
426 * this context was not guilty.
427 */
428 if (status != GL_NO_ERROR) {
429 ctx->Shared->ShareGroupReset = true;
430 } else if (ctx->Shared->ShareGroupReset && !ctx->ShareGroupReset) {
431 status = GL_INNOCENT_CONTEXT_RESET_ARB;
432 }
433
434 ctx->ShareGroupReset = ctx->Shared->ShareGroupReset;
435 mtx_unlock(&ctx->Shared->Mutex);
436 }
437
438 if (status != GL_NO_ERROR)
439 _mesa_set_context_lost_dispatch(ctx);
440
441 if (!ctx->Driver.GetGraphicsResetStatus && (MESA_VERBOSE & VERBOSE_API))
442 _mesa_debug(ctx,
443 "glGetGraphicsResetStatusARB always returns GL_NO_ERROR "
444 "because the driver doesn't track reset status.\n");
445
446 return status;
447 }