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