6f6a2983aedf27a205e6aa20e5f4531374e82ce0
[mesa.git] / src / mesa / vbo / vbo_exec_array.c
1 /**************************************************************************
2 *
3 * Copyright 2003 Tungsten Graphics, Inc., Cedar Park, Texas.
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 TUNGSTEN GRAPHICS 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 "main/glheader.h"
30 #include "main/context.h"
31 #include "main/state.h"
32 #include "main/api_validate.h"
33 #include "main/varray.h"
34 #include "main/bufferobj.h"
35 #include "main/enums.h"
36 #include "main/macros.h"
37 #include "main/transformfeedback.h"
38
39 #include "vbo_context.h"
40
41
42 /**
43 * All vertex buffers should be in an unmapped state when we're about
44 * to draw. This debug function checks that.
45 */
46 static void
47 check_buffers_are_unmapped(const struct gl_client_array **inputs)
48 {
49 #ifdef DEBUG
50 GLuint i;
51
52 for (i = 0; i < VERT_ATTRIB_MAX; i++) {
53 if (inputs[i]) {
54 struct gl_buffer_object *obj = inputs[i]->BufferObj;
55 assert(!_mesa_bufferobj_mapped(obj));
56 (void) obj;
57 }
58 }
59 #endif
60 }
61
62
63 /**
64 * A debug function that may be called from other parts of Mesa as
65 * needed during debugging.
66 */
67 void
68 vbo_check_buffers_are_unmapped(struct gl_context *ctx)
69 {
70 struct vbo_context *vbo = vbo_context(ctx);
71 struct vbo_exec_context *exec = &vbo->exec;
72 /* check the current vertex arrays */
73 check_buffers_are_unmapped(exec->array.inputs);
74 /* check the current glBegin/glVertex/glEnd-style VBO */
75 assert(!_mesa_bufferobj_mapped(exec->vtx.bufferobj));
76 }
77
78
79
80 /**
81 * Compute min and max elements by scanning the index buffer for
82 * glDraw[Range]Elements() calls.
83 * If primitive restart is enabled, we need to ignore restart
84 * indexes when computing min/max.
85 */
86 static void
87 vbo_get_minmax_index(struct gl_context *ctx,
88 const struct _mesa_prim *prim,
89 const struct _mesa_index_buffer *ib,
90 GLuint *min_index, GLuint *max_index,
91 const GLuint count)
92 {
93 const GLboolean restart = ctx->Array.PrimitiveRestart;
94 const GLuint restartIndex = ctx->Array.RestartIndex;
95 const int index_size = vbo_sizeof_ib_type(ib->type);
96 const char *indices;
97 GLuint i;
98
99 indices = (char *) ib->ptr + prim->start * index_size;
100 if (_mesa_is_bufferobj(ib->obj)) {
101 GLsizeiptr size = MIN2(count * index_size, ib->obj->Size);
102 indices = ctx->Driver.MapBufferRange(ctx, (GLintptr) indices, size,
103 GL_MAP_READ_BIT, ib->obj);
104 }
105
106 switch (ib->type) {
107 case GL_UNSIGNED_INT: {
108 const GLuint *ui_indices = (const GLuint *)indices;
109 GLuint max_ui = 0;
110 GLuint min_ui = ~0U;
111 if (restart) {
112 for (i = 0; i < count; i++) {
113 if (ui_indices[i] != restartIndex) {
114 if (ui_indices[i] > max_ui) max_ui = ui_indices[i];
115 if (ui_indices[i] < min_ui) min_ui = ui_indices[i];
116 }
117 }
118 }
119 else {
120 for (i = 0; i < count; i++) {
121 if (ui_indices[i] > max_ui) max_ui = ui_indices[i];
122 if (ui_indices[i] < min_ui) min_ui = ui_indices[i];
123 }
124 }
125 *min_index = min_ui;
126 *max_index = max_ui;
127 break;
128 }
129 case GL_UNSIGNED_SHORT: {
130 const GLushort *us_indices = (const GLushort *)indices;
131 GLuint max_us = 0;
132 GLuint min_us = ~0U;
133 if (restart) {
134 for (i = 0; i < count; i++) {
135 if (us_indices[i] != restartIndex) {
136 if (us_indices[i] > max_us) max_us = us_indices[i];
137 if (us_indices[i] < min_us) min_us = us_indices[i];
138 }
139 }
140 }
141 else {
142 for (i = 0; i < count; i++) {
143 if (us_indices[i] > max_us) max_us = us_indices[i];
144 if (us_indices[i] < min_us) min_us = us_indices[i];
145 }
146 }
147 *min_index = min_us;
148 *max_index = max_us;
149 break;
150 }
151 case GL_UNSIGNED_BYTE: {
152 const GLubyte *ub_indices = (const GLubyte *)indices;
153 GLuint max_ub = 0;
154 GLuint min_ub = ~0U;
155 if (restart) {
156 for (i = 0; i < count; i++) {
157 if (ub_indices[i] != restartIndex) {
158 if (ub_indices[i] > max_ub) max_ub = ub_indices[i];
159 if (ub_indices[i] < min_ub) min_ub = ub_indices[i];
160 }
161 }
162 }
163 else {
164 for (i = 0; i < count; i++) {
165 if (ub_indices[i] > max_ub) max_ub = ub_indices[i];
166 if (ub_indices[i] < min_ub) min_ub = ub_indices[i];
167 }
168 }
169 *min_index = min_ub;
170 *max_index = max_ub;
171 break;
172 }
173 default:
174 assert(0);
175 break;
176 }
177
178 if (_mesa_is_bufferobj(ib->obj)) {
179 ctx->Driver.UnmapBuffer(ctx, ib->obj);
180 }
181 }
182
183 /**
184 * Compute min and max elements for nr_prims
185 */
186 void
187 vbo_get_minmax_indices(struct gl_context *ctx,
188 const struct _mesa_prim *prims,
189 const struct _mesa_index_buffer *ib,
190 GLuint *min_index,
191 GLuint *max_index,
192 GLuint nr_prims)
193 {
194 GLuint tmp_min, tmp_max;
195 GLuint i;
196 GLuint count;
197
198 *min_index = ~0;
199 *max_index = 0;
200
201 for (i = 0; i < nr_prims; i++) {
202 const struct _mesa_prim *start_prim;
203
204 start_prim = &prims[i];
205 count = start_prim->count;
206 /* Do combination if possible to reduce map/unmap count */
207 while ((i + 1 < nr_prims) &&
208 (prims[i].start + prims[i].count == prims[i+1].start)) {
209 count += prims[i+1].count;
210 i++;
211 }
212 vbo_get_minmax_index(ctx, start_prim, ib, &tmp_min, &tmp_max, count);
213 *min_index = MIN2(*min_index, tmp_min);
214 *max_index = MAX2(*max_index, tmp_max);
215 }
216 }
217
218
219 /**
220 * Check that element 'j' of the array has reasonable data.
221 * Map VBO if needed.
222 * For debugging purposes; not normally used.
223 */
224 static void
225 check_array_data(struct gl_context *ctx, struct gl_client_array *array,
226 GLuint attrib, GLuint j)
227 {
228 if (array->Enabled) {
229 const void *data = array->Ptr;
230 if (_mesa_is_bufferobj(array->BufferObj)) {
231 if (!array->BufferObj->Pointer) {
232 /* need to map now */
233 array->BufferObj->Pointer =
234 ctx->Driver.MapBufferRange(ctx, 0, array->BufferObj->Size,
235 GL_MAP_READ_BIT, array->BufferObj);
236 }
237 data = ADD_POINTERS(data, array->BufferObj->Pointer);
238 }
239 switch (array->Type) {
240 case GL_FLOAT:
241 {
242 GLfloat *f = (GLfloat *) ((GLubyte *) data + array->StrideB * j);
243 GLint k;
244 for (k = 0; k < array->Size; k++) {
245 if (IS_INF_OR_NAN(f[k]) ||
246 f[k] >= 1.0e20 || f[k] <= -1.0e10) {
247 printf("Bad array data:\n");
248 printf(" Element[%u].%u = %f\n", j, k, f[k]);
249 printf(" Array %u at %p\n", attrib, (void* ) array);
250 printf(" Type 0x%x, Size %d, Stride %d\n",
251 array->Type, array->Size, array->Stride);
252 printf(" Address/offset %p in Buffer Object %u\n",
253 array->Ptr, array->BufferObj->Name);
254 f[k] = 1.0; /* XXX replace the bad value! */
255 }
256 /*assert(!IS_INF_OR_NAN(f[k]));*/
257 }
258 }
259 break;
260 default:
261 ;
262 }
263 }
264 }
265
266
267 /**
268 * Unmap the buffer object referenced by given array, if mapped.
269 */
270 static void
271 unmap_array_buffer(struct gl_context *ctx, struct gl_client_array *array)
272 {
273 if (array->Enabled &&
274 _mesa_is_bufferobj(array->BufferObj) &&
275 _mesa_bufferobj_mapped(array->BufferObj)) {
276 ctx->Driver.UnmapBuffer(ctx, array->BufferObj);
277 }
278 }
279
280
281 /**
282 * Examine the array's data for NaNs, etc.
283 * For debug purposes; not normally used.
284 */
285 static void
286 check_draw_elements_data(struct gl_context *ctx, GLsizei count, GLenum elemType,
287 const void *elements, GLint basevertex)
288 {
289 struct gl_array_object *arrayObj = ctx->Array.ArrayObj;
290 const void *elemMap;
291 GLint i, k;
292
293 if (_mesa_is_bufferobj(ctx->Array.ArrayObj->ElementArrayBufferObj)) {
294 elemMap = ctx->Driver.MapBufferRange(ctx, 0,
295 ctx->Array.ArrayObj->ElementArrayBufferObj->Size,
296 GL_MAP_READ_BIT,
297 ctx->Array.ArrayObj->ElementArrayBufferObj);
298 elements = ADD_POINTERS(elements, elemMap);
299 }
300
301 for (i = 0; i < count; i++) {
302 GLuint j;
303
304 /* j = element[i] */
305 switch (elemType) {
306 case GL_UNSIGNED_BYTE:
307 j = ((const GLubyte *) elements)[i];
308 break;
309 case GL_UNSIGNED_SHORT:
310 j = ((const GLushort *) elements)[i];
311 break;
312 case GL_UNSIGNED_INT:
313 j = ((const GLuint *) elements)[i];
314 break;
315 default:
316 assert(0);
317 }
318
319 /* check element j of each enabled array */
320 for (k = 0; k < Elements(arrayObj->VertexAttrib); k++) {
321 check_array_data(ctx, &arrayObj->VertexAttrib[k], k, j);
322 }
323 }
324
325 if (_mesa_is_bufferobj(arrayObj->ElementArrayBufferObj)) {
326 ctx->Driver.UnmapBuffer(ctx, ctx->Array.ArrayObj->ElementArrayBufferObj);
327 }
328
329 for (k = 0; k < Elements(arrayObj->VertexAttrib); k++) {
330 unmap_array_buffer(ctx, &arrayObj->VertexAttrib[k]);
331 }
332 }
333
334
335 /**
336 * Check array data, looking for NaNs, etc.
337 */
338 static void
339 check_draw_arrays_data(struct gl_context *ctx, GLint start, GLsizei count)
340 {
341 /* TO DO */
342 }
343
344
345 /**
346 * Print info/data for glDrawArrays(), for debugging.
347 */
348 static void
349 print_draw_arrays(struct gl_context *ctx,
350 GLenum mode, GLint start, GLsizei count)
351 {
352 struct vbo_context *vbo = vbo_context(ctx);
353 struct vbo_exec_context *exec = &vbo->exec;
354 struct gl_array_object *arrayObj = ctx->Array.ArrayObj;
355 int i;
356
357 printf("vbo_exec_DrawArrays(mode 0x%x, start %d, count %d):\n",
358 mode, start, count);
359
360 for (i = 0; i < 32; i++) {
361 struct gl_buffer_object *bufObj = exec->array.inputs[i]->BufferObj;
362 GLuint bufName = bufObj->Name;
363 GLint stride = exec->array.inputs[i]->Stride;
364 printf("attr %2d: size %d stride %d enabled %d "
365 "ptr %p Bufobj %u\n",
366 i,
367 exec->array.inputs[i]->Size,
368 stride,
369 /*exec->array.inputs[i]->Enabled,*/
370 arrayObj->VertexAttrib[VERT_ATTRIB_FF(i)].Enabled,
371 exec->array.inputs[i]->Ptr,
372 bufName);
373
374 if (bufName) {
375 GLubyte *p = ctx->Driver.MapBufferRange(ctx, 0, bufObj->Size,
376 GL_MAP_READ_BIT, bufObj);
377 int offset = (int) (GLintptr) exec->array.inputs[i]->Ptr;
378 float *f = (float *) (p + offset);
379 int *k = (int *) f;
380 int i;
381 int n = (count * stride) / 4;
382 if (n > 32)
383 n = 32;
384 printf(" Data at offset %d:\n", offset);
385 for (i = 0; i < n; i++) {
386 printf(" float[%d] = 0x%08x %f\n", i, k[i], f[i]);
387 }
388 ctx->Driver.UnmapBuffer(ctx, bufObj);
389 }
390 }
391 }
392
393
394 /**
395 * Set the vbo->exec->inputs[] pointers to point to the enabled
396 * vertex arrays. This depends on the current vertex program/shader
397 * being executed because of whether or not generic vertex arrays
398 * alias the conventional vertex arrays.
399 * For arrays that aren't enabled, we set the input[attrib] pointer
400 * to point at a zero-stride current value "array".
401 */
402 static void
403 recalculate_input_bindings(struct gl_context *ctx)
404 {
405 struct vbo_context *vbo = vbo_context(ctx);
406 struct vbo_exec_context *exec = &vbo->exec;
407 struct gl_client_array *vertexAttrib = ctx->Array.ArrayObj->VertexAttrib;
408 const struct gl_client_array **inputs = &exec->array.inputs[0];
409 GLbitfield64 const_inputs = 0x0;
410 GLuint i;
411
412 switch (get_program_mode(ctx)) {
413 case VP_NONE:
414 /* When no vertex program is active (or the vertex program is generated
415 * from fixed-function state). We put the material values into the
416 * generic slots. This is the only situation where material values
417 * are available as per-vertex attributes.
418 */
419 for (i = 0; i < VERT_ATTRIB_FF_MAX; i++) {
420 if (vertexAttrib[VERT_ATTRIB_FF(i)].Enabled)
421 inputs[i] = &vertexAttrib[VERT_ATTRIB_FF(i)];
422 else {
423 inputs[i] = &vbo->currval[VBO_ATTRIB_POS+i];
424 const_inputs |= VERT_BIT(i);
425 }
426 }
427
428 for (i = 0; i < MAT_ATTRIB_MAX; i++) {
429 inputs[VERT_ATTRIB_GENERIC(i)] =
430 &vbo->currval[VBO_ATTRIB_MAT_FRONT_AMBIENT+i];
431 const_inputs |= VERT_BIT_GENERIC(i);
432 }
433
434 /* Could use just about anything, just to fill in the empty
435 * slots:
436 */
437 for (i = MAT_ATTRIB_MAX; i < VERT_ATTRIB_GENERIC_MAX; i++) {
438 inputs[VERT_ATTRIB_GENERIC(i)] = &vbo->currval[VBO_ATTRIB_GENERIC0+i];
439 const_inputs |= VERT_BIT_GENERIC(i);
440 }
441 break;
442
443 case VP_NV:
444 /* NV_vertex_program - attribute arrays alias and override
445 * conventional, legacy arrays. No materials, and the generic
446 * slots are vacant.
447 */
448 for (i = 0; i < VERT_ATTRIB_FF_MAX; i++) {
449 if (i < VERT_ATTRIB_GENERIC_MAX
450 && vertexAttrib[VERT_ATTRIB_GENERIC(i)].Enabled)
451 inputs[i] = &vertexAttrib[VERT_ATTRIB_GENERIC(i)];
452 else if (vertexAttrib[VERT_ATTRIB_FF(i)].Enabled)
453 inputs[i] = &vertexAttrib[VERT_ATTRIB_FF(i)];
454 else {
455 inputs[i] = &vbo->currval[VBO_ATTRIB_POS+i];
456 const_inputs |= VERT_BIT_FF(i);
457 }
458 }
459
460 /* Could use just about anything, just to fill in the empty
461 * slots:
462 */
463 for (i = 0; i < VERT_ATTRIB_GENERIC_MAX; i++) {
464 inputs[VERT_ATTRIB_GENERIC(i)] = &vbo->currval[VBO_ATTRIB_GENERIC0+i];
465 const_inputs |= VERT_BIT_GENERIC(i);
466 }
467 break;
468
469 case VP_ARB:
470 /* GL_ARB_vertex_program or GLSL vertex shader - Only the generic[0]
471 * attribute array aliases and overrides the legacy position array.
472 *
473 * Otherwise, legacy attributes available in the legacy slots,
474 * generic attributes in the generic slots and materials are not
475 * available as per-vertex attributes.
476 */
477 if (vertexAttrib[VERT_ATTRIB_GENERIC0].Enabled)
478 inputs[0] = &vertexAttrib[VERT_ATTRIB_GENERIC0];
479 else if (vertexAttrib[VERT_ATTRIB_POS].Enabled)
480 inputs[0] = &vertexAttrib[VERT_ATTRIB_POS];
481 else {
482 inputs[0] = &vbo->currval[VBO_ATTRIB_POS];
483 const_inputs |= VERT_BIT_POS;
484 }
485
486 for (i = 1; i < VERT_ATTRIB_FF_MAX; i++) {
487 if (vertexAttrib[VERT_ATTRIB_FF(i)].Enabled)
488 inputs[i] = &vertexAttrib[VERT_ATTRIB_FF(i)];
489 else {
490 inputs[i] = &vbo->currval[VBO_ATTRIB_POS+i];
491 const_inputs |= VERT_BIT_FF(i);
492 }
493 }
494
495 for (i = 1; i < VERT_ATTRIB_GENERIC_MAX; i++) {
496 if (vertexAttrib[VERT_ATTRIB_GENERIC(i)].Enabled)
497 inputs[VERT_ATTRIB_GENERIC(i)] = &vertexAttrib[VERT_ATTRIB_GENERIC(i)];
498 else {
499 inputs[VERT_ATTRIB_GENERIC(i)] = &vbo->currval[VBO_ATTRIB_GENERIC0+i];
500 const_inputs |= VERT_BIT_GENERIC(i);
501 }
502 }
503
504 inputs[VERT_ATTRIB_GENERIC0] = inputs[0];
505 break;
506 }
507
508 _mesa_set_varying_vp_inputs( ctx, VERT_BIT_ALL & (~const_inputs) );
509 ctx->NewDriverState |= ctx->DriverFlags.NewArray;
510 }
511
512
513 /**
514 * Examine the enabled vertex arrays to set the exec->array.inputs[] values.
515 * These will point to the arrays to actually use for drawing. Some will
516 * be user-provided arrays, other will be zero-stride const-valued arrays.
517 * Note that this might set the _NEW_VARYING_VP_INPUTS dirty flag so state
518 * validation must be done after this call.
519 */
520 void
521 vbo_bind_arrays(struct gl_context *ctx)
522 {
523 struct vbo_context *vbo = vbo_context(ctx);
524 struct vbo_exec_context *exec = &vbo->exec;
525
526 vbo_draw_method(vbo, DRAW_ARRAYS);
527
528 if (exec->array.recalculate_inputs) {
529 recalculate_input_bindings(ctx);
530
531 /* Again... because we may have changed the bitmask of per-vertex varying
532 * attributes. If we regenerate the fixed-function vertex program now
533 * we may be able to prune down the number of vertex attributes which we
534 * need in the shader.
535 */
536 if (ctx->NewState) {
537 _mesa_update_state(ctx);
538 }
539
540 exec->array.recalculate_inputs = GL_FALSE;
541 }
542 }
543
544
545 /**
546 * Handle a draw case that potentially has primitive restart enabled.
547 *
548 * If primitive restart is enabled, and PrimitiveRestartInSoftware is
549 * set, then vbo_sw_primitive_restart is used to handle the primitive
550 * restart case in software.
551 */
552 static void
553 vbo_handle_primitive_restart(struct gl_context *ctx,
554 const struct _mesa_prim *prim,
555 GLuint nr_prims,
556 const struct _mesa_index_buffer *ib,
557 GLboolean index_bounds_valid,
558 GLuint min_index,
559 GLuint max_index)
560 {
561 struct vbo_context *vbo = vbo_context(ctx);
562
563 if ((ib != NULL) &&
564 ctx->Const.PrimitiveRestartInSoftware &&
565 ctx->Array.PrimitiveRestart) {
566 /* Handle primitive restart in software */
567 vbo_sw_primitive_restart(ctx, prim, nr_prims, ib);
568 } else {
569 /* Call driver directly for draw_prims */
570 vbo->draw_prims(ctx, prim, nr_prims, ib,
571 index_bounds_valid, min_index, max_index, NULL);
572 }
573 }
574
575
576 /**
577 * Helper function called by the other DrawArrays() functions below.
578 * This is where we handle primitive restart for drawing non-indexed
579 * arrays. If primitive restart is enabled, it typically means
580 * splitting one DrawArrays() into two.
581 */
582 static void
583 vbo_draw_arrays(struct gl_context *ctx, GLenum mode, GLint start,
584 GLsizei count, GLuint numInstances, GLuint baseInstance)
585 {
586 struct vbo_context *vbo = vbo_context(ctx);
587 struct vbo_exec_context *exec = &vbo->exec;
588 struct _mesa_prim prim[2];
589
590 vbo_bind_arrays(ctx);
591
592 /* init most fields to zero */
593 memset(prim, 0, sizeof(prim));
594 prim[0].begin = 1;
595 prim[0].end = 1;
596 prim[0].mode = mode;
597 prim[0].num_instances = numInstances;
598 prim[0].base_instance = baseInstance;
599
600 /* Implement the primitive restart index */
601 if (ctx->Array.PrimitiveRestart && ctx->Array.RestartIndex < count) {
602 GLuint primCount = 0;
603
604 if (ctx->Array.RestartIndex == start) {
605 /* special case: RestartIndex at beginning */
606 if (count > 1) {
607 prim[0].start = start + 1;
608 prim[0].count = count - 1;
609 primCount = 1;
610 }
611 }
612 else if (ctx->Array.RestartIndex == start + count - 1) {
613 /* special case: RestartIndex at end */
614 if (count > 1) {
615 prim[0].start = start;
616 prim[0].count = count - 1;
617 primCount = 1;
618 }
619 }
620 else {
621 /* general case: RestartIndex in middle, split into two prims */
622 prim[0].start = start;
623 prim[0].count = ctx->Array.RestartIndex - start;
624
625 prim[1] = prim[0];
626 prim[1].start = ctx->Array.RestartIndex + 1;
627 prim[1].count = count - prim[1].start;
628
629 primCount = 2;
630 }
631
632 if (primCount > 0) {
633 /* draw one or two prims */
634 check_buffers_are_unmapped(exec->array.inputs);
635 vbo->draw_prims(ctx, prim, primCount, NULL,
636 GL_TRUE, start, start + count - 1, NULL);
637 }
638 }
639 else {
640 /* no prim restart */
641 prim[0].start = start;
642 prim[0].count = count;
643
644 check_buffers_are_unmapped(exec->array.inputs);
645 vbo->draw_prims(ctx, prim, 1, NULL,
646 GL_TRUE, start, start + count - 1,
647 NULL);
648 }
649
650 if (MESA_DEBUG_FLAGS & DEBUG_ALWAYS_FLUSH) {
651 _mesa_flush(ctx);
652 }
653 }
654
655
656
657 /**
658 * Called from glDrawArrays when in immediate mode (not display list mode).
659 */
660 static void GLAPIENTRY
661 vbo_exec_DrawArrays(GLenum mode, GLint start, GLsizei count)
662 {
663 GET_CURRENT_CONTEXT(ctx);
664
665 if (MESA_VERBOSE & VERBOSE_DRAW)
666 _mesa_debug(ctx, "glDrawArrays(%s, %d, %d)\n",
667 _mesa_lookup_enum_by_nr(mode), start, count);
668
669 FLUSH_CURRENT(ctx, 0);
670
671 if (!_mesa_validate_DrawArrays( ctx, mode, start, count ))
672 return;
673
674 if (0)
675 check_draw_arrays_data(ctx, start, count);
676
677 vbo_draw_arrays(ctx, mode, start, count, 1, 0);
678
679 if (0)
680 print_draw_arrays(ctx, mode, start, count);
681 }
682
683
684 /**
685 * Called from glDrawArraysInstanced when in immediate mode (not
686 * display list mode).
687 */
688 static void GLAPIENTRY
689 vbo_exec_DrawArraysInstanced(GLenum mode, GLint start, GLsizei count,
690 GLsizei numInstances)
691 {
692 GET_CURRENT_CONTEXT(ctx);
693
694 if (MESA_VERBOSE & VERBOSE_DRAW)
695 _mesa_debug(ctx, "glDrawArraysInstanced(%s, %d, %d, %d)\n",
696 _mesa_lookup_enum_by_nr(mode), start, count, numInstances);
697
698 FLUSH_CURRENT(ctx, 0);
699
700 if (!_mesa_validate_DrawArraysInstanced(ctx, mode, start, count, numInstances))
701 return;
702
703 if (0)
704 check_draw_arrays_data(ctx, start, count);
705
706 vbo_draw_arrays(ctx, mode, start, count, numInstances, 0);
707
708 if (0)
709 print_draw_arrays(ctx, mode, start, count);
710 }
711
712
713 /**
714 * Called from glDrawArraysInstancedBaseInstance when in immediate mode.
715 */
716 static void GLAPIENTRY
717 vbo_exec_DrawArraysInstancedBaseInstance(GLenum mode, GLint first, GLsizei count,
718 GLsizei numInstances, GLuint baseInstance)
719 {
720 GET_CURRENT_CONTEXT(ctx);
721
722 if (MESA_VERBOSE & VERBOSE_DRAW)
723 _mesa_debug(ctx, "glDrawArraysInstancedBaseInstance(%s, %d, %d, %d, %d)\n",
724 _mesa_lookup_enum_by_nr(mode), first, count,
725 numInstances, baseInstance);
726
727 if (!_mesa_validate_DrawArraysInstanced(ctx, mode, first, count,
728 numInstances))
729 return;
730
731 FLUSH_CURRENT(ctx, 0);
732
733 if (!_mesa_valid_to_render(ctx, "glDrawArraysInstancedBaseInstance"))
734 return;
735
736 if (0)
737 check_draw_arrays_data(ctx, first, count);
738
739 vbo_draw_arrays(ctx, mode, first, count, numInstances, baseInstance);
740
741 if (0)
742 print_draw_arrays(ctx, mode, first, count);
743 }
744
745
746
747 /**
748 * Map GL_ELEMENT_ARRAY_BUFFER and print contents.
749 * For debugging.
750 */
751 #if 0
752 static void
753 dump_element_buffer(struct gl_context *ctx, GLenum type)
754 {
755 const GLvoid *map =
756 ctx->Driver.MapBufferRange(ctx, 0,
757 ctx->Array.ArrayObj->ElementArrayBufferObj->Size,
758 GL_MAP_READ_BIT,
759 ctx->Array.ArrayObj->ElementArrayBufferObj);
760 switch (type) {
761 case GL_UNSIGNED_BYTE:
762 {
763 const GLubyte *us = (const GLubyte *) map;
764 GLint i;
765 for (i = 0; i < ctx->Array.ArrayObj->ElementArrayBufferObj->Size; i++) {
766 printf("%02x ", us[i]);
767 if (i % 32 == 31)
768 printf("\n");
769 }
770 printf("\n");
771 }
772 break;
773 case GL_UNSIGNED_SHORT:
774 {
775 const GLushort *us = (const GLushort *) map;
776 GLint i;
777 for (i = 0; i < ctx->Array.ArrayObj->ElementArrayBufferObj->Size / 2; i++) {
778 printf("%04x ", us[i]);
779 if (i % 16 == 15)
780 printf("\n");
781 }
782 printf("\n");
783 }
784 break;
785 case GL_UNSIGNED_INT:
786 {
787 const GLuint *us = (const GLuint *) map;
788 GLint i;
789 for (i = 0; i < ctx->Array.ArrayObj->ElementArrayBufferObj->Size / 4; i++) {
790 printf("%08x ", us[i]);
791 if (i % 8 == 7)
792 printf("\n");
793 }
794 printf("\n");
795 }
796 break;
797 default:
798 ;
799 }
800
801 ctx->Driver.UnmapBuffer(ctx, ctx->Array.ArrayObj->ElementArrayBufferObj);
802 }
803 #endif
804
805
806 /**
807 * Inner support for both _mesa_DrawElements and _mesa_DrawRangeElements.
808 * Do the rendering for a glDrawElements or glDrawRangeElements call after
809 * we've validated buffer bounds, etc.
810 */
811 static void
812 vbo_validated_drawrangeelements(struct gl_context *ctx, GLenum mode,
813 GLboolean index_bounds_valid,
814 GLuint start, GLuint end,
815 GLsizei count, GLenum type,
816 const GLvoid *indices,
817 GLint basevertex, GLint numInstances,
818 GLuint baseInstance)
819 {
820 struct vbo_context *vbo = vbo_context(ctx);
821 struct vbo_exec_context *exec = &vbo->exec;
822 struct _mesa_index_buffer ib;
823 struct _mesa_prim prim[1];
824
825 vbo_bind_arrays(ctx);
826
827 ib.count = count;
828 ib.type = type;
829 ib.obj = ctx->Array.ArrayObj->ElementArrayBufferObj;
830 ib.ptr = indices;
831
832 prim[0].begin = 1;
833 prim[0].end = 1;
834 prim[0].weak = 0;
835 prim[0].pad = 0;
836 prim[0].mode = mode;
837 prim[0].start = 0;
838 prim[0].count = count;
839 prim[0].indexed = 1;
840 prim[0].basevertex = basevertex;
841 prim[0].num_instances = numInstances;
842 prim[0].base_instance = baseInstance;
843
844 /* Need to give special consideration to rendering a range of
845 * indices starting somewhere above zero. Typically the
846 * application is issuing multiple DrawRangeElements() to draw
847 * successive primitives layed out linearly in the vertex arrays.
848 * Unless the vertex arrays are all in a VBO (or locked as with
849 * CVA), the OpenGL semantics imply that we need to re-read or
850 * re-upload the vertex data on each draw call.
851 *
852 * In the case of hardware tnl, we want to avoid starting the
853 * upload at zero, as it will mean every draw call uploads an
854 * increasing amount of not-used vertex data. Worse - in the
855 * software tnl module, all those vertices might be transformed and
856 * lit but never rendered.
857 *
858 * If we just upload or transform the vertices in start..end,
859 * however, the indices will be incorrect.
860 *
861 * At this level, we don't know exactly what the requirements of
862 * the backend are going to be, though it will likely boil down to
863 * either:
864 *
865 * 1) Do nothing, everything is in a VBO and is processed once
866 * only.
867 *
868 * 2) Adjust the indices and vertex arrays so that start becomes
869 * zero.
870 *
871 * Rather than doing anything here, I'll provide a helper function
872 * for the latter case elsewhere.
873 */
874
875 check_buffers_are_unmapped(exec->array.inputs);
876 vbo_handle_primitive_restart(ctx, prim, 1, &ib,
877 index_bounds_valid, start, end);
878
879 if (MESA_DEBUG_FLAGS & DEBUG_ALWAYS_FLUSH) {
880 _mesa_flush(ctx);
881 }
882 }
883
884
885 /**
886 * Called by glDrawRangeElementsBaseVertex() in immediate mode.
887 */
888 static void GLAPIENTRY
889 vbo_exec_DrawRangeElementsBaseVertex(GLenum mode,
890 GLuint start, GLuint end,
891 GLsizei count, GLenum type,
892 const GLvoid *indices,
893 GLint basevertex)
894 {
895 static GLuint warnCount = 0;
896 GLboolean index_bounds_valid = GL_TRUE;
897 GET_CURRENT_CONTEXT(ctx);
898
899 if (MESA_VERBOSE & VERBOSE_DRAW)
900 _mesa_debug(ctx,
901 "glDrawRangeElementsBaseVertex(%s, %u, %u, %d, %s, %p, %d)\n",
902 _mesa_lookup_enum_by_nr(mode), start, end, count,
903 _mesa_lookup_enum_by_nr(type), indices, basevertex);
904
905 FLUSH_CURRENT(ctx, 0);
906
907 if (!_mesa_validate_DrawRangeElements( ctx, mode, start, end, count,
908 type, indices, basevertex ))
909 return;
910
911 if ((int) end + basevertex < 0 ||
912 start + basevertex >= ctx->Array.ArrayObj->_MaxElement) {
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 ctx->Array.ArrayObj->_MaxElement - 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.ArrayObj->ElementArrayBufferObj->Name,
953 basevertex);
954 }
955
956 if ((int) start + basevertex < 0 ||
957 end + basevertex >= ctx->Array.ArrayObj->_MaxElement)
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_lookup_enum_by_nr(mode), start, end, count,
983 _mesa_lookup_enum_by_nr(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_lookup_enum_by_nr(mode), count,
1003 _mesa_lookup_enum_by_nr(type), indices);
1004
1005 FLUSH_CURRENT(ctx, 0);
1006
1007 if (!_mesa_validate_DrawElements( ctx, mode, count, type, indices, 0 ))
1008 return;
1009
1010 vbo_validated_drawrangeelements(ctx, mode, GL_FALSE, ~0, ~0,
1011 count, type, indices, 0, 1, 0);
1012 }
1013
1014
1015 /**
1016 * Called by glDrawElementsBaseVertex() in immediate mode.
1017 */
1018 static void GLAPIENTRY
1019 vbo_exec_DrawElementsBaseVertex(GLenum mode, GLsizei count, GLenum type,
1020 const GLvoid *indices, GLint basevertex)
1021 {
1022 GET_CURRENT_CONTEXT(ctx);
1023
1024 if (MESA_VERBOSE & VERBOSE_DRAW)
1025 _mesa_debug(ctx, "glDrawElementsBaseVertex(%s, %d, %s, %p, %d)\n",
1026 _mesa_lookup_enum_by_nr(mode), count,
1027 _mesa_lookup_enum_by_nr(type), indices, basevertex);
1028
1029 FLUSH_CURRENT(ctx, 0);
1030
1031 if (!_mesa_validate_DrawElements( ctx, mode, count, type, indices,
1032 basevertex ))
1033 return;
1034
1035 vbo_validated_drawrangeelements(ctx, mode, GL_FALSE, ~0, ~0,
1036 count, type, indices, basevertex, 1, 0);
1037 }
1038
1039
1040 /**
1041 * Called by glDrawElementsInstanced() in immediate mode.
1042 */
1043 static void GLAPIENTRY
1044 vbo_exec_DrawElementsInstanced(GLenum mode, GLsizei count, GLenum type,
1045 const GLvoid *indices, GLsizei numInstances)
1046 {
1047 GET_CURRENT_CONTEXT(ctx);
1048
1049 if (MESA_VERBOSE & VERBOSE_DRAW)
1050 _mesa_debug(ctx, "glDrawElementsInstanced(%s, %d, %s, %p, %d)\n",
1051 _mesa_lookup_enum_by_nr(mode), count,
1052 _mesa_lookup_enum_by_nr(type), indices, numInstances);
1053
1054 FLUSH_CURRENT(ctx, 0);
1055
1056 if (!_mesa_validate_DrawElementsInstanced(ctx, mode, count, type, indices,
1057 numInstances, 0))
1058 return;
1059
1060 vbo_validated_drawrangeelements(ctx, mode, GL_FALSE, ~0, ~0,
1061 count, type, indices, 0, numInstances, 0);
1062 }
1063
1064
1065 /**
1066 * Called by glDrawElementsInstancedBaseVertex() in immediate mode.
1067 */
1068 static void GLAPIENTRY
1069 vbo_exec_DrawElementsInstancedBaseVertex(GLenum mode, GLsizei count, GLenum type,
1070 const GLvoid *indices, GLsizei numInstances,
1071 GLint basevertex)
1072 {
1073 GET_CURRENT_CONTEXT(ctx);
1074
1075 if (MESA_VERBOSE & VERBOSE_DRAW)
1076 _mesa_debug(ctx, "glDrawElementsInstancedBaseVertex(%s, %d, %s, %p, %d; %d)\n",
1077 _mesa_lookup_enum_by_nr(mode), count,
1078 _mesa_lookup_enum_by_nr(type), indices,
1079 numInstances, basevertex);
1080
1081 FLUSH_CURRENT(ctx, 0);
1082
1083 if (!_mesa_validate_DrawElementsInstanced(ctx, mode, count, type, indices,
1084 numInstances, basevertex))
1085 return;
1086
1087 vbo_validated_drawrangeelements(ctx, mode, GL_FALSE, ~0, ~0,
1088 count, type, indices, basevertex, numInstances, 0);
1089 }
1090
1091
1092 /**
1093 * Called by glDrawElementsInstancedBaseInstance() in immediate mode.
1094 */
1095 static void GLAPIENTRY
1096 vbo_exec_DrawElementsInstancedBaseInstance(GLenum mode, GLsizei count, GLenum type,
1097 const GLvoid *indices, GLsizei numInstances,
1098 GLuint baseInstance)
1099 {
1100 GET_CURRENT_CONTEXT(ctx);
1101
1102 if (MESA_VERBOSE & VERBOSE_DRAW)
1103 _mesa_debug(ctx, "glDrawElementsInstancedBaseInstance(%s, %d, %s, %p, %d, %d)\n",
1104 _mesa_lookup_enum_by_nr(mode), count,
1105 _mesa_lookup_enum_by_nr(type), indices,
1106 numInstances, baseInstance);
1107
1108 if (!_mesa_validate_DrawElementsInstanced(ctx, mode, count, type, indices,
1109 numInstances, 0))
1110 return;
1111
1112 vbo_validated_drawrangeelements(ctx, mode, GL_FALSE, ~0, ~0,
1113 count, type, indices, 0, numInstances,
1114 baseInstance);
1115 }
1116
1117
1118 /**
1119 * Called by glDrawElementsInstancedBaseVertexBaseInstance() in immediate mode.
1120 */
1121 static void GLAPIENTRY
1122 vbo_exec_DrawElementsInstancedBaseVertexBaseInstance(GLenum mode, GLsizei count, GLenum type,
1123 const GLvoid *indices, GLsizei numInstances,
1124 GLint basevertex, GLuint baseInstance)
1125 {
1126 GET_CURRENT_CONTEXT(ctx);
1127
1128 if (MESA_VERBOSE & VERBOSE_DRAW)
1129 _mesa_debug(ctx, "glDrawElementsInstancedBaseVertexBaseInstance(%s, %d, %s, %p, %d, %d, %d)\n",
1130 _mesa_lookup_enum_by_nr(mode), count,
1131 _mesa_lookup_enum_by_nr(type), indices,
1132 numInstances, basevertex, baseInstance);
1133
1134 if (!_mesa_validate_DrawElementsInstanced(ctx, mode, count, type, indices,
1135 numInstances, basevertex))
1136 return;
1137
1138 vbo_validated_drawrangeelements(ctx, mode, GL_FALSE, ~0, ~0,
1139 count, type, indices, basevertex, numInstances,
1140 baseInstance);
1141 }
1142
1143
1144 /**
1145 * Inner support for both _mesa_MultiDrawElements() and
1146 * _mesa_MultiDrawRangeElements().
1147 * This does the actual rendering after we've checked array indexes, etc.
1148 */
1149 static void
1150 vbo_validated_multidrawelements(struct gl_context *ctx, GLenum mode,
1151 const GLsizei *count, GLenum type,
1152 const GLvoid * const *indices,
1153 GLsizei primcount,
1154 const GLint *basevertex)
1155 {
1156 struct vbo_context *vbo = vbo_context(ctx);
1157 struct vbo_exec_context *exec = &vbo->exec;
1158 struct _mesa_index_buffer ib;
1159 struct _mesa_prim *prim;
1160 unsigned int index_type_size = vbo_sizeof_ib_type(type);
1161 uintptr_t min_index_ptr, max_index_ptr;
1162 GLboolean fallback = GL_FALSE;
1163 int i;
1164
1165 if (primcount == 0)
1166 return;
1167
1168 prim = calloc(1, primcount * sizeof(*prim));
1169 if (prim == NULL) {
1170 _mesa_error(ctx, GL_OUT_OF_MEMORY, "glMultiDrawElements");
1171 return;
1172 }
1173
1174 vbo_bind_arrays(ctx);
1175
1176 min_index_ptr = (uintptr_t)indices[0];
1177 max_index_ptr = 0;
1178 for (i = 0; i < primcount; i++) {
1179 min_index_ptr = MIN2(min_index_ptr, (uintptr_t)indices[i]);
1180 max_index_ptr = MAX2(max_index_ptr, (uintptr_t)indices[i] +
1181 index_type_size * count[i]);
1182 }
1183
1184 /* Check if we can handle this thing as a bunch of index offsets from the
1185 * same index pointer. If we can't, then we have to fall back to doing
1186 * a draw_prims per primitive.
1187 * Check that the difference between each prim's indexes is a multiple of
1188 * the index/element size.
1189 */
1190 if (index_type_size != 1) {
1191 for (i = 0; i < primcount; i++) {
1192 if ((((uintptr_t)indices[i] - min_index_ptr) % index_type_size) != 0) {
1193 fallback = GL_TRUE;
1194 break;
1195 }
1196 }
1197 }
1198
1199 /* If the index buffer isn't in a VBO, then treating the application's
1200 * subranges of the index buffer as one large index buffer may lead to
1201 * us reading unmapped memory.
1202 */
1203 if (!_mesa_is_bufferobj(ctx->Array.ArrayObj->ElementArrayBufferObj))
1204 fallback = GL_TRUE;
1205
1206 if (!fallback) {
1207 ib.count = (max_index_ptr - min_index_ptr) / index_type_size;
1208 ib.type = type;
1209 ib.obj = ctx->Array.ArrayObj->ElementArrayBufferObj;
1210 ib.ptr = (void *)min_index_ptr;
1211
1212 for (i = 0; i < primcount; i++) {
1213 prim[i].begin = (i == 0);
1214 prim[i].end = (i == primcount - 1);
1215 prim[i].weak = 0;
1216 prim[i].pad = 0;
1217 prim[i].mode = mode;
1218 prim[i].start = ((uintptr_t)indices[i] - min_index_ptr) / index_type_size;
1219 prim[i].count = count[i];
1220 prim[i].indexed = 1;
1221 prim[i].num_instances = 1;
1222 prim[i].base_instance = 0;
1223 if (basevertex != NULL)
1224 prim[i].basevertex = basevertex[i];
1225 else
1226 prim[i].basevertex = 0;
1227 }
1228
1229 check_buffers_are_unmapped(exec->array.inputs);
1230 vbo_handle_primitive_restart(ctx, prim, primcount, &ib,
1231 GL_FALSE, ~0, ~0);
1232 } else {
1233 /* render one prim at a time */
1234 for (i = 0; i < primcount; i++) {
1235 ib.count = count[i];
1236 ib.type = type;
1237 ib.obj = ctx->Array.ArrayObj->ElementArrayBufferObj;
1238 ib.ptr = indices[i];
1239
1240 prim[0].begin = 1;
1241 prim[0].end = 1;
1242 prim[0].weak = 0;
1243 prim[0].pad = 0;
1244 prim[0].mode = mode;
1245 prim[0].start = 0;
1246 prim[0].count = count[i];
1247 prim[0].indexed = 1;
1248 prim[0].num_instances = 1;
1249 prim[0].base_instance = 0;
1250 if (basevertex != NULL)
1251 prim[0].basevertex = basevertex[i];
1252 else
1253 prim[0].basevertex = 0;
1254
1255 check_buffers_are_unmapped(exec->array.inputs);
1256 vbo_handle_primitive_restart(ctx, prim, 1, &ib,
1257 GL_FALSE, ~0, ~0);
1258 }
1259 }
1260
1261 free(prim);
1262
1263 if (MESA_DEBUG_FLAGS & DEBUG_ALWAYS_FLUSH) {
1264 _mesa_flush(ctx);
1265 }
1266 }
1267
1268
1269 static void GLAPIENTRY
1270 vbo_exec_MultiDrawElements(GLenum mode,
1271 const GLsizei *count, GLenum type,
1272 const GLvoid **indices,
1273 GLsizei primcount)
1274 {
1275 GET_CURRENT_CONTEXT(ctx);
1276 GLint i;
1277
1278 ASSERT_OUTSIDE_BEGIN_END_AND_FLUSH(ctx);
1279
1280 for (i = 0; i < primcount; i++) {
1281 if (!_mesa_validate_DrawElements(ctx, mode, count[i], type, indices[i],
1282 0))
1283 return;
1284 }
1285
1286 vbo_validated_multidrawelements(ctx, mode, count, type, indices, primcount,
1287 NULL);
1288 }
1289
1290
1291 static void GLAPIENTRY
1292 vbo_exec_MultiDrawElementsBaseVertex(GLenum mode,
1293 const GLsizei *count, GLenum type,
1294 const GLvoid * const *indices,
1295 GLsizei primcount,
1296 const GLsizei *basevertex)
1297 {
1298 GET_CURRENT_CONTEXT(ctx);
1299 GLint i;
1300
1301 ASSERT_OUTSIDE_BEGIN_END_AND_FLUSH(ctx);
1302
1303 for (i = 0; i < primcount; i++) {
1304 if (!_mesa_validate_DrawElements(ctx, mode, count[i], type, indices[i],
1305 basevertex[i]))
1306 return;
1307 }
1308
1309 vbo_validated_multidrawelements(ctx, mode, count, type, indices, primcount,
1310 basevertex);
1311 }
1312
1313 #if FEATURE_EXT_transform_feedback
1314
1315 static void
1316 vbo_draw_transform_feedback(struct gl_context *ctx, GLenum mode,
1317 struct gl_transform_feedback_object *obj,
1318 GLuint numInstances)
1319 {
1320 struct vbo_context *vbo = vbo_context(ctx);
1321 struct vbo_exec_context *exec = &vbo->exec;
1322 struct _mesa_prim prim[2];
1323
1324 vbo_bind_arrays(ctx);
1325
1326 /* init most fields to zero */
1327 memset(prim, 0, sizeof(prim));
1328 prim[0].begin = 1;
1329 prim[0].end = 1;
1330 prim[0].mode = mode;
1331 prim[0].num_instances = numInstances;
1332 prim[0].base_instance = 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 check_buffers_are_unmapped(exec->array.inputs);
1339 vbo->draw_prims(ctx, prim, 1, NULL,
1340 GL_TRUE, 0, 0, obj);
1341
1342 if (MESA_DEBUG_FLAGS & DEBUG_ALWAYS_FLUSH) {
1343 _mesa_flush(ctx);
1344 }
1345 }
1346
1347 /**
1348 * Like DrawArrays, but take the count from a transform feedback object.
1349 * \param mode GL_POINTS, GL_LINES, GL_TRIANGLE_STRIP, etc.
1350 * \param name the transform feedback object
1351 * User still has to setup of the vertex attribute info with
1352 * glVertexPointer, glColorPointer, etc.
1353 * Part of GL_ARB_transform_feedback2.
1354 */
1355 static void GLAPIENTRY
1356 vbo_exec_DrawTransformFeedback(GLenum mode, GLuint name)
1357 {
1358 GET_CURRENT_CONTEXT(ctx);
1359 struct gl_transform_feedback_object *obj =
1360 _mesa_lookup_transform_feedback_object(ctx, name);
1361
1362 if (MESA_VERBOSE & VERBOSE_DRAW)
1363 _mesa_debug(ctx, "glDrawTransformFeedback(%s, %d)\n",
1364 _mesa_lookup_enum_by_nr(mode), name);
1365
1366 FLUSH_CURRENT(ctx, 0);
1367
1368 if (!_mesa_validate_DrawTransformFeedback(ctx, mode, obj)) {
1369 return;
1370 }
1371
1372 vbo_draw_transform_feedback(ctx, mode, obj, 1);
1373 }
1374
1375 #endif
1376
1377 /**
1378 * Plug in the immediate-mode vertex array drawing commands into the
1379 * givven vbo_exec_context object.
1380 */
1381 void
1382 vbo_exec_array_init( struct vbo_exec_context *exec )
1383 {
1384 exec->vtxfmt.DrawArrays = vbo_exec_DrawArrays;
1385 exec->vtxfmt.DrawElements = vbo_exec_DrawElements;
1386 exec->vtxfmt.DrawRangeElements = vbo_exec_DrawRangeElements;
1387 exec->vtxfmt.MultiDrawElementsEXT = vbo_exec_MultiDrawElements;
1388 exec->vtxfmt.DrawElementsBaseVertex = vbo_exec_DrawElementsBaseVertex;
1389 exec->vtxfmt.DrawRangeElementsBaseVertex = vbo_exec_DrawRangeElementsBaseVertex;
1390 exec->vtxfmt.MultiDrawElementsBaseVertex = vbo_exec_MultiDrawElementsBaseVertex;
1391 exec->vtxfmt.DrawArraysInstanced = vbo_exec_DrawArraysInstanced;
1392 exec->vtxfmt.DrawArraysInstancedBaseInstance = vbo_exec_DrawArraysInstancedBaseInstance;
1393 exec->vtxfmt.DrawElementsInstanced = vbo_exec_DrawElementsInstanced;
1394 exec->vtxfmt.DrawElementsInstancedBaseInstance = vbo_exec_DrawElementsInstancedBaseInstance;
1395 exec->vtxfmt.DrawElementsInstancedBaseVertex = vbo_exec_DrawElementsInstancedBaseVertex;
1396 exec->vtxfmt.DrawElementsInstancedBaseVertexBaseInstance = vbo_exec_DrawElementsInstancedBaseVertexBaseInstance;
1397 #if FEATURE_EXT_transform_feedback
1398 exec->vtxfmt.DrawTransformFeedback = vbo_exec_DrawTransformFeedback;
1399 #endif
1400 }
1401
1402
1403 void
1404 vbo_exec_array_destroy( struct vbo_exec_context *exec )
1405 {
1406 /* nothing to do */
1407 }
1408
1409
1410
1411 /**
1412 * The following functions are only used for OpenGL ES 1/2 support.
1413 * And some aren't even supported (yet) in ES 1/2.
1414 */
1415
1416
1417 void GLAPIENTRY
1418 _mesa_DrawArrays(GLenum mode, GLint first, GLsizei count)
1419 {
1420 vbo_exec_DrawArrays(mode, first, count);
1421 }
1422
1423
1424 void GLAPIENTRY
1425 _mesa_DrawElements(GLenum mode, GLsizei count, GLenum type,
1426 const GLvoid *indices)
1427 {
1428 vbo_exec_DrawElements(mode, count, type, indices);
1429 }
1430
1431
1432 void GLAPIENTRY
1433 _mesa_DrawElementsBaseVertex(GLenum mode, GLsizei count, GLenum type,
1434 const GLvoid *indices, GLint basevertex)
1435 {
1436 vbo_exec_DrawElementsBaseVertex(mode, count, type, indices, basevertex);
1437 }
1438
1439
1440 void GLAPIENTRY
1441 _mesa_DrawRangeElements(GLenum mode, GLuint start, GLuint end, GLsizei count,
1442 GLenum type, const GLvoid *indices)
1443 {
1444 vbo_exec_DrawRangeElements(mode, start, end, count, type, indices);
1445 }
1446
1447
1448 void GLAPIENTRY
1449 _mesa_DrawRangeElementsBaseVertex(GLenum mode, GLuint start, GLuint end,
1450 GLsizei count, GLenum type,
1451 const GLvoid *indices, GLint basevertex)
1452 {
1453 vbo_exec_DrawRangeElementsBaseVertex(mode, start, end, count, type,
1454 indices, basevertex);
1455 }
1456
1457
1458 void GLAPIENTRY
1459 _mesa_MultiDrawElementsEXT(GLenum mode, const GLsizei *count, GLenum type,
1460 const GLvoid **indices, GLsizei primcount)
1461 {
1462 vbo_exec_MultiDrawElements(mode, count, type, indices, primcount);
1463 }
1464
1465
1466 void GLAPIENTRY
1467 _mesa_MultiDrawElementsBaseVertex(GLenum mode,
1468 const GLsizei *count, GLenum type,
1469 const GLvoid **indices, GLsizei primcount,
1470 const GLint *basevertex)
1471 {
1472 vbo_exec_MultiDrawElementsBaseVertex(mode, count, type, indices,
1473 primcount, basevertex);
1474 }
1475
1476 #if FEATURE_EXT_transform_feedback
1477
1478 void GLAPIENTRY
1479 _mesa_DrawTransformFeedback(GLenum mode, GLuint name)
1480 {
1481 vbo_exec_DrawTransformFeedback(mode, name);
1482 }
1483
1484 #endif