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