1b8e80941Smrg/**************************************************************************
2b8e80941Smrg *
3b8e80941Smrg * Copyright 2003 VMware, Inc.
4b8e80941Smrg * Copyright 2009 VMware, Inc.
5b8e80941Smrg * All Rights Reserved.
6b8e80941Smrg *
7b8e80941Smrg * Permission is hereby granted, free of charge, to any person obtaining a
8b8e80941Smrg * copy of this software and associated documentation files (the
9b8e80941Smrg * "Software"), to deal in the Software without restriction, including
10b8e80941Smrg * without limitation the rights to use, copy, modify, merge, publish,
11b8e80941Smrg * distribute, sub license, and/or sell copies of the Software, and to
12b8e80941Smrg * permit persons to whom the Software is furnished to do so, subject to
13b8e80941Smrg * the following conditions:
14b8e80941Smrg *
15b8e80941Smrg * The above copyright notice and this permission notice (including the
16b8e80941Smrg * next paragraph) shall be included in all copies or substantial portions
17b8e80941Smrg * of the Software.
18b8e80941Smrg *
19b8e80941Smrg * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
20b8e80941Smrg * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
21b8e80941Smrg * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT.
22b8e80941Smrg * IN NO EVENT SHALL VMWARE AND/OR ITS SUPPLIERS BE LIABLE FOR
23b8e80941Smrg * ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
24b8e80941Smrg * TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
25b8e80941Smrg * SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
26b8e80941Smrg *
27b8e80941Smrg **************************************************************************/
28b8e80941Smrg
29b8e80941Smrg#include <stdio.h>
30b8e80941Smrg#include "arrayobj.h"
31b8e80941Smrg#include "glheader.h"
32b8e80941Smrg#include "c99_alloca.h"
33b8e80941Smrg#include "context.h"
34b8e80941Smrg#include "state.h"
35b8e80941Smrg#include "draw.h"
36b8e80941Smrg#include "draw_validate.h"
37b8e80941Smrg#include "dispatch.h"
38b8e80941Smrg#include "varray.h"
39b8e80941Smrg#include "bufferobj.h"
40b8e80941Smrg#include "enums.h"
41b8e80941Smrg#include "macros.h"
42b8e80941Smrg#include "transformfeedback.h"
43b8e80941Smrg
44b8e80941Smrgtypedef struct {
45b8e80941Smrg   GLuint count;
46b8e80941Smrg   GLuint primCount;
47b8e80941Smrg   GLuint first;
48b8e80941Smrg   GLuint baseInstance;
49b8e80941Smrg} DrawArraysIndirectCommand;
50b8e80941Smrg
51b8e80941Smrgtypedef struct {
52b8e80941Smrg   GLuint count;
53b8e80941Smrg   GLuint primCount;
54b8e80941Smrg   GLuint firstIndex;
55b8e80941Smrg   GLint  baseVertex;
56b8e80941Smrg   GLuint baseInstance;
57b8e80941Smrg} DrawElementsIndirectCommand;
58b8e80941Smrg
59b8e80941Smrg
60b8e80941Smrg/**
61b8e80941Smrg * Check that element 'j' of the array has reasonable data.
62b8e80941Smrg * Map VBO if needed.
63b8e80941Smrg * For debugging purposes; not normally used.
64b8e80941Smrg */
65b8e80941Smrgstatic void
66b8e80941Smrgcheck_array_data(struct gl_context *ctx, struct gl_vertex_array_object *vao,
67b8e80941Smrg                 GLuint attrib, GLuint j)
68b8e80941Smrg{
69b8e80941Smrg   const struct gl_array_attributes *array = &vao->VertexAttrib[attrib];
70b8e80941Smrg   if (vao->Enabled & VERT_BIT(attrib)) {
71b8e80941Smrg      const struct gl_vertex_buffer_binding *binding =
72b8e80941Smrg         &vao->BufferBinding[array->BufferBindingIndex];
73b8e80941Smrg      struct gl_buffer_object *bo = binding->BufferObj;
74b8e80941Smrg      const void *data = array->Ptr;
75b8e80941Smrg      if (_mesa_is_bufferobj(bo)) {
76b8e80941Smrg         data = ADD_POINTERS(_mesa_vertex_attrib_address(array, binding),
77b8e80941Smrg                             bo->Mappings[MAP_INTERNAL].Pointer);
78b8e80941Smrg      }
79b8e80941Smrg      switch (array->Format.Type) {
80b8e80941Smrg      case GL_FLOAT:
81b8e80941Smrg         {
82b8e80941Smrg            GLfloat *f = (GLfloat *) ((GLubyte *) data + binding->Stride * j);
83b8e80941Smrg            GLint k;
84b8e80941Smrg            for (k = 0; k < array->Format.Size; k++) {
85b8e80941Smrg               if (IS_INF_OR_NAN(f[k]) || f[k] >= 1.0e20F || f[k] <= -1.0e10F) {
86b8e80941Smrg                  printf("Bad array data:\n");
87b8e80941Smrg                  printf("  Element[%u].%u = %f\n", j, k, f[k]);
88b8e80941Smrg                  printf("  Array %u at %p\n", attrib, (void *) array);
89b8e80941Smrg                  printf("  Type 0x%x, Size %d, Stride %d\n",
90b8e80941Smrg                         array->Format.Type, array->Format.Size,
91b8e80941Smrg                         binding->Stride);
92b8e80941Smrg                  printf("  Address/offset %p in Buffer Object %u\n",
93b8e80941Smrg                         array->Ptr, bo->Name);
94b8e80941Smrg                  f[k] = 1.0F;  /* XXX replace the bad value! */
95b8e80941Smrg               }
96b8e80941Smrg               /*assert(!IS_INF_OR_NAN(f[k])); */
97b8e80941Smrg            }
98b8e80941Smrg         }
99b8e80941Smrg         break;
100b8e80941Smrg      default:
101b8e80941Smrg         ;
102b8e80941Smrg      }
103b8e80941Smrg   }
104b8e80941Smrg}
105b8e80941Smrg
106b8e80941Smrg
107b8e80941Smrgstatic inline int
108b8e80941Smrgsizeof_ib_type(GLenum type)
109b8e80941Smrg{
110b8e80941Smrg   switch (type) {
111b8e80941Smrg   case GL_UNSIGNED_INT:
112b8e80941Smrg      return sizeof(GLuint);
113b8e80941Smrg   case GL_UNSIGNED_SHORT:
114b8e80941Smrg      return sizeof(GLushort);
115b8e80941Smrg   case GL_UNSIGNED_BYTE:
116b8e80941Smrg      return sizeof(GLubyte);
117b8e80941Smrg   default:
118b8e80941Smrg      assert(!"unsupported index data type");
119b8e80941Smrg      /* In case assert is turned off */
120b8e80941Smrg      return 0;
121b8e80941Smrg   }
122b8e80941Smrg}
123b8e80941Smrg
124b8e80941Smrg/**
125b8e80941Smrg * Examine the array's data for NaNs, etc.
126b8e80941Smrg * For debug purposes; not normally used.
127b8e80941Smrg */
128b8e80941Smrgstatic void
129b8e80941Smrgcheck_draw_elements_data(struct gl_context *ctx, GLsizei count,
130b8e80941Smrg                         GLenum elemType, const void *elements,
131b8e80941Smrg                         GLint basevertex)
132b8e80941Smrg{
133b8e80941Smrg   struct gl_vertex_array_object *vao = ctx->Array.VAO;
134b8e80941Smrg   GLint i;
135b8e80941Smrg   GLuint k;
136b8e80941Smrg
137b8e80941Smrg   _mesa_vao_map(ctx, vao, GL_MAP_READ_BIT);
138b8e80941Smrg
139b8e80941Smrg   if (_mesa_is_bufferobj(vao->IndexBufferObj))
140b8e80941Smrg       elements =
141b8e80941Smrg          ADD_POINTERS(vao->IndexBufferObj->Mappings[MAP_INTERNAL].Pointer, elements);
142b8e80941Smrg
143b8e80941Smrg   for (i = 0; i < count; i++) {
144b8e80941Smrg      GLuint j;
145b8e80941Smrg
146b8e80941Smrg      /* j = element[i] */
147b8e80941Smrg      switch (elemType) {
148b8e80941Smrg      case GL_UNSIGNED_BYTE:
149b8e80941Smrg         j = ((const GLubyte *) elements)[i];
150b8e80941Smrg         break;
151b8e80941Smrg      case GL_UNSIGNED_SHORT:
152b8e80941Smrg         j = ((const GLushort *) elements)[i];
153b8e80941Smrg         break;
154b8e80941Smrg      case GL_UNSIGNED_INT:
155b8e80941Smrg         j = ((const GLuint *) elements)[i];
156b8e80941Smrg         break;
157b8e80941Smrg      default:
158b8e80941Smrg         unreachable("Unexpected index buffer type");
159b8e80941Smrg      }
160b8e80941Smrg
161b8e80941Smrg      /* check element j of each enabled array */
162b8e80941Smrg      for (k = 0; k < VERT_ATTRIB_MAX; k++) {
163b8e80941Smrg         check_array_data(ctx, vao, k, j);
164b8e80941Smrg      }
165b8e80941Smrg   }
166b8e80941Smrg
167b8e80941Smrg   _mesa_vao_unmap(ctx, vao);
168b8e80941Smrg}
169b8e80941Smrg
170b8e80941Smrg
171b8e80941Smrg/**
172b8e80941Smrg * Check array data, looking for NaNs, etc.
173b8e80941Smrg */
174b8e80941Smrgstatic void
175b8e80941Smrgcheck_draw_arrays_data(struct gl_context *ctx, GLint start, GLsizei count)
176b8e80941Smrg{
177b8e80941Smrg   /* TO DO */
178b8e80941Smrg}
179b8e80941Smrg
180b8e80941Smrg
181b8e80941Smrg/**
182b8e80941Smrg * Check if we should skip the draw call even after validation was successful.
183b8e80941Smrg */
184b8e80941Smrgstatic bool
185b8e80941Smrgskip_validated_draw(struct gl_context *ctx)
186b8e80941Smrg{
187b8e80941Smrg   switch (ctx->API) {
188b8e80941Smrg   case API_OPENGLES2:
189b8e80941Smrg      /* For ES2, we can draw if we have a vertex program/shader). */
190b8e80941Smrg      return ctx->VertexProgram._Current == NULL;
191b8e80941Smrg
192b8e80941Smrg   case API_OPENGLES:
193b8e80941Smrg      /* For OpenGL ES, only draw if we have vertex positions
194b8e80941Smrg       */
195b8e80941Smrg      if (!(ctx->Array.VAO->Enabled & VERT_BIT_POS))
196b8e80941Smrg         return true;
197b8e80941Smrg      break;
198b8e80941Smrg
199b8e80941Smrg   case API_OPENGL_CORE:
200b8e80941Smrg      /* Section 7.3 (Program Objects) of the OpenGL 4.5 Core Profile spec
201b8e80941Smrg       * says:
202b8e80941Smrg       *
203b8e80941Smrg       *     "If there is no active program for the vertex or fragment shader
204b8e80941Smrg       *     stages, the results of vertex and/or fragment processing will be
205b8e80941Smrg       *     undefined. However, this is not an error."
206b8e80941Smrg       *
207b8e80941Smrg       * The fragment shader is not tested here because other state (e.g.,
208b8e80941Smrg       * GL_RASTERIZER_DISCARD) affects whether or not we actually care.
209b8e80941Smrg       */
210b8e80941Smrg      return ctx->VertexProgram._Current == NULL;
211b8e80941Smrg
212b8e80941Smrg   case API_OPENGL_COMPAT:
213b8e80941Smrg      if (ctx->VertexProgram._Current != NULL) {
214b8e80941Smrg         /* Draw regardless of whether or not we have any vertex arrays.
215b8e80941Smrg          * (Ex: could draw a point using a constant vertex pos)
216b8e80941Smrg          */
217b8e80941Smrg         return false;
218b8e80941Smrg      } else {
219b8e80941Smrg         /* Draw if we have vertex positions (GL_VERTEX_ARRAY or generic
220b8e80941Smrg          * array [0]).
221b8e80941Smrg          */
222b8e80941Smrg         return !(ctx->Array.VAO->Enabled & (VERT_BIT_POS|VERT_BIT_GENERIC0));
223b8e80941Smrg      }
224b8e80941Smrg      break;
225b8e80941Smrg
226b8e80941Smrg   default:
227b8e80941Smrg      unreachable("Invalid API value in check_valid_to_render()");
228b8e80941Smrg   }
229b8e80941Smrg
230b8e80941Smrg   return false;
231b8e80941Smrg}
232b8e80941Smrg
233b8e80941Smrg
234b8e80941Smrg/**
235b8e80941Smrg * Print info/data for glDrawArrays(), for debugging.
236b8e80941Smrg */
237b8e80941Smrgstatic void
238b8e80941Smrgprint_draw_arrays(struct gl_context *ctx,
239b8e80941Smrg                  GLenum mode, GLint start, GLsizei count)
240b8e80941Smrg{
241b8e80941Smrg   struct gl_vertex_array_object *vao = ctx->Array.VAO;
242b8e80941Smrg
243b8e80941Smrg   printf("_mesa_DrawArrays(mode 0x%x, start %d, count %d):\n",
244b8e80941Smrg          mode, start, count);
245b8e80941Smrg
246b8e80941Smrg   _mesa_vao_map_arrays(ctx, vao, GL_MAP_READ_BIT);
247b8e80941Smrg
248b8e80941Smrg   GLbitfield mask = vao->Enabled;
249b8e80941Smrg   while (mask) {
250b8e80941Smrg      const gl_vert_attrib i = u_bit_scan(&mask);
251b8e80941Smrg      const struct gl_array_attributes *array = &vao->VertexAttrib[i];
252b8e80941Smrg
253b8e80941Smrg      const struct gl_vertex_buffer_binding *binding =
254b8e80941Smrg         &vao->BufferBinding[array->BufferBindingIndex];
255b8e80941Smrg      struct gl_buffer_object *bufObj = binding->BufferObj;
256b8e80941Smrg
257b8e80941Smrg      printf("attr %s: size %d stride %d  "
258b8e80941Smrg             "ptr %p  Bufobj %u\n",
259b8e80941Smrg             gl_vert_attrib_name((gl_vert_attrib) i),
260b8e80941Smrg             array->Format.Size, binding->Stride,
261b8e80941Smrg             array->Ptr, bufObj->Name);
262b8e80941Smrg
263b8e80941Smrg      if (_mesa_is_bufferobj(bufObj)) {
264b8e80941Smrg         GLubyte *p = bufObj->Mappings[MAP_INTERNAL].Pointer;
265b8e80941Smrg         int offset = (int) (GLintptr)
266b8e80941Smrg            _mesa_vertex_attrib_address(array, binding);
267b8e80941Smrg
268b8e80941Smrg         unsigned multiplier;
269b8e80941Smrg         switch (array->Format.Type) {
270b8e80941Smrg         case GL_DOUBLE:
271b8e80941Smrg         case GL_INT64_ARB:
272b8e80941Smrg         case GL_UNSIGNED_INT64_ARB:
273b8e80941Smrg            multiplier = 2;
274b8e80941Smrg            break;
275b8e80941Smrg         default:
276b8e80941Smrg            multiplier = 1;
277b8e80941Smrg         }
278b8e80941Smrg
279b8e80941Smrg         float *f = (float *) (p + offset);
280b8e80941Smrg         int *k = (int *) f;
281b8e80941Smrg         int i = 0;
282b8e80941Smrg         int n = (count - 1) * (binding->Stride / (4 * multiplier))
283b8e80941Smrg            + array->Format.Size;
284b8e80941Smrg         if (n > 32)
285b8e80941Smrg            n = 32;
286b8e80941Smrg         printf("  Data at offset %d:\n", offset);
287b8e80941Smrg         do {
288b8e80941Smrg            if (multiplier == 2)
289b8e80941Smrg               printf("    double[%d] = 0x%016llx %lf\n", i,
290b8e80941Smrg                      ((unsigned long long *) k)[i], ((double *) f)[i]);
291b8e80941Smrg            else
292b8e80941Smrg               printf("    float[%d] = 0x%08x %f\n", i, k[i], f[i]);
293b8e80941Smrg            i++;
294b8e80941Smrg         } while (i < n);
295b8e80941Smrg      }
296b8e80941Smrg   }
297b8e80941Smrg
298b8e80941Smrg   _mesa_vao_unmap_arrays(ctx, vao);
299b8e80941Smrg}
300b8e80941Smrg
301b8e80941Smrg
302b8e80941Smrg/**
303b8e80941Smrg * Return a filter mask for the net enabled vao arrays.
304b8e80941Smrg * This is to mask out arrays that would otherwise supersed required current
305b8e80941Smrg * values for the fixed function shaders for example.
306b8e80941Smrg */
307b8e80941Smrgstatic GLbitfield
308b8e80941Smrgenabled_filter(const struct gl_context *ctx)
309b8e80941Smrg{
310b8e80941Smrg   switch (ctx->VertexProgram._VPMode) {
311b8e80941Smrg   case VP_MODE_FF:
312b8e80941Smrg      /* When no vertex program is active (or the vertex program is generated
313b8e80941Smrg       * from fixed-function state).  We put the material values into the
314b8e80941Smrg       * generic slots.  Since the vao has no material arrays, mute these
315b8e80941Smrg       * slots from the enabled arrays so that the current material values
316b8e80941Smrg       * are pulled instead of the vao arrays.
317b8e80941Smrg       */
318b8e80941Smrg      return VERT_BIT_FF_ALL;
319b8e80941Smrg
320b8e80941Smrg   case VP_MODE_SHADER:
321b8e80941Smrg      /* There are no shaders in OpenGL ES 1.x, so this code path should be
322b8e80941Smrg       * impossible to reach.  The meta code is careful to not use shaders in
323b8e80941Smrg       * ES1.
324b8e80941Smrg       */
325b8e80941Smrg      assert(ctx->API != API_OPENGLES);
326b8e80941Smrg
327b8e80941Smrg      /* Other parts of the code assume that inputs[VERT_ATTRIB_POS] through
328b8e80941Smrg       * inputs[VERT_ATTRIB_FF_MAX] will be non-NULL.  However, in OpenGL
329b8e80941Smrg       * ES 2.0+ or OpenGL core profile, none of these arrays should ever
330b8e80941Smrg       * be enabled.
331b8e80941Smrg       */
332b8e80941Smrg      if (ctx->API != API_OPENGL_COMPAT)
333b8e80941Smrg         return VERT_BIT_GENERIC_ALL;
334b8e80941Smrg
335b8e80941Smrg      return VERT_BIT_ALL;
336b8e80941Smrg
337b8e80941Smrg   default:
338b8e80941Smrg      assert(0);
339b8e80941Smrg      return 0;
340b8e80941Smrg   }
341b8e80941Smrg}
342b8e80941Smrg
343b8e80941Smrg
344b8e80941Smrg/**
345b8e80941Smrg * Helper function called by the other DrawArrays() functions below.
346b8e80941Smrg * This is where we handle primitive restart for drawing non-indexed
347b8e80941Smrg * arrays.  If primitive restart is enabled, it typically means
348b8e80941Smrg * splitting one DrawArrays() into two.
349b8e80941Smrg */
350b8e80941Smrgstatic void
351b8e80941Smrg_mesa_draw_arrays(struct gl_context *ctx, GLenum mode, GLint start,
352b8e80941Smrg                  GLsizei count, GLuint numInstances, GLuint baseInstance,
353b8e80941Smrg                  GLuint drawID)
354b8e80941Smrg{
355b8e80941Smrg   struct _mesa_prim prim;
356b8e80941Smrg
357b8e80941Smrg   if (skip_validated_draw(ctx))
358b8e80941Smrg      return;
359b8e80941Smrg
360b8e80941Smrg   /* OpenGL 4.5 says that primitive restart is ignored with non-indexed
361b8e80941Smrg    * draws.
362b8e80941Smrg    */
363b8e80941Smrg   memset(&prim, 0, sizeof(prim));
364b8e80941Smrg   prim.begin = 1;
365b8e80941Smrg   prim.end = 1;
366b8e80941Smrg   prim.mode = mode;
367b8e80941Smrg   prim.num_instances = numInstances;
368b8e80941Smrg   prim.base_instance = baseInstance;
369b8e80941Smrg   prim.draw_id = drawID;
370b8e80941Smrg   prim.is_indirect = 0;
371b8e80941Smrg   prim.start = start;
372b8e80941Smrg   prim.count = count;
373b8e80941Smrg
374b8e80941Smrg   ctx->Driver.Draw(ctx, &prim, 1, NULL,
375b8e80941Smrg                    GL_TRUE, start, start + count - 1, NULL, 0, NULL);
376b8e80941Smrg
377b8e80941Smrg   if (MESA_DEBUG_FLAGS & DEBUG_ALWAYS_FLUSH) {
378b8e80941Smrg      _mesa_flush(ctx);
379b8e80941Smrg   }
380b8e80941Smrg}
381b8e80941Smrg
382b8e80941Smrg
383b8e80941Smrg/**
384b8e80941Smrg * Execute a glRectf() function.
385b8e80941Smrg */
386b8e80941Smrgstatic void GLAPIENTRY
387b8e80941Smrg_mesa_exec_Rectf(GLfloat x1, GLfloat y1, GLfloat x2, GLfloat y2)
388b8e80941Smrg{
389b8e80941Smrg   GET_CURRENT_CONTEXT(ctx);
390b8e80941Smrg   ASSERT_OUTSIDE_BEGIN_END(ctx);
391b8e80941Smrg
392b8e80941Smrg   CALL_Begin(GET_DISPATCH(), (GL_QUADS));
393b8e80941Smrg   CALL_Vertex2f(GET_DISPATCH(), (x1, y1));
394b8e80941Smrg   CALL_Vertex2f(GET_DISPATCH(), (x2, y1));
395b8e80941Smrg   CALL_Vertex2f(GET_DISPATCH(), (x2, y2));
396b8e80941Smrg   CALL_Vertex2f(GET_DISPATCH(), (x1, y2));
397b8e80941Smrg   CALL_End(GET_DISPATCH(), ());
398b8e80941Smrg}
399b8e80941Smrg
400b8e80941Smrg
401b8e80941Smrgstatic void GLAPIENTRY
402b8e80941Smrg_mesa_exec_EvalMesh1(GLenum mode, GLint i1, GLint i2)
403b8e80941Smrg{
404b8e80941Smrg   GET_CURRENT_CONTEXT(ctx);
405b8e80941Smrg   GLint i;
406b8e80941Smrg   GLfloat u, du;
407b8e80941Smrg   GLenum prim;
408b8e80941Smrg
409b8e80941Smrg   switch (mode) {
410b8e80941Smrg   case GL_POINT:
411b8e80941Smrg      prim = GL_POINTS;
412b8e80941Smrg      break;
413b8e80941Smrg   case GL_LINE:
414b8e80941Smrg      prim = GL_LINE_STRIP;
415b8e80941Smrg      break;
416b8e80941Smrg   default:
417b8e80941Smrg      _mesa_error(ctx, GL_INVALID_ENUM, "glEvalMesh1(mode)");
418b8e80941Smrg      return;
419b8e80941Smrg   }
420b8e80941Smrg
421b8e80941Smrg   /* No effect if vertex maps disabled.
422b8e80941Smrg    */
423b8e80941Smrg   if (!ctx->Eval.Map1Vertex4 && !ctx->Eval.Map1Vertex3)
424b8e80941Smrg      return;
425b8e80941Smrg
426b8e80941Smrg   du = ctx->Eval.MapGrid1du;
427b8e80941Smrg   u = ctx->Eval.MapGrid1u1 + i1 * du;
428b8e80941Smrg
429b8e80941Smrg   CALL_Begin(GET_DISPATCH(), (prim));
430b8e80941Smrg   for (i = i1; i <= i2; i++, u += du) {
431b8e80941Smrg      CALL_EvalCoord1f(GET_DISPATCH(), (u));
432b8e80941Smrg   }
433b8e80941Smrg   CALL_End(GET_DISPATCH(), ());
434b8e80941Smrg}
435b8e80941Smrg
436b8e80941Smrg
437b8e80941Smrgstatic void GLAPIENTRY
438b8e80941Smrg_mesa_exec_EvalMesh2(GLenum mode, GLint i1, GLint i2, GLint j1, GLint j2)
439b8e80941Smrg{
440b8e80941Smrg   GET_CURRENT_CONTEXT(ctx);
441b8e80941Smrg   GLfloat u, du, v, dv, v1, u1;
442b8e80941Smrg   GLint i, j;
443b8e80941Smrg
444b8e80941Smrg   switch (mode) {
445b8e80941Smrg   case GL_POINT:
446b8e80941Smrg   case GL_LINE:
447b8e80941Smrg   case GL_FILL:
448b8e80941Smrg      break;
449b8e80941Smrg   default:
450b8e80941Smrg      _mesa_error(ctx, GL_INVALID_ENUM, "glEvalMesh2(mode)");
451b8e80941Smrg      return;
452b8e80941Smrg   }
453b8e80941Smrg
454b8e80941Smrg   /* No effect if vertex maps disabled.
455b8e80941Smrg    */
456b8e80941Smrg   if (!ctx->Eval.Map2Vertex4 && !ctx->Eval.Map2Vertex3)
457b8e80941Smrg      return;
458b8e80941Smrg
459b8e80941Smrg   du = ctx->Eval.MapGrid2du;
460b8e80941Smrg   dv = ctx->Eval.MapGrid2dv;
461b8e80941Smrg   v1 = ctx->Eval.MapGrid2v1 + j1 * dv;
462b8e80941Smrg   u1 = ctx->Eval.MapGrid2u1 + i1 * du;
463b8e80941Smrg
464b8e80941Smrg   switch (mode) {
465b8e80941Smrg   case GL_POINT:
466b8e80941Smrg      CALL_Begin(GET_DISPATCH(), (GL_POINTS));
467b8e80941Smrg      for (v = v1, j = j1; j <= j2; j++, v += dv) {
468b8e80941Smrg         for (u = u1, i = i1; i <= i2; i++, u += du) {
469b8e80941Smrg            CALL_EvalCoord2f(GET_DISPATCH(), (u, v));
470b8e80941Smrg         }
471b8e80941Smrg      }
472b8e80941Smrg      CALL_End(GET_DISPATCH(), ());
473b8e80941Smrg      break;
474b8e80941Smrg   case GL_LINE:
475b8e80941Smrg      for (v = v1, j = j1; j <= j2; j++, v += dv) {
476b8e80941Smrg         CALL_Begin(GET_DISPATCH(), (GL_LINE_STRIP));
477b8e80941Smrg         for (u = u1, i = i1; i <= i2; i++, u += du) {
478b8e80941Smrg            CALL_EvalCoord2f(GET_DISPATCH(), (u, v));
479b8e80941Smrg         }
480b8e80941Smrg         CALL_End(GET_DISPATCH(), ());
481b8e80941Smrg      }
482b8e80941Smrg      for (u = u1, i = i1; i <= i2; i++, u += du) {
483b8e80941Smrg         CALL_Begin(GET_DISPATCH(), (GL_LINE_STRIP));
484b8e80941Smrg         for (v = v1, j = j1; j <= j2; j++, v += dv) {
485b8e80941Smrg            CALL_EvalCoord2f(GET_DISPATCH(), (u, v));
486b8e80941Smrg         }
487b8e80941Smrg         CALL_End(GET_DISPATCH(), ());
488b8e80941Smrg      }
489b8e80941Smrg      break;
490b8e80941Smrg   case GL_FILL:
491b8e80941Smrg      for (v = v1, j = j1; j < j2; j++, v += dv) {
492b8e80941Smrg         CALL_Begin(GET_DISPATCH(), (GL_TRIANGLE_STRIP));
493b8e80941Smrg         for (u = u1, i = i1; i <= i2; i++, u += du) {
494b8e80941Smrg            CALL_EvalCoord2f(GET_DISPATCH(), (u, v));
495b8e80941Smrg            CALL_EvalCoord2f(GET_DISPATCH(), (u, v + dv));
496b8e80941Smrg         }
497b8e80941Smrg         CALL_End(GET_DISPATCH(), ());
498b8e80941Smrg      }
499b8e80941Smrg      break;
500b8e80941Smrg   }
501b8e80941Smrg}
502b8e80941Smrg
503b8e80941Smrg
504b8e80941Smrg/**
505b8e80941Smrg * Called from glDrawArrays when in immediate mode (not display list mode).
506b8e80941Smrg */
507b8e80941Smrgvoid GLAPIENTRY
508b8e80941Smrg_mesa_DrawArrays(GLenum mode, GLint start, GLsizei count)
509b8e80941Smrg{
510b8e80941Smrg   GET_CURRENT_CONTEXT(ctx);
511b8e80941Smrg
512b8e80941Smrg   if (MESA_VERBOSE & VERBOSE_DRAW)
513b8e80941Smrg      _mesa_debug(ctx, "glDrawArrays(%s, %d, %d)\n",
514b8e80941Smrg                  _mesa_enum_to_string(mode), start, count);
515b8e80941Smrg
516b8e80941Smrg   FLUSH_FOR_DRAW(ctx);
517b8e80941Smrg
518b8e80941Smrg   _mesa_set_draw_vao(ctx, ctx->Array.VAO, enabled_filter(ctx));
519b8e80941Smrg
520b8e80941Smrg   if (_mesa_is_no_error_enabled(ctx)) {
521b8e80941Smrg      if (ctx->NewState)
522b8e80941Smrg         _mesa_update_state(ctx);
523b8e80941Smrg   } else {
524b8e80941Smrg      if (!_mesa_validate_DrawArrays(ctx, mode, count))
525b8e80941Smrg         return;
526b8e80941Smrg   }
527b8e80941Smrg
528b8e80941Smrg   if (0)
529b8e80941Smrg      check_draw_arrays_data(ctx, start, count);
530b8e80941Smrg
531b8e80941Smrg   _mesa_draw_arrays(ctx, mode, start, count, 1, 0, 0);
532b8e80941Smrg
533b8e80941Smrg   if (0)
534b8e80941Smrg      print_draw_arrays(ctx, mode, start, count);
535b8e80941Smrg}
536b8e80941Smrg
537b8e80941Smrg
538b8e80941Smrg/**
539b8e80941Smrg * Called from glDrawArraysInstanced when in immediate mode (not
540b8e80941Smrg * display list mode).
541b8e80941Smrg */
542b8e80941Smrgvoid GLAPIENTRY
543b8e80941Smrg_mesa_DrawArraysInstanced(GLenum mode, GLint start, GLsizei count,
544b8e80941Smrg                          GLsizei numInstances)
545b8e80941Smrg{
546b8e80941Smrg   GET_CURRENT_CONTEXT(ctx);
547b8e80941Smrg
548b8e80941Smrg   if (MESA_VERBOSE & VERBOSE_DRAW)
549b8e80941Smrg      _mesa_debug(ctx, "glDrawArraysInstanced(%s, %d, %d, %d)\n",
550b8e80941Smrg                  _mesa_enum_to_string(mode), start, count, numInstances);
551b8e80941Smrg
552b8e80941Smrg   FLUSH_FOR_DRAW(ctx);
553b8e80941Smrg
554b8e80941Smrg   _mesa_set_draw_vao(ctx, ctx->Array.VAO, enabled_filter(ctx));
555b8e80941Smrg
556b8e80941Smrg   if (_mesa_is_no_error_enabled(ctx)) {
557b8e80941Smrg      if (ctx->NewState)
558b8e80941Smrg         _mesa_update_state(ctx);
559b8e80941Smrg   } else {
560b8e80941Smrg      if (!_mesa_validate_DrawArraysInstanced(ctx, mode, start, count,
561b8e80941Smrg                                              numInstances))
562b8e80941Smrg         return;
563b8e80941Smrg   }
564b8e80941Smrg
565b8e80941Smrg   if (0)
566b8e80941Smrg      check_draw_arrays_data(ctx, start, count);
567b8e80941Smrg
568b8e80941Smrg   _mesa_draw_arrays(ctx, mode, start, count, numInstances, 0, 0);
569b8e80941Smrg
570b8e80941Smrg   if (0)
571b8e80941Smrg      print_draw_arrays(ctx, mode, start, count);
572b8e80941Smrg}
573b8e80941Smrg
574b8e80941Smrg
575b8e80941Smrg/**
576b8e80941Smrg * Called from glDrawArraysInstancedBaseInstance when in immediate mode.
577b8e80941Smrg */
578b8e80941Smrgstatic void GLAPIENTRY
579b8e80941Smrg_mesa_exec_DrawArraysInstancedBaseInstance(GLenum mode, GLint first,
580b8e80941Smrg                                           GLsizei count, GLsizei numInstances,
581b8e80941Smrg                                           GLuint baseInstance)
582b8e80941Smrg{
583b8e80941Smrg   GET_CURRENT_CONTEXT(ctx);
584b8e80941Smrg
585b8e80941Smrg   if (MESA_VERBOSE & VERBOSE_DRAW)
586b8e80941Smrg      _mesa_debug(ctx,
587b8e80941Smrg                  "glDrawArraysInstancedBaseInstance(%s, %d, %d, %d, %d)\n",
588b8e80941Smrg                  _mesa_enum_to_string(mode), first, count,
589b8e80941Smrg                  numInstances, baseInstance);
590b8e80941Smrg
591b8e80941Smrg   FLUSH_FOR_DRAW(ctx);
592b8e80941Smrg
593b8e80941Smrg   _mesa_set_draw_vao(ctx, ctx->Array.VAO, enabled_filter(ctx));
594b8e80941Smrg
595b8e80941Smrg   if (_mesa_is_no_error_enabled(ctx)) {
596b8e80941Smrg      if (ctx->NewState)
597b8e80941Smrg         _mesa_update_state(ctx);
598b8e80941Smrg   } else {
599b8e80941Smrg      if (!_mesa_validate_DrawArraysInstanced(ctx, mode, first, count,
600b8e80941Smrg                                              numInstances))
601b8e80941Smrg         return;
602b8e80941Smrg   }
603b8e80941Smrg
604b8e80941Smrg   if (0)
605b8e80941Smrg      check_draw_arrays_data(ctx, first, count);
606b8e80941Smrg
607b8e80941Smrg   _mesa_draw_arrays(ctx, mode, first, count, numInstances, baseInstance, 0);
608b8e80941Smrg
609b8e80941Smrg   if (0)
610b8e80941Smrg      print_draw_arrays(ctx, mode, first, count);
611b8e80941Smrg}
612b8e80941Smrg
613b8e80941Smrg
614b8e80941Smrg/**
615b8e80941Smrg * Called from glMultiDrawArrays when in immediate mode.
616b8e80941Smrg */
617b8e80941Smrgstatic void GLAPIENTRY
618b8e80941Smrg_mesa_exec_MultiDrawArrays(GLenum mode, const GLint *first,
619b8e80941Smrg                           const GLsizei *count, GLsizei primcount)
620b8e80941Smrg{
621b8e80941Smrg   GET_CURRENT_CONTEXT(ctx);
622b8e80941Smrg   GLint i;
623b8e80941Smrg
624b8e80941Smrg   if (MESA_VERBOSE & VERBOSE_DRAW)
625b8e80941Smrg      _mesa_debug(ctx,
626b8e80941Smrg                  "glMultiDrawArrays(%s, %p, %p, %d)\n",
627b8e80941Smrg                  _mesa_enum_to_string(mode), first, count, primcount);
628b8e80941Smrg
629b8e80941Smrg   FLUSH_FOR_DRAW(ctx);
630b8e80941Smrg
631b8e80941Smrg   _mesa_set_draw_vao(ctx, ctx->Array.VAO, enabled_filter(ctx));
632b8e80941Smrg
633b8e80941Smrg   if (_mesa_is_no_error_enabled(ctx)) {
634b8e80941Smrg      if (ctx->NewState)
635b8e80941Smrg         _mesa_update_state(ctx);
636b8e80941Smrg   } else {
637b8e80941Smrg      if (!_mesa_validate_MultiDrawArrays(ctx, mode, count, primcount))
638b8e80941Smrg         return;
639b8e80941Smrg   }
640b8e80941Smrg
641b8e80941Smrg   for (i = 0; i < primcount; i++) {
642b8e80941Smrg      if (count[i] > 0) {
643b8e80941Smrg         if (0)
644b8e80941Smrg            check_draw_arrays_data(ctx, first[i], count[i]);
645b8e80941Smrg
646b8e80941Smrg         /* The GL_ARB_shader_draw_parameters spec adds the following after the
647b8e80941Smrg          * pseudo-code describing glMultiDrawArrays:
648b8e80941Smrg          *
649b8e80941Smrg          *    "The index of the draw (<i> in the above pseudo-code) may be
650b8e80941Smrg          *     read by a vertex shader as <gl_DrawIDARB>, as described in
651b8e80941Smrg          *     Section 11.1.3.9."
652b8e80941Smrg          */
653b8e80941Smrg         _mesa_draw_arrays(ctx, mode, first[i], count[i], 1, 0, i);
654b8e80941Smrg
655b8e80941Smrg         if (0)
656b8e80941Smrg            print_draw_arrays(ctx, mode, first[i], count[i]);
657b8e80941Smrg      }
658b8e80941Smrg   }
659b8e80941Smrg}
660b8e80941Smrg
661b8e80941Smrg
662b8e80941Smrg
663b8e80941Smrg/**
664b8e80941Smrg * Map GL_ELEMENT_ARRAY_BUFFER and print contents.
665b8e80941Smrg * For debugging.
666b8e80941Smrg */
667b8e80941Smrg#if 0
668b8e80941Smrgstatic void
669b8e80941Smrgdump_element_buffer(struct gl_context *ctx, GLenum type)
670b8e80941Smrg{
671b8e80941Smrg   const GLvoid *map =
672b8e80941Smrg      ctx->Driver.MapBufferRange(ctx, 0,
673b8e80941Smrg                                 ctx->Array.VAO->IndexBufferObj->Size,
674b8e80941Smrg                                 GL_MAP_READ_BIT,
675b8e80941Smrg                                 ctx->Array.VAO->IndexBufferObj,
676b8e80941Smrg                                 MAP_INTERNAL);
677b8e80941Smrg   switch (type) {
678b8e80941Smrg   case GL_UNSIGNED_BYTE:
679b8e80941Smrg      {
680b8e80941Smrg         const GLubyte *us = (const GLubyte *) map;
681b8e80941Smrg         GLint i;
682b8e80941Smrg         for (i = 0; i < ctx->Array.VAO->IndexBufferObj->Size; i++) {
683b8e80941Smrg            printf("%02x ", us[i]);
684b8e80941Smrg            if (i % 32 == 31)
685b8e80941Smrg               printf("\n");
686b8e80941Smrg         }
687b8e80941Smrg         printf("\n");
688b8e80941Smrg      }
689b8e80941Smrg      break;
690b8e80941Smrg   case GL_UNSIGNED_SHORT:
691b8e80941Smrg      {
692b8e80941Smrg         const GLushort *us = (const GLushort *) map;
693b8e80941Smrg         GLint i;
694b8e80941Smrg         for (i = 0; i < ctx->Array.VAO->IndexBufferObj->Size / 2; i++) {
695b8e80941Smrg            printf("%04x ", us[i]);
696b8e80941Smrg            if (i % 16 == 15)
697b8e80941Smrg               printf("\n");
698b8e80941Smrg         }
699b8e80941Smrg         printf("\n");
700b8e80941Smrg      }
701b8e80941Smrg      break;
702b8e80941Smrg   case GL_UNSIGNED_INT:
703b8e80941Smrg      {
704b8e80941Smrg         const GLuint *us = (const GLuint *) map;
705b8e80941Smrg         GLint i;
706b8e80941Smrg         for (i = 0; i < ctx->Array.VAO->IndexBufferObj->Size / 4; i++) {
707b8e80941Smrg            printf("%08x ", us[i]);
708b8e80941Smrg            if (i % 8 == 7)
709b8e80941Smrg               printf("\n");
710b8e80941Smrg         }
711b8e80941Smrg         printf("\n");
712b8e80941Smrg      }
713b8e80941Smrg      break;
714b8e80941Smrg   default:
715b8e80941Smrg      ;
716b8e80941Smrg   }
717b8e80941Smrg
718b8e80941Smrg   ctx->Driver.UnmapBuffer(ctx, ctx->Array.VAO->IndexBufferObj, MAP_INTERNAL);
719b8e80941Smrg}
720b8e80941Smrg#endif
721b8e80941Smrg
722b8e80941Smrg
723b8e80941Smrgstatic bool
724b8e80941Smrgskip_draw_elements(struct gl_context *ctx, GLsizei count,
725b8e80941Smrg                   const GLvoid *indices)
726b8e80941Smrg{
727b8e80941Smrg   if (count == 0)
728b8e80941Smrg      return true;
729b8e80941Smrg
730b8e80941Smrg   /* Not using a VBO for indices, so avoid NULL pointer derefs later.
731b8e80941Smrg    */
732b8e80941Smrg   if (!_mesa_is_bufferobj(ctx->Array.VAO->IndexBufferObj) && indices == NULL)
733b8e80941Smrg      return true;
734b8e80941Smrg
735b8e80941Smrg   if (skip_validated_draw(ctx))
736b8e80941Smrg      return true;
737b8e80941Smrg
738b8e80941Smrg   return false;
739b8e80941Smrg}
740b8e80941Smrg
741b8e80941Smrg
742b8e80941Smrg/**
743b8e80941Smrg * Inner support for both _mesa_DrawElements and _mesa_DrawRangeElements.
744b8e80941Smrg * Do the rendering for a glDrawElements or glDrawRangeElements call after
745b8e80941Smrg * we've validated buffer bounds, etc.
746b8e80941Smrg */
747b8e80941Smrgstatic void
748b8e80941Smrg_mesa_validated_drawrangeelements(struct gl_context *ctx, GLenum mode,
749b8e80941Smrg                                  GLboolean index_bounds_valid,
750b8e80941Smrg                                  GLuint start, GLuint end,
751b8e80941Smrg                                  GLsizei count, GLenum type,
752b8e80941Smrg                                  const GLvoid * indices,
753b8e80941Smrg                                  GLint basevertex, GLuint numInstances,
754b8e80941Smrg                                  GLuint baseInstance)
755b8e80941Smrg{
756b8e80941Smrg   struct _mesa_index_buffer ib;
757b8e80941Smrg   struct _mesa_prim prim;
758b8e80941Smrg
759b8e80941Smrg   if (!index_bounds_valid) {
760b8e80941Smrg      assert(start == 0u);
761b8e80941Smrg      assert(end == ~0u);
762b8e80941Smrg   }
763b8e80941Smrg
764b8e80941Smrg   if (skip_draw_elements(ctx, count, indices))
765b8e80941Smrg      return;
766b8e80941Smrg
767b8e80941Smrg   ib.count = count;
768b8e80941Smrg   ib.index_size = sizeof_ib_type(type);
769b8e80941Smrg   ib.obj = ctx->Array.VAO->IndexBufferObj;
770b8e80941Smrg   ib.ptr = indices;
771b8e80941Smrg
772b8e80941Smrg   prim.begin = 1;
773b8e80941Smrg   prim.end = 1;
774b8e80941Smrg   prim.pad = 0;
775b8e80941Smrg   prim.mode = mode;
776b8e80941Smrg   prim.start = 0;
777b8e80941Smrg   prim.count = count;
778b8e80941Smrg   prim.indexed = 1;
779b8e80941Smrg   prim.is_indirect = 0;
780b8e80941Smrg   prim.basevertex = basevertex;
781b8e80941Smrg   prim.num_instances = numInstances;
782b8e80941Smrg   prim.base_instance = baseInstance;
783b8e80941Smrg   prim.draw_id = 0;
784b8e80941Smrg
785b8e80941Smrg   /* Need to give special consideration to rendering a range of
786b8e80941Smrg    * indices starting somewhere above zero.  Typically the
787b8e80941Smrg    * application is issuing multiple DrawRangeElements() to draw
788b8e80941Smrg    * successive primitives layed out linearly in the vertex arrays.
789b8e80941Smrg    * Unless the vertex arrays are all in a VBO (or locked as with
790b8e80941Smrg    * CVA), the OpenGL semantics imply that we need to re-read or
791b8e80941Smrg    * re-upload the vertex data on each draw call.
792b8e80941Smrg    *
793b8e80941Smrg    * In the case of hardware tnl, we want to avoid starting the
794b8e80941Smrg    * upload at zero, as it will mean every draw call uploads an
795b8e80941Smrg    * increasing amount of not-used vertex data.  Worse - in the
796b8e80941Smrg    * software tnl module, all those vertices might be transformed and
797b8e80941Smrg    * lit but never rendered.
798b8e80941Smrg    *
799b8e80941Smrg    * If we just upload or transform the vertices in start..end,
800b8e80941Smrg    * however, the indices will be incorrect.
801b8e80941Smrg    *
802b8e80941Smrg    * At this level, we don't know exactly what the requirements of
803b8e80941Smrg    * the backend are going to be, though it will likely boil down to
804b8e80941Smrg    * either:
805b8e80941Smrg    *
806b8e80941Smrg    * 1) Do nothing, everything is in a VBO and is processed once
807b8e80941Smrg    *       only.
808b8e80941Smrg    *
809b8e80941Smrg    * 2) Adjust the indices and vertex arrays so that start becomes
810b8e80941Smrg    *    zero.
811b8e80941Smrg    *
812b8e80941Smrg    * Rather than doing anything here, I'll provide a helper function
813b8e80941Smrg    * for the latter case elsewhere.
814b8e80941Smrg    */
815b8e80941Smrg
816b8e80941Smrg   ctx->Driver.Draw(ctx, &prim, 1, &ib,
817b8e80941Smrg                    index_bounds_valid, start, end, NULL, 0, NULL);
818b8e80941Smrg
819b8e80941Smrg   if (MESA_DEBUG_FLAGS & DEBUG_ALWAYS_FLUSH) {
820b8e80941Smrg      _mesa_flush(ctx);
821b8e80941Smrg   }
822b8e80941Smrg}
823b8e80941Smrg
824b8e80941Smrg
825b8e80941Smrg/**
826b8e80941Smrg * Called by glDrawRangeElementsBaseVertex() in immediate mode.
827b8e80941Smrg */
828b8e80941Smrgvoid GLAPIENTRY
829b8e80941Smrg_mesa_DrawRangeElementsBaseVertex(GLenum mode, GLuint start, GLuint end,
830b8e80941Smrg                                  GLsizei count, GLenum type,
831b8e80941Smrg                                  const GLvoid * indices, GLint basevertex)
832b8e80941Smrg{
833b8e80941Smrg   static GLuint warnCount = 0;
834b8e80941Smrg   GLboolean index_bounds_valid = GL_TRUE;
835b8e80941Smrg
836b8e80941Smrg   /* This is only useful to catch invalid values in the "end" parameter
837b8e80941Smrg    * like ~0.
838b8e80941Smrg    */
839b8e80941Smrg   GLuint max_element = 2 * 1000 * 1000 * 1000; /* just a big number */
840b8e80941Smrg
841b8e80941Smrg   GET_CURRENT_CONTEXT(ctx);
842b8e80941Smrg
843b8e80941Smrg   if (MESA_VERBOSE & VERBOSE_DRAW)
844b8e80941Smrg      _mesa_debug(ctx,
845b8e80941Smrg                  "glDrawRangeElementsBaseVertex(%s, %u, %u, %d, %s, %p, %d)\n",
846b8e80941Smrg                  _mesa_enum_to_string(mode), start, end, count,
847b8e80941Smrg                  _mesa_enum_to_string(type), indices, basevertex);
848b8e80941Smrg
849b8e80941Smrg   FLUSH_FOR_DRAW(ctx);
850b8e80941Smrg
851b8e80941Smrg   _mesa_set_draw_vao(ctx, ctx->Array.VAO, enabled_filter(ctx));
852b8e80941Smrg
853b8e80941Smrg   if (_mesa_is_no_error_enabled(ctx)) {
854b8e80941Smrg      if (ctx->NewState)
855b8e80941Smrg         _mesa_update_state(ctx);
856b8e80941Smrg   } else {
857b8e80941Smrg      if (!_mesa_validate_DrawRangeElements(ctx, mode, start, end, count,
858b8e80941Smrg                                            type, indices))
859b8e80941Smrg         return;
860b8e80941Smrg   }
861b8e80941Smrg
862b8e80941Smrg   if ((int) end + basevertex < 0 || start + basevertex >= max_element) {
863b8e80941Smrg      /* The application requested we draw using a range of indices that's
864b8e80941Smrg       * outside the bounds of the current VBO.  This is invalid and appears
865b8e80941Smrg       * to give undefined results.  The safest thing to do is to simply
866b8e80941Smrg       * ignore the range, in case the application botched their range tracking
867b8e80941Smrg       * but did provide valid indices.  Also issue a warning indicating that
868b8e80941Smrg       * the application is broken.
869b8e80941Smrg       */
870b8e80941Smrg      if (warnCount++ < 10) {
871b8e80941Smrg         _mesa_warning(ctx, "glDrawRangeElements(start %u, end %u, "
872b8e80941Smrg                       "basevertex %d, count %d, type 0x%x, indices=%p):\n"
873b8e80941Smrg                       "\trange is outside VBO bounds (max=%u); ignoring.\n"
874b8e80941Smrg                       "\tThis should be fixed in the application.",
875b8e80941Smrg                       start, end, basevertex, count, type, indices,
876b8e80941Smrg                       max_element - 1);
877b8e80941Smrg      }
878b8e80941Smrg      index_bounds_valid = GL_FALSE;
879b8e80941Smrg   }
880b8e80941Smrg
881b8e80941Smrg   /* NOTE: It's important that 'end' is a reasonable value.
882b8e80941Smrg    * in _tnl_draw_prims(), we use end to determine how many vertices
883b8e80941Smrg    * to transform.  If it's too large, we can unnecessarily split prims
884b8e80941Smrg    * or we can read/write out of memory in several different places!
885b8e80941Smrg    */
886b8e80941Smrg
887b8e80941Smrg   /* Catch/fix some potential user errors */
888b8e80941Smrg   if (type == GL_UNSIGNED_BYTE) {
889b8e80941Smrg      start = MIN2(start, 0xff);
890b8e80941Smrg      end = MIN2(end, 0xff);
891b8e80941Smrg   }
892b8e80941Smrg   else if (type == GL_UNSIGNED_SHORT) {
893b8e80941Smrg      start = MIN2(start, 0xffff);
894b8e80941Smrg      end = MIN2(end, 0xffff);
895b8e80941Smrg   }
896b8e80941Smrg
897b8e80941Smrg   if (0) {
898b8e80941Smrg      printf("glDraw[Range]Elements{,BaseVertex}"
899b8e80941Smrg             "(start %u, end %u, type 0x%x, count %d) ElemBuf %u, "
900b8e80941Smrg             "base %d\n",
901b8e80941Smrg             start, end, type, count,
902b8e80941Smrg             ctx->Array.VAO->IndexBufferObj->Name, basevertex);
903b8e80941Smrg   }
904b8e80941Smrg
905b8e80941Smrg   if ((int) start + basevertex < 0 || end + basevertex >= max_element)
906b8e80941Smrg      index_bounds_valid = GL_FALSE;
907b8e80941Smrg
908b8e80941Smrg#if 0
909b8e80941Smrg   check_draw_elements_data(ctx, count, type, indices, basevertex);
910b8e80941Smrg#else
911b8e80941Smrg   (void) check_draw_elements_data;
912b8e80941Smrg#endif
913b8e80941Smrg
914b8e80941Smrg   if (!index_bounds_valid) {
915b8e80941Smrg      start = 0;
916b8e80941Smrg      end = ~0;
917b8e80941Smrg   }
918b8e80941Smrg
919b8e80941Smrg   _mesa_validated_drawrangeelements(ctx, mode, index_bounds_valid, start, end,
920b8e80941Smrg                                     count, type, indices, basevertex, 1, 0);
921b8e80941Smrg}
922b8e80941Smrg
923b8e80941Smrg
924b8e80941Smrg/**
925b8e80941Smrg * Called by glDrawRangeElements() in immediate mode.
926b8e80941Smrg */
927b8e80941Smrgvoid GLAPIENTRY
928b8e80941Smrg_mesa_DrawRangeElements(GLenum mode, GLuint start, GLuint end,
929b8e80941Smrg                        GLsizei count, GLenum type, const GLvoid * indices)
930b8e80941Smrg{
931b8e80941Smrg   if (MESA_VERBOSE & VERBOSE_DRAW) {
932b8e80941Smrg      GET_CURRENT_CONTEXT(ctx);
933b8e80941Smrg      _mesa_debug(ctx,
934b8e80941Smrg                  "glDrawRangeElements(%s, %u, %u, %d, %s, %p)\n",
935b8e80941Smrg                  _mesa_enum_to_string(mode), start, end, count,
936b8e80941Smrg                  _mesa_enum_to_string(type), indices);
937b8e80941Smrg   }
938b8e80941Smrg
939b8e80941Smrg   _mesa_DrawRangeElementsBaseVertex(mode, start, end, count, type,
940b8e80941Smrg                                     indices, 0);
941b8e80941Smrg}
942b8e80941Smrg
943b8e80941Smrg
944b8e80941Smrg/**
945b8e80941Smrg * Called by glDrawElements() in immediate mode.
946b8e80941Smrg */
947b8e80941Smrgvoid GLAPIENTRY
948b8e80941Smrg_mesa_DrawElements(GLenum mode, GLsizei count, GLenum type,
949b8e80941Smrg                   const GLvoid * indices)
950b8e80941Smrg{
951b8e80941Smrg   GET_CURRENT_CONTEXT(ctx);
952b8e80941Smrg
953b8e80941Smrg   if (MESA_VERBOSE & VERBOSE_DRAW)
954b8e80941Smrg      _mesa_debug(ctx, "glDrawElements(%s, %u, %s, %p)\n",
955b8e80941Smrg                  _mesa_enum_to_string(mode), count,
956b8e80941Smrg                  _mesa_enum_to_string(type), indices);
957b8e80941Smrg
958b8e80941Smrg   FLUSH_FOR_DRAW(ctx);
959b8e80941Smrg
960b8e80941Smrg   _mesa_set_draw_vao(ctx, ctx->Array.VAO, enabled_filter(ctx));
961b8e80941Smrg
962b8e80941Smrg   if (_mesa_is_no_error_enabled(ctx)) {
963b8e80941Smrg      if (ctx->NewState)
964b8e80941Smrg         _mesa_update_state(ctx);
965b8e80941Smrg   } else {
966b8e80941Smrg      if (!_mesa_validate_DrawElements(ctx, mode, count, type, indices))
967b8e80941Smrg         return;
968b8e80941Smrg   }
969b8e80941Smrg
970b8e80941Smrg   _mesa_validated_drawrangeelements(ctx, mode, GL_FALSE, 0, ~0,
971b8e80941Smrg                                     count, type, indices, 0, 1, 0);
972b8e80941Smrg}
973b8e80941Smrg
974b8e80941Smrg
975b8e80941Smrg/**
976b8e80941Smrg * Called by glDrawElementsBaseVertex() in immediate mode.
977b8e80941Smrg */
978b8e80941Smrgvoid GLAPIENTRY
979b8e80941Smrg_mesa_DrawElementsBaseVertex(GLenum mode, GLsizei count, GLenum type,
980b8e80941Smrg                             const GLvoid * indices, GLint basevertex)
981b8e80941Smrg{
982b8e80941Smrg   GET_CURRENT_CONTEXT(ctx);
983b8e80941Smrg
984b8e80941Smrg   if (MESA_VERBOSE & VERBOSE_DRAW)
985b8e80941Smrg      _mesa_debug(ctx, "glDrawElements(%s, %u, %s, %p)\n",
986b8e80941Smrg                  _mesa_enum_to_string(mode), count,
987b8e80941Smrg                  _mesa_enum_to_string(type), indices);
988b8e80941Smrg
989b8e80941Smrg   FLUSH_FOR_DRAW(ctx);
990b8e80941Smrg
991b8e80941Smrg   _mesa_set_draw_vao(ctx, ctx->Array.VAO, enabled_filter(ctx));
992b8e80941Smrg
993b8e80941Smrg   if (_mesa_is_no_error_enabled(ctx)) {
994b8e80941Smrg      if (ctx->NewState)
995b8e80941Smrg         _mesa_update_state(ctx);
996b8e80941Smrg   } else {
997b8e80941Smrg      if (!_mesa_validate_DrawElements(ctx, mode, count, type, indices))
998b8e80941Smrg         return;
999b8e80941Smrg   }
1000b8e80941Smrg
1001b8e80941Smrg   _mesa_validated_drawrangeelements(ctx, mode, GL_FALSE, 0, ~0,
1002b8e80941Smrg                                     count, type, indices, basevertex, 1, 0);
1003b8e80941Smrg}
1004b8e80941Smrg
1005b8e80941Smrg
1006b8e80941Smrg/**
1007b8e80941Smrg * Called by glDrawElementsInstanced() in immediate mode.
1008b8e80941Smrg */
1009b8e80941Smrgstatic void GLAPIENTRY
1010b8e80941Smrg_mesa_exec_DrawElementsInstanced(GLenum mode, GLsizei count, GLenum type,
1011b8e80941Smrg                                 const GLvoid * indices, GLsizei numInstances)
1012b8e80941Smrg{
1013b8e80941Smrg   GET_CURRENT_CONTEXT(ctx);
1014b8e80941Smrg
1015b8e80941Smrg   if (MESA_VERBOSE & VERBOSE_DRAW)
1016b8e80941Smrg      _mesa_debug(ctx, "glDrawElements(%s, %u, %s, %p)\n",
1017b8e80941Smrg                  _mesa_enum_to_string(mode), count,
1018b8e80941Smrg                  _mesa_enum_to_string(type), indices);
1019b8e80941Smrg
1020b8e80941Smrg   FLUSH_FOR_DRAW(ctx);
1021b8e80941Smrg
1022b8e80941Smrg   _mesa_set_draw_vao(ctx, ctx->Array.VAO, enabled_filter(ctx));
1023b8e80941Smrg
1024b8e80941Smrg   if (_mesa_is_no_error_enabled(ctx)) {
1025b8e80941Smrg      if (ctx->NewState)
1026b8e80941Smrg         _mesa_update_state(ctx);
1027b8e80941Smrg   } else {
1028b8e80941Smrg      if (!_mesa_validate_DrawElementsInstanced(ctx, mode, count, type,
1029b8e80941Smrg                                                indices, numInstances))
1030b8e80941Smrg         return;
1031b8e80941Smrg   }
1032b8e80941Smrg
1033b8e80941Smrg   _mesa_validated_drawrangeelements(ctx, mode, GL_FALSE, 0, ~0,
1034b8e80941Smrg                                     count, type, indices, 0, numInstances, 0);
1035b8e80941Smrg}
1036b8e80941Smrg
1037b8e80941Smrg
1038b8e80941Smrg/**
1039b8e80941Smrg * Called by glDrawElementsInstancedBaseVertex() in immediate mode.
1040b8e80941Smrg */
1041b8e80941Smrgstatic void GLAPIENTRY
1042b8e80941Smrg_mesa_exec_DrawElementsInstancedBaseVertex(GLenum mode, GLsizei count,
1043b8e80941Smrg                                           GLenum type, const GLvoid * indices,
1044b8e80941Smrg                                           GLsizei numInstances,
1045b8e80941Smrg                                           GLint basevertex)
1046b8e80941Smrg{
1047b8e80941Smrg   GET_CURRENT_CONTEXT(ctx);
1048b8e80941Smrg
1049b8e80941Smrg   if (MESA_VERBOSE & VERBOSE_DRAW)
1050b8e80941Smrg      _mesa_debug(ctx,
1051b8e80941Smrg                  "glDrawElementsInstancedBaseVertex"
1052b8e80941Smrg                  "(%s, %d, %s, %p, %d; %d)\n",
1053b8e80941Smrg                  _mesa_enum_to_string(mode), count,
1054b8e80941Smrg                  _mesa_enum_to_string(type), indices,
1055b8e80941Smrg                  numInstances, basevertex);
1056b8e80941Smrg
1057b8e80941Smrg   FLUSH_FOR_DRAW(ctx);
1058b8e80941Smrg
1059b8e80941Smrg   _mesa_set_draw_vao(ctx, ctx->Array.VAO, enabled_filter(ctx));
1060b8e80941Smrg
1061b8e80941Smrg   if (_mesa_is_no_error_enabled(ctx)) {
1062b8e80941Smrg      if (ctx->NewState)
1063b8e80941Smrg         _mesa_update_state(ctx);
1064b8e80941Smrg   } else {
1065b8e80941Smrg      if (!_mesa_validate_DrawElementsInstanced(ctx, mode, count, type,
1066b8e80941Smrg                                                indices, numInstances))
1067b8e80941Smrg         return;
1068b8e80941Smrg   }
1069b8e80941Smrg
1070b8e80941Smrg   _mesa_validated_drawrangeelements(ctx, mode, GL_FALSE, 0, ~0,
1071b8e80941Smrg                                     count, type, indices,
1072b8e80941Smrg                                     basevertex, numInstances, 0);
1073b8e80941Smrg}
1074b8e80941Smrg
1075b8e80941Smrg
1076b8e80941Smrg/**
1077b8e80941Smrg * Called by glDrawElementsInstancedBaseInstance() in immediate mode.
1078b8e80941Smrg */
1079b8e80941Smrgstatic void GLAPIENTRY
1080b8e80941Smrg_mesa_exec_DrawElementsInstancedBaseInstance(GLenum mode, GLsizei count,
1081b8e80941Smrg                                             GLenum type,
1082b8e80941Smrg                                             const GLvoid *indices,
1083b8e80941Smrg                                             GLsizei numInstances,
1084b8e80941Smrg                                             GLuint baseInstance)
1085b8e80941Smrg{
1086b8e80941Smrg   GET_CURRENT_CONTEXT(ctx);
1087b8e80941Smrg
1088b8e80941Smrg   if (MESA_VERBOSE & VERBOSE_DRAW)
1089b8e80941Smrg      _mesa_debug(ctx,
1090b8e80941Smrg                  "glDrawElementsInstancedBaseInstance"
1091b8e80941Smrg                  "(%s, %d, %s, %p, %d, %d)\n",
1092b8e80941Smrg                  _mesa_enum_to_string(mode), count,
1093b8e80941Smrg                  _mesa_enum_to_string(type), indices,
1094b8e80941Smrg                  numInstances, baseInstance);
1095b8e80941Smrg
1096b8e80941Smrg   FLUSH_FOR_DRAW(ctx);
1097b8e80941Smrg
1098b8e80941Smrg   _mesa_set_draw_vao(ctx, ctx->Array.VAO, enabled_filter(ctx));
1099b8e80941Smrg
1100b8e80941Smrg   if (_mesa_is_no_error_enabled(ctx)) {
1101b8e80941Smrg      if (ctx->NewState)
1102b8e80941Smrg         _mesa_update_state(ctx);
1103b8e80941Smrg   } else {
1104b8e80941Smrg      if (!_mesa_validate_DrawElementsInstanced(ctx, mode, count, type,
1105b8e80941Smrg                                                indices, numInstances))
1106b8e80941Smrg         return;
1107b8e80941Smrg   }
1108b8e80941Smrg
1109b8e80941Smrg   _mesa_validated_drawrangeelements(ctx, mode, GL_FALSE, 0, ~0,
1110b8e80941Smrg                                     count, type, indices, 0, numInstances,
1111b8e80941Smrg                                     baseInstance);
1112b8e80941Smrg}
1113b8e80941Smrg
1114b8e80941Smrg
1115b8e80941Smrg/**
1116b8e80941Smrg * Called by glDrawElementsInstancedBaseVertexBaseInstance() in immediate mode.
1117b8e80941Smrg */
1118b8e80941Smrgstatic void GLAPIENTRY
1119b8e80941Smrg_mesa_exec_DrawElementsInstancedBaseVertexBaseInstance(GLenum mode,
1120b8e80941Smrg                                                       GLsizei count,
1121b8e80941Smrg                                                       GLenum type,
1122b8e80941Smrg                                                       const GLvoid *indices,
1123b8e80941Smrg                                                       GLsizei numInstances,
1124b8e80941Smrg                                                       GLint basevertex,
1125b8e80941Smrg                                                       GLuint baseInstance)
1126b8e80941Smrg{
1127b8e80941Smrg   GET_CURRENT_CONTEXT(ctx);
1128b8e80941Smrg
1129b8e80941Smrg   if (MESA_VERBOSE & VERBOSE_DRAW)
1130b8e80941Smrg      _mesa_debug(ctx,
1131b8e80941Smrg                  "glDrawElementsInstancedBaseVertexBaseInstance"
1132b8e80941Smrg                  "(%s, %d, %s, %p, %d, %d, %d)\n",
1133b8e80941Smrg                  _mesa_enum_to_string(mode), count,
1134b8e80941Smrg                  _mesa_enum_to_string(type), indices,
1135b8e80941Smrg                  numInstances, basevertex, baseInstance);
1136b8e80941Smrg
1137b8e80941Smrg   FLUSH_FOR_DRAW(ctx);
1138b8e80941Smrg
1139b8e80941Smrg   _mesa_set_draw_vao(ctx, ctx->Array.VAO, enabled_filter(ctx));
1140b8e80941Smrg
1141b8e80941Smrg   if (_mesa_is_no_error_enabled(ctx)) {
1142b8e80941Smrg      if (ctx->NewState)
1143b8e80941Smrg         _mesa_update_state(ctx);
1144b8e80941Smrg   } else {
1145b8e80941Smrg      if (!_mesa_validate_DrawElementsInstanced(ctx, mode, count, type,
1146b8e80941Smrg                                                indices, numInstances))
1147b8e80941Smrg         return;
1148b8e80941Smrg   }
1149b8e80941Smrg
1150b8e80941Smrg   _mesa_validated_drawrangeelements(ctx, mode, GL_FALSE, 0, ~0,
1151b8e80941Smrg                                     count, type, indices, basevertex,
1152b8e80941Smrg                                     numInstances, baseInstance);
1153b8e80941Smrg}
1154b8e80941Smrg
1155b8e80941Smrg
1156b8e80941Smrg/**
1157b8e80941Smrg * Inner support for both _mesa_MultiDrawElements() and
1158b8e80941Smrg * _mesa_MultiDrawRangeElements().
1159b8e80941Smrg * This does the actual rendering after we've checked array indexes, etc.
1160b8e80941Smrg */
1161b8e80941Smrgstatic void
1162b8e80941Smrg_mesa_validated_multidrawelements(struct gl_context *ctx, GLenum mode,
1163b8e80941Smrg                                  const GLsizei *count, GLenum type,
1164b8e80941Smrg                                  const GLvoid * const *indices,
1165b8e80941Smrg                                  GLsizei primcount, const GLint *basevertex)
1166b8e80941Smrg{
1167b8e80941Smrg   struct _mesa_index_buffer ib;
1168b8e80941Smrg   struct _mesa_prim *prim;
1169b8e80941Smrg   unsigned int index_type_size = sizeof_ib_type(type);
1170b8e80941Smrg   uintptr_t min_index_ptr, max_index_ptr;
1171b8e80941Smrg   GLboolean fallback = GL_FALSE;
1172b8e80941Smrg   int i;
1173b8e80941Smrg
1174b8e80941Smrg   if (primcount == 0)
1175b8e80941Smrg      return;
1176b8e80941Smrg
1177b8e80941Smrg   prim = calloc(primcount, sizeof(*prim));
1178b8e80941Smrg   if (prim == NULL) {
1179b8e80941Smrg      _mesa_error(ctx, GL_OUT_OF_MEMORY, "glMultiDrawElements");
1180b8e80941Smrg      return;
1181b8e80941Smrg   }
1182b8e80941Smrg
1183b8e80941Smrg   min_index_ptr = (uintptr_t) indices[0];
1184b8e80941Smrg   max_index_ptr = 0;
1185b8e80941Smrg   for (i = 0; i < primcount; i++) {
1186b8e80941Smrg      min_index_ptr = MIN2(min_index_ptr, (uintptr_t) indices[i]);
1187b8e80941Smrg      max_index_ptr = MAX2(max_index_ptr, (uintptr_t) indices[i] +
1188b8e80941Smrg                           index_type_size * count[i]);
1189b8e80941Smrg   }
1190b8e80941Smrg
1191b8e80941Smrg   /* Check if we can handle this thing as a bunch of index offsets from the
1192b8e80941Smrg    * same index pointer.  If we can't, then we have to fall back to doing
1193b8e80941Smrg    * a draw_prims per primitive.
1194b8e80941Smrg    * Check that the difference between each prim's indexes is a multiple of
1195b8e80941Smrg    * the index/element size.
1196b8e80941Smrg    */
1197b8e80941Smrg   if (index_type_size != 1) {
1198b8e80941Smrg      for (i = 0; i < primcount; i++) {
1199b8e80941Smrg         if ((((uintptr_t) indices[i] - min_index_ptr) % index_type_size) !=
1200b8e80941Smrg             0) {
1201b8e80941Smrg            fallback = GL_TRUE;
1202b8e80941Smrg            break;
1203b8e80941Smrg         }
1204b8e80941Smrg      }
1205b8e80941Smrg   }
1206b8e80941Smrg
1207b8e80941Smrg   /* Draw primitives individually if one count is zero, so we can easily skip
1208b8e80941Smrg    * that primitive.
1209b8e80941Smrg    */
1210b8e80941Smrg   for (i = 0; i < primcount; i++) {
1211b8e80941Smrg      if (count[i] == 0) {
1212b8e80941Smrg         fallback = GL_TRUE;
1213b8e80941Smrg         break;
1214b8e80941Smrg      }
1215b8e80941Smrg   }
1216b8e80941Smrg
1217b8e80941Smrg   /* If the index buffer isn't in a VBO, then treating the application's
1218b8e80941Smrg    * subranges of the index buffer as one large index buffer may lead to
1219b8e80941Smrg    * us reading unmapped memory.
1220b8e80941Smrg    */
1221b8e80941Smrg   if (!_mesa_is_bufferobj(ctx->Array.VAO->IndexBufferObj))
1222b8e80941Smrg      fallback = GL_TRUE;
1223b8e80941Smrg
1224b8e80941Smrg   if (!fallback) {
1225b8e80941Smrg      ib.count = (max_index_ptr - min_index_ptr) / index_type_size;
1226b8e80941Smrg      ib.index_size = sizeof_ib_type(type);
1227b8e80941Smrg      ib.obj = ctx->Array.VAO->IndexBufferObj;
1228b8e80941Smrg      ib.ptr = (void *) min_index_ptr;
1229b8e80941Smrg
1230b8e80941Smrg      for (i = 0; i < primcount; i++) {
1231b8e80941Smrg         prim[i].begin = (i == 0);
1232b8e80941Smrg         prim[i].end = (i == primcount - 1);
1233b8e80941Smrg         prim[i].pad = 0;
1234b8e80941Smrg         prim[i].mode = mode;
1235b8e80941Smrg         prim[i].start =
1236b8e80941Smrg            ((uintptr_t) indices[i] - min_index_ptr) / index_type_size;
1237b8e80941Smrg         prim[i].count = count[i];
1238b8e80941Smrg         prim[i].indexed = 1;
1239b8e80941Smrg         prim[i].num_instances = 1;
1240b8e80941Smrg         prim[i].base_instance = 0;
1241b8e80941Smrg         prim[i].draw_id = i;
1242b8e80941Smrg         prim[i].is_indirect = 0;
1243b8e80941Smrg         if (basevertex != NULL)
1244b8e80941Smrg            prim[i].basevertex = basevertex[i];
1245b8e80941Smrg         else
1246b8e80941Smrg            prim[i].basevertex = 0;
1247b8e80941Smrg      }
1248b8e80941Smrg
1249b8e80941Smrg      ctx->Driver.Draw(ctx, prim, primcount, &ib,
1250b8e80941Smrg                       false, 0, ~0, NULL, 0, NULL);
1251b8e80941Smrg   }
1252b8e80941Smrg   else {
1253b8e80941Smrg      /* render one prim at a time */
1254b8e80941Smrg      for (i = 0; i < primcount; i++) {
1255b8e80941Smrg         if (count[i] == 0)
1256b8e80941Smrg            continue;
1257b8e80941Smrg         ib.count = count[i];
1258b8e80941Smrg         ib.index_size = sizeof_ib_type(type);
1259b8e80941Smrg         ib.obj = ctx->Array.VAO->IndexBufferObj;
1260b8e80941Smrg         ib.ptr = indices[i];
1261b8e80941Smrg
1262b8e80941Smrg         prim[0].begin = 1;
1263b8e80941Smrg         prim[0].end = 1;
1264b8e80941Smrg         prim[0].pad = 0;
1265b8e80941Smrg         prim[0].mode = mode;
1266b8e80941Smrg         prim[0].start = 0;
1267b8e80941Smrg         prim[0].count = count[i];
1268b8e80941Smrg         prim[0].indexed = 1;
1269b8e80941Smrg         prim[0].num_instances = 1;
1270b8e80941Smrg         prim[0].base_instance = 0;
1271b8e80941Smrg         prim[0].draw_id = i;
1272b8e80941Smrg         prim[0].is_indirect = 0;
1273b8e80941Smrg         if (basevertex != NULL)
1274b8e80941Smrg            prim[0].basevertex = basevertex[i];
1275b8e80941Smrg         else
1276b8e80941Smrg            prim[0].basevertex = 0;
1277b8e80941Smrg
1278b8e80941Smrg         ctx->Driver.Draw(ctx, prim, 1, &ib, false, 0, ~0, NULL, 0, NULL);
1279b8e80941Smrg      }
1280b8e80941Smrg   }
1281b8e80941Smrg
1282b8e80941Smrg   free(prim);
1283b8e80941Smrg
1284b8e80941Smrg   if (MESA_DEBUG_FLAGS & DEBUG_ALWAYS_FLUSH) {
1285b8e80941Smrg      _mesa_flush(ctx);
1286b8e80941Smrg   }
1287b8e80941Smrg}
1288b8e80941Smrg
1289b8e80941Smrg
1290b8e80941Smrgvoid GLAPIENTRY
1291b8e80941Smrg_mesa_MultiDrawElements(GLenum mode, const GLsizei *count, GLenum type,
1292b8e80941Smrg                        const GLvoid * const *indices, GLsizei primcount)
1293b8e80941Smrg{
1294b8e80941Smrg   GET_CURRENT_CONTEXT(ctx);
1295b8e80941Smrg
1296b8e80941Smrg   FLUSH_FOR_DRAW(ctx);
1297b8e80941Smrg
1298b8e80941Smrg   _mesa_set_draw_vao(ctx, ctx->Array.VAO, enabled_filter(ctx));
1299b8e80941Smrg
1300b8e80941Smrg   if (!_mesa_validate_MultiDrawElements(ctx, mode, count, type, indices,
1301b8e80941Smrg                                         primcount))
1302b8e80941Smrg      return;
1303b8e80941Smrg
1304b8e80941Smrg   if (skip_validated_draw(ctx))
1305b8e80941Smrg      return;
1306b8e80941Smrg
1307b8e80941Smrg   _mesa_validated_multidrawelements(ctx, mode, count, type, indices, primcount,
1308b8e80941Smrg                                     NULL);
1309b8e80941Smrg}
1310b8e80941Smrg
1311b8e80941Smrg
1312b8e80941Smrgvoid GLAPIENTRY
1313b8e80941Smrg_mesa_MultiDrawElementsBaseVertex(GLenum mode,
1314b8e80941Smrg                                  const GLsizei *count, GLenum type,
1315b8e80941Smrg                                  const GLvoid * const *indices,
1316b8e80941Smrg                                  GLsizei primcount,
1317b8e80941Smrg                                  const GLsizei *basevertex)
1318b8e80941Smrg{
1319b8e80941Smrg   GET_CURRENT_CONTEXT(ctx);
1320b8e80941Smrg
1321b8e80941Smrg   FLUSH_FOR_DRAW(ctx);
1322b8e80941Smrg
1323b8e80941Smrg   _mesa_set_draw_vao(ctx, ctx->Array.VAO, enabled_filter(ctx));
1324b8e80941Smrg
1325b8e80941Smrg   if (_mesa_is_no_error_enabled(ctx)) {
1326b8e80941Smrg      if (ctx->NewState)
1327b8e80941Smrg         _mesa_update_state(ctx);
1328b8e80941Smrg   } else {
1329b8e80941Smrg      if (!_mesa_validate_MultiDrawElements(ctx, mode, count, type, indices,
1330b8e80941Smrg                                            primcount))
1331b8e80941Smrg         return;
1332b8e80941Smrg   }
1333b8e80941Smrg
1334b8e80941Smrg   if (skip_validated_draw(ctx))
1335b8e80941Smrg      return;
1336b8e80941Smrg
1337b8e80941Smrg   _mesa_validated_multidrawelements(ctx, mode, count, type, indices, primcount,
1338b8e80941Smrg                                     basevertex);
1339b8e80941Smrg}
1340b8e80941Smrg
1341b8e80941Smrg
1342b8e80941Smrg/**
1343b8e80941Smrg * Draw a GL primitive using a vertex count obtained from transform feedback.
1344b8e80941Smrg * \param mode  the type of GL primitive to draw
1345b8e80941Smrg * \param obj  the transform feedback object to use
1346b8e80941Smrg * \param stream  index of the transform feedback stream from which to
1347b8e80941Smrg *                get the primitive count.
1348b8e80941Smrg * \param numInstances  number of instances to draw
1349b8e80941Smrg */
1350b8e80941Smrgstatic void
1351b8e80941Smrg_mesa_draw_transform_feedback(struct gl_context *ctx, GLenum mode,
1352b8e80941Smrg                              struct gl_transform_feedback_object *obj,
1353b8e80941Smrg                              GLuint stream, GLuint numInstances)
1354b8e80941Smrg{
1355b8e80941Smrg   struct _mesa_prim prim;
1356b8e80941Smrg
1357b8e80941Smrg   FLUSH_FOR_DRAW(ctx);
1358b8e80941Smrg
1359b8e80941Smrg   _mesa_set_draw_vao(ctx, ctx->Array.VAO, enabled_filter(ctx));
1360b8e80941Smrg
1361b8e80941Smrg   if (_mesa_is_no_error_enabled(ctx)) {
1362b8e80941Smrg      if (ctx->NewState)
1363b8e80941Smrg         _mesa_update_state(ctx);
1364b8e80941Smrg   } else {
1365b8e80941Smrg      if (!_mesa_validate_DrawTransformFeedback(ctx, mode, obj, stream,
1366b8e80941Smrg                                                numInstances)) {
1367b8e80941Smrg         return;
1368b8e80941Smrg      }
1369b8e80941Smrg   }
1370b8e80941Smrg
1371b8e80941Smrg   if (ctx->Driver.GetTransformFeedbackVertexCount &&
1372b8e80941Smrg       (ctx->Const.AlwaysUseGetTransformFeedbackVertexCount ||
1373b8e80941Smrg        !_mesa_all_varyings_in_vbos(ctx->Array.VAO))) {
1374b8e80941Smrg      GLsizei n =
1375b8e80941Smrg         ctx->Driver.GetTransformFeedbackVertexCount(ctx, obj, stream);
1376b8e80941Smrg      _mesa_draw_arrays(ctx, mode, 0, n, numInstances, 0, 0);
1377b8e80941Smrg      return;
1378b8e80941Smrg   }
1379b8e80941Smrg
1380b8e80941Smrg   if (skip_validated_draw(ctx))
1381b8e80941Smrg      return;
1382b8e80941Smrg
1383b8e80941Smrg   /* init most fields to zero */
1384b8e80941Smrg   memset(&prim, 0, sizeof(prim));
1385b8e80941Smrg   prim.begin = 1;
1386b8e80941Smrg   prim.end = 1;
1387b8e80941Smrg   prim.mode = mode;
1388b8e80941Smrg   prim.num_instances = numInstances;
1389b8e80941Smrg   prim.base_instance = 0;
1390b8e80941Smrg   prim.is_indirect = 0;
1391b8e80941Smrg
1392b8e80941Smrg   /* Maybe we should do some primitive splitting for primitive restart
1393b8e80941Smrg    * (like in DrawArrays), but we have no way to know how many vertices
1394b8e80941Smrg    * will be rendered. */
1395b8e80941Smrg
1396b8e80941Smrg   ctx->Driver.Draw(ctx, &prim, 1, NULL, GL_FALSE, 0, ~0, obj, stream, NULL);
1397b8e80941Smrg
1398b8e80941Smrg   if (MESA_DEBUG_FLAGS & DEBUG_ALWAYS_FLUSH) {
1399b8e80941Smrg      _mesa_flush(ctx);
1400b8e80941Smrg   }
1401b8e80941Smrg}
1402b8e80941Smrg
1403b8e80941Smrg
1404b8e80941Smrg/**
1405b8e80941Smrg * Like DrawArrays, but take the count from a transform feedback object.
1406b8e80941Smrg * \param mode  GL_POINTS, GL_LINES, GL_TRIANGLE_STRIP, etc.
1407b8e80941Smrg * \param name  the transform feedback object
1408b8e80941Smrg * User still has to setup of the vertex attribute info with
1409b8e80941Smrg * glVertexPointer, glColorPointer, etc.
1410b8e80941Smrg * Part of GL_ARB_transform_feedback2.
1411b8e80941Smrg */
1412b8e80941Smrgvoid GLAPIENTRY
1413b8e80941Smrg_mesa_DrawTransformFeedback(GLenum mode, GLuint name)
1414b8e80941Smrg{
1415b8e80941Smrg   GET_CURRENT_CONTEXT(ctx);
1416b8e80941Smrg   struct gl_transform_feedback_object *obj =
1417b8e80941Smrg      _mesa_lookup_transform_feedback_object(ctx, name);
1418b8e80941Smrg
1419b8e80941Smrg   if (MESA_VERBOSE & VERBOSE_DRAW)
1420b8e80941Smrg      _mesa_debug(ctx, "glDrawTransformFeedback(%s, %d)\n",
1421b8e80941Smrg                  _mesa_enum_to_string(mode), name);
1422b8e80941Smrg
1423b8e80941Smrg   _mesa_draw_transform_feedback(ctx, mode, obj, 0, 1);
1424b8e80941Smrg}
1425b8e80941Smrg
1426b8e80941Smrg
1427b8e80941Smrgstatic void GLAPIENTRY
1428b8e80941Smrg_mesa_exec_DrawTransformFeedbackStream(GLenum mode, GLuint name, GLuint stream)
1429b8e80941Smrg{
1430b8e80941Smrg   GET_CURRENT_CONTEXT(ctx);
1431b8e80941Smrg   struct gl_transform_feedback_object *obj =
1432b8e80941Smrg      _mesa_lookup_transform_feedback_object(ctx, name);
1433b8e80941Smrg
1434b8e80941Smrg   if (MESA_VERBOSE & VERBOSE_DRAW)
1435b8e80941Smrg      _mesa_debug(ctx, "glDrawTransformFeedbackStream(%s, %u, %u)\n",
1436b8e80941Smrg                  _mesa_enum_to_string(mode), name, stream);
1437b8e80941Smrg
1438b8e80941Smrg   _mesa_draw_transform_feedback(ctx, mode, obj, stream, 1);
1439b8e80941Smrg}
1440b8e80941Smrg
1441b8e80941Smrg
1442b8e80941Smrgstatic void GLAPIENTRY
1443b8e80941Smrg_mesa_exec_DrawTransformFeedbackInstanced(GLenum mode, GLuint name,
1444b8e80941Smrg                                          GLsizei primcount)
1445b8e80941Smrg{
1446b8e80941Smrg   GET_CURRENT_CONTEXT(ctx);
1447b8e80941Smrg   struct gl_transform_feedback_object *obj =
1448b8e80941Smrg      _mesa_lookup_transform_feedback_object(ctx, name);
1449b8e80941Smrg
1450b8e80941Smrg   if (MESA_VERBOSE & VERBOSE_DRAW)
1451b8e80941Smrg      _mesa_debug(ctx, "glDrawTransformFeedbackInstanced(%s, %d)\n",
1452b8e80941Smrg                  _mesa_enum_to_string(mode), name);
1453b8e80941Smrg
1454b8e80941Smrg   _mesa_draw_transform_feedback(ctx, mode, obj, 0, primcount);
1455b8e80941Smrg}
1456b8e80941Smrg
1457b8e80941Smrg
1458b8e80941Smrgstatic void GLAPIENTRY
1459b8e80941Smrg_mesa_exec_DrawTransformFeedbackStreamInstanced(GLenum mode, GLuint name,
1460b8e80941Smrg                                                GLuint stream,
1461b8e80941Smrg                                                GLsizei primcount)
1462b8e80941Smrg{
1463b8e80941Smrg   GET_CURRENT_CONTEXT(ctx);
1464b8e80941Smrg   struct gl_transform_feedback_object *obj =
1465b8e80941Smrg      _mesa_lookup_transform_feedback_object(ctx, name);
1466b8e80941Smrg
1467b8e80941Smrg   if (MESA_VERBOSE & VERBOSE_DRAW)
1468b8e80941Smrg      _mesa_debug(ctx, "glDrawTransformFeedbackStreamInstanced"
1469b8e80941Smrg                  "(%s, %u, %u, %i)\n",
1470b8e80941Smrg                  _mesa_enum_to_string(mode), name, stream, primcount);
1471b8e80941Smrg
1472b8e80941Smrg   _mesa_draw_transform_feedback(ctx, mode, obj, stream, primcount);
1473b8e80941Smrg}
1474b8e80941Smrg
1475b8e80941Smrg
1476b8e80941Smrgstatic void
1477b8e80941Smrg_mesa_validated_drawarraysindirect(struct gl_context *ctx,
1478b8e80941Smrg                                   GLenum mode, const GLvoid *indirect)
1479b8e80941Smrg{
1480b8e80941Smrg   ctx->Driver.DrawIndirect(ctx, mode,
1481b8e80941Smrg                            ctx->DrawIndirectBuffer, (GLsizeiptr) indirect,
1482b8e80941Smrg                            1 /* draw_count */ , 16 /* stride */ ,
1483b8e80941Smrg                            NULL, 0, NULL);
1484b8e80941Smrg
1485b8e80941Smrg   if (MESA_DEBUG_FLAGS & DEBUG_ALWAYS_FLUSH)
1486b8e80941Smrg      _mesa_flush(ctx);
1487b8e80941Smrg}
1488b8e80941Smrg
1489b8e80941Smrg
1490b8e80941Smrgstatic void
1491b8e80941Smrg_mesa_validated_multidrawarraysindirect(struct gl_context *ctx,
1492b8e80941Smrg                                        GLenum mode,
1493b8e80941Smrg                                        const GLvoid *indirect,
1494b8e80941Smrg                                        GLsizei primcount, GLsizei stride)
1495b8e80941Smrg{
1496b8e80941Smrg   GLsizeiptr offset = (GLsizeiptr) indirect;
1497b8e80941Smrg
1498b8e80941Smrg   if (primcount == 0)
1499b8e80941Smrg      return;
1500b8e80941Smrg
1501b8e80941Smrg   ctx->Driver.DrawIndirect(ctx, mode, ctx->DrawIndirectBuffer, offset,
1502b8e80941Smrg                            primcount, stride, NULL, 0, NULL);
1503b8e80941Smrg
1504b8e80941Smrg   if (MESA_DEBUG_FLAGS & DEBUG_ALWAYS_FLUSH)
1505b8e80941Smrg      _mesa_flush(ctx);
1506b8e80941Smrg}
1507b8e80941Smrg
1508b8e80941Smrg
1509b8e80941Smrgstatic void
1510b8e80941Smrg_mesa_validated_drawelementsindirect(struct gl_context *ctx,
1511b8e80941Smrg                                     GLenum mode, GLenum type,
1512b8e80941Smrg                                     const GLvoid *indirect)
1513b8e80941Smrg{
1514b8e80941Smrg   struct _mesa_index_buffer ib;
1515b8e80941Smrg
1516b8e80941Smrg   ib.count = 0;                /* unknown */
1517b8e80941Smrg   ib.index_size = sizeof_ib_type(type);
1518b8e80941Smrg   ib.obj = ctx->Array.VAO->IndexBufferObj;
1519b8e80941Smrg   ib.ptr = NULL;
1520b8e80941Smrg
1521b8e80941Smrg   ctx->Driver.DrawIndirect(ctx, mode,
1522b8e80941Smrg                            ctx->DrawIndirectBuffer, (GLsizeiptr) indirect,
1523b8e80941Smrg                            1 /* draw_count */ , 20 /* stride */ ,
1524b8e80941Smrg                            NULL, 0, &ib);
1525b8e80941Smrg
1526b8e80941Smrg   if (MESA_DEBUG_FLAGS & DEBUG_ALWAYS_FLUSH)
1527b8e80941Smrg      _mesa_flush(ctx);
1528b8e80941Smrg}
1529b8e80941Smrg
1530b8e80941Smrg
1531b8e80941Smrgstatic void
1532b8e80941Smrg_mesa_validated_multidrawelementsindirect(struct gl_context *ctx,
1533b8e80941Smrg                                          GLenum mode, GLenum type,
1534b8e80941Smrg                                          const GLvoid *indirect,
1535b8e80941Smrg                                          GLsizei primcount, GLsizei stride)
1536b8e80941Smrg{
1537b8e80941Smrg   struct _mesa_index_buffer ib;
1538b8e80941Smrg   GLsizeiptr offset = (GLsizeiptr) indirect;
1539b8e80941Smrg
1540b8e80941Smrg   if (primcount == 0)
1541b8e80941Smrg      return;
1542b8e80941Smrg
1543b8e80941Smrg   /* NOTE: IndexBufferObj is guaranteed to be a VBO. */
1544b8e80941Smrg
1545b8e80941Smrg   ib.count = 0;                /* unknown */
1546b8e80941Smrg   ib.index_size = sizeof_ib_type(type);
1547b8e80941Smrg   ib.obj = ctx->Array.VAO->IndexBufferObj;
1548b8e80941Smrg   ib.ptr = NULL;
1549b8e80941Smrg
1550b8e80941Smrg   ctx->Driver.DrawIndirect(ctx, mode,
1551b8e80941Smrg                            ctx->DrawIndirectBuffer, offset,
1552b8e80941Smrg                            primcount, stride, NULL, 0, &ib);
1553b8e80941Smrg
1554b8e80941Smrg   if (MESA_DEBUG_FLAGS & DEBUG_ALWAYS_FLUSH)
1555b8e80941Smrg      _mesa_flush(ctx);
1556b8e80941Smrg}
1557b8e80941Smrg
1558b8e80941Smrg
1559b8e80941Smrg/**
1560b8e80941Smrg * Like [Multi]DrawArrays/Elements, but they take most arguments from
1561b8e80941Smrg * a buffer object.
1562b8e80941Smrg */
1563b8e80941Smrgstatic void GLAPIENTRY
1564b8e80941Smrg_mesa_exec_DrawArraysIndirect(GLenum mode, const GLvoid *indirect)
1565b8e80941Smrg{
1566b8e80941Smrg   GET_CURRENT_CONTEXT(ctx);
1567b8e80941Smrg
1568b8e80941Smrg   if (MESA_VERBOSE & VERBOSE_DRAW)
1569b8e80941Smrg      _mesa_debug(ctx, "glDrawArraysIndirect(%s, %p)\n",
1570b8e80941Smrg                  _mesa_enum_to_string(mode), indirect);
1571b8e80941Smrg
1572b8e80941Smrg   /* From the ARB_draw_indirect spec:
1573b8e80941Smrg    *
1574b8e80941Smrg    *    "Initially zero is bound to DRAW_INDIRECT_BUFFER. In the
1575b8e80941Smrg    *    compatibility profile, this indicates that DrawArraysIndirect and
1576b8e80941Smrg    *    DrawElementsIndirect are to source their arguments directly from the
1577b8e80941Smrg    *    pointer passed as their <indirect> parameters."
1578b8e80941Smrg    */
1579b8e80941Smrg   if (ctx->API == API_OPENGL_COMPAT &&
1580b8e80941Smrg       !_mesa_is_bufferobj(ctx->DrawIndirectBuffer)) {
1581b8e80941Smrg      DrawArraysIndirectCommand *cmd = (DrawArraysIndirectCommand *) indirect;
1582b8e80941Smrg
1583b8e80941Smrg      _mesa_exec_DrawArraysInstancedBaseInstance(mode, cmd->first, cmd->count,
1584b8e80941Smrg                                                 cmd->primCount,
1585b8e80941Smrg                                                 cmd->baseInstance);
1586b8e80941Smrg      return;
1587b8e80941Smrg   }
1588b8e80941Smrg
1589b8e80941Smrg   FLUSH_FOR_DRAW(ctx);
1590b8e80941Smrg
1591b8e80941Smrg   _mesa_set_draw_vao(ctx, ctx->Array.VAO, enabled_filter(ctx));
1592b8e80941Smrg
1593b8e80941Smrg   if (_mesa_is_no_error_enabled(ctx)) {
1594b8e80941Smrg      if (ctx->NewState)
1595b8e80941Smrg         _mesa_update_state(ctx);
1596b8e80941Smrg   } else {
1597b8e80941Smrg      if (!_mesa_validate_DrawArraysIndirect(ctx, mode, indirect))
1598b8e80941Smrg         return;
1599b8e80941Smrg   }
1600b8e80941Smrg
1601b8e80941Smrg   if (skip_validated_draw(ctx))
1602b8e80941Smrg      return;
1603b8e80941Smrg
1604b8e80941Smrg   _mesa_validated_drawarraysindirect(ctx, mode, indirect);
1605b8e80941Smrg}
1606b8e80941Smrg
1607b8e80941Smrg
1608b8e80941Smrgstatic void GLAPIENTRY
1609b8e80941Smrg_mesa_exec_DrawElementsIndirect(GLenum mode, GLenum type, const GLvoid *indirect)
1610b8e80941Smrg{
1611b8e80941Smrg   GET_CURRENT_CONTEXT(ctx);
1612b8e80941Smrg
1613b8e80941Smrg   if (MESA_VERBOSE & VERBOSE_DRAW)
1614b8e80941Smrg      _mesa_debug(ctx, "glDrawElementsIndirect(%s, %s, %p)\n",
1615b8e80941Smrg                  _mesa_enum_to_string(mode),
1616b8e80941Smrg                  _mesa_enum_to_string(type), indirect);
1617b8e80941Smrg
1618b8e80941Smrg   /* From the ARB_draw_indirect spec:
1619b8e80941Smrg    *
1620b8e80941Smrg    *    "Initially zero is bound to DRAW_INDIRECT_BUFFER. In the
1621b8e80941Smrg    *    compatibility profile, this indicates that DrawArraysIndirect and
1622b8e80941Smrg    *    DrawElementsIndirect are to source their arguments directly from the
1623b8e80941Smrg    *    pointer passed as their <indirect> parameters."
1624b8e80941Smrg    */
1625b8e80941Smrg   if (ctx->API == API_OPENGL_COMPAT &&
1626b8e80941Smrg       !_mesa_is_bufferobj(ctx->DrawIndirectBuffer)) {
1627b8e80941Smrg      /*
1628b8e80941Smrg       * Unlike regular DrawElementsInstancedBaseVertex commands, the indices
1629b8e80941Smrg       * may not come from a client array and must come from an index buffer.
1630b8e80941Smrg       * If no element array buffer is bound, an INVALID_OPERATION error is
1631b8e80941Smrg       * generated.
1632b8e80941Smrg       */
1633b8e80941Smrg      if (!_mesa_is_bufferobj(ctx->Array.VAO->IndexBufferObj)) {
1634b8e80941Smrg         _mesa_error(ctx, GL_INVALID_OPERATION,
1635b8e80941Smrg                     "glDrawElementsIndirect(no buffer bound "
1636b8e80941Smrg                     "to GL_ELEMENT_ARRAY_BUFFER)");
1637b8e80941Smrg      } else {
1638b8e80941Smrg         DrawElementsIndirectCommand *cmd =
1639b8e80941Smrg            (DrawElementsIndirectCommand *) indirect;
1640b8e80941Smrg
1641b8e80941Smrg         /* Convert offset to pointer */
1642b8e80941Smrg         void *offset = (void *)
1643b8e80941Smrg            ((cmd->firstIndex * _mesa_sizeof_type(type)) & 0xffffffffUL);
1644b8e80941Smrg
1645b8e80941Smrg         _mesa_exec_DrawElementsInstancedBaseVertexBaseInstance(mode, cmd->count,
1646b8e80941Smrg                                                                type, offset,
1647b8e80941Smrg                                                                cmd->primCount,
1648b8e80941Smrg                                                                cmd->baseVertex,
1649b8e80941Smrg                                                                cmd->baseInstance);
1650b8e80941Smrg      }
1651b8e80941Smrg
1652b8e80941Smrg      return;
1653b8e80941Smrg   }
1654b8e80941Smrg
1655b8e80941Smrg   FLUSH_FOR_DRAW(ctx);
1656b8e80941Smrg
1657b8e80941Smrg   _mesa_set_draw_vao(ctx, ctx->Array.VAO, enabled_filter(ctx));
1658b8e80941Smrg
1659b8e80941Smrg   if (_mesa_is_no_error_enabled(ctx)) {
1660b8e80941Smrg      if (ctx->NewState)
1661b8e80941Smrg         _mesa_update_state(ctx);
1662b8e80941Smrg   } else {
1663b8e80941Smrg      if (!_mesa_validate_DrawElementsIndirect(ctx, mode, type, indirect))
1664b8e80941Smrg         return;
1665b8e80941Smrg   }
1666b8e80941Smrg
1667b8e80941Smrg   if (skip_validated_draw(ctx))
1668b8e80941Smrg      return;
1669b8e80941Smrg
1670b8e80941Smrg   _mesa_validated_drawelementsindirect(ctx, mode, type, indirect);
1671b8e80941Smrg}
1672b8e80941Smrg
1673b8e80941Smrg
1674b8e80941Smrgstatic void GLAPIENTRY
1675b8e80941Smrg_mesa_exec_MultiDrawArraysIndirect(GLenum mode, const GLvoid *indirect,
1676b8e80941Smrg                                   GLsizei primcount, GLsizei stride)
1677b8e80941Smrg{
1678b8e80941Smrg   GET_CURRENT_CONTEXT(ctx);
1679b8e80941Smrg
1680b8e80941Smrg   if (MESA_VERBOSE & VERBOSE_DRAW)
1681b8e80941Smrg      _mesa_debug(ctx, "glMultiDrawArraysIndirect(%s, %p, %i, %i)\n",
1682b8e80941Smrg                  _mesa_enum_to_string(mode), indirect, primcount, stride);
1683b8e80941Smrg
1684b8e80941Smrg   /* If <stride> is zero, the array elements are treated as tightly packed. */
1685b8e80941Smrg   if (stride == 0)
1686b8e80941Smrg      stride = sizeof(DrawArraysIndirectCommand);
1687b8e80941Smrg
1688b8e80941Smrg   /* From the ARB_draw_indirect spec:
1689b8e80941Smrg    *
1690b8e80941Smrg    *    "Initially zero is bound to DRAW_INDIRECT_BUFFER. In the
1691b8e80941Smrg    *    compatibility profile, this indicates that DrawArraysIndirect and
1692b8e80941Smrg    *    DrawElementsIndirect are to source their arguments directly from the
1693b8e80941Smrg    *    pointer passed as their <indirect> parameters."
1694b8e80941Smrg    */
1695b8e80941Smrg   if (ctx->API == API_OPENGL_COMPAT &&
1696b8e80941Smrg       !_mesa_is_bufferobj(ctx->DrawIndirectBuffer)) {
1697b8e80941Smrg
1698b8e80941Smrg      if (!_mesa_valid_draw_indirect_multi(ctx, primcount, stride,
1699b8e80941Smrg                                           "glMultiDrawArraysIndirect"))
1700b8e80941Smrg         return;
1701b8e80941Smrg
1702b8e80941Smrg      const ubyte *ptr = (const ubyte *) indirect;
1703b8e80941Smrg      for (unsigned i = 0; i < primcount; i++) {
1704b8e80941Smrg         DrawArraysIndirectCommand *cmd = (DrawArraysIndirectCommand *) ptr;
1705b8e80941Smrg         _mesa_exec_DrawArraysInstancedBaseInstance(mode, cmd->first,
1706b8e80941Smrg                                                    cmd->count, cmd->primCount,
1707b8e80941Smrg                                                    cmd->baseInstance);
1708b8e80941Smrg
1709b8e80941Smrg         if (stride == 0) {
1710b8e80941Smrg            ptr += sizeof(DrawArraysIndirectCommand);
1711b8e80941Smrg         } else {
1712b8e80941Smrg            ptr += stride;
1713b8e80941Smrg         }
1714b8e80941Smrg      }
1715b8e80941Smrg
1716b8e80941Smrg      return;
1717b8e80941Smrg   }
1718b8e80941Smrg
1719b8e80941Smrg   FLUSH_FOR_DRAW(ctx);
1720b8e80941Smrg
1721b8e80941Smrg   _mesa_set_draw_vao(ctx, ctx->Array.VAO, enabled_filter(ctx));
1722b8e80941Smrg
1723b8e80941Smrg   if (_mesa_is_no_error_enabled(ctx)) {
1724b8e80941Smrg      if (ctx->NewState)
1725b8e80941Smrg         _mesa_update_state(ctx);
1726b8e80941Smrg   } else {
1727b8e80941Smrg      if (!_mesa_validate_MultiDrawArraysIndirect(ctx, mode, indirect,
1728b8e80941Smrg                                                  primcount, stride))
1729b8e80941Smrg         return;
1730b8e80941Smrg   }
1731b8e80941Smrg
1732b8e80941Smrg   if (skip_validated_draw(ctx))
1733b8e80941Smrg      return;
1734b8e80941Smrg
1735b8e80941Smrg   _mesa_validated_multidrawarraysindirect(ctx, mode, indirect,
1736b8e80941Smrg                                           primcount, stride);
1737b8e80941Smrg}
1738b8e80941Smrg
1739b8e80941Smrg
1740b8e80941Smrgstatic void GLAPIENTRY
1741b8e80941Smrg_mesa_exec_MultiDrawElementsIndirect(GLenum mode, GLenum type,
1742b8e80941Smrg                                     const GLvoid *indirect,
1743b8e80941Smrg                                     GLsizei primcount, GLsizei stride)
1744b8e80941Smrg{
1745b8e80941Smrg   GET_CURRENT_CONTEXT(ctx);
1746b8e80941Smrg
1747b8e80941Smrg   if (MESA_VERBOSE & VERBOSE_DRAW)
1748b8e80941Smrg      _mesa_debug(ctx, "glMultiDrawElementsIndirect(%s, %s, %p, %i, %i)\n",
1749b8e80941Smrg                  _mesa_enum_to_string(mode),
1750b8e80941Smrg                  _mesa_enum_to_string(type), indirect, primcount, stride);
1751b8e80941Smrg
1752b8e80941Smrg   /* If <stride> is zero, the array elements are treated as tightly packed. */
1753b8e80941Smrg   if (stride == 0)
1754b8e80941Smrg      stride = sizeof(DrawElementsIndirectCommand);
1755b8e80941Smrg
1756b8e80941Smrg
1757b8e80941Smrg   /* From the ARB_draw_indirect spec:
1758b8e80941Smrg    *
1759b8e80941Smrg    *    "Initially zero is bound to DRAW_INDIRECT_BUFFER. In the
1760b8e80941Smrg    *    compatibility profile, this indicates that DrawArraysIndirect and
1761b8e80941Smrg    *    DrawElementsIndirect are to source their arguments directly from the
1762b8e80941Smrg    *    pointer passed as their <indirect> parameters."
1763b8e80941Smrg    */
1764b8e80941Smrg   if (ctx->API == API_OPENGL_COMPAT &&
1765b8e80941Smrg       !_mesa_is_bufferobj(ctx->DrawIndirectBuffer)) {
1766b8e80941Smrg      /*
1767b8e80941Smrg       * Unlike regular DrawElementsInstancedBaseVertex commands, the indices
1768b8e80941Smrg       * may not come from a client array and must come from an index buffer.
1769b8e80941Smrg       * If no element array buffer is bound, an INVALID_OPERATION error is
1770b8e80941Smrg       * generated.
1771b8e80941Smrg       */
1772b8e80941Smrg      if (!_mesa_is_bufferobj(ctx->Array.VAO->IndexBufferObj)) {
1773b8e80941Smrg         _mesa_error(ctx, GL_INVALID_OPERATION,
1774b8e80941Smrg                     "glMultiDrawElementsIndirect(no buffer bound "
1775b8e80941Smrg                     "to GL_ELEMENT_ARRAY_BUFFER)");
1776b8e80941Smrg
1777b8e80941Smrg         return;
1778b8e80941Smrg      }
1779b8e80941Smrg
1780b8e80941Smrg      if (!_mesa_valid_draw_indirect_multi(ctx, primcount, stride,
1781b8e80941Smrg                                           "glMultiDrawArraysIndirect"))
1782b8e80941Smrg         return;
1783b8e80941Smrg
1784b8e80941Smrg      const ubyte *ptr = (const ubyte *) indirect;
1785b8e80941Smrg      for (unsigned i = 0; i < primcount; i++) {
1786b8e80941Smrg         _mesa_exec_DrawElementsIndirect(mode, type, ptr);
1787b8e80941Smrg
1788b8e80941Smrg         if (stride == 0) {
1789b8e80941Smrg            ptr += sizeof(DrawElementsIndirectCommand);
1790b8e80941Smrg         } else {
1791b8e80941Smrg            ptr += stride;
1792b8e80941Smrg         }
1793b8e80941Smrg      }
1794b8e80941Smrg
1795b8e80941Smrg      return;
1796b8e80941Smrg   }
1797b8e80941Smrg
1798b8e80941Smrg   FLUSH_FOR_DRAW(ctx);
1799b8e80941Smrg
1800b8e80941Smrg   _mesa_set_draw_vao(ctx, ctx->Array.VAO, enabled_filter(ctx));
1801b8e80941Smrg
1802b8e80941Smrg   if (_mesa_is_no_error_enabled(ctx)) {
1803b8e80941Smrg      if (ctx->NewState)
1804b8e80941Smrg         _mesa_update_state(ctx);
1805b8e80941Smrg   } else {
1806b8e80941Smrg      if (!_mesa_validate_MultiDrawElementsIndirect(ctx, mode, type, indirect,
1807b8e80941Smrg                                                    primcount, stride))
1808b8e80941Smrg         return;
1809b8e80941Smrg   }
1810b8e80941Smrg
1811b8e80941Smrg   if (skip_validated_draw(ctx))
1812b8e80941Smrg      return;
1813b8e80941Smrg
1814b8e80941Smrg   _mesa_validated_multidrawelementsindirect(ctx, mode, type, indirect,
1815b8e80941Smrg                                             primcount, stride);
1816b8e80941Smrg}
1817b8e80941Smrg
1818b8e80941Smrg
1819b8e80941Smrgstatic void
1820b8e80941Smrg_mesa_validated_multidrawarraysindirectcount(struct gl_context *ctx,
1821b8e80941Smrg                                             GLenum mode,
1822b8e80941Smrg                                             GLintptr indirect,
1823b8e80941Smrg                                             GLintptr drawcount_offset,
1824b8e80941Smrg                                             GLsizei maxdrawcount,
1825b8e80941Smrg                                             GLsizei stride)
1826b8e80941Smrg{
1827b8e80941Smrg   GLsizeiptr offset = indirect;
1828b8e80941Smrg
1829b8e80941Smrg   if (maxdrawcount == 0)
1830b8e80941Smrg      return;
1831b8e80941Smrg
1832b8e80941Smrg   ctx->Driver.DrawIndirect(ctx, mode,
1833b8e80941Smrg                            ctx->DrawIndirectBuffer, offset,
1834b8e80941Smrg                            maxdrawcount, stride,
1835b8e80941Smrg                            ctx->ParameterBuffer, drawcount_offset, NULL);
1836b8e80941Smrg
1837b8e80941Smrg   if (MESA_DEBUG_FLAGS & DEBUG_ALWAYS_FLUSH)
1838b8e80941Smrg      _mesa_flush(ctx);
1839b8e80941Smrg}
1840b8e80941Smrg
1841b8e80941Smrg
1842b8e80941Smrgstatic void
1843b8e80941Smrg_mesa_validated_multidrawelementsindirectcount(struct gl_context *ctx,
1844b8e80941Smrg                                               GLenum mode, GLenum type,
1845b8e80941Smrg                                               GLintptr indirect,
1846b8e80941Smrg                                               GLintptr drawcount_offset,
1847b8e80941Smrg                                               GLsizei maxdrawcount,
1848b8e80941Smrg                                               GLsizei stride)
1849b8e80941Smrg{
1850b8e80941Smrg   struct _mesa_index_buffer ib;
1851b8e80941Smrg   GLsizeiptr offset = (GLsizeiptr) indirect;
1852b8e80941Smrg
1853b8e80941Smrg   if (maxdrawcount == 0)
1854b8e80941Smrg      return;
1855b8e80941Smrg
1856b8e80941Smrg   /* NOTE: IndexBufferObj is guaranteed to be a VBO. */
1857b8e80941Smrg
1858b8e80941Smrg   ib.count = 0;                /* unknown */
1859b8e80941Smrg   ib.index_size = sizeof_ib_type(type);
1860b8e80941Smrg   ib.obj = ctx->Array.VAO->IndexBufferObj;
1861b8e80941Smrg   ib.ptr = NULL;
1862b8e80941Smrg
1863b8e80941Smrg   ctx->Driver.DrawIndirect(ctx, mode,
1864b8e80941Smrg                            ctx->DrawIndirectBuffer, offset,
1865b8e80941Smrg                            maxdrawcount, stride,
1866b8e80941Smrg                            ctx->ParameterBuffer, drawcount_offset, &ib);
1867b8e80941Smrg
1868b8e80941Smrg   if (MESA_DEBUG_FLAGS & DEBUG_ALWAYS_FLUSH)
1869b8e80941Smrg      _mesa_flush(ctx);
1870b8e80941Smrg}
1871b8e80941Smrg
1872b8e80941Smrg
1873b8e80941Smrgstatic void GLAPIENTRY
1874b8e80941Smrg_mesa_exec_MultiDrawArraysIndirectCount(GLenum mode, GLintptr indirect,
1875b8e80941Smrg                                        GLintptr drawcount_offset,
1876b8e80941Smrg                                        GLsizei maxdrawcount, GLsizei stride)
1877b8e80941Smrg{
1878b8e80941Smrg   GET_CURRENT_CONTEXT(ctx);
1879b8e80941Smrg
1880b8e80941Smrg   if (MESA_VERBOSE & VERBOSE_DRAW)
1881b8e80941Smrg      _mesa_debug(ctx, "glMultiDrawArraysIndirectCountARB"
1882b8e80941Smrg                  "(%s, %lx, %lx, %i, %i)\n",
1883b8e80941Smrg                  _mesa_enum_to_string(mode),
1884b8e80941Smrg                  (unsigned long) indirect, (unsigned long) drawcount_offset,
1885b8e80941Smrg                  maxdrawcount, stride);
1886b8e80941Smrg
1887b8e80941Smrg   /* If <stride> is zero, the array elements are treated as tightly packed. */
1888b8e80941Smrg   if (stride == 0)
1889b8e80941Smrg      stride = 4 * sizeof(GLuint);      /* sizeof(DrawArraysIndirectCommand) */
1890b8e80941Smrg
1891b8e80941Smrg   FLUSH_FOR_DRAW(ctx);
1892b8e80941Smrg
1893b8e80941Smrg   _mesa_set_draw_vao(ctx, ctx->Array.VAO, enabled_filter(ctx));
1894b8e80941Smrg
1895b8e80941Smrg   if (_mesa_is_no_error_enabled(ctx)) {
1896b8e80941Smrg      if (ctx->NewState)
1897b8e80941Smrg         _mesa_update_state(ctx);
1898b8e80941Smrg   } else {
1899b8e80941Smrg      if (!_mesa_validate_MultiDrawArraysIndirectCount(ctx, mode,
1900b8e80941Smrg                                                       indirect,
1901b8e80941Smrg                                                       drawcount_offset,
1902b8e80941Smrg                                                       maxdrawcount, stride))
1903b8e80941Smrg         return;
1904b8e80941Smrg   }
1905b8e80941Smrg
1906b8e80941Smrg   if (skip_validated_draw(ctx))
1907b8e80941Smrg      return;
1908b8e80941Smrg
1909b8e80941Smrg   _mesa_validated_multidrawarraysindirectcount(ctx, mode, indirect,
1910b8e80941Smrg                                                drawcount_offset,
1911b8e80941Smrg                                                maxdrawcount, stride);
1912b8e80941Smrg}
1913b8e80941Smrg
1914b8e80941Smrg
1915b8e80941Smrgstatic void GLAPIENTRY
1916b8e80941Smrg_mesa_exec_MultiDrawElementsIndirectCount(GLenum mode, GLenum type,
1917b8e80941Smrg                                          GLintptr indirect,
1918b8e80941Smrg                                          GLintptr drawcount_offset,
1919b8e80941Smrg                                          GLsizei maxdrawcount, GLsizei stride)
1920b8e80941Smrg{
1921b8e80941Smrg   GET_CURRENT_CONTEXT(ctx);
1922b8e80941Smrg
1923b8e80941Smrg   if (MESA_VERBOSE & VERBOSE_DRAW)
1924b8e80941Smrg      _mesa_debug(ctx, "glMultiDrawElementsIndirectCountARB"
1925b8e80941Smrg                  "(%s, %s, %lx, %lx, %i, %i)\n",
1926b8e80941Smrg                  _mesa_enum_to_string(mode), _mesa_enum_to_string(type),
1927b8e80941Smrg                  (unsigned long) indirect, (unsigned long) drawcount_offset,
1928b8e80941Smrg                  maxdrawcount, stride);
1929b8e80941Smrg
1930b8e80941Smrg   /* If <stride> is zero, the array elements are treated as tightly packed. */
1931b8e80941Smrg   if (stride == 0)
1932b8e80941Smrg      stride = 5 * sizeof(GLuint);      /* sizeof(DrawElementsIndirectCommand) */
1933b8e80941Smrg
1934b8e80941Smrg   FLUSH_FOR_DRAW(ctx);
1935b8e80941Smrg
1936b8e80941Smrg   _mesa_set_draw_vao(ctx, ctx->Array.VAO, enabled_filter(ctx));
1937b8e80941Smrg
1938b8e80941Smrg   if (_mesa_is_no_error_enabled(ctx)) {
1939b8e80941Smrg      if (ctx->NewState)
1940b8e80941Smrg         _mesa_update_state(ctx);
1941b8e80941Smrg   } else {
1942b8e80941Smrg      if (!_mesa_validate_MultiDrawElementsIndirectCount(ctx, mode, type,
1943b8e80941Smrg                                                         indirect,
1944b8e80941Smrg                                                         drawcount_offset,
1945b8e80941Smrg                                                         maxdrawcount, stride))
1946b8e80941Smrg         return;
1947b8e80941Smrg   }
1948b8e80941Smrg
1949b8e80941Smrg   if (skip_validated_draw(ctx))
1950b8e80941Smrg      return;
1951b8e80941Smrg
1952b8e80941Smrg   _mesa_validated_multidrawelementsindirectcount(ctx, mode, type, indirect,
1953b8e80941Smrg                                                  drawcount_offset, maxdrawcount,
1954b8e80941Smrg                                                  stride);
1955b8e80941Smrg}
1956b8e80941Smrg
1957b8e80941Smrg
1958b8e80941Smrg/**
1959b8e80941Smrg * Initialize the dispatch table with the VBO functions for drawing.
1960b8e80941Smrg */
1961b8e80941Smrgvoid
1962b8e80941Smrg_mesa_initialize_exec_dispatch(const struct gl_context *ctx,
1963b8e80941Smrg                               struct _glapi_table *exec)
1964b8e80941Smrg{
1965b8e80941Smrg   SET_DrawArrays(exec, _mesa_DrawArrays);
1966b8e80941Smrg   SET_DrawElements(exec, _mesa_DrawElements);
1967b8e80941Smrg
1968b8e80941Smrg   if (_mesa_is_desktop_gl(ctx) || _mesa_is_gles3(ctx)) {
1969b8e80941Smrg      SET_DrawRangeElements(exec, _mesa_DrawRangeElements);
1970b8e80941Smrg   }
1971b8e80941Smrg
1972b8e80941Smrg   SET_MultiDrawArrays(exec, _mesa_exec_MultiDrawArrays);
1973b8e80941Smrg   SET_MultiDrawElementsEXT(exec, _mesa_MultiDrawElements);
1974b8e80941Smrg
1975b8e80941Smrg   if (ctx->API == API_OPENGL_COMPAT) {
1976b8e80941Smrg      SET_Rectf(exec, _mesa_exec_Rectf);
1977b8e80941Smrg      SET_EvalMesh1(exec, _mesa_exec_EvalMesh1);
1978b8e80941Smrg      SET_EvalMesh2(exec, _mesa_exec_EvalMesh2);
1979b8e80941Smrg   }
1980b8e80941Smrg
1981b8e80941Smrg   if (ctx->API != API_OPENGLES &&
1982b8e80941Smrg       ctx->Extensions.ARB_draw_elements_base_vertex) {
1983b8e80941Smrg      SET_DrawElementsBaseVertex(exec, _mesa_DrawElementsBaseVertex);
1984b8e80941Smrg      SET_MultiDrawElementsBaseVertex(exec,
1985b8e80941Smrg                                      _mesa_MultiDrawElementsBaseVertex);
1986b8e80941Smrg
1987b8e80941Smrg      if (_mesa_is_desktop_gl(ctx) || _mesa_is_gles3(ctx)) {
1988b8e80941Smrg         SET_DrawRangeElementsBaseVertex(exec,
1989b8e80941Smrg                                         _mesa_DrawRangeElementsBaseVertex);
1990b8e80941Smrg         SET_DrawElementsInstancedBaseVertex(exec,
1991b8e80941Smrg                                             _mesa_exec_DrawElementsInstancedBaseVertex);
1992b8e80941Smrg      }
1993b8e80941Smrg   }
1994b8e80941Smrg
1995b8e80941Smrg   if (_mesa_is_desktop_gl(ctx) || _mesa_is_gles3(ctx)) {
1996b8e80941Smrg      SET_DrawArraysInstancedBaseInstance(exec,
1997b8e80941Smrg                                          _mesa_exec_DrawArraysInstancedBaseInstance);
1998b8e80941Smrg      SET_DrawElementsInstancedBaseInstance(exec,
1999b8e80941Smrg                                            _mesa_exec_DrawElementsInstancedBaseInstance);
2000b8e80941Smrg      SET_DrawElementsInstancedBaseVertexBaseInstance(exec,
2001b8e80941Smrg                                                      _mesa_exec_DrawElementsInstancedBaseVertexBaseInstance);
2002b8e80941Smrg   }
2003b8e80941Smrg
2004b8e80941Smrg   if (_mesa_is_desktop_gl(ctx) || _mesa_is_gles31(ctx)) {
2005b8e80941Smrg      SET_DrawArraysIndirect(exec, _mesa_exec_DrawArraysIndirect);
2006b8e80941Smrg      SET_DrawElementsIndirect(exec, _mesa_exec_DrawElementsIndirect);
2007b8e80941Smrg   }
2008b8e80941Smrg
2009b8e80941Smrg   if (_mesa_is_desktop_gl(ctx) || _mesa_is_gles3(ctx)) {
2010b8e80941Smrg      SET_DrawArraysInstancedARB(exec, _mesa_DrawArraysInstanced);
2011b8e80941Smrg      SET_DrawElementsInstancedARB(exec, _mesa_exec_DrawElementsInstanced);
2012b8e80941Smrg   }
2013b8e80941Smrg
2014b8e80941Smrg   if (_mesa_is_desktop_gl(ctx)) {
2015b8e80941Smrg      SET_DrawTransformFeedback(exec, _mesa_DrawTransformFeedback);
2016b8e80941Smrg      SET_DrawTransformFeedbackStream(exec,
2017b8e80941Smrg                                      _mesa_exec_DrawTransformFeedbackStream);
2018b8e80941Smrg      SET_DrawTransformFeedbackInstanced(exec,
2019b8e80941Smrg                                         _mesa_exec_DrawTransformFeedbackInstanced);
2020b8e80941Smrg      SET_DrawTransformFeedbackStreamInstanced(exec,
2021b8e80941Smrg                                               _mesa_exec_DrawTransformFeedbackStreamInstanced);
2022b8e80941Smrg      SET_MultiDrawArraysIndirect(exec, _mesa_exec_MultiDrawArraysIndirect);
2023b8e80941Smrg      SET_MultiDrawElementsIndirect(exec, _mesa_exec_MultiDrawElementsIndirect);
2024b8e80941Smrg      SET_MultiDrawArraysIndirectCountARB(exec,
2025b8e80941Smrg                                          _mesa_exec_MultiDrawArraysIndirectCount);
2026b8e80941Smrg      SET_MultiDrawElementsIndirectCountARB(exec,
2027b8e80941Smrg                                            _mesa_exec_MultiDrawElementsIndirectCount);
2028b8e80941Smrg   }
2029b8e80941Smrg}
2030b8e80941Smrg
2031b8e80941Smrg
2032b8e80941Smrg
2033b8e80941Smrg/* GL_IBM_multimode_draw_arrays */
2034b8e80941Smrgvoid GLAPIENTRY
2035b8e80941Smrg_mesa_MultiModeDrawArraysIBM( const GLenum * mode, const GLint * first,
2036b8e80941Smrg                              const GLsizei * count,
2037b8e80941Smrg                              GLsizei primcount, GLint modestride )
2038b8e80941Smrg{
2039b8e80941Smrg   GET_CURRENT_CONTEXT(ctx);
2040b8e80941Smrg   GLint i;
2041b8e80941Smrg
2042b8e80941Smrg   FLUSH_VERTICES(ctx, 0);
2043b8e80941Smrg
2044b8e80941Smrg   for ( i = 0 ; i < primcount ; i++ ) {
2045b8e80941Smrg      if ( count[i] > 0 ) {
2046b8e80941Smrg         GLenum m = *((GLenum *) ((GLubyte *) mode + i * modestride));
2047b8e80941Smrg         CALL_DrawArrays(ctx->CurrentServerDispatch, ( m, first[i], count[i] ));
2048b8e80941Smrg      }
2049b8e80941Smrg   }
2050b8e80941Smrg}
2051b8e80941Smrg
2052b8e80941Smrg
2053b8e80941Smrg/* GL_IBM_multimode_draw_arrays */
2054b8e80941Smrgvoid GLAPIENTRY
2055b8e80941Smrg_mesa_MultiModeDrawElementsIBM( const GLenum * mode, const GLsizei * count,
2056b8e80941Smrg                                GLenum type, const GLvoid * const * indices,
2057b8e80941Smrg                                GLsizei primcount, GLint modestride )
2058b8e80941Smrg{
2059b8e80941Smrg   GET_CURRENT_CONTEXT(ctx);
2060b8e80941Smrg   GLint i;
2061b8e80941Smrg
2062b8e80941Smrg   FLUSH_VERTICES(ctx, 0);
2063b8e80941Smrg
2064b8e80941Smrg   /* XXX not sure about ARB_vertex_buffer_object handling here */
2065b8e80941Smrg
2066b8e80941Smrg   for ( i = 0 ; i < primcount ; i++ ) {
2067b8e80941Smrg      if ( count[i] > 0 ) {
2068b8e80941Smrg         GLenum m = *((GLenum *) ((GLubyte *) mode + i * modestride));
2069b8e80941Smrg         CALL_DrawElements(ctx->CurrentServerDispatch, ( m, count[i], type,
2070b8e80941Smrg                                                         indices[i] ));
2071b8e80941Smrg      }
2072b8e80941Smrg   }
2073b8e80941Smrg}
2074b8e80941Smrg
2075b8e80941Smrg
2076b8e80941Smrg/*
2077b8e80941Smrg * Helper function for _mesa_draw_indirect below that additionally takes a zero
2078b8e80941Smrg * initialized array of _mesa_prim scratch space memory as the last argument.
2079b8e80941Smrg */
2080b8e80941Smrgstatic void
2081b8e80941Smrgdraw_indirect(struct gl_context *ctx, GLuint mode,
2082b8e80941Smrg              struct gl_buffer_object *indirect_data,
2083b8e80941Smrg              GLsizeiptr indirect_offset, unsigned draw_count,
2084b8e80941Smrg              unsigned stride,
2085b8e80941Smrg              struct gl_buffer_object *indirect_draw_count_buffer,
2086b8e80941Smrg              GLsizeiptr indirect_draw_count_offset,
2087b8e80941Smrg              const struct _mesa_index_buffer *ib,
2088b8e80941Smrg              struct _mesa_prim *prim)
2089b8e80941Smrg{
2090b8e80941Smrg   prim[0].begin = 1;
2091b8e80941Smrg   prim[draw_count - 1].end = 1;
2092b8e80941Smrg   for (unsigned i = 0; i < draw_count; ++i, indirect_offset += stride) {
2093b8e80941Smrg      prim[i].mode = mode;
2094b8e80941Smrg      prim[i].indexed = !!ib;
2095b8e80941Smrg      prim[i].indirect_offset = indirect_offset;
2096b8e80941Smrg      prim[i].is_indirect = 1;
2097b8e80941Smrg      prim[i].draw_id = i;
2098b8e80941Smrg   }
2099b8e80941Smrg
2100b8e80941Smrg   /* This should always be true at this time */
2101b8e80941Smrg   assert(indirect_data == ctx->DrawIndirectBuffer);
2102b8e80941Smrg
2103b8e80941Smrg   ctx->Driver.Draw(ctx, prim, draw_count, ib, false, 0u, ~0u,
2104b8e80941Smrg                    NULL, 0, indirect_data);
2105b8e80941Smrg}
2106b8e80941Smrg
2107b8e80941Smrg
2108b8e80941Smrg/*
2109b8e80941Smrg * Function to be put into dd_function_table::DrawIndirect as fallback.
2110b8e80941Smrg * Calls into dd_function_table::Draw past adapting call arguments.
2111b8e80941Smrg * See dd_function_table::DrawIndirect for call argument documentation.
2112b8e80941Smrg */
2113b8e80941Smrgvoid
2114b8e80941Smrg_mesa_draw_indirect(struct gl_context *ctx, GLuint mode,
2115b8e80941Smrg                    struct gl_buffer_object *indirect_data,
2116b8e80941Smrg                    GLsizeiptr indirect_offset, unsigned draw_count,
2117b8e80941Smrg                    unsigned stride,
2118b8e80941Smrg                    struct gl_buffer_object *indirect_draw_count_buffer,
2119b8e80941Smrg                    GLsizeiptr indirect_draw_count_offset,
2120b8e80941Smrg                    const struct _mesa_index_buffer *ib)
2121b8e80941Smrg{
2122b8e80941Smrg   /* Use alloca for the prim space if we are somehow in bounds. */
2123b8e80941Smrg   if (draw_count*sizeof(struct _mesa_prim) < 1024) {
2124b8e80941Smrg      struct _mesa_prim *space = alloca(draw_count*sizeof(struct _mesa_prim));
2125b8e80941Smrg      memset(space, 0, draw_count*sizeof(struct _mesa_prim));
2126b8e80941Smrg
2127b8e80941Smrg      draw_indirect(ctx, mode, indirect_data, indirect_offset, draw_count,
2128b8e80941Smrg                    stride, indirect_draw_count_buffer,
2129b8e80941Smrg                    indirect_draw_count_offset, ib, space);
2130b8e80941Smrg   } else {
2131b8e80941Smrg      struct _mesa_prim *space = calloc(draw_count, sizeof(struct _mesa_prim));
2132b8e80941Smrg      if (space == NULL) {
2133b8e80941Smrg         _mesa_error(ctx, GL_OUT_OF_MEMORY, "gl%sDraw%sIndirect%s",
2134b8e80941Smrg                     (draw_count > 1) ? "Multi" : "",
2135b8e80941Smrg                     ib ? "Elements" : "Arrays",
2136b8e80941Smrg                     indirect_data ? "CountARB" : "");
2137b8e80941Smrg         return;
2138b8e80941Smrg      }
2139b8e80941Smrg
2140b8e80941Smrg      draw_indirect(ctx, mode, indirect_data, indirect_offset, draw_count,
2141b8e80941Smrg                    stride, indirect_draw_count_buffer,
2142b8e80941Smrg                    indirect_draw_count_offset, ib, space);
2143b8e80941Smrg
2144b8e80941Smrg      free(space);
2145b8e80941Smrg   }
2146b8e80941Smrg}
2147