api_validate.c revision 2655265fcba9017e793026c76e490e04db088c8f
1/* 2 * Mesa 3-D graphics library 3 * 4 * Copyright (C) 1999-2007 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#include <stdbool.h> 26#include "glheader.h" 27#include "api_validate.h" 28#include "bufferobj.h" 29#include "context.h" 30#include "imports.h" 31#include "mtypes.h" 32#include "enums.h" 33#include "vbo/vbo.h" 34#include "transformfeedback.h" 35#include <stdbool.h> 36 37 38/** 39 * Check if OK to draw arrays/elements. 40 */ 41static bool 42check_valid_to_render(struct gl_context *ctx, const char *function) 43{ 44 if (!_mesa_valid_to_render(ctx, function)) { 45 return false; 46 } 47 48 switch (ctx->API) { 49 case API_OPENGLES2: 50 /* For ES2, we can draw if we have a vertex program/shader). */ 51 return ctx->VertexProgram._Current != NULL; 52 53 case API_OPENGLES: 54 /* For OpenGL ES, only draw if we have vertex positions 55 */ 56 if (!ctx->Array.VAO->VertexAttrib[VERT_ATTRIB_POS].Enabled) 57 return false; 58 break; 59 60 case API_OPENGL_CORE: 61 /* Section 10.4 (Drawing Commands Using Vertex Arrays) of the OpenGL 4.5 62 * Core Profile spec says: 63 * 64 * "An INVALID_OPERATION error is generated if no vertex array 65 * object is bound (see section 10.3.1)." 66 */ 67 if (ctx->Array.VAO == ctx->Array.DefaultVAO) { 68 _mesa_error(ctx, GL_INVALID_OPERATION, "%s(no VAO bound)", function); 69 return false; 70 } 71 72 /* The spec argues that this is allowed because a tess ctrl shader 73 * without a tess eval shader can be used with transform feedback. 74 * However, glBeginTransformFeedback doesn't allow GL_PATCHES and 75 * therefore doesn't allow tessellation. 76 * 77 * Further investigation showed that this is indeed a spec bug and 78 * a tess ctrl shader without a tess eval shader shouldn't have been 79 * allowed, because there is no API in GL 4.0 that can make use this 80 * to produce something useful. 81 * 82 * Also, all vendors except one don't support a tess ctrl shader without 83 * a tess eval shader anyway. 84 */ 85 if (ctx->TessCtrlProgram._Current && !ctx->TessEvalProgram._Current) { 86 _mesa_error(ctx, GL_INVALID_OPERATION, 87 "%s(tess eval shader is missing)", function); 88 return false; 89 } 90 91 /* Section 7.3 (Program Objects) of the OpenGL 4.5 Core Profile spec 92 * says: 93 * 94 * "If there is no active program for the vertex or fragment shader 95 * stages, the results of vertex and/or fragment processing will be 96 * undefined. However, this is not an error." 97 * 98 * The fragment shader is not tested here because other state (e.g., 99 * GL_RASTERIZER_DISCARD) affects whether or not we actually care. 100 */ 101 return ctx->VertexProgram._Current != NULL; 102 103 case API_OPENGL_COMPAT: 104 if (ctx->VertexProgram._Current != NULL) { 105 /* Draw regardless of whether or not we have any vertex arrays. 106 * (Ex: could draw a point using a constant vertex pos) 107 */ 108 return true; 109 } else { 110 /* Draw if we have vertex positions (GL_VERTEX_ARRAY or generic 111 * array [0]). 112 */ 113 return (ctx->Array.VAO->VertexAttrib[VERT_ATTRIB_POS].Enabled || 114 ctx->Array.VAO->VertexAttrib[VERT_ATTRIB_GENERIC0].Enabled); 115 } 116 break; 117 118 default: 119 unreachable("Invalid API value in check_valid_to_render()"); 120 } 121 122 return true; 123} 124 125 126/** 127 * Is 'mode' a valid value for glBegin(), glDrawArrays(), glDrawElements(), 128 * etc? The set of legal values depends on whether geometry shaders/programs 129 * are supported. 130 * Note: This may be called during display list compilation. 131 */ 132bool 133_mesa_is_valid_prim_mode(struct gl_context *ctx, GLenum mode) 134{ 135 /* The overwhelmingly common case is (mode <= GL_TRIANGLE_FAN). Test that 136 * first and exit. You would think that a switch-statement would be the 137 * right approach, but at least GCC 4.7.2 generates some pretty dire code 138 * for the common case. 139 */ 140 if (likely(mode <= GL_TRIANGLE_FAN)) 141 return true; 142 143 if (mode <= GL_POLYGON) 144 return (ctx->API == API_OPENGL_COMPAT); 145 146 if (mode <= GL_TRIANGLE_STRIP_ADJACENCY) 147 return _mesa_has_geometry_shaders(ctx); 148 149 if (mode == GL_PATCHES) 150 return _mesa_has_tessellation(ctx); 151 152 return false; 153} 154 155 156/** 157 * Is 'mode' a valid value for glBegin(), glDrawArrays(), glDrawElements(), 158 * etc? Also, do additional checking related to transformation feedback. 159 * Note: this function cannot be called during glNewList(GL_COMPILE) because 160 * this code depends on current transform feedback state. 161 * Also, do additional checking related to tessellation shaders. 162 */ 163GLboolean 164_mesa_valid_prim_mode(struct gl_context *ctx, GLenum mode, const char *name) 165{ 166 bool valid_enum = _mesa_is_valid_prim_mode(ctx, mode); 167 168 if (!valid_enum) { 169 _mesa_error(ctx, GL_INVALID_ENUM, "%s(mode=%x)", name, mode); 170 return GL_FALSE; 171 } 172 173 /* From the OpenGL 4.5 specification, section 11.3.1: 174 * 175 * The error INVALID_OPERATION is generated if Begin, or any command that 176 * implicitly calls Begin, is called when a geometry shader is active and: 177 * 178 * * the input primitive type of the current geometry shader is 179 * POINTS and <mode> is not POINTS, 180 * 181 * * the input primitive type of the current geometry shader is 182 * LINES and <mode> is not LINES, LINE_STRIP, or LINE_LOOP, 183 * 184 * * the input primitive type of the current geometry shader is 185 * TRIANGLES and <mode> is not TRIANGLES, TRIANGLE_STRIP or 186 * TRIANGLE_FAN, 187 * 188 * * the input primitive type of the current geometry shader is 189 * LINES_ADJACENCY_ARB and <mode> is not LINES_ADJACENCY_ARB or 190 * LINE_STRIP_ADJACENCY_ARB, or 191 * 192 * * the input primitive type of the current geometry shader is 193 * TRIANGLES_ADJACENCY_ARB and <mode> is not 194 * TRIANGLES_ADJACENCY_ARB or TRIANGLE_STRIP_ADJACENCY_ARB. 195 * 196 * The GL spec doesn't mention any interaction with tessellation, which 197 * is clearly a spec bug. The same rule should apply, but instead of 198 * the draw primitive mode, the tessellation evaluation shader primitive 199 * mode should be used for the checking. 200 */ 201 if (ctx->_Shader->CurrentProgram[MESA_SHADER_GEOMETRY]) { 202 const GLenum geom_mode = 203 ctx->_Shader->CurrentProgram[MESA_SHADER_GEOMETRY]->Geom.InputType; 204 struct gl_shader_program *tes = 205 ctx->_Shader->CurrentProgram[MESA_SHADER_TESS_EVAL]; 206 GLenum mode_before_gs = mode; 207 208 if (tes) { 209 if (tes->TessEval.PointMode) 210 mode_before_gs = GL_POINTS; 211 else if (tes->TessEval.PrimitiveMode == GL_ISOLINES) 212 mode_before_gs = GL_LINES; 213 else 214 /* the GL_QUADS mode generates triangles too */ 215 mode_before_gs = GL_TRIANGLES; 216 } 217 218 switch (mode_before_gs) { 219 case GL_POINTS: 220 valid_enum = (geom_mode == GL_POINTS); 221 break; 222 case GL_LINES: 223 case GL_LINE_LOOP: 224 case GL_LINE_STRIP: 225 valid_enum = (geom_mode == GL_LINES); 226 break; 227 case GL_TRIANGLES: 228 case GL_TRIANGLE_STRIP: 229 case GL_TRIANGLE_FAN: 230 valid_enum = (geom_mode == GL_TRIANGLES); 231 break; 232 case GL_QUADS: 233 case GL_QUAD_STRIP: 234 case GL_POLYGON: 235 valid_enum = false; 236 break; 237 case GL_LINES_ADJACENCY: 238 case GL_LINE_STRIP_ADJACENCY: 239 valid_enum = (geom_mode == GL_LINES_ADJACENCY); 240 break; 241 case GL_TRIANGLES_ADJACENCY: 242 case GL_TRIANGLE_STRIP_ADJACENCY: 243 valid_enum = (geom_mode == GL_TRIANGLES_ADJACENCY); 244 break; 245 default: 246 valid_enum = false; 247 break; 248 } 249 if (!valid_enum) { 250 _mesa_error(ctx, GL_INVALID_OPERATION, 251 "%s(mode=%s vs geometry shader input %s)", 252 name, 253 _mesa_lookup_prim_by_nr(mode_before_gs), 254 _mesa_lookup_prim_by_nr(geom_mode)); 255 return GL_FALSE; 256 } 257 } 258 259 /* From the OpenGL 4.0 (Core Profile) spec (section 2.12): 260 * 261 * "Tessellation operates only on patch primitives. If tessellation is 262 * active, any command that transfers vertices to the GL will 263 * generate an INVALID_OPERATION error if the primitive mode is not 264 * PATCHES. 265 * Patch primitives are not supported by pipeline stages below the 266 * tessellation evaluation shader. If there is no active program 267 * object or the active program object does not contain a tessellation 268 * evaluation shader, the error INVALID_OPERATION is generated by any 269 * command that transfers vertices to the GL if the primitive mode is 270 * PATCHES." 271 * 272 */ 273 if (ctx->_Shader->CurrentProgram[MESA_SHADER_TESS_EVAL] || 274 ctx->_Shader->CurrentProgram[MESA_SHADER_TESS_CTRL]) { 275 if (mode != GL_PATCHES) { 276 _mesa_error(ctx, GL_INVALID_OPERATION, 277 "only GL_PATCHES valid with tessellation"); 278 return GL_FALSE; 279 } 280 } 281 else { 282 if (mode == GL_PATCHES) { 283 _mesa_error(ctx, GL_INVALID_OPERATION, 284 "GL_PATCHES only valid with tessellation"); 285 return GL_FALSE; 286 } 287 } 288 289 /* From the GL_EXT_transform_feedback spec: 290 * 291 * "The error INVALID_OPERATION is generated if Begin, or any command 292 * that performs an explicit Begin, is called when: 293 * 294 * * a geometry shader is not active and <mode> does not match the 295 * allowed begin modes for the current transform feedback state as 296 * given by table X.1. 297 * 298 * * a geometry shader is active and the output primitive type of the 299 * geometry shader does not match the allowed begin modes for the 300 * current transform feedback state as given by table X.1. 301 * 302 */ 303 if (_mesa_is_xfb_active_and_unpaused(ctx)) { 304 GLboolean pass = GL_TRUE; 305 306 if(ctx->_Shader->CurrentProgram[MESA_SHADER_GEOMETRY]) { 307 switch (ctx->_Shader->CurrentProgram[MESA_SHADER_GEOMETRY]->Geom.OutputType) { 308 case GL_POINTS: 309 pass = ctx->TransformFeedback.Mode == GL_POINTS; 310 break; 311 case GL_LINE_STRIP: 312 pass = ctx->TransformFeedback.Mode == GL_LINES; 313 break; 314 case GL_TRIANGLE_STRIP: 315 pass = ctx->TransformFeedback.Mode == GL_TRIANGLES; 316 break; 317 default: 318 pass = GL_FALSE; 319 } 320 } 321 else if (ctx->_Shader->CurrentProgram[MESA_SHADER_TESS_EVAL]) { 322 struct gl_shader_program *tes = 323 ctx->_Shader->CurrentProgram[MESA_SHADER_TESS_EVAL]; 324 325 if (tes->TessEval.PointMode) 326 pass = ctx->TransformFeedback.Mode == GL_POINTS; 327 else if (tes->TessEval.PrimitiveMode == GL_ISOLINES) 328 pass = ctx->TransformFeedback.Mode == GL_LINES; 329 else 330 pass = ctx->TransformFeedback.Mode == GL_TRIANGLES; 331 } 332 else { 333 switch (mode) { 334 case GL_POINTS: 335 pass = ctx->TransformFeedback.Mode == GL_POINTS; 336 break; 337 case GL_LINES: 338 case GL_LINE_STRIP: 339 case GL_LINE_LOOP: 340 pass = ctx->TransformFeedback.Mode == GL_LINES; 341 break; 342 default: 343 pass = ctx->TransformFeedback.Mode == GL_TRIANGLES; 344 break; 345 } 346 } 347 if (!pass) { 348 _mesa_error(ctx, GL_INVALID_OPERATION, 349 "%s(mode=%s vs transform feedback %s)", 350 name, 351 _mesa_lookup_prim_by_nr(mode), 352 _mesa_lookup_prim_by_nr(ctx->TransformFeedback.Mode)); 353 return GL_FALSE; 354 } 355 } 356 357 return GL_TRUE; 358} 359 360/** 361 * Verify that the element type is valid. 362 * 363 * Generates \c GL_INVALID_ENUM and returns \c false if it is not. 364 */ 365static bool 366valid_elements_type(struct gl_context *ctx, GLenum type, const char *name) 367{ 368 switch (type) { 369 case GL_UNSIGNED_BYTE: 370 case GL_UNSIGNED_SHORT: 371 case GL_UNSIGNED_INT: 372 return true; 373 374 default: 375 _mesa_error(ctx, GL_INVALID_ENUM, "%s(type = %s)", name, 376 _mesa_enum_to_string(type)); 377 return false; 378 } 379} 380 381static bool 382validate_DrawElements_common(struct gl_context *ctx, 383 GLenum mode, GLsizei count, GLenum type, 384 const GLvoid *indices, 385 const char *caller) 386{ 387 /* From the GLES3 specification, section 2.14.2 (Transform Feedback 388 * Primitive Capture): 389 * 390 * The error INVALID_OPERATION is also generated by DrawElements, 391 * DrawElementsInstanced, and DrawRangeElements while transform feedback 392 * is active and not paused, regardless of mode. 393 */ 394 if (_mesa_is_gles3(ctx) && _mesa_is_xfb_active_and_unpaused(ctx)) { 395 _mesa_error(ctx, GL_INVALID_OPERATION, 396 "%s(transform feedback active)", caller); 397 return false; 398 } 399 400 if (count < 0) { 401 _mesa_error(ctx, GL_INVALID_VALUE, "%s(count)", caller); 402 return false; 403 } 404 405 if (!_mesa_valid_prim_mode(ctx, mode, caller)) { 406 return false; 407 } 408 409 if (!valid_elements_type(ctx, type, caller)) 410 return false; 411 412 if (!check_valid_to_render(ctx, caller)) 413 return false; 414 415 /* Not using a VBO for indices, so avoid NULL pointer derefs later. 416 */ 417 if (!_mesa_is_bufferobj(ctx->Array.VAO->IndexBufferObj) && indices == NULL) 418 return false; 419 420 if (count == 0) 421 return false; 422 423 return true; 424} 425 426/** 427 * Error checking for glDrawElements(). Includes parameter checking 428 * and VBO bounds checking. 429 * \return GL_TRUE if OK to render, GL_FALSE if error found 430 */ 431GLboolean 432_mesa_validate_DrawElements(struct gl_context *ctx, 433 GLenum mode, GLsizei count, GLenum type, 434 const GLvoid *indices) 435{ 436 FLUSH_CURRENT(ctx, 0); 437 438 return validate_DrawElements_common(ctx, mode, count, type, indices, 439 "glDrawElements"); 440} 441 442 443/** 444 * Error checking for glMultiDrawElements(). Includes parameter checking 445 * and VBO bounds checking. 446 * \return GL_TRUE if OK to render, GL_FALSE if error found 447 */ 448GLboolean 449_mesa_validate_MultiDrawElements(struct gl_context *ctx, 450 GLenum mode, const GLsizei *count, 451 GLenum type, const GLvoid * const *indices, 452 GLuint primcount) 453{ 454 unsigned i; 455 456 FLUSH_CURRENT(ctx, 0); 457 458 for (i = 0; i < primcount; i++) { 459 if (count[i] < 0) { 460 _mesa_error(ctx, GL_INVALID_VALUE, 461 "glMultiDrawElements(count)" ); 462 return GL_FALSE; 463 } 464 } 465 466 if (!_mesa_valid_prim_mode(ctx, mode, "glMultiDrawElements")) { 467 return GL_FALSE; 468 } 469 470 if (!valid_elements_type(ctx, type, "glMultiDrawElements")) 471 return GL_FALSE; 472 473 if (!check_valid_to_render(ctx, "glMultiDrawElements")) 474 return GL_FALSE; 475 476 /* Not using a VBO for indices, so avoid NULL pointer derefs later. 477 */ 478 if (!_mesa_is_bufferobj(ctx->Array.VAO->IndexBufferObj)) { 479 for (i = 0; i < primcount; i++) { 480 if (!indices[i]) 481 return GL_FALSE; 482 } 483 } 484 485 return GL_TRUE; 486} 487 488 489/** 490 * Error checking for glDrawRangeElements(). Includes parameter checking 491 * and VBO bounds checking. 492 * \return GL_TRUE if OK to render, GL_FALSE if error found 493 */ 494GLboolean 495_mesa_validate_DrawRangeElements(struct gl_context *ctx, GLenum mode, 496 GLuint start, GLuint end, 497 GLsizei count, GLenum type, 498 const GLvoid *indices) 499{ 500 FLUSH_CURRENT(ctx, 0); 501 502 if (end < start) { 503 _mesa_error(ctx, GL_INVALID_VALUE, "glDrawRangeElements(end<start)"); 504 return GL_FALSE; 505 } 506 507 return validate_DrawElements_common(ctx, mode, count, type, indices, 508 "glDrawRangeElements"); 509} 510 511 512/** 513 * Called from the tnl module to error check the function parameters and 514 * verify that we really can draw something. 515 * \return GL_TRUE if OK to render, GL_FALSE if error found 516 */ 517GLboolean 518_mesa_validate_DrawArrays(struct gl_context *ctx, GLenum mode, GLsizei count) 519{ 520 struct gl_transform_feedback_object *xfb_obj 521 = ctx->TransformFeedback.CurrentObject; 522 FLUSH_CURRENT(ctx, 0); 523 524 if (count < 0) { 525 _mesa_error(ctx, GL_INVALID_VALUE, "glDrawArrays(count)" ); 526 return GL_FALSE; 527 } 528 529 if (!_mesa_valid_prim_mode(ctx, mode, "glDrawArrays")) { 530 return GL_FALSE; 531 } 532 533 if (!check_valid_to_render(ctx, "glDrawArrays")) 534 return GL_FALSE; 535 536 /* From the GLES3 specification, section 2.14.2 (Transform Feedback 537 * Primitive Capture): 538 * 539 * The error INVALID_OPERATION is generated by DrawArrays and 540 * DrawArraysInstanced if recording the vertices of a primitive to the 541 * buffer objects being used for transform feedback purposes would result 542 * in either exceeding the limits of any buffer object’s size, or in 543 * exceeding the end position offset + size − 1, as set by 544 * BindBufferRange. 545 * 546 * This is in contrast to the behaviour of desktop GL, where the extra 547 * primitives are silently dropped from the transform feedback buffer. 548 */ 549 if (_mesa_is_gles3(ctx) && _mesa_is_xfb_active_and_unpaused(ctx)) { 550 size_t prim_count = vbo_count_tessellated_primitives(mode, count, 1); 551 if (xfb_obj->GlesRemainingPrims < prim_count) { 552 _mesa_error(ctx, GL_INVALID_OPERATION, 553 "glDrawArrays(exceeds transform feedback size)"); 554 return GL_FALSE; 555 } 556 xfb_obj->GlesRemainingPrims -= prim_count; 557 } 558 559 if (count == 0) 560 return GL_FALSE; 561 562 return GL_TRUE; 563} 564 565 566GLboolean 567_mesa_validate_DrawArraysInstanced(struct gl_context *ctx, GLenum mode, GLint first, 568 GLsizei count, GLsizei numInstances) 569{ 570 struct gl_transform_feedback_object *xfb_obj 571 = ctx->TransformFeedback.CurrentObject; 572 FLUSH_CURRENT(ctx, 0); 573 574 if (count < 0) { 575 _mesa_error(ctx, GL_INVALID_VALUE, 576 "glDrawArraysInstanced(count=%d)", count); 577 return GL_FALSE; 578 } 579 580 if (first < 0) { 581 _mesa_error(ctx, GL_INVALID_VALUE, 582 "glDrawArraysInstanced(start=%d)", first); 583 return GL_FALSE; 584 } 585 586 if (!_mesa_valid_prim_mode(ctx, mode, "glDrawArraysInstanced")) { 587 return GL_FALSE; 588 } 589 590 if (numInstances <= 0) { 591 if (numInstances < 0) 592 _mesa_error(ctx, GL_INVALID_VALUE, 593 "glDrawArraysInstanced(numInstances=%d)", numInstances); 594 return GL_FALSE; 595 } 596 597 if (!check_valid_to_render(ctx, "glDrawArraysInstanced(invalid to render)")) 598 return GL_FALSE; 599 600 /* From the GLES3 specification, section 2.14.2 (Transform Feedback 601 * Primitive Capture): 602 * 603 * The error INVALID_OPERATION is generated by DrawArrays and 604 * DrawArraysInstanced if recording the vertices of a primitive to the 605 * buffer objects being used for transform feedback purposes would result 606 * in either exceeding the limits of any buffer object’s size, or in 607 * exceeding the end position offset + size − 1, as set by 608 * BindBufferRange. 609 * 610 * This is in contrast to the behaviour of desktop GL, where the extra 611 * primitives are silently dropped from the transform feedback buffer. 612 */ 613 if (_mesa_is_gles3(ctx) && _mesa_is_xfb_active_and_unpaused(ctx)) { 614 size_t prim_count 615 = vbo_count_tessellated_primitives(mode, count, numInstances); 616 if (xfb_obj->GlesRemainingPrims < prim_count) { 617 _mesa_error(ctx, GL_INVALID_OPERATION, 618 "glDrawArraysInstanced(exceeds transform feedback size)"); 619 return GL_FALSE; 620 } 621 xfb_obj->GlesRemainingPrims -= prim_count; 622 } 623 624 if (count == 0) 625 return GL_FALSE; 626 627 return GL_TRUE; 628} 629 630 631GLboolean 632_mesa_validate_DrawElementsInstanced(struct gl_context *ctx, 633 GLenum mode, GLsizei count, GLenum type, 634 const GLvoid *indices, GLsizei numInstances) 635{ 636 FLUSH_CURRENT(ctx, 0); 637 638 if (numInstances < 0) { 639 _mesa_error(ctx, GL_INVALID_VALUE, 640 "glDrawElementsInstanced(numInstances=%d)", numInstances); 641 return GL_FALSE; 642 } 643 644 return validate_DrawElements_common(ctx, mode, count, type, indices, 645 "glDrawElementsInstanced") 646 && (numInstances > 0); 647} 648 649 650GLboolean 651_mesa_validate_DrawTransformFeedback(struct gl_context *ctx, 652 GLenum mode, 653 struct gl_transform_feedback_object *obj, 654 GLuint stream, 655 GLsizei numInstances) 656{ 657 FLUSH_CURRENT(ctx, 0); 658 659 if (!_mesa_valid_prim_mode(ctx, mode, "glDrawTransformFeedback*(mode)")) { 660 return GL_FALSE; 661 } 662 663 if (!obj) { 664 _mesa_error(ctx, GL_INVALID_VALUE, "glDrawTransformFeedback*(name)"); 665 return GL_FALSE; 666 } 667 668 if (stream >= ctx->Const.MaxVertexStreams) { 669 _mesa_error(ctx, GL_INVALID_VALUE, 670 "glDrawTransformFeedbackStream*(index>=MaxVertexStream)"); 671 return GL_FALSE; 672 } 673 674 if (!obj->EndedAnytime) { 675 _mesa_error(ctx, GL_INVALID_OPERATION, "glDrawTransformFeedback*"); 676 return GL_FALSE; 677 } 678 679 if (numInstances <= 0) { 680 if (numInstances < 0) 681 _mesa_error(ctx, GL_INVALID_VALUE, 682 "glDrawTransformFeedback*Instanced(numInstances=%d)", 683 numInstances); 684 return GL_FALSE; 685 } 686 687 if (!check_valid_to_render(ctx, "glDrawTransformFeedback*")) { 688 return GL_FALSE; 689 } 690 691 return GL_TRUE; 692} 693 694static GLboolean 695valid_draw_indirect(struct gl_context *ctx, 696 GLenum mode, const GLvoid *indirect, 697 GLsizei size, const char *name) 698{ 699 const uint64_t end = (uint64_t) (uintptr_t) indirect + size; 700 701 /* OpenGL ES 3.1 spec. section 10.5: 702 * 703 * "DrawArraysIndirect requires that all data sourced for the 704 * command, including the DrawArraysIndirectCommand 705 * structure, be in buffer objects, and may not be called when 706 * the default vertex array object is bound." 707 */ 708 if (ctx->Array.VAO == ctx->Array.DefaultVAO) { 709 _mesa_error(ctx, GL_INVALID_OPERATION, "(no VAO bound)"); 710 return GL_FALSE; 711 } 712 713 /* From OpenGL ES 3.1 spec. section 10.5: 714 * "An INVALID_OPERATION error is generated if zero is bound to 715 * VERTEX_ARRAY_BINDING, DRAW_INDIRECT_BUFFER or to any enabled 716 * vertex array." 717 * 718 * Here we check that for each enabled vertex array we have a vertex 719 * buffer bound. 720 */ 721 if (_mesa_is_gles31(ctx) && 722 ctx->Array.VAO->_Enabled != ctx->Array.VAO->VertexAttribBufferMask) { 723 _mesa_error(ctx, GL_INVALID_OPERATION, "%s(No VBO bound)", name); 724 return GL_FALSE; 725 } 726 727 if (!_mesa_valid_prim_mode(ctx, mode, name)) 728 return GL_FALSE; 729 730 /* OpenGL ES 3.1 specification, section 10.5: 731 * 732 * "An INVALID_OPERATION error is generated if 733 * transform feedback is active and not paused." 734 */ 735 if (_mesa_is_gles31(ctx) && _mesa_is_xfb_active_and_unpaused(ctx)) { 736 _mesa_error(ctx, GL_INVALID_OPERATION, 737 "%s(TransformFeedback is active and not paused)", name); 738 } 739 740 /* From OpenGL version 4.4. section 10.5 741 * and OpenGL ES 3.1, section 10.6: 742 * 743 * "An INVALID_VALUE error is generated if indirect is not a 744 * multiple of the size, in basic machine units, of uint." 745 */ 746 if ((GLsizeiptr)indirect & (sizeof(GLuint) - 1)) { 747 _mesa_error(ctx, GL_INVALID_VALUE, 748 "%s(indirect is not aligned)", name); 749 return GL_FALSE; 750 } 751 752 if (!_mesa_is_bufferobj(ctx->DrawIndirectBuffer)) { 753 _mesa_error(ctx, GL_INVALID_OPERATION, 754 "%s: no buffer bound to DRAW_INDIRECT_BUFFER", name); 755 return GL_FALSE; 756 } 757 758 if (_mesa_check_disallowed_mapping(ctx->DrawIndirectBuffer)) { 759 _mesa_error(ctx, GL_INVALID_OPERATION, 760 "%s(DRAW_INDIRECT_BUFFER is mapped)", name); 761 return GL_FALSE; 762 } 763 764 /* From the ARB_draw_indirect specification: 765 * "An INVALID_OPERATION error is generated if the commands source data 766 * beyond the end of the buffer object [...]" 767 */ 768 if (ctx->DrawIndirectBuffer->Size < end) { 769 _mesa_error(ctx, GL_INVALID_OPERATION, 770 "%s(DRAW_INDIRECT_BUFFER too small)", name); 771 return GL_FALSE; 772 } 773 774 if (!check_valid_to_render(ctx, name)) 775 return GL_FALSE; 776 777 return GL_TRUE; 778} 779 780static inline GLboolean 781valid_draw_indirect_elements(struct gl_context *ctx, 782 GLenum mode, GLenum type, const GLvoid *indirect, 783 GLsizeiptr size, const char *name) 784{ 785 if (!valid_elements_type(ctx, type, name)) 786 return GL_FALSE; 787 788 /* 789 * Unlike regular DrawElementsInstancedBaseVertex commands, the indices 790 * may not come from a client array and must come from an index buffer. 791 * If no element array buffer is bound, an INVALID_OPERATION error is 792 * generated. 793 */ 794 if (!_mesa_is_bufferobj(ctx->Array.VAO->IndexBufferObj)) { 795 _mesa_error(ctx, GL_INVALID_OPERATION, 796 "%s(no buffer bound to GL_ELEMENT_ARRAY_BUFFER)", name); 797 return GL_FALSE; 798 } 799 800 return valid_draw_indirect(ctx, mode, indirect, size, name); 801} 802 803static inline GLboolean 804valid_draw_indirect_multi(struct gl_context *ctx, 805 GLsizei primcount, GLsizei stride, 806 const char *name) 807{ 808 809 /* From the ARB_multi_draw_indirect specification: 810 * "INVALID_VALUE is generated by MultiDrawArraysIndirect or 811 * MultiDrawElementsIndirect if <primcount> is negative." 812 * 813 * "<primcount> must be positive, otherwise an INVALID_VALUE error will 814 * be generated." 815 */ 816 if (primcount < 0) { 817 _mesa_error(ctx, GL_INVALID_VALUE, "%s(primcount < 0)", name); 818 return GL_FALSE; 819 } 820 821 822 /* From the ARB_multi_draw_indirect specification: 823 * "<stride> must be a multiple of four, otherwise an INVALID_VALUE 824 * error is generated." 825 */ 826 if (stride % 4) { 827 _mesa_error(ctx, GL_INVALID_VALUE, "%s(stride %% 4)", name); 828 return GL_FALSE; 829 } 830 831 return GL_TRUE; 832} 833 834GLboolean 835_mesa_validate_DrawArraysIndirect(struct gl_context *ctx, 836 GLenum mode, 837 const GLvoid *indirect) 838{ 839 const unsigned drawArraysNumParams = 4; 840 841 FLUSH_CURRENT(ctx, 0); 842 843 return valid_draw_indirect(ctx, mode, 844 indirect, drawArraysNumParams * sizeof(GLuint), 845 "glDrawArraysIndirect"); 846} 847 848GLboolean 849_mesa_validate_DrawElementsIndirect(struct gl_context *ctx, 850 GLenum mode, GLenum type, 851 const GLvoid *indirect) 852{ 853 const unsigned drawElementsNumParams = 5; 854 855 FLUSH_CURRENT(ctx, 0); 856 857 return valid_draw_indirect_elements(ctx, mode, type, 858 indirect, drawElementsNumParams * sizeof(GLuint), 859 "glDrawElementsIndirect"); 860} 861 862GLboolean 863_mesa_validate_MultiDrawArraysIndirect(struct gl_context *ctx, 864 GLenum mode, 865 const GLvoid *indirect, 866 GLsizei primcount, GLsizei stride) 867{ 868 GLsizeiptr size = 0; 869 const unsigned drawArraysNumParams = 4; 870 871 FLUSH_CURRENT(ctx, 0); 872 873 /* caller has converted stride==0 to drawArraysNumParams * sizeof(GLuint) */ 874 assert(stride != 0); 875 876 if (!valid_draw_indirect_multi(ctx, primcount, stride, 877 "glMultiDrawArraysIndirect")) 878 return GL_FALSE; 879 880 /* number of bytes of the indirect buffer which will be read */ 881 size = primcount 882 ? (primcount - 1) * stride + drawArraysNumParams * sizeof(GLuint) 883 : 0; 884 885 if (!valid_draw_indirect(ctx, mode, indirect, size, 886 "glMultiDrawArraysIndirect")) 887 return GL_FALSE; 888 889 return GL_TRUE; 890} 891 892GLboolean 893_mesa_validate_MultiDrawElementsIndirect(struct gl_context *ctx, 894 GLenum mode, GLenum type, 895 const GLvoid *indirect, 896 GLsizei primcount, GLsizei stride) 897{ 898 GLsizeiptr size = 0; 899 const unsigned drawElementsNumParams = 5; 900 901 FLUSH_CURRENT(ctx, 0); 902 903 /* caller has converted stride==0 to drawElementsNumParams * sizeof(GLuint) */ 904 assert(stride != 0); 905 906 if (!valid_draw_indirect_multi(ctx, primcount, stride, 907 "glMultiDrawElementsIndirect")) 908 return GL_FALSE; 909 910 /* number of bytes of the indirect buffer which will be read */ 911 size = primcount 912 ? (primcount - 1) * stride + drawElementsNumParams * sizeof(GLuint) 913 : 0; 914 915 if (!valid_draw_indirect_elements(ctx, mode, type, 916 indirect, size, 917 "glMultiDrawElementsIndirect")) 918 return GL_FALSE; 919 920 return GL_TRUE; 921} 922 923static GLboolean 924valid_draw_indirect_parameters(struct gl_context *ctx, 925 const char *name, 926 GLintptr drawcount) 927{ 928 /* From the ARB_indirect_parameters specification: 929 * "INVALID_VALUE is generated by MultiDrawArraysIndirectCountARB or 930 * MultiDrawElementsIndirectCountARB if <drawcount> is not a multiple of 931 * four." 932 */ 933 if (drawcount & 3) { 934 _mesa_error(ctx, GL_INVALID_VALUE, 935 "%s(drawcount is not a multiple of 4)", name); 936 return GL_FALSE; 937 } 938 939 /* From the ARB_indirect_parameters specification: 940 * "INVALID_OPERATION is generated by MultiDrawArraysIndirectCountARB or 941 * MultiDrawElementsIndirectCountARB if no buffer is bound to the 942 * PARAMETER_BUFFER_ARB binding point." 943 */ 944 if (!_mesa_is_bufferobj(ctx->ParameterBuffer)) { 945 _mesa_error(ctx, GL_INVALID_OPERATION, 946 "%s: no buffer bound to PARAMETER_BUFFER", name); 947 return GL_FALSE; 948 } 949 950 if (_mesa_check_disallowed_mapping(ctx->ParameterBuffer)) { 951 _mesa_error(ctx, GL_INVALID_OPERATION, 952 "%s(PARAMETER_BUFFER is mapped)", name); 953 return GL_FALSE; 954 } 955 956 /* From the ARB_indirect_parameters specification: 957 * "INVALID_OPERATION is generated by MultiDrawArraysIndirectCountARB or 958 * MultiDrawElementsIndirectCountARB if reading a <sizei> typed value 959 * from the buffer bound to the PARAMETER_BUFFER_ARB target at the offset 960 * specified by <drawcount> would result in an out-of-bounds access." 961 */ 962 if (ctx->ParameterBuffer->Size < drawcount + sizeof(GLsizei)) { 963 _mesa_error(ctx, GL_INVALID_OPERATION, 964 "%s(PARAMETER_BUFFER too small)", name); 965 return GL_FALSE; 966 } 967 968 return GL_TRUE; 969} 970 971GLboolean 972_mesa_validate_MultiDrawArraysIndirectCount(struct gl_context *ctx, 973 GLenum mode, 974 GLintptr indirect, 975 GLintptr drawcount, 976 GLsizei maxdrawcount, 977 GLsizei stride) 978{ 979 GLsizeiptr size = 0; 980 const unsigned drawArraysNumParams = 4; 981 982 FLUSH_CURRENT(ctx, 0); 983 984 /* caller has converted stride==0 to drawArraysNumParams * sizeof(GLuint) */ 985 assert(stride != 0); 986 987 if (!valid_draw_indirect_multi(ctx, maxdrawcount, stride, 988 "glMultiDrawArraysIndirectCountARB")) 989 return GL_FALSE; 990 991 /* number of bytes of the indirect buffer which will be read */ 992 size = maxdrawcount 993 ? (maxdrawcount - 1) * stride + drawArraysNumParams * sizeof(GLuint) 994 : 0; 995 996 if (!valid_draw_indirect(ctx, mode, (void *)indirect, size, 997 "glMultiDrawArraysIndirectCountARB")) 998 return GL_FALSE; 999 1000 return valid_draw_indirect_parameters( 1001 ctx, "glMultiDrawArraysIndirectCountARB", drawcount); 1002} 1003 1004GLboolean 1005_mesa_validate_MultiDrawElementsIndirectCount(struct gl_context *ctx, 1006 GLenum mode, GLenum type, 1007 GLintptr indirect, 1008 GLintptr drawcount, 1009 GLsizei maxdrawcount, 1010 GLsizei stride) 1011{ 1012 GLsizeiptr size = 0; 1013 const unsigned drawElementsNumParams = 5; 1014 1015 FLUSH_CURRENT(ctx, 0); 1016 1017 /* caller has converted stride==0 to drawElementsNumParams * sizeof(GLuint) */ 1018 assert(stride != 0); 1019 1020 if (!valid_draw_indirect_multi(ctx, maxdrawcount, stride, 1021 "glMultiDrawElementsIndirectCountARB")) 1022 return GL_FALSE; 1023 1024 /* number of bytes of the indirect buffer which will be read */ 1025 size = maxdrawcount 1026 ? (maxdrawcount - 1) * stride + drawElementsNumParams * sizeof(GLuint) 1027 : 0; 1028 1029 if (!valid_draw_indirect_elements(ctx, mode, type, 1030 (void *)indirect, size, 1031 "glMultiDrawElementsIndirectCountARB")) 1032 return GL_FALSE; 1033 1034 return valid_draw_indirect_parameters( 1035 ctx, "glMultiDrawElementsIndirectCountARB", drawcount); 1036} 1037 1038static bool 1039check_valid_to_compute(struct gl_context *ctx, const char *function) 1040{ 1041 struct gl_shader_program *prog; 1042 1043 if (!_mesa_has_compute_shaders(ctx)) { 1044 _mesa_error(ctx, GL_INVALID_OPERATION, 1045 "unsupported function (%s) called", 1046 function); 1047 return false; 1048 } 1049 1050 /* From the OpenGL 4.3 Core Specification, Chapter 19, Compute Shaders: 1051 * 1052 * "An INVALID_OPERATION error is generated if there is no active program 1053 * for the compute shader stage." 1054 */ 1055 prog = ctx->_Shader->CurrentProgram[MESA_SHADER_COMPUTE]; 1056 if (prog == NULL || prog->_LinkedShaders[MESA_SHADER_COMPUTE] == NULL) { 1057 _mesa_error(ctx, GL_INVALID_OPERATION, 1058 "%s(no active compute shader)", 1059 function); 1060 return false; 1061 } 1062 1063 return true; 1064} 1065 1066GLboolean 1067_mesa_validate_DispatchCompute(struct gl_context *ctx, 1068 const GLuint *num_groups) 1069{ 1070 int i; 1071 FLUSH_CURRENT(ctx, 0); 1072 1073 if (!check_valid_to_compute(ctx, "glDispatchCompute")) 1074 return GL_FALSE; 1075 1076 for (i = 0; i < 3; i++) { 1077 /* From the OpenGL 4.3 Core Specification, Chapter 19, Compute Shaders: 1078 * 1079 * "An INVALID_VALUE error is generated if any of num_groups_x, 1080 * num_groups_y and num_groups_z are greater than or equal to the 1081 * maximum work group count for the corresponding dimension." 1082 * 1083 * However, the "or equal to" portions appears to be a specification 1084 * bug. In all other areas, the specification appears to indicate that 1085 * the number of workgroups can match the MAX_COMPUTE_WORK_GROUP_COUNT 1086 * value. For example, under DispatchComputeIndirect: 1087 * 1088 * "If any of num_groups_x, num_groups_y or num_groups_z is greater than 1089 * the value of MAX_COMPUTE_WORK_GROUP_COUNT for the corresponding 1090 * dimension then the results are undefined." 1091 * 1092 * Additionally, the OpenGLES 3.1 specification does not contain "or 1093 * equal to" as an error condition. 1094 */ 1095 if (num_groups[i] > ctx->Const.MaxComputeWorkGroupCount[i]) { 1096 _mesa_error(ctx, GL_INVALID_VALUE, 1097 "glDispatchCompute(num_groups_%c)", 'x' + i); 1098 return GL_FALSE; 1099 } 1100 } 1101 1102 return GL_TRUE; 1103} 1104 1105static GLboolean 1106valid_dispatch_indirect(struct gl_context *ctx, 1107 GLintptr indirect, 1108 GLsizei size, const char *name) 1109{ 1110 GLintptr end = (GLintptr)indirect + size; 1111 1112 if (!check_valid_to_compute(ctx, name)) 1113 return GL_FALSE; 1114 1115 /* From the OpenGL 4.3 Core Specification, Chapter 19, Compute Shaders: 1116 * 1117 * "An INVALID_VALUE error is generated if indirect is negative or is not a 1118 * multiple of four." 1119 */ 1120 if ((GLintptr)indirect & (sizeof(GLuint) - 1)) { 1121 _mesa_error(ctx, GL_INVALID_VALUE, 1122 "%s(indirect is not aligned)", name); 1123 return GL_FALSE; 1124 } 1125 1126 if ((GLintptr)indirect < 0) { 1127 _mesa_error(ctx, GL_INVALID_VALUE, 1128 "%s(indirect is less than zero)", name); 1129 return GL_FALSE; 1130 } 1131 1132 /* From the OpenGL 4.3 Core Specification, Chapter 19, Compute Shaders: 1133 * 1134 * "An INVALID_OPERATION error is generated if no buffer is bound to the 1135 * DRAW_INDIRECT_BUFFER binding, or if the command would source data 1136 * beyond the end of the buffer object." 1137 */ 1138 if (!_mesa_is_bufferobj(ctx->DispatchIndirectBuffer)) { 1139 _mesa_error(ctx, GL_INVALID_OPERATION, 1140 "%s: no buffer bound to DISPATCH_INDIRECT_BUFFER", name); 1141 return GL_FALSE; 1142 } 1143 1144 if (_mesa_check_disallowed_mapping(ctx->DispatchIndirectBuffer)) { 1145 _mesa_error(ctx, GL_INVALID_OPERATION, 1146 "%s(DISPATCH_INDIRECT_BUFFER is mapped)", name); 1147 return GL_FALSE; 1148 } 1149 1150 if (ctx->DispatchIndirectBuffer->Size < end) { 1151 _mesa_error(ctx, GL_INVALID_OPERATION, 1152 "%s(DISPATCH_INDIRECT_BUFFER too small)", name); 1153 return GL_FALSE; 1154 } 1155 1156 return GL_TRUE; 1157} 1158 1159GLboolean 1160_mesa_validate_DispatchComputeIndirect(struct gl_context *ctx, 1161 GLintptr indirect) 1162{ 1163 FLUSH_CURRENT(ctx, 0); 1164 1165 return valid_dispatch_indirect(ctx, indirect, 3 * sizeof(GLuint), 1166 "glDispatchComputeIndirect"); 1167} 1168