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