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