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.min_index = start;
1171 info.max_index = start + count - 1;
1172
1173 draw.start = start;
1174 draw.count = count;
1175
1176 st_prepare_draw(ctx, ST_PIPELINE_RENDER_STATE_MASK);
1177
1178 ctx->Driver.DrawGallium(ctx, &info, ctx->DrawID, NULL, &draw, 1);
1179
1180 if (MESA_DEBUG_FLAGS & DEBUG_ALWAYS_FLUSH) {
1181 _mesa_flush(ctx);
1182 }
1183 }
1184
1185
1186 /**
1187 * Execute a glRectf() function.
1188 */
1189 void GLAPIENTRY
_mesa_Rectf(GLfloat x1,GLfloat y1,GLfloat x2,GLfloat y2)1190 _mesa_Rectf(GLfloat x1, GLfloat y1, GLfloat x2, GLfloat y2)
1191 {
1192 GET_CURRENT_CONTEXT(ctx);
1193 ASSERT_OUTSIDE_BEGIN_END(ctx);
1194
1195 CALL_Begin(ctx->Dispatch.Current, (GL_QUADS));
1196 /* Begin can change Dispatch.Current. */
1197 struct _glapi_table *dispatch = ctx->Dispatch.Current;
1198 CALL_Vertex2f(dispatch, (x1, y1));
1199 CALL_Vertex2f(dispatch, (x2, y1));
1200 CALL_Vertex2f(dispatch, (x2, y2));
1201 CALL_Vertex2f(dispatch, (x1, y2));
1202 CALL_End(dispatch, ());
1203 }
1204
1205
1206 void GLAPIENTRY
_mesa_Rectd(GLdouble x1,GLdouble y1,GLdouble x2,GLdouble y2)1207 _mesa_Rectd(GLdouble x1, GLdouble y1, GLdouble x2, GLdouble y2)
1208 {
1209 _mesa_Rectf((GLfloat) x1, (GLfloat) y1, (GLfloat) x2, (GLfloat) y2);
1210 }
1211
1212 void GLAPIENTRY
_mesa_Rectdv(const GLdouble * v1,const GLdouble * v2)1213 _mesa_Rectdv(const GLdouble *v1, const GLdouble *v2)
1214 {
1215 _mesa_Rectf((GLfloat) v1[0], (GLfloat) v1[1], (GLfloat) v2[0], (GLfloat) v2[1]);
1216 }
1217
1218 void GLAPIENTRY
_mesa_Rectfv(const GLfloat * v1,const GLfloat * v2)1219 _mesa_Rectfv(const GLfloat *v1, const GLfloat *v2)
1220 {
1221 _mesa_Rectf(v1[0], v1[1], v2[0], v2[1]);
1222 }
1223
1224 void GLAPIENTRY
_mesa_Recti(GLint x1,GLint y1,GLint x2,GLint y2)1225 _mesa_Recti(GLint x1, GLint y1, GLint x2, GLint y2)
1226 {
1227 _mesa_Rectf((GLfloat) x1, (GLfloat) y1, (GLfloat) x2, (GLfloat) y2);
1228 }
1229
1230 void GLAPIENTRY
_mesa_Rectiv(const GLint * v1,const GLint * v2)1231 _mesa_Rectiv(const GLint *v1, const GLint *v2)
1232 {
1233 _mesa_Rectf((GLfloat) v1[0], (GLfloat) v1[1], (GLfloat) v2[0], (GLfloat) v2[1]);
1234 }
1235
1236 void GLAPIENTRY
_mesa_Rects(GLshort x1,GLshort y1,GLshort x2,GLshort y2)1237 _mesa_Rects(GLshort x1, GLshort y1, GLshort x2, GLshort y2)
1238 {
1239 _mesa_Rectf((GLfloat) x1, (GLfloat) y1, (GLfloat) x2, (GLfloat) y2);
1240 }
1241
1242 void GLAPIENTRY
_mesa_Rectsv(const GLshort * v1,const GLshort * v2)1243 _mesa_Rectsv(const GLshort *v1, const GLshort *v2)
1244 {
1245 _mesa_Rectf((GLfloat) v1[0], (GLfloat) v1[1], (GLfloat) v2[0], (GLfloat) v2[1]);
1246 }
1247
1248
1249 void GLAPIENTRY
_mesa_EvalMesh1(GLenum mode,GLint i1,GLint i2)1250 _mesa_EvalMesh1(GLenum mode, GLint i1, GLint i2)
1251 {
1252 GET_CURRENT_CONTEXT(ctx);
1253 GLint i;
1254 GLfloat u, du;
1255 GLenum prim;
1256
1257 switch (mode) {
1258 case GL_POINT:
1259 prim = GL_POINTS;
1260 break;
1261 case GL_LINE:
1262 prim = GL_LINE_STRIP;
1263 break;
1264 default:
1265 _mesa_error(ctx, GL_INVALID_ENUM, "glEvalMesh1(mode)");
1266 return;
1267 }
1268
1269 /* No effect if vertex maps disabled.
1270 */
1271 if (!ctx->Eval.Map1Vertex4 && !ctx->Eval.Map1Vertex3)
1272 return;
1273
1274 du = ctx->Eval.MapGrid1du;
1275 u = ctx->Eval.MapGrid1u1 + i1 * du;
1276
1277
1278 CALL_Begin(ctx->Dispatch.Current, (prim));
1279 /* Begin can change Dispatch.Current. */
1280 struct _glapi_table *dispatch = ctx->Dispatch.Current;
1281 for (i = i1; i <= i2; i++, u += du) {
1282 CALL_EvalCoord1f(dispatch, (u));
1283 }
1284 CALL_End(dispatch, ());
1285 }
1286
1287
1288 void GLAPIENTRY
_mesa_EvalMesh2(GLenum mode,GLint i1,GLint i2,GLint j1,GLint j2)1289 _mesa_EvalMesh2(GLenum mode, GLint i1, GLint i2, GLint j1, GLint j2)
1290 {
1291 GET_CURRENT_CONTEXT(ctx);
1292 GLfloat u, du, v, dv, v1, u1;
1293 GLint i, j;
1294
1295 switch (mode) {
1296 case GL_POINT:
1297 case GL_LINE:
1298 case GL_FILL:
1299 break;
1300 default:
1301 _mesa_error(ctx, GL_INVALID_ENUM, "glEvalMesh2(mode)");
1302 return;
1303 }
1304
1305 /* No effect if vertex maps disabled.
1306 */
1307 if (!ctx->Eval.Map2Vertex4 && !ctx->Eval.Map2Vertex3)
1308 return;
1309
1310 du = ctx->Eval.MapGrid2du;
1311 dv = ctx->Eval.MapGrid2dv;
1312 v1 = ctx->Eval.MapGrid2v1 + j1 * dv;
1313 u1 = ctx->Eval.MapGrid2u1 + i1 * du;
1314
1315 struct _glapi_table *dispatch;
1316
1317 switch (mode) {
1318 case GL_POINT:
1319 CALL_Begin(ctx->Dispatch.Current, (GL_POINTS));
1320 /* Begin can change Dispatch.Current. */
1321 dispatch = ctx->Dispatch.Current;
1322 for (v = v1, j = j1; j <= j2; j++, v += dv) {
1323 for (u = u1, i = i1; i <= i2; i++, u += du) {
1324 CALL_EvalCoord2f(dispatch, (u, v));
1325 }
1326 }
1327 CALL_End(dispatch, ());
1328 break;
1329 case GL_LINE:
1330 for (v = v1, j = j1; j <= j2; j++, v += dv) {
1331 CALL_Begin(ctx->Dispatch.Current, (GL_LINE_STRIP));
1332 /* Begin can change Dispatch.Current. */
1333 dispatch = ctx->Dispatch.Current;
1334 for (u = u1, i = i1; i <= i2; i++, u += du) {
1335 CALL_EvalCoord2f(dispatch, (u, v));
1336 }
1337 CALL_End(dispatch, ());
1338 }
1339 for (u = u1, i = i1; i <= i2; i++, u += du) {
1340 CALL_Begin(ctx->Dispatch.Current, (GL_LINE_STRIP));
1341 /* Begin can change Dispatch.Current. */
1342 dispatch = ctx->Dispatch.Current;
1343 for (v = v1, j = j1; j <= j2; j++, v += dv) {
1344 CALL_EvalCoord2f(dispatch, (u, v));
1345 }
1346 CALL_End(dispatch, ());
1347 }
1348 break;
1349 case GL_FILL:
1350 for (v = v1, j = j1; j < j2; j++, v += dv) {
1351 CALL_Begin(ctx->Dispatch.Current, (GL_TRIANGLE_STRIP));
1352 /* Begin can change Dispatch.Current. */
1353 dispatch = ctx->Dispatch.Current;
1354 for (u = u1, i = i1; i <= i2; i++, u += du) {
1355 CALL_EvalCoord2f(dispatch, (u, v));
1356 CALL_EvalCoord2f(dispatch, (u, v + dv));
1357 }
1358 CALL_End(dispatch, ());
1359 }
1360 break;
1361 }
1362 }
1363
1364
1365 /**
1366 * Called from glDrawArrays when in immediate mode (not display list mode).
1367 */
1368 void GLAPIENTRY
_mesa_DrawArrays(GLenum mode,GLint start,GLsizei count)1369 _mesa_DrawArrays(GLenum mode, GLint start, GLsizei count)
1370 {
1371 GET_CURRENT_CONTEXT(ctx);
1372 FLUSH_FOR_DRAW(ctx);
1373
1374 _mesa_set_varying_vp_inputs(ctx, ctx->VertexProgram._VPModeInputFilter &
1375 ctx->Array._DrawVAO->_EnabledWithMapMode);
1376 if (ctx->NewState)
1377 _mesa_update_state(ctx);
1378
1379 if (!_mesa_is_no_error_enabled(ctx) &&
1380 !_mesa_validate_DrawArrays(ctx, mode, count))
1381 return;
1382
1383 if (0)
1384 check_draw_arrays_data(ctx, start, count);
1385
1386 _mesa_draw_arrays(ctx, mode, start, count, 1, 0);
1387
1388 if (0)
1389 print_draw_arrays(ctx, mode, start, count);
1390 }
1391
1392
1393 /**
1394 * Called from glDrawArraysInstanced when in immediate mode (not
1395 * display list mode).
1396 */
1397 void GLAPIENTRY
_mesa_DrawArraysInstanced(GLenum mode,GLint start,GLsizei count,GLsizei numInstances)1398 _mesa_DrawArraysInstanced(GLenum mode, GLint start, GLsizei count,
1399 GLsizei numInstances)
1400 {
1401 _mesa_DrawArraysInstancedBaseInstance(mode, start, count, numInstances, 0);
1402 }
1403
1404
1405 /**
1406 * Called from glDrawArraysInstancedBaseInstance when in immediate mode.
1407 */
1408 void GLAPIENTRY
_mesa_DrawArraysInstancedBaseInstance(GLenum mode,GLint first,GLsizei count,GLsizei numInstances,GLuint baseInstance)1409 _mesa_DrawArraysInstancedBaseInstance(GLenum mode, GLint first,
1410 GLsizei count, GLsizei numInstances,
1411 GLuint baseInstance)
1412 {
1413 GET_CURRENT_CONTEXT(ctx);
1414 FLUSH_FOR_DRAW(ctx);
1415
1416 _mesa_set_varying_vp_inputs(ctx, ctx->VertexProgram._VPModeInputFilter &
1417 ctx->Array._DrawVAO->_EnabledWithMapMode);
1418 if (ctx->NewState)
1419 _mesa_update_state(ctx);
1420
1421 if (!_mesa_is_no_error_enabled(ctx) &&
1422 !_mesa_validate_DrawArraysInstanced(ctx, mode, first, count,
1423 numInstances))
1424 return;
1425
1426 if (0)
1427 check_draw_arrays_data(ctx, first, count);
1428
1429 _mesa_draw_arrays(ctx, mode, first, count, numInstances, baseInstance);
1430
1431 if (0)
1432 print_draw_arrays(ctx, mode, first, count);
1433 }
1434
1435
1436 /**
1437 * Called from glMultiDrawArrays when in immediate mode.
1438 */
1439 void GLAPIENTRY
_mesa_MultiDrawArrays(GLenum mode,const GLint * first,const GLsizei * count,GLsizei primcount)1440 _mesa_MultiDrawArrays(GLenum mode, const GLint *first,
1441 const GLsizei *count, GLsizei primcount)
1442 {
1443 GET_CURRENT_CONTEXT(ctx);
1444 FLUSH_FOR_DRAW(ctx);
1445
1446 _mesa_set_varying_vp_inputs(ctx, ctx->VertexProgram._VPModeInputFilter &
1447 ctx->Array._DrawVAO->_EnabledWithMapMode);
1448 if (ctx->NewState)
1449 _mesa_update_state(ctx);
1450
1451 if (!_mesa_is_no_error_enabled(ctx) &&
1452 !_mesa_validate_MultiDrawArrays(ctx, mode, count, primcount))
1453 return;
1454
1455 if (primcount == 0)
1456 return;
1457
1458 struct pipe_draw_info info;
1459 struct pipe_draw_start_count_bias *draw = get_temp_draws(ctx, primcount);
1460 if (!draw)
1461 return;
1462
1463 info.mode = mode;
1464 info.index_size = 0;
1465 /* Packed section begin. */
1466 info.primitive_restart = false;
1467 info.has_user_indices = false;
1468 info.index_bounds_valid = false;
1469 info.increment_draw_id = primcount > 1;
1470 info.was_line_loop = false;
1471 info.take_index_buffer_ownership = false;
1472 info.index_bias_varies = false;
1473 /* Packed section end. */
1474 info.start_instance = 0;
1475 info.instance_count = 1;
1476
1477 for (int i = 0; i < primcount; i++) {
1478 draw[i].start = first[i];
1479 draw[i].count = count[i];
1480 }
1481
1482 st_prepare_draw(ctx, ST_PIPELINE_RENDER_STATE_MASK);
1483
1484 ctx->Driver.DrawGallium(ctx, &info, 0, NULL, draw, primcount);
1485
1486 if (MESA_DEBUG_FLAGS & DEBUG_ALWAYS_FLUSH)
1487 _mesa_flush(ctx);
1488 }
1489
1490
1491
1492 /**
1493 * Map GL_ELEMENT_ARRAY_BUFFER and print contents.
1494 * For debugging.
1495 */
1496 #if 0
1497 static void
1498 dump_element_buffer(struct gl_context *ctx, GLenum type)
1499 {
1500 const GLvoid *map =
1501 ctx->Driver.MapBufferRange(ctx, 0,
1502 ctx->Array.VAO->IndexBufferObj->Size,
1503 GL_MAP_READ_BIT,
1504 ctx->Array.VAO->IndexBufferObj,
1505 MAP_INTERNAL);
1506 switch (type) {
1507 case GL_UNSIGNED_BYTE:
1508 {
1509 const GLubyte *us = (const GLubyte *) map;
1510 GLint i;
1511 for (i = 0; i < ctx->Array.VAO->IndexBufferObj->Size; i++) {
1512 printf("%02x ", us[i]);
1513 if (i % 32 == 31)
1514 printf("\n");
1515 }
1516 printf("\n");
1517 }
1518 break;
1519 case GL_UNSIGNED_SHORT:
1520 {
1521 const GLushort *us = (const GLushort *) map;
1522 GLint i;
1523 for (i = 0; i < ctx->Array.VAO->IndexBufferObj->Size / 2; i++) {
1524 printf("%04x ", us[i]);
1525 if (i % 16 == 15)
1526 printf("\n");
1527 }
1528 printf("\n");
1529 }
1530 break;
1531 case GL_UNSIGNED_INT:
1532 {
1533 const GLuint *us = (const GLuint *) map;
1534 GLint i;
1535 for (i = 0; i < ctx->Array.VAO->IndexBufferObj->Size / 4; i++) {
1536 printf("%08x ", us[i]);
1537 if (i % 8 == 7)
1538 printf("\n");
1539 }
1540 printf("\n");
1541 }
1542 break;
1543 default:
1544 ;
1545 }
1546
1547 ctx->Driver.UnmapBuffer(ctx, ctx->Array.VAO->IndexBufferObj, MAP_INTERNAL);
1548 }
1549 #endif
1550
1551 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)1552 validate_index_bounds(struct gl_context *ctx, struct pipe_draw_info *info,
1553 const struct pipe_draw_start_count_bias *draws,
1554 unsigned num_draws)
1555 {
1556 assert(info->index_size);
1557
1558 /* Get index bounds for user buffers. */
1559 if (!info->index_bounds_valid && ctx->st->draw_needs_minmax_index) {
1560 /* Return if this fails, which means all draws have count == 0. */
1561 if (!vbo_get_minmax_indices_gallium(ctx, info, draws, num_draws))
1562 return false;
1563
1564 info->index_bounds_valid = true;
1565 }
1566 return true;
1567 }
1568
1569 /**
1570 * Inner support for both _mesa_DrawElements and _mesa_DrawRangeElements.
1571 * Do the rendering for a glDrawElements or glDrawRangeElements call after
1572 * we've validated buffer bounds, etc.
1573 */
1574 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)1575 _mesa_validated_drawrangeelements(struct gl_context *ctx,
1576 struct gl_buffer_object *index_bo,
1577 GLenum mode,
1578 bool index_bounds_valid,
1579 GLuint start, GLuint end,
1580 GLsizei count, GLenum type,
1581 const GLvoid * indices,
1582 GLint basevertex, GLuint numInstances,
1583 GLuint baseInstance)
1584 {
1585 /* Viewperf has many draws with count=0. Discarding them is faster than
1586 * processing them.
1587 */
1588 if (!count || !numInstances)
1589 return;
1590
1591 if (!index_bounds_valid) {
1592 assert(start == 0u);
1593 assert(end == ~0u);
1594 }
1595
1596 unsigned index_size_shift = _mesa_get_index_size_shift(type);
1597
1598 if (index_bo) {
1599 if (!indices_aligned(index_size_shift, indices))
1600 return;
1601
1602 if (unlikely(index_bo->Size < (uintptr_t)indices || !index_bo->buffer)) {
1603 #ifndef NDEBUG
1604 _mesa_warning(ctx, "Invalid indices offset 0x%" PRIxPTR
1605 " (indices buffer size is %ld bytes)"
1606 " or unallocated buffer (%u). Draw skipped.",
1607 (uintptr_t)indices, (long)index_bo->Size,
1608 !!index_bo->buffer);
1609 #endif
1610 return;
1611 }
1612 }
1613
1614 st_prepare_draw(ctx, ST_PIPELINE_RENDER_STATE_MASK);
1615
1616 /* Fast path for a very common DrawElements case:
1617 * - there are no user indices here (always true with glthread)
1618 * - DrawGallium is st_draw_gallium (regular render mode, almost always
1619 * true), which only calls cso_context::draw_vbo
1620 * - the threaded context is enabled while u_vbuf is bypassed (cso_context
1621 * always calls tc_draw_vbo, which is always true with glthread if all
1622 * vertex formats are also supported by the driver)
1623 * - DrawID is 0 (true if glthread isn't unrolling an indirect multi draw,
1624 * which is almost always true)
1625 */
1626 struct st_context *st = st_context(ctx);
1627 if (index_bo && ctx->Driver.DrawGallium == st_draw_gallium &&
1628 st->cso_context->draw_vbo == tc_draw_vbo && ctx->DrawID == 0) {
1629 assert(!st->draw_needs_minmax_index);
1630 struct pipe_resource *index_buffer =
1631 _mesa_get_bufferobj_reference(ctx, index_bo);
1632 struct tc_draw_single *draw =
1633 tc_add_draw_single_call(st->pipe, index_buffer);
1634 bool primitive_restart = ctx->Array._PrimitiveRestart[index_size_shift];
1635
1636 /* This must be set exactly like u_threaded_context sets it, not like
1637 * it would be set for draw_vbo.
1638 */
1639 draw->info.mode = mode;
1640 draw->info.index_size = 1 << index_size_shift;
1641 /* Packed section begin. */
1642 draw->info.primitive_restart = primitive_restart;
1643 draw->info.has_user_indices = false;
1644 draw->info.index_bounds_valid = false;
1645 draw->info.increment_draw_id = false;
1646 draw->info.take_index_buffer_ownership = false;
1647 draw->info.index_bias_varies = false;
1648 draw->info.was_line_loop = false;
1649 draw->info._pad = 0;
1650 /* Packed section end. */
1651 draw->info.start_instance = baseInstance;
1652 draw->info.instance_count = numInstances;
1653 draw->info.restart_index =
1654 primitive_restart ? ctx->Array._RestartIndex[index_size_shift] : 0;
1655 draw->info.index.resource = index_buffer;
1656
1657 /* u_threaded_context stores start/count in min/max_index for single draws. */
1658 draw->info.min_index = (uintptr_t)indices >> index_size_shift;
1659 draw->info.max_index = count;
1660 draw->index_bias = basevertex;
1661 return;
1662 }
1663
1664 struct pipe_draw_info info;
1665 struct pipe_draw_start_count_bias draw;
1666
1667 info.mode = mode;
1668 info.index_size = 1 << index_size_shift;
1669 /* Packed section begin. */
1670 info.primitive_restart = ctx->Array._PrimitiveRestart[index_size_shift];
1671 info.has_user_indices = index_bo == NULL;
1672 info.index_bounds_valid = index_bounds_valid;
1673 info.increment_draw_id = false;
1674 info.was_line_loop = false;
1675 info.take_index_buffer_ownership = false;
1676 info.index_bias_varies = false;
1677 /* Packed section end. */
1678 info.start_instance = baseInstance;
1679 info.instance_count = numInstances;
1680 info.restart_index = ctx->Array._RestartIndex[index_size_shift];
1681
1682 if (info.has_user_indices) {
1683 info.index.user = indices;
1684 draw.start = 0;
1685 } else {
1686 draw.start = (uintptr_t)indices >> index_size_shift;
1687
1688 if (ctx->pipe->draw_vbo == tc_draw_vbo) {
1689 /* Fast path for u_threaded_context to eliminate atomics. */
1690 info.index.resource = _mesa_get_bufferobj_reference(ctx, index_bo);
1691 info.take_index_buffer_ownership = true;
1692 } else {
1693 info.index.resource = index_bo->buffer;
1694 }
1695 }
1696 draw.index_bias = basevertex;
1697
1698 info.min_index = start;
1699 info.max_index = end;
1700 draw.count = count;
1701
1702 if (!validate_index_bounds(ctx, &info, &draw, 1))
1703 return;
1704
1705 ctx->Driver.DrawGallium(ctx, &info, ctx->DrawID, NULL, &draw, 1);
1706
1707 if (MESA_DEBUG_FLAGS & DEBUG_ALWAYS_FLUSH) {
1708 _mesa_flush(ctx);
1709 }
1710 }
1711
1712
1713 /**
1714 * Called by glDrawRangeElementsBaseVertex() in immediate mode.
1715 */
1716 void GLAPIENTRY
_mesa_DrawRangeElementsBaseVertex(GLenum mode,GLuint start,GLuint end,GLsizei count,GLenum type,const GLvoid * indices,GLint basevertex)1717 _mesa_DrawRangeElementsBaseVertex(GLenum mode, GLuint start, GLuint end,
1718 GLsizei count, GLenum type,
1719 const GLvoid * indices, GLint basevertex)
1720 {
1721 static GLuint warnCount = 0;
1722 bool index_bounds_valid = true;
1723
1724 /* This is only useful to catch invalid values in the "end" parameter
1725 * like ~0.
1726 */
1727 GLuint max_element = 2 * 1000 * 1000 * 1000; /* just a big number */
1728
1729 GET_CURRENT_CONTEXT(ctx);
1730 FLUSH_FOR_DRAW(ctx);
1731
1732 _mesa_set_varying_vp_inputs(ctx, ctx->VertexProgram._VPModeInputFilter &
1733 ctx->Array._DrawVAO->_EnabledWithMapMode);
1734 if (ctx->NewState)
1735 _mesa_update_state(ctx);
1736
1737 if (!_mesa_is_no_error_enabled(ctx) &&
1738 !_mesa_validate_DrawRangeElements(ctx, mode, start, end, count,
1739 type))
1740 return;
1741
1742 if ((int) end + basevertex < 0 || start + basevertex >= max_element) {
1743 /* The application requested we draw using a range of indices that's
1744 * outside the bounds of the current VBO. This is invalid and appears
1745 * to give undefined results. The safest thing to do is to simply
1746 * ignore the range, in case the application botched their range tracking
1747 * but did provide valid indices. Also issue a warning indicating that
1748 * the application is broken.
1749 */
1750 if (warnCount++ < 10) {
1751 _mesa_warning(ctx, "glDrawRangeElements(start %u, end %u, "
1752 "basevertex %d, count %d, type 0x%x, indices=%p):\n"
1753 "\trange is outside VBO bounds (max=%u); ignoring.\n"
1754 "\tThis should be fixed in the application.",
1755 start, end, basevertex, count, type, indices,
1756 max_element - 1);
1757 }
1758 index_bounds_valid = false;
1759 }
1760
1761 /* NOTE: It's important that 'end' is a reasonable value.
1762 * in _tnl_draw_prims(), we use end to determine how many vertices
1763 * to transform. If it's too large, we can unnecessarily split prims
1764 * or we can read/write out of memory in several different places!
1765 */
1766
1767 /* Catch/fix some potential user errors */
1768 if (type == GL_UNSIGNED_BYTE) {
1769 start = MIN2(start, 0xff);
1770 end = MIN2(end, 0xff);
1771 }
1772 else if (type == GL_UNSIGNED_SHORT) {
1773 start = MIN2(start, 0xffff);
1774 end = MIN2(end, 0xffff);
1775 }
1776
1777 if (0) {
1778 printf("glDraw[Range]Elements{,BaseVertex}"
1779 "(start %u, end %u, type 0x%x, count %d) ElemBuf %u, "
1780 "base %d\n",
1781 start, end, type, count,
1782 ctx->Array.VAO->IndexBufferObj ?
1783 ctx->Array.VAO->IndexBufferObj->Name : 0, basevertex);
1784 }
1785
1786 if ((int) start + basevertex < 0 || end + basevertex >= max_element)
1787 index_bounds_valid = false;
1788
1789 #if 0
1790 check_draw_elements_data(ctx, count, type, indices, basevertex);
1791 #else
1792 (void) check_draw_elements_data;
1793 #endif
1794
1795 if (!index_bounds_valid) {
1796 start = 0;
1797 end = ~0;
1798 }
1799
1800 _mesa_validated_drawrangeelements(ctx, ctx->Array.VAO->IndexBufferObj,
1801 mode, index_bounds_valid, start, end,
1802 count, type, indices, basevertex, 1, 0);
1803 }
1804
1805
1806 /**
1807 * Called by glDrawRangeElements() in immediate mode.
1808 */
1809 void GLAPIENTRY
_mesa_DrawRangeElements(GLenum mode,GLuint start,GLuint end,GLsizei count,GLenum type,const GLvoid * indices)1810 _mesa_DrawRangeElements(GLenum mode, GLuint start, GLuint end,
1811 GLsizei count, GLenum type, const GLvoid * indices)
1812 {
1813 _mesa_DrawRangeElementsBaseVertex(mode, start, end, count, type,
1814 indices, 0);
1815 }
1816
1817
1818 /**
1819 * Called by glDrawElements() in immediate mode.
1820 */
1821 void GLAPIENTRY
_mesa_DrawElements(GLenum mode,GLsizei count,GLenum type,const GLvoid * indices)1822 _mesa_DrawElements(GLenum mode, GLsizei count, GLenum type,
1823 const GLvoid * indices)
1824 {
1825 _mesa_DrawElementsBaseVertex(mode, count, type, indices, 0);
1826 }
1827
1828
1829 /**
1830 * Called by glDrawElementsBaseVertex() in immediate mode.
1831 */
1832 void GLAPIENTRY
_mesa_DrawElementsBaseVertex(GLenum mode,GLsizei count,GLenum type,const GLvoid * indices,GLint basevertex)1833 _mesa_DrawElementsBaseVertex(GLenum mode, GLsizei count, GLenum type,
1834 const GLvoid * indices, GLint basevertex)
1835 {
1836 GET_CURRENT_CONTEXT(ctx);
1837 FLUSH_FOR_DRAW(ctx);
1838
1839 _mesa_set_varying_vp_inputs(ctx, ctx->VertexProgram._VPModeInputFilter &
1840 ctx->Array._DrawVAO->_EnabledWithMapMode);
1841 if (ctx->NewState)
1842 _mesa_update_state(ctx);
1843
1844 if (!_mesa_is_no_error_enabled(ctx) &&
1845 !_mesa_validate_DrawElements(ctx, mode, count, type))
1846 return;
1847
1848 _mesa_validated_drawrangeelements(ctx, ctx->Array.VAO->IndexBufferObj,
1849 mode, false, 0, ~0,
1850 count, type, indices, basevertex, 1, 0);
1851 }
1852
1853
1854 /**
1855 * Called by glDrawElementsInstanced() in immediate mode.
1856 */
1857 void GLAPIENTRY
_mesa_DrawElementsInstanced(GLenum mode,GLsizei count,GLenum type,const GLvoid * indices,GLsizei numInstances)1858 _mesa_DrawElementsInstanced(GLenum mode, GLsizei count, GLenum type,
1859 const GLvoid * indices, GLsizei numInstances)
1860 {
1861 _mesa_DrawElementsInstancedBaseVertexBaseInstance(mode, count, type,
1862 indices, numInstances,
1863 0, 0);
1864 }
1865
1866
1867 /**
1868 * Called by glDrawElementsInstancedBaseVertex() in immediate mode.
1869 */
1870 void GLAPIENTRY
_mesa_DrawElementsInstancedBaseVertex(GLenum mode,GLsizei count,GLenum type,const GLvoid * indices,GLsizei numInstances,GLint basevertex)1871 _mesa_DrawElementsInstancedBaseVertex(GLenum mode, GLsizei count,
1872 GLenum type, const GLvoid * indices,
1873 GLsizei numInstances,
1874 GLint basevertex)
1875 {
1876 _mesa_DrawElementsInstancedBaseVertexBaseInstance(mode, count, type,
1877 indices, numInstances,
1878 basevertex, 0);
1879 }
1880
1881
1882 /**
1883 * Called by glDrawElementsInstancedBaseInstance() in immediate mode.
1884 */
1885 void GLAPIENTRY
_mesa_DrawElementsInstancedBaseInstance(GLenum mode,GLsizei count,GLenum type,const GLvoid * indices,GLsizei numInstances,GLuint baseInstance)1886 _mesa_DrawElementsInstancedBaseInstance(GLenum mode, GLsizei count,
1887 GLenum type,
1888 const GLvoid *indices,
1889 GLsizei numInstances,
1890 GLuint baseInstance)
1891 {
1892 _mesa_DrawElementsInstancedBaseVertexBaseInstance(mode, count, type,
1893 indices, numInstances,
1894 0, baseInstance);
1895 }
1896
1897
1898 /**
1899 * Called by glDrawElementsInstancedBaseVertexBaseInstance() in immediate mode.
1900 */
1901 void GLAPIENTRY
_mesa_DrawElementsInstancedBaseVertexBaseInstance(GLenum mode,GLsizei count,GLenum type,const GLvoid * indices,GLsizei numInstances,GLint basevertex,GLuint baseInstance)1902 _mesa_DrawElementsInstancedBaseVertexBaseInstance(GLenum mode,
1903 GLsizei count,
1904 GLenum type,
1905 const GLvoid *indices,
1906 GLsizei numInstances,
1907 GLint basevertex,
1908 GLuint baseInstance)
1909 {
1910 GET_CURRENT_CONTEXT(ctx);
1911 FLUSH_FOR_DRAW(ctx);
1912
1913 _mesa_set_varying_vp_inputs(ctx, ctx->VertexProgram._VPModeInputFilter &
1914 ctx->Array._DrawVAO->_EnabledWithMapMode);
1915 if (ctx->NewState)
1916 _mesa_update_state(ctx);
1917
1918 if (!_mesa_is_no_error_enabled(ctx) &&
1919 !_mesa_validate_DrawElementsInstanced(ctx, mode, count, type,
1920 numInstances))
1921 return;
1922
1923 _mesa_validated_drawrangeelements(ctx, ctx->Array.VAO->IndexBufferObj,
1924 mode, false, 0, ~0,
1925 count, type, indices, basevertex,
1926 numInstances, baseInstance);
1927 }
1928
1929 /**
1930 * Same as glDrawElementsInstancedBaseVertexBaseInstance, but the index
1931 * buffer is set by the indexBuf parameter instead of using the bound
1932 * GL_ELEMENT_ARRAY_BUFFER if indexBuf != NULL.
1933 */
1934 void GLAPIENTRY
_mesa_DrawElementsUserBuf(const GLvoid * ptr)1935 _mesa_DrawElementsUserBuf(const GLvoid *ptr)
1936 {
1937 GET_CURRENT_CONTEXT(ctx);
1938 FLUSH_FOR_DRAW(ctx);
1939
1940 _mesa_set_varying_vp_inputs(ctx, ctx->VertexProgram._VPModeInputFilter &
1941 ctx->Array._DrawVAO->_EnabledWithMapMode);
1942 if (ctx->NewState)
1943 _mesa_update_state(ctx);
1944
1945 const struct marshal_cmd_DrawElementsUserBuf *cmd =
1946 (const struct marshal_cmd_DrawElementsUserBuf *)ptr;
1947 const GLenum mode = cmd->mode;
1948 const GLsizei count = cmd->count;
1949 const GLenum type = _mesa_decode_index_type(cmd->type);
1950 const GLsizei instance_count = cmd->instance_count;
1951
1952 if (!_mesa_is_no_error_enabled(ctx) &&
1953 !_mesa_validate_DrawElementsInstanced(ctx, mode, count, type,
1954 instance_count))
1955 return;
1956
1957 struct gl_buffer_object *index_bo =
1958 cmd->index_buffer ? cmd->index_buffer : ctx->Array.VAO->IndexBufferObj;
1959
1960 const GLvoid *indices = cmd->indices;
1961 const GLint basevertex = cmd->basevertex;
1962 const GLuint baseinstance = cmd->baseinstance;
1963
1964 ctx->DrawID = cmd->drawid;
1965 _mesa_validated_drawrangeelements(ctx, index_bo,
1966 mode, false, 0, ~0,
1967 count, type, indices, basevertex,
1968 instance_count, baseinstance);
1969 ctx->DrawID = 0;
1970 }
1971
1972 /**
1973 * Same as glDrawElementsInstancedBaseVertexBaseInstance, but the index
1974 * buffer is set by the indexBuf parameter instead of using the bound
1975 * GL_ELEMENT_ARRAY_BUFFER if indexBuf != NULL.
1976 */
1977 void GLAPIENTRY
_mesa_DrawElementsUserBufPacked(const GLvoid * ptr)1978 _mesa_DrawElementsUserBufPacked(const GLvoid *ptr)
1979 {
1980 GET_CURRENT_CONTEXT(ctx);
1981 FLUSH_FOR_DRAW(ctx);
1982
1983 _mesa_set_varying_vp_inputs(ctx, ctx->VertexProgram._VPModeInputFilter &
1984 ctx->Array._DrawVAO->_EnabledWithMapMode);
1985 if (ctx->NewState)
1986 _mesa_update_state(ctx);
1987
1988 const struct marshal_cmd_DrawElementsUserBufPacked *cmd =
1989 (const struct marshal_cmd_DrawElementsUserBufPacked *)ptr;
1990 const GLenum mode = cmd->mode;
1991 const GLsizei count = cmd->count;
1992 const GLenum type = _mesa_decode_index_type(cmd->type);
1993
1994 if (!_mesa_is_no_error_enabled(ctx) &&
1995 !_mesa_validate_DrawElements(ctx, mode, count, type))
1996 return;
1997
1998 struct gl_buffer_object *index_bo =
1999 cmd->index_buffer ? cmd->index_buffer : ctx->Array.VAO->IndexBufferObj;
2000
2001 const GLvoid *indices = (void*)(uintptr_t)cmd->indices;
2002
2003 _mesa_validated_drawrangeelements(ctx, index_bo, mode, false, 0, ~0,
2004 count, type, indices, 0, 1, 0);
2005 }
2006
2007 /**
2008 * Inner support for both _mesa_MultiDrawElements() and
2009 * _mesa_MultiDrawRangeElements().
2010 * This does the actual rendering after we've checked array indexes, etc.
2011 */
2012 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)2013 _mesa_validated_multidrawelements(struct gl_context *ctx,
2014 struct gl_buffer_object *index_bo,
2015 GLenum mode, const GLsizei *count,
2016 GLenum type, const GLvoid * const *indices,
2017 GLsizei primcount, const GLint *basevertex)
2018 {
2019 uintptr_t min_index_ptr, max_index_ptr;
2020 bool fallback = false;
2021 int i;
2022
2023 if (primcount == 0)
2024 return;
2025
2026 unsigned index_size_shift = _mesa_get_index_size_shift(type);
2027
2028 min_index_ptr = (uintptr_t) indices[0];
2029 max_index_ptr = 0;
2030 for (i = 0; i < primcount; i++) {
2031 if (count[i]) {
2032 min_index_ptr = MIN2(min_index_ptr, (uintptr_t) indices[i]);
2033 max_index_ptr = MAX2(max_index_ptr, (uintptr_t) indices[i] +
2034 (count[i] << index_size_shift));
2035 }
2036 }
2037
2038 /* Check if we can handle this thing as a bunch of index offsets from the
2039 * same index pointer. If we can't, then we have to fall back to doing
2040 * a draw_prims per primitive.
2041 * Check that the difference between each prim's indexes is a multiple of
2042 * the index/element size.
2043 */
2044 if (index_size_shift) {
2045 for (i = 0; i < primcount; i++) {
2046 if (count[i] &&
2047 (((uintptr_t)indices[i] - min_index_ptr) &
2048 ((1 << index_size_shift) - 1)) != 0) {
2049 fallback = true;
2050 break;
2051 }
2052 }
2053 }
2054
2055 struct pipe_draw_info info;
2056
2057 info.mode = mode;
2058 info.index_size = 1 << index_size_shift;
2059 /* Packed section begin. */
2060 info.primitive_restart = ctx->Array._PrimitiveRestart[index_size_shift];
2061 info.has_user_indices = index_bo == NULL;
2062 info.index_bounds_valid = false;
2063 info.increment_draw_id = primcount > 1;
2064 info.was_line_loop = false;
2065 info.take_index_buffer_ownership = false;
2066 info.index_bias_varies = !!basevertex;
2067 /* Packed section end. */
2068 info.start_instance = 0;
2069 info.instance_count = 1;
2070 info.restart_index = ctx->Array._RestartIndex[index_size_shift];
2071
2072 if (info.has_user_indices) {
2073 info.index.user = (void*)min_index_ptr;
2074 } else {
2075 if (ctx->pipe->draw_vbo == tc_draw_vbo) {
2076 /* Fast path for u_threaded_context to eliminate atomics. */
2077 info.index.resource = _mesa_get_bufferobj_reference(ctx, index_bo);
2078 info.take_index_buffer_ownership = true;
2079 } else {
2080 info.index.resource = index_bo->buffer;
2081 }
2082
2083 /* No index buffer storage allocated - nothing to do. */
2084 if (!info.index.resource)
2085 return;
2086 }
2087
2088 if (!fallback &&
2089 (!info.has_user_indices ||
2090 /* "max_index_ptr - min_index_ptr >> index_size_shift" is stored
2091 * in draw[i].start. The driver will multiply it later by index_size
2092 * so make sure the final value won't overflow.
2093 *
2094 * For real index buffers, gallium doesn't support index buffer offsets
2095 * greater than UINT32_MAX bytes.
2096 */
2097 max_index_ptr - min_index_ptr <= UINT32_MAX)) {
2098 struct pipe_draw_start_count_bias *draw = get_temp_draws(ctx, primcount);
2099 if (!draw)
2100 return;
2101
2102 if (info.has_user_indices) {
2103 for (int i = 0; i < primcount; i++) {
2104 draw[i].start =
2105 ((uintptr_t)indices[i] - min_index_ptr) >> index_size_shift;
2106 draw[i].count = count[i];
2107 draw[i].index_bias = basevertex ? basevertex[i] : 0;
2108 }
2109 } else {
2110 for (int i = 0; i < primcount; i++) {
2111 draw[i].start = (uintptr_t)indices[i] >> index_size_shift;
2112 draw[i].count =
2113 indices_aligned(index_size_shift, indices[i]) ? count[i] : 0;
2114 draw[i].index_bias = basevertex ? basevertex[i] : 0;
2115 }
2116 }
2117
2118 st_prepare_draw(ctx, ST_PIPELINE_RENDER_STATE_MASK);
2119 if (!validate_index_bounds(ctx, &info, draw, primcount))
2120 return;
2121
2122 ctx->Driver.DrawGallium(ctx, &info, 0, NULL, draw, primcount);
2123 } else {
2124 /* draw[i].start would overflow. Draw one at a time. */
2125 assert(info.has_user_indices);
2126 info.increment_draw_id = false;
2127
2128 st_prepare_draw(ctx, ST_PIPELINE_RENDER_STATE_MASK);
2129
2130 for (int i = 0; i < primcount; i++) {
2131 struct pipe_draw_start_count_bias draw;
2132
2133 if (!count[i])
2134 continue;
2135
2136 /* Reset these, because the callee can change them. */
2137 info.index_bounds_valid = false;
2138 info.index.user = indices[i];
2139 draw.start = 0;
2140 draw.index_bias = basevertex ? basevertex[i] : 0;
2141 draw.count = count[i];
2142
2143 if (!draw.count || !validate_index_bounds(ctx, &info, &draw, 1))
2144 continue;
2145
2146 ctx->Driver.DrawGallium(ctx, &info, i, NULL, &draw, 1);
2147 }
2148 }
2149
2150 if (MESA_DEBUG_FLAGS & DEBUG_ALWAYS_FLUSH) {
2151 _mesa_flush(ctx);
2152 }
2153 }
2154
2155
2156 void GLAPIENTRY
_mesa_MultiDrawElements(GLenum mode,const GLsizei * count,GLenum type,const GLvoid * const * indices,GLsizei primcount)2157 _mesa_MultiDrawElements(GLenum mode, const GLsizei *count, GLenum type,
2158 const GLvoid * const *indices, GLsizei primcount)
2159 {
2160 GET_CURRENT_CONTEXT(ctx);
2161 FLUSH_FOR_DRAW(ctx);
2162
2163 _mesa_set_varying_vp_inputs(ctx, ctx->VertexProgram._VPModeInputFilter &
2164 ctx->Array._DrawVAO->_EnabledWithMapMode);
2165 if (ctx->NewState)
2166 _mesa_update_state(ctx);
2167
2168 struct gl_buffer_object *index_bo = ctx->Array.VAO->IndexBufferObj;
2169
2170 if (!_mesa_is_no_error_enabled(ctx) &&
2171 !_mesa_validate_MultiDrawElements(ctx, mode, count, type, indices,
2172 primcount, index_bo))
2173 return;
2174
2175 _mesa_validated_multidrawelements(ctx, index_bo, mode, count, type,
2176 indices, primcount, NULL);
2177 }
2178
2179
2180 void GLAPIENTRY
_mesa_MultiDrawElementsBaseVertex(GLenum mode,const GLsizei * count,GLenum type,const GLvoid * const * indices,GLsizei primcount,const GLsizei * basevertex)2181 _mesa_MultiDrawElementsBaseVertex(GLenum mode,
2182 const GLsizei *count, GLenum type,
2183 const GLvoid * const *indices,
2184 GLsizei primcount,
2185 const GLsizei *basevertex)
2186 {
2187 GET_CURRENT_CONTEXT(ctx);
2188 FLUSH_FOR_DRAW(ctx);
2189
2190 _mesa_set_varying_vp_inputs(ctx, ctx->VertexProgram._VPModeInputFilter &
2191 ctx->Array._DrawVAO->_EnabledWithMapMode);
2192 if (ctx->NewState)
2193 _mesa_update_state(ctx);
2194
2195 struct gl_buffer_object *index_bo = ctx->Array.VAO->IndexBufferObj;
2196
2197 if (!_mesa_is_no_error_enabled(ctx) &&
2198 !_mesa_validate_MultiDrawElements(ctx, mode, count, type, indices,
2199 primcount, index_bo))
2200 return;
2201
2202 _mesa_validated_multidrawelements(ctx, index_bo, mode, count, type,
2203 indices, primcount, basevertex);
2204 }
2205
2206
2207 /**
2208 * Same as glMultiDrawElementsBaseVertex, but the index buffer is set by
2209 * the indexBuf parameter instead of using the bound GL_ELEMENT_ARRAY_BUFFER
2210 * if indexBuf != NULL.
2211 */
2212 void GLAPIENTRY
_mesa_MultiDrawElementsUserBuf(GLintptr indexBuf,GLenum mode,const GLsizei * count,GLenum type,const GLvoid * const * indices,GLsizei primcount,const GLint * basevertex)2213 _mesa_MultiDrawElementsUserBuf(GLintptr indexBuf, GLenum mode,
2214 const GLsizei *count, GLenum type,
2215 const GLvoid * const * indices,
2216 GLsizei primcount, const GLint * basevertex)
2217 {
2218 GET_CURRENT_CONTEXT(ctx);
2219 FLUSH_FOR_DRAW(ctx);
2220
2221 _mesa_set_varying_vp_inputs(ctx, ctx->VertexProgram._VPModeInputFilter &
2222 ctx->Array._DrawVAO->_EnabledWithMapMode);
2223 if (ctx->NewState)
2224 _mesa_update_state(ctx);
2225
2226 struct gl_buffer_object *index_bo =
2227 indexBuf ? (struct gl_buffer_object*)indexBuf :
2228 ctx->Array.VAO->IndexBufferObj;
2229
2230 if (!_mesa_is_no_error_enabled(ctx) &&
2231 !_mesa_validate_MultiDrawElements(ctx, mode, count, type, indices,
2232 primcount, index_bo))
2233 return;
2234
2235 _mesa_validated_multidrawelements(ctx, index_bo, mode, count, type,
2236 indices, primcount, basevertex);
2237 }
2238
2239
2240 /**
2241 * Like DrawArrays, but take the count from a transform feedback object.
2242 * \param mode GL_POINTS, GL_LINES, GL_TRIANGLE_STRIP, etc.
2243 * \param name the transform feedback object
2244 * User still has to setup of the vertex attribute info with
2245 * glVertexPointer, glColorPointer, etc.
2246 * Part of GL_ARB_transform_feedback2.
2247 */
2248 void GLAPIENTRY
_mesa_DrawTransformFeedback(GLenum mode,GLuint name)2249 _mesa_DrawTransformFeedback(GLenum mode, GLuint name)
2250 {
2251 _mesa_DrawTransformFeedbackStreamInstanced(mode, name, 0, 1);
2252 }
2253
2254
2255 void GLAPIENTRY
_mesa_DrawTransformFeedbackStream(GLenum mode,GLuint name,GLuint stream)2256 _mesa_DrawTransformFeedbackStream(GLenum mode, GLuint name, GLuint stream)
2257 {
2258 _mesa_DrawTransformFeedbackStreamInstanced(mode, name, stream, 1);
2259 }
2260
2261
2262 void GLAPIENTRY
_mesa_DrawTransformFeedbackInstanced(GLenum mode,GLuint name,GLsizei primcount)2263 _mesa_DrawTransformFeedbackInstanced(GLenum mode, GLuint name,
2264 GLsizei primcount)
2265 {
2266 _mesa_DrawTransformFeedbackStreamInstanced(mode, name, 0, primcount);
2267 }
2268
2269
2270 void GLAPIENTRY
_mesa_DrawTransformFeedbackStreamInstanced(GLenum mode,GLuint name,GLuint stream,GLsizei primcount)2271 _mesa_DrawTransformFeedbackStreamInstanced(GLenum mode, GLuint name,
2272 GLuint stream,
2273 GLsizei primcount)
2274 {
2275 GET_CURRENT_CONTEXT(ctx);
2276 struct gl_transform_feedback_object *obj =
2277 _mesa_lookup_transform_feedback_object(ctx, name);
2278
2279 FLUSH_FOR_DRAW(ctx);
2280
2281 _mesa_set_varying_vp_inputs(ctx, ctx->VertexProgram._VPModeInputFilter &
2282 ctx->Array._DrawVAO->_EnabledWithMapMode);
2283 if (ctx->NewState)
2284 _mesa_update_state(ctx);
2285
2286 if (!_mesa_is_no_error_enabled(ctx) &&
2287 !_mesa_validate_DrawTransformFeedback(ctx, mode, obj, stream,
2288 primcount))
2289 return;
2290
2291 st_prepare_draw(ctx, ST_PIPELINE_RENDER_STATE_MASK);
2292
2293 struct pipe_draw_indirect_info indirect;
2294 memset(&indirect, 0, sizeof(indirect));
2295 indirect.count_from_stream_output = obj->draw_count[stream];
2296 if (indirect.count_from_stream_output == NULL)
2297 return;
2298
2299 struct pipe_draw_start_count_bias draw = {0};
2300 struct pipe_draw_info info;
2301 util_draw_init_info(&info);
2302 info.max_index = ~0u; /* so that u_vbuf can tell that it's unknown */
2303 info.mode = mode;
2304 info.instance_count = primcount;
2305
2306 ctx->Driver.DrawGallium(ctx, &info, 0, &indirect, &draw, 1);
2307
2308 if (MESA_DEBUG_FLAGS & DEBUG_ALWAYS_FLUSH) {
2309 _mesa_flush(ctx);
2310 }
2311 }
2312
2313
2314 /**
2315 * Like [Multi]DrawArrays/Elements, but they take most arguments from
2316 * a buffer object.
2317 */
2318 void GLAPIENTRY
_mesa_DrawArraysIndirect(GLenum mode,const GLvoid * indirect)2319 _mesa_DrawArraysIndirect(GLenum mode, const GLvoid *indirect)
2320 {
2321 GET_CURRENT_CONTEXT(ctx);
2322
2323 /* From the ARB_draw_indirect spec:
2324 *
2325 * "Initially zero is bound to DRAW_INDIRECT_BUFFER. In the
2326 * compatibility profile, this indicates that DrawArraysIndirect and
2327 * DrawElementsIndirect are to source their arguments directly from the
2328 * pointer passed as their <indirect> parameters."
2329 */
2330 if (_mesa_is_desktop_gl_compat(ctx) &&
2331 !ctx->DrawIndirectBuffer) {
2332 DrawArraysIndirectCommand *cmd = (DrawArraysIndirectCommand *) indirect;
2333
2334 _mesa_DrawArraysInstancedBaseInstance(mode, cmd->first, cmd->count,
2335 cmd->primCount,
2336 cmd->baseInstance);
2337 return;
2338 }
2339
2340 FLUSH_FOR_DRAW(ctx);
2341
2342 _mesa_set_varying_vp_inputs(ctx, ctx->VertexProgram._VPModeInputFilter &
2343 ctx->Array._DrawVAO->_EnabledWithMapMode);
2344 if (ctx->NewState)
2345 _mesa_update_state(ctx);
2346
2347 if (!_mesa_is_no_error_enabled(ctx) &&
2348 !_mesa_validate_DrawArraysIndirect(ctx, mode, indirect))
2349 return;
2350
2351 st_indirect_draw_vbo(ctx, mode, 0, (GLintptr)indirect, 0, 1, 16);
2352 }
2353
2354
2355 void GLAPIENTRY
_mesa_DrawElementsIndirect(GLenum mode,GLenum type,const GLvoid * indirect)2356 _mesa_DrawElementsIndirect(GLenum mode, GLenum type, const GLvoid *indirect)
2357 {
2358 GET_CURRENT_CONTEXT(ctx);
2359
2360 /* From the ARB_draw_indirect spec:
2361 *
2362 * "Initially zero is bound to DRAW_INDIRECT_BUFFER. In the
2363 * compatibility profile, this indicates that DrawArraysIndirect and
2364 * DrawElementsIndirect are to source their arguments directly from the
2365 * pointer passed as their <indirect> parameters."
2366 */
2367 if (_mesa_is_desktop_gl_compat(ctx) &&
2368 !ctx->DrawIndirectBuffer) {
2369 /*
2370 * Unlike regular DrawElementsInstancedBaseVertex commands, the indices
2371 * may not come from a client array and must come from an index buffer.
2372 * If no element array buffer is bound, an INVALID_OPERATION error is
2373 * generated.
2374 */
2375 if (!ctx->Array.VAO->IndexBufferObj) {
2376 _mesa_error(ctx, GL_INVALID_OPERATION,
2377 "glDrawElementsIndirect(no buffer bound "
2378 "to GL_ELEMENT_ARRAY_BUFFER)");
2379 } else {
2380 DrawElementsIndirectCommand *cmd =
2381 (DrawElementsIndirectCommand *) indirect;
2382
2383 /* Convert offset to pointer */
2384 void *offset = (void *)
2385 (uintptr_t)((cmd->firstIndex * _mesa_sizeof_type(type)) & 0xffffffffUL);
2386
2387 _mesa_DrawElementsInstancedBaseVertexBaseInstance(mode, cmd->count,
2388 type, offset,
2389 cmd->primCount,
2390 cmd->baseVertex,
2391 cmd->baseInstance);
2392 }
2393
2394 return;
2395 }
2396
2397 FLUSH_FOR_DRAW(ctx);
2398
2399 _mesa_set_varying_vp_inputs(ctx, ctx->VertexProgram._VPModeInputFilter &
2400 ctx->Array._DrawVAO->_EnabledWithMapMode);
2401 if (ctx->NewState)
2402 _mesa_update_state(ctx);
2403
2404 if (!_mesa_is_no_error_enabled(ctx) &&
2405 !_mesa_validate_DrawElementsIndirect(ctx, mode, type, indirect))
2406 return;
2407
2408 st_indirect_draw_vbo(ctx, mode, type, (GLintptr)indirect, 0, 1, 20);
2409 }
2410
2411
2412 void GLAPIENTRY
_mesa_MultiDrawArraysIndirect(GLenum mode,const GLvoid * indirect,GLsizei primcount,GLsizei stride)2413 _mesa_MultiDrawArraysIndirect(GLenum mode, const GLvoid *indirect,
2414 GLsizei primcount, GLsizei stride)
2415 {
2416 GET_CURRENT_CONTEXT(ctx);
2417
2418 /* If <stride> is zero, the array elements are treated as tightly packed. */
2419 if (stride == 0)
2420 stride = sizeof(DrawArraysIndirectCommand);
2421
2422 FLUSH_FOR_DRAW(ctx);
2423
2424 _mesa_set_varying_vp_inputs(ctx, ctx->VertexProgram._VPModeInputFilter &
2425 ctx->Array._DrawVAO->_EnabledWithMapMode);
2426 if (ctx->NewState)
2427 _mesa_update_state(ctx);
2428
2429 /* From the ARB_draw_indirect spec:
2430 *
2431 * "Initially zero is bound to DRAW_INDIRECT_BUFFER. In the
2432 * compatibility profile, this indicates that DrawArraysIndirect and
2433 * DrawElementsIndirect are to source their arguments directly from the
2434 * pointer passed as their <indirect> parameters."
2435 */
2436 if (_mesa_is_desktop_gl_compat(ctx) &&
2437 !ctx->DrawIndirectBuffer) {
2438
2439 if (!_mesa_is_no_error_enabled(ctx) &&
2440 (!_mesa_valid_draw_indirect_multi(ctx, primcount, stride,
2441 "glMultiDrawArraysIndirect") ||
2442 !_mesa_validate_DrawArrays(ctx, mode, 1)))
2443 return;
2444
2445 struct pipe_draw_info info;
2446 info.mode = mode;
2447 info.index_size = 0;
2448 /* Packed section begin. */
2449 info.primitive_restart = false;
2450 info.has_user_indices = false;
2451 info.index_bounds_valid = false;
2452 info.increment_draw_id = primcount > 1;
2453 info.was_line_loop = false;
2454 info.take_index_buffer_ownership = false;
2455 info.index_bias_varies = false;
2456 /* Packed section end. */
2457
2458 st_prepare_draw(ctx, ST_PIPELINE_RENDER_STATE_MASK);
2459
2460 const uint8_t *ptr = (const uint8_t *) indirect;
2461 for (unsigned i = 0; i < primcount; i++) {
2462 DrawArraysIndirectCommand *cmd = (DrawArraysIndirectCommand *) ptr;
2463
2464 info.start_instance = cmd->baseInstance;
2465 info.instance_count = cmd->primCount;
2466
2467 struct pipe_draw_start_count_bias draw;
2468 draw.start = cmd->first;
2469 draw.count = cmd->count;
2470
2471 if (!draw.count)
2472 continue;
2473
2474 ctx->Driver.DrawGallium(ctx, &info, i, NULL, &draw, 1);
2475 ptr += stride;
2476 }
2477
2478 return;
2479 }
2480
2481 if (!_mesa_is_no_error_enabled(ctx) &&
2482 !_mesa_validate_MultiDrawArraysIndirect(ctx, mode, indirect,
2483 primcount, stride))
2484 return;
2485
2486 st_indirect_draw_vbo(ctx, mode, 0, (GLintptr)indirect, 0, primcount, stride);
2487 }
2488
2489
2490 void GLAPIENTRY
_mesa_MultiDrawElementsIndirect(GLenum mode,GLenum type,const GLvoid * indirect,GLsizei primcount,GLsizei stride)2491 _mesa_MultiDrawElementsIndirect(GLenum mode, GLenum type,
2492 const GLvoid *indirect,
2493 GLsizei primcount, GLsizei stride)
2494 {
2495 GET_CURRENT_CONTEXT(ctx);
2496
2497 FLUSH_FOR_DRAW(ctx);
2498
2499 _mesa_set_varying_vp_inputs(ctx, ctx->VertexProgram._VPModeInputFilter &
2500 ctx->Array._DrawVAO->_EnabledWithMapMode);
2501 if (ctx->NewState)
2502 _mesa_update_state(ctx);
2503
2504 /* If <stride> is zero, the array elements are treated as tightly packed. */
2505 if (stride == 0)
2506 stride = sizeof(DrawElementsIndirectCommand);
2507
2508 /* From the ARB_draw_indirect spec:
2509 *
2510 * "Initially zero is bound to DRAW_INDIRECT_BUFFER. In the
2511 * compatibility profile, this indicates that DrawArraysIndirect and
2512 * DrawElementsIndirect are to source their arguments directly from the
2513 * pointer passed as their <indirect> parameters."
2514 */
2515 if (_mesa_is_desktop_gl_compat(ctx) &&
2516 !ctx->DrawIndirectBuffer) {
2517 /*
2518 * Unlike regular DrawElementsInstancedBaseVertex commands, the indices
2519 * may not come from a client array and must come from an index buffer.
2520 * If no element array buffer is bound, an INVALID_OPERATION error is
2521 * generated.
2522 */
2523 if (!ctx->Array.VAO->IndexBufferObj) {
2524 _mesa_error(ctx, GL_INVALID_OPERATION,
2525 "glMultiDrawElementsIndirect(no buffer bound "
2526 "to GL_ELEMENT_ARRAY_BUFFER)");
2527
2528 return;
2529 }
2530
2531 if (!_mesa_is_no_error_enabled(ctx) &&
2532 (!_mesa_valid_draw_indirect_multi(ctx, primcount, stride,
2533 "glMultiDrawArraysIndirect") ||
2534 !_mesa_validate_DrawElements(ctx, mode, 1, type)))
2535 return;
2536
2537 unsigned index_size_shift = _mesa_get_index_size_shift(type);
2538
2539 struct pipe_draw_info info;
2540 info.mode = mode;
2541 info.index_size = 1 << index_size_shift;
2542 /* Packed section begin. */
2543 info.primitive_restart = ctx->Array._PrimitiveRestart[index_size_shift];
2544 info.has_user_indices = false;
2545 info.index_bounds_valid = false;
2546 info.increment_draw_id = primcount > 1;
2547 info.was_line_loop = false;
2548 info.take_index_buffer_ownership = false;
2549 info.index_bias_varies = false;
2550 /* Packed section end. */
2551 info.restart_index = ctx->Array._RestartIndex[index_size_shift];
2552
2553 struct gl_buffer_object *index_bo = ctx->Array.VAO->IndexBufferObj;
2554
2555 if (ctx->pipe->draw_vbo == tc_draw_vbo) {
2556 /* Fast path for u_threaded_context to eliminate atomics. */
2557 info.index.resource = _mesa_get_bufferobj_reference(ctx, index_bo);
2558 info.take_index_buffer_ownership = true;
2559 /* Increase refcount so be able to use take_index_buffer_ownership with
2560 * multiple draws.
2561 */
2562 if (primcount > 1 && info.index.resource)
2563 p_atomic_add(&info.index.resource->reference.count, primcount - 1);
2564 } else {
2565 info.index.resource = index_bo->buffer;
2566 }
2567
2568 /* No index buffer storage allocated - nothing to do. */
2569 if (!info.index.resource)
2570 return;
2571
2572 st_prepare_draw(ctx, ST_PIPELINE_RENDER_STATE_MASK);
2573
2574 const uint8_t *ptr = (const uint8_t *) indirect;
2575 for (unsigned i = 0; i < primcount; i++) {
2576 DrawElementsIndirectCommand *cmd = (DrawElementsIndirectCommand*)ptr;
2577
2578 info.start_instance = cmd->baseInstance;
2579 info.instance_count = cmd->primCount;
2580
2581 struct pipe_draw_start_count_bias draw;
2582 draw.start = cmd->firstIndex;
2583 draw.count = cmd->count;
2584 draw.index_bias = cmd->baseVertex;
2585
2586 if (!draw.count || !validate_index_bounds(ctx, &info, &draw, 1))
2587 continue;
2588
2589 ctx->Driver.DrawGallium(ctx, &info, i, NULL, &draw, 1);
2590 ptr += stride;
2591 }
2592
2593 return;
2594 }
2595
2596 if (!_mesa_is_no_error_enabled(ctx) &&
2597 !_mesa_validate_MultiDrawElementsIndirect(ctx, mode, type, indirect,
2598 primcount, stride))
2599 return;
2600
2601 st_indirect_draw_vbo(ctx, mode, type, (GLintptr)indirect, 0, primcount, stride);
2602 }
2603
2604
2605 void GLAPIENTRY
_mesa_MultiDrawArraysIndirectCountARB(GLenum mode,GLintptr indirect,GLintptr drawcount_offset,GLsizei maxdrawcount,GLsizei stride)2606 _mesa_MultiDrawArraysIndirectCountARB(GLenum mode, GLintptr indirect,
2607 GLintptr drawcount_offset,
2608 GLsizei maxdrawcount, GLsizei stride)
2609 {
2610 GET_CURRENT_CONTEXT(ctx);
2611 FLUSH_FOR_DRAW(ctx);
2612
2613 /* If <stride> is zero, the array elements are treated as tightly packed. */
2614 if (stride == 0)
2615 stride = 4 * sizeof(GLuint); /* sizeof(DrawArraysIndirectCommand) */
2616
2617 _mesa_set_varying_vp_inputs(ctx, ctx->VertexProgram._VPModeInputFilter &
2618 ctx->Array._DrawVAO->_EnabledWithMapMode);
2619 if (ctx->NewState)
2620 _mesa_update_state(ctx);
2621
2622 if (!_mesa_is_no_error_enabled(ctx) &&
2623 !_mesa_validate_MultiDrawArraysIndirectCount(ctx, mode, indirect,
2624 drawcount_offset,
2625 maxdrawcount, stride))
2626 return;
2627
2628 st_indirect_draw_vbo(ctx, mode, 0, (GLintptr)indirect, drawcount_offset,
2629 maxdrawcount, stride);
2630 }
2631
2632
2633 void GLAPIENTRY
_mesa_MultiDrawElementsIndirectCountARB(GLenum mode,GLenum type,GLintptr indirect,GLintptr drawcount_offset,GLsizei maxdrawcount,GLsizei stride)2634 _mesa_MultiDrawElementsIndirectCountARB(GLenum mode, GLenum type,
2635 GLintptr indirect,
2636 GLintptr drawcount_offset,
2637 GLsizei maxdrawcount, GLsizei stride)
2638 {
2639 GET_CURRENT_CONTEXT(ctx);
2640 FLUSH_FOR_DRAW(ctx);
2641
2642 /* If <stride> is zero, the array elements are treated as tightly packed. */
2643 if (stride == 0)
2644 stride = 5 * sizeof(GLuint); /* sizeof(DrawElementsIndirectCommand) */
2645
2646 _mesa_set_varying_vp_inputs(ctx, ctx->VertexProgram._VPModeInputFilter &
2647 ctx->Array._DrawVAO->_EnabledWithMapMode);
2648 if (ctx->NewState)
2649 _mesa_update_state(ctx);
2650
2651 if (!_mesa_is_no_error_enabled(ctx) &&
2652 !_mesa_validate_MultiDrawElementsIndirectCount(ctx, mode, type,
2653 indirect,
2654 drawcount_offset,
2655 maxdrawcount, stride))
2656 return;
2657
2658 st_indirect_draw_vbo(ctx, mode, type, (GLintptr)indirect, drawcount_offset,
2659 maxdrawcount, stride);
2660 }
2661
2662
2663 /* GL_IBM_multimode_draw_arrays */
2664 void GLAPIENTRY
_mesa_MultiModeDrawArraysIBM(const GLenum * mode,const GLint * first,const GLsizei * count,GLsizei primcount,GLint modestride)2665 _mesa_MultiModeDrawArraysIBM( const GLenum * mode, const GLint * first,
2666 const GLsizei * count,
2667 GLsizei primcount, GLint modestride )
2668 {
2669 GET_CURRENT_CONTEXT(ctx);
2670 GLint i;
2671
2672 for ( i = 0 ; i < primcount ; i++ ) {
2673 if ( count[i] > 0 ) {
2674 GLenum m = *((GLenum *) ((GLubyte *) mode + i * modestride));
2675 CALL_DrawArrays(ctx->Dispatch.Current, ( m, first[i], count[i] ));
2676 }
2677 }
2678 }
2679
2680
2681 /* GL_IBM_multimode_draw_arrays */
2682 void GLAPIENTRY
_mesa_MultiModeDrawElementsIBM(const GLenum * mode,const GLsizei * count,GLenum type,const GLvoid * const * indices,GLsizei primcount,GLint modestride)2683 _mesa_MultiModeDrawElementsIBM( const GLenum * mode, const GLsizei * count,
2684 GLenum type, const GLvoid * const * indices,
2685 GLsizei primcount, GLint modestride )
2686 {
2687 GET_CURRENT_CONTEXT(ctx);
2688 GLint i;
2689
2690 for ( i = 0 ; i < primcount ; i++ ) {
2691 if ( count[i] > 0 ) {
2692 GLenum m = *((GLenum *) ((GLubyte *) mode + i * modestride));
2693 CALL_DrawElements(ctx->Dispatch.Current, ( m, count[i], type,
2694 indices[i] ));
2695 }
2696 }
2697 }
2698