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