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