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