getstring.c 13.8 KB
Newer Older
1 2 3
/*
 * Mesa 3-D graphics library
 *
Brian Paul's avatar
Brian Paul committed
4
 * Copyright (C) 1999-2008  Brian Paul   All Rights Reserved.
5 6 7 8 9 10 11 12 13 14 15 16 17 18
 *
 * Permission is hereby granted, free of charge, to any person obtaining a
 * copy of this software and associated documentation files (the "Software"),
 * to deal in the Software without restriction, including without limitation
 * the rights to use, copy, modify, merge, publish, distribute, sublicense,
 * and/or sell copies of the Software, and to permit persons to whom the
 * Software is furnished to do so, subject to the following conditions:
 *
 * The above copyright notice and this permission notice shall be included
 * in all copies or substantial portions of the Software.
 *
 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
 * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL
19 20 21 22
 * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR
 * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
 * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
 * OTHER DEALINGS IN THE SOFTWARE.
23 24 25
 */


26
#include <stdbool.h>
27 28
#include "glheader.h"
#include "context.h"
29
#include "debug_output.h"
30 31 32
#include "get.h"
#include "enums.h"
#include "extensions.h"
33
#include "mtypes.h"
34 35
#include "macros.h"
#include "main/dispatch.h" /* for _gloffset_COUNT */
36 37 38 39

/**
 * Return the string for a glGetString(GL_SHADING_LANGUAGE_VERSION) query.
 */
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 47 48 49 50
      switch (ctx->Const.GLSLVersion) {
      case 120:
         return (const GLubyte *) "1.20";
      case 130:
         return (const GLubyte *) "1.30";
51 52
      case 140:
         return (const GLubyte *) "1.40";
53 54 55 56 57 58 59 60 61 62
      case 150:
         return (const GLubyte *) "1.50";
      case 330:
         return (const GLubyte *) "3.30";
      case 400:
         return (const GLubyte *) "4.00";
      case 410:
         return (const GLubyte *) "4.10";
      case 420:
         return (const GLubyte *) "4.20";
63 64 65 66 67 68
      case 430:
         return (const GLubyte *) "4.30";
      case 440:
         return (const GLubyte *) "4.40";
      case 450:
         return (const GLubyte *) "4.50";
69 70 71 72 73 74
      default:
         _mesa_problem(ctx,
                       "Invalid GLSL version in shading_language_version()");
         return (const GLubyte *) 0;
      }
      break;
75 76

   case API_OPENGLES2:
77 78 79 80 81 82 83 84 85 86 87 88
      switch (ctx->Version) {
      case 20:
         return (const GLubyte *) "OpenGL ES GLSL ES 1.0.16";
      case 30:
         return (const GLubyte *) "OpenGL ES GLSL ES 3.00";
      case 31:
         return (const GLubyte *) "OpenGL ES GLSL ES 3.10";
      default:
         _mesa_problem(ctx,
                       "Invalid OpenGL ES version in shading_language_version()");
         return (const GLubyte *) 0;
      }
89
   case API_OPENGLES:
90 91
      /* fall-through */

92
   default:
93
      _mesa_problem(ctx, "Unexpected API value in shading_language_version()");
94 95 96 97
      return (const GLubyte *) 0;
   }
}

98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115

/**
 * Query string-valued state.  The return value should _not_ be freed by
 * the caller.
 *
 * \param name  the state variable to query.
 *
 * \sa glGetString().
 *
 * Tries to get the string from dd_function_table::GetString, otherwise returns
 * the hardcoded strings.
 */
const GLubyte * GLAPIENTRY
_mesa_GetString( GLenum name )
{
   GET_CURRENT_CONTEXT(ctx);
   static const char *vendor = "Brian Paul";
   static const char *renderer = "Mesa";
116

Brian Paul's avatar
Brian Paul committed
117 118 119
   if (!ctx)
      return NULL;

120
   ASSERT_OUTSIDE_BEGIN_END_WITH_RETVAL(ctx, NULL);
121 122 123 124 125

   /* this is a required driver function */
   assert(ctx->Driver.GetString);
   {
      /* Give the driver the chance to handle this query */
126
      const GLubyte *str = ctx->Driver.GetString(ctx, name);
127 128 129 130 131 132 133 134
      if (str)
         return str;
   }

   switch (name) {
      case GL_VENDOR:
         return (const GLubyte *) vendor;
      case GL_RENDERER:
135
         return (const GLubyte *) renderer;
136
      case GL_VERSION:
137
         return (const GLubyte *) ctx->VersionString;
138
      case GL_EXTENSIONS:
139 140 141 142
         if (ctx->API == API_OPENGL_CORE) {
            _mesa_error(ctx, GL_INVALID_ENUM, "glGetString(GL_EXTENSIONS)");
            return (const GLubyte *) 0;
         }
Michal Krol's avatar
Michal Krol committed
143
         return (const GLubyte *) ctx->Extensions.String;
144
      case GL_SHADING_LANGUAGE_VERSION:
145 146
         if (ctx->API == API_OPENGLES)
            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 153
            return (const GLubyte *) ctx->Program.ErrorString;
         }
154
         break;
155
      default:
156
         break;
157
   }
