• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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 "arrayobj.h"
29 #include "bufferobj.h"
30 #include "context.h"
31 #include "imports.h"
32 #include "mtypes.h"
33 #include "pipelineobj.h"
34 #include "enums.h"
35 #include "state.h"
36 #include "transformfeedback.h"
37 #include "uniforms.h"
38 #include "vbo/vbo.h"
39 #include "program/prog_print.h"
40 
41 
42 static bool
check_blend_func_error(struct gl_context * ctx)43 check_blend_func_error(struct gl_context *ctx)
44 {
45    /* The ARB_blend_func_extended spec's ERRORS section says:
46     *
47     *    "The error INVALID_OPERATION is generated by Begin or any procedure
48     *     that implicitly calls Begin if any draw buffer has a blend function
49     *     requiring the second color input (SRC1_COLOR, ONE_MINUS_SRC1_COLOR,
50     *     SRC1_ALPHA or ONE_MINUS_SRC1_ALPHA), and a framebuffer is bound that
51     *     has more than the value of MAX_DUAL_SOURCE_DRAW_BUFFERS-1 active
52     *     color attachements."
53     */
54    for (unsigned i = ctx->Const.MaxDualSourceDrawBuffers;
55 	i < ctx->DrawBuffer->_NumColorDrawBuffers;
56 	i++) {
57       if (ctx->Color.Blend[i]._UsesDualSrc) {
58 	 _mesa_error(ctx, GL_INVALID_OPERATION,
59 		     "dual source blend on illegal attachment");
60 	 return false;
61       }
62    }
63 
64    if (ctx->Color.BlendEnabled && ctx->Color._AdvancedBlendMode) {
65       /* The KHR_blend_equation_advanced spec says:
66        *
67        *    "If any non-NONE draw buffer uses a blend equation found in table
68        *     X.1 or X.2, the error INVALID_OPERATION is generated by Begin or
69        *     any operation that implicitly calls Begin (such as DrawElements)
70        *     if:
71        *
72        *       * the draw buffer for color output zero selects multiple color
73        *         buffers (e.g., FRONT_AND_BACK in the default framebuffer); or
74        *
75        *       * the draw buffer for any other color output is not NONE."
76        */
77       if (ctx->DrawBuffer->ColorDrawBuffer[0] == GL_FRONT_AND_BACK) {
78          _mesa_error(ctx, GL_INVALID_OPERATION,
79                      "advanced blending is active and draw buffer for color "
80                      "output zero selects multiple color buffers");
81          return false;
82       }
83 
84       for (unsigned i = 1; i < ctx->DrawBuffer->_NumColorDrawBuffers; i++) {
85          if (ctx->DrawBuffer->ColorDrawBuffer[i] != GL_NONE) {
86             _mesa_error(ctx, GL_INVALID_OPERATION,
87                         "advanced blending is active with multiple color "
88                         "draw buffers");
89             return false;
90          }
91       }
92 
93       /* The KHR_blend_equation_advanced spec says:
94        *
95        *    "Advanced blending equations require the use of a fragment shader
96        *     with a matching "blend_support" layout qualifier.  If the current
97        *     blend equation is found in table X.1 or X.2, and the active
98        *     fragment shader does not include the layout qualifier matching
99        *     the blend equation or "blend_support_all_equations", the error
100        *     INVALID_OPERATION is generated [...]"
101        */
102       const struct gl_program *prog = ctx->FragmentProgram._Current;
103       const GLbitfield blend_support = !prog ? 0 : prog->sh.fs.BlendSupport;
104 
105       if ((blend_support & ctx->Color._AdvancedBlendMode) == 0) {
106          _mesa_error(ctx, GL_INVALID_OPERATION,
107                      "fragment shader does not allow advanced blending mode "
108                      "(%s)",
109                       _mesa_enum_to_string(ctx->Color.Blend[0].EquationRGB));
110       }
111    }
112 
113    return true;
114 }
115 
116 
117 /**
118  * Prior to drawing anything with glBegin, glDrawArrays, etc. this function
119  * is called to see if it's valid to render.  This involves checking that
120  * the current shader is valid and the framebuffer is complete.
121  * It also check the current pipeline object is valid if any.
122  * If an error is detected it'll be recorded here.
123  * \return GL_TRUE if OK to render, GL_FALSE if not
124  */
125 GLboolean
_mesa_valid_to_render(struct gl_context * ctx,const char * where)126 _mesa_valid_to_render(struct gl_context *ctx, const char *where)
127 {
128    /* This depends on having up to date derived state (shaders) */
129    if (ctx->NewState)
130       _mesa_update_state(ctx);
131 
132    if (ctx->API == API_OPENGL_COMPAT) {
133       /* Any shader stages that are not supplied by the GLSL shader and have
134        * assembly shaders enabled must now be validated.
135        */
136       if (!ctx->_Shader->CurrentProgram[MESA_SHADER_VERTEX] &&
137           ctx->VertexProgram.Enabled &&
138           !_mesa_arb_vertex_program_enabled(ctx)) {
139          _mesa_error(ctx, GL_INVALID_OPERATION,
140                      "%s(vertex program not valid)", where);
141          return GL_FALSE;
142       }
143 
144       if (!ctx->_Shader->CurrentProgram[MESA_SHADER_FRAGMENT]) {
145          if (ctx->FragmentProgram.Enabled &&
146              !_mesa_arb_fragment_program_enabled(ctx)) {
147             _mesa_error(ctx, GL_INVALID_OPERATION,
148                         "%s(fragment program not valid)", where);
149             return GL_FALSE;
150          }
151 
152          /* If drawing to integer-valued color buffers, there must be an
153           * active fragment shader (GL_EXT_texture_integer).
154           */
155          if (ctx->DrawBuffer && ctx->DrawBuffer->_IntegerBuffers) {
156             _mesa_error(ctx, GL_INVALID_OPERATION,
157                         "%s(integer format but no fragment shader)", where);
158             return GL_FALSE;
159          }
160       }
161    }
162 
163    /* A pipeline object is bound */
164    if (ctx->_Shader->Name && !ctx->_Shader->Validated) {
165       if (!_mesa_validate_program_pipeline(ctx, ctx->_Shader)) {
166          _mesa_error(ctx, GL_INVALID_OPERATION,
167                      "glValidateProgramPipeline failed to validate the "
168                      "pipeline");
169          return GL_FALSE;
170       }
171    }
172 
173    /* If a program is active and SSO not in use, check if validation of
174     * samplers succeeded for the active program. */
175    if (ctx->_Shader->ActiveProgram && ctx->_Shader != ctx->Pipeline.Current) {
176       char errMsg[100];
177       if (!_mesa_sampler_uniforms_are_valid(ctx->_Shader->ActiveProgram,
178                                             errMsg, 100)) {
179          _mesa_error(ctx, GL_INVALID_OPERATION, "%s", errMsg);
180          return GL_FALSE;
181       }
182    }
183 
184    if (ctx->DrawBuffer->_Status != GL_FRAMEBUFFER_COMPLETE_EXT) {
185       _mesa_error(ctx, GL_INVALID_FRAMEBUFFER_OPERATION_EXT,
186                   "%s(incomplete framebuffer)", where);
187       return GL_FALSE;
188    }
189 
190    if (!check_blend_func_error(ctx)) {
191       return GL_FALSE;
192    }
193 
194    /* From the GL_NV_fill_rectangle spec:
195     *
196     * "An INVALID_OPERATION error is generated by Begin or any Draw command if
197     *  only one of the front and back polygon mode is FILL_RECTANGLE_NV."
198     */
199    if ((ctx->Polygon.FrontMode == GL_FILL_RECTANGLE_NV) !=
200        (ctx->Polygon.BackMode == GL_FILL_RECTANGLE_NV)) {
201       _mesa_error(ctx, GL_INVALID_OPERATION,
202                   "GL_FILL_RECTANGLE_NV must be used as both front/back "
203                   "polygon mode or neither");
204       return GL_FALSE;
205    }
206 
207 #ifdef DEBUG
208    if (ctx->_Shader->Flags & GLSL_LOG) {
209       struct gl_program **prog = ctx->_Shader->CurrentProgram;
210 
211       for (unsigned i = 0; i < MESA_SHADER_STAGES; i++) {
212 	 if (prog[i] == NULL || prog[i]->_Used)
213 	    continue;
214 
215 	 /* This is the first time this shader is being used.
216 	  * Append shader's constants/uniforms to log file.
217 	  *
218 	  * Only log data for the program target that matches the shader
219 	  * target.  It's possible to have a program bound to the vertex
220 	  * shader target that also supplied a fragment shader.  If that
221 	  * program isn't also bound to the fragment shader target we don't
222 	  * want to log its fragment data.
223 	  */
224 	 _mesa_append_uniforms_to_file(prog[i]);
225       }
226 
227       for (unsigned i = 0; i < MESA_SHADER_STAGES; i++) {
228 	 if (prog[i] != NULL)
229 	    prog[i]->_Used = GL_TRUE;
230       }
231    }
232 #endif
233 
234    return GL_TRUE;
235 }
236 
237 
238 /**
239  * Check if OK to draw arrays/elements.
240  */
241 static bool
check_valid_to_render(struct gl_context * ctx,const char * function)242 check_valid_to_render(struct gl_context *ctx, const char *function)
243 {
244    if (!_mesa_valid_to_render(ctx, function)) {
245       return false;
246    }
247 
248    /* Section 6.3.2 from the GL 4.5:
249     * "Any GL command which attempts to read from, write to, or change
250     *  the state of a buffer object may generate an INVALID_OPERATION error if
251     *  all or part of the buffer object is mapped ... However, only commands
252     *  which explicitly describe this error are required to do so. If an error
253     *  is not generated, such commands will have undefined results and may
254     *  result in GL interruption or termination."
255     *
256     * Only some buffer API functions require INVALID_OPERATION with mapped
257     * buffers. No other functions list such an error, thus it's not required
258     * to report INVALID_OPERATION for draw calls with mapped buffers.
259     */
260    if (!ctx->Const.AllowMappedBuffersDuringExecution &&
261        !_mesa_all_buffers_are_unmapped(ctx->Array.VAO)) {
262       _mesa_error(ctx, GL_INVALID_OPERATION,
263                   "%s(vertex buffers are mapped)", function);
264       return false;
265    }
266 
267    /* Section 11.2 (Tessellation) of the ES 3.2 spec says:
268     *
269     * "An INVALID_OPERATION error is generated by any command that
270     *  transfers vertices to the GL if the current program state has
271     *  one but not both of a tessellation control shader and tessellation
272     *  evaluation shader."
273     *
274     * The OpenGL spec argues that this is allowed because a tess ctrl shader
275     * without a tess eval shader can be used with transform feedback.
276     * However, glBeginTransformFeedback doesn't allow GL_PATCHES and
277     * therefore doesn't allow tessellation.
278     *
279     * Further investigation showed that this is indeed a spec bug and
280     * a tess ctrl shader without a tess eval shader shouldn't have been
281     * allowed, because there is no API in GL 4.0 that can make use this
282     * to produce something useful.
283     *
284     * Also, all vendors except one don't support a tess ctrl shader without
285     * a tess eval shader anyway.
286     */
287    if (ctx->TessCtrlProgram._Current && !ctx->TessEvalProgram._Current) {
288       _mesa_error(ctx, GL_INVALID_OPERATION,
289                   "%s(tess eval shader is missing)", function);
290       return false;
291    }
292 
293    switch (ctx->API) {
294    case API_OPENGLES2:
295       /* Section 11.2 (Tessellation) of the ES 3.2 spec says:
296        *
297        * "An INVALID_OPERATION error is generated by any command that
298        *  transfers vertices to the GL if the current program state has
299        *  one but not both of a tessellation control shader and tessellation
300        *  evaluation shader."
301        */
302       if (_mesa_is_gles3(ctx) &&
303           ctx->TessEvalProgram._Current && !ctx->TessCtrlProgram._Current) {
304          _mesa_error(ctx, GL_INVALID_OPERATION,
305                      "%s(tess ctrl shader is missing)", function);
306          return false;
307       }
308       break;
309 
310    case API_OPENGL_CORE:
311       /* Section 10.4 (Drawing Commands Using Vertex Arrays) of the OpenGL 4.5
312        * Core Profile spec says:
313        *
314        *     "An INVALID_OPERATION error is generated if no vertex array
315        *     object is bound (see section 10.3.1)."
316        */
317       if (ctx->Array.VAO == ctx->Array.DefaultVAO) {
318          _mesa_error(ctx, GL_INVALID_OPERATION, "%s(no VAO bound)", function);
319          return false;
320       }
321       break;
322 
323    case API_OPENGLES:
324    case API_OPENGL_COMPAT:
325       break;
326 
327    default:
328       unreachable("Invalid API value in check_valid_to_render()");
329    }
330 
331    return true;
332 }
333 
334 
335 /**
336  * Is 'mode' a valid value for glBegin(), glDrawArrays(), glDrawElements(),
337  * etc?  The set of legal values depends on whether geometry shaders/programs
338  * are supported.
339  * Note: This may be called during display list compilation.
340  */
341 bool
_mesa_is_valid_prim_mode(const struct gl_context * ctx,GLenum mode)342 _mesa_is_valid_prim_mode(const struct gl_context *ctx, GLenum mode)
343 {
344    /* The overwhelmingly common case is (mode <= GL_TRIANGLE_FAN).  Test that
345     * first and exit.  You would think that a switch-statement would be the
346     * right approach, but at least GCC 4.7.2 generates some pretty dire code
347     * for the common case.
348     */
349    if (likely(mode <= GL_TRIANGLE_FAN))
350       return true;
351 
352    if (mode <= GL_POLYGON)
353       return (ctx->API == API_OPENGL_COMPAT);
354 
355    if (mode <= GL_TRIANGLE_STRIP_ADJACENCY)
356       return _mesa_has_geometry_shaders(ctx);
357 
358    if (mode == GL_PATCHES)
359       return _mesa_has_tessellation(ctx);
360 
361    return false;
362 }
363 
364 
365 /**
366  * Is 'mode' a valid value for glBegin(), glDrawArrays(), glDrawElements(),
367  * etc?  Also, do additional checking related to transformation feedback.
368  * Note: this function cannot be called during glNewList(GL_COMPILE) because
369  * this code depends on current transform feedback state.
370  * Also, do additional checking related to tessellation shaders.
371  */
372 GLboolean
_mesa_valid_prim_mode(struct gl_context * ctx,GLenum mode,const char * name)373 _mesa_valid_prim_mode(struct gl_context *ctx, GLenum mode, const char *name)
374 {
375    bool valid_enum = _mesa_is_valid_prim_mode(ctx, mode);
376 
377    if (!valid_enum) {
378       _mesa_error(ctx, GL_INVALID_ENUM, "%s(mode=%x)", name, mode);
379       return GL_FALSE;
380    }
381 
382    /* From the OpenGL 4.5 specification, section 11.3.1:
383     *
384     * The error INVALID_OPERATION is generated if Begin, or any command that
385     * implicitly calls Begin, is called when a geometry shader is active and:
386     *
387     * * the input primitive type of the current geometry shader is
388     *   POINTS and <mode> is not POINTS,
389     *
390     * * the input primitive type of the current geometry shader is
391     *   LINES and <mode> is not LINES, LINE_STRIP, or LINE_LOOP,
392     *
393     * * the input primitive type of the current geometry shader is
394     *   TRIANGLES and <mode> is not TRIANGLES, TRIANGLE_STRIP or
395     *   TRIANGLE_FAN,
396     *
397     * * the input primitive type of the current geometry shader is
398     *   LINES_ADJACENCY_ARB and <mode> is not LINES_ADJACENCY_ARB or
399     *   LINE_STRIP_ADJACENCY_ARB, or
400     *
401     * * the input primitive type of the current geometry shader is
402     *   TRIANGLES_ADJACENCY_ARB and <mode> is not
403     *   TRIANGLES_ADJACENCY_ARB or TRIANGLE_STRIP_ADJACENCY_ARB.
404     *
405     * The GL spec doesn't mention any interaction with tessellation, which
406     * is clearly a spec bug. The same rule should apply, but instead of
407     * the draw primitive mode, the tessellation evaluation shader primitive
408     * mode should be used for the checking.
409    */
410    if (ctx->_Shader->CurrentProgram[MESA_SHADER_GEOMETRY]) {
411       const GLenum geom_mode =
412          ctx->_Shader->CurrentProgram[MESA_SHADER_GEOMETRY]->
413             info.gs.input_primitive;
414       struct gl_program *tes =
415          ctx->_Shader->CurrentProgram[MESA_SHADER_TESS_EVAL];
416       GLenum mode_before_gs = mode;
417 
418       if (tes) {
419          if (tes->info.tess.point_mode)
420             mode_before_gs = GL_POINTS;
421          else if (tes->info.tess.primitive_mode == GL_ISOLINES)
422             mode_before_gs = GL_LINES;
423          else
424             /* the GL_QUADS mode generates triangles too */
425             mode_before_gs = GL_TRIANGLES;
426       }
427 
428       switch (mode_before_gs) {
429       case GL_POINTS:
430          valid_enum = (geom_mode == GL_POINTS);
431          break;
432       case GL_LINES:
433       case GL_LINE_LOOP:
434       case GL_LINE_STRIP:
435          valid_enum = (geom_mode == GL_LINES);
436          break;
437       case GL_TRIANGLES:
438       case GL_TRIANGLE_STRIP:
439       case GL_TRIANGLE_FAN:
440          valid_enum = (geom_mode == GL_TRIANGLES);
441          break;
442       case GL_QUADS:
443       case GL_QUAD_STRIP:
444       case GL_POLYGON:
445          valid_enum = false;
446          break;
447       case GL_LINES_ADJACENCY:
448       case GL_LINE_STRIP_ADJACENCY:
449          valid_enum = (geom_mode == GL_LINES_ADJACENCY);
450          break;
451       case GL_TRIANGLES_ADJACENCY:
452       case GL_TRIANGLE_STRIP_ADJACENCY:
453          valid_enum = (geom_mode == GL_TRIANGLES_ADJACENCY);
454          break;
455       default:
456          valid_enum = false;
457          break;
458       }
459       if (!valid_enum) {
460          _mesa_error(ctx, GL_INVALID_OPERATION,
461                      "%s(mode=%s vs geometry shader input %s)",
462                      name,
463                      _mesa_lookup_prim_by_nr(mode_before_gs),
464                      _mesa_lookup_prim_by_nr(geom_mode));
465          return GL_FALSE;
466       }
467    }
468 
469    /* From the OpenGL 4.0 (Core Profile) spec (section 2.12):
470     *
471     *     "Tessellation operates only on patch primitives. If tessellation is
472     *      active, any command that transfers vertices to the GL will
473     *      generate an INVALID_OPERATION error if the primitive mode is not
474     *      PATCHES.
475     *      Patch primitives are not supported by pipeline stages below the
476     *      tessellation evaluation shader. If there is no active program
477     *      object or the active program object does not contain a tessellation
478     *      evaluation shader, the error INVALID_OPERATION is generated by any
479     *      command that transfers vertices to the GL if the primitive mode is
480     *      PATCHES."
481     *
482     */
483    if (ctx->_Shader->CurrentProgram[MESA_SHADER_TESS_EVAL] ||
484        ctx->_Shader->CurrentProgram[MESA_SHADER_TESS_CTRL]) {
485       if (mode != GL_PATCHES) {
486          _mesa_error(ctx, GL_INVALID_OPERATION,
487                      "only GL_PATCHES valid with tessellation");
488          return GL_FALSE;
489       }
490    }
491    else {
492       if (mode == GL_PATCHES) {
493          _mesa_error(ctx, GL_INVALID_OPERATION,
494                      "GL_PATCHES only valid with tessellation");
495          return GL_FALSE;
496       }
497    }
498 
499    /* From the GL_EXT_transform_feedback spec:
500     *
501     *     "The error INVALID_OPERATION is generated if Begin, or any command
502     *      that performs an explicit Begin, is called when:
503     *
504     *      * a geometry shader is not active and <mode> does not match the
505     *        allowed begin modes for the current transform feedback state as
506     *        given by table X.1.
507     *
508     *      * a geometry shader is active and the output primitive type of the
509     *        geometry shader does not match the allowed begin modes for the
510     *        current transform feedback state as given by table X.1.
511     *
512     */
513    if (_mesa_is_xfb_active_and_unpaused(ctx)) {
514       GLboolean pass = GL_TRUE;
515 
516       if(ctx->_Shader->CurrentProgram[MESA_SHADER_GEOMETRY]) {
517          switch (ctx->_Shader->CurrentProgram[MESA_SHADER_GEOMETRY]->
518                     info.gs.output_primitive) {
519          case GL_POINTS:
520             pass = ctx->TransformFeedback.Mode == GL_POINTS;
521             break;
522          case GL_LINE_STRIP:
523             pass = ctx->TransformFeedback.Mode == GL_LINES;
524             break;
525          case GL_TRIANGLE_STRIP:
526             pass = ctx->TransformFeedback.Mode == GL_TRIANGLES;
527             break;
528          default:
529             pass = GL_FALSE;
530          }
531       }
532       else if (ctx->_Shader->CurrentProgram[MESA_SHADER_TESS_EVAL]) {
533          struct gl_program *tes =
534             ctx->_Shader->CurrentProgram[MESA_SHADER_TESS_EVAL];
535          if (tes->info.tess.point_mode)
536             pass = ctx->TransformFeedback.Mode == GL_POINTS;
537          else if (tes->info.tess.primitive_mode == GL_ISOLINES)
538             pass = ctx->TransformFeedback.Mode == GL_LINES;
539          else
540             pass = ctx->TransformFeedback.Mode == GL_TRIANGLES;
541       }
542       else {
543          switch (mode) {
544          case GL_POINTS:
545             pass = ctx->TransformFeedback.Mode == GL_POINTS;
546             break;
547          case GL_LINES:
548          case GL_LINE_STRIP:
549          case GL_LINE_LOOP:
550             pass = ctx->TransformFeedback.Mode == GL_LINES;
551             break;
552          default:
553             pass = ctx->TransformFeedback.Mode == GL_TRIANGLES;
554             break;
555          }
556       }
557       if (!pass) {
558          _mesa_error(ctx, GL_INVALID_OPERATION,
559                          "%s(mode=%s vs transform feedback %s)",
560                          name,
561                          _mesa_lookup_prim_by_nr(mode),
562                          _mesa_lookup_prim_by_nr(ctx->TransformFeedback.Mode));
563          return GL_FALSE;
564       }
565    }
566 
567    /* From GL_INTEL_conservative_rasterization spec:
568     *
569     * The conservative rasterization option applies only to polygons with
570     * PolygonMode state set to FILL. Draw requests for polygons with different
571     * PolygonMode setting or for other primitive types (points/lines) generate
572     * INVALID_OPERATION error.
573     */
574    if (ctx->IntelConservativeRasterization) {
575       GLboolean pass = GL_TRUE;
576 
577       switch (mode) {
578       case GL_POINTS:
579       case GL_LINES:
580       case GL_LINE_LOOP:
581       case GL_LINE_STRIP:
582       case GL_LINES_ADJACENCY:
583       case GL_LINE_STRIP_ADJACENCY:
584          pass = GL_FALSE;
585          break;
586       case GL_TRIANGLES:
587       case GL_TRIANGLE_STRIP:
588       case GL_TRIANGLE_FAN:
589       case GL_QUADS:
590       case GL_QUAD_STRIP:
591       case GL_POLYGON:
592       case GL_TRIANGLES_ADJACENCY:
593       case GL_TRIANGLE_STRIP_ADJACENCY:
594          if (ctx->Polygon.FrontMode != GL_FILL ||
595              ctx->Polygon.BackMode != GL_FILL)
596             pass = GL_FALSE;
597          break;
598       default:
599          pass = GL_FALSE;
600       }
601       if (!pass) {
602          _mesa_error(ctx, GL_INVALID_OPERATION,
603                      "mode=%s invalid with GL_INTEL_conservative_rasterization",
604                      _mesa_lookup_prim_by_nr(mode));
605          return GL_FALSE;
606       }
607    }
608 
609    return GL_TRUE;
610 }
611 
612 /**
613  * Verify that the element type is valid.
614  *
615  * Generates \c GL_INVALID_ENUM and returns \c false if it is not.
616  */
617 static bool
valid_elements_type(struct gl_context * ctx,GLenum type,const char * name)618 valid_elements_type(struct gl_context *ctx, GLenum type, const char *name)
619 {
620    switch (type) {
621    case GL_UNSIGNED_BYTE:
622    case GL_UNSIGNED_SHORT:
623    case GL_UNSIGNED_INT:
624       return true;
625 
626    default:
627       _mesa_error(ctx, GL_INVALID_ENUM, "%s(type = %s)", name,
628                   _mesa_enum_to_string(type));
629       return false;
630    }
631 }
632 
633 static bool
validate_DrawElements_common(struct gl_context * ctx,GLenum mode,GLsizei count,GLenum type,const GLvoid * indices,const char * caller)634 validate_DrawElements_common(struct gl_context *ctx,
635                              GLenum mode, GLsizei count, GLenum type,
636                              const GLvoid *indices,
637                              const char *caller)
638 {
639    /* Section 2.14.2 (Transform Feedback Primitive Capture) of the OpenGL ES
640     * 3.1 spec says:
641     *
642     *   The error INVALID_OPERATION is also generated by DrawElements,
643     *   DrawElementsInstanced, and DrawRangeElements while transform feedback
644     *   is active and not paused, regardless of mode.
645     *
646     * The OES_geometry_shader_spec says:
647     *
648     *    Issues:
649     *
650     *    ...
651     *
652     *    (13) Does this extension change how transform feedback operates
653     *    compared to unextended OpenGL ES 3.0 or 3.1?
654     *
655     *    RESOLVED: Yes... Since we no longer require being able to predict how
656     *    much geometry will be generated, we also lift the restriction that
657     *    only DrawArray* commands are supported and also support the
658     *    DrawElements* commands for transform feedback.
659     *
660     * This should also be reflected in the body of the spec, but that appears
661     * to have been overlooked.  The body of the spec only explicitly allows
662     * the indirect versions.
663     */
664    if (_mesa_is_gles3(ctx) &&
665        !_mesa_has_OES_geometry_shader(ctx) &&
666        _mesa_is_xfb_active_and_unpaused(ctx)) {
667       _mesa_error(ctx, GL_INVALID_OPERATION,
668                   "%s(transform feedback active)", caller);
669       return false;
670    }
671 
672    if (count < 0) {
673       _mesa_error(ctx, GL_INVALID_VALUE, "%s(count)", caller);
674       return false;
675    }
676 
677    if (!_mesa_valid_prim_mode(ctx, mode, caller)) {
678       return false;
679    }
680 
681    if (!valid_elements_type(ctx, type, caller))
682       return false;
683 
684    if (!check_valid_to_render(ctx, caller))
685       return false;
686 
687    return true;
688 }
689 
690 /**
691  * Error checking for glDrawElements().  Includes parameter checking
692  * and VBO bounds checking.
693  * \return GL_TRUE if OK to render, GL_FALSE if error found
694  */
695 GLboolean
_mesa_validate_DrawElements(struct gl_context * ctx,GLenum mode,GLsizei count,GLenum type,const GLvoid * indices)696 _mesa_validate_DrawElements(struct gl_context *ctx,
697                             GLenum mode, GLsizei count, GLenum type,
698                             const GLvoid *indices)
699 {
700    FLUSH_CURRENT(ctx, 0);
701 
702    return validate_DrawElements_common(ctx, mode, count, type, indices,
703                                        "glDrawElements");
704 }
705 
706 
707 /**
708  * Error checking for glMultiDrawElements().  Includes parameter checking
709  * and VBO bounds checking.
710  * \return GL_TRUE if OK to render, GL_FALSE if error found
711  */
712 GLboolean
_mesa_validate_MultiDrawElements(struct gl_context * ctx,GLenum mode,const GLsizei * count,GLenum type,const GLvoid * const * indices,GLsizei primcount)713 _mesa_validate_MultiDrawElements(struct gl_context *ctx,
714                                  GLenum mode, const GLsizei *count,
715                                  GLenum type, const GLvoid * const *indices,
716                                  GLsizei primcount)
717 {
718    GLsizei i;
719 
720    FLUSH_CURRENT(ctx, 0);
721 
722    /*
723     * Section 2.3.1 (Errors) of the OpenGL 4.5 (Core Profile) spec says:
724     *
725     *    "If a negative number is provided where an argument of type sizei or
726     *     sizeiptr is specified, an INVALID_VALUE error is generated."
727     *
728     * and in the same section:
729     *
730     *    "In other cases, there are no side effects unless otherwise noted;
731     *     the command which generates the error is ignored so that it has no
732     *     effect on GL state or framebuffer contents."
733     *
734     * Hence, check both primcount and all the count[i].
735     */
736    if (primcount < 0) {
737       _mesa_error(ctx, GL_INVALID_VALUE,
738                   "glMultiDrawElements(primcount=%d)", primcount);
739       return GL_FALSE;
740    }
741 
742    for (i = 0; i < primcount; i++) {
743       if (count[i] < 0) {
744          _mesa_error(ctx, GL_INVALID_VALUE,
745                      "glMultiDrawElements(count)" );
746          return GL_FALSE;
747       }
748    }
749 
750    if (!_mesa_valid_prim_mode(ctx, mode, "glMultiDrawElements")) {
751       return GL_FALSE;
752    }
753 
754    if (!valid_elements_type(ctx, type, "glMultiDrawElements"))
755       return GL_FALSE;
756 
757    if (!check_valid_to_render(ctx, "glMultiDrawElements"))
758       return GL_FALSE;
759 
760    /* Not using a VBO for indices, so avoid NULL pointer derefs later.
761     */
762    if (!_mesa_is_bufferobj(ctx->Array.VAO->IndexBufferObj)) {
763       for (i = 0; i < primcount; i++) {
764          if (!indices[i])
765             return GL_FALSE;
766       }
767    }
768 
769    return GL_TRUE;
770 }
771 
772 
773 /**
774  * Error checking for glDrawRangeElements().  Includes parameter checking
775  * and VBO bounds checking.
776  * \return GL_TRUE if OK to render, GL_FALSE if error found
777  */
778 GLboolean
_mesa_validate_DrawRangeElements(struct gl_context * ctx,GLenum mode,GLuint start,GLuint end,GLsizei count,GLenum type,const GLvoid * indices)779 _mesa_validate_DrawRangeElements(struct gl_context *ctx, GLenum mode,
780                                  GLuint start, GLuint end,
781                                  GLsizei count, GLenum type,
782                                  const GLvoid *indices)
783 {
784    FLUSH_CURRENT(ctx, 0);
785 
786    if (end < start) {
787       _mesa_error(ctx, GL_INVALID_VALUE, "glDrawRangeElements(end<start)");
788       return GL_FALSE;
789    }
790 
791    return validate_DrawElements_common(ctx, mode, count, type, indices,
792                                        "glDrawRangeElements");
793 }
794 
795 
796 static bool
need_xfb_remaining_prims_check(const struct gl_context * ctx)797 need_xfb_remaining_prims_check(const struct gl_context *ctx)
798 {
799    /* From the GLES3 specification, section 2.14.2 (Transform Feedback
800     * Primitive Capture):
801     *
802     *   The error INVALID_OPERATION is generated by DrawArrays and
803     *   DrawArraysInstanced if recording the vertices of a primitive to the
804     *   buffer objects being used for transform feedback purposes would result
805     *   in either exceeding the limits of any buffer object’s size, or in
806     *   exceeding the end position offset + size − 1, as set by
807     *   BindBufferRange.
808     *
809     * This is in contrast to the behaviour of desktop GL, where the extra
810     * primitives are silently dropped from the transform feedback buffer.
811     *
812     * This text is removed in ES 3.2, presumably because it's not really
813     * implementable with geometry and tessellation shaders.  In fact,
814     * the OES_geometry_shader spec says:
815     *
816     *    "(13) Does this extension change how transform feedback operates
817     *     compared to unextended OpenGL ES 3.0 or 3.1?
818     *
819     *     RESOLVED: Yes. Because dynamic geometry amplification in a geometry
820     *     shader can make it difficult if not impossible to predict the amount
821     *     of geometry that may be generated in advance of executing the shader,
822     *     the draw-time error for transform feedback buffer overflow conditions
823     *     is removed and replaced with the GL behavior (primitives are not
824     *     written and the corresponding counter is not updated)..."
825     */
826    return _mesa_is_gles3(ctx) && _mesa_is_xfb_active_and_unpaused(ctx) &&
827           !_mesa_has_OES_geometry_shader(ctx) &&
828           !_mesa_has_OES_tessellation_shader(ctx);
829 }
830 
831 
832 static bool
validate_draw_arrays(struct gl_context * ctx,const char * func,GLenum mode,GLsizei count,GLsizei numInstances)833 validate_draw_arrays(struct gl_context *ctx, const char *func,
834                      GLenum mode, GLsizei count, GLsizei numInstances)
835 {
836    FLUSH_CURRENT(ctx, 0);
837 
838    if (count < 0) {
839       _mesa_error(ctx, GL_INVALID_VALUE, "%s(count)", func);
840       return false;
841    }
842 
843    if (!_mesa_valid_prim_mode(ctx, mode, func))
844       return false;
845 
846    if (!check_valid_to_render(ctx, func))
847       return false;
848 
849    if (need_xfb_remaining_prims_check(ctx)) {
850       struct gl_transform_feedback_object *xfb_obj
851          = ctx->TransformFeedback.CurrentObject;
852       size_t prim_count = vbo_count_tessellated_primitives(mode, count, numInstances);
853       if (xfb_obj->GlesRemainingPrims < prim_count) {
854          _mesa_error(ctx, GL_INVALID_OPERATION,
855                      "%s(exceeds transform feedback size)", func);
856          return false;
857       }
858       xfb_obj->GlesRemainingPrims -= prim_count;
859    }
860 
861    if (count == 0)
862       return false;
863 
864    return true;
865 }
866 
867 /**
868  * Called from the tnl module to error check the function parameters and
869  * verify that we really can draw something.
870  * \return GL_TRUE if OK to render, GL_FALSE if error found
871  */
872 GLboolean
_mesa_validate_DrawArrays(struct gl_context * ctx,GLenum mode,GLsizei count)873 _mesa_validate_DrawArrays(struct gl_context *ctx, GLenum mode, GLsizei count)
874 {
875    return validate_draw_arrays(ctx, "glDrawArrays", mode, count, 1);
876 }
877 
878 
879 GLboolean
_mesa_validate_DrawArraysInstanced(struct gl_context * ctx,GLenum mode,GLint first,GLsizei count,GLsizei numInstances)880 _mesa_validate_DrawArraysInstanced(struct gl_context *ctx, GLenum mode, GLint first,
881                                    GLsizei count, GLsizei numInstances)
882 {
883    if (first < 0) {
884       _mesa_error(ctx, GL_INVALID_VALUE,
885                   "glDrawArraysInstanced(start=%d)", first);
886       return GL_FALSE;
887    }
888 
889    if (numInstances <= 0) {
890       if (numInstances < 0)
891          _mesa_error(ctx, GL_INVALID_VALUE,
892                      "glDrawArraysInstanced(numInstances=%d)", numInstances);
893       return GL_FALSE;
894    }
895 
896    return validate_draw_arrays(ctx, "glDrawArraysInstanced", mode, count, 1);
897 }
898 
899 
900 /**
901  * Called to error check the function parameters.
902  *
903  * Note that glMultiDrawArrays is not part of GLES, so there's limited scope
904  * for sharing code with the validation of glDrawArrays.
905  */
906 bool
_mesa_validate_MultiDrawArrays(struct gl_context * ctx,GLenum mode,const GLsizei * count,GLsizei primcount)907 _mesa_validate_MultiDrawArrays(struct gl_context *ctx, GLenum mode,
908                                const GLsizei *count, GLsizei primcount)
909 {
910    int i;
911 
912    FLUSH_CURRENT(ctx, 0);
913 
914    if (!_mesa_valid_prim_mode(ctx, mode, "glMultiDrawArrays"))
915       return false;
916 
917    if (!check_valid_to_render(ctx, "glMultiDrawArrays"))
918       return false;
919 
920    if (primcount < 0) {
921       _mesa_error(ctx, GL_INVALID_VALUE, "glMultiDrawArrays(primcount=%d)",
922                   primcount);
923       return false;
924    }
925 
926    for (i = 0; i < primcount; ++i) {
927       if (count[i] < 0) {
928          _mesa_error(ctx, GL_INVALID_VALUE, "glMultiDrawArrays(count[%d]=%d)",
929                      i, count[i]);
930          return false;
931       }
932    }
933 
934    if (need_xfb_remaining_prims_check(ctx)) {
935       struct gl_transform_feedback_object *xfb_obj
936          = ctx->TransformFeedback.CurrentObject;
937       size_t xfb_prim_count = 0;
938 
939       for (i = 0; i < primcount; ++i)
940          xfb_prim_count += vbo_count_tessellated_primitives(mode, count[i], 1);
941 
942       if (xfb_obj->GlesRemainingPrims < xfb_prim_count) {
943          _mesa_error(ctx, GL_INVALID_OPERATION,
944                      "glMultiDrawArrays(exceeds transform feedback size)");
945          return false;
946       }
947       xfb_obj->GlesRemainingPrims -= xfb_prim_count;
948    }
949 
950    return true;
951 }
952 
953 
954 GLboolean
_mesa_validate_DrawElementsInstanced(struct gl_context * ctx,GLenum mode,GLsizei count,GLenum type,const GLvoid * indices,GLsizei numInstances)955 _mesa_validate_DrawElementsInstanced(struct gl_context *ctx,
956                                      GLenum mode, GLsizei count, GLenum type,
957                                      const GLvoid *indices, GLsizei numInstances)
958 {
959    FLUSH_CURRENT(ctx, 0);
960 
961    if (numInstances < 0) {
962       _mesa_error(ctx, GL_INVALID_VALUE,
963                   "glDrawElementsInstanced(numInstances=%d)", numInstances);
964       return GL_FALSE;
965    }
966 
967    return validate_DrawElements_common(ctx, mode, count, type, indices,
968                                        "glDrawElementsInstanced")
969       && (numInstances > 0);
970 }
971 
972 
973 GLboolean
_mesa_validate_DrawTransformFeedback(struct gl_context * ctx,GLenum mode,struct gl_transform_feedback_object * obj,GLuint stream,GLsizei numInstances)974 _mesa_validate_DrawTransformFeedback(struct gl_context *ctx,
975                                      GLenum mode,
976                                      struct gl_transform_feedback_object *obj,
977                                      GLuint stream,
978                                      GLsizei numInstances)
979 {
980    FLUSH_CURRENT(ctx, 0);
981 
982    if (!_mesa_valid_prim_mode(ctx, mode, "glDrawTransformFeedback*(mode)")) {
983       return GL_FALSE;
984    }
985 
986    if (!obj) {
987       _mesa_error(ctx, GL_INVALID_VALUE, "glDrawTransformFeedback*(name)");
988       return GL_FALSE;
989    }
990 
991    /* From the GL 4.5 specification, page 429:
992     * "An INVALID_VALUE error is generated if id is not the name of a
993     *  transform feedback object."
994     */
995    if (!obj->EverBound) {
996       _mesa_error(ctx, GL_INVALID_VALUE, "glDrawTransformFeedback*(name)");
997       return GL_FALSE;
998    }
999 
1000    if (stream >= ctx->Const.MaxVertexStreams) {
1001       _mesa_error(ctx, GL_INVALID_VALUE,
1002                   "glDrawTransformFeedbackStream*(index>=MaxVertexStream)");
1003       return GL_FALSE;
1004    }
1005 
1006    if (!obj->EndedAnytime) {
1007       _mesa_error(ctx, GL_INVALID_OPERATION, "glDrawTransformFeedback*");
1008       return GL_FALSE;
1009    }
1010 
1011    if (numInstances <= 0) {
1012       if (numInstances < 0)
1013          _mesa_error(ctx, GL_INVALID_VALUE,
1014                      "glDrawTransformFeedback*Instanced(numInstances=%d)",
1015                      numInstances);
1016       return GL_FALSE;
1017    }
1018 
1019    if (!check_valid_to_render(ctx, "glDrawTransformFeedback*")) {
1020       return GL_FALSE;
1021    }
1022 
1023    return GL_TRUE;
1024 }
1025 
1026 static GLboolean
valid_draw_indirect(struct gl_context * ctx,GLenum mode,const GLvoid * indirect,GLsizei size,const char * name)1027 valid_draw_indirect(struct gl_context *ctx,
1028                     GLenum mode, const GLvoid *indirect,
1029                     GLsizei size, const char *name)
1030 {
1031    const uint64_t end = (uint64_t) (uintptr_t) indirect + size;
1032 
1033    /* OpenGL ES 3.1 spec. section 10.5:
1034     *
1035     *      "DrawArraysIndirect requires that all data sourced for the
1036     *      command, including the DrawArraysIndirectCommand
1037     *      structure,  be in buffer objects,  and may not be called when
1038     *      the default vertex array object is bound."
1039     */
1040    if (ctx->Array.VAO == ctx->Array.DefaultVAO) {
1041       _mesa_error(ctx, GL_INVALID_OPERATION, "(no VAO bound)");
1042       return GL_FALSE;
1043    }
1044 
1045    /* From OpenGL ES 3.1 spec. section 10.5:
1046     *     "An INVALID_OPERATION error is generated if zero is bound to
1047     *     VERTEX_ARRAY_BINDING, DRAW_INDIRECT_BUFFER or to any enabled
1048     *     vertex array."
1049     *
1050     * Here we check that for each enabled vertex array we have a vertex
1051     * buffer bound.
1052     */
1053    if (_mesa_is_gles31(ctx) &&
1054        ctx->Array.VAO->_Enabled & ~ctx->Array.VAO->VertexAttribBufferMask) {
1055       _mesa_error(ctx, GL_INVALID_OPERATION, "%s(No VBO bound)", name);
1056       return GL_FALSE;
1057    }
1058 
1059    if (!_mesa_valid_prim_mode(ctx, mode, name))
1060       return GL_FALSE;
1061 
1062    /* OpenGL ES 3.1 specification, section 10.5:
1063     *
1064     *      "An INVALID_OPERATION error is generated if
1065     *      transform feedback is active and not paused."
1066     *
1067     * The OES_geometry_shader spec says:
1068     *
1069     *    On p. 250 in the errors section for the DrawArraysIndirect command,
1070     *    and on p. 254 in the errors section for the DrawElementsIndirect
1071     *    command, delete the errors which state:
1072     *
1073     *    "An INVALID_OPERATION error is generated if transform feedback is
1074     *    active and not paused."
1075     *
1076     *    (thus allowing transform feedback to work with indirect draw commands).
1077     */
1078    if (_mesa_is_gles31(ctx) && !ctx->Extensions.OES_geometry_shader &&
1079        _mesa_is_xfb_active_and_unpaused(ctx)) {
1080       _mesa_error(ctx, GL_INVALID_OPERATION,
1081                   "%s(TransformFeedback is active and not paused)", name);
1082    }
1083 
1084    /* From OpenGL version 4.4. section 10.5
1085     * and OpenGL ES 3.1, section 10.6:
1086     *
1087     *      "An INVALID_VALUE error is generated if indirect is not a
1088     *       multiple of the size, in basic machine units, of uint."
1089     */
1090    if ((GLsizeiptr)indirect & (sizeof(GLuint) - 1)) {
1091       _mesa_error(ctx, GL_INVALID_VALUE,
1092                   "%s(indirect is not aligned)", name);
1093       return GL_FALSE;
1094    }
1095 
1096    if (!_mesa_is_bufferobj(ctx->DrawIndirectBuffer)) {
1097       _mesa_error(ctx, GL_INVALID_OPERATION,
1098                   "%s: no buffer bound to DRAW_INDIRECT_BUFFER", name);
1099       return GL_FALSE;
1100    }
1101 
1102    if (_mesa_check_disallowed_mapping(ctx->DrawIndirectBuffer)) {
1103       _mesa_error(ctx, GL_INVALID_OPERATION,
1104                   "%s(DRAW_INDIRECT_BUFFER is mapped)", name);
1105       return GL_FALSE;
1106    }
1107 
1108    /* From the ARB_draw_indirect specification:
1109     * "An INVALID_OPERATION error is generated if the commands source data
1110     *  beyond the end of the buffer object [...]"
1111     */
1112    if (ctx->DrawIndirectBuffer->Size < end) {
1113       _mesa_error(ctx, GL_INVALID_OPERATION,
1114                   "%s(DRAW_INDIRECT_BUFFER too small)", name);
1115       return GL_FALSE;
1116    }
1117 
1118    if (!check_valid_to_render(ctx, name))
1119       return GL_FALSE;
1120 
1121    return GL_TRUE;
1122 }
1123 
1124 static inline GLboolean
valid_draw_indirect_elements(struct gl_context * ctx,GLenum mode,GLenum type,const GLvoid * indirect,GLsizeiptr size,const char * name)1125 valid_draw_indirect_elements(struct gl_context *ctx,
1126                              GLenum mode, GLenum type, const GLvoid *indirect,
1127                              GLsizeiptr size, const char *name)
1128 {
1129    if (!valid_elements_type(ctx, type, name))
1130       return GL_FALSE;
1131 
1132    /*
1133     * Unlike regular DrawElementsInstancedBaseVertex commands, the indices
1134     * may not come from a client array and must come from an index buffer.
1135     * If no element array buffer is bound, an INVALID_OPERATION error is
1136     * generated.
1137     */
1138    if (!_mesa_is_bufferobj(ctx->Array.VAO->IndexBufferObj)) {
1139       _mesa_error(ctx, GL_INVALID_OPERATION,
1140                   "%s(no buffer bound to GL_ELEMENT_ARRAY_BUFFER)", name);
1141       return GL_FALSE;
1142    }
1143 
1144    return valid_draw_indirect(ctx, mode, indirect, size, name);
1145 }
1146 
1147 static inline GLboolean
valid_draw_indirect_multi(struct gl_context * ctx,GLsizei primcount,GLsizei stride,const char * name)1148 valid_draw_indirect_multi(struct gl_context *ctx,
1149                           GLsizei primcount, GLsizei stride,
1150                           const char *name)
1151 {
1152 
1153    /* From the ARB_multi_draw_indirect specification:
1154     * "INVALID_VALUE is generated by MultiDrawArraysIndirect or
1155     *  MultiDrawElementsIndirect if <primcount> is negative."
1156     *
1157     * "<primcount> must be positive, otherwise an INVALID_VALUE error will
1158     *  be generated."
1159     */
1160    if (primcount < 0) {
1161       _mesa_error(ctx, GL_INVALID_VALUE, "%s(primcount < 0)", name);
1162       return GL_FALSE;
1163    }
1164 
1165 
1166    /* From the ARB_multi_draw_indirect specification:
1167     * "<stride> must be a multiple of four, otherwise an INVALID_VALUE
1168     *  error is generated."
1169     */
1170    if (stride % 4) {
1171       _mesa_error(ctx, GL_INVALID_VALUE, "%s(stride %% 4)", name);
1172       return GL_FALSE;
1173    }
1174 
1175    return GL_TRUE;
1176 }
1177 
1178 GLboolean
_mesa_validate_DrawArraysIndirect(struct gl_context * ctx,GLenum mode,const GLvoid * indirect)1179 _mesa_validate_DrawArraysIndirect(struct gl_context *ctx,
1180                                   GLenum mode,
1181                                   const GLvoid *indirect)
1182 {
1183    const unsigned drawArraysNumParams = 4;
1184 
1185    FLUSH_CURRENT(ctx, 0);
1186 
1187    return valid_draw_indirect(ctx, mode,
1188                               indirect, drawArraysNumParams * sizeof(GLuint),
1189                               "glDrawArraysIndirect");
1190 }
1191 
1192 GLboolean
_mesa_validate_DrawElementsIndirect(struct gl_context * ctx,GLenum mode,GLenum type,const GLvoid * indirect)1193 _mesa_validate_DrawElementsIndirect(struct gl_context *ctx,
1194                                     GLenum mode, GLenum type,
1195                                     const GLvoid *indirect)
1196 {
1197    const unsigned drawElementsNumParams = 5;
1198 
1199    FLUSH_CURRENT(ctx, 0);
1200 
1201    return valid_draw_indirect_elements(ctx, mode, type,
1202                                        indirect, drawElementsNumParams * sizeof(GLuint),
1203                                        "glDrawElementsIndirect");
1204 }
1205 
1206 GLboolean
_mesa_validate_MultiDrawArraysIndirect(struct gl_context * ctx,GLenum mode,const GLvoid * indirect,GLsizei primcount,GLsizei stride)1207 _mesa_validate_MultiDrawArraysIndirect(struct gl_context *ctx,
1208                                        GLenum mode,
1209                                        const GLvoid *indirect,
1210                                        GLsizei primcount, GLsizei stride)
1211 {
1212    GLsizeiptr size = 0;
1213    const unsigned drawArraysNumParams = 4;
1214 
1215    FLUSH_CURRENT(ctx, 0);
1216 
1217    /* caller has converted stride==0 to drawArraysNumParams * sizeof(GLuint) */
1218    assert(stride != 0);
1219 
1220    if (!valid_draw_indirect_multi(ctx, primcount, stride,
1221                                   "glMultiDrawArraysIndirect"))
1222       return GL_FALSE;
1223 
1224    /* number of bytes of the indirect buffer which will be read */
1225    size = primcount
1226       ? (primcount - 1) * stride + drawArraysNumParams * sizeof(GLuint)
1227       : 0;
1228 
1229    if (!valid_draw_indirect(ctx, mode, indirect, size,
1230                             "glMultiDrawArraysIndirect"))
1231       return GL_FALSE;
1232 
1233    return GL_TRUE;
1234 }
1235 
1236 GLboolean
_mesa_validate_MultiDrawElementsIndirect(struct gl_context * ctx,GLenum mode,GLenum type,const GLvoid * indirect,GLsizei primcount,GLsizei stride)1237 _mesa_validate_MultiDrawElementsIndirect(struct gl_context *ctx,
1238                                          GLenum mode, GLenum type,
1239                                          const GLvoid *indirect,
1240                                          GLsizei primcount, GLsizei stride)
1241 {
1242    GLsizeiptr size = 0;
1243    const unsigned drawElementsNumParams = 5;
1244 
1245    FLUSH_CURRENT(ctx, 0);
1246 
1247    /* caller has converted stride==0 to drawElementsNumParams * sizeof(GLuint) */
1248    assert(stride != 0);
1249 
1250    if (!valid_draw_indirect_multi(ctx, primcount, stride,
1251                                   "glMultiDrawElementsIndirect"))
1252       return GL_FALSE;
1253 
1254    /* number of bytes of the indirect buffer which will be read */
1255    size = primcount
1256       ? (primcount - 1) * stride + drawElementsNumParams * sizeof(GLuint)
1257       : 0;
1258 
1259    if (!valid_draw_indirect_elements(ctx, mode, type,
1260                                      indirect, size,
1261                                      "glMultiDrawElementsIndirect"))
1262       return GL_FALSE;
1263 
1264    return GL_TRUE;
1265 }
1266 
1267 static GLboolean
valid_draw_indirect_parameters(struct gl_context * ctx,const char * name,GLintptr drawcount)1268 valid_draw_indirect_parameters(struct gl_context *ctx,
1269                                const char *name,
1270                                GLintptr drawcount)
1271 {
1272    /* From the ARB_indirect_parameters specification:
1273     * "INVALID_VALUE is generated by MultiDrawArraysIndirectCountARB or
1274     *  MultiDrawElementsIndirectCountARB if <drawcount> is not a multiple of
1275     *  four."
1276     */
1277    if (drawcount & 3) {
1278       _mesa_error(ctx, GL_INVALID_VALUE,
1279                   "%s(drawcount is not a multiple of 4)", name);
1280       return GL_FALSE;
1281    }
1282 
1283    /* From the ARB_indirect_parameters specification:
1284     * "INVALID_OPERATION is generated by MultiDrawArraysIndirectCountARB or
1285     *  MultiDrawElementsIndirectCountARB if no buffer is bound to the
1286     *  PARAMETER_BUFFER_ARB binding point."
1287     */
1288    if (!_mesa_is_bufferobj(ctx->ParameterBuffer)) {
1289       _mesa_error(ctx, GL_INVALID_OPERATION,
1290                   "%s: no buffer bound to PARAMETER_BUFFER", name);
1291       return GL_FALSE;
1292    }
1293 
1294    if (_mesa_check_disallowed_mapping(ctx->ParameterBuffer)) {
1295       _mesa_error(ctx, GL_INVALID_OPERATION,
1296                   "%s(PARAMETER_BUFFER is mapped)", name);
1297       return GL_FALSE;
1298    }
1299 
1300    /* From the ARB_indirect_parameters specification:
1301     * "INVALID_OPERATION is generated by MultiDrawArraysIndirectCountARB or
1302     *  MultiDrawElementsIndirectCountARB if reading a <sizei> typed value
1303     *  from the buffer bound to the PARAMETER_BUFFER_ARB target at the offset
1304     *  specified by <drawcount> would result in an out-of-bounds access."
1305     */
1306    if (ctx->ParameterBuffer->Size < drawcount + sizeof(GLsizei)) {
1307       _mesa_error(ctx, GL_INVALID_OPERATION,
1308                   "%s(PARAMETER_BUFFER too small)", name);
1309       return GL_FALSE;
1310    }
1311 
1312    return GL_TRUE;
1313 }
1314 
1315 GLboolean
_mesa_validate_MultiDrawArraysIndirectCount(struct gl_context * ctx,GLenum mode,GLintptr indirect,GLintptr drawcount,GLsizei maxdrawcount,GLsizei stride)1316 _mesa_validate_MultiDrawArraysIndirectCount(struct gl_context *ctx,
1317                                             GLenum mode,
1318                                             GLintptr indirect,
1319                                             GLintptr drawcount,
1320                                             GLsizei maxdrawcount,
1321                                             GLsizei stride)
1322 {
1323    GLsizeiptr size = 0;
1324    const unsigned drawArraysNumParams = 4;
1325 
1326    FLUSH_CURRENT(ctx, 0);
1327 
1328    /* caller has converted stride==0 to drawArraysNumParams * sizeof(GLuint) */
1329    assert(stride != 0);
1330 
1331    if (!valid_draw_indirect_multi(ctx, maxdrawcount, stride,
1332                                   "glMultiDrawArraysIndirectCountARB"))
1333       return GL_FALSE;
1334 
1335    /* number of bytes of the indirect buffer which will be read */
1336    size = maxdrawcount
1337       ? (maxdrawcount - 1) * stride + drawArraysNumParams * sizeof(GLuint)
1338       : 0;
1339 
1340    if (!valid_draw_indirect(ctx, mode, (void *)indirect, size,
1341                             "glMultiDrawArraysIndirectCountARB"))
1342       return GL_FALSE;
1343 
1344    return valid_draw_indirect_parameters(
1345          ctx, "glMultiDrawArraysIndirectCountARB", drawcount);
1346 }
1347 
1348 GLboolean
_mesa_validate_MultiDrawElementsIndirectCount(struct gl_context * ctx,GLenum mode,GLenum type,GLintptr indirect,GLintptr drawcount,GLsizei maxdrawcount,GLsizei stride)1349 _mesa_validate_MultiDrawElementsIndirectCount(struct gl_context *ctx,
1350                                               GLenum mode, GLenum type,
1351                                               GLintptr indirect,
1352                                               GLintptr drawcount,
1353                                               GLsizei maxdrawcount,
1354                                               GLsizei stride)
1355 {
1356    GLsizeiptr size = 0;
1357    const unsigned drawElementsNumParams = 5;
1358 
1359    FLUSH_CURRENT(ctx, 0);
1360 
1361    /* caller has converted stride==0 to drawElementsNumParams * sizeof(GLuint) */
1362    assert(stride != 0);
1363 
1364    if (!valid_draw_indirect_multi(ctx, maxdrawcount, stride,
1365                                   "glMultiDrawElementsIndirectCountARB"))
1366       return GL_FALSE;
1367 
1368    /* number of bytes of the indirect buffer which will be read */
1369    size = maxdrawcount
1370       ? (maxdrawcount - 1) * stride + drawElementsNumParams * sizeof(GLuint)
1371       : 0;
1372 
1373    if (!valid_draw_indirect_elements(ctx, mode, type,
1374                                      (void *)indirect, size,
1375                                      "glMultiDrawElementsIndirectCountARB"))
1376       return GL_FALSE;
1377 
1378    return valid_draw_indirect_parameters(
1379          ctx, "glMultiDrawElementsIndirectCountARB", drawcount);
1380 }
1381