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