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