s/Tungsten Graphics/VMware/
[mesa.git] / src / mesa / vbo / vbo_exec_array.c
1 /**************************************************************************
2 *
3 * Copyright 2003 VMware, Inc.
4 * Copyright 2009 VMware, Inc.
5 * All Rights Reserved.
6 *
7 * Permission is hereby granted, free of charge, to any person obtaining a
8 * copy of this software and associated documentation files (the
9 * "Software"), to deal in the Software without restriction, including
10 * without limitation the rights to use, copy, modify, merge, publish,
11 * distribute, sub license, and/or sell copies of the Software, and to
12 * permit persons to whom the Software is furnished to do so, subject to
13 * the following conditions:
14 *
15 * The above copyright notice and this permission notice (including the
16 * next paragraph) shall be included in all copies or substantial portions
17 * of the Software.
18 *
19 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
20 * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
21 * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT.
22 * IN NO EVENT SHALL VMWARE AND/OR ITS SUPPLIERS BE LIABLE FOR
23 * ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
24 * TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
25 * SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
26 *
27 **************************************************************************/
28
29 #include "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 /* There are no shaders in OpenGL ES 1.x, so this code path should be
446 * impossible to reach. The meta code is careful to not use shaders in
447 * ES1.
448 */
449 assert(ctx->API != API_OPENGLES);
450
451 /* In the compatibility profile of desktop OpenGL, the generic[0]
452 * attribute array aliases and overrides the legacy position array.
453 * Otherwise, legacy attributes available in the legacy slots,
454 * generic attributes in the generic slots and materials are not
455 * available as per-vertex attributes.
456 *
457 * In all other APIs, only the generic attributes exist, and none of the
458 * slots are considered "magic."
459 */
460 if (ctx->API == API_OPENGL_COMPAT) {
461 if (vertexAttrib[VERT_ATTRIB_GENERIC0].Enabled)
462 inputs[0] = &vertexAttrib[VERT_ATTRIB_GENERIC0];
463 else if (vertexAttrib[VERT_ATTRIB_POS].Enabled)
464 inputs[0] = &vertexAttrib[VERT_ATTRIB_POS];
465 else {
466 inputs[0] = &vbo->currval[VBO_ATTRIB_POS];
467 const_inputs |= VERT_BIT_POS;
468 }
469
470 for (i = 1; i < VERT_ATTRIB_FF_MAX; i++) {
471 if (vertexAttrib[VERT_ATTRIB_FF(i)].Enabled)
472 inputs[i] = &vertexAttrib[VERT_ATTRIB_FF(i)];
473 else {
474 inputs[i] = &vbo->currval[VBO_ATTRIB_POS+i];
475 const_inputs |= VERT_BIT_FF(i);
476 }
477 }
478
479 for (i = 1; i < VERT_ATTRIB_GENERIC_MAX; i++) {
480 if (vertexAttrib[VERT_ATTRIB_GENERIC(i)].Enabled)
481 inputs[VERT_ATTRIB_GENERIC(i)] =
482 &vertexAttrib[VERT_ATTRIB_GENERIC(i)];
483 else {
484 inputs[VERT_ATTRIB_GENERIC(i)] =
485 &vbo->currval[VBO_ATTRIB_GENERIC0+i];
486 const_inputs |= VERT_BIT_GENERIC(i);
487 }
488 }
489
490 inputs[VERT_ATTRIB_GENERIC0] = inputs[0];
491 } else {
492 /* Other parts of the code assume that inputs[0] through
493 * inputs[VERT_ATTRIB_FF_MAX] will be non-NULL. However, in OpenGL
494 * ES 2.0+ or OpenGL core profile, none of these arrays should ever
495 * be enabled.
496 */
497 for (i = 0; i < VERT_ATTRIB_FF_MAX; i++) {
498 assert(!vertexAttrib[VERT_ATTRIB_FF(i)].Enabled);
499
500 inputs[i] = &vbo->currval[VBO_ATTRIB_POS+i];
501 const_inputs |= VERT_BIT_FF(i);
502 }
503
504 for (i = 0; i < VERT_ATTRIB_GENERIC_MAX; i++) {
505 if (vertexAttrib[VERT_ATTRIB_GENERIC(i)].Enabled)
506 inputs[VERT_ATTRIB_GENERIC(i)] =
507 &vertexAttrib[VERT_ATTRIB_GENERIC(i)];
508 else {
509 inputs[VERT_ATTRIB_GENERIC(i)] =
510 &vbo->currval[VBO_ATTRIB_GENERIC0+i];
511 const_inputs |= VERT_BIT_GENERIC(i);
512 }
513 }
514 }
515
516 break;
517 }
518
519 _mesa_set_varying_vp_inputs( ctx, VERT_BIT_ALL & (~const_inputs) );
520 ctx->NewDriverState |= ctx->DriverFlags.NewArray;
521 }
522
523
524 /**
525 * Examine the enabled vertex arrays to set the exec->array.inputs[] values.
526 * These will point to the arrays to actually use for drawing. Some will
527 * be user-provided arrays, other will be zero-stride const-valued arrays.
528 * Note that this might set the _NEW_VARYING_VP_INPUTS dirty flag so state
529 * validation must be done after this call.
530 */
531 void
532 vbo_bind_arrays(struct gl_context *ctx)
533 {
534 struct vbo_context *vbo = vbo_context(ctx);
535 struct vbo_exec_context *exec = &vbo->exec;
536
537 vbo_draw_method(vbo, DRAW_ARRAYS);
538
539 if (exec->array.recalculate_inputs) {
540 recalculate_input_bindings(ctx);
541 exec->array.recalculate_inputs = GL_FALSE;
542
543 /* Again... because we may have changed the bitmask of per-vertex varying
544 * attributes. If we regenerate the fixed-function vertex program now
545 * we may be able to prune down the number of vertex attributes which we
546 * need in the shader.
547 */
548 if (ctx->NewState) {
549 /* Setting "validating" to TRUE prevents _mesa_update_state from
550 * invalidating what we just did.
551 */
552 exec->validating = GL_TRUE;
553 _mesa_update_state(ctx);
554 exec->validating = GL_FALSE;
555 }
556 }
557 }
558
559
560 /**
561 * Handle a draw case that potentially has primitive restart enabled.
562 *
563 * If primitive restart is enabled, and PrimitiveRestartInSoftware is
564 * set, then vbo_sw_primitive_restart is used to handle the primitive
565 * restart case in software.
566 */
567 static void
568 vbo_handle_primitive_restart(struct gl_context *ctx,
569 const struct _mesa_prim *prim,
570 GLuint nr_prims,
571 const struct _mesa_index_buffer *ib,
572 GLboolean index_bounds_valid,
573 GLuint min_index,
574 GLuint max_index)
575 {
576 struct vbo_context *vbo = vbo_context(ctx);
577
578 if ((ib != NULL) &&
579 ctx->Const.PrimitiveRestartInSoftware &&
580 ctx->Array._PrimitiveRestart) {
581 /* Handle primitive restart in software */
582 vbo_sw_primitive_restart(ctx, prim, nr_prims, ib, NULL);
583 } else {
584 /* Call driver directly for draw_prims */
585 vbo->draw_prims(ctx, prim, nr_prims, ib,
586 index_bounds_valid, min_index, max_index, NULL, NULL);
587 }
588 }
589
590
591 /**
592 * Helper function called by the other DrawArrays() functions below.
593 * This is where we handle primitive restart for drawing non-indexed
594 * arrays. If primitive restart is enabled, it typically means
595 * splitting one DrawArrays() into two.
596 */
597 static void
598 vbo_draw_arrays(struct gl_context *ctx, GLenum mode, GLint start,
599 GLsizei count, GLuint numInstances, GLuint baseInstance)
600 {
601 struct vbo_context *vbo = vbo_context(ctx);
602 struct vbo_exec_context *exec = &vbo->exec;
603 struct _mesa_prim prim[2];
604
605 vbo_bind_arrays(ctx);
606
607 /* init most fields to zero */
608 memset(prim, 0, sizeof(prim));
609 prim[0].begin = 1;
610 prim[0].end = 1;
611 prim[0].mode = mode;
612 prim[0].num_instances = numInstances;
613 prim[0].base_instance = baseInstance;
614 prim[0].is_indirect = 0;
615
616 /* Implement the primitive restart index */
617 if (ctx->Array.PrimitiveRestart && ctx->Array.RestartIndex < count) {
618 GLuint primCount = 0;
619
620 if (ctx->Array.RestartIndex == start) {
621 /* special case: RestartIndex at beginning */
622 if (count > 1) {
623 prim[0].start = start + 1;
624 prim[0].count = count - 1;
625 primCount = 1;
626 }
627 }
628 else if (ctx->Array.RestartIndex == start + count - 1) {
629 /* special case: RestartIndex at end */
630 if (count > 1) {
631 prim[0].start = start;
632 prim[0].count = count - 1;
633 primCount = 1;
634 }
635 }
636 else {
637 /* general case: RestartIndex in middle, split into two prims */
638 prim[0].start = start;
639 prim[0].count = ctx->Array.RestartIndex - start;
640
641 prim[1] = prim[0];
642 prim[1].start = ctx->Array.RestartIndex + 1;
643 prim[1].count = count - prim[1].start;
644
645 primCount = 2;
646 }
647
648 if (primCount > 0) {
649 /* draw one or two prims */
650 check_buffers_are_unmapped(exec->array.inputs);
651 vbo->draw_prims(ctx, prim, primCount, NULL,
652 GL_TRUE, start, start + count - 1, NULL, NULL);
653 }
654 }
655 else {
656 /* no prim restart */
657 prim[0].start = start;
658 prim[0].count = count;
659
660 check_buffers_are_unmapped(exec->array.inputs);
661 vbo->draw_prims(ctx, prim, 1, NULL,
662 GL_TRUE, start, start + count - 1,
663 NULL, NULL);
664 }
665
666 if (MESA_DEBUG_FLAGS & DEBUG_ALWAYS_FLUSH) {
667 _mesa_flush(ctx);
668 }
669 }
670
671
672 /**
673 * Execute a glRectf() function.
674 */
675 static void GLAPIENTRY
676 vbo_exec_Rectf(GLfloat x1, GLfloat y1, GLfloat x2, GLfloat y2)
677 {
678 GET_CURRENT_CONTEXT(ctx);
679 ASSERT_OUTSIDE_BEGIN_END(ctx);
680
681 CALL_Begin(GET_DISPATCH(), (GL_QUADS));
682 CALL_Vertex2f(GET_DISPATCH(), (x1, y1));
683 CALL_Vertex2f(GET_DISPATCH(), (x2, y1));
684 CALL_Vertex2f(GET_DISPATCH(), (x2, y2));
685 CALL_Vertex2f(GET_DISPATCH(), (x1, y2));
686 CALL_End(GET_DISPATCH(), ());
687 }
688
689
690 static void GLAPIENTRY
691 vbo_exec_EvalMesh1(GLenum mode, GLint i1, GLint i2)
692 {
693 GET_CURRENT_CONTEXT(ctx);
694 GLint i;
695 GLfloat u, du;
696 GLenum prim;
697
698 switch (mode) {
699 case GL_POINT:
700 prim = GL_POINTS;
701 break;
702 case GL_LINE:
703 prim = GL_LINE_STRIP;
704 break;
705 default:
706 _mesa_error( ctx, GL_INVALID_ENUM, "glEvalMesh1(mode)" );
707 return;
708 }
709
710 /* No effect if vertex maps disabled.
711 */
712 if (!ctx->Eval.Map1Vertex4 &&
713 !ctx->Eval.Map1Vertex3)
714 return;
715
716 du = ctx->Eval.MapGrid1du;
717 u = ctx->Eval.MapGrid1u1 + i1 * du;
718
719 CALL_Begin(GET_DISPATCH(), (prim));
720 for (i=i1;i<=i2;i++,u+=du) {
721 CALL_EvalCoord1f(GET_DISPATCH(), (u));
722 }
723 CALL_End(GET_DISPATCH(), ());
724 }
725
726
727 static void GLAPIENTRY
728 vbo_exec_EvalMesh2(GLenum mode, GLint i1, GLint i2, GLint j1, GLint j2)
729 {
730 GET_CURRENT_CONTEXT(ctx);
731 GLfloat u, du, v, dv, v1, u1;
732 GLint i, j;
733
734 switch (mode) {
735 case GL_POINT:
736 case GL_LINE:
737 case GL_FILL:
738 break;
739 default:
740 _mesa_error( ctx, GL_INVALID_ENUM, "glEvalMesh2(mode)" );
741 return;
742 }
743
744 /* No effect if vertex maps disabled.
745 */
746 if (!ctx->Eval.Map2Vertex4 &&
747 !ctx->Eval.Map2Vertex3)
748 return;
749
750 du = ctx->Eval.MapGrid2du;
751 dv = ctx->Eval.MapGrid2dv;
752 v1 = ctx->Eval.MapGrid2v1 + j1 * dv;
753 u1 = ctx->Eval.MapGrid2u1 + i1 * du;
754
755 switch (mode) {
756 case GL_POINT:
757 CALL_Begin(GET_DISPATCH(), (GL_POINTS));
758 for (v=v1,j=j1;j<=j2;j++,v+=dv) {
759 for (u=u1,i=i1;i<=i2;i++,u+=du) {
760 CALL_EvalCoord2f(GET_DISPATCH(), (u, v));
761 }
762 }
763 CALL_End(GET_DISPATCH(), ());
764 break;
765 case GL_LINE:
766 for (v=v1,j=j1;j<=j2;j++,v+=dv) {
767 CALL_Begin(GET_DISPATCH(), (GL_LINE_STRIP));
768 for (u=u1,i=i1;i<=i2;i++,u+=du) {
769 CALL_EvalCoord2f(GET_DISPATCH(), (u, v));
770 }
771 CALL_End(GET_DISPATCH(), ());
772 }
773 for (u=u1,i=i1;i<=i2;i++,u+=du) {
774 CALL_Begin(GET_DISPATCH(), (GL_LINE_STRIP));
775 for (v=v1,j=j1;j<=j2;j++,v+=dv) {
776 CALL_EvalCoord2f(GET_DISPATCH(), (u, v));
777 }
778 CALL_End(GET_DISPATCH(), ());
779 }
780 break;
781 case GL_FILL:
782 for (v=v1,j=j1;j<j2;j++,v+=dv) {
783 CALL_Begin(GET_DISPATCH(), (GL_TRIANGLE_STRIP));
784 for (u=u1,i=i1;i<=i2;i++,u+=du) {
785 CALL_EvalCoord2f(GET_DISPATCH(), (u, v));
786 CALL_EvalCoord2f(GET_DISPATCH(), (u, v+dv));
787 }
788 CALL_End(GET_DISPATCH(), ());
789 }
790 break;
791 }
792 }
793
794
795 /**
796 * Called from glDrawArrays when in immediate mode (not display list mode).
797 */
798 static void GLAPIENTRY
799 vbo_exec_DrawArrays(GLenum mode, GLint start, GLsizei count)
800 {
801 GET_CURRENT_CONTEXT(ctx);
802
803 if (MESA_VERBOSE & VERBOSE_DRAW)
804 _mesa_debug(ctx, "glDrawArrays(%s, %d, %d)\n",
805 _mesa_lookup_enum_by_nr(mode), start, count);
806
807 if (!_mesa_validate_DrawArrays( ctx, mode, start, count ))
808 return;
809
810 if (0)
811 check_draw_arrays_data(ctx, start, count);
812
813 vbo_draw_arrays(ctx, mode, start, count, 1, 0);
814
815 if (0)
816 print_draw_arrays(ctx, mode, start, count);
817 }
818
819
820 /**
821 * Called from glDrawArraysInstanced when in immediate mode (not
822 * display list mode).
823 */
824 static void GLAPIENTRY
825 vbo_exec_DrawArraysInstanced(GLenum mode, GLint start, GLsizei count,
826 GLsizei numInstances)
827 {
828 GET_CURRENT_CONTEXT(ctx);
829
830 if (MESA_VERBOSE & VERBOSE_DRAW)
831 _mesa_debug(ctx, "glDrawArraysInstanced(%s, %d, %d, %d)\n",
832 _mesa_lookup_enum_by_nr(mode), start, count, numInstances);
833
834 if (!_mesa_validate_DrawArraysInstanced(ctx, mode, start, count, numInstances))
835 return;
836
837 if (0)
838 check_draw_arrays_data(ctx, start, count);
839
840 vbo_draw_arrays(ctx, mode, start, count, numInstances, 0);
841
842 if (0)
843 print_draw_arrays(ctx, mode, start, count);
844 }
845
846
847 /**
848 * Called from glDrawArraysInstancedBaseInstance when in immediate mode.
849 */
850 static void GLAPIENTRY
851 vbo_exec_DrawArraysInstancedBaseInstance(GLenum mode, GLint first, GLsizei count,
852 GLsizei numInstances, GLuint baseInstance)
853 {
854 GET_CURRENT_CONTEXT(ctx);
855
856 if (MESA_VERBOSE & VERBOSE_DRAW)
857 _mesa_debug(ctx, "glDrawArraysInstancedBaseInstance(%s, %d, %d, %d, %d)\n",
858 _mesa_lookup_enum_by_nr(mode), first, count,
859 numInstances, baseInstance);
860
861 if (!_mesa_validate_DrawArraysInstanced(ctx, mode, first, count,
862 numInstances))
863 return;
864
865 if (0)
866 check_draw_arrays_data(ctx, first, count);
867
868 vbo_draw_arrays(ctx, mode, first, count, numInstances, baseInstance);
869
870 if (0)
871 print_draw_arrays(ctx, mode, first, count);
872 }
873
874
875
876 /**
877 * Map GL_ELEMENT_ARRAY_BUFFER and print contents.
878 * For debugging.
879 */
880 #if 0
881 static void
882 dump_element_buffer(struct gl_context *ctx, GLenum type)
883 {
884 const GLvoid *map =
885 ctx->Driver.MapBufferRange(ctx, 0,
886 ctx->Array.ArrayObj->ElementArrayBufferObj->Size,
887 GL_MAP_READ_BIT,
888 ctx->Array.ArrayObj->ElementArrayBufferObj);
889 switch (type) {
890 case GL_UNSIGNED_BYTE:
891 {
892 const GLubyte *us = (const GLubyte *) map;
893 GLint i;
894 for (i = 0; i < ctx->Array.ArrayObj->ElementArrayBufferObj->Size; i++) {
895 printf("%02x ", us[i]);
896 if (i % 32 == 31)
897 printf("\n");
898 }
899 printf("\n");
900 }
901 break;
902 case GL_UNSIGNED_SHORT:
903 {
904 const GLushort *us = (const GLushort *) map;
905 GLint i;
906 for (i = 0; i < ctx->Array.ArrayObj->ElementArrayBufferObj->Size / 2; i++) {
907 printf("%04x ", us[i]);
908 if (i % 16 == 15)
909 printf("\n");
910 }
911 printf("\n");
912 }
913 break;
914 case GL_UNSIGNED_INT:
915 {
916 const GLuint *us = (const GLuint *) map;
917 GLint i;
918 for (i = 0; i < ctx->Array.ArrayObj->ElementArrayBufferObj->Size / 4; i++) {
919 printf("%08x ", us[i]);
920 if (i % 8 == 7)
921 printf("\n");
922 }
923 printf("\n");
924 }
925 break;
926 default:
927 ;
928 }
929
930 ctx->Driver.UnmapBuffer(ctx, ctx->Array.ArrayObj->ElementArrayBufferObj);
931 }
932 #endif
933
934
935 /**
936 * Inner support for both _mesa_DrawElements and _mesa_DrawRangeElements.
937 * Do the rendering for a glDrawElements or glDrawRangeElements call after
938 * we've validated buffer bounds, etc.
939 */
940 static void
941 vbo_validated_drawrangeelements(struct gl_context *ctx, GLenum mode,
942 GLboolean index_bounds_valid,
943 GLuint start, GLuint end,
944 GLsizei count, GLenum type,
945 const GLvoid *indices,
946 GLint basevertex, GLuint numInstances,
947 GLuint baseInstance)
948 {
949 struct vbo_context *vbo = vbo_context(ctx);
950 struct vbo_exec_context *exec = &vbo->exec;
951 struct _mesa_index_buffer ib;
952 struct _mesa_prim prim[1];
953
954 vbo_bind_arrays(ctx);
955
956 ib.count = count;
957 ib.type = type;
958 ib.obj = ctx->Array.ArrayObj->ElementArrayBufferObj;
959 ib.ptr = indices;
960
961 prim[0].begin = 1;
962 prim[0].end = 1;
963 prim[0].weak = 0;
964 prim[0].pad = 0;
965 prim[0].mode = mode;
966 prim[0].start = 0;
967 prim[0].count = count;
968 prim[0].indexed = 1;
969 prim[0].is_indirect = 0;
970 prim[0].basevertex = basevertex;
971 prim[0].num_instances = numInstances;
972 prim[0].base_instance = baseInstance;
973
974 /* Need to give special consideration to rendering a range of
975 * indices starting somewhere above zero. Typically the
976 * application is issuing multiple DrawRangeElements() to draw
977 * successive primitives layed out linearly in the vertex arrays.
978 * Unless the vertex arrays are all in a VBO (or locked as with
979 * CVA), the OpenGL semantics imply that we need to re-read or
980 * re-upload the vertex data on each draw call.
981 *
982 * In the case of hardware tnl, we want to avoid starting the
983 * upload at zero, as it will mean every draw call uploads an
984 * increasing amount of not-used vertex data. Worse - in the
985 * software tnl module, all those vertices might be transformed and
986 * lit but never rendered.
987 *
988 * If we just upload or transform the vertices in start..end,
989 * however, the indices will be incorrect.
990 *
991 * At this level, we don't know exactly what the requirements of
992 * the backend are going to be, though it will likely boil down to
993 * either:
994 *
995 * 1) Do nothing, everything is in a VBO and is processed once
996 * only.
997 *
998 * 2) Adjust the indices and vertex arrays so that start becomes
999 * zero.
1000 *
1001 * Rather than doing anything here, I'll provide a helper function
1002 * for the latter case elsewhere.
1003 */
1004
1005 check_buffers_are_unmapped(exec->array.inputs);
1006 vbo_handle_primitive_restart(ctx, prim, 1, &ib,
1007 index_bounds_valid, start, end);
1008
1009 if (MESA_DEBUG_FLAGS & DEBUG_ALWAYS_FLUSH) {
1010 _mesa_flush(ctx);
1011 }
1012 }
1013
1014
1015 /**
1016 * Called by glDrawRangeElementsBaseVertex() in immediate mode.
1017 */
1018 static void GLAPIENTRY
1019 vbo_exec_DrawRangeElementsBaseVertex(GLenum mode,
1020 GLuint start, GLuint end,
1021 GLsizei count, GLenum type,
1022 const GLvoid *indices,
1023 GLint basevertex)
1024 {
1025 static GLuint warnCount = 0;
1026 GLboolean index_bounds_valid = GL_TRUE;
1027 GLuint max_element;
1028 GET_CURRENT_CONTEXT(ctx);
1029
1030 if (MESA_VERBOSE & VERBOSE_DRAW)
1031 _mesa_debug(ctx,
1032 "glDrawRangeElementsBaseVertex(%s, %u, %u, %d, %s, %p, %d)\n",
1033 _mesa_lookup_enum_by_nr(mode), start, end, count,
1034 _mesa_lookup_enum_by_nr(type), indices, basevertex);
1035
1036 if (!_mesa_validate_DrawRangeElements( ctx, mode, start, end, count,
1037 type, indices, basevertex ))
1038 return;
1039
1040 if (ctx->Const.CheckArrayBounds) {
1041 /* _MaxElement was computed, so we can use it.
1042 * This path is used for drivers which need strict bounds checking.
1043 */
1044 max_element = ctx->Array.ArrayObj->_MaxElement;
1045 }
1046 else {
1047 /* Generally, hardware drivers don't need to know the buffer bounds
1048 * if all vertex attributes are in VBOs.
1049 * However, if none of vertex attributes are in VBOs, _MaxElement
1050 * is always set to some random big number anyway, so bounds checking
1051 * is mostly useless.
1052 *
1053 * This is only useful to catch invalid values in the "end" parameter
1054 * like ~0.
1055 */
1056 max_element = 2 * 1000 * 1000 * 1000; /* just a big number */
1057 }
1058
1059 if ((int) end + basevertex < 0 ||
1060 start + basevertex >= max_element) {
1061 /* The application requested we draw using a range of indices that's
1062 * outside the bounds of the current VBO. This is invalid and appears
1063 * to give undefined results. The safest thing to do is to simply
1064 * ignore the range, in case the application botched their range tracking
1065 * but did provide valid indices. Also issue a warning indicating that
1066 * the application is broken.
1067 */
1068 if (warnCount++ < 10) {
1069 _mesa_warning(ctx, "glDrawRangeElements(start %u, end %u, "
1070 "basevertex %d, count %d, type 0x%x, indices=%p):\n"
1071 "\trange is outside VBO bounds (max=%u); ignoring.\n"
1072 "\tThis should be fixed in the application.",
1073 start, end, basevertex, count, type, indices,
1074 max_element - 1);
1075 }
1076 index_bounds_valid = GL_FALSE;
1077 }
1078
1079 /* NOTE: It's important that 'end' is a reasonable value.
1080 * in _tnl_draw_prims(), we use end to determine how many vertices
1081 * to transform. If it's too large, we can unnecessarily split prims
1082 * or we can read/write out of memory in several different places!
1083 */
1084
1085 /* Catch/fix some potential user errors */
1086 if (type == GL_UNSIGNED_BYTE) {
1087 start = MIN2(start, 0xff);
1088 end = MIN2(end, 0xff);
1089 }
1090 else if (type == GL_UNSIGNED_SHORT) {
1091 start = MIN2(start, 0xffff);
1092 end = MIN2(end, 0xffff);
1093 }
1094
1095 if (0) {
1096 printf("glDraw[Range]Elements{,BaseVertex}"
1097 "(start %u, end %u, type 0x%x, count %d) ElemBuf %u, "
1098 "base %d\n",
1099 start, end, type, count,
1100 ctx->Array.ArrayObj->ElementArrayBufferObj->Name,
1101 basevertex);
1102 }
1103
1104 if ((int) start + basevertex < 0 ||
1105 end + basevertex >= max_element)
1106 index_bounds_valid = GL_FALSE;
1107
1108 #if 0
1109 check_draw_elements_data(ctx, count, type, indices);
1110 #else
1111 (void) check_draw_elements_data;
1112 #endif
1113
1114 vbo_validated_drawrangeelements(ctx, mode, index_bounds_valid, start, end,
1115 count, type, indices, basevertex, 1, 0);
1116 }
1117
1118
1119 /**
1120 * Called by glDrawRangeElements() in immediate mode.
1121 */
1122 static void GLAPIENTRY
1123 vbo_exec_DrawRangeElements(GLenum mode, GLuint start, GLuint end,
1124 GLsizei count, GLenum type, const GLvoid *indices)
1125 {
1126 if (MESA_VERBOSE & VERBOSE_DRAW) {
1127 GET_CURRENT_CONTEXT(ctx);
1128 _mesa_debug(ctx,
1129 "glDrawRangeElements(%s, %u, %u, %d, %s, %p)\n",
1130 _mesa_lookup_enum_by_nr(mode), start, end, count,
1131 _mesa_lookup_enum_by_nr(type), indices);
1132 }
1133
1134 vbo_exec_DrawRangeElementsBaseVertex(mode, start, end, count, type,
1135 indices, 0);
1136 }
1137
1138
1139 /**
1140 * Called by glDrawElements() in immediate mode.
1141 */
1142 static void GLAPIENTRY
1143 vbo_exec_DrawElements(GLenum mode, GLsizei count, GLenum type,
1144 const GLvoid *indices)
1145 {
1146 GET_CURRENT_CONTEXT(ctx);
1147
1148 if (MESA_VERBOSE & VERBOSE_DRAW)
1149 _mesa_debug(ctx, "glDrawElements(%s, %u, %s, %p)\n",
1150 _mesa_lookup_enum_by_nr(mode), count,
1151 _mesa_lookup_enum_by_nr(type), indices);
1152
1153 if (!_mesa_validate_DrawElements( ctx, mode, count, type, indices, 0 ))
1154 return;
1155
1156 vbo_validated_drawrangeelements(ctx, mode, GL_FALSE, ~0, ~0,
1157 count, type, indices, 0, 1, 0);
1158 }
1159
1160
1161 /**
1162 * Called by glDrawElementsBaseVertex() in immediate mode.
1163 */
1164 static void GLAPIENTRY
1165 vbo_exec_DrawElementsBaseVertex(GLenum mode, GLsizei count, GLenum type,
1166 const GLvoid *indices, GLint basevertex)
1167 {
1168 GET_CURRENT_CONTEXT(ctx);
1169
1170 if (MESA_VERBOSE & VERBOSE_DRAW)
1171 _mesa_debug(ctx, "glDrawElementsBaseVertex(%s, %d, %s, %p, %d)\n",
1172 _mesa_lookup_enum_by_nr(mode), count,
1173 _mesa_lookup_enum_by_nr(type), indices, basevertex);
1174
1175 if (!_mesa_validate_DrawElements( ctx, mode, count, type, indices,
1176 basevertex ))
1177 return;
1178
1179 vbo_validated_drawrangeelements(ctx, mode, GL_FALSE, ~0, ~0,
1180 count, type, indices, basevertex, 1, 0);
1181 }
1182
1183
1184 /**
1185 * Called by glDrawElementsInstanced() in immediate mode.
1186 */
1187 static void GLAPIENTRY
1188 vbo_exec_DrawElementsInstanced(GLenum mode, GLsizei count, GLenum type,
1189 const GLvoid *indices, GLsizei numInstances)
1190 {
1191 GET_CURRENT_CONTEXT(ctx);
1192
1193 if (MESA_VERBOSE & VERBOSE_DRAW)
1194 _mesa_debug(ctx, "glDrawElementsInstanced(%s, %d, %s, %p, %d)\n",
1195 _mesa_lookup_enum_by_nr(mode), count,
1196 _mesa_lookup_enum_by_nr(type), indices, numInstances);
1197
1198 if (!_mesa_validate_DrawElementsInstanced(ctx, mode, count, type, indices,
1199 numInstances, 0))
1200 return;
1201
1202 vbo_validated_drawrangeelements(ctx, mode, GL_FALSE, ~0, ~0,
1203 count, type, indices, 0, numInstances, 0);
1204 }
1205
1206
1207 /**
1208 * Called by glDrawElementsInstancedBaseVertex() in immediate mode.
1209 */
1210 static void GLAPIENTRY
1211 vbo_exec_DrawElementsInstancedBaseVertex(GLenum mode, GLsizei count, GLenum type,
1212 const GLvoid *indices, GLsizei numInstances,
1213 GLint basevertex)
1214 {
1215 GET_CURRENT_CONTEXT(ctx);
1216
1217 if (MESA_VERBOSE & VERBOSE_DRAW)
1218 _mesa_debug(ctx, "glDrawElementsInstancedBaseVertex(%s, %d, %s, %p, %d; %d)\n",
1219 _mesa_lookup_enum_by_nr(mode), count,
1220 _mesa_lookup_enum_by_nr(type), indices,
1221 numInstances, basevertex);
1222
1223 if (!_mesa_validate_DrawElementsInstanced(ctx, mode, count, type, indices,
1224 numInstances, basevertex))
1225 return;
1226
1227 vbo_validated_drawrangeelements(ctx, mode, GL_FALSE, ~0, ~0,
1228 count, type, indices, basevertex, numInstances, 0);
1229 }
1230
1231
1232 /**
1233 * Called by glDrawElementsInstancedBaseInstance() in immediate mode.
1234 */
1235 static void GLAPIENTRY
1236 vbo_exec_DrawElementsInstancedBaseInstance(GLenum mode, GLsizei count, GLenum type,
1237 const GLvoid *indices, GLsizei numInstances,
1238 GLuint baseInstance)
1239 {
1240 GET_CURRENT_CONTEXT(ctx);
1241
1242 if (MESA_VERBOSE & VERBOSE_DRAW)
1243 _mesa_debug(ctx, "glDrawElementsInstancedBaseInstance(%s, %d, %s, %p, %d, %d)\n",
1244 _mesa_lookup_enum_by_nr(mode), count,
1245 _mesa_lookup_enum_by_nr(type), indices,
1246 numInstances, baseInstance);
1247
1248 if (!_mesa_validate_DrawElementsInstanced(ctx, mode, count, type, indices,
1249 numInstances, 0))
1250 return;
1251
1252 vbo_validated_drawrangeelements(ctx, mode, GL_FALSE, ~0, ~0,
1253 count, type, indices, 0, numInstances,
1254 baseInstance);
1255 }
1256
1257
1258 /**
1259 * Called by glDrawElementsInstancedBaseVertexBaseInstance() in immediate mode.
1260 */
1261 static void GLAPIENTRY
1262 vbo_exec_DrawElementsInstancedBaseVertexBaseInstance(GLenum mode, GLsizei count, GLenum type,
1263 const GLvoid *indices, GLsizei numInstances,
1264 GLint basevertex, GLuint baseInstance)
1265 {
1266 GET_CURRENT_CONTEXT(ctx);
1267
1268 if (MESA_VERBOSE & VERBOSE_DRAW)
1269 _mesa_debug(ctx, "glDrawElementsInstancedBaseVertexBaseInstance(%s, %d, %s, %p, %d, %d, %d)\n",
1270 _mesa_lookup_enum_by_nr(mode), count,
1271 _mesa_lookup_enum_by_nr(type), indices,
1272 numInstances, basevertex, baseInstance);
1273
1274 if (!_mesa_validate_DrawElementsInstanced(ctx, mode, count, type, indices,
1275 numInstances, basevertex))
1276 return;
1277
1278 vbo_validated_drawrangeelements(ctx, mode, GL_FALSE, ~0, ~0,
1279 count, type, indices, basevertex, numInstances,
1280 baseInstance);
1281 }
1282
1283
1284 /**
1285 * Inner support for both _mesa_MultiDrawElements() and
1286 * _mesa_MultiDrawRangeElements().
1287 * This does the actual rendering after we've checked array indexes, etc.
1288 */
1289 static void
1290 vbo_validated_multidrawelements(struct gl_context *ctx, GLenum mode,
1291 const GLsizei *count, GLenum type,
1292 const GLvoid * const *indices,
1293 GLsizei primcount,
1294 const GLint *basevertex)
1295 {
1296 struct vbo_context *vbo = vbo_context(ctx);
1297 struct vbo_exec_context *exec = &vbo->exec;
1298 struct _mesa_index_buffer ib;
1299 struct _mesa_prim *prim;
1300 unsigned int index_type_size = vbo_sizeof_ib_type(type);
1301 uintptr_t min_index_ptr, max_index_ptr;
1302 GLboolean fallback = GL_FALSE;
1303 int i;
1304
1305 if (primcount == 0)
1306 return;
1307
1308 prim = calloc(1, primcount * sizeof(*prim));
1309 if (prim == NULL) {
1310 _mesa_error(ctx, GL_OUT_OF_MEMORY, "glMultiDrawElements");
1311 return;
1312 }
1313
1314 vbo_bind_arrays(ctx);
1315
1316 min_index_ptr = (uintptr_t)indices[0];
1317 max_index_ptr = 0;
1318 for (i = 0; i < primcount; i++) {
1319 min_index_ptr = MIN2(min_index_ptr, (uintptr_t)indices[i]);
1320 max_index_ptr = MAX2(max_index_ptr, (uintptr_t)indices[i] +
1321 index_type_size * count[i]);
1322 }
1323
1324 /* Check if we can handle this thing as a bunch of index offsets from the
1325 * same index pointer. If we can't, then we have to fall back to doing
1326 * a draw_prims per primitive.
1327 * Check that the difference between each prim's indexes is a multiple of
1328 * the index/element size.
1329 */
1330 if (index_type_size != 1) {
1331 for (i = 0; i < primcount; i++) {
1332 if ((((uintptr_t)indices[i] - min_index_ptr) % index_type_size) != 0) {
1333 fallback = GL_TRUE;
1334 break;
1335 }
1336 }
1337 }
1338
1339 /* Draw primitives individually if one count is zero, so we can easily skip
1340 * that primitive.
1341 */
1342 for (i = 0; i < primcount; i++) {
1343 if (count[i] == 0) {
1344 fallback = GL_TRUE;
1345 break;
1346 }
1347 }
1348
1349 /* If the index buffer isn't in a VBO, then treating the application's
1350 * subranges of the index buffer as one large index buffer may lead to
1351 * us reading unmapped memory.
1352 */
1353 if (!_mesa_is_bufferobj(ctx->Array.ArrayObj->ElementArrayBufferObj))
1354 fallback = GL_TRUE;
1355
1356 if (!fallback) {
1357 ib.count = (max_index_ptr - min_index_ptr) / index_type_size;
1358 ib.type = type;
1359 ib.obj = ctx->Array.ArrayObj->ElementArrayBufferObj;
1360 ib.ptr = (void *)min_index_ptr;
1361
1362 for (i = 0; i < primcount; i++) {
1363 prim[i].begin = (i == 0);
1364 prim[i].end = (i == primcount - 1);
1365 prim[i].weak = 0;
1366 prim[i].pad = 0;
1367 prim[i].mode = mode;
1368 prim[i].start = ((uintptr_t)indices[i] - min_index_ptr) / index_type_size;
1369 prim[i].count = count[i];
1370 prim[i].indexed = 1;
1371 prim[i].num_instances = 1;
1372 prim[i].base_instance = 0;
1373 prim[i].is_indirect = 0;
1374 if (basevertex != NULL)
1375 prim[i].basevertex = basevertex[i];
1376 else
1377 prim[i].basevertex = 0;
1378 }
1379
1380 check_buffers_are_unmapped(exec->array.inputs);
1381 vbo_handle_primitive_restart(ctx, prim, primcount, &ib,
1382 GL_FALSE, ~0, ~0);
1383 } else {
1384 /* render one prim at a time */
1385 for (i = 0; i < primcount; i++) {
1386 if (count[i] == 0)
1387 continue;
1388 ib.count = count[i];
1389 ib.type = type;
1390 ib.obj = ctx->Array.ArrayObj->ElementArrayBufferObj;
1391 ib.ptr = indices[i];
1392
1393 prim[0].begin = 1;
1394 prim[0].end = 1;
1395 prim[0].weak = 0;
1396 prim[0].pad = 0;
1397 prim[0].mode = mode;
1398 prim[0].start = 0;
1399 prim[0].count = count[i];
1400 prim[0].indexed = 1;
1401 prim[0].num_instances = 1;
1402 prim[0].base_instance = 0;
1403 prim[0].is_indirect = 0;
1404 if (basevertex != NULL)
1405 prim[0].basevertex = basevertex[i];
1406 else
1407 prim[0].basevertex = 0;
1408
1409 check_buffers_are_unmapped(exec->array.inputs);
1410 vbo_handle_primitive_restart(ctx, prim, 1, &ib,
1411 GL_FALSE, ~0, ~0);
1412 }
1413 }
1414
1415 free(prim);
1416
1417 if (MESA_DEBUG_FLAGS & DEBUG_ALWAYS_FLUSH) {
1418 _mesa_flush(ctx);
1419 }
1420 }
1421
1422
1423 static void GLAPIENTRY
1424 vbo_exec_MultiDrawElements(GLenum mode,
1425 const GLsizei *count, GLenum type,
1426 const GLvoid * const *indices,
1427 GLsizei primcount)
1428 {
1429 GET_CURRENT_CONTEXT(ctx);
1430
1431 if (!_mesa_validate_MultiDrawElements(ctx, mode, count, type, indices,
1432 primcount, NULL))
1433 return;
1434
1435 vbo_validated_multidrawelements(ctx, mode, count, type, indices, primcount,
1436 NULL);
1437 }
1438
1439
1440 static void GLAPIENTRY
1441 vbo_exec_MultiDrawElementsBaseVertex(GLenum mode,
1442 const GLsizei *count, GLenum type,
1443 const GLvoid * const *indices,
1444 GLsizei primcount,
1445 const GLsizei *basevertex)
1446 {
1447 GET_CURRENT_CONTEXT(ctx);
1448
1449 if (!_mesa_validate_MultiDrawElements(ctx, mode, count, type, indices,
1450 primcount, basevertex))
1451 return;
1452
1453 vbo_validated_multidrawelements(ctx, mode, count, type, indices, primcount,
1454 basevertex);
1455 }
1456
1457 static void
1458 vbo_draw_transform_feedback(struct gl_context *ctx, GLenum mode,
1459 struct gl_transform_feedback_object *obj,
1460 GLuint stream, GLuint numInstances)
1461 {
1462 struct vbo_context *vbo = vbo_context(ctx);
1463 struct vbo_exec_context *exec = &vbo->exec;
1464 struct _mesa_prim prim[2];
1465
1466 if (!_mesa_validate_DrawTransformFeedback(ctx, mode, obj, stream,
1467 numInstances)) {
1468 return;
1469 }
1470
1471 if (ctx->Driver.GetTransformFeedbackVertexCount &&
1472 (ctx->Const.AlwaysUseGetTransformFeedbackVertexCount ||
1473 (ctx->Const.PrimitiveRestartInSoftware &&
1474 ctx->Array._PrimitiveRestart) ||
1475 !vbo_all_varyings_in_vbos(exec->array.inputs))) {
1476 GLsizei n = ctx->Driver.GetTransformFeedbackVertexCount(ctx, obj, stream);
1477 vbo_draw_arrays(ctx, mode, 0, n, numInstances, 0);
1478 return;
1479 }
1480
1481 vbo_bind_arrays(ctx);
1482
1483 /* init most fields to zero */
1484 memset(prim, 0, sizeof(prim));
1485 prim[0].begin = 1;
1486 prim[0].end = 1;
1487 prim[0].mode = mode;
1488 prim[0].num_instances = numInstances;
1489 prim[0].base_instance = 0;
1490 prim[0].is_indirect = 0;
1491
1492 /* Maybe we should do some primitive splitting for primitive restart
1493 * (like in DrawArrays), but we have no way to know how many vertices
1494 * will be rendered. */
1495
1496 check_buffers_are_unmapped(exec->array.inputs);
1497 vbo->draw_prims(ctx, prim, 1, NULL,
1498 GL_TRUE, 0, 0, obj, NULL);
1499
1500 if (MESA_DEBUG_FLAGS & DEBUG_ALWAYS_FLUSH) {
1501 _mesa_flush(ctx);
1502 }
1503 }
1504
1505 /**
1506 * Like DrawArrays, but take the count from a transform feedback object.
1507 * \param mode GL_POINTS, GL_LINES, GL_TRIANGLE_STRIP, etc.
1508 * \param name the transform feedback object
1509 * User still has to setup of the vertex attribute info with
1510 * glVertexPointer, glColorPointer, etc.
1511 * Part of GL_ARB_transform_feedback2.
1512 */
1513 static void GLAPIENTRY
1514 vbo_exec_DrawTransformFeedback(GLenum mode, GLuint name)
1515 {
1516 GET_CURRENT_CONTEXT(ctx);
1517 struct gl_transform_feedback_object *obj =
1518 _mesa_lookup_transform_feedback_object(ctx, name);
1519
1520 if (MESA_VERBOSE & VERBOSE_DRAW)
1521 _mesa_debug(ctx, "glDrawTransformFeedback(%s, %d)\n",
1522 _mesa_lookup_enum_by_nr(mode), name);
1523
1524 vbo_draw_transform_feedback(ctx, mode, obj, 0, 1);
1525 }
1526
1527 static void GLAPIENTRY
1528 vbo_exec_DrawTransformFeedbackStream(GLenum mode, GLuint name, GLuint stream)
1529 {
1530 GET_CURRENT_CONTEXT(ctx);
1531 struct gl_transform_feedback_object *obj =
1532 _mesa_lookup_transform_feedback_object(ctx, name);
1533
1534 if (MESA_VERBOSE & VERBOSE_DRAW)
1535 _mesa_debug(ctx, "glDrawTransformFeedbackStream(%s, %u, %u)\n",
1536 _mesa_lookup_enum_by_nr(mode), name, stream);
1537
1538 vbo_draw_transform_feedback(ctx, mode, obj, stream, 1);
1539 }
1540
1541 static void GLAPIENTRY
1542 vbo_exec_DrawTransformFeedbackInstanced(GLenum mode, GLuint name,
1543 GLsizei primcount)
1544 {
1545 GET_CURRENT_CONTEXT(ctx);
1546 struct gl_transform_feedback_object *obj =
1547 _mesa_lookup_transform_feedback_object(ctx, name);
1548
1549 if (MESA_VERBOSE & VERBOSE_DRAW)
1550 _mesa_debug(ctx, "glDrawTransformFeedbackInstanced(%s, %d)\n",
1551 _mesa_lookup_enum_by_nr(mode), name);
1552
1553 vbo_draw_transform_feedback(ctx, mode, obj, 0, primcount);
1554 }
1555
1556 static void GLAPIENTRY
1557 vbo_exec_DrawTransformFeedbackStreamInstanced(GLenum mode, GLuint name,
1558 GLuint stream, GLsizei primcount)
1559 {
1560 GET_CURRENT_CONTEXT(ctx);
1561 struct gl_transform_feedback_object *obj =
1562 _mesa_lookup_transform_feedback_object(ctx, name);
1563
1564 if (MESA_VERBOSE & VERBOSE_DRAW)
1565 _mesa_debug(ctx, "glDrawTransformFeedbackStreamInstanced"
1566 "(%s, %u, %u, %i)\n",
1567 _mesa_lookup_enum_by_nr(mode), name, stream, primcount);
1568
1569 vbo_draw_transform_feedback(ctx, mode, obj, stream, primcount);
1570 }
1571
1572 static void
1573 vbo_validated_drawarraysindirect(struct gl_context *ctx,
1574 GLenum mode, const GLvoid *indirect)
1575 {
1576 struct vbo_context *vbo = vbo_context(ctx);
1577 struct vbo_exec_context *exec = &vbo->exec;
1578 struct _mesa_prim prim[1];
1579
1580 vbo_bind_arrays(ctx);
1581
1582 memset(prim, 0, sizeof(prim));
1583 prim[0].begin = 1;
1584 prim[0].end = 1;
1585 prim[0].mode = mode;
1586 prim[0].is_indirect = 1;
1587 prim[0].indirect_offset = (GLsizeiptr)indirect;
1588
1589 /* NOTE: We do NOT want to handle primitive restart here, nor perform any
1590 * other checks that require knowledge of the values in the command buffer.
1591 * That would defeat the whole purpose of this function.
1592 */
1593
1594 check_buffers_are_unmapped(exec->array.inputs);
1595 vbo->draw_prims(ctx, prim, 1,
1596 NULL, GL_TRUE, 0, ~0,
1597 NULL,
1598 ctx->DrawIndirectBuffer);
1599
1600 if (MESA_DEBUG_FLAGS & DEBUG_ALWAYS_FLUSH)
1601 _mesa_flush(ctx);
1602 }
1603
1604 static void
1605 vbo_validated_multidrawarraysindirect(struct gl_context *ctx,
1606 GLenum mode,
1607 const GLvoid *indirect,
1608 GLsizei primcount, GLsizei stride)
1609 {
1610 struct vbo_context *vbo = vbo_context(ctx);
1611 struct vbo_exec_context *exec = &vbo->exec;
1612 struct _mesa_prim *prim;
1613 GLsizei i;
1614 GLsizeiptr offset = (GLsizeiptr)indirect;
1615
1616 if (primcount == 0)
1617 return;
1618 prim = calloc(primcount, sizeof(*prim));
1619 if (prim == NULL) {
1620 _mesa_error(ctx, GL_OUT_OF_MEMORY, "glMultiDrawArraysIndirect");
1621 return;
1622 }
1623
1624 vbo_bind_arrays(ctx);
1625
1626 prim[0].begin = 1;
1627 prim[primcount - 1].end = 1;
1628 for (i = 0; i < primcount; ++i, offset += stride) {
1629 prim[i].mode = mode;
1630 prim[i].indirect_offset = offset;
1631 prim[i].is_indirect = 1;
1632 }
1633
1634 check_buffers_are_unmapped(exec->array.inputs);
1635 vbo->draw_prims(ctx, prim, primcount,
1636 NULL, GL_TRUE, 0, ~0,
1637 NULL,
1638 ctx->DrawIndirectBuffer);
1639
1640 free(prim);
1641
1642 if (MESA_DEBUG_FLAGS & DEBUG_ALWAYS_FLUSH)
1643 _mesa_flush(ctx);
1644 }
1645
1646 static void
1647 vbo_validated_drawelementsindirect(struct gl_context *ctx,
1648 GLenum mode, GLenum type,
1649 const GLvoid *indirect)
1650 {
1651 struct vbo_context *vbo = vbo_context(ctx);
1652 struct vbo_exec_context *exec = &vbo->exec;
1653 struct _mesa_index_buffer ib;
1654 struct _mesa_prim prim[1];
1655
1656 vbo_bind_arrays(ctx);
1657
1658 ib.count = 0; /* unknown */
1659 ib.type = type;
1660 ib.obj = ctx->Array.ArrayObj->ElementArrayBufferObj;
1661 ib.ptr = NULL;
1662
1663 memset(prim, 0, sizeof(prim));
1664 prim[0].begin = 1;
1665 prim[0].end = 1;
1666 prim[0].mode = mode;
1667 prim[0].indexed = 1;
1668 prim[0].indirect_offset = (GLsizeiptr)indirect;
1669 prim[0].is_indirect = 1;
1670
1671 check_buffers_are_unmapped(exec->array.inputs);
1672 vbo->draw_prims(ctx, prim, 1,
1673 &ib, GL_TRUE, 0, ~0,
1674 NULL,
1675 ctx->DrawIndirectBuffer);
1676
1677 if (MESA_DEBUG_FLAGS & DEBUG_ALWAYS_FLUSH)
1678 _mesa_flush(ctx);
1679 }
1680
1681 static void
1682 vbo_validated_multidrawelementsindirect(struct gl_context *ctx,
1683 GLenum mode, GLenum type,
1684 const GLvoid *indirect,
1685 GLsizei primcount, GLsizei stride)
1686 {
1687 struct vbo_context *vbo = vbo_context(ctx);
1688 struct vbo_exec_context *exec = &vbo->exec;
1689 struct _mesa_index_buffer ib;
1690 struct _mesa_prim *prim;
1691 GLsizei i;
1692 GLsizeiptr offset = (GLsizeiptr)indirect;
1693
1694 if (primcount == 0)
1695 return;
1696 prim = calloc(primcount, sizeof(*prim));
1697 if (prim == NULL) {
1698 _mesa_error(ctx, GL_OUT_OF_MEMORY, "glMultiDrawElementsIndirect");
1699 return;
1700 }
1701
1702 vbo_bind_arrays(ctx);
1703
1704 /* NOTE: ElementArrayBufferObj is guaranteed to be a VBO. */
1705
1706 ib.count = 0; /* unknown */
1707 ib.type = type;
1708 ib.obj = ctx->Array.ArrayObj->ElementArrayBufferObj;
1709 ib.ptr = NULL;
1710
1711 prim[0].begin = 1;
1712 prim[primcount - 1].end = 1;
1713 for (i = 0; i < primcount; ++i, offset += stride) {
1714 prim[i].mode = mode;
1715 prim[i].indexed = 1;
1716 prim[i].indirect_offset = offset;
1717 prim[i].is_indirect = 1;
1718 }
1719
1720 check_buffers_are_unmapped(exec->array.inputs);
1721 vbo->draw_prims(ctx, prim, primcount,
1722 &ib, GL_TRUE, 0, ~0,
1723 NULL,
1724 ctx->DrawIndirectBuffer);
1725
1726 free(prim);
1727
1728 if (MESA_DEBUG_FLAGS & DEBUG_ALWAYS_FLUSH)
1729 _mesa_flush(ctx);
1730 }
1731
1732 /**
1733 * Like [Multi]DrawArrays/Elements, but they take most arguments from
1734 * a buffer object.
1735 */
1736 static void GLAPIENTRY
1737 vbo_exec_DrawArraysIndirect(GLenum mode, const GLvoid *indirect)
1738 {
1739 GET_CURRENT_CONTEXT(ctx);
1740
1741 if (MESA_VERBOSE & VERBOSE_DRAW)
1742 _mesa_debug(ctx, "glDrawArraysIndirect(%s, %p)\n",
1743 _mesa_lookup_enum_by_nr(mode), indirect);
1744
1745 if (!_mesa_validate_DrawArraysIndirect(ctx, mode, indirect))
1746 return;
1747
1748 vbo_validated_drawarraysindirect(ctx, mode, indirect);
1749 }
1750
1751 static void GLAPIENTRY
1752 vbo_exec_DrawElementsIndirect(GLenum mode, GLenum type,
1753 const GLvoid *indirect)
1754 {
1755 GET_CURRENT_CONTEXT(ctx);
1756
1757 if (MESA_VERBOSE & VERBOSE_DRAW)
1758 _mesa_debug(ctx, "glDrawElementsIndirect(%s, %s, %p)\n",
1759 _mesa_lookup_enum_by_nr(mode),
1760 _mesa_lookup_enum_by_nr(type), indirect);
1761
1762 if (!_mesa_validate_DrawElementsIndirect(ctx, mode, type, indirect))
1763 return;
1764
1765 vbo_validated_drawelementsindirect(ctx, mode, type, indirect);
1766 }
1767
1768 static void GLAPIENTRY
1769 vbo_exec_MultiDrawArraysIndirect(GLenum mode,
1770 const GLvoid *indirect,
1771 GLsizei primcount, GLsizei stride)
1772 {
1773 GET_CURRENT_CONTEXT(ctx);
1774
1775 if (MESA_VERBOSE & VERBOSE_DRAW)
1776 _mesa_debug(ctx, "glMultiDrawArraysIndirect(%s, %p, %i, %i)\n",
1777 _mesa_lookup_enum_by_nr(mode), indirect, primcount, stride);
1778
1779 /* If <stride> is zero, the array elements are treated as tightly packed. */
1780 if (stride == 0)
1781 stride = 4 * sizeof(GLuint); /* sizeof(DrawArraysIndirectCommand) */
1782
1783 if (!_mesa_validate_MultiDrawArraysIndirect(ctx, mode,
1784 indirect,
1785 primcount, stride))
1786 return;
1787
1788 vbo_validated_multidrawarraysindirect(ctx, mode,
1789 indirect,
1790 primcount, stride);
1791 }
1792
1793 static void GLAPIENTRY
1794 vbo_exec_MultiDrawElementsIndirect(GLenum mode, GLenum type,
1795 const GLvoid *indirect,
1796 GLsizei primcount, GLsizei stride)
1797 {
1798 GET_CURRENT_CONTEXT(ctx);
1799
1800 if (MESA_VERBOSE & VERBOSE_DRAW)
1801 _mesa_debug(ctx, "glMultiDrawElementsIndirect(%s, %s, %p, %i, %i)\n",
1802 _mesa_lookup_enum_by_nr(mode),
1803 _mesa_lookup_enum_by_nr(type), indirect, primcount, stride);
1804
1805 /* If <stride> is zero, the array elements are treated as tightly packed. */
1806 if (stride == 0)
1807 stride = 5 * sizeof(GLuint); /* sizeof(DrawElementsIndirectCommand) */
1808
1809 if (!_mesa_validate_MultiDrawElementsIndirect(ctx, mode, type,
1810 indirect,
1811 primcount, stride))
1812 return;
1813
1814 vbo_validated_multidrawelementsindirect(ctx, mode, type,
1815 indirect,
1816 primcount, stride);
1817 }
1818
1819 /**
1820 * Initialize the dispatch table with the VBO functions for drawing.
1821 */
1822 void
1823 vbo_initialize_exec_dispatch(const struct gl_context *ctx,
1824 struct _glapi_table *exec)
1825 {
1826 SET_DrawArrays(exec, vbo_exec_DrawArrays);
1827 SET_DrawElements(exec, vbo_exec_DrawElements);
1828
1829 if (_mesa_is_desktop_gl(ctx) || _mesa_is_gles3(ctx)) {
1830 SET_DrawRangeElements(exec, vbo_exec_DrawRangeElements);
1831 }
1832
1833 SET_MultiDrawElementsEXT(exec, vbo_exec_MultiDrawElements);
1834
1835 if (ctx->API == API_OPENGL_COMPAT) {
1836 SET_Rectf(exec, vbo_exec_Rectf);
1837 SET_EvalMesh1(exec, vbo_exec_EvalMesh1);
1838 SET_EvalMesh2(exec, vbo_exec_EvalMesh2);
1839 }
1840
1841 if (_mesa_is_desktop_gl(ctx)) {
1842 SET_DrawElementsBaseVertex(exec, vbo_exec_DrawElementsBaseVertex);
1843 SET_DrawRangeElementsBaseVertex(exec, vbo_exec_DrawRangeElementsBaseVertex);
1844 SET_MultiDrawElementsBaseVertex(exec, vbo_exec_MultiDrawElementsBaseVertex);
1845 SET_DrawArraysInstancedBaseInstance(exec, vbo_exec_DrawArraysInstancedBaseInstance);
1846 SET_DrawElementsInstancedBaseInstance(exec, vbo_exec_DrawElementsInstancedBaseInstance);
1847 SET_DrawElementsInstancedBaseVertex(exec, vbo_exec_DrawElementsInstancedBaseVertex);
1848 SET_DrawElementsInstancedBaseVertexBaseInstance(exec, vbo_exec_DrawElementsInstancedBaseVertexBaseInstance);
1849 }
1850
1851 if (ctx->API == API_OPENGL_CORE) {
1852 SET_DrawArraysIndirect(exec, vbo_exec_DrawArraysIndirect);
1853 SET_DrawElementsIndirect(exec, vbo_exec_DrawElementsIndirect);
1854 SET_MultiDrawArraysIndirect(exec, vbo_exec_MultiDrawArraysIndirect);
1855 SET_MultiDrawElementsIndirect(exec, vbo_exec_MultiDrawElementsIndirect);
1856 }
1857
1858 if (_mesa_is_desktop_gl(ctx) || _mesa_is_gles3(ctx)) {
1859 SET_DrawArraysInstancedARB(exec, vbo_exec_DrawArraysInstanced);
1860 SET_DrawElementsInstancedARB(exec, vbo_exec_DrawElementsInstanced);
1861 }
1862
1863 if (_mesa_is_desktop_gl(ctx)) {
1864 SET_DrawTransformFeedback(exec, vbo_exec_DrawTransformFeedback);
1865 SET_DrawTransformFeedbackStream(exec, vbo_exec_DrawTransformFeedbackStream);
1866 SET_DrawTransformFeedbackInstanced(exec, vbo_exec_DrawTransformFeedbackInstanced);
1867 SET_DrawTransformFeedbackStreamInstanced(exec, vbo_exec_DrawTransformFeedbackStreamInstanced);
1868 }
1869 }
1870
1871
1872
1873 /**
1874 * The following functions are only used for OpenGL ES 1/2 support.
1875 * And some aren't even supported (yet) in ES 1/2.
1876 */
1877
1878
1879 void GLAPIENTRY
1880 _mesa_DrawArrays(GLenum mode, GLint first, GLsizei count)
1881 {
1882 vbo_exec_DrawArrays(mode, first, count);
1883 }
1884
1885
1886 void GLAPIENTRY
1887 _mesa_DrawElements(GLenum mode, GLsizei count, GLenum type,
1888 const GLvoid *indices)
1889 {
1890 vbo_exec_DrawElements(mode, count, type, indices);
1891 }
1892
1893
1894 void GLAPIENTRY
1895 _mesa_DrawElementsBaseVertex(GLenum mode, GLsizei count, GLenum type,
1896 const GLvoid *indices, GLint basevertex)
1897 {
1898 vbo_exec_DrawElementsBaseVertex(mode, count, type, indices, basevertex);
1899 }
1900
1901
1902 void GLAPIENTRY
1903 _mesa_DrawRangeElements(GLenum mode, GLuint start, GLuint end, GLsizei count,
1904 GLenum type, const GLvoid *indices)
1905 {
1906 vbo_exec_DrawRangeElements(mode, start, end, count, type, indices);
1907 }
1908
1909
1910 void GLAPIENTRY
1911 _mesa_DrawRangeElementsBaseVertex(GLenum mode, GLuint start, GLuint end,
1912 GLsizei count, GLenum type,
1913 const GLvoid *indices, GLint basevertex)
1914 {
1915 vbo_exec_DrawRangeElementsBaseVertex(mode, start, end, count, type,
1916 indices, basevertex);
1917 }
1918
1919
1920 void GLAPIENTRY
1921 _mesa_MultiDrawElementsEXT(GLenum mode, const GLsizei *count, GLenum type,
1922 const GLvoid **indices, GLsizei primcount)
1923 {
1924 vbo_exec_MultiDrawElements(mode, count, type, indices, primcount);
1925 }
1926
1927
1928 void GLAPIENTRY
1929 _mesa_MultiDrawElementsBaseVertex(GLenum mode,
1930 const GLsizei *count, GLenum type,
1931 const GLvoid **indices, GLsizei primcount,
1932 const GLint *basevertex)
1933 {
1934 vbo_exec_MultiDrawElementsBaseVertex(mode, count, type, indices,
1935 primcount, basevertex);
1936 }
1937
1938 void GLAPIENTRY
1939 _mesa_DrawTransformFeedback(GLenum mode, GLuint name)
1940 {
1941 vbo_exec_DrawTransformFeedback(mode, name);
1942 }