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