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