158 159 160

   _mesa_error( ctx, GL_INVALID_ENUM, "glGetString" );
   return (const GLubyte *) 0;
161 162 163
}


164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184
/**
 * GL3
 */
const GLubyte * GLAPIENTRY
_mesa_GetStringi(GLenum name, GLuint index)
{
   GET_CURRENT_CONTEXT(ctx);

   if (!ctx)
      return NULL;

   ASSERT_OUTSIDE_BEGIN_END_WITH_RETVAL(ctx, NULL);

   switch (name) {
   case GL_EXTENSIONS:
      if (index >= _mesa_get_extension_count(ctx)) {
         _mesa_error(ctx, GL_INVALID_VALUE, "glGetStringi(index=%u)", index);
         return (const GLubyte *) 0;
      }
      return _mesa_get_enabled_extension(ctx, index);
   default:
185
      _mesa_error(ctx, GL_INVALID_ENUM, "glGetStringi");
186 187 188 189 190 191
      return (const GLubyte *) 0;
   }
}



192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207
/**
 * Return pointer-valued state, such as a vertex array pointer.
 *
 * \param pname  names state to be queried
 * \param params  returns the pointer value
 *
 * \sa glGetPointerv().
 *
 * Tries to get the specified pointer via dd_function_table::GetPointerv,
 * otherwise gets the specified pointer from the current context.
 */
