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