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