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