api_validate.c revision 467e3aa3de0e1f5b357975d35c1312f7566af577
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 * \return  number of bytes in array [count] of type.
40 */
41static GLsizei
42index_bytes(GLenum type, GLsizei count)
43{
44   if (type == GL_UNSIGNED_INT) {
45      return count * sizeof(GLuint);
46   }
47   else if (type == GL_UNSIGNED_BYTE) {
48      return count * sizeof(GLubyte);
49   }
50   else {
51      ASSERT(type == GL_UNSIGNED_SHORT);
52      return count * sizeof(GLushort);
53   }
54}
55
56
57/**
58 * Find the max index in the given element/index buffer
59 */
60GLuint
61_mesa_max_buffer_index(struct gl_context *ctx, GLuint count, GLenum type,
62                       const void *indices,
63                       struct gl_buffer_object *elementBuf)
64{
65   const GLubyte *map = NULL;
66   GLuint max = 0;
67   GLuint i;
68
69   if (_mesa_is_bufferobj(elementBuf)) {
70      /* elements are in a user-defined buffer object.  need to map it */
71      map = ctx->Driver.MapBufferRange(ctx, 0, elementBuf->Size,
72				       GL_MAP_READ_BIT, elementBuf);
73      /* Actual address is the sum of pointers */
74      indices = (const GLvoid *) ADD_POINTERS(map, (const GLubyte *) indices);
75   }
76
77   if (type == GL_UNSIGNED_INT) {
78      for (i = 0; i < count; i++)
79         if (((GLuint *) indices)[i] > max)
80            max = ((GLuint *) indices)[i];
81   }
82   else if (type == GL_UNSIGNED_SHORT) {
83      for (i = 0; i < count; i++)
84         if (((GLushort *) indices)[i] > max)
85            max = ((GLushort *) indices)[i];
86   }
87   else {
88      ASSERT(type == GL_UNSIGNED_BYTE);
89      for (i = 0; i < count; i++)
90         if (((GLubyte *) indices)[i] > max)
91            max = ((GLubyte *) indices)[i];
92   }
93
94   if (map) {
95      ctx->Driver.UnmapBuffer(ctx, elementBuf);
96   }
97
98   return max;
99}
100
101
102/**
103 * Check if OK to draw arrays/elements.
104 */
105static GLboolean
106check_valid_to_render(struct gl_context *ctx, const char *function)
107{
108   if (!_mesa_valid_to_render(ctx, function)) {
109      return GL_FALSE;
110   }
111
112   switch (ctx->API) {
113   case API_OPENGLES2:
114      /* For ES2, we can draw if any vertex array is enabled (and we
115       * should always have a vertex program/shader). */
116      if (ctx->Array.ArrayObj->_Enabled == 0x0 || !ctx->VertexProgram._Current)
117	 return GL_FALSE;
118      break;
119
120   case API_OPENGLES:
121      /* For OpenGL ES, only draw if we have vertex positions
122       */
123      if (!ctx->Array.ArrayObj->VertexAttrib[VERT_ATTRIB_POS].Enabled)
124	 return GL_FALSE;
125      break;
126
127   case API_OPENGL_COMPAT:
128   case API_OPENGL_CORE:
129      {
130         const struct gl_shader_program *vsProg =
131            ctx->Shader.CurrentVertexProgram;
132         GLboolean haveVertexShader = (vsProg && vsProg->LinkStatus);
133         GLboolean haveVertexProgram = ctx->VertexProgram._Enabled;
134         if (haveVertexShader || haveVertexProgram) {
135            /* Draw regardless of whether or not we have any vertex arrays.
136             * (Ex: could draw a point using a constant vertex pos)
137             */
138            return GL_TRUE;
139         }
140         else {
141            /* Draw if we have vertex positions (GL_VERTEX_ARRAY or generic
142             * array [0]).
143             */
144            return (ctx->Array.ArrayObj->VertexAttrib[VERT_ATTRIB_POS].Enabled ||
145                    ctx->Array.ArrayObj->VertexAttrib[VERT_ATTRIB_GENERIC0].Enabled);
146         }
147      }
148      break;
149
150   default:
151      assert(!"Invalid API value in check_valid_to_render()");
152   }
153
154   return GL_TRUE;
155}
156
157
158/**
159 * Do bounds checking on array element indexes.  Check that the vertices
160 * pointed to by the indices don't lie outside buffer object bounds.
161 * \return GL_TRUE if OK, GL_FALSE if any indexed vertex goes is out of bounds
162 */
163static GLboolean
164check_index_bounds(struct gl_context *ctx, GLsizei count, GLenum type,
165		   const GLvoid *indices, GLint basevertex)
166{
167   struct _mesa_prim prim;
168   struct _mesa_index_buffer ib;
169   GLuint min, max;
170
171   /* Only the X Server needs to do this -- otherwise, accessing outside
172    * array/BO bounds allows application termination.
173    */
174   if (!ctx->Const.CheckArrayBounds)
175      return GL_TRUE;
176
177   memset(&prim, 0, sizeof(prim));
178   prim.count = count;
179
180   memset(&ib, 0, sizeof(ib));
181   ib.type = type;
182   ib.ptr = indices;
183   ib.obj = ctx->Array.ArrayObj->ElementArrayBufferObj;
184
185   vbo_get_minmax_indices(ctx, &prim, &ib, &min, &max, 1);
186
187   if ((int)(min + basevertex) < 0 ||
188       max + basevertex >= ctx->Array.ArrayObj->_MaxElement) {
189      /* the max element is out of bounds of one or more enabled arrays */
190      _mesa_warning(ctx, "glDrawElements() index=%u is out of bounds (max=%u)",
191                    max, ctx->Array.ArrayObj->_MaxElement);
192      return GL_FALSE;
193   }
194
195   return GL_TRUE;
196}
197
198
199/**
200 * Is 'mode' a valid value for glBegin(), glDrawArrays(), glDrawElements(),
201 * etc?  The set of legal values depends on whether geometry shaders/programs
202 * are supported.
203 * Note: This may be called during display list compilation.
204 */
205bool
206_mesa_is_valid_prim_mode(struct gl_context *ctx, GLenum mode)
207{
208   switch (mode) {
209   case GL_POINTS:
210   case GL_LINES:
211   case GL_LINE_LOOP:
212   case GL_LINE_STRIP:
213   case GL_TRIANGLES:
214   case GL_TRIANGLE_STRIP:
215   case GL_TRIANGLE_FAN:
216      return true;
217   case GL_QUADS:
218   case GL_QUAD_STRIP:
219   case GL_POLYGON:
220      return (ctx->API == API_OPENGL_COMPAT);
221   case GL_LINES_ADJACENCY:
222   case GL_LINE_STRIP_ADJACENCY:
223   case GL_TRIANGLES_ADJACENCY:
224   case GL_TRIANGLE_STRIP_ADJACENCY:
225      return _mesa_has_geometry_shaders(ctx);
226   default:
227      return false;
228   }
229}
230
231
232/**
233 * Is 'mode' a valid value for glBegin(), glDrawArrays(), glDrawElements(),
234 * etc?  Also, do additional checking related to transformation feedback.
235 * Note: this function cannot be called during glNewList(GL_COMPILE) because
236 * this code depends on current transform feedback state.
237 */
238GLboolean
239_mesa_valid_prim_mode(struct gl_context *ctx, GLenum mode, const char *name)
240{
241   bool valid_enum = _mesa_is_valid_prim_mode(ctx, mode);
242
243   if (!valid_enum) {
244      _mesa_error(ctx, GL_INVALID_ENUM, "%s(mode=%x)", name, mode);
245      return GL_FALSE;
246   }
247
248   /* From the ARB_geometry_shader4 spec:
249    *
250    * The error INVALID_OPERATION is generated if Begin, or any command that
251    * implicitly calls Begin, is called when a geometry shader is active and:
252    *
253    * * the input primitive type of the current geometry shader is
254    *   POINTS and <mode> is not POINTS,
255    *
256    * * the input primitive type of the current geometry shader is
257    *   LINES and <mode> is not LINES, LINE_STRIP, or LINE_LOOP,
258    *
259    * * the input primitive type of the current geometry shader is
260    *   TRIANGLES and <mode> is not TRIANGLES, TRIANGLE_STRIP or
261    *   TRIANGLE_FAN,
262    *
263    * * the input primitive type of the current geometry shader is
264    *   LINES_ADJACENCY_ARB and <mode> is not LINES_ADJACENCY_ARB or
265    *   LINE_STRIP_ADJACENCY_ARB, or
266    *
267    * * the input primitive type of the current geometry shader is
268    *   TRIANGLES_ADJACENCY_ARB and <mode> is not
269    *   TRIANGLES_ADJACENCY_ARB or TRIANGLE_STRIP_ADJACENCY_ARB.
270    *
271   */
272   if (ctx->Shader.CurrentGeometryProgram) {
273      const GLenum geom_mode =
274         ctx->Shader.CurrentGeometryProgram->Geom.InputType;
275      switch (mode) {
276      case GL_POINTS:
277         valid_enum = (geom_mode == GL_POINTS);
278         break;
279      case GL_LINES:
280      case GL_LINE_LOOP:
281      case GL_LINE_STRIP:
282         valid_enum = (geom_mode == GL_LINES);
283         break;
284      case GL_TRIANGLES:
285      case GL_TRIANGLE_STRIP:
286      case GL_TRIANGLE_FAN:
287         valid_enum = (geom_mode == GL_TRIANGLES);
288         break;
289      case GL_QUADS:
290      case GL_QUAD_STRIP:
291      case GL_POLYGON:
292         valid_enum = false;
293         break;
294      case GL_LINES_ADJACENCY:
295      case GL_LINE_STRIP_ADJACENCY:
296         valid_enum = (geom_mode == GL_LINES_ADJACENCY);
297         break;
298      case GL_TRIANGLES_ADJACENCY:
299      case GL_TRIANGLE_STRIP_ADJACENCY:
300         valid_enum = (geom_mode == GL_TRIANGLES_ADJACENCY);
301         break;
302      default:
303         valid_enum = false;
304         break;
305      }
306      if (!valid_enum) {
307         _mesa_error(ctx, GL_INVALID_OPERATION,
308                     "%s(mode=%s vs geometry shader input %s)",
309                     name,
310                     _mesa_lookup_prim_by_nr(mode),
311                     _mesa_lookup_prim_by_nr(geom_mode));
312         return GL_FALSE;
313      }
314   }
315
316   /* From the GL_EXT_transform_feedback spec:
317    *
318    *     "The error INVALID_OPERATION is generated if Begin, or any command
319    *      that performs an explicit Begin, is called when:
320    *
321    *      * a geometry shader is not active and <mode> does not match the
322    *        allowed begin modes for the current transform feedback state as
323    *        given by table X.1.
324    *
325    *      * a geometry shader is active and the output primitive type of the
326    *        geometry shader does not match the allowed begin modes for the
327    *        current transform feedback state as given by table X.1.
328    *
329    */
330   if (_mesa_is_xfb_active_and_unpaused(ctx)) {
331      GLboolean pass = GL_TRUE;
332
333      if(ctx->Shader.CurrentGeometryProgram) {
334         switch (ctx->Shader.CurrentGeometryProgram->Geom.OutputType) {
335         case GL_POINTS:
336            pass = ctx->TransformFeedback.Mode == GL_POINTS;
337            break;
338         case GL_LINE_STRIP:
339            pass = ctx->TransformFeedback.Mode == GL_LINES;
340            break;
341         case GL_TRIANGLE_STRIP:
342            pass = ctx->TransformFeedback.Mode == GL_TRIANGLES;
343            break;
344         default:
345            pass = GL_FALSE;
346         }
347      }
348      else {
349         switch (mode) {
350         case GL_POINTS:
351            pass = ctx->TransformFeedback.Mode == GL_POINTS;
352            break;
353         case GL_LINES:
354         case GL_LINE_STRIP:
355         case GL_LINE_LOOP:
356            pass = ctx->TransformFeedback.Mode == GL_LINES;
357            break;
358         default:
359            pass = ctx->TransformFeedback.Mode == GL_TRIANGLES;
360            break;
361         }
362      }
363      if (!pass) {
364         _mesa_error(ctx, GL_INVALID_OPERATION,
365	                 "%s(mode=%s vs transform feedback %s)",
366	                 name,
367	                 _mesa_lookup_prim_by_nr(mode),
368	                 _mesa_lookup_prim_by_nr(ctx->TransformFeedback.Mode));
369         return GL_FALSE;
370      }
371   }
372
373   return GL_TRUE;
374}
375
376/**
377 * Verify that the element type is valid.
378 *
379 * Generates \c GL_INVALID_ENUM and returns \c false if it is not.
380 */
381static bool
382valid_elements_type(struct gl_context *ctx, GLenum type, const char *name)
383{
384   switch (type) {
385   case GL_UNSIGNED_BYTE:
386   case GL_UNSIGNED_SHORT:
387   case GL_UNSIGNED_INT:
388      return true;
389
390   default:
391      _mesa_error(ctx, GL_INVALID_ENUM, "%s(type = %s)", name,
392                  _mesa_lookup_enum_by_nr(type));
393      return false;
394   }
395}
396
397/**
398 * Error checking for glDrawElements().  Includes parameter checking
399 * and VBO bounds checking.
400 * \return GL_TRUE if OK to render, GL_FALSE if error found
401 */
402GLboolean
403_mesa_validate_DrawElements(struct gl_context *ctx,
404			    GLenum mode, GLsizei count, GLenum type,
405			    const GLvoid *indices, GLint basevertex)
406{
407   FLUSH_CURRENT(ctx, 0);
408
409   /* From the GLES3 specification, section 2.14.2 (Transform Feedback
410    * Primitive Capture):
411    *
412    *   The error INVALID_OPERATION is also generated by DrawElements,
413    *   DrawElementsInstanced, and DrawRangeElements while transform feedback
414    *   is active and not paused, regardless of mode.
415    */
416   if (_mesa_is_gles3(ctx) && _mesa_is_xfb_active_and_unpaused(ctx)) {
417      _mesa_error(ctx, GL_INVALID_OPERATION,
418                  "glDrawElements(transform feedback active)");
419      return GL_FALSE;
420   }
421
422   if (count < 0) {
423      _mesa_error(ctx, GL_INVALID_VALUE, "glDrawElements(count)" );
424      return GL_FALSE;
425   }
426
427   if (!_mesa_valid_prim_mode(ctx, mode, "glDrawElements")) {
428      return GL_FALSE;
429   }
430
431   if (!valid_elements_type(ctx, type, "glDrawElements"))
432      return GL_FALSE;
433
434   if (!check_valid_to_render(ctx, "glDrawElements"))
435      return GL_FALSE;
436
437   /* Vertex buffer object tests */
438   if (_mesa_is_bufferobj(ctx->Array.ArrayObj->ElementArrayBufferObj)) {
439      /* use indices in the buffer object */
440      /* make sure count doesn't go outside buffer bounds */
441      if (index_bytes(type, count) > ctx->Array.ArrayObj->ElementArrayBufferObj->Size) {
442         _mesa_warning(ctx, "glDrawElements index out of buffer bounds");
443         return GL_FALSE;
444      }
445   }
446   else {
447      /* not using a VBO */
448      if (!indices)
449         return GL_FALSE;
450   }
451
452   if (!check_index_bounds(ctx, count, type, indices, basevertex))
453      return GL_FALSE;
454
455   if (count == 0)
456      return GL_FALSE;
457
458   return GL_TRUE;
459}
460
461
462/**
463 * Error checking for glMultiDrawElements().  Includes parameter checking
464 * and VBO bounds checking.
465 * \return GL_TRUE if OK to render, GL_FALSE if error found
466 */
467GLboolean
468_mesa_validate_MultiDrawElements(struct gl_context *ctx,
469                                 GLenum mode, const GLsizei *count,
470                                 GLenum type, const GLvoid * const *indices,
471                                 GLuint primcount, const GLint *basevertex)
472{
473   unsigned i;
474
475   FLUSH_CURRENT(ctx, 0);
476
477   for (i = 0; i < primcount; i++) {
478      if (count[i] < 0) {
479         _mesa_error(ctx, GL_INVALID_VALUE,
480                     "glMultiDrawElements(count)" );
481         return GL_FALSE;
482      }
483   }
484
485   if (!_mesa_valid_prim_mode(ctx, mode, "glMultiDrawElements")) {
486      return GL_FALSE;
487   }
488
489   if (!valid_elements_type(ctx, type, "glMultiDrawElements"))
490      return GL_FALSE;
491
492   if (!check_valid_to_render(ctx, "glMultiDrawElements"))
493      return GL_FALSE;
494
495   /* Vertex buffer object tests */
496   if (_mesa_is_bufferobj(ctx->Array.ArrayObj->ElementArrayBufferObj)) {
497      /* use indices in the buffer object */
498      /* make sure count doesn't go outside buffer bounds */
499      for (i = 0; i < primcount; i++) {
500         if (index_bytes(type, count[i]) >
501             ctx->Array.ArrayObj->ElementArrayBufferObj->Size) {
502            _mesa_warning(ctx,
503                          "glMultiDrawElements index out of buffer bounds");
504            return GL_FALSE;
505         }
506      }
507   }
508   else {
509      /* not using a VBO */
510      for (i = 0; i < primcount; i++) {
511         if (!indices[i])
512            return GL_FALSE;
513      }
514   }
515
516   for (i = 0; i < primcount; i++) {
517      if (!check_index_bounds(ctx, count[i], type, indices[i],
518                              basevertex ? basevertex[i] : 0))
519         return GL_FALSE;
520   }
521
522   return GL_TRUE;
523}
524
525
526/**
527 * Error checking for glDrawRangeElements().  Includes parameter checking
528 * and VBO bounds checking.
529 * \return GL_TRUE if OK to render, GL_FALSE if error found
530 */
531GLboolean
532_mesa_validate_DrawRangeElements(struct gl_context *ctx, GLenum mode,
533				 GLuint start, GLuint end,
534				 GLsizei count, GLenum type,
535				 const GLvoid *indices, GLint basevertex)
536{
537   FLUSH_CURRENT(ctx, 0);
538
539   /* From the GLES3 specification, section 2.14.2 (Transform Feedback
540    * Primitive Capture):
541    *
542    *   The error INVALID_OPERATION is also generated by DrawElements,
543    *   DrawElementsInstanced, and DrawRangeElements while transform feedback
544    *   is active and not paused, regardless of mode.
545    */
546   if (_mesa_is_gles3(ctx) && _mesa_is_xfb_active_and_unpaused(ctx)) {
547      _mesa_error(ctx, GL_INVALID_OPERATION,
548                  "glDrawElements(transform feedback active)");
549      return GL_FALSE;
550   }
551
552   if (count < 0) {
553      _mesa_error(ctx, GL_INVALID_VALUE, "glDrawRangeElements(count)" );
554      return GL_FALSE;
555   }
556
557   if (!_mesa_valid_prim_mode(ctx, mode, "glDrawRangeElements")) {
558      return GL_FALSE;
559   }
560
561   if (end < start) {
562      _mesa_error(ctx, GL_INVALID_VALUE, "glDrawRangeElements(end<start)");
563      return GL_FALSE;
564   }
565
566   if (!valid_elements_type(ctx, type, "glDrawRangeElements"))
567      return GL_FALSE;
568
569   if (!check_valid_to_render(ctx, "glDrawRangeElements"))
570      return GL_FALSE;
571
572   /* Vertex buffer object tests */
573   if (_mesa_is_bufferobj(ctx->Array.ArrayObj->ElementArrayBufferObj)) {
574      /* use indices in the buffer object */
575      /* make sure count doesn't go outside buffer bounds */
576      if (index_bytes(type, count) > ctx->Array.ArrayObj->ElementArrayBufferObj->Size) {
577         _mesa_warning(ctx, "glDrawRangeElements index out of buffer bounds");
578         return GL_FALSE;
579      }
580   }
581   else {
582      /* not using a VBO */
583      if (!indices)
584         return GL_FALSE;
585   }
586
587   if (!check_index_bounds(ctx, count, type, indices, basevertex))
588      return GL_FALSE;
589
590   if (count == 0)
591      return GL_FALSE;
592
593   return GL_TRUE;
594}
595
596
597/**
598 * Called from the tnl module to error check the function parameters and
599 * verify that we really can draw something.
600 * \return GL_TRUE if OK to render, GL_FALSE if error found
601 */
602GLboolean
603_mesa_validate_DrawArrays(struct gl_context *ctx,
604			  GLenum mode, GLint start, GLsizei count)
605{
606   struct gl_transform_feedback_object *xfb_obj
607      = ctx->TransformFeedback.CurrentObject;
608   FLUSH_CURRENT(ctx, 0);
609
610   if (count < 0) {
611      _mesa_error(ctx, GL_INVALID_VALUE, "glDrawArrays(count)" );
612      return GL_FALSE;
613   }
614
615   if (!_mesa_valid_prim_mode(ctx, mode, "glDrawArrays")) {
616      return GL_FALSE;
617   }
618
619   if (!check_valid_to_render(ctx, "glDrawArrays"))
620      return GL_FALSE;
621
622   if (ctx->Const.CheckArrayBounds) {
623      if (start + count > (GLint) ctx->Array.ArrayObj->_MaxElement)
624         return GL_FALSE;
625   }
626
627   /* From the GLES3 specification, section 2.14.2 (Transform Feedback
628    * Primitive Capture):
629    *
630    *   The error INVALID_OPERATION is generated by DrawArrays and
631    *   DrawArraysInstanced if recording the vertices of a primitive to the
632    *   buffer objects being used for transform feedback purposes would result
633    *   in either exceeding the limits of any buffer object’s size, or in
634    *   exceeding the end position offset + size − 1, as set by
635    *   BindBufferRange.
636    *
637    * This is in contrast to the behaviour of desktop GL, where the extra
638    * primitives are silently dropped from the transform feedback buffer.
639    */
640   if (_mesa_is_gles3(ctx) && _mesa_is_xfb_active_and_unpaused(ctx)) {
641      size_t prim_count = vbo_count_tessellated_primitives(mode, count, 1);
642      if (xfb_obj->GlesRemainingPrims < prim_count) {
643         _mesa_error(ctx, GL_INVALID_OPERATION,
644                     "glDrawArrays(exceeds transform feedback size)");
645         return GL_FALSE;
646      }
647      xfb_obj->GlesRemainingPrims -= prim_count;
648   }
649
650   if (count == 0)
651      return GL_FALSE;
652
653   return GL_TRUE;
654}
655
656
657GLboolean
658_mesa_validate_DrawArraysInstanced(struct gl_context *ctx, GLenum mode, GLint first,
659                                   GLsizei count, GLsizei numInstances)
660{
661   struct gl_transform_feedback_object *xfb_obj
662      = ctx->TransformFeedback.CurrentObject;
663   FLUSH_CURRENT(ctx, 0);
664
665   if (count < 0) {
666      _mesa_error(ctx, GL_INVALID_VALUE,
667                  "glDrawArraysInstanced(count=%d)", count);
668      return GL_FALSE;
669   }
670
671   if (first < 0) {
672      _mesa_error(ctx, GL_INVALID_VALUE,
673		  "glDrawArraysInstanced(start=%d)", first);
674      return GL_FALSE;
675   }
676
677   if (!_mesa_valid_prim_mode(ctx, mode, "glDrawArraysInstanced")) {
678      return GL_FALSE;
679   }
680
681   if (numInstances <= 0) {
682      if (numInstances < 0)
683         _mesa_error(ctx, GL_INVALID_VALUE,
684                     "glDrawArraysInstanced(numInstances=%d)", numInstances);
685      return GL_FALSE;
686   }
687
688   if (!check_valid_to_render(ctx, "glDrawArraysInstanced(invalid to render)"))
689      return GL_FALSE;
690
691   if (ctx->Const.CheckArrayBounds) {
692      if (first + count > (GLint) ctx->Array.ArrayObj->_MaxElement)
693         return GL_FALSE;
694   }
695
696   /* From the GLES3 specification, section 2.14.2 (Transform Feedback
697    * Primitive Capture):
698    *
699    *   The error INVALID_OPERATION is generated by DrawArrays and
700    *   DrawArraysInstanced if recording the vertices of a primitive to the
701    *   buffer objects being used for transform feedback purposes would result
702    *   in either exceeding the limits of any buffer object’s size, or in
703    *   exceeding the end position offset + size − 1, as set by
704    *   BindBufferRange.
705    *
706    * This is in contrast to the behaviour of desktop GL, where the extra
707    * primitives are silently dropped from the transform feedback buffer.
708    */
709   if (_mesa_is_gles3(ctx) && _mesa_is_xfb_active_and_unpaused(ctx)) {
710      size_t prim_count
711         = vbo_count_tessellated_primitives(mode, count, numInstances);
712      if (xfb_obj->GlesRemainingPrims < prim_count) {
713         _mesa_error(ctx, GL_INVALID_OPERATION,
714                     "glDrawArraysInstanced(exceeds transform feedback size)");
715         return GL_FALSE;
716      }
717      xfb_obj->GlesRemainingPrims -= prim_count;
718   }
719
720   if (count == 0)
721      return GL_FALSE;
722
723   return GL_TRUE;
724}
725
726
727GLboolean
728_mesa_validate_DrawElementsInstanced(struct gl_context *ctx,
729                                     GLenum mode, GLsizei count, GLenum type,
730                                     const GLvoid *indices, GLsizei numInstances,
731                                     GLint basevertex)
732{
733   FLUSH_CURRENT(ctx, 0);
734
735   /* From the GLES3 specification, section 2.14.2 (Transform Feedback
736    * Primitive Capture):
737    *
738    *   The error INVALID_OPERATION is also generated by DrawElements,
739    *   DrawElementsInstanced, and DrawRangeElements while transform feedback
740    *   is active and not paused, regardless of mode.
741    */
742   if (_mesa_is_gles3(ctx) && _mesa_is_xfb_active_and_unpaused(ctx)) {
743      _mesa_error(ctx, GL_INVALID_OPERATION,
744                  "glDrawElements(transform feedback active)");
745      return GL_FALSE;
746   }
747
748   if (count < 0) {
749      _mesa_error(ctx, GL_INVALID_VALUE,
750                  "glDrawElementsInstanced(count=%d)", count);
751      return GL_FALSE;
752   }
753
754   if (!_mesa_valid_prim_mode(ctx, mode, "glDrawElementsInstanced")) {
755      return GL_FALSE;
756   }
757
758   if (!valid_elements_type(ctx, type, "glDrawElementsInstanced"))
759      return GL_FALSE;
760
761   if (numInstances <= 0) {
762      if (numInstances < 0)
763         _mesa_error(ctx, GL_INVALID_VALUE,
764                     "glDrawElementsInstanced(numInstances=%d)", numInstances);
765      return GL_FALSE;
766   }
767
768   if (!check_valid_to_render(ctx, "glDrawElementsInstanced"))
769      return GL_FALSE;
770
771   /* Vertex buffer object tests */
772   if (_mesa_is_bufferobj(ctx->Array.ArrayObj->ElementArrayBufferObj)) {
773      /* use indices in the buffer object */
774      /* make sure count doesn't go outside buffer bounds */
775      if (index_bytes(type, count) > ctx->Array.ArrayObj->ElementArrayBufferObj->Size) {
776         _mesa_warning(ctx,
777                       "glDrawElementsInstanced index out of buffer bounds");
778         return GL_FALSE;
779      }
780   }
781   else {
782      /* not using a VBO */
783      if (!indices)
784         return GL_FALSE;
785   }
786
787   if (count == 0)
788      return GL_FALSE;
789
790   if (!check_index_bounds(ctx, count, type, indices, basevertex))
791      return GL_FALSE;
792
793   return GL_TRUE;
794}
795
796
797GLboolean
798_mesa_validate_DrawTransformFeedback(struct gl_context *ctx,
799                                     GLenum mode,
800                                     struct gl_transform_feedback_object *obj,
801                                     GLuint stream,
802                                     GLsizei numInstances)
803{
804   FLUSH_CURRENT(ctx, 0);
805
806   if (!_mesa_valid_prim_mode(ctx, mode, "glDrawTransformFeedback*(mode)")) {
807      return GL_FALSE;
808   }
809
810   if (!obj) {
811      _mesa_error(ctx, GL_INVALID_VALUE, "glDrawTransformFeedback*(name)");
812      return GL_FALSE;
813   }
814
815   if (!obj->EndedAnytime) {
816      _mesa_error(ctx, GL_INVALID_OPERATION, "glDrawTransformFeedback*");
817      return GL_FALSE;
818   }
819
820   if (stream >= ctx->Const.MaxVertexStreams) {
821      _mesa_error(ctx, GL_INVALID_VALUE,
822                  "glDrawTransformFeedbackStream*(index>=MaxVertexStream)");
823      return GL_FALSE;
824   }
825
826   if (numInstances <= 0) {
827      if (numInstances < 0)
828         _mesa_error(ctx, GL_INVALID_VALUE,
829                     "glDrawTransformFeedback*Instanced(numInstances=%d)",
830                     numInstances);
831      return GL_FALSE;
832   }
833
834   if (!check_valid_to_render(ctx, "glDrawTransformFeedback*")) {
835      return GL_FALSE;
836   }
837
838   return GL_TRUE;
839}
840