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 "arrayobj.h"
31 #include "glheader.h"
32 #include "c99_alloca.h"
33 #include "context.h"
34 #include "state.h"
35 #include "draw.h"
36 #include "draw_validate.h"
37 #include "dispatch.h"
38 #include "varray.h"
39 #include "bufferobj.h"
40 #include "enums.h"
41 #include "macros.h"
42 #include "transformfeedback.h"
43 #include "pipe/p_state.h"
44 #include "api_exec_decl.h"
45
46 #include "state_tracker/st_context.h"
47 #include "state_tracker/st_draw.h"
48
49 typedef struct {
50 GLuint count;
51 GLuint primCount;
52 GLuint first;
53 GLuint baseInstance;
54 } DrawArraysIndirectCommand;
55
56 typedef struct {
57 GLuint count;
58 GLuint primCount;
59 GLuint firstIndex;
60 GLint baseVertex;
61 GLuint baseInstance;
62 } DrawElementsIndirectCommand;
63
64
65 /**
66 * Want to figure out which fragment program inputs are actually
67 * constant/current values from ctx->Current. These should be
68 * referenced as a tracked state variable rather than a fragment
69 * program input, to save the overhead of putting a constant value in
70 * every submitted vertex, transferring it to hardware, interpolating
71 * it across the triangle, etc...
72 *
73 * When there is a VP bound, just use vp->outputs. But when we're
74 * generating vp from fixed function state, basically want to
75 * calculate:
76 *
77 * vp_out_2_fp_in( vp_in_2_vp_out( varying_inputs ) |
78 * potential_vp_outputs )
79 *
80 * Where potential_vp_outputs is calculated by looking at enabled
81 * texgen, etc.
82 *
83 * The generated fragment program should then only declare inputs that
84 * may vary or otherwise differ from the ctx->Current values.
85 * Otherwise, the fp should track them as state values instead.
86 */
87 void
_mesa_set_varying_vp_inputs(struct gl_context * ctx,GLbitfield varying_inputs)88 _mesa_set_varying_vp_inputs(struct gl_context *ctx, GLbitfield varying_inputs)
89 {
90 if (ctx->VertexProgram._VPModeOptimizesConstantAttribs &&
91 ctx->VertexProgram._VaryingInputs != varying_inputs) {
92 ctx->VertexProgram._VaryingInputs = varying_inputs;
93 ctx->NewState |= _NEW_FF_VERT_PROGRAM | _NEW_FF_FRAG_PROGRAM;
94 }
95 }
96
97
98 /**
99 * Set the _DrawVAO and the net enabled arrays.
100 * The vao->_Enabled bitmask is transformed due to position/generic0
101 * as stored in vao->_AttributeMapMode. Then the filter bitmask is applied
102 * to filter out arrays unwanted for the currently executed draw operation.
103 * For example, the generic attributes are masked out form the _DrawVAO's
104 * enabled arrays when a fixed function array draw is executed.
105 */
106 void
_mesa_set_draw_vao(struct gl_context * ctx,struct gl_vertex_array_object * vao,GLbitfield filter)107 _mesa_set_draw_vao(struct gl_context *ctx, struct gl_vertex_array_object *vao,
108 GLbitfield filter)
109 {
110 struct gl_vertex_array_object **ptr = &ctx->Array._DrawVAO;
111 bool new_vertex_buffers = false, new_vertex_elements = false;
112
113 if (*ptr != vao) {
114 _mesa_reference_vao_(ctx, ptr, vao);
115 new_vertex_buffers = true;
116 new_vertex_elements = true;
117 }
118
119 if (vao->NewVertexBuffers || vao->NewVertexElements) {
120 _mesa_update_vao_derived_arrays(ctx, vao);
121 new_vertex_buffers |= vao->NewVertexBuffers;
122 new_vertex_elements |= vao->NewVertexElements;
123 vao->NewVertexBuffers = false;
124 vao->NewVertexElements = false;
125 }
126
127 assert(vao->_EnabledWithMapMode ==
128 _mesa_vao_enable_to_vp_inputs(vao->_AttributeMapMode, vao->Enabled));
129
130 /* Filter out unwanted arrays. */
131 const GLbitfield enabled = filter & vao->_EnabledWithMapMode;
132 if (ctx->Array._DrawVAOEnabledAttribs != enabled) {
133 ctx->Array._DrawVAOEnabledAttribs = enabled;
134 new_vertex_buffers = true;
135 new_vertex_elements = true;
136 }
137
138 if (new_vertex_buffers || new_vertex_elements) {
139 ctx->NewDriverState |= ST_NEW_VERTEX_ARRAYS;
140 ctx->Array.NewVertexElements |= new_vertex_elements;
141 }
142
143 _mesa_set_varying_vp_inputs(ctx, enabled);
144 }
145
146
147 /**
148 * Is 'mode' a valid value for glBegin(), glDrawArrays(), glDrawElements(),
149 * etc? Also, do additional checking related to transformation feedback.
150 * Note: this function cannot be called during glNewList(GL_COMPILE) because
151 * this code depends on current transform feedback state.
152 * Also, do additional checking related to tessellation shaders.
153 */
154 static GLenum
valid_prim_mode_custom(struct gl_context * ctx,GLenum mode,GLbitfield valid_prim_mask)155 valid_prim_mode_custom(struct gl_context *ctx, GLenum mode,
156 GLbitfield valid_prim_mask)
157 {
158 #if DEBUG
159 unsigned mask = ctx->ValidPrimMask;
160 unsigned mask_indexed = ctx->ValidPrimMaskIndexed;
161 bool drawpix_valid = ctx->DrawPixValid;
162 _mesa_update_valid_to_render_state(ctx);
163 assert(mask == ctx->ValidPrimMask &&
164 mask_indexed == ctx->ValidPrimMaskIndexed &&
165 drawpix_valid == ctx->DrawPixValid);
166 #endif
167
168 /* All primitive type enums are less than 32, so we can use the shift. */
169 if (mode >= 32 || !((1u << mode) & valid_prim_mask)) {
170 /* If the primitive type is not in SupportedPrimMask, set GL_INVALID_ENUM,
171 * else set DrawGLError (e.g. GL_INVALID_OPERATION).
172 */
173 return mode >= 32 || !((1u << mode) & ctx->SupportedPrimMask) ?
174 GL_INVALID_ENUM : ctx->DrawGLError;
175 }
176
177 return GL_NO_ERROR;
178 }
179
180 GLenum
_mesa_valid_prim_mode(struct gl_context * ctx,GLenum mode)181 _mesa_valid_prim_mode(struct gl_context *ctx, GLenum mode)
182 {
183 return valid_prim_mode_custom(ctx, mode, ctx->ValidPrimMask);
184 }
185
186 static GLenum
valid_prim_mode_indexed(struct gl_context * ctx,GLenum mode)187 valid_prim_mode_indexed(struct gl_context *ctx, GLenum mode)
188 {
189 return valid_prim_mode_custom(ctx, mode, ctx->ValidPrimMaskIndexed);
190 }
191
192 /**
193 * Verify that the element type is valid.
194 *
195 * Generates \c GL_INVALID_ENUM and returns \c false if it is not.
196 */
197 static GLenum
valid_elements_type(struct gl_context * ctx,GLenum type)198 valid_elements_type(struct gl_context *ctx, GLenum type)
199 {
200 /* GL_UNSIGNED_BYTE = 0x1401
201 * GL_UNSIGNED_SHORT = 0x1403
202 * GL_UNSIGNED_INT = 0x1405
203 *
204 * The trick is that bit 1 and bit 2 mean USHORT and UINT, respectively.
205 * After clearing those two bits (with ~6), we should get UBYTE.
206 * Both bits can't be set, because the enum would be greater than UINT.
207 */
208 if (!(type <= GL_UNSIGNED_INT && (type & ~6) == GL_UNSIGNED_BYTE))
209 return GL_INVALID_ENUM;
210
211 return GL_NO_ERROR;
212 }
213
214 static inline bool
indices_aligned(unsigned index_size_shift,const GLvoid * indices)215 indices_aligned(unsigned index_size_shift, const GLvoid *indices)
216 {
217 /* Require that indices are aligned to the element size. GL doesn't specify
218 * an error for this, but the ES 3.0 spec says:
219 *
220 * "Clients must align data elements consistently with the requirements
221 * of the client platform, with an additional base-level requirement
222 * that an offset within a buffer to a datum comprising N basic machine
223 * units be a multiple of N"
224 *
225 * This is only required by index buffers, not user indices.
226 */
227 return ((uintptr_t)indices & ((1 << index_size_shift) - 1)) == 0;
228 }
229
230 static GLenum
validate_DrawElements_common(struct gl_context * ctx,GLenum mode,GLsizei count,GLsizei numInstances,GLenum type)231 validate_DrawElements_common(struct gl_context *ctx, GLenum mode,
232 GLsizei count, GLsizei numInstances, GLenum type)
233 {
234 if (count < 0 || numInstances < 0)
235 return GL_INVALID_VALUE;
236
237 GLenum error = valid_prim_mode_indexed(ctx, mode);
238 if (error)
239 return error;
240
241 return valid_elements_type(ctx, type);
242 }
243
244 /**
245 * Error checking for glDrawElements(). Includes parameter checking
246 * and VBO bounds checking.
247 * \return GL_TRUE if OK to render, GL_FALSE if error found
248 */
249 static GLboolean
_mesa_validate_DrawElements(struct gl_context * ctx,GLenum mode,GLsizei count,GLenum type)250 _mesa_validate_DrawElements(struct gl_context *ctx,
251 GLenum mode, GLsizei count, GLenum type)
252 {
253 GLenum error = validate_DrawElements_common(ctx, mode, count, 1, type);
254 if (error)
255 _mesa_error(ctx, error, "glDrawElements");
256
257 return !error;
258 }
259
260
261 /**
262 * Error checking for glMultiDrawElements(). Includes parameter checking
263 * and VBO bounds checking.
264 * \return GL_TRUE if OK to render, GL_FALSE if error found
265 */
266 static GLboolean
_mesa_validate_MultiDrawElements(struct gl_context * ctx,GLenum mode,const GLsizei * count,GLenum type,const GLvoid * const * indices,GLsizei primcount)267 _mesa_validate_MultiDrawElements(struct gl_context *ctx,
268 GLenum mode, const GLsizei *count,
269 GLenum type, const GLvoid * const *indices,
270 GLsizei primcount)
271 {
272 GLenum error;
273
274 /*
275 * Section 2.3.1 (Errors) of the OpenGL 4.5 (Core Profile) spec says:
276 *
277 * "If a negative number is provided where an argument of type sizei or
278 * sizeiptr is specified, an INVALID_VALUE error is generated."
279 *
280 * and in the same section:
281 *
282 * "In other cases, there are no side effects unless otherwise noted;
283 * the command which generates the error is ignored so that it has no
284 * effect on GL state or framebuffer contents."
285 *
286 * Hence, check both primcount and all the count[i].
287 */
288 if (primcount < 0) {
289 error = GL_INVALID_VALUE;
290 } else {
291 error = valid_prim_mode_indexed(ctx, mode);
292
293 if (!error) {
294 error = valid_elements_type(ctx, type);
295
296 if (!error) {
297 for (int i = 0; i < primcount; i++) {
298 if (count[i] < 0) {
299 error = GL_INVALID_VALUE;
300 break;
301 }
302 }
303 }
304 }
305 }
306
307 if (error)
308 _mesa_error(ctx, error, "glMultiDrawElements");
309
310 /* Not using a VBO for indices, so avoid NULL pointer derefs later.
311 */
312 if (!ctx->Array.VAO->IndexBufferObj) {
313 for (int i = 0; i < primcount; i++) {
314 if (!indices[i])
315 return GL_FALSE;
316 }
317 }
318
319 return !error;
320 }
321
322
323 /**
324 * Error checking for glDrawRangeElements(). Includes parameter checking
325 * and VBO bounds checking.
326 * \return GL_TRUE if OK to render, GL_FALSE if error found
327 */
328 static GLboolean
_mesa_validate_DrawRangeElements(struct gl_context * ctx,GLenum mode,GLuint start,GLuint end,GLsizei count,GLenum type)329 _mesa_validate_DrawRangeElements(struct gl_context *ctx, GLenum mode,
330 GLuint start, GLuint end,
331 GLsizei count, GLenum type)
332 {
333 GLenum error;
334
335 if (end < start) {
336 error = GL_INVALID_VALUE;
337 } else {
338 error = validate_DrawElements_common(ctx, mode, count, 1, type);
339 }
340
341 if (error)
342 _mesa_error(ctx, error, "glDrawRangeElements");
343
344 return !error;
345 }
346
347
348 static bool
need_xfb_remaining_prims_check(const struct gl_context * ctx)349 need_xfb_remaining_prims_check(const struct gl_context *ctx)
350 {
351 /* From the GLES3 specification, section 2.14.2 (Transform Feedback
352 * Primitive Capture):
353 *
354 * The error INVALID_OPERATION is generated by DrawArrays and
355 * DrawArraysInstanced if recording the vertices of a primitive to the
356 * buffer objects being used for transform feedback purposes would result
357 * in either exceeding the limits of any buffer object’s size, or in
358 * exceeding the end position offset + size − 1, as set by
359 * BindBufferRange.
360 *
361 * This is in contrast to the behaviour of desktop GL, where the extra
362 * primitives are silently dropped from the transform feedback buffer.
363 *
364 * This text is removed in ES 3.2, presumably because it's not really
365 * implementable with geometry and tessellation shaders. In fact,
366 * the OES_geometry_shader spec says:
367 *
368 * "(13) Does this extension change how transform feedback operates
369 * compared to unextended OpenGL ES 3.0 or 3.1?
370 *
371 * RESOLVED: Yes. Because dynamic geometry amplification in a geometry
372 * shader can make it difficult if not impossible to predict the amount
373 * of geometry that may be generated in advance of executing the shader,
374 * the draw-time error for transform feedback buffer overflow conditions
375 * is removed and replaced with the GL behavior (primitives are not
376 * written and the corresponding counter is not updated)..."
377 */
378 return _mesa_is_gles3(ctx) && _mesa_is_xfb_active_and_unpaused(ctx) &&
379 !_mesa_has_OES_geometry_shader(ctx) &&
380 !_mesa_has_OES_tessellation_shader(ctx);
381 }
382
383
384 /**
385 * Figure out the number of transform feedback primitives that will be output
386 * considering the drawing mode, number of vertices, and instance count,
387 * assuming that no geometry shading is done and primitive restart is not
388 * used.
389 *
390 * This is used by driver back-ends in implementing the PRIMITIVES_GENERATED
391 * and TRANSFORM_FEEDBACK_PRIMITIVES_WRITTEN queries. It is also used to
392 * pre-validate draw calls in GLES3 (where draw calls only succeed if there is
393 * enough room in the transform feedback buffer for the result).
394 */
395 static size_t
count_tessellated_primitives(GLenum mode,GLuint count,GLuint num_instances)396 count_tessellated_primitives(GLenum mode, GLuint count, GLuint num_instances)
397 {
398 size_t num_primitives;
399 switch (mode) {
400 case GL_POINTS:
401 num_primitives = count;
402 break;
403 case GL_LINE_STRIP:
404 num_primitives = count >= 2 ? count - 1 : 0;
405 break;
406 case GL_LINE_LOOP:
407 num_primitives = count >= 2 ? count : 0;
408 break;
409 case GL_LINES:
410 num_primitives = count / 2;
411 break;
412 case GL_TRIANGLE_STRIP:
413 case GL_TRIANGLE_FAN:
414 case GL_POLYGON:
415 num_primitives = count >= 3 ? count - 2 : 0;
416 break;
417 case GL_TRIANGLES:
418 num_primitives = count / 3;
419 break;
420 case GL_QUAD_STRIP:
421 num_primitives = count >= 4 ? ((count / 2) - 1) * 2 : 0;
422 break;
423 case GL_QUADS:
424 num_primitives = (count / 4) * 2;
425 break;
426 case GL_LINES_ADJACENCY:
427 num_primitives = count / 4;
428 break;
429 case GL_LINE_STRIP_ADJACENCY:
430 num_primitives = count >= 4 ? count - 3 : 0;
431 break;
432 case GL_TRIANGLES_ADJACENCY:
433 num_primitives = count / 6;
434 break;
435 case GL_TRIANGLE_STRIP_ADJACENCY:
436 num_primitives = count >= 6 ? (count - 4) / 2 : 0;
437 break;
438 default:
439 assert(!"Unexpected primitive type in count_tessellated_primitives");
440 num_primitives = 0;
441 break;
442 }
443 return num_primitives * num_instances;
444 }
445
446
447 static GLenum
validate_draw_arrays(struct gl_context * ctx,GLenum mode,GLsizei count,GLsizei numInstances)448 validate_draw_arrays(struct gl_context *ctx,
449 GLenum mode, GLsizei count, GLsizei numInstances)
450 {
451 if (count < 0 || numInstances < 0)
452 return GL_INVALID_VALUE;
453
454 GLenum error = _mesa_valid_prim_mode(ctx, mode);
455 if (error)
456 return error;
457
458 if (need_xfb_remaining_prims_check(ctx)) {
459 struct gl_transform_feedback_object *xfb_obj
460 = ctx->TransformFeedback.CurrentObject;
461 size_t prim_count = count_tessellated_primitives(mode, count, numInstances);
462 if (xfb_obj->GlesRemainingPrims < prim_count)
463 return GL_INVALID_OPERATION;
464
465 xfb_obj->GlesRemainingPrims -= prim_count;
466 }
467
468 return GL_NO_ERROR;
469 }
470
471 /**
472 * Called from the tnl module to error check the function parameters and
473 * verify that we really can draw something.
474 * \return GL_TRUE if OK to render, GL_FALSE if error found
475 */
476 static GLboolean
_mesa_validate_DrawArrays(struct gl_context * ctx,GLenum mode,GLsizei count)477 _mesa_validate_DrawArrays(struct gl_context *ctx, GLenum mode, GLsizei count)
478 {
479 GLenum error = validate_draw_arrays(ctx, mode, count, 1);
480
481 if (error)
482 _mesa_error(ctx, error, "glDrawArrays");
483
484 return !error;
485 }
486
487
488 static GLboolean
_mesa_validate_DrawArraysInstanced(struct gl_context * ctx,GLenum mode,GLint first,GLsizei count,GLsizei numInstances)489 _mesa_validate_DrawArraysInstanced(struct gl_context *ctx, GLenum mode, GLint first,
490 GLsizei count, GLsizei numInstances)
491 {
492 GLenum error;
493
494 if (first < 0) {
495 error = GL_INVALID_VALUE;
496 } else {
497 error = validate_draw_arrays(ctx, mode, count, numInstances);
498 }
499
500 if (error)
501 _mesa_error(ctx, error, "glDrawArraysInstanced");
502
503 return !error;
504 }
505
506
507 /**
508 * Called to error check the function parameters.
509 *
510 * Note that glMultiDrawArrays is not part of GLES, so there's limited scope
511 * for sharing code with the validation of glDrawArrays.
512 */
513 static bool
_mesa_validate_MultiDrawArrays(struct gl_context * ctx,GLenum mode,const GLsizei * count,GLsizei primcount)514 _mesa_validate_MultiDrawArrays(struct gl_context *ctx, GLenum mode,
515 const GLsizei *count, GLsizei primcount)
516 {
517 GLenum error;
518
519 if (primcount < 0) {
520 error = GL_INVALID_VALUE;
521 } else {
522 error = _mesa_valid_prim_mode(ctx, mode);
523
524 if (!error) {
525 for (int i = 0; i < primcount; ++i) {
526 if (count[i] < 0) {
527 error = GL_INVALID_VALUE;
528 break;
529 }
530 }
531
532 if (!error) {
533 if (need_xfb_remaining_prims_check(ctx)) {
534 struct gl_transform_feedback_object *xfb_obj
535 = ctx->TransformFeedback.CurrentObject;
536 size_t xfb_prim_count = 0;
537
538 for (int i = 0; i < primcount; ++i) {
539 xfb_prim_count +=
540 count_tessellated_primitives(mode, count[i], 1);
541 }
542
543 if (xfb_obj->GlesRemainingPrims < xfb_prim_count) {
544 error = GL_INVALID_OPERATION;
545 } else {
546 xfb_obj->GlesRemainingPrims -= xfb_prim_count;
547 }
548 }
549 }
550 }
551 }
552
553 if (error)
554 _mesa_error(ctx, error, "glMultiDrawArrays");
555
556 return !error;
557 }
558
559
560 static GLboolean
_mesa_validate_DrawElementsInstanced(struct gl_context * ctx,GLenum mode,GLsizei count,GLenum type,GLsizei numInstances)561 _mesa_validate_DrawElementsInstanced(struct gl_context *ctx,
562 GLenum mode, GLsizei count, GLenum type,
563 GLsizei numInstances)
564 {
565 GLenum error =
566 validate_DrawElements_common(ctx, mode, count, numInstances, type);
567
568 if (error)
569 _mesa_error(ctx, error, "glDrawElementsInstanced");
570
571 return !error;
572 }
573
574
575 static GLboolean
_mesa_validate_DrawTransformFeedback(struct gl_context * ctx,GLenum mode,struct gl_transform_feedback_object * obj,GLuint stream,GLsizei numInstances)576 _mesa_validate_DrawTransformFeedback(struct gl_context *ctx,
577 GLenum mode,
578 struct gl_transform_feedback_object *obj,
579 GLuint stream,
580 GLsizei numInstances)
581 {
582 GLenum error;
583
584 /* From the GL 4.5 specification, page 429:
585 * "An INVALID_VALUE error is generated if id is not the name of a
586 * transform feedback object."
587 */
588 if (!obj || !obj->EverBound || stream >= ctx->Const.MaxVertexStreams ||
589 numInstances < 0) {
590 error = GL_INVALID_VALUE;
591 } else {
592 error = _mesa_valid_prim_mode(ctx, mode);
593
594 if (!error) {
595 if (!obj->EndedAnytime)
596 error = GL_INVALID_OPERATION;
597 }
598 }
599
600 if (error)
601 _mesa_error(ctx, error, "glDrawTransformFeedback*");
602
603 return !error;
604 }
605
606 static GLenum
valid_draw_indirect(struct gl_context * ctx,GLenum mode,const GLvoid * indirect,GLsizei size)607 valid_draw_indirect(struct gl_context *ctx,
608 GLenum mode, const GLvoid *indirect,
609 GLsizei size)
610 {
611 const uint64_t end = (uint64_t) (uintptr_t) indirect + size;
612
613 /* OpenGL ES 3.1 spec. section 10.5:
614 *
615 * "DrawArraysIndirect requires that all data sourced for the
616 * command, including the DrawArraysIndirectCommand
617 * structure, be in buffer objects, and may not be called when
618 * the default vertex array object is bound."
619 */
620 if (ctx->API != API_OPENGL_COMPAT &&
621 ctx->Array.VAO == ctx->Array.DefaultVAO)
622 return GL_INVALID_OPERATION;
623
624 /* From OpenGL ES 3.1 spec. section 10.5:
625 * "An INVALID_OPERATION error is generated if zero is bound to
626 * VERTEX_ARRAY_BINDING, DRAW_INDIRECT_BUFFER or to any enabled
627 * vertex array."
628 *
629 * Here we check that for each enabled vertex array we have a vertex
630 * buffer bound.
631 */
632 if (_mesa_is_gles31(ctx) &&
633 ctx->Array.VAO->Enabled & ~ctx->Array.VAO->VertexAttribBufferMask)
634 return GL_INVALID_OPERATION;
635
636 GLenum error = _mesa_valid_prim_mode(ctx, mode);
637 if (error)
638 return error;
639
640 /* OpenGL ES 3.1 specification, section 10.5:
641 *
642 * "An INVALID_OPERATION error is generated if
643 * transform feedback is active and not paused."
644 *
645 * The OES_geometry_shader spec says:
646 *
647 * On p. 250 in the errors section for the DrawArraysIndirect command,
648 * and on p. 254 in the errors section for the DrawElementsIndirect
649 * command, delete the errors which state:
650 *
651 * "An INVALID_OPERATION error is generated if transform feedback is
652 * active and not paused."
653 *
654 * (thus allowing transform feedback to work with indirect draw commands).
655 */
656 if (_mesa_is_gles31(ctx) && !ctx->Extensions.OES_geometry_shader &&
657 _mesa_is_xfb_active_and_unpaused(ctx))
658 return GL_INVALID_OPERATION;
659
660 /* From OpenGL version 4.4. section 10.5
661 * and OpenGL ES 3.1, section 10.6:
662 *
663 * "An INVALID_VALUE error is generated if indirect is not a
664 * multiple of the size, in basic machine units, of uint."
665 */
666 if ((GLsizeiptr)indirect & (sizeof(GLuint) - 1))
667 return GL_INVALID_VALUE;
668
669 if (!ctx->DrawIndirectBuffer)
670 return GL_INVALID_OPERATION;
671
672 if (_mesa_check_disallowed_mapping(ctx->DrawIndirectBuffer))
673 return GL_INVALID_OPERATION;
674
675 /* From the ARB_draw_indirect specification:
676 * "An INVALID_OPERATION error is generated if the commands source data
677 * beyond the end of the buffer object [...]"
678 */
679 if (ctx->DrawIndirectBuffer->Size < end)
680 return GL_INVALID_OPERATION;
681
682 return GL_NO_ERROR;
683 }
684
685 static inline GLenum
valid_draw_indirect_elements(struct gl_context * ctx,GLenum mode,GLenum type,const GLvoid * indirect,GLsizeiptr size)686 valid_draw_indirect_elements(struct gl_context *ctx,
687 GLenum mode, GLenum type, const GLvoid *indirect,
688 GLsizeiptr size)
689 {
690 GLenum error = valid_elements_type(ctx, type);
691 if (error)
692 return error;
693
694 /*
695 * Unlike regular DrawElementsInstancedBaseVertex commands, the indices
696 * may not come from a client array and must come from an index buffer.
697 * If no element array buffer is bound, an INVALID_OPERATION error is
698 * generated.
699 */
700 if (!ctx->Array.VAO->IndexBufferObj)
701 return GL_INVALID_OPERATION;
702
703 return valid_draw_indirect(ctx, mode, indirect, size);
704 }
705
706 static GLboolean
_mesa_valid_draw_indirect_multi(struct gl_context * ctx,GLsizei primcount,GLsizei stride,const char * name)707 _mesa_valid_draw_indirect_multi(struct gl_context *ctx,
708 GLsizei primcount, GLsizei stride,
709 const char *name)
710 {
711
712 /* From the ARB_multi_draw_indirect specification:
713 * "INVALID_VALUE is generated by MultiDrawArraysIndirect or
714 * MultiDrawElementsIndirect if <primcount> is negative."
715 *
716 * "<primcount> must be positive, otherwise an INVALID_VALUE error will
717 * be generated."
718 */
719 if (primcount < 0) {
720 _mesa_error(ctx, GL_INVALID_VALUE, "%s(primcount < 0)", name);
721 return GL_FALSE;
722 }
723
724
725 /* From the ARB_multi_draw_indirect specification:
726 * "<stride> must be a multiple of four, otherwise an INVALID_VALUE
727 * error is generated."
728 */
729 if (stride % 4) {
730 _mesa_error(ctx, GL_INVALID_VALUE, "%s(stride %% 4)", name);
731 return GL_FALSE;
732 }
733
734 return GL_TRUE;
735 }
736
737 static GLboolean
_mesa_validate_DrawArraysIndirect(struct gl_context * ctx,GLenum mode,const GLvoid * indirect)738 _mesa_validate_DrawArraysIndirect(struct gl_context *ctx,
739 GLenum mode,
740 const GLvoid *indirect)
741 {
742 const unsigned drawArraysNumParams = 4;
743 GLenum error =
744 valid_draw_indirect(ctx, mode, indirect,
745 drawArraysNumParams * sizeof(GLuint));
746
747 if (error)
748 _mesa_error(ctx, error, "glDrawArraysIndirect");
749
750 return !error;
751 }
752
753 static GLboolean
_mesa_validate_DrawElementsIndirect(struct gl_context * ctx,GLenum mode,GLenum type,const GLvoid * indirect)754 _mesa_validate_DrawElementsIndirect(struct gl_context *ctx,
755 GLenum mode, GLenum type,
756 const GLvoid *indirect)
757 {
758 const unsigned drawElementsNumParams = 5;
759 GLenum error = valid_draw_indirect_elements(ctx, mode, type, indirect,
760 drawElementsNumParams *
761 sizeof(GLuint));
762 if (error)
763 _mesa_error(ctx, error, "glDrawElementsIndirect");
764
765 return !error;
766 }
767
768 static GLboolean
_mesa_validate_MultiDrawArraysIndirect(struct gl_context * ctx,GLenum mode,const GLvoid * indirect,GLsizei primcount,GLsizei stride)769 _mesa_validate_MultiDrawArraysIndirect(struct gl_context *ctx,
770 GLenum mode,
771 const GLvoid *indirect,
772 GLsizei primcount, GLsizei stride)
773 {
774 GLsizeiptr size = 0;
775 const unsigned drawArraysNumParams = 4;
776
777 /* caller has converted stride==0 to drawArraysNumParams * sizeof(GLuint) */
778 assert(stride != 0);
779
780 if (!_mesa_valid_draw_indirect_multi(ctx, primcount, stride,
781 "glMultiDrawArraysIndirect"))
782 return GL_FALSE;
783
784 /* number of bytes of the indirect buffer which will be read */
785 size = primcount
786 ? (primcount - 1) * stride + drawArraysNumParams * sizeof(GLuint)
787 : 0;
788
789 GLenum error = valid_draw_indirect(ctx, mode, indirect, size);
790 if (error)
791 _mesa_error(ctx, error, "glMultiDrawArraysIndirect");
792
793 return !error;
794 }
795
796 static GLboolean
_mesa_validate_MultiDrawElementsIndirect(struct gl_context * ctx,GLenum mode,GLenum type,const GLvoid * indirect,GLsizei primcount,GLsizei stride)797 _mesa_validate_MultiDrawElementsIndirect(struct gl_context *ctx,
798 GLenum mode, GLenum type,
799 const GLvoid *indirect,
800 GLsizei primcount, GLsizei stride)
801 {
802 GLsizeiptr size = 0;
803 const unsigned drawElementsNumParams = 5;
804
805 /* caller has converted stride==0 to drawElementsNumParams * sizeof(GLuint) */
806 assert(stride != 0);
807
808 if (!_mesa_valid_draw_indirect_multi(ctx, primcount, stride,
809 "glMultiDrawElementsIndirect"))
810 return GL_FALSE;
811
812 /* number of bytes of the indirect buffer which will be read */
813 size = primcount
814 ? (primcount - 1) * stride + drawElementsNumParams * sizeof(GLuint)
815 : 0;
816
817 GLenum error = valid_draw_indirect_elements(ctx, mode, type, indirect,
818 size);
819 if (error)
820 _mesa_error(ctx, error, "glMultiDrawElementsIndirect");
821
822 return !error;
823 }
824
825 static GLenum
valid_draw_indirect_parameters(struct gl_context * ctx,GLintptr drawcount)826 valid_draw_indirect_parameters(struct gl_context *ctx,
827 GLintptr drawcount)
828 {
829 /* From the ARB_indirect_parameters specification:
830 * "INVALID_VALUE is generated by MultiDrawArraysIndirectCountARB or
831 * MultiDrawElementsIndirectCountARB if <drawcount> is not a multiple of
832 * four."
833 */
834 if (drawcount & 3)
835 return GL_INVALID_VALUE;
836
837 /* From the ARB_indirect_parameters specification:
838 * "INVALID_OPERATION is generated by MultiDrawArraysIndirectCountARB or
839 * MultiDrawElementsIndirectCountARB if no buffer is bound to the
840 * PARAMETER_BUFFER_ARB binding point."
841 */
842 if (!ctx->ParameterBuffer)
843 return GL_INVALID_OPERATION;
844
845 if (_mesa_check_disallowed_mapping(ctx->ParameterBuffer))
846 return GL_INVALID_OPERATION;
847
848 /* From the ARB_indirect_parameters specification:
849 * "INVALID_OPERATION is generated by MultiDrawArraysIndirectCountARB or
850 * MultiDrawElementsIndirectCountARB if reading a <sizei> typed value
851 * from the buffer bound to the PARAMETER_BUFFER_ARB target at the offset
852 * specified by <drawcount> would result in an out-of-bounds access."
853 */
854 if (ctx->ParameterBuffer->Size < drawcount + sizeof(GLsizei))
855 return GL_INVALID_OPERATION;
856
857 return GL_NO_ERROR;
858 }
859
860 static GLboolean
_mesa_validate_MultiDrawArraysIndirectCount(struct gl_context * ctx,GLenum mode,GLintptr indirect,GLintptr drawcount,GLsizei maxdrawcount,GLsizei stride)861 _mesa_validate_MultiDrawArraysIndirectCount(struct gl_context *ctx,
862 GLenum mode,
863 GLintptr indirect,
864 GLintptr drawcount,
865 GLsizei maxdrawcount,
866 GLsizei stride)
867 {
868 GLsizeiptr size = 0;
869 const unsigned drawArraysNumParams = 4;
870
871 /* caller has converted stride==0 to drawArraysNumParams * sizeof(GLuint) */
872 assert(stride != 0);
873
874 if (!_mesa_valid_draw_indirect_multi(ctx, maxdrawcount, stride,
875 "glMultiDrawArraysIndirectCountARB"))
876 return GL_FALSE;
877
878 /* number of bytes of the indirect buffer which will be read */
879 size = maxdrawcount
880 ? (maxdrawcount - 1) * stride + drawArraysNumParams * sizeof(GLuint)
881 : 0;
882
883 GLenum error = valid_draw_indirect(ctx, mode, (void *)indirect, size);
884 if (!error)
885 error = valid_draw_indirect_parameters(ctx, drawcount);
886
887 if (error)
888 _mesa_error(ctx, error, "glMultiDrawArraysIndirectCountARB");
889
890 return !error;
891 }
892
893 static GLboolean
_mesa_validate_MultiDrawElementsIndirectCount(struct gl_context * ctx,GLenum mode,GLenum type,GLintptr indirect,GLintptr drawcount,GLsizei maxdrawcount,GLsizei stride)894 _mesa_validate_MultiDrawElementsIndirectCount(struct gl_context *ctx,
895 GLenum mode, GLenum type,
896 GLintptr indirect,
897 GLintptr drawcount,
898 GLsizei maxdrawcount,
899 GLsizei stride)
900 {
901 GLsizeiptr size = 0;
902 const unsigned drawElementsNumParams = 5;
903
904 /* caller has converted stride==0 to drawElementsNumParams * sizeof(GLuint) */
905 assert(stride != 0);
906
907 if (!_mesa_valid_draw_indirect_multi(ctx, maxdrawcount, stride,
908 "glMultiDrawElementsIndirectCountARB"))
909 return GL_FALSE;
910
911 /* number of bytes of the indirect buffer which will be read */
912 size = maxdrawcount
913 ? (maxdrawcount - 1) * stride + drawElementsNumParams * sizeof(GLuint)
914 : 0;
915
916 GLenum error = valid_draw_indirect_elements(ctx, mode, type,
917 (void *)indirect, size);
918 if (!error)
919 error = valid_draw_indirect_parameters(ctx, drawcount);
920
921 if (error)
922 _mesa_error(ctx, error, "glMultiDrawElementsIndirectCountARB");
923
924 return !error;
925 }
926
927
928 #define MAX_ALLOCA_PRIMS(prim) (50000 / sizeof(*prim))
929
930 /* Use calloc for large allocations and alloca for small allocations. */
931 /* We have to use a macro because alloca is local within the function. */
932 #define ALLOC_PRIMS(prim, primcount, func) do { \
933 if (unlikely(primcount > MAX_ALLOCA_PRIMS(prim))) { \
934 prim = calloc(primcount, sizeof(*prim)); \
935 if (!prim) { \
936 _mesa_error(ctx, GL_OUT_OF_MEMORY, func); \
937 return; \
938 } \
939 } else { \
940 prim = alloca(primcount * sizeof(*prim)); \
941 } \
942 } while (0)
943
944 #define FREE_PRIMS(prim, primcount) do { \
945 if (primcount > MAX_ALLOCA_PRIMS(prim)) \
946 free(prim); \
947 } while (0)
948
949
950 /**
951 * Called via Driver.DrawGallium. This is a fallback invoking Driver.Draw.
952 */
953 void
_mesa_draw_gallium_fallback(struct gl_context * ctx,struct pipe_draw_info * info,unsigned drawid_offset,const struct pipe_draw_start_count_bias * draws,unsigned num_draws)954 _mesa_draw_gallium_fallback(struct gl_context *ctx,
955 struct pipe_draw_info *info,
956 unsigned drawid_offset,
957 const struct pipe_draw_start_count_bias *draws,
958 unsigned num_draws)
959 {
960 struct _mesa_index_buffer ib;
961 unsigned index_size = info->index_size;
962 unsigned min_index = 0, max_index = ~0u;
963 bool index_bounds_valid = false;
964
965 if (!info->instance_count)
966 return;
967
968 if (index_size) {
969 if (info->index_bounds_valid) {
970 min_index = info->min_index;
971 max_index = info->max_index;
972 index_bounds_valid = true;
973 }
974 } else {
975 /* The index_bounds_valid field and min/max_index are not used for
976 * non-indexed draw calls (they are undefined), but classic drivers
977 * need the index bounds. They will be computed manually.
978 */
979 index_bounds_valid = true;
980 }
981
982 ib.index_size_shift = util_logbase2(index_size);
983
984 /* Single draw or a fallback for user indices. */
985 if (num_draws == 1) {
986 if (!draws[0].count)
987 return;
988
989 if (index_size) {
990 ib.count = draws[0].count;
991
992 if (info->has_user_indices) {
993 ib.obj = NULL;
994 ib.ptr = (const char*)info->index.user;
995 } else {
996 ib.obj = info->index.gl_bo;
997 ib.ptr = NULL;
998 }
999 }
1000
1001 struct _mesa_prim prim;
1002 prim.mode = info->mode;
1003 prim.begin = 1;
1004 prim.end = 1;
1005 prim.start = draws[0].start;
1006 prim.count = draws[0].count;
1007 prim.basevertex = index_size ? draws[0].index_bias : 0;
1008 prim.draw_id = drawid_offset;
1009
1010 if (!index_size) {
1011 min_index = draws[0].start;
1012 max_index = draws[0].start + draws[0].count - 1;
1013 }
1014
1015 st_feedback_draw_vbo(ctx, &prim, 1, index_size ? &ib : NULL,
1016 index_bounds_valid, info->primitive_restart,
1017 info->restart_index, min_index, max_index,
1018 info->instance_count, info->start_instance);
1019 return;
1020 }
1021
1022 struct _mesa_prim *prim;
1023 unsigned max_count = 0;
1024 unsigned num_prims = 0;
1025
1026 ALLOC_PRIMS(prim, num_draws, "DrawGallium");
1027
1028 min_index = ~0u;
1029 max_index = 0;
1030
1031 for (unsigned i = 0; i < num_draws; i++) {
1032 if (!draws[i].count)
1033 continue;
1034
1035 prim[num_prims].mode = info->mode;
1036 prim[num_prims].begin = 1;
1037 prim[num_prims].end = 1;
1038 prim[num_prims].start = draws[i].start;
1039 prim[num_prims].count = draws[i].count;
1040 prim[num_prims].basevertex = info->index_size ? draws[i].index_bias : 0;
1041 prim[num_prims].draw_id = drawid_offset + (info->increment_draw_id ? i : 0);
1042
1043 if (!index_size) {
1044 min_index = MIN2(min_index, draws[i].start);
1045 max_index = MAX2(max_index, draws[i].start + draws[i].count - 1);
1046 }
1047
1048 max_count = MAX2(max_count, prim[num_prims].count);
1049 num_prims++;
1050 }
1051
1052 if (info->index_size) {
1053 ib.count = max_count;
1054 ib.index_size_shift = util_logbase2(index_size);
1055
1056 if (info->has_user_indices) {
1057 ib.obj = NULL;
1058 ib.ptr = (const char*)info->index.user;
1059 } else {
1060 ib.obj = info->index.gl_bo;
1061 ib.ptr = NULL;
1062 }
1063 }
1064
1065 if (num_prims)
1066 st_feedback_draw_vbo(ctx, prim, num_prims, index_size ? &ib : NULL,
1067 index_bounds_valid, info->primitive_restart,
1068 info->restart_index, min_index, max_index,
1069 info->instance_count, info->start_instance);
1070 FREE_PRIMS(prim, num_draws);
1071 }
1072
1073
1074 /**
1075 * Called via Driver.DrawGallium. This is a fallback invoking Driver.Draw.
1076 */
1077 void
_mesa_draw_gallium_multimode_fallback(struct gl_context * ctx,struct pipe_draw_info * info,const struct pipe_draw_start_count_bias * draws,const unsigned char * mode,unsigned num_draws)1078 _mesa_draw_gallium_multimode_fallback(struct gl_context *ctx,
1079 struct pipe_draw_info *info,
1080 const struct pipe_draw_start_count_bias *draws,
1081 const unsigned char *mode,
1082 unsigned num_draws)
1083 {
1084 unsigned i, first;
1085
1086 /* Find consecutive draws where mode doesn't vary. */
1087 for (i = 0, first = 0; i <= num_draws; i++) {
1088 if (i == num_draws || mode[i] != mode[first]) {
1089 info->mode = mode[first];
1090 ctx->Driver.DrawGallium(ctx, info, 0, &draws[first], i - first);
1091 first = i;
1092 }
1093 }
1094 }
1095
1096 /**
1097 * Check that element 'j' of the array has reasonable data.
1098 * Map VBO if needed.
1099 * For debugging purposes; not normally used.
1100 */
1101 static void
check_array_data(struct gl_context * ctx,struct gl_vertex_array_object * vao,GLuint attrib,GLuint j)1102 check_array_data(struct gl_context *ctx, struct gl_vertex_array_object *vao,
1103 GLuint attrib, GLuint j)
1104 {
1105 const struct gl_array_attributes *array = &vao->VertexAttrib[attrib];
1106 if (vao->Enabled & VERT_BIT(attrib)) {
1107 const struct gl_vertex_buffer_binding *binding =
1108 &vao->BufferBinding[array->BufferBindingIndex];
1109 struct gl_buffer_object *bo = binding->BufferObj;
1110 const void *data = array->Ptr;
1111 if (bo) {
1112 data = ADD_POINTERS(_mesa_vertex_attrib_address(array, binding),
1113 bo->Mappings[MAP_INTERNAL].Pointer);
1114 }
1115 switch (array->Format.Type) {
1116 case GL_FLOAT:
1117 {
1118 GLfloat *f = (GLfloat *) ((GLubyte *) data + binding->Stride * j);
1119 GLint k;
1120 for (k = 0; k < array->Format.Size; k++) {
1121 if (util_is_inf_or_nan(f[k]) || f[k] >= 1.0e20F || f[k] <= -1.0e10F) {
1122 printf("Bad array data:\n");
1123 printf(" Element[%u].%u = %f\n", j, k, f[k]);
1124 printf(" Array %u at %p\n", attrib, (void *) array);
1125 printf(" Type 0x%x, Size %d, Stride %d\n",
1126 array->Format.Type, array->Format.Size,
1127 binding->Stride);
1128 printf(" Address/offset %p in Buffer Object %u\n",
1129 array->Ptr, bo ? bo->Name : 0);
1130 f[k] = 1.0F; /* XXX replace the bad value! */
1131 }
1132 /*assert(!util_is_inf_or_nan(f[k])); */
1133 }
1134 }
1135 break;
1136 default:
1137 ;
1138 }
1139 }
1140 }
1141
1142
1143 static inline unsigned
get_index_size_shift(GLenum type)1144 get_index_size_shift(GLenum type)
1145 {
1146 /* The type is already validated, so use a fast conversion.
1147 *
1148 * GL_UNSIGNED_BYTE - GL_UNSIGNED_BYTE = 0
1149 * GL_UNSIGNED_SHORT - GL_UNSIGNED_BYTE = 2
1150 * GL_UNSIGNED_INT - GL_UNSIGNED_BYTE = 4
1151 *
1152 * Divide by 2 to get 0,1,2.
1153 */
1154 return (type - GL_UNSIGNED_BYTE) >> 1;
1155 }
1156
1157 /**
1158 * Examine the array's data for NaNs, etc.
1159 * For debug purposes; not normally used.
1160 */
1161 static void
check_draw_elements_data(struct gl_context * ctx,GLsizei count,GLenum elemType,const void * elements,GLint basevertex)1162 check_draw_elements_data(struct gl_context *ctx, GLsizei count,
1163 GLenum elemType, const void *elements,
1164 GLint basevertex)
1165 {
1166 struct gl_vertex_array_object *vao = ctx->Array.VAO;
1167 GLint i;
1168 GLuint k;
1169
1170 _mesa_vao_map(ctx, vao, GL_MAP_READ_BIT);
1171
1172 if (vao->IndexBufferObj)
1173 elements =
1174 ADD_POINTERS(vao->IndexBufferObj->Mappings[MAP_INTERNAL].Pointer, elements);
1175
1176 for (i = 0; i < count; i++) {
1177 GLuint j;
1178
1179 /* j = element[i] */
1180 switch (elemType) {
1181 case GL_UNSIGNED_BYTE:
1182 j = ((const GLubyte *) elements)[i];
1183 break;
1184 case GL_UNSIGNED_SHORT:
1185 j = ((const GLushort *) elements)[i];
1186 break;
1187 case GL_UNSIGNED_INT:
1188 j = ((const GLuint *) elements)[i];
1189 break;
1190 default:
1191 unreachable("Unexpected index buffer type");
1192 }
1193
1194 /* check element j of each enabled array */
1195 for (k = 0; k < VERT_ATTRIB_MAX; k++) {
1196 check_array_data(ctx, vao, k, j);
1197 }
1198 }
1199
1200 _mesa_vao_unmap(ctx, vao);
1201 }
1202
1203
1204 /**
1205 * Check array data, looking for NaNs, etc.
1206 */
1207 static void
check_draw_arrays_data(struct gl_context * ctx,GLint start,GLsizei count)1208 check_draw_arrays_data(struct gl_context *ctx, GLint start, GLsizei count)
1209 {
1210 /* TO DO */
1211 }
1212
1213
1214 /**
1215 * Print info/data for glDrawArrays(), for debugging.
1216 */
1217 static void
print_draw_arrays(struct gl_context * ctx,GLenum mode,GLint start,GLsizei count)1218 print_draw_arrays(struct gl_context *ctx,
1219 GLenum mode, GLint start, GLsizei count)
1220 {
1221 struct gl_vertex_array_object *vao = ctx->Array.VAO;
1222
1223 printf("_mesa_DrawArrays(mode 0x%x, start %d, count %d):\n",
1224 mode, start, count);
1225
1226 _mesa_vao_map_arrays(ctx, vao, GL_MAP_READ_BIT);
1227
1228 GLbitfield mask = vao->Enabled;
1229 while (mask) {
1230 const gl_vert_attrib i = u_bit_scan(&mask);
1231 const struct gl_array_attributes *array = &vao->VertexAttrib[i];
1232
1233 const struct gl_vertex_buffer_binding *binding =
1234 &vao->BufferBinding[array->BufferBindingIndex];
1235 struct gl_buffer_object *bufObj = binding->BufferObj;
1236
1237 printf("attr %s: size %d stride %d "
1238 "ptr %p Bufobj %u\n",
1239 gl_vert_attrib_name((gl_vert_attrib) i),
1240 array->Format.Size, binding->Stride,
1241 array->Ptr, bufObj ? bufObj->Name : 0);
1242
1243 if (bufObj) {
1244 GLubyte *p = bufObj->Mappings[MAP_INTERNAL].Pointer;
1245 int offset = (int) (GLintptr)
1246 _mesa_vertex_attrib_address(array, binding);
1247
1248 unsigned multiplier;
1249 switch (array->Format.Type) {
1250 case GL_DOUBLE:
1251 case GL_INT64_ARB:
1252 case GL_UNSIGNED_INT64_ARB:
1253 multiplier = 2;
1254 break;
1255 default:
1256 multiplier = 1;
1257 }
1258
1259 float *f = (float *) (p + offset);
1260 int *k = (int *) f;
1261 int i = 0;
1262 int n = (count - 1) * (binding->Stride / (4 * multiplier))
1263 + array->Format.Size;
1264 if (n > 32)
1265 n = 32;
1266 printf(" Data at offset %d:\n", offset);
1267 do {
1268 if (multiplier == 2)
1269 printf(" double[%d] = 0x%016llx %lf\n", i,
1270 ((unsigned long long *) k)[i], ((double *) f)[i]);
1271 else
1272 printf(" float[%d] = 0x%08x %f\n", i, k[i], f[i]);
1273 i++;
1274 } while (i < n);
1275 }
1276 }
1277
1278 _mesa_vao_unmap_arrays(ctx, vao);
1279 }
1280
1281
1282 /**
1283 * Helper function called by the other DrawArrays() functions below.
1284 * This is where we handle primitive restart for drawing non-indexed
1285 * arrays. If primitive restart is enabled, it typically means
1286 * splitting one DrawArrays() into two.
1287 */
1288 static void
_mesa_draw_arrays(struct gl_context * ctx,GLenum mode,GLint start,GLsizei count,GLuint numInstances,GLuint baseInstance)1289 _mesa_draw_arrays(struct gl_context *ctx, GLenum mode, GLint start,
1290 GLsizei count, GLuint numInstances, GLuint baseInstance)
1291 {
1292 /* Viewperf has many draws with count=0. Discarding them is faster than
1293 * processing them.
1294 */
1295 if (!count || !numInstances)
1296 return;
1297
1298 /* OpenGL 4.5 says that primitive restart is ignored with non-indexed
1299 * draws.
1300 */
1301 struct pipe_draw_info info;
1302 struct pipe_draw_start_count_bias draw;
1303
1304 info.mode = mode;
1305 info.index_size = 0;
1306 /* Packed section begin. */
1307 info.primitive_restart = false;
1308 info.has_user_indices = false;
1309 info.index_bounds_valid = true;
1310 info.increment_draw_id = false;
1311 info.was_line_loop = false;
1312 info.take_index_buffer_ownership = false;
1313 info.index_bias_varies = false;
1314 /* Packed section end. */
1315 info.start_instance = baseInstance;
1316 info.instance_count = numInstances;
1317 info.view_mask = 0;
1318 info.min_index = start;
1319 info.max_index = start + count - 1;
1320
1321 draw.start = start;
1322 draw.count = count;
1323
1324 ctx->Driver.DrawGallium(ctx, &info, 0, &draw, 1);
1325
1326 if (MESA_DEBUG_FLAGS & DEBUG_ALWAYS_FLUSH) {
1327 _mesa_flush(ctx);
1328 }
1329 }
1330
1331
1332 /**
1333 * Execute a glRectf() function.
1334 */
1335 void GLAPIENTRY
_mesa_Rectf(GLfloat x1,GLfloat y1,GLfloat x2,GLfloat y2)1336 _mesa_Rectf(GLfloat x1, GLfloat y1, GLfloat x2, GLfloat y2)
1337 {
1338 GET_CURRENT_CONTEXT(ctx);
1339 ASSERT_OUTSIDE_BEGIN_END(ctx);
1340
1341 CALL_Begin(ctx->CurrentServerDispatch, (GL_QUADS));
1342 /* Begin can change CurrentServerDispatch. */
1343 struct _glapi_table *dispatch = ctx->CurrentServerDispatch;
1344 CALL_Vertex2f(dispatch, (x1, y1));
1345 CALL_Vertex2f(dispatch, (x2, y1));
1346 CALL_Vertex2f(dispatch, (x2, y2));
1347 CALL_Vertex2f(dispatch, (x1, y2));
1348 CALL_End(dispatch, ());
1349 }
1350
1351
1352 void GLAPIENTRY
_mesa_Rectd(GLdouble x1,GLdouble y1,GLdouble x2,GLdouble y2)1353 _mesa_Rectd(GLdouble x1, GLdouble y1, GLdouble x2, GLdouble y2)
1354 {
1355 _mesa_Rectf((GLfloat) x1, (GLfloat) y1, (GLfloat) x2, (GLfloat) y2);
1356 }
1357
1358 void GLAPIENTRY
_mesa_Rectdv(const GLdouble * v1,const GLdouble * v2)1359 _mesa_Rectdv(const GLdouble *v1, const GLdouble *v2)
1360 {
1361 _mesa_Rectf((GLfloat) v1[0], (GLfloat) v1[1], (GLfloat) v2[0], (GLfloat) v2[1]);
1362 }
1363
1364 void GLAPIENTRY
_mesa_Rectfv(const GLfloat * v1,const GLfloat * v2)1365 _mesa_Rectfv(const GLfloat *v1, const GLfloat *v2)
1366 {
1367 _mesa_Rectf(v1[0], v1[1], v2[0], v2[1]);
1368 }
1369
1370 void GLAPIENTRY
_mesa_Recti(GLint x1,GLint y1,GLint x2,GLint y2)1371 _mesa_Recti(GLint x1, GLint y1, GLint x2, GLint y2)
1372 {
1373 _mesa_Rectf((GLfloat) x1, (GLfloat) y1, (GLfloat) x2, (GLfloat) y2);
1374 }
1375
1376 void GLAPIENTRY
_mesa_Rectiv(const GLint * v1,const GLint * v2)1377 _mesa_Rectiv(const GLint *v1, const GLint *v2)
1378 {
1379 _mesa_Rectf((GLfloat) v1[0], (GLfloat) v1[1], (GLfloat) v2[0], (GLfloat) v2[1]);
1380 }
1381
1382 void GLAPIENTRY
_mesa_Rects(GLshort x1,GLshort y1,GLshort x2,GLshort y2)1383 _mesa_Rects(GLshort x1, GLshort y1, GLshort x2, GLshort y2)
1384 {
1385 _mesa_Rectf((GLfloat) x1, (GLfloat) y1, (GLfloat) x2, (GLfloat) y2);
1386 }
1387
1388 void GLAPIENTRY
_mesa_Rectsv(const GLshort * v1,const GLshort * v2)1389 _mesa_Rectsv(const GLshort *v1, const GLshort *v2)
1390 {
1391 _mesa_Rectf((GLfloat) v1[0], (GLfloat) v1[1], (GLfloat) v2[0], (GLfloat) v2[1]);
1392 }
1393
1394
1395 void GLAPIENTRY
_mesa_EvalMesh1(GLenum mode,GLint i1,GLint i2)1396 _mesa_EvalMesh1(GLenum mode, GLint i1, GLint i2)
1397 {
1398 GET_CURRENT_CONTEXT(ctx);
1399 GLint i;
1400 GLfloat u, du;
1401 GLenum prim;
1402
1403 switch (mode) {
1404 case GL_POINT:
1405 prim = GL_POINTS;
1406 break;
1407 case GL_LINE:
1408 prim = GL_LINE_STRIP;
1409 break;
1410 default:
1411 _mesa_error(ctx, GL_INVALID_ENUM, "glEvalMesh1(mode)");
1412 return;
1413 }
1414
1415 /* No effect if vertex maps disabled.
1416 */
1417 if (!ctx->Eval.Map1Vertex4 && !ctx->Eval.Map1Vertex3)
1418 return;
1419
1420 du = ctx->Eval.MapGrid1du;
1421 u = ctx->Eval.MapGrid1u1 + i1 * du;
1422
1423
1424 CALL_Begin(ctx->CurrentServerDispatch, (prim));
1425 /* Begin can change CurrentServerDispatch. */
1426 struct _glapi_table *dispatch = ctx->CurrentServerDispatch;
1427 for (i = i1; i <= i2; i++, u += du) {
1428 CALL_EvalCoord1f(dispatch, (u));
1429 }
1430 CALL_End(dispatch, ());
1431 }
1432
1433
1434 void GLAPIENTRY
_mesa_EvalMesh2(GLenum mode,GLint i1,GLint i2,GLint j1,GLint j2)1435 _mesa_EvalMesh2(GLenum mode, GLint i1, GLint i2, GLint j1, GLint j2)
1436 {
1437 GET_CURRENT_CONTEXT(ctx);
1438 GLfloat u, du, v, dv, v1, u1;
1439 GLint i, j;
1440
1441 switch (mode) {
1442 case GL_POINT:
1443 case GL_LINE:
1444 case GL_FILL:
1445 break;
1446 default:
1447 _mesa_error(ctx, GL_INVALID_ENUM, "glEvalMesh2(mode)");
1448 return;
1449 }
1450
1451 /* No effect if vertex maps disabled.
1452 */
1453 if (!ctx->Eval.Map2Vertex4 && !ctx->Eval.Map2Vertex3)
1454 return;
1455
1456 du = ctx->Eval.MapGrid2du;
1457 dv = ctx->Eval.MapGrid2dv;
1458 v1 = ctx->Eval.MapGrid2v1 + j1 * dv;
1459 u1 = ctx->Eval.MapGrid2u1 + i1 * du;
1460
1461 struct _glapi_table *dispatch;
1462
1463 switch (mode) {
1464 case GL_POINT:
1465 CALL_Begin(ctx->CurrentServerDispatch, (GL_POINTS));
1466 /* Begin can change CurrentServerDispatch. */
1467 dispatch = ctx->CurrentServerDispatch;
1468 for (v = v1, j = j1; j <= j2; j++, v += dv) {
1469 for (u = u1, i = i1; i <= i2; i++, u += du) {
1470 CALL_EvalCoord2f(dispatch, (u, v));
1471 }
1472 }
1473 CALL_End(dispatch, ());
1474 break;
1475 case GL_LINE:
1476 for (v = v1, j = j1; j <= j2; j++, v += dv) {
1477 CALL_Begin(ctx->CurrentServerDispatch, (GL_LINE_STRIP));
1478 /* Begin can change CurrentServerDispatch. */
1479 dispatch = ctx->CurrentServerDispatch;
1480 for (u = u1, i = i1; i <= i2; i++, u += du) {
1481 CALL_EvalCoord2f(dispatch, (u, v));
1482 }
1483 CALL_End(dispatch, ());
1484 }
1485 for (u = u1, i = i1; i <= i2; i++, u += du) {
1486 CALL_Begin(ctx->CurrentServerDispatch, (GL_LINE_STRIP));
1487 /* Begin can change CurrentServerDispatch. */
1488 dispatch = ctx->CurrentServerDispatch;
1489 for (v = v1, j = j1; j <= j2; j++, v += dv) {
1490 CALL_EvalCoord2f(dispatch, (u, v));
1491 }
1492 CALL_End(dispatch, ());
1493 }
1494 break;
1495 case GL_FILL:
1496 for (v = v1, j = j1; j < j2; j++, v += dv) {
1497 CALL_Begin(ctx->CurrentServerDispatch, (GL_TRIANGLE_STRIP));
1498 /* Begin can change CurrentServerDispatch. */
1499 dispatch = ctx->CurrentServerDispatch;
1500 for (u = u1, i = i1; i <= i2; i++, u += du) {
1501 CALL_EvalCoord2f(dispatch, (u, v));
1502 CALL_EvalCoord2f(dispatch, (u, v + dv));
1503 }
1504 CALL_End(dispatch, ());
1505 }
1506 break;
1507 }
1508 }
1509
1510
1511 /**
1512 * Called from glDrawArrays when in immediate mode (not display list mode).
1513 */
1514 void GLAPIENTRY
_mesa_DrawArrays(GLenum mode,GLint start,GLsizei count)1515 _mesa_DrawArrays(GLenum mode, GLint start, GLsizei count)
1516 {
1517 GET_CURRENT_CONTEXT(ctx);
1518 FLUSH_FOR_DRAW(ctx);
1519
1520 _mesa_set_draw_vao(ctx, ctx->Array.VAO,
1521 ctx->VertexProgram._VPModeInputFilter);
1522
1523 if (ctx->NewState)
1524 _mesa_update_state(ctx);
1525
1526 if (!_mesa_is_no_error_enabled(ctx) &&
1527 !_mesa_validate_DrawArrays(ctx, mode, count))
1528 return;
1529
1530 if (0)
1531 check_draw_arrays_data(ctx, start, count);
1532
1533 _mesa_draw_arrays(ctx, mode, start, count, 1, 0);
1534
1535 if (0)
1536 print_draw_arrays(ctx, mode, start, count);
1537 }
1538
1539
1540 /**
1541 * Called from glDrawArraysInstanced when in immediate mode (not
1542 * display list mode).
1543 */
1544 void GLAPIENTRY
_mesa_DrawArraysInstancedARB(GLenum mode,GLint start,GLsizei count,GLsizei numInstances)1545 _mesa_DrawArraysInstancedARB(GLenum mode, GLint start, GLsizei count,
1546 GLsizei numInstances)
1547 {
1548 GET_CURRENT_CONTEXT(ctx);
1549 FLUSH_FOR_DRAW(ctx);
1550
1551 _mesa_set_draw_vao(ctx, ctx->Array.VAO,
1552 ctx->VertexProgram._VPModeInputFilter);
1553
1554 if (ctx->NewState)
1555 _mesa_update_state(ctx);
1556
1557 if (!_mesa_is_no_error_enabled(ctx) &&
1558 !_mesa_validate_DrawArraysInstanced(ctx, mode, start, count,
1559 numInstances))
1560 return;
1561
1562 if (0)
1563 check_draw_arrays_data(ctx, start, count);
1564
1565 _mesa_draw_arrays(ctx, mode, start, count, numInstances, 0);
1566
1567 if (0)
1568 print_draw_arrays(ctx, mode, start, count);
1569 }
1570
1571
1572 /**
1573 * Called from glDrawArraysInstancedBaseInstance when in immediate mode.
1574 */
1575 void GLAPIENTRY
_mesa_DrawArraysInstancedBaseInstance(GLenum mode,GLint first,GLsizei count,GLsizei numInstances,GLuint baseInstance)1576 _mesa_DrawArraysInstancedBaseInstance(GLenum mode, GLint first,
1577 GLsizei count, GLsizei numInstances,
1578 GLuint baseInstance)
1579 {
1580 GET_CURRENT_CONTEXT(ctx);
1581 FLUSH_FOR_DRAW(ctx);
1582
1583 _mesa_set_draw_vao(ctx, ctx->Array.VAO,
1584 ctx->VertexProgram._VPModeInputFilter);
1585
1586 if (ctx->NewState)
1587 _mesa_update_state(ctx);
1588
1589 if (!_mesa_is_no_error_enabled(ctx) &&
1590 !_mesa_validate_DrawArraysInstanced(ctx, mode, first, count,
1591 numInstances))
1592 return;
1593
1594 if (0)
1595 check_draw_arrays_data(ctx, first, count);
1596
1597 _mesa_draw_arrays(ctx, mode, first, count, numInstances, baseInstance);
1598
1599 if (0)
1600 print_draw_arrays(ctx, mode, first, count);
1601 }
1602
1603
1604 /**
1605 * Called from glMultiDrawArrays when in immediate mode.
1606 */
1607 void GLAPIENTRY
_mesa_MultiDrawArrays(GLenum mode,const GLint * first,const GLsizei * count,GLsizei primcount)1608 _mesa_MultiDrawArrays(GLenum mode, const GLint *first,
1609 const GLsizei *count, GLsizei primcount)
1610 {
1611 GET_CURRENT_CONTEXT(ctx);
1612 FLUSH_FOR_DRAW(ctx);
1613
1614 _mesa_set_draw_vao(ctx, ctx->Array.VAO,
1615 ctx->VertexProgram._VPModeInputFilter);
1616
1617 if (ctx->NewState)
1618 _mesa_update_state(ctx);
1619
1620 if (!_mesa_is_no_error_enabled(ctx) &&
1621 !_mesa_validate_MultiDrawArrays(ctx, mode, count, primcount))
1622 return;
1623
1624 if (primcount == 0)
1625 return;
1626
1627 struct pipe_draw_info info;
1628 struct pipe_draw_start_count_bias *draw;
1629
1630 ALLOC_PRIMS(draw, primcount, "glMultiDrawElements");
1631
1632 info.mode = mode;
1633 info.index_size = 0;
1634 /* Packed section begin. */
1635 info.primitive_restart = false;
1636 info.has_user_indices = false;
1637 info.index_bounds_valid = false;
1638 info.increment_draw_id = primcount > 1;
1639 info.was_line_loop = false;
1640 info.take_index_buffer_ownership = false;
1641 info.index_bias_varies = false;
1642 /* Packed section end. */
1643 info.start_instance = 0;
1644 info.instance_count = 1;
1645 info.view_mask = 0;
1646
1647 for (int i = 0; i < primcount; i++) {
1648 draw[i].start = first[i];
1649 draw[i].count = count[i];
1650 }
1651
1652 ctx->Driver.DrawGallium(ctx, &info, 0, draw, primcount);
1653
1654 if (MESA_DEBUG_FLAGS & DEBUG_ALWAYS_FLUSH)
1655 _mesa_flush(ctx);
1656
1657 FREE_PRIMS(draw, primcount);
1658 }
1659
1660
1661
1662 /**
1663 * Map GL_ELEMENT_ARRAY_BUFFER and print contents.
1664 * For debugging.
1665 */
1666 #if 0
1667 static void
1668 dump_element_buffer(struct gl_context *ctx, GLenum type)
1669 {
1670 const GLvoid *map =
1671 ctx->Driver.MapBufferRange(ctx, 0,
1672 ctx->Array.VAO->IndexBufferObj->Size,
1673 GL_MAP_READ_BIT,
1674 ctx->Array.VAO->IndexBufferObj,
1675 MAP_INTERNAL);
1676 switch (type) {
1677 case GL_UNSIGNED_BYTE:
1678 {
1679 const GLubyte *us = (const GLubyte *) map;
1680 GLint i;
1681 for (i = 0; i < ctx->Array.VAO->IndexBufferObj->Size; i++) {
1682 printf("%02x ", us[i]);
1683 if (i % 32 == 31)
1684 printf("\n");
1685 }
1686 printf("\n");
1687 }
1688 break;
1689 case GL_UNSIGNED_SHORT:
1690 {
1691 const GLushort *us = (const GLushort *) map;
1692 GLint i;
1693 for (i = 0; i < ctx->Array.VAO->IndexBufferObj->Size / 2; i++) {
1694 printf("%04x ", us[i]);
1695 if (i % 16 == 15)
1696 printf("\n");
1697 }
1698 printf("\n");
1699 }
1700 break;
1701 case GL_UNSIGNED_INT:
1702 {
1703 const GLuint *us = (const GLuint *) map;
1704 GLint i;
1705 for (i = 0; i < ctx->Array.VAO->IndexBufferObj->Size / 4; i++) {
1706 printf("%08x ", us[i]);
1707 if (i % 8 == 7)
1708 printf("\n");
1709 }
1710 printf("\n");
1711 }
1712 break;
1713 default:
1714 ;
1715 }
1716
1717 ctx->Driver.UnmapBuffer(ctx, ctx->Array.VAO->IndexBufferObj, MAP_INTERNAL);
1718 }
1719 #endif
1720
1721
1722 /**
1723 * Inner support for both _mesa_DrawElements and _mesa_DrawRangeElements.
1724 * Do the rendering for a glDrawElements or glDrawRangeElements call after
1725 * we've validated buffer bounds, etc.
1726 */
1727 static void
_mesa_validated_drawrangeelements(struct gl_context * ctx,GLenum mode,bool index_bounds_valid,GLuint start,GLuint end,GLsizei count,GLenum type,const GLvoid * indices,GLint basevertex,GLuint numInstances,GLuint baseInstance)1728 _mesa_validated_drawrangeelements(struct gl_context *ctx, GLenum mode,
1729 bool index_bounds_valid,
1730 GLuint start, GLuint end,
1731 GLsizei count, GLenum type,
1732 const GLvoid * indices,
1733 GLint basevertex, GLuint numInstances,
1734 GLuint baseInstance)
1735 {
1736 /* Viewperf has many draws with count=0. Discarding them is faster than
1737 * processing them.
1738 */
1739 if (!count || !numInstances)
1740 return;
1741
1742 if (!index_bounds_valid) {
1743 assert(start == 0u);
1744 assert(end == ~0u);
1745 }
1746
1747 struct pipe_draw_info info;
1748 struct pipe_draw_start_count_bias draw;
1749 unsigned index_size_shift = get_index_size_shift(type);
1750 struct gl_buffer_object *index_bo = ctx->Array.VAO->IndexBufferObj;
1751
1752 if (index_bo && !indices_aligned(index_size_shift, indices))
1753 return;
1754
1755 info.mode = mode;
1756 info.index_size = 1 << index_size_shift;
1757 /* Packed section begin. */
1758 info.primitive_restart = ctx->Array._PrimitiveRestart[index_size_shift];
1759 info.has_user_indices = index_bo == NULL;
1760 info.index_bounds_valid = index_bounds_valid;
1761 info.increment_draw_id = false;
1762 info.was_line_loop = false;
1763 info.take_index_buffer_ownership = false;
1764 info.index_bias_varies = false;
1765 /* Packed section end. */
1766 info.start_instance = baseInstance;
1767 info.instance_count = numInstances;
1768 info.view_mask = 0;
1769 info.restart_index = ctx->Array._RestartIndex[index_size_shift];
1770
1771 if (info.has_user_indices) {
1772 info.index.user = indices;
1773 draw.start = 0;
1774 } else {
1775 uintptr_t start = (uintptr_t) indices;
1776 if (unlikely(index_bo->Size < start)) {
1777 _mesa_warning(ctx, "Invalid indices offset 0x%" PRIxPTR
1778 " (indices buffer size is %ld bytes)."
1779 " Draw skipped.", start, index_bo->Size);
1780 return;
1781 }
1782 info.index.gl_bo = index_bo;
1783 draw.start = start >> index_size_shift;
1784 }
1785 draw.index_bias = basevertex;
1786
1787 info.min_index = start;
1788 info.max_index = end;
1789 draw.count = count;
1790
1791 /* Need to give special consideration to rendering a range of
1792 * indices starting somewhere above zero. Typically the
1793 * application is issuing multiple DrawRangeElements() to draw
1794 * successive primitives layed out linearly in the vertex arrays.
1795 * Unless the vertex arrays are all in a VBO (or locked as with
1796 * CVA), the OpenGL semantics imply that we need to re-read or
1797 * re-upload the vertex data on each draw call.
1798 *
1799 * In the case of hardware tnl, we want to avoid starting the
1800 * upload at zero, as it will mean every draw call uploads an
1801 * increasing amount of not-used vertex data. Worse - in the
1802 * software tnl module, all those vertices might be transformed and
1803 * lit but never rendered.
1804 *
1805 * If we just upload or transform the vertices in start..end,
1806 * however, the indices will be incorrect.
1807 *
1808 * At this level, we don't know exactly what the requirements of
1809 * the backend are going to be, though it will likely boil down to
1810 * either:
1811 *
1812 * 1) Do nothing, everything is in a VBO and is processed once
1813 * only.
1814 *
1815 * 2) Adjust the indices and vertex arrays so that start becomes
1816 * zero.
1817 *
1818 * Rather than doing anything here, I'll provide a helper function
1819 * for the latter case elsewhere.
1820 */
1821
1822 ctx->Driver.DrawGallium(ctx, &info, 0, &draw, 1);
1823
1824 if (MESA_DEBUG_FLAGS & DEBUG_ALWAYS_FLUSH) {
1825 _mesa_flush(ctx);
1826 }
1827 }
1828
1829
1830 /**
1831 * Called by glDrawRangeElementsBaseVertex() in immediate mode.
1832 */
1833 void GLAPIENTRY
_mesa_DrawRangeElementsBaseVertex(GLenum mode,GLuint start,GLuint end,GLsizei count,GLenum type,const GLvoid * indices,GLint basevertex)1834 _mesa_DrawRangeElementsBaseVertex(GLenum mode, GLuint start, GLuint end,
1835 GLsizei count, GLenum type,
1836 const GLvoid * indices, GLint basevertex)
1837 {
1838 static GLuint warnCount = 0;
1839 bool index_bounds_valid = true;
1840
1841 /* This is only useful to catch invalid values in the "end" parameter
1842 * like ~0.
1843 */
1844 GLuint max_element = 2 * 1000 * 1000 * 1000; /* just a big number */
1845
1846 GET_CURRENT_CONTEXT(ctx);
1847 FLUSH_FOR_DRAW(ctx);
1848
1849 _mesa_set_draw_vao(ctx, ctx->Array.VAO,
1850 ctx->VertexProgram._VPModeInputFilter);
1851
1852 if (ctx->NewState)
1853 _mesa_update_state(ctx);
1854
1855 if (!_mesa_is_no_error_enabled(ctx) &&
1856 !_mesa_validate_DrawRangeElements(ctx, mode, start, end, count,
1857 type))
1858 return;
1859
1860 if ((int) end + basevertex < 0 || start + basevertex >= max_element) {
1861 /* The application requested we draw using a range of indices that's
1862 * outside the bounds of the current VBO. This is invalid and appears
1863 * to give undefined results. The safest thing to do is to simply
1864 * ignore the range, in case the application botched their range tracking
1865 * but did provide valid indices. Also issue a warning indicating that
1866 * the application is broken.
1867 */
1868 if (warnCount++ < 10) {
1869 _mesa_warning(ctx, "glDrawRangeElements(start %u, end %u, "
1870 "basevertex %d, count %d, type 0x%x, indices=%p):\n"
1871 "\trange is outside VBO bounds (max=%u); ignoring.\n"
1872 "\tThis should be fixed in the application.",
1873 start, end, basevertex, count, type, indices,
1874 max_element - 1);
1875 }
1876 index_bounds_valid = false;
1877 }
1878
1879 /* NOTE: It's important that 'end' is a reasonable value.
1880 * in _tnl_draw_prims(), we use end to determine how many vertices
1881 * to transform. If it's too large, we can unnecessarily split prims
1882 * or we can read/write out of memory in several different places!
1883 */
1884
1885 /* Catch/fix some potential user errors */
1886 if (type == GL_UNSIGNED_BYTE) {
1887 start = MIN2(start, 0xff);
1888 end = MIN2(end, 0xff);
1889 }
1890 else if (type == GL_UNSIGNED_SHORT) {
1891 start = MIN2(start, 0xffff);
1892 end = MIN2(end, 0xffff);
1893 }
1894
1895 if (0) {
1896 printf("glDraw[Range]Elements{,BaseVertex}"
1897 "(start %u, end %u, type 0x%x, count %d) ElemBuf %u, "
1898 "base %d\n",
1899 start, end, type, count,
1900 ctx->Array.VAO->IndexBufferObj ?
1901 ctx->Array.VAO->IndexBufferObj->Name : 0, basevertex);
1902 }
1903
1904 if ((int) start + basevertex < 0 || end + basevertex >= max_element)
1905 index_bounds_valid = false;
1906
1907 #if 0
1908 check_draw_elements_data(ctx, count, type, indices, basevertex);
1909 #else
1910 (void) check_draw_elements_data;
1911 #endif
1912
1913 if (!index_bounds_valid) {
1914 start = 0;
1915 end = ~0;
1916 }
1917
1918 _mesa_validated_drawrangeelements(ctx, mode, index_bounds_valid, start, end,
1919 count, type, indices, basevertex, 1, 0);
1920 }
1921
1922
1923 /**
1924 * Called by glDrawRangeElements() in immediate mode.
1925 */
1926 void GLAPIENTRY
_mesa_DrawRangeElements(GLenum mode,GLuint start,GLuint end,GLsizei count,GLenum type,const GLvoid * indices)1927 _mesa_DrawRangeElements(GLenum mode, GLuint start, GLuint end,
1928 GLsizei count, GLenum type, const GLvoid * indices)
1929 {
1930 _mesa_DrawRangeElementsBaseVertex(mode, start, end, count, type,
1931 indices, 0);
1932 }
1933
1934
1935 /**
1936 * Called by glDrawElements() in immediate mode.
1937 */
1938 void GLAPIENTRY
_mesa_DrawElements(GLenum mode,GLsizei count,GLenum type,const GLvoid * indices)1939 _mesa_DrawElements(GLenum mode, GLsizei count, GLenum type,
1940 const GLvoid * indices)
1941 {
1942 GET_CURRENT_CONTEXT(ctx);
1943 FLUSH_FOR_DRAW(ctx);
1944
1945 _mesa_set_draw_vao(ctx, ctx->Array.VAO,
1946 ctx->VertexProgram._VPModeInputFilter);
1947
1948 if (ctx->NewState)
1949 _mesa_update_state(ctx);
1950
1951 if (!_mesa_is_no_error_enabled(ctx) &&
1952 !_mesa_validate_DrawElements(ctx, mode, count, type))
1953 return;
1954
1955 _mesa_validated_drawrangeelements(ctx, mode, false, 0, ~0,
1956 count, type, indices, 0, 1, 0);
1957 }
1958
1959
1960 /**
1961 * Called by glDrawElementsBaseVertex() in immediate mode.
1962 */
1963 void GLAPIENTRY
_mesa_DrawElementsBaseVertex(GLenum mode,GLsizei count,GLenum type,const GLvoid * indices,GLint basevertex)1964 _mesa_DrawElementsBaseVertex(GLenum mode, GLsizei count, GLenum type,
1965 const GLvoid * indices, GLint basevertex)
1966 {
1967 GET_CURRENT_CONTEXT(ctx);
1968 FLUSH_FOR_DRAW(ctx);
1969
1970 _mesa_set_draw_vao(ctx, ctx->Array.VAO,
1971 ctx->VertexProgram._VPModeInputFilter);
1972
1973 if (ctx->NewState)
1974 _mesa_update_state(ctx);
1975
1976 if (!_mesa_is_no_error_enabled(ctx) &&
1977 !_mesa_validate_DrawElements(ctx, mode, count, type))
1978 return;
1979
1980 _mesa_validated_drawrangeelements(ctx, mode, false, 0, ~0,
1981 count, type, indices, basevertex, 1, 0);
1982 }
1983
1984
1985 /**
1986 * Called by glDrawElementsInstanced() in immediate mode.
1987 */
1988 void GLAPIENTRY
_mesa_DrawElementsInstancedARB(GLenum mode,GLsizei count,GLenum type,const GLvoid * indices,GLsizei numInstances)1989 _mesa_DrawElementsInstancedARB(GLenum mode, GLsizei count, GLenum type,
1990 const GLvoid * indices, GLsizei numInstances)
1991 {
1992 GET_CURRENT_CONTEXT(ctx);
1993 FLUSH_FOR_DRAW(ctx);
1994
1995 _mesa_set_draw_vao(ctx, ctx->Array.VAO,
1996 ctx->VertexProgram._VPModeInputFilter);
1997
1998 if (ctx->NewState)
1999 _mesa_update_state(ctx);
2000
2001 if (!_mesa_is_no_error_enabled(ctx) &&
2002 !_mesa_validate_DrawElementsInstanced(ctx, mode, count, type,
2003 numInstances))
2004 return;
2005
2006 _mesa_validated_drawrangeelements(ctx, mode, false, 0, ~0,
2007 count, type, indices, 0, numInstances, 0);
2008 }
2009
2010
2011 /**
2012 * Called by glDrawElementsInstancedBaseVertex() in immediate mode.
2013 */
2014 void GLAPIENTRY
_mesa_DrawElementsInstancedBaseVertex(GLenum mode,GLsizei count,GLenum type,const GLvoid * indices,GLsizei numInstances,GLint basevertex)2015 _mesa_DrawElementsInstancedBaseVertex(GLenum mode, GLsizei count,
2016 GLenum type, const GLvoid * indices,
2017 GLsizei numInstances,
2018 GLint basevertex)
2019 {
2020 GET_CURRENT_CONTEXT(ctx);
2021 FLUSH_FOR_DRAW(ctx);
2022
2023 _mesa_set_draw_vao(ctx, ctx->Array.VAO,
2024 ctx->VertexProgram._VPModeInputFilter);
2025
2026 if (ctx->NewState)
2027 _mesa_update_state(ctx);
2028
2029 if (!_mesa_is_no_error_enabled(ctx) &&
2030 !_mesa_validate_DrawElementsInstanced(ctx, mode, count, type,
2031 numInstances))
2032 return;
2033
2034 _mesa_validated_drawrangeelements(ctx, mode, false, 0, ~0,
2035 count, type, indices,
2036 basevertex, numInstances, 0);
2037 }
2038
2039
2040 /**
2041 * Called by glDrawElementsInstancedBaseInstance() in immediate mode.
2042 */
2043 void GLAPIENTRY
_mesa_DrawElementsInstancedBaseInstance(GLenum mode,GLsizei count,GLenum type,const GLvoid * indices,GLsizei numInstances,GLuint baseInstance)2044 _mesa_DrawElementsInstancedBaseInstance(GLenum mode, GLsizei count,
2045 GLenum type,
2046 const GLvoid *indices,
2047 GLsizei numInstances,
2048 GLuint baseInstance)
2049 {
2050 GET_CURRENT_CONTEXT(ctx);
2051 FLUSH_FOR_DRAW(ctx);
2052
2053 _mesa_set_draw_vao(ctx, ctx->Array.VAO,
2054 ctx->VertexProgram._VPModeInputFilter);
2055
2056 if (ctx->NewState)
2057 _mesa_update_state(ctx);
2058
2059 if (!_mesa_is_no_error_enabled(ctx) &&
2060 !_mesa_validate_DrawElementsInstanced(ctx, mode, count, type,
2061 numInstances))
2062 return;
2063
2064 _mesa_validated_drawrangeelements(ctx, mode, false, 0, ~0,
2065 count, type, indices, 0, numInstances,
2066 baseInstance);
2067 }
2068
2069
2070 /**
2071 * Called by glDrawElementsInstancedBaseVertexBaseInstance() in immediate mode.
2072 */
2073 void GLAPIENTRY
_mesa_DrawElementsInstancedBaseVertexBaseInstance(GLenum mode,GLsizei count,GLenum type,const GLvoid * indices,GLsizei numInstances,GLint basevertex,GLuint baseInstance)2074 _mesa_DrawElementsInstancedBaseVertexBaseInstance(GLenum mode,
2075 GLsizei count,
2076 GLenum type,
2077 const GLvoid *indices,
2078 GLsizei numInstances,
2079 GLint basevertex,
2080 GLuint baseInstance)
2081 {
2082 GET_CURRENT_CONTEXT(ctx);
2083 FLUSH_FOR_DRAW(ctx);
2084
2085 _mesa_set_draw_vao(ctx, ctx->Array.VAO,
2086 ctx->VertexProgram._VPModeInputFilter);
2087
2088 if (ctx->NewState)
2089 _mesa_update_state(ctx);
2090
2091 if (!_mesa_is_no_error_enabled(ctx) &&
2092 !_mesa_validate_DrawElementsInstanced(ctx, mode, count, type,
2093 numInstances))
2094 return;
2095
2096 _mesa_validated_drawrangeelements(ctx, mode, false, 0, ~0,
2097 count, type, indices, basevertex,
2098 numInstances, baseInstance);
2099 }
2100
2101
2102 /**
2103 * Inner support for both _mesa_MultiDrawElements() and
2104 * _mesa_MultiDrawRangeElements().
2105 * This does the actual rendering after we've checked array indexes, etc.
2106 */
2107 static void
_mesa_validated_multidrawelements(struct gl_context * ctx,GLenum mode,const GLsizei * count,GLenum type,const GLvoid * const * indices,GLsizei primcount,const GLint * basevertex)2108 _mesa_validated_multidrawelements(struct gl_context *ctx, GLenum mode,
2109 const GLsizei *count, GLenum type,
2110 const GLvoid * const *indices,
2111 GLsizei primcount, const GLint *basevertex)
2112 {
2113 uintptr_t min_index_ptr, max_index_ptr;
2114 bool fallback = false;
2115 int i;
2116
2117 if (primcount == 0)
2118 return;
2119
2120 unsigned index_size_shift = get_index_size_shift(type);
2121
2122 min_index_ptr = (uintptr_t) indices[0];
2123 max_index_ptr = 0;
2124 for (i = 0; i < primcount; i++) {
2125 min_index_ptr = MIN2(min_index_ptr, (uintptr_t) indices[i]);
2126 max_index_ptr = MAX2(max_index_ptr, (uintptr_t) indices[i] +
2127 (count[i] << index_size_shift));
2128 }
2129
2130 /* Check if we can handle this thing as a bunch of index offsets from the
2131 * same index pointer. If we can't, then we have to fall back to doing
2132 * a draw_prims per primitive.
2133 * Check that the difference between each prim's indexes is a multiple of
2134 * the index/element size.
2135 */
2136 if (index_size_shift) {
2137 for (i = 0; i < primcount; i++) {
2138 if ((((uintptr_t) indices[i] - min_index_ptr) &
2139 ((1 << index_size_shift) - 1)) != 0) {
2140 fallback = true;
2141 break;
2142 }
2143 }
2144 }
2145
2146 struct gl_buffer_object *index_bo = ctx->Array.VAO->IndexBufferObj;
2147 struct pipe_draw_info info;
2148
2149 info.mode = mode;
2150 info.index_size = 1 << index_size_shift;
2151 /* Packed section begin. */
2152 info.primitive_restart = ctx->Array._PrimitiveRestart[index_size_shift];
2153 info.has_user_indices = index_bo == NULL;
2154 info.index_bounds_valid = false;
2155 info.increment_draw_id = primcount > 1;
2156 info.was_line_loop = false;
2157 info.take_index_buffer_ownership = false;
2158 info.index_bias_varies = !!basevertex;
2159 /* Packed section end. */
2160 info.start_instance = 0;
2161 info.instance_count = 1;
2162 info.view_mask = 0;
2163 info.restart_index = ctx->Array._RestartIndex[index_size_shift];
2164
2165 if (info.has_user_indices)
2166 info.index.user = (void*)min_index_ptr;
2167 else
2168 info.index.gl_bo = index_bo;
2169
2170 if (!fallback &&
2171 (!info.has_user_indices ||
2172 /* "max_index_ptr - min_index_ptr >> index_size_shift" is stored
2173 * in draw[i].start. The driver will multiply it later by index_size
2174 * so make sure the final value won't overflow.
2175 *
2176 * For real index buffers, gallium doesn't support index buffer offsets
2177 * greater than UINT32_MAX bytes.
2178 */
2179 max_index_ptr - min_index_ptr <= UINT32_MAX)) {
2180 struct pipe_draw_start_count_bias *draw;
2181
2182 ALLOC_PRIMS(draw, primcount, "glMultiDrawElements");
2183
2184 if (info.has_user_indices) {
2185 for (int i = 0; i < primcount; i++) {
2186 draw[i].start =
2187 ((uintptr_t)indices[i] - min_index_ptr) >> index_size_shift;
2188 draw[i].count = count[i];
2189 draw[i].index_bias = basevertex ? basevertex[i] : 0;
2190 }
2191 } else {
2192 for (int i = 0; i < primcount; i++) {
2193 draw[i].start = (uintptr_t)indices[i] >> index_size_shift;
2194 draw[i].count =
2195 indices_aligned(index_size_shift, indices[i]) ? count[i] : 0;
2196 draw[i].index_bias = basevertex ? basevertex[i] : 0;
2197 }
2198 }
2199
2200 ctx->Driver.DrawGallium(ctx, &info, 0, draw, primcount);
2201 FREE_PRIMS(draw, primcount);
2202 } else {
2203 /* draw[i].start would overflow. Draw one at a time. */
2204 assert(info.has_user_indices);
2205 info.increment_draw_id = false;
2206
2207 for (int i = 0; i < primcount; i++) {
2208 struct pipe_draw_start_count_bias draw;
2209
2210 if (!count[i])
2211 continue;
2212
2213 /* Reset these, because the callee can change them. */
2214 info.index_bounds_valid = false;
2215 info.index.user = indices[i];
2216 draw.start = 0;
2217 draw.index_bias = basevertex ? basevertex[i] : 0;
2218 draw.count = count[i];
2219
2220 ctx->Driver.DrawGallium(ctx, &info, i, &draw, 1);
2221 }
2222 }
2223
2224 if (MESA_DEBUG_FLAGS & DEBUG_ALWAYS_FLUSH) {
2225 _mesa_flush(ctx);
2226 }
2227 }
2228
2229
2230 void GLAPIENTRY
_mesa_MultiDrawElementsEXT(GLenum mode,const GLsizei * count,GLenum type,const GLvoid * const * indices,GLsizei primcount)2231 _mesa_MultiDrawElementsEXT(GLenum mode, const GLsizei *count, GLenum type,
2232 const GLvoid * const *indices, GLsizei primcount)
2233 {
2234 GET_CURRENT_CONTEXT(ctx);
2235 FLUSH_FOR_DRAW(ctx);
2236
2237 _mesa_set_draw_vao(ctx, ctx->Array.VAO,
2238 ctx->VertexProgram._VPModeInputFilter);
2239
2240 if (ctx->NewState)
2241 _mesa_update_state(ctx);
2242
2243 if (!_mesa_is_no_error_enabled(ctx) &&
2244 !_mesa_validate_MultiDrawElements(ctx, mode, count, type, indices,
2245 primcount))
2246 return;
2247
2248 _mesa_validated_multidrawelements(ctx, mode, count, type, indices, primcount,
2249 NULL);
2250 }
2251
2252
2253 void GLAPIENTRY
_mesa_MultiDrawElementsBaseVertex(GLenum mode,const GLsizei * count,GLenum type,const GLvoid * const * indices,GLsizei primcount,const GLsizei * basevertex)2254 _mesa_MultiDrawElementsBaseVertex(GLenum mode,
2255 const GLsizei *count, GLenum type,
2256 const GLvoid * const *indices,
2257 GLsizei primcount,
2258 const GLsizei *basevertex)
2259 {
2260 GET_CURRENT_CONTEXT(ctx);
2261 FLUSH_FOR_DRAW(ctx);
2262
2263 _mesa_set_draw_vao(ctx, ctx->Array.VAO,
2264 ctx->VertexProgram._VPModeInputFilter);
2265
2266 if (ctx->NewState)
2267 _mesa_update_state(ctx);
2268
2269 if (!_mesa_is_no_error_enabled(ctx) &&
2270 !_mesa_validate_MultiDrawElements(ctx, mode, count, type, indices,
2271 primcount))
2272 return;
2273
2274 _mesa_validated_multidrawelements(ctx, mode, count, type, indices, primcount,
2275 basevertex);
2276 }
2277
2278
2279 /**
2280 * Draw a GL primitive using a vertex count obtained from transform feedback.
2281 * \param mode the type of GL primitive to draw
2282 * \param obj the transform feedback object to use
2283 * \param stream index of the transform feedback stream from which to
2284 * get the primitive count.
2285 * \param numInstances number of instances to draw
2286 */
2287 static void
_mesa_draw_transform_feedback(struct gl_context * ctx,GLenum mode,struct gl_transform_feedback_object * obj,GLuint stream,GLuint numInstances)2288 _mesa_draw_transform_feedback(struct gl_context *ctx, GLenum mode,
2289 struct gl_transform_feedback_object *obj,
2290 GLuint stream, GLuint numInstances)
2291 {
2292 FLUSH_FOR_DRAW(ctx);
2293
2294 _mesa_set_draw_vao(ctx, ctx->Array.VAO,
2295 ctx->VertexProgram._VPModeInputFilter);
2296
2297 if (ctx->NewState)
2298 _mesa_update_state(ctx);
2299
2300 if (!_mesa_is_no_error_enabled(ctx) &&
2301 !_mesa_validate_DrawTransformFeedback(ctx, mode, obj, stream,
2302 numInstances))
2303 return;
2304
2305 /* Maybe we should do some primitive splitting for primitive restart
2306 * (like in DrawArrays), but we have no way to know how many vertices
2307 * will be rendered. */
2308
2309 st_draw_transform_feedback(ctx, mode, numInstances, stream, obj);
2310
2311 if (MESA_DEBUG_FLAGS & DEBUG_ALWAYS_FLUSH) {
2312 _mesa_flush(ctx);
2313 }
2314 }
2315
2316
2317 /**
2318 * Like DrawArrays, but take the count from a transform feedback object.
2319 * \param mode GL_POINTS, GL_LINES, GL_TRIANGLE_STRIP, etc.
2320 * \param name the transform feedback object
2321 * User still has to setup of the vertex attribute info with
2322 * glVertexPointer, glColorPointer, etc.
2323 * Part of GL_ARB_transform_feedback2.
2324 */
2325 void GLAPIENTRY
_mesa_DrawTransformFeedback(GLenum mode,GLuint name)2326 _mesa_DrawTransformFeedback(GLenum mode, GLuint name)
2327 {
2328 GET_CURRENT_CONTEXT(ctx);
2329 struct gl_transform_feedback_object *obj =
2330 _mesa_lookup_transform_feedback_object(ctx, name);
2331
2332 _mesa_draw_transform_feedback(ctx, mode, obj, 0, 1);
2333 }
2334
2335
2336 void GLAPIENTRY
_mesa_DrawTransformFeedbackStream(GLenum mode,GLuint name,GLuint stream)2337 _mesa_DrawTransformFeedbackStream(GLenum mode, GLuint name, GLuint stream)
2338 {
2339 GET_CURRENT_CONTEXT(ctx);
2340 struct gl_transform_feedback_object *obj =
2341 _mesa_lookup_transform_feedback_object(ctx, name);
2342
2343 _mesa_draw_transform_feedback(ctx, mode, obj, stream, 1);
2344 }
2345
2346
2347 void GLAPIENTRY
_mesa_DrawTransformFeedbackInstanced(GLenum mode,GLuint name,GLsizei primcount)2348 _mesa_DrawTransformFeedbackInstanced(GLenum mode, GLuint name,
2349 GLsizei primcount)
2350 {
2351 GET_CURRENT_CONTEXT(ctx);
2352 struct gl_transform_feedback_object *obj =
2353 _mesa_lookup_transform_feedback_object(ctx, name);
2354
2355 _mesa_draw_transform_feedback(ctx, mode, obj, 0, primcount);
2356 }
2357
2358
2359 void GLAPIENTRY
_mesa_DrawTransformFeedbackStreamInstanced(GLenum mode,GLuint name,GLuint stream,GLsizei primcount)2360 _mesa_DrawTransformFeedbackStreamInstanced(GLenum mode, GLuint name,
2361 GLuint stream,
2362 GLsizei primcount)
2363 {
2364 GET_CURRENT_CONTEXT(ctx);
2365 struct gl_transform_feedback_object *obj =
2366 _mesa_lookup_transform_feedback_object(ctx, name);
2367
2368 _mesa_draw_transform_feedback(ctx, mode, obj, stream, primcount);
2369 }
2370
2371
2372 static void
_mesa_validated_multidrawarraysindirect(struct gl_context * ctx,GLenum mode,GLintptr indirect,GLintptr drawcount_offset,GLsizei drawcount,GLsizei stride,struct gl_buffer_object * drawcount_buffer)2373 _mesa_validated_multidrawarraysindirect(struct gl_context *ctx, GLenum mode,
2374 GLintptr indirect,
2375 GLintptr drawcount_offset,
2376 GLsizei drawcount, GLsizei stride,
2377 struct gl_buffer_object *drawcount_buffer)
2378 {
2379 /* If drawcount_buffer is set, drawcount is the maximum draw count.*/
2380 if (drawcount == 0)
2381 return;
2382
2383 st_indirect_draw_vbo(ctx, mode, ctx->DrawIndirectBuffer, indirect,
2384 drawcount, stride, drawcount_buffer,
2385 drawcount_offset, NULL, false, 0);
2386
2387 if (MESA_DEBUG_FLAGS & DEBUG_ALWAYS_FLUSH)
2388 _mesa_flush(ctx);
2389 }
2390
2391
2392 static void
_mesa_validated_multidrawelementsindirect(struct gl_context * ctx,GLenum mode,GLenum type,GLintptr indirect,GLintptr drawcount_offset,GLsizei drawcount,GLsizei stride,struct gl_buffer_object * drawcount_buffer)2393 _mesa_validated_multidrawelementsindirect(struct gl_context *ctx,
2394 GLenum mode, GLenum type,
2395 GLintptr indirect,
2396 GLintptr drawcount_offset,
2397 GLsizei drawcount, GLsizei stride,
2398 struct gl_buffer_object *drawcount_buffer)
2399 {
2400 /* If drawcount_buffer is set, drawcount is the maximum draw count.*/
2401 if (drawcount == 0)
2402 return;
2403
2404 /* NOTE: IndexBufferObj is guaranteed to be a VBO. */
2405 struct _mesa_index_buffer ib;
2406 ib.count = 0; /* unknown */
2407 ib.obj = ctx->Array.VAO->IndexBufferObj;
2408 ib.ptr = NULL;
2409 ib.index_size_shift = get_index_size_shift(type);
2410
2411 st_indirect_draw_vbo(ctx, mode, ctx->DrawIndirectBuffer, indirect,
2412 drawcount, stride, drawcount_buffer,
2413 drawcount_offset, &ib,
2414 ctx->Array._PrimitiveRestart[ib.index_size_shift],
2415 ctx->Array._RestartIndex[ib.index_size_shift]);
2416
2417 if (MESA_DEBUG_FLAGS & DEBUG_ALWAYS_FLUSH)
2418 _mesa_flush(ctx);
2419 }
2420
2421
2422 /**
2423 * Like [Multi]DrawArrays/Elements, but they take most arguments from
2424 * a buffer object.
2425 */
2426 void GLAPIENTRY
_mesa_DrawArraysIndirect(GLenum mode,const GLvoid * indirect)2427 _mesa_DrawArraysIndirect(GLenum mode, const GLvoid *indirect)
2428 {
2429 GET_CURRENT_CONTEXT(ctx);
2430
2431 /* From the ARB_draw_indirect spec:
2432 *
2433 * "Initially zero is bound to DRAW_INDIRECT_BUFFER. In the
2434 * compatibility profile, this indicates that DrawArraysIndirect and
2435 * DrawElementsIndirect are to source their arguments directly from the
2436 * pointer passed as their <indirect> parameters."
2437 */
2438 if (ctx->API == API_OPENGL_COMPAT &&
2439 !ctx->DrawIndirectBuffer) {
2440 DrawArraysIndirectCommand *cmd = (DrawArraysIndirectCommand *) indirect;
2441
2442 _mesa_DrawArraysInstancedBaseInstance(mode, cmd->first, cmd->count,
2443 cmd->primCount,
2444 cmd->baseInstance);
2445 return;
2446 }
2447
2448 FLUSH_FOR_DRAW(ctx);
2449
2450 _mesa_set_draw_vao(ctx, ctx->Array.VAO,
2451 ctx->VertexProgram._VPModeInputFilter);
2452
2453 if (ctx->NewState)
2454 _mesa_update_state(ctx);
2455
2456 if (!_mesa_is_no_error_enabled(ctx) &&
2457 !_mesa_validate_DrawArraysIndirect(ctx, mode, indirect))
2458 return;
2459
2460 _mesa_validated_multidrawarraysindirect(ctx, mode, (GLintptr)indirect,
2461 0, 1, 16, NULL);
2462 }
2463
2464
2465 void GLAPIENTRY
_mesa_DrawElementsIndirect(GLenum mode,GLenum type,const GLvoid * indirect)2466 _mesa_DrawElementsIndirect(GLenum mode, GLenum type, const GLvoid *indirect)
2467 {
2468 GET_CURRENT_CONTEXT(ctx);
2469
2470 /* From the ARB_draw_indirect spec:
2471 *
2472 * "Initially zero is bound to DRAW_INDIRECT_BUFFER. In the
2473 * compatibility profile, this indicates that DrawArraysIndirect and
2474 * DrawElementsIndirect are to source their arguments directly from the
2475 * pointer passed as their <indirect> parameters."
2476 */
2477 if (ctx->API == API_OPENGL_COMPAT &&
2478 !ctx->DrawIndirectBuffer) {
2479 /*
2480 * Unlike regular DrawElementsInstancedBaseVertex commands, the indices
2481 * may not come from a client array and must come from an index buffer.
2482 * If no element array buffer is bound, an INVALID_OPERATION error is
2483 * generated.
2484 */
2485 if (!ctx->Array.VAO->IndexBufferObj) {
2486 _mesa_error(ctx, GL_INVALID_OPERATION,
2487 "glDrawElementsIndirect(no buffer bound "
2488 "to GL_ELEMENT_ARRAY_BUFFER)");
2489 } else {
2490 DrawElementsIndirectCommand *cmd =
2491 (DrawElementsIndirectCommand *) indirect;
2492
2493 /* Convert offset to pointer */
2494 void *offset = (void *)
2495 (uintptr_t)((cmd->firstIndex * _mesa_sizeof_type(type)) & 0xffffffffUL);
2496
2497 _mesa_DrawElementsInstancedBaseVertexBaseInstance(mode, cmd->count,
2498 type, offset,
2499 cmd->primCount,
2500 cmd->baseVertex,
2501 cmd->baseInstance);
2502 }
2503
2504 return;
2505 }
2506
2507 FLUSH_FOR_DRAW(ctx);
2508
2509 _mesa_set_draw_vao(ctx, ctx->Array.VAO,
2510 ctx->VertexProgram._VPModeInputFilter);
2511
2512 if (ctx->NewState)
2513 _mesa_update_state(ctx);
2514
2515 if (!_mesa_is_no_error_enabled(ctx) &&
2516 !_mesa_validate_DrawElementsIndirect(ctx, mode, type, indirect))
2517 return;
2518
2519 _mesa_validated_multidrawelementsindirect(ctx, mode, type,
2520 (GLintptr)indirect, 0,
2521 1, 20, NULL);
2522 }
2523
2524
2525 void GLAPIENTRY
_mesa_MultiDrawArraysIndirect(GLenum mode,const GLvoid * indirect,GLsizei primcount,GLsizei stride)2526 _mesa_MultiDrawArraysIndirect(GLenum mode, const GLvoid *indirect,
2527 GLsizei primcount, GLsizei stride)
2528 {
2529 GET_CURRENT_CONTEXT(ctx);
2530
2531 /* If <stride> is zero, the array elements are treated as tightly packed. */
2532 if (stride == 0)
2533 stride = sizeof(DrawArraysIndirectCommand);
2534
2535 FLUSH_FOR_DRAW(ctx);
2536
2537 _mesa_set_draw_vao(ctx, ctx->Array.VAO,
2538 ctx->VertexProgram._VPModeInputFilter);
2539
2540 if (ctx->NewState)
2541 _mesa_update_state(ctx);
2542
2543 /* From the ARB_draw_indirect spec:
2544 *
2545 * "Initially zero is bound to DRAW_INDIRECT_BUFFER. In the
2546 * compatibility profile, this indicates that DrawArraysIndirect and
2547 * DrawElementsIndirect are to source their arguments directly from the
2548 * pointer passed as their <indirect> parameters."
2549 */
2550 if (ctx->API == API_OPENGL_COMPAT &&
2551 !ctx->DrawIndirectBuffer) {
2552
2553 if (!_mesa_is_no_error_enabled(ctx) &&
2554 (!_mesa_valid_draw_indirect_multi(ctx, primcount, stride,
2555 "glMultiDrawArraysIndirect") ||
2556 !_mesa_validate_DrawArrays(ctx, mode, 1)))
2557 return;
2558
2559 struct pipe_draw_info info;
2560 info.mode = mode;
2561 info.index_size = 0;
2562 info.view_mask = 0;
2563 /* Packed section begin. */
2564 info.primitive_restart = false;
2565 info.has_user_indices = false;
2566 info.index_bounds_valid = false;
2567 info.increment_draw_id = primcount > 1;
2568 info.was_line_loop = false;
2569 info.take_index_buffer_ownership = false;
2570 info.index_bias_varies = false;
2571 /* Packed section end. */
2572
2573 const uint8_t *ptr = (const uint8_t *) indirect;
2574 for (unsigned i = 0; i < primcount; i++) {
2575 DrawArraysIndirectCommand *cmd = (DrawArraysIndirectCommand *) ptr;
2576
2577 info.start_instance = cmd->baseInstance;
2578 info.instance_count = cmd->primCount;
2579
2580 struct pipe_draw_start_count_bias draw;
2581 draw.start = cmd->first;
2582 draw.count = cmd->count;
2583
2584 ctx->Driver.DrawGallium(ctx, &info, i, &draw, 1);
2585 ptr += stride;
2586 }
2587
2588 return;
2589 }
2590
2591 if (!_mesa_is_no_error_enabled(ctx) &&
2592 !_mesa_validate_MultiDrawArraysIndirect(ctx, mode, indirect,
2593 primcount, stride))
2594 return;
2595
2596 _mesa_validated_multidrawarraysindirect(ctx, mode, (GLintptr)indirect, 0,
2597 primcount, stride, NULL);
2598 }
2599
2600
2601 void GLAPIENTRY
_mesa_MultiDrawElementsIndirect(GLenum mode,GLenum type,const GLvoid * indirect,GLsizei primcount,GLsizei stride)2602 _mesa_MultiDrawElementsIndirect(GLenum mode, GLenum type,
2603 const GLvoid *indirect,
2604 GLsizei primcount, GLsizei stride)
2605 {
2606 GET_CURRENT_CONTEXT(ctx);
2607
2608 FLUSH_FOR_DRAW(ctx);
2609
2610 _mesa_set_draw_vao(ctx, ctx->Array.VAO,
2611 ctx->VertexProgram._VPModeInputFilter);
2612
2613 if (ctx->NewState)
2614 _mesa_update_state(ctx);
2615
2616 /* If <stride> is zero, the array elements are treated as tightly packed. */
2617 if (stride == 0)
2618 stride = sizeof(DrawElementsIndirectCommand);
2619
2620 /* From the ARB_draw_indirect spec:
2621 *
2622 * "Initially zero is bound to DRAW_INDIRECT_BUFFER. In the
2623 * compatibility profile, this indicates that DrawArraysIndirect and
2624 * DrawElementsIndirect are to source their arguments directly from the
2625 * pointer passed as their <indirect> parameters."
2626 */
2627 if (ctx->API == API_OPENGL_COMPAT &&
2628 !ctx->DrawIndirectBuffer) {
2629 /*
2630 * Unlike regular DrawElementsInstancedBaseVertex commands, the indices
2631 * may not come from a client array and must come from an index buffer.
2632 * If no element array buffer is bound, an INVALID_OPERATION error is
2633 * generated.
2634 */
2635 if (!ctx->Array.VAO->IndexBufferObj) {
2636 _mesa_error(ctx, GL_INVALID_OPERATION,
2637 "glMultiDrawElementsIndirect(no buffer bound "
2638 "to GL_ELEMENT_ARRAY_BUFFER)");
2639
2640 return;
2641 }
2642
2643 if (!_mesa_is_no_error_enabled(ctx) &&
2644 (!_mesa_valid_draw_indirect_multi(ctx, primcount, stride,
2645 "glMultiDrawArraysIndirect") ||
2646 !_mesa_validate_DrawElements(ctx, mode, 1, type)))
2647 return;
2648
2649 unsigned index_size_shift = get_index_size_shift(type);
2650
2651 struct pipe_draw_info info;
2652 info.mode = mode;
2653 info.index_size = 1 << index_size_shift;
2654 info.view_mask = 0;
2655 /* Packed section begin. */
2656 info.primitive_restart = ctx->Array._PrimitiveRestart[index_size_shift];
2657 info.has_user_indices = false;
2658 info.index_bounds_valid = false;
2659 info.increment_draw_id = primcount > 1;
2660 info.was_line_loop = false;
2661 info.take_index_buffer_ownership = false;
2662 info.index_bias_varies = false;
2663 /* Packed section end. */
2664 info.restart_index = ctx->Array._RestartIndex[index_size_shift];
2665
2666 const uint8_t *ptr = (const uint8_t *) indirect;
2667 for (unsigned i = 0; i < primcount; i++) {
2668 DrawElementsIndirectCommand *cmd = (DrawElementsIndirectCommand*)ptr;
2669
2670 info.index.gl_bo = ctx->Array.VAO->IndexBufferObj;
2671 info.start_instance = cmd->baseInstance;
2672 info.instance_count = cmd->primCount;
2673
2674 struct pipe_draw_start_count_bias draw;
2675 draw.start = cmd->firstIndex;
2676 draw.count = cmd->count;
2677 draw.index_bias = cmd->baseVertex;
2678
2679 ctx->Driver.DrawGallium(ctx, &info, i, &draw, 1);
2680 ptr += stride;
2681 }
2682
2683 return;
2684 }
2685
2686 if (!_mesa_is_no_error_enabled(ctx) &&
2687 !_mesa_validate_MultiDrawElementsIndirect(ctx, mode, type, indirect,
2688 primcount, stride))
2689 return;
2690
2691 _mesa_validated_multidrawelementsindirect(ctx, mode, type,
2692 (GLintptr)indirect, 0, primcount,
2693 stride, NULL);
2694 }
2695
2696
2697 void GLAPIENTRY
_mesa_MultiDrawArraysIndirectCountARB(GLenum mode,GLintptr indirect,GLintptr drawcount_offset,GLsizei maxdrawcount,GLsizei stride)2698 _mesa_MultiDrawArraysIndirectCountARB(GLenum mode, GLintptr indirect,
2699 GLintptr drawcount_offset,
2700 GLsizei maxdrawcount, GLsizei stride)
2701 {
2702 GET_CURRENT_CONTEXT(ctx);
2703 FLUSH_FOR_DRAW(ctx);
2704
2705 /* If <stride> is zero, the array elements are treated as tightly packed. */
2706 if (stride == 0)
2707 stride = 4 * sizeof(GLuint); /* sizeof(DrawArraysIndirectCommand) */
2708
2709 _mesa_set_draw_vao(ctx, ctx->Array.VAO,
2710 ctx->VertexProgram._VPModeInputFilter);
2711
2712 if (ctx->NewState)
2713 _mesa_update_state(ctx);
2714
2715 if (!_mesa_is_no_error_enabled(ctx) &&
2716 !_mesa_validate_MultiDrawArraysIndirectCount(ctx, mode, indirect,
2717 drawcount_offset,
2718 maxdrawcount, stride))
2719 return;
2720
2721 _mesa_validated_multidrawarraysindirect(ctx, mode, indirect,
2722 drawcount_offset, maxdrawcount,
2723 stride, ctx->ParameterBuffer);
2724 }
2725
2726
2727 void GLAPIENTRY
_mesa_MultiDrawElementsIndirectCountARB(GLenum mode,GLenum type,GLintptr indirect,GLintptr drawcount_offset,GLsizei maxdrawcount,GLsizei stride)2728 _mesa_MultiDrawElementsIndirectCountARB(GLenum mode, GLenum type,
2729 GLintptr indirect,
2730 GLintptr drawcount_offset,
2731 GLsizei maxdrawcount, GLsizei stride)
2732 {
2733 GET_CURRENT_CONTEXT(ctx);
2734 FLUSH_FOR_DRAW(ctx);
2735
2736 /* If <stride> is zero, the array elements are treated as tightly packed. */
2737 if (stride == 0)
2738 stride = 5 * sizeof(GLuint); /* sizeof(DrawElementsIndirectCommand) */
2739
2740 _mesa_set_draw_vao(ctx, ctx->Array.VAO,
2741 ctx->VertexProgram._VPModeInputFilter);
2742
2743 if (ctx->NewState)
2744 _mesa_update_state(ctx);
2745
2746 if (!_mesa_is_no_error_enabled(ctx) &&
2747 !_mesa_validate_MultiDrawElementsIndirectCount(ctx, mode, type,
2748 indirect,
2749 drawcount_offset,
2750 maxdrawcount, stride))
2751 return;
2752
2753 _mesa_validated_multidrawelementsindirect(ctx, mode, type, indirect,
2754 drawcount_offset, maxdrawcount,
2755 stride, ctx->ParameterBuffer);
2756 }
2757
2758
2759 /* GL_IBM_multimode_draw_arrays */
2760 void GLAPIENTRY
_mesa_MultiModeDrawArraysIBM(const GLenum * mode,const GLint * first,const GLsizei * count,GLsizei primcount,GLint modestride)2761 _mesa_MultiModeDrawArraysIBM( const GLenum * mode, const GLint * first,
2762 const GLsizei * count,
2763 GLsizei primcount, GLint modestride )
2764 {
2765 GET_CURRENT_CONTEXT(ctx);
2766 GLint i;
2767
2768 for ( i = 0 ; i < primcount ; i++ ) {
2769 if ( count[i] > 0 ) {
2770 GLenum m = *((GLenum *) ((GLubyte *) mode + i * modestride));
2771 CALL_DrawArrays(ctx->CurrentServerDispatch, ( m, first[i], count[i] ));
2772 }
2773 }
2774 }
2775
2776
2777 /* GL_IBM_multimode_draw_arrays */
2778 void GLAPIENTRY
_mesa_MultiModeDrawElementsIBM(const GLenum * mode,const GLsizei * count,GLenum type,const GLvoid * const * indices,GLsizei primcount,GLint modestride)2779 _mesa_MultiModeDrawElementsIBM( const GLenum * mode, const GLsizei * count,
2780 GLenum type, const GLvoid * const * indices,
2781 GLsizei primcount, GLint modestride )
2782 {
2783 GET_CURRENT_CONTEXT(ctx);
2784 GLint i;
2785
2786 for ( i = 0 ; i < primcount ; i++ ) {
2787 if ( count[i] > 0 ) {
2788 GLenum m = *((GLenum *) ((GLubyte *) mode + i * modestride));
2789 CALL_DrawElements(ctx->CurrentServerDispatch, ( m, count[i], type,
2790 indices[i] ));
2791 }
2792 }
2793 }
2794