• 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 "draw_validate.h"
28 #include "arrayobj.h"
29 #include "bufferobj.h"
30 #include "context.h"
31 
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 "program/prog_print.h"
39 
40 
41 static bool
check_blend_func_error(struct gl_context * ctx)42 check_blend_func_error(struct gl_context *ctx)
43 {
44    /* The ARB_blend_func_extended spec's ERRORS section says:
45     *
46     *    "The error INVALID_OPERATION is generated by Begin or any procedure
47     *     that implicitly calls Begin if any draw buffer has a blend function
48     *     requiring the second color input (SRC1_COLOR, ONE_MINUS_SRC1_COLOR,
49     *     SRC1_ALPHA or ONE_MINUS_SRC1_ALPHA), and a framebuffer is bound that
50     *     has more than the value of MAX_DUAL_SOURCE_DRAW_BUFFERS-1 active
51     *     color attachements."
52     */
53    for (unsigned i = ctx->Const.MaxDualSourceDrawBuffers;
54 	i < ctx->DrawBuffer->_NumColorDrawBuffers;
55 	i++) {
56       if (ctx->Color.Blend[i]._UsesDualSrc) {
57 	 _mesa_error(ctx, GL_INVALID_OPERATION,
58 		     "dual source blend on illegal attachment");
59 	 return false;
60       }
61    }
62 
63    if (ctx->Color.BlendEnabled &&
64        ctx->Color._AdvancedBlendMode != BLEND_NONE) {
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 & BITFIELD_BIT(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 
309       /* From GL_EXT_color_buffer_float:
310        *
311        *     "Blending applies only if the color buffer has a fixed-point or
312        *     or floating-point format. If the color buffer has an integer
313        *     format, proceed to the next operation.  Furthermore, an
314        *     INVALID_OPERATION error is generated by DrawArrays and the other
315        *     drawing commands defined in section 2.8.3 (10.5 in ES 3.1) if
316        *     blending is enabled (see below) and any draw buffer has 32-bit
317        *     floating-point format components."
318        *
319        * However GL_EXT_float_blend removes this text.
320        */
321       if (!ctx->Extensions.EXT_float_blend &&
322           (ctx->DrawBuffer->_FP32Buffers & ctx->Color.BlendEnabled)) {
323          _mesa_error(ctx, GL_INVALID_OPERATION,
324                      "%s(32-bit float output + blending)", function);
325          return false;
326       }
327       break;
328 
329    case API_OPENGL_CORE:
330       /* Section 10.4 (Drawing Commands Using Vertex Arrays) of the OpenGL 4.5
331        * Core Profile spec says:
332        *
333        *     "An INVALID_OPERATION error is generated if no vertex array
334        *     object is bound (see section 10.3.1)."
335        */
336       if (ctx->Array.VAO == ctx->Array.DefaultVAO) {
337          _mesa_error(ctx, GL_INVALID_OPERATION, "%s(no VAO bound)", function);
338          return false;
339       }
340       break;
341 
342    case API_OPENGLES:
343    case API_OPENGL_COMPAT:
344       break;
345 
346    default:
347       unreachable("Invalid API value in check_valid_to_render()");
348    }
349 
350    return true;
351 }
352 
353 
354 /**
355  * Is 'mode' a valid value for glBegin(), glDrawArrays(), glDrawElements(),
356  * etc?  The set of legal values depends on whether geometry shaders/programs
357  * are supported.
358  * Note: This may be called during display list compilation.
359  */
360 bool
_mesa_is_valid_prim_mode(const struct gl_context * ctx,GLenum mode)361 _mesa_is_valid_prim_mode(const struct gl_context *ctx, GLenum mode)
362 {
363    /* The overwhelmingly common case is (mode <= GL_TRIANGLE_FAN).  Test that
364     * first and exit.  You would think that a switch-statement would be the
365     * right approach, but at least GCC 4.7.2 generates some pretty dire code
366     * for the common case.
367     */
368    if (likely(mode <= GL_TRIANGLE_FAN))
369       return true;
370 
371    if (mode <= GL_POLYGON)
372       return (ctx->API == API_OPENGL_COMPAT);
373 
374    if (mode <= GL_TRIANGLE_STRIP_ADJACENCY)
375       return _mesa_has_geometry_shaders(ctx);
376 
377    if (mode == GL_PATCHES)
378       return _mesa_has_tessellation(ctx);
379 
380    return false;
381 }
382 
383 
384 /**
385  * Is 'mode' a valid value for glBegin(), glDrawArrays(), glDrawElements(),
386  * etc?  Also, do additional checking related to transformation feedback.
387  * Note: this function cannot be called during glNewList(GL_COMPILE) because
388  * this code depends on current transform feedback state.
389  * Also, do additional checking related to tessellation shaders.
390  */
391 GLboolean
_mesa_valid_prim_mode(struct gl_context * ctx,GLenum mode,const char * name)392 _mesa_valid_prim_mode(struct gl_context *ctx, GLenum mode, const char *name)
393 {
394    bool valid_enum = _mesa_is_valid_prim_mode(ctx, mode);
395 
396    if (!valid_enum) {
397       _mesa_error(ctx, GL_INVALID_ENUM, "%s(mode=%x)", name, mode);
398       return GL_FALSE;
399    }
400 
401    /* From the OpenGL 4.5 specification, section 11.3.1:
402     *
403     * The error INVALID_OPERATION is generated if Begin, or any command that
404     * implicitly calls Begin, is called when a geometry shader is active and:
405     *
406     * * the input primitive type of the current geometry shader is
407     *   POINTS and <mode> is not POINTS,
408     *
409     * * the input primitive type of the current geometry shader is
410     *   LINES and <mode> is not LINES, LINE_STRIP, or LINE_LOOP,
411     *
412     * * the input primitive type of the current geometry shader is
413     *   TRIANGLES and <mode> is not TRIANGLES, TRIANGLE_STRIP or
414     *   TRIANGLE_FAN,
415     *
416     * * the input primitive type of the current geometry shader is
417     *   LINES_ADJACENCY_ARB and <mode> is not LINES_ADJACENCY_ARB or
418     *   LINE_STRIP_ADJACENCY_ARB, or
419     *
420     * * the input primitive type of the current geometry shader is
421     *   TRIANGLES_ADJACENCY_ARB and <mode> is not
422     *   TRIANGLES_ADJACENCY_ARB or TRIANGLE_STRIP_ADJACENCY_ARB.
423     *
424     * The GL spec doesn't mention any interaction with tessellation, which
425     * is clearly a spec bug. The same rule should apply, but instead of
426     * the draw primitive mode, the tessellation evaluation shader primitive
427     * mode should be used for the checking.
428    */
429    if (ctx->_Shader->CurrentProgram[MESA_SHADER_GEOMETRY]) {
430       const GLenum geom_mode =
431          ctx->_Shader->CurrentProgram[MESA_SHADER_GEOMETRY]->
432             info.gs.input_primitive;
433       struct gl_program *tes =
434          ctx->_Shader->CurrentProgram[MESA_SHADER_TESS_EVAL];
435       GLenum mode_before_gs = mode;
436 
437       if (tes) {
438          if (tes->info.tess.point_mode)
439             mode_before_gs = GL_POINTS;
440          else if (tes->info.tess.primitive_mode == GL_ISOLINES)
441             mode_before_gs = GL_LINES;
442          else
443             /* the GL_QUADS mode generates triangles too */
444             mode_before_gs = GL_TRIANGLES;
445       }
446 
447       switch (mode_before_gs) {
448       case GL_POINTS:
449          valid_enum = (geom_mode == GL_POINTS);
450          break;
451       case GL_LINES:
452       case GL_LINE_LOOP:
453       case GL_LINE_STRIP:
454          valid_enum = (geom_mode == GL_LINES);
455          break;
456       case GL_TRIANGLES:
457       case GL_TRIANGLE_STRIP:
458       case GL_TRIANGLE_FAN:
459          valid_enum = (geom_mode == GL_TRIANGLES);
460          break;
461       case GL_QUADS:
462       case GL_QUAD_STRIP:
463       case GL_POLYGON:
464          valid_enum = false;
465          break;
466       case GL_LINES_ADJACENCY:
467       case GL_LINE_STRIP_ADJACENCY:
468          valid_enum = (geom_mode == GL_LINES_ADJACENCY);
469          break;
470       case GL_TRIANGLES_ADJACENCY:
471       case GL_TRIANGLE_STRIP_ADJACENCY:
472          valid_enum = (geom_mode == GL_TRIANGLES_ADJACENCY);
473          break;
474       default:
475          valid_enum = false;
476          break;
477       }
478       if (!valid_enum) {
479          _mesa_error(ctx, GL_INVALID_OPERATION,
480                      "%s(mode=%s vs geometry shader input %s)",
481                      name,
482                      _mesa_lookup_prim_by_nr(mode_before_gs),
483                      _mesa_lookup_prim_by_nr(geom_mode));
484          return GL_FALSE;
485       }
486    }
487 
488    /* From the OpenGL 4.0 (Core Profile) spec (section 2.12):
489     *
490     *     "Tessellation operates only on patch primitives. If tessellation is
491     *      active, any command that transfers vertices to the GL will
492     *      generate an INVALID_OPERATION error if the primitive mode is not
493     *      PATCHES.
494     *      Patch primitives are not supported by pipeline stages below the
495     *      tessellation evaluation shader. If there is no active program
496     *      object or the active program object does not contain a tessellation
497     *      evaluation shader, the error INVALID_OPERATION is generated by any
498     *      command that transfers vertices to the GL if the primitive mode is
499     *      PATCHES."
500     *
501     */
502    if (ctx->_Shader->CurrentProgram[MESA_SHADER_TESS_EVAL] ||
503        ctx->_Shader->CurrentProgram[MESA_SHADER_TESS_CTRL]) {
504       if (mode != GL_PATCHES) {
505          _mesa_error(ctx, GL_INVALID_OPERATION,
506                      "only GL_PATCHES valid with tessellation");
507          return GL_FALSE;
508       }
509    }
510    else {
511       if (mode == GL_PATCHES) {
512          _mesa_error(ctx, GL_INVALID_OPERATION,
513                      "GL_PATCHES only valid with tessellation");
514          return GL_FALSE;
515       }
516    }
517 
518    /* From the GL_EXT_transform_feedback spec:
519     *
520     *     "The error INVALID_OPERATION is generated if Begin, or any command
521     *      that performs an explicit Begin, is called when:
522     *
523     *      * a geometry shader is not active and <mode> does not match the
524     *        allowed begin modes for the current transform feedback state as
525     *        given by table X.1.
526     *
527     *      * a geometry shader is active and the output primitive type of the
528     *        geometry shader does not match the allowed begin modes for the
529     *        current transform feedback state as given by table X.1.
530     *
531     */
532    if (_mesa_is_xfb_active_and_unpaused(ctx)) {
533       GLboolean pass = GL_TRUE;
534 
535       if(ctx->_Shader->CurrentProgram[MESA_SHADER_GEOMETRY]) {
536          switch (ctx->_Shader->CurrentProgram[MESA_SHADER_GEOMETRY]->
537                     info.gs.output_primitive) {
538          case GL_POINTS:
539             pass = ctx->TransformFeedback.Mode == GL_POINTS;
540             break;
541          case GL_LINE_STRIP:
542             pass = ctx->TransformFeedback.Mode == GL_LINES;
543             break;
544          case GL_TRIANGLE_STRIP:
545             pass = ctx->TransformFeedback.Mode == GL_TRIANGLES;
546             break;
547          default:
548             pass = GL_FALSE;
549          }
550       }
551       else if (ctx->_Shader->CurrentProgram[MESA_SHADER_TESS_EVAL]) {
552          struct gl_program *tes =
553             ctx->_Shader->CurrentProgram[MESA_SHADER_TESS_EVAL];
554          if (tes->info.tess.point_mode)
555             pass = ctx->TransformFeedback.Mode == GL_POINTS;
556          else if (tes->info.tess.primitive_mode == GL_ISOLINES)
557             pass = ctx->TransformFeedback.Mode == GL_LINES;
558          else
559             pass = ctx->TransformFeedback.Mode == GL_TRIANGLES;
560       }
561       else {
562          switch (mode) {
563          case GL_POINTS:
564             pass = ctx->TransformFeedback.Mode == GL_POINTS;
565             break;
566          case GL_LINES:
567          case GL_LINE_STRIP:
568          case GL_LINE_LOOP:
569             pass = ctx->TransformFeedback.Mode == GL_LINES;
570             break;
571          default:
572             pass = ctx->TransformFeedback.Mode == GL_TRIANGLES;
573             break;
574          }
575       }
576       if (!pass) {
577          _mesa_error(ctx, GL_INVALID_OPERATION,
578                          "%s(mode=%s vs transform feedback %s)",
579                          name,
580                          _mesa_lookup_prim_by_nr(mode),
581                          _mesa_lookup_prim_by_nr(ctx->TransformFeedback.Mode));
582          return GL_FALSE;
583       }
584    }
585 
586    /* From GL_INTEL_conservative_rasterization spec:
587     *
588     * The conservative rasterization option applies only to polygons with
589     * PolygonMode state set to FILL. Draw requests for polygons with different
590     * PolygonMode setting or for other primitive types (points/lines) generate
591     * INVALID_OPERATION error.
592     */
593    if (ctx->IntelConservativeRasterization) {
594       GLboolean pass = GL_TRUE;
595 
596       switch (mode) {
597       case GL_POINTS:
598       case GL_LINES:
599       case GL_LINE_LOOP:
600       case GL_LINE_STRIP:
601       case GL_LINES_ADJACENCY:
602       case GL_LINE_STRIP_ADJACENCY:
603          pass = GL_FALSE;
604          break;
605       case GL_TRIANGLES:
606       case GL_TRIANGLE_STRIP:
607       case GL_TRIANGLE_FAN:
608       case GL_QUADS:
609       case GL_QUAD_STRIP:
610       case GL_POLYGON:
611       case GL_TRIANGLES_ADJACENCY:
612       case GL_TRIANGLE_STRIP_ADJACENCY:
613          if (ctx->Polygon.FrontMode != GL_FILL ||
614              ctx->Polygon.BackMode != GL_FILL)
615             pass = GL_FALSE;
616          break;
617       default:
618          pass = GL_FALSE;
619       }
620       if (!pass) {
621          _mesa_error(ctx, GL_INVALID_OPERATION,
622                      "mode=%s invalid with GL_INTEL_conservative_rasterization",
623                      _mesa_lookup_prim_by_nr(mode));
624          return GL_FALSE;
625       }
626    }
627 
628    return GL_TRUE;
629 }
630 
631 /**
632  * Verify that the element type is valid.
633  *
634  * Generates \c GL_INVALID_ENUM and returns \c false if it is not.
635  */
636 static bool
valid_elements_type(struct gl_context * ctx,GLenum type,const char * name)637 valid_elements_type(struct gl_context *ctx, GLenum type, const char *name)
638 {
639    switch (type) {
640    case GL_UNSIGNED_BYTE:
641    case GL_UNSIGNED_SHORT:
642    case GL_UNSIGNED_INT:
643       return true;
644 
645    default:
646       _mesa_error(ctx, GL_INVALID_ENUM, "%s(type = %s)", name,
647                   _mesa_enum_to_string(type));
648       return false;
649    }
650 }
651 
652 static bool
validate_DrawElements_common(struct gl_context * ctx,GLenum mode,GLsizei count,GLenum type,const GLvoid * indices,const char * caller)653 validate_DrawElements_common(struct gl_context *ctx,
654                              GLenum mode, GLsizei count, GLenum type,
655                              const GLvoid *indices,
656                              const char *caller)
657 {
658    /* Section 2.14.2 (Transform Feedback Primitive Capture) of the OpenGL ES
659     * 3.1 spec says:
660     *
661     *   The error INVALID_OPERATION is also generated by DrawElements,
662     *   DrawElementsInstanced, and DrawRangeElements while transform feedback
663     *   is active and not paused, regardless of mode.
664     *
665     * The OES_geometry_shader_spec says:
666     *
667     *    Issues:
668     *
669     *    ...
670     *
671     *    (13) Does this extension change how transform feedback operates
672     *    compared to unextended OpenGL ES 3.0 or 3.1?
673     *
674     *    RESOLVED: Yes... Since we no longer require being able to predict how
675     *    much geometry will be generated, we also lift the restriction that
676     *    only DrawArray* commands are supported and also support the
677     *    DrawElements* commands for transform feedback.
678     *
679     * This should also be reflected in the body of the spec, but that appears
680     * to have been overlooked.  The body of the spec only explicitly allows
681     * the indirect versions.
682     */
683    if (_mesa_is_gles3(ctx) &&
684        !_mesa_has_OES_geometry_shader(ctx) &&
685        _mesa_is_xfb_active_and_unpaused(ctx)) {
686       _mesa_error(ctx, GL_INVALID_OPERATION,
687                   "%s(transform feedback active)", caller);
688       return false;
689    }
690 
691    if (count < 0) {
692       _mesa_error(ctx, GL_INVALID_VALUE, "%s(count)", caller);
693       return false;
694    }
695 
696    if (!_mesa_valid_prim_mode(ctx, mode, caller)) {
697       return false;
698    }
699 
700    if (!valid_elements_type(ctx, type, caller))
701       return false;
702 
703    if (!check_valid_to_render(ctx, caller))
704       return false;
705 
706    return true;
707 }
708 
709 /**
710  * Error checking for glDrawElements().  Includes parameter checking
711  * and VBO bounds checking.
712  * \return GL_TRUE if OK to render, GL_FALSE if error found
713  */
714 GLboolean
_mesa_validate_DrawElements(struct gl_context * ctx,GLenum mode,GLsizei count,GLenum type,const GLvoid * indices)715 _mesa_validate_DrawElements(struct gl_context *ctx,
716                             GLenum mode, GLsizei count, GLenum type,
717                             const GLvoid *indices)
718 {
719    return validate_DrawElements_common(ctx, mode, count, type, indices,
720                                        "glDrawElements");
721 }
722 
723 
724 /**
725  * Error checking for glMultiDrawElements().  Includes parameter checking
726  * and VBO bounds checking.
727  * \return GL_TRUE if OK to render, GL_FALSE if error found
728  */
729 GLboolean
_mesa_validate_MultiDrawElements(struct gl_context * ctx,GLenum mode,const GLsizei * count,GLenum type,const GLvoid * const * indices,GLsizei primcount)730 _mesa_validate_MultiDrawElements(struct gl_context *ctx,
731                                  GLenum mode, const GLsizei *count,
732                                  GLenum type, const GLvoid * const *indices,
733                                  GLsizei primcount)
734 {
735    GLsizei i;
736 
737    /*
738     * Section 2.3.1 (Errors) of the OpenGL 4.5 (Core Profile) spec says:
739     *
740     *    "If a negative number is provided where an argument of type sizei or
741     *     sizeiptr is specified, an INVALID_VALUE error is generated."
742     *
743     * and in the same section:
744     *
745     *    "In other cases, there are no side effects unless otherwise noted;
746     *     the command which generates the error is ignored so that it has no
747     *     effect on GL state or framebuffer contents."
748     *
749     * Hence, check both primcount and all the count[i].
750     */
751    if (primcount < 0) {
752       _mesa_error(ctx, GL_INVALID_VALUE,
753                   "glMultiDrawElements(primcount=%d)", primcount);
754       return GL_FALSE;
755    }
756 
757    for (i = 0; i < primcount; i++) {
758       if (count[i] < 0) {
759          _mesa_error(ctx, GL_INVALID_VALUE,
760                      "glMultiDrawElements(count)" );
761          return GL_FALSE;
762       }
763    }
764 
765    if (!_mesa_valid_prim_mode(ctx, mode, "glMultiDrawElements")) {
766       return GL_FALSE;
767    }
768 
769    if (!valid_elements_type(ctx, type, "glMultiDrawElements"))
770       return GL_FALSE;
771 
772    if (!check_valid_to_render(ctx, "glMultiDrawElements"))
773       return GL_FALSE;
774 
775    /* Not using a VBO for indices, so avoid NULL pointer derefs later.
776     */
777    if (!ctx->Array.VAO->IndexBufferObj) {
778       for (i = 0; i < primcount; i++) {
779          if (!indices[i])
780             return GL_FALSE;
781       }
782    }
783 
784    return GL_TRUE;
785 }
786 
787 
788 /**
789  * Error checking for glDrawRangeElements().  Includes parameter checking
790  * and VBO bounds checking.
791  * \return GL_TRUE if OK to render, GL_FALSE if error found
792  */
793 GLboolean
_mesa_validate_DrawRangeElements(struct gl_context * ctx,GLenum mode,GLuint start,GLuint end,GLsizei count,GLenum type,const GLvoid * indices)794 _mesa_validate_DrawRangeElements(struct gl_context *ctx, GLenum mode,
795                                  GLuint start, GLuint end,
796                                  GLsizei count, GLenum type,
797                                  const GLvoid *indices)
798 {
799    if (end < start) {
800       _mesa_error(ctx, GL_INVALID_VALUE, "glDrawRangeElements(end<start)");
801       return GL_FALSE;
802    }
803 
804    return validate_DrawElements_common(ctx, mode, count, type, indices,
805                                        "glDrawRangeElements");
806 }
807 
808 
809 static bool
need_xfb_remaining_prims_check(const struct gl_context * ctx)810 need_xfb_remaining_prims_check(const struct gl_context *ctx)
811 {
812    /* From the GLES3 specification, section 2.14.2 (Transform Feedback
813     * Primitive Capture):
814     *
815     *   The error INVALID_OPERATION is generated by DrawArrays and
816     *   DrawArraysInstanced if recording the vertices of a primitive to the
817     *   buffer objects being used for transform feedback purposes would result
818     *   in either exceeding the limits of any buffer object’s size, or in
819     *   exceeding the end position offset + size − 1, as set by
820     *   BindBufferRange.
821     *
822     * This is in contrast to the behaviour of desktop GL, where the extra
823     * primitives are silently dropped from the transform feedback buffer.
824     *
825     * This text is removed in ES 3.2, presumably because it's not really
826     * implementable with geometry and tessellation shaders.  In fact,
827     * the OES_geometry_shader spec says:
828     *
829     *    "(13) Does this extension change how transform feedback operates
830     *     compared to unextended OpenGL ES 3.0 or 3.1?
831     *
832     *     RESOLVED: Yes. Because dynamic geometry amplification in a geometry
833     *     shader can make it difficult if not impossible to predict the amount
834     *     of geometry that may be generated in advance of executing the shader,
835     *     the draw-time error for transform feedback buffer overflow conditions
836     *     is removed and replaced with the GL behavior (primitives are not
837     *     written and the corresponding counter is not updated)..."
838     */
839    return _mesa_is_gles3(ctx) && _mesa_is_xfb_active_and_unpaused(ctx) &&
840           !_mesa_has_OES_geometry_shader(ctx) &&
841           !_mesa_has_OES_tessellation_shader(ctx);
842 }
843 
844 
845 /**
846  * Figure out the number of transform feedback primitives that will be output
847  * considering the drawing mode, number of vertices, and instance count,
848  * assuming that no geometry shading is done and primitive restart is not
849  * used.
850  *
851  * This is used by driver back-ends in implementing the PRIMITIVES_GENERATED
852  * and TRANSFORM_FEEDBACK_PRIMITIVES_WRITTEN queries.  It is also used to
853  * pre-validate draw calls in GLES3 (where draw calls only succeed if there is
854  * enough room in the transform feedback buffer for the result).
855  */
856 static size_t
count_tessellated_primitives(GLenum mode,GLuint count,GLuint num_instances)857 count_tessellated_primitives(GLenum mode, GLuint count, GLuint num_instances)
858 {
859    size_t num_primitives;
860    switch (mode) {
861    case GL_POINTS:
862       num_primitives = count;
863       break;
864    case GL_LINE_STRIP:
865       num_primitives = count >= 2 ? count - 1 : 0;
866       break;
867    case GL_LINE_LOOP:
868       num_primitives = count >= 2 ? count : 0;
869       break;
870    case GL_LINES:
871       num_primitives = count / 2;
872       break;
873    case GL_TRIANGLE_STRIP:
874    case GL_TRIANGLE_FAN:
875    case GL_POLYGON:
876       num_primitives = count >= 3 ? count - 2 : 0;
877       break;
878    case GL_TRIANGLES:
879       num_primitives = count / 3;
880       break;
881    case GL_QUAD_STRIP:
882       num_primitives = count >= 4 ? ((count / 2) - 1) * 2 : 0;
883       break;
884    case GL_QUADS:
885       num_primitives = (count / 4) * 2;
886       break;
887    case GL_LINES_ADJACENCY:
888       num_primitives = count / 4;
889       break;
890    case GL_LINE_STRIP_ADJACENCY:
891       num_primitives = count >= 4 ? count - 3 : 0;
892       break;
893    case GL_TRIANGLES_ADJACENCY:
894       num_primitives = count / 6;
895       break;
896    case GL_TRIANGLE_STRIP_ADJACENCY:
897       num_primitives = count >= 6 ? (count - 4) / 2 : 0;
898       break;
899    default:
900       assert(!"Unexpected primitive type in count_tessellated_primitives");
901       num_primitives = 0;
902       break;
903    }
904    return num_primitives * num_instances;
905 }
906 
907 
908 static bool
validate_draw_arrays(struct gl_context * ctx,const char * func,GLenum mode,GLsizei count,GLsizei numInstances)909 validate_draw_arrays(struct gl_context *ctx, const char *func,
910                      GLenum mode, GLsizei count, GLsizei numInstances)
911 {
912    if (count < 0) {
913       _mesa_error(ctx, GL_INVALID_VALUE, "%s(count)", func);
914       return false;
915    }
916 
917    if (!_mesa_valid_prim_mode(ctx, mode, func))
918       return false;
919 
920    if (!check_valid_to_render(ctx, func))
921       return false;
922 
923    if (need_xfb_remaining_prims_check(ctx)) {
924       struct gl_transform_feedback_object *xfb_obj
925          = ctx->TransformFeedback.CurrentObject;
926       size_t prim_count = count_tessellated_primitives(mode, count, numInstances);
927       if (xfb_obj->GlesRemainingPrims < prim_count) {
928          _mesa_error(ctx, GL_INVALID_OPERATION,
929                      "%s(exceeds transform feedback size)", func);
930          return false;
931       }
932       xfb_obj->GlesRemainingPrims -= prim_count;
933    }
934 
935    if (count == 0)
936       return false;
937 
938    return true;
939 }
940 
941 /**
942  * Called from the tnl module to error check the function parameters and
943  * verify that we really can draw something.
944  * \return GL_TRUE if OK to render, GL_FALSE if error found
945  */
946 GLboolean
_mesa_validate_DrawArrays(struct gl_context * ctx,GLenum mode,GLsizei count)947 _mesa_validate_DrawArrays(struct gl_context *ctx, GLenum mode, GLsizei count)
948 {
949    return validate_draw_arrays(ctx, "glDrawArrays", mode, count, 1);
950 }
951 
952 
953 GLboolean
_mesa_validate_DrawArraysInstanced(struct gl_context * ctx,GLenum mode,GLint first,GLsizei count,GLsizei numInstances)954 _mesa_validate_DrawArraysInstanced(struct gl_context *ctx, GLenum mode, GLint first,
955                                    GLsizei count, GLsizei numInstances)
956 {
957    if (first < 0) {
958       _mesa_error(ctx, GL_INVALID_VALUE,
959                   "glDrawArraysInstanced(start=%d)", first);
960       return GL_FALSE;
961    }
962 
963    if (numInstances <= 0) {
964       if (numInstances < 0)
965          _mesa_error(ctx, GL_INVALID_VALUE,
966                      "glDrawArraysInstanced(numInstances=%d)", numInstances);
967       return GL_FALSE;
968    }
969 
970    return validate_draw_arrays(ctx, "glDrawArraysInstanced", mode, count, 1);
971 }
972 
973 
974 /**
975  * Called to error check the function parameters.
976  *
977  * Note that glMultiDrawArrays is not part of GLES, so there's limited scope
978  * for sharing code with the validation of glDrawArrays.
979  */
980 bool
_mesa_validate_MultiDrawArrays(struct gl_context * ctx,GLenum mode,const GLsizei * count,GLsizei primcount)981 _mesa_validate_MultiDrawArrays(struct gl_context *ctx, GLenum mode,
982                                const GLsizei *count, GLsizei primcount)
983 {
984    int i;
985 
986    if (!_mesa_valid_prim_mode(ctx, mode, "glMultiDrawArrays"))
987       return false;
988 
989    if (!check_valid_to_render(ctx, "glMultiDrawArrays"))
990       return false;
991 
992    if (primcount < 0) {
993       _mesa_error(ctx, GL_INVALID_VALUE, "glMultiDrawArrays(primcount=%d)",
994                   primcount);
995       return false;
996    }
997 
998    for (i = 0; i < primcount; ++i) {
999       if (count[i] < 0) {
1000          _mesa_error(ctx, GL_INVALID_VALUE, "glMultiDrawArrays(count[%d]=%d)",
1001                      i, count[i]);
1002          return false;
1003       }
1004    }
1005 
1006    if (need_xfb_remaining_prims_check(ctx)) {
1007       struct gl_transform_feedback_object *xfb_obj
1008          = ctx->TransformFeedback.CurrentObject;
1009       size_t xfb_prim_count = 0;
1010 
1011       for (i = 0; i < primcount; ++i)
1012          xfb_prim_count += count_tessellated_primitives(mode, count[i], 1);
1013 
1014       if (xfb_obj->GlesRemainingPrims < xfb_prim_count) {
1015          _mesa_error(ctx, GL_INVALID_OPERATION,
1016                      "glMultiDrawArrays(exceeds transform feedback size)");
1017          return false;
1018       }
1019       xfb_obj->GlesRemainingPrims -= xfb_prim_count;
1020    }
1021 
1022    return true;
1023 }
1024 
1025 
1026 GLboolean
_mesa_validate_DrawElementsInstanced(struct gl_context * ctx,GLenum mode,GLsizei count,GLenum type,const GLvoid * indices,GLsizei numInstances)1027 _mesa_validate_DrawElementsInstanced(struct gl_context *ctx,
1028                                      GLenum mode, GLsizei count, GLenum type,
1029                                      const GLvoid *indices, GLsizei numInstances)
1030 {
1031    if (numInstances < 0) {
1032       _mesa_error(ctx, GL_INVALID_VALUE,
1033                   "glDrawElementsInstanced(numInstances=%d)", numInstances);
1034       return GL_FALSE;
1035    }
1036 
1037    return validate_DrawElements_common(ctx, mode, count, type, indices,
1038                                        "glDrawElementsInstanced")
1039       && (numInstances > 0);
1040 }
1041 
1042 
1043 GLboolean
_mesa_validate_DrawTransformFeedback(struct gl_context * ctx,GLenum mode,struct gl_transform_feedback_object * obj,GLuint stream,GLsizei numInstances)1044 _mesa_validate_DrawTransformFeedback(struct gl_context *ctx,
1045                                      GLenum mode,
1046                                      struct gl_transform_feedback_object *obj,
1047                                      GLuint stream,
1048                                      GLsizei numInstances)
1049 {
1050    if (!_mesa_valid_prim_mode(ctx, mode, "glDrawTransformFeedback*(mode)")) {
1051       return GL_FALSE;
1052    }
1053 
1054    if (!obj) {
1055       _mesa_error(ctx, GL_INVALID_VALUE, "glDrawTransformFeedback*(name)");
1056       return GL_FALSE;
1057    }
1058 
1059    /* From the GL 4.5 specification, page 429:
1060     * "An INVALID_VALUE error is generated if id is not the name of a
1061     *  transform feedback object."
1062     */
1063    if (!obj->EverBound) {
1064       _mesa_error(ctx, GL_INVALID_VALUE, "glDrawTransformFeedback*(name)");
1065       return GL_FALSE;
1066    }
1067 
1068    if (stream >= ctx->Const.MaxVertexStreams) {
1069       _mesa_error(ctx, GL_INVALID_VALUE,
1070                   "glDrawTransformFeedbackStream*(index>=MaxVertexStream)");
1071       return GL_FALSE;
1072    }
1073 
1074    if (!obj->EndedAnytime) {
1075       _mesa_error(ctx, GL_INVALID_OPERATION, "glDrawTransformFeedback*");
1076       return GL_FALSE;
1077    }
1078 
1079    if (numInstances <= 0) {
1080       if (numInstances < 0)
1081          _mesa_error(ctx, GL_INVALID_VALUE,
1082                      "glDrawTransformFeedback*Instanced(numInstances=%d)",
1083                      numInstances);
1084       return GL_FALSE;
1085    }
1086 
1087    if (!check_valid_to_render(ctx, "glDrawTransformFeedback*")) {
1088       return GL_FALSE;
1089    }
1090 
1091    return GL_TRUE;
1092 }
1093 
1094 static GLboolean
valid_draw_indirect(struct gl_context * ctx,GLenum mode,const GLvoid * indirect,GLsizei size,const char * name)1095 valid_draw_indirect(struct gl_context *ctx,
1096                     GLenum mode, const GLvoid *indirect,
1097                     GLsizei size, const char *name)
1098 {
1099    const uint64_t end = (uint64_t) (uintptr_t) indirect + size;
1100 
1101    /* OpenGL ES 3.1 spec. section 10.5:
1102     *
1103     *      "DrawArraysIndirect requires that all data sourced for the
1104     *      command, including the DrawArraysIndirectCommand
1105     *      structure,  be in buffer objects,  and may not be called when
1106     *      the default vertex array object is bound."
1107     */
1108    if (ctx->API != API_OPENGL_COMPAT &&
1109        ctx->Array.VAO == ctx->Array.DefaultVAO) {
1110       _mesa_error(ctx, GL_INVALID_OPERATION, "(no VAO bound)");
1111       return GL_FALSE;
1112    }
1113 
1114    /* From OpenGL ES 3.1 spec. section 10.5:
1115     *     "An INVALID_OPERATION error is generated if zero is bound to
1116     *     VERTEX_ARRAY_BINDING, DRAW_INDIRECT_BUFFER or to any enabled
1117     *     vertex array."
1118     *
1119     * Here we check that for each enabled vertex array we have a vertex
1120     * buffer bound.
1121     */
1122    if (_mesa_is_gles31(ctx) &&
1123        ctx->Array.VAO->Enabled & ~ctx->Array.VAO->VertexAttribBufferMask) {
1124       _mesa_error(ctx, GL_INVALID_OPERATION, "%s(No VBO bound)", name);
1125       return GL_FALSE;
1126    }
1127 
1128    if (!_mesa_valid_prim_mode(ctx, mode, name))
1129       return GL_FALSE;
1130 
1131    /* OpenGL ES 3.1 specification, section 10.5:
1132     *
1133     *      "An INVALID_OPERATION error is generated if
1134     *      transform feedback is active and not paused."
1135     *
1136     * The OES_geometry_shader spec says:
1137     *
1138     *    On p. 250 in the errors section for the DrawArraysIndirect command,
1139     *    and on p. 254 in the errors section for the DrawElementsIndirect
1140     *    command, delete the errors which state:
1141     *
1142     *    "An INVALID_OPERATION error is generated if transform feedback is
1143     *    active and not paused."
1144     *
1145     *    (thus allowing transform feedback to work with indirect draw commands).
1146     */
1147    if (_mesa_is_gles31(ctx) && !ctx->Extensions.OES_geometry_shader &&
1148        _mesa_is_xfb_active_and_unpaused(ctx)) {
1149       _mesa_error(ctx, GL_INVALID_OPERATION,
1150                   "%s(TransformFeedback is active and not paused)", name);
1151    }
1152 
1153    /* From OpenGL version 4.4. section 10.5
1154     * and OpenGL ES 3.1, section 10.6:
1155     *
1156     *      "An INVALID_VALUE error is generated if indirect is not a
1157     *       multiple of the size, in basic machine units, of uint."
1158     */
1159    if ((GLsizeiptr)indirect & (sizeof(GLuint) - 1)) {
1160       _mesa_error(ctx, GL_INVALID_VALUE,
1161                   "%s(indirect is not aligned)", name);
1162       return GL_FALSE;
1163    }
1164 
1165    if (!ctx->DrawIndirectBuffer) {
1166       _mesa_error(ctx, GL_INVALID_OPERATION,
1167                   "%s: no buffer bound to DRAW_INDIRECT_BUFFER", name);
1168       return GL_FALSE;
1169    }
1170 
1171    if (_mesa_check_disallowed_mapping(ctx->DrawIndirectBuffer)) {
1172       _mesa_error(ctx, GL_INVALID_OPERATION,
1173                   "%s(DRAW_INDIRECT_BUFFER is mapped)", name);
1174       return GL_FALSE;
1175    }
1176 
1177    /* From the ARB_draw_indirect specification:
1178     * "An INVALID_OPERATION error is generated if the commands source data
1179     *  beyond the end of the buffer object [...]"
1180     */
1181    if (ctx->DrawIndirectBuffer->Size < end) {
1182       _mesa_error(ctx, GL_INVALID_OPERATION,
1183                   "%s(DRAW_INDIRECT_BUFFER too small)", name);
1184       return GL_FALSE;
1185    }
1186 
1187    if (!check_valid_to_render(ctx, name))
1188       return GL_FALSE;
1189 
1190    return GL_TRUE;
1191 }
1192 
1193 static inline GLboolean
valid_draw_indirect_elements(struct gl_context * ctx,GLenum mode,GLenum type,const GLvoid * indirect,GLsizeiptr size,const char * name)1194 valid_draw_indirect_elements(struct gl_context *ctx,
1195                              GLenum mode, GLenum type, const GLvoid *indirect,
1196                              GLsizeiptr size, const char *name)
1197 {
1198    if (!valid_elements_type(ctx, type, name))
1199       return GL_FALSE;
1200 
1201    /*
1202     * Unlike regular DrawElementsInstancedBaseVertex commands, the indices
1203     * may not come from a client array and must come from an index buffer.
1204     * If no element array buffer is bound, an INVALID_OPERATION error is
1205     * generated.
1206     */
1207    if (!ctx->Array.VAO->IndexBufferObj) {
1208       _mesa_error(ctx, GL_INVALID_OPERATION,
1209                   "%s(no buffer bound to GL_ELEMENT_ARRAY_BUFFER)", name);
1210       return GL_FALSE;
1211    }
1212 
1213    return valid_draw_indirect(ctx, mode, indirect, size, name);
1214 }
1215 
1216 GLboolean
_mesa_valid_draw_indirect_multi(struct gl_context * ctx,GLsizei primcount,GLsizei stride,const char * name)1217 _mesa_valid_draw_indirect_multi(struct gl_context *ctx,
1218                                 GLsizei primcount, GLsizei stride,
1219                                 const char *name)
1220 {
1221 
1222    /* From the ARB_multi_draw_indirect specification:
1223     * "INVALID_VALUE is generated by MultiDrawArraysIndirect or
1224     *  MultiDrawElementsIndirect if <primcount> is negative."
1225     *
1226     * "<primcount> must be positive, otherwise an INVALID_VALUE error will
1227     *  be generated."
1228     */
1229    if (primcount < 0) {
1230       _mesa_error(ctx, GL_INVALID_VALUE, "%s(primcount < 0)", name);
1231       return GL_FALSE;
1232    }
1233 
1234 
1235    /* From the ARB_multi_draw_indirect specification:
1236     * "<stride> must be a multiple of four, otherwise an INVALID_VALUE
1237     *  error is generated."
1238     */
1239    if (stride % 4) {
1240       _mesa_error(ctx, GL_INVALID_VALUE, "%s(stride %% 4)", name);
1241       return GL_FALSE;
1242    }
1243 
1244    return GL_TRUE;
1245 }
1246 
1247 GLboolean
_mesa_validate_DrawArraysIndirect(struct gl_context * ctx,GLenum mode,const GLvoid * indirect)1248 _mesa_validate_DrawArraysIndirect(struct gl_context *ctx,
1249                                   GLenum mode,
1250                                   const GLvoid *indirect)
1251 {
1252    const unsigned drawArraysNumParams = 4;
1253 
1254    return valid_draw_indirect(ctx, mode,
1255                               indirect, drawArraysNumParams * sizeof(GLuint),
1256                               "glDrawArraysIndirect");
1257 }
1258 
1259 GLboolean
_mesa_validate_DrawElementsIndirect(struct gl_context * ctx,GLenum mode,GLenum type,const GLvoid * indirect)1260 _mesa_validate_DrawElementsIndirect(struct gl_context *ctx,
1261                                     GLenum mode, GLenum type,
1262                                     const GLvoid *indirect)
1263 {
1264    const unsigned drawElementsNumParams = 5;
1265 
1266    return valid_draw_indirect_elements(ctx, mode, type,
1267                                        indirect, drawElementsNumParams * sizeof(GLuint),
1268                                        "glDrawElementsIndirect");
1269 }
1270 
1271 GLboolean
_mesa_validate_MultiDrawArraysIndirect(struct gl_context * ctx,GLenum mode,const GLvoid * indirect,GLsizei primcount,GLsizei stride)1272 _mesa_validate_MultiDrawArraysIndirect(struct gl_context *ctx,
1273                                        GLenum mode,
1274                                        const GLvoid *indirect,
1275                                        GLsizei primcount, GLsizei stride)
1276 {
1277    GLsizeiptr size = 0;
1278    const unsigned drawArraysNumParams = 4;
1279 
1280    /* caller has converted stride==0 to drawArraysNumParams * sizeof(GLuint) */
1281    assert(stride != 0);
1282 
1283    if (!_mesa_valid_draw_indirect_multi(ctx, primcount, stride,
1284                                         "glMultiDrawArraysIndirect"))
1285       return GL_FALSE;
1286 
1287    /* number of bytes of the indirect buffer which will be read */
1288    size = primcount
1289       ? (primcount - 1) * stride + drawArraysNumParams * sizeof(GLuint)
1290       : 0;
1291 
1292    if (!valid_draw_indirect(ctx, mode, indirect, size,
1293                             "glMultiDrawArraysIndirect"))
1294       return GL_FALSE;
1295 
1296    return GL_TRUE;
1297 }
1298 
1299 GLboolean
_mesa_validate_MultiDrawElementsIndirect(struct gl_context * ctx,GLenum mode,GLenum type,const GLvoid * indirect,GLsizei primcount,GLsizei stride)1300 _mesa_validate_MultiDrawElementsIndirect(struct gl_context *ctx,
1301                                          GLenum mode, GLenum type,
1302                                          const GLvoid *indirect,
1303                                          GLsizei primcount, GLsizei stride)
1304 {
1305    GLsizeiptr size = 0;
1306    const unsigned drawElementsNumParams = 5;
1307 
1308    /* caller has converted stride==0 to drawElementsNumParams * sizeof(GLuint) */
1309    assert(stride != 0);
1310 
1311    if (!_mesa_valid_draw_indirect_multi(ctx, primcount, stride,
1312                                         "glMultiDrawElementsIndirect"))
1313       return GL_FALSE;
1314 
1315    /* number of bytes of the indirect buffer which will be read */
1316    size = primcount
1317       ? (primcount - 1) * stride + drawElementsNumParams * sizeof(GLuint)
1318       : 0;
1319 
1320    if (!valid_draw_indirect_elements(ctx, mode, type,
1321                                      indirect, size,
1322                                      "glMultiDrawElementsIndirect"))
1323       return GL_FALSE;
1324 
1325    return GL_TRUE;
1326 }
1327 
1328 static GLboolean
valid_draw_indirect_parameters(struct gl_context * ctx,const char * name,GLintptr drawcount)1329 valid_draw_indirect_parameters(struct gl_context *ctx,
1330                                const char *name,
1331                                GLintptr drawcount)
1332 {
1333    /* From the ARB_indirect_parameters specification:
1334     * "INVALID_VALUE is generated by MultiDrawArraysIndirectCountARB or
1335     *  MultiDrawElementsIndirectCountARB if <drawcount> is not a multiple of
1336     *  four."
1337     */
1338    if (drawcount & 3) {
1339       _mesa_error(ctx, GL_INVALID_VALUE,
1340                   "%s(drawcount is not a multiple of 4)", name);
1341       return GL_FALSE;
1342    }
1343 
1344    /* From the ARB_indirect_parameters specification:
1345     * "INVALID_OPERATION is generated by MultiDrawArraysIndirectCountARB or
1346     *  MultiDrawElementsIndirectCountARB if no buffer is bound to the
1347     *  PARAMETER_BUFFER_ARB binding point."
1348     */
1349    if (!ctx->ParameterBuffer) {
1350       _mesa_error(ctx, GL_INVALID_OPERATION,
1351                   "%s: no buffer bound to PARAMETER_BUFFER", name);
1352       return GL_FALSE;
1353    }
1354 
1355    if (_mesa_check_disallowed_mapping(ctx->ParameterBuffer)) {
1356       _mesa_error(ctx, GL_INVALID_OPERATION,
1357                   "%s(PARAMETER_BUFFER is mapped)", name);
1358       return GL_FALSE;
1359    }
1360 
1361    /* From the ARB_indirect_parameters specification:
1362     * "INVALID_OPERATION is generated by MultiDrawArraysIndirectCountARB or
1363     *  MultiDrawElementsIndirectCountARB if reading a <sizei> typed value
1364     *  from the buffer bound to the PARAMETER_BUFFER_ARB target at the offset
1365     *  specified by <drawcount> would result in an out-of-bounds access."
1366     */
1367    if (ctx->ParameterBuffer->Size < drawcount + sizeof(GLsizei)) {
1368       _mesa_error(ctx, GL_INVALID_OPERATION,
1369                   "%s(PARAMETER_BUFFER too small)", name);
1370       return GL_FALSE;
1371    }
1372 
1373    return GL_TRUE;
1374 }
1375 
1376 GLboolean
_mesa_validate_MultiDrawArraysIndirectCount(struct gl_context * ctx,GLenum mode,GLintptr indirect,GLintptr drawcount,GLsizei maxdrawcount,GLsizei stride)1377 _mesa_validate_MultiDrawArraysIndirectCount(struct gl_context *ctx,
1378                                             GLenum mode,
1379                                             GLintptr indirect,
1380                                             GLintptr drawcount,
1381                                             GLsizei maxdrawcount,
1382                                             GLsizei stride)
1383 {
1384    GLsizeiptr size = 0;
1385    const unsigned drawArraysNumParams = 4;
1386 
1387    /* caller has converted stride==0 to drawArraysNumParams * sizeof(GLuint) */
1388    assert(stride != 0);
1389 
1390    if (!_mesa_valid_draw_indirect_multi(ctx, maxdrawcount, stride,
1391                                         "glMultiDrawArraysIndirectCountARB"))
1392       return GL_FALSE;
1393 
1394    /* number of bytes of the indirect buffer which will be read */
1395    size = maxdrawcount
1396       ? (maxdrawcount - 1) * stride + drawArraysNumParams * sizeof(GLuint)
1397       : 0;
1398 
1399    if (!valid_draw_indirect(ctx, mode, (void *)indirect, size,
1400                             "glMultiDrawArraysIndirectCountARB"))
1401       return GL_FALSE;
1402 
1403    return valid_draw_indirect_parameters(
1404          ctx, "glMultiDrawArraysIndirectCountARB", drawcount);
1405 }
1406 
1407 GLboolean
_mesa_validate_MultiDrawElementsIndirectCount(struct gl_context * ctx,GLenum mode,GLenum type,GLintptr indirect,GLintptr drawcount,GLsizei maxdrawcount,GLsizei stride)1408 _mesa_validate_MultiDrawElementsIndirectCount(struct gl_context *ctx,
1409                                               GLenum mode, GLenum type,
1410                                               GLintptr indirect,
1411                                               GLintptr drawcount,
1412                                               GLsizei maxdrawcount,
1413                                               GLsizei stride)
1414 {
1415    GLsizeiptr size = 0;
1416    const unsigned drawElementsNumParams = 5;
1417 
1418    /* caller has converted stride==0 to drawElementsNumParams * sizeof(GLuint) */
1419    assert(stride != 0);
1420 
1421    if (!_mesa_valid_draw_indirect_multi(ctx, maxdrawcount, stride,
1422                                         "glMultiDrawElementsIndirectCountARB"))
1423       return GL_FALSE;
1424 
1425    /* number of bytes of the indirect buffer which will be read */
1426    size = maxdrawcount
1427       ? (maxdrawcount - 1) * stride + drawElementsNumParams * sizeof(GLuint)
1428       : 0;
1429 
1430    if (!valid_draw_indirect_elements(ctx, mode, type,
1431                                      (void *)indirect, size,
1432                                      "glMultiDrawElementsIndirectCountARB"))
1433       return GL_FALSE;
1434 
1435    return valid_draw_indirect_parameters(
1436          ctx, "glMultiDrawElementsIndirectCountARB", drawcount);
1437 }
1438