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