void GLAPIENTRY
_mesa_GetPointerv( GLenum pname, GLvoid **params )
{
   GET_CURRENT_CONTEXT(ctx);
   const GLuint clientUnit = ctx->Array.ActiveTexture;
208 209 210 211 212 213
   const char *callerstr;

   if (_mesa_is_desktop_gl(ctx))
      callerstr = "glGetPointerv";
   else
      callerstr = "glGetPointervKHR";
214 215 216 217 218

   if (!params)
      return;

   if (MESA_VERBOSE & VERBOSE_API)
219
      _mesa_debug(ctx, "%s %s\n", callerstr, _mesa_enum_to_string(pname));
220 221 222

   switch (pname) {
      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 227
         break;
      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 232
         break;
      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 237
         break;
      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 242
         break;
      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 247
         break;
      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 252
         break;
      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 257
         break;
      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 262
         break;
      case GL_FEEDBACK_BUFFER_POINTER:
263
         if (ctx->API != API_OPENGL_COMPAT)
264
            goto invalid_pname;
265 266 267
         *params = ctx->Feedback.Buffer;
         break;
      case GL_SELECTION_BUFFER_POINTER:
268
         if (ctx->API != API_OPENGL_COMPAT)
269
            goto invalid_pname;
270 271
         *params = ctx->Select.Buffer;
         break;
272
      case GL_POINT_SIZE_ARRAY_POINTER_OES:
273 274
         if (ctx->API != API_OPENGLES)
            goto invalid_pname;
275
         *params = (GLvoid *) ctx->Array.VAO->VertexAttrib[VERT_ATTRIB_POINT_SIZE].Ptr;
276
         break;
277 278
      case GL_DEBUG_CALLBACK_FUNCTION_ARB:
      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 286 287

   return;

invalid_pname:
288
   _mesa_error( ctx, GL_INVALID_ENUM, "%s", callerstr);
289
   return;
290 291 292 293 294 295 296
}


/**
 * Returns the current GL error code, or GL_NO_ERROR.
 * \return current error code
 *
297
 * Returns __struct gl_contextRec::ErrorValue.
298 299 300 301 302 303 304 305 306
 */
GLenum GLAPIENTRY
_mesa_GetError( void )
{
   GET_CURRENT_CONTEXT(ctx);
   GLenum e = ctx->ErrorValue;
   ASSERT_OUTSIDE_BEGIN_END_WITH_RETVAL(ctx, 0);

   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 312
   return e;
}
Brian Paul's avatar
Brian Paul committed
313

314 315 316 317 318 319 320 321 322 323 324 325 326 327 328 329 330 331 332 333 334 335 336 337 338 339 340 341 342 343 344 345 346 347 348 349 350 351 352 353 354 355 356 357 358 359 360 361 362 363 364 365 366 367 368 369 370 371 372 373 374 375 376 377 378 379 380 381 382 383 384 385 386 387 388 389
static void
_context_lost_GetSynciv(GLsync sync, GLenum pname, GLsizei bufSize, GLsizei *length,
                        GLint *values)
{
   GET_CURRENT_CONTEXT(ctx);
   if (ctx)
      _mesa_error(ctx, GL_CONTEXT_LOST, "GetSynciv(invalid call)");

   if (pname == GL_SYNC_STATUS && bufSize >= 1)
      *values = GL_SIGNALED;
}

static void
_context_lost_GetQueryObjectuiv(GLuint id, GLenum pname, GLuint *params)
{
   GET_CURRENT_CONTEXT(ctx);
   if (ctx)
      _mesa_error(ctx, GL_CONTEXT_LOST, "GetQueryObjectuiv(context lost)");

   if (pname == GL_QUERY_RESULT_AVAILABLE)
      *params = GL_TRUE;
}

static int
context_lost_nop_handler(void)
{
   GET_CURRENT_CONTEXT(ctx);
   if (ctx)
      _mesa_error(ctx, GL_CONTEXT_LOST, "context lost");

   return 0;
}

void
_mesa_set_context_lost_dispatch(struct gl_context *ctx)
{
   if (ctx->ContextLost == NULL) {
      int numEntries = MAX2(_glapi_get_dispatch_table_size(), _gloffset_COUNT);

      ctx->ContextLost = malloc(numEntries * sizeof(_glapi_proc));
      if (!ctx->ContextLost)
         return;

      _glapi_proc *entry = (_glapi_proc *) ctx->ContextLost;
      unsigned i;
      for (i = 0; i < numEntries; i++)
         entry[i] = (_glapi_proc) context_lost_nop_handler;

      /* The ARB_robustness specification says:
       *
       *    "* GetError and GetGraphicsResetStatus behave normally following a
       *       graphics reset, so that the application can determine a reset
       *       has occurred, and when it is safe to destroy and recreate the
       *       context.
       *
       *     * Any commands which might cause a polling application to block
       *       indefinitely will generate a CONTEXT_LOST error, but will also
       *       return a value indicating completion to the application. Such
       *       commands include:
       *
       *        + GetSynciv with <pname> SYNC_STATUS ignores the other
       *          parameters and returns SIGNALED in <values>.
       *
       *        + GetQueryObjectuiv with <pname> QUERY_RESULT_AVAILABLE
       *          ignores the other parameters and returns TRUE in <params>."
       */
      SET_GetError(ctx->ContextLost, _mesa_GetError);
      SET_GetGraphicsResetStatusARB(ctx->ContextLost, _mesa_GetGraphicsResetStatusARB);
      SET_GetSynciv(ctx->ContextLost, _context_lost_GetSynciv);
      SET_GetQueryObjectuiv(ctx->ContextLost, _context_lost_GetQueryObjectuiv);
   }

   ctx->CurrentDispatch = ctx->ContextLost;
   _glapi_set_dispatch(ctx->CurrentDispatch);
}

Brian Paul's avatar
Brian Paul committed
390 391 392 393 394 395 396 397
/**
 * Returns an error code specified by GL_ARB_robustness, or GL_NO_ERROR.
 * \return current context status
 */
GLenum GLAPIENTRY
_mesa_GetGraphicsResetStatusARB( void )
{
   GET_CURRENT_CONTEXT(ctx);
398
   GLenum status = GL_NO_ERROR;
Brian Paul's avatar
Brian Paul committed
399

400 401 402 403 404 405 406 407 408 409 410 411 412 413 414 415 416 417 418 419 420
   /* The ARB_robustness specification says:
    *
    *     "If the reset notification behavior is NO_RESET_NOTIFICATION_ARB,
    *     then the implementation will never deliver notification of reset
    *     events, and GetGraphicsResetStatusARB will always return NO_ERROR."
    */
   if (ctx->Const.ResetStrategy == GL_NO_RESET_NOTIFICATION_ARB) {
      if (MESA_VERBOSE & VERBOSE_API)
         _mesa_debug(ctx,
                     "glGetGraphicsResetStatusARB always returns GL_NO_ERROR "
                     "because reset notifictation was not requested at context "
                     "creation.\n");

      return GL_NO_ERROR;
   }

   if (ctx->Driver.GetGraphicsResetStatus) {
      /* Query the reset status of this context from the driver core.
       */
      status = ctx->Driver.GetGraphicsResetStatus(ctx);

421
      mtx_lock(&ctx->Shared->Mutex);
422 423 424 425 426 427 428 429 430 431 432 433 434

      /* If this context has not been affected by a GPU reset, check to see if
       * some other context in the share group has been affected by a reset.
       * If another context saw a reset but this context did not, assume that
       * this context was not guilty.
       */
      if (status != GL_NO_ERROR) {
         ctx->Shared->ShareGroupReset = true;
      } else if (ctx->Shared->ShareGroupReset && !ctx->ShareGroupReset) {
         status = GL_INNOCENT_CONTEXT_RESET_ARB;
      }

      ctx->ShareGroupReset = ctx->Shared->ShareGroupReset;
435
      mtx_unlock(&ctx->Shared->Mutex);
436 437
   }

438 439 440
   if (status != GL_NO_ERROR)
      _mesa_set_context_lost_dispatch(ctx);

441 442 443 444
   if (!ctx->Driver.GetGraphicsResetStatus && (MESA_VERBOSE & VERBOSE_API))
      _mesa_debug(ctx,
                  "glGetGraphicsResetStatusARB always returns GL_NO_ERROR "
                  "because the driver doesn't track reset status.\n");
Brian Paul's avatar
Brian Paul committed
445 446 447

   return status;
}