mesa: remove outdated version lines in comments
[mesa.git] / src / mesa / main / api_validate.c
1 /*
2 * Mesa 3-D graphics library
3 *
4 * Copyright (C) 1999-2007 Brian Paul All Rights Reserved.
5 *
6 * Permission is hereby granted, free of charge, to any person obtaining a
7 * copy of this software and associated documentation files (the "Software"),
8 * to deal in the Software without restriction, including without limitation
9 * the rights to use, copy, modify, merge, publish, distribute, sublicense,
10 * and/or sell copies of the Software, and to permit persons to whom the
11 * Software is furnished to do so, subject to the following conditions:
12 *
13 * The above copyright notice and this permission notice shall be included
14 * in all copies or substantial portions of the Software.
15 *
16 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
17 * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
18 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
19 * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR
20 * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
21 * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
22 * OTHER DEALINGS IN THE SOFTWARE.
23 */
24
25 #include <stdbool.h>
26 #include "glheader.h"
27 #include "api_validate.h"
28 #include "bufferobj.h"
29 #include "context.h"
30 #include "imports.h"
31 #include "mtypes.h"
32 #include "enums.h"
33 #include "vbo/vbo.h"
34 #include "transformfeedback.h"
35 #include <stdbool.h>
36
37
38 /**
39 * \return number of bytes in array [count] of type.
40 */
41 static GLsizei
42 index_bytes(GLenum type, GLsizei count)
43 {
44 if (type == GL_UNSIGNED_INT) {
45 return count * sizeof(GLuint);
46 }
47 else if (type == GL_UNSIGNED_BYTE) {
48 return count * sizeof(GLubyte);
49 }
50 else {
51 ASSERT(type == GL_UNSIGNED_SHORT);
52 return count * sizeof(GLushort);
53 }
54 }
55
56
57 /**
58 * Find the max index in the given element/index buffer
59 */
60 GLuint
61 _mesa_max_buffer_index(struct gl_context *ctx, GLuint count, GLenum type,
62 const void *indices,
63 struct gl_buffer_object *elementBuf)
64 {
65 const GLubyte *map = NULL;
66 GLuint max = 0;
67 GLuint i;
68
69 if (_mesa_is_bufferobj(elementBuf)) {
70 /* elements are in a user-defined buffer object. need to map it */
71 map = ctx->Driver.MapBufferRange(ctx, 0, elementBuf->Size,
72 GL_MAP_READ_BIT, elementBuf);
73 /* Actual address is the sum of pointers */
74 indices = (const GLvoid *) ADD_POINTERS(map, (const GLubyte *) indices);
75 }
76
77 if (type == GL_UNSIGNED_INT) {
78 for (i = 0; i < count; i++)
79 if (((GLuint *) indices)[i] > max)
80 max = ((GLuint *) indices)[i];
81 }
82 else if (type == GL_UNSIGNED_SHORT) {
83 for (i = 0; i < count; i++)
84 if (((GLushort *) indices)[i] > max)
85 max = ((GLushort *) indices)[i];
86 }
87 else {
88 ASSERT(type == GL_UNSIGNED_BYTE);
89 for (i = 0; i < count; i++)
90 if (((GLubyte *) indices)[i] > max)
91 max = ((GLubyte *) indices)[i];
92 }
93
94 if (map) {
95 ctx->Driver.UnmapBuffer(ctx, elementBuf);
96 }
97
98 return max;
99 }
100
101
102 /**
103 * Check if OK to draw arrays/elements.
104 */
105 static GLboolean
106 check_valid_to_render(struct gl_context *ctx, const char *function)
107 {
108 if (!_mesa_valid_to_render(ctx, function)) {
109 return GL_FALSE;
110 }
111
112 switch (ctx->API) {
113 case API_OPENGLES2:
114 /* For ES2, we can draw if any vertex array is enabled (and we
115 * should always have a vertex program/shader). */
116 if (ctx->Array.ArrayObj->_Enabled == 0x0 || !ctx->VertexProgram._Current)
117 return GL_FALSE;
118 break;
119
120 case API_OPENGLES:
121 /* For OpenGL ES, only draw if we have vertex positions
122 */
123 if (!ctx->Array.ArrayObj->VertexAttrib[VERT_ATTRIB_POS].Enabled)
124 return GL_FALSE;
125 break;
126
127 case API_OPENGL_COMPAT:
128 case API_OPENGL_CORE:
129 {
130 const struct gl_shader_program *vsProg =
131 ctx->Shader.CurrentVertexProgram;
132 GLboolean haveVertexShader = (vsProg && vsProg->LinkStatus);
133 GLboolean haveVertexProgram = ctx->VertexProgram._Enabled;
134 if (haveVertexShader || haveVertexProgram) {
135 /* Draw regardless of whether or not we have any vertex arrays.
136 * (Ex: could draw a point using a constant vertex pos)
137 */
138 return GL_TRUE;
139 }
140 else {
141 /* Draw if we have vertex positions (GL_VERTEX_ARRAY or generic
142 * array [0]).
143 */
144 return (ctx->Array.ArrayObj->VertexAttrib[VERT_ATTRIB_POS].Enabled ||
145 ctx->Array.ArrayObj->VertexAttrib[VERT_ATTRIB_GENERIC0].Enabled);
146 }
147 }
148 break;
149
150 default:
151 assert(!"Invalid API value in check_valid_to_render()");
152 }
153
154 return GL_TRUE;
155 }
156
157
158 /**
159 * Do bounds checking on array element indexes. Check that the vertices
160 * pointed to by the indices don't lie outside buffer object bounds.
161 * \return GL_TRUE if OK, GL_FALSE if any indexed vertex goes is out of bounds
162 */
163 static GLboolean
164 check_index_bounds(struct gl_context *ctx, GLsizei count, GLenum type,
165 const GLvoid *indices, GLint basevertex)
166 {
167 struct _mesa_prim prim;
168 struct _mesa_index_buffer ib;
169 GLuint min, max;
170
171 /* Only the X Server needs to do this -- otherwise, accessing outside
172 * array/BO bounds allows application termination.
173 */
174 if (!ctx->Const.CheckArrayBounds)
175 return GL_TRUE;
176
177 memset(&prim, 0, sizeof(prim));
178 prim.count = count;
179
180 memset(&ib, 0, sizeof(ib));
181 ib.type = type;
182 ib.ptr = indices;
183 ib.obj = ctx->Array.ArrayObj->ElementArrayBufferObj;
184
185 vbo_get_minmax_indices(ctx, &prim, &ib, &min, &max, 1);
186
187 if ((int)(min + basevertex) < 0 ||
188 max + basevertex >= ctx->Array.ArrayObj->_MaxElement) {
189 /* the max element is out of bounds of one or more enabled arrays */
190 _mesa_warning(ctx, "glDrawElements() index=%u is out of bounds (max=%u)",
191 max, ctx->Array.ArrayObj->_MaxElement);
192 return GL_FALSE;
193 }
194
195 return GL_TRUE;
196 }
197
198
199 /**
200 * Is 'mode' a valid value for glBegin(), glDrawArrays(), glDrawElements(),
201 * etc? The set of legal values depends on whether geometry shaders/programs
202 * are supported.
203 * Note: This may be called during display list compilation.
204 */
205 bool
206 _mesa_is_valid_prim_mode(struct gl_context *ctx, GLenum mode)
207 {
208 switch (mode) {
209 case GL_POINTS:
210 case GL_LINES:
211 case GL_LINE_LOOP:
212 case GL_LINE_STRIP:
213 case GL_TRIANGLES:
214 case GL_TRIANGLE_STRIP:
215 case GL_TRIANGLE_FAN:
216 return true;
217 case GL_QUADS:
218 case GL_QUAD_STRIP:
219 case GL_POLYGON:
220 return (ctx->API == API_OPENGL_COMPAT);
221 case GL_LINES_ADJACENCY:
222 case GL_LINE_STRIP_ADJACENCY:
223 case GL_TRIANGLES_ADJACENCY:
224 case GL_TRIANGLE_STRIP_ADJACENCY:
225 return _mesa_is_desktop_gl(ctx) && ctx->Extensions.ARB_geometry_shader4;
226 default:
227 return false;
228 }
229 }
230
231
232 /**
233 * Is 'mode' a valid value for glBegin(), glDrawArrays(), glDrawElements(),
234 * etc? Also, do additional checking related to transformation feedback.
235 * Note: this function cannot be called during glNewList(GL_COMPILE) because
236 * this code depends on current transform feedback state.
237 */
238 GLboolean
239 _mesa_valid_prim_mode(struct gl_context *ctx, GLenum mode, const char *name)
240 {
241 bool valid_enum = _mesa_is_valid_prim_mode(ctx, mode);
242
243 if (!valid_enum) {
244 _mesa_error(ctx, GL_INVALID_ENUM, "%s(mode=%x)", name, mode);
245 return GL_FALSE;
246 }
247
248 /* From the GL_EXT_transform_feedback spec:
249 *
250 * "The error INVALID_OPERATION is generated if Begin, or any command
251 * that performs an explicit Begin, is called when:
252 *
253 * * a geometry shader is not active and <mode> does not match the
254 * allowed begin modes for the current transform feedback state as
255 * given by table X.1.
256 *
257 * * a geometry shader is active and the output primitive type of the
258 * geometry shader does not match the allowed begin modes for the
259 * current transform feedback state as given by table X.1.
260 *
261 */
262 if (_mesa_is_xfb_active_and_unpaused(ctx)) {
263 GLboolean pass = GL_TRUE;
264
265 switch (mode) {
266 case GL_POINTS:
267 pass = ctx->TransformFeedback.Mode == GL_POINTS;
268 break;
269 case GL_LINES:
270 case GL_LINE_STRIP:
271 case GL_LINE_LOOP:
272 pass = ctx->TransformFeedback.Mode == GL_LINES;
273 break;
274 default:
275 pass = ctx->TransformFeedback.Mode == GL_TRIANGLES;
276 break;
277 }
278 if (!pass) {
279 _mesa_error(ctx, GL_INVALID_OPERATION,
280 "%s(mode=%s vs transform feedback %s)",
281 name,
282 _mesa_lookup_prim_by_nr(mode),
283 _mesa_lookup_prim_by_nr(ctx->TransformFeedback.Mode));
284 return GL_FALSE;
285 }
286 }
287
288 return GL_TRUE;
289 }
290
291 /**
292 * Verify that the element type is valid.
293 *
294 * Generates \c GL_INVALID_ENUM and returns \c false if it is not.
295 */
296 static bool
297 valid_elements_type(struct gl_context *ctx, GLenum type, const char *name)
298 {
299 switch (type) {
300 case GL_UNSIGNED_BYTE:
301 case GL_UNSIGNED_SHORT:
302 case GL_UNSIGNED_INT:
303 return true;
304
305 default:
306 _mesa_error(ctx, GL_INVALID_ENUM, "%s(type = %s)", name,
307 _mesa_lookup_enum_by_nr(type));
308 return false;
309 }
310 }
311
312 /**
313 * Error checking for glDrawElements(). Includes parameter checking
314 * and VBO bounds checking.
315 * \return GL_TRUE if OK to render, GL_FALSE if error found
316 */
317 GLboolean
318 _mesa_validate_DrawElements(struct gl_context *ctx,
319 GLenum mode, GLsizei count, GLenum type,
320 const GLvoid *indices, GLint basevertex)
321 {
322 FLUSH_CURRENT(ctx, 0);
323
324 /* From the GLES3 specification, section 2.14.2 (Transform Feedback
325 * Primitive Capture):
326 *
327 * The error INVALID_OPERATION is also generated by DrawElements,
328 * DrawElementsInstanced, and DrawRangeElements while transform feedback
329 * is active and not paused, regardless of mode.
330 */
331 if (_mesa_is_gles3(ctx) && _mesa_is_xfb_active_and_unpaused(ctx)) {
332 _mesa_error(ctx, GL_INVALID_OPERATION,
333 "glDrawElements(transform feedback active)");
334 return GL_FALSE;
335 }
336
337 if (count <= 0) {
338 if (count < 0)
339 _mesa_error(ctx, GL_INVALID_VALUE, "glDrawElements(count)" );
340 return GL_FALSE;
341 }
342
343 if (!_mesa_valid_prim_mode(ctx, mode, "glDrawElements")) {
344 return GL_FALSE;
345 }
346
347 if (!valid_elements_type(ctx, type, "glDrawElements"))
348 return GL_FALSE;
349
350 if (!check_valid_to_render(ctx, "glDrawElements"))
351 return GL_FALSE;
352
353 /* Vertex buffer object tests */
354 if (_mesa_is_bufferobj(ctx->Array.ArrayObj->ElementArrayBufferObj)) {
355 /* use indices in the buffer object */
356 /* make sure count doesn't go outside buffer bounds */
357 if (index_bytes(type, count) > ctx->Array.ArrayObj->ElementArrayBufferObj->Size) {
358 _mesa_warning(ctx, "glDrawElements index out of buffer bounds");
359 return GL_FALSE;
360 }
361 }
362 else {
363 /* not using a VBO */
364 if (!indices)
365 return GL_FALSE;
366 }
367
368 if (!check_index_bounds(ctx, count, type, indices, basevertex))
369 return GL_FALSE;
370
371 return GL_TRUE;
372 }
373
374
375 /**
376 * Error checking for glMultiDrawElements(). Includes parameter checking
377 * and VBO bounds checking.
378 * \return GL_TRUE if OK to render, GL_FALSE if error found
379 */
380 GLboolean
381 _mesa_validate_MultiDrawElements(struct gl_context *ctx,
382 GLenum mode, const GLsizei *count,
383 GLenum type, const GLvoid * const *indices,
384 GLuint primcount, const GLint *basevertex)
385 {
386 unsigned i;
387
388 FLUSH_CURRENT(ctx, 0);
389
390 for (i = 0; i < primcount; i++) {
391 if (count[i] <= 0) {
392 if (count[i] < 0)
393 _mesa_error(ctx, GL_INVALID_VALUE,
394 "glMultiDrawElements(count)" );
395 return GL_FALSE;
396 }
397 }
398
399 if (!_mesa_valid_prim_mode(ctx, mode, "glMultiDrawElements")) {
400 return GL_FALSE;
401 }
402
403 if (!valid_elements_type(ctx, type, "glMultiDrawElements"))
404 return GL_FALSE;
405
406 if (!check_valid_to_render(ctx, "glMultiDrawElements"))
407 return GL_FALSE;
408
409 /* Vertex buffer object tests */
410 if (_mesa_is_bufferobj(ctx->Array.ArrayObj->ElementArrayBufferObj)) {
411 /* use indices in the buffer object */
412 /* make sure count doesn't go outside buffer bounds */
413 for (i = 0; i < primcount; i++) {
414 if (index_bytes(type, count[i]) >
415 ctx->Array.ArrayObj->ElementArrayBufferObj->Size) {
416 _mesa_warning(ctx,
417 "glMultiDrawElements index out of buffer bounds");
418 return GL_FALSE;
419 }
420 }
421 }
422 else {
423 /* not using a VBO */
424 for (i = 0; i < primcount; i++) {
425 if (!indices[i])
426 return GL_FALSE;
427 }
428 }
429
430 for (i = 0; i < primcount; i++) {
431 if (!check_index_bounds(ctx, count[i], type, indices[i],
432 basevertex ? basevertex[i] : 0))
433 return GL_FALSE;
434 }
435
436 return GL_TRUE;
437 }
438
439
440 /**
441 * Error checking for glDrawRangeElements(). Includes parameter checking
442 * and VBO bounds checking.
443 * \return GL_TRUE if OK to render, GL_FALSE if error found
444 */
445 GLboolean
446 _mesa_validate_DrawRangeElements(struct gl_context *ctx, GLenum mode,
447 GLuint start, GLuint end,
448 GLsizei count, GLenum type,
449 const GLvoid *indices, GLint basevertex)
450 {
451 FLUSH_CURRENT(ctx, 0);
452
453 /* From the GLES3 specification, section 2.14.2 (Transform Feedback
454 * Primitive Capture):
455 *
456 * The error INVALID_OPERATION is also generated by DrawElements,
457 * DrawElementsInstanced, and DrawRangeElements while transform feedback
458 * is active and not paused, regardless of mode.
459 */
460 if (_mesa_is_gles3(ctx) && _mesa_is_xfb_active_and_unpaused(ctx)) {
461 _mesa_error(ctx, GL_INVALID_OPERATION,
462 "glDrawElements(transform feedback active)");
463 return GL_FALSE;
464 }
465
466 if (count <= 0) {
467 if (count < 0)
468 _mesa_error(ctx, GL_INVALID_VALUE, "glDrawRangeElements(count)" );
469 return GL_FALSE;
470 }
471
472 if (!_mesa_valid_prim_mode(ctx, mode, "glDrawRangeElements")) {
473 return GL_FALSE;
474 }
475
476 if (end < start) {
477 _mesa_error(ctx, GL_INVALID_VALUE, "glDrawRangeElements(end<start)");
478 return GL_FALSE;
479 }
480
481 if (!valid_elements_type(ctx, type, "glDrawRangeElements"))
482 return GL_FALSE;
483
484 if (!check_valid_to_render(ctx, "glDrawRangeElements"))
485 return GL_FALSE;
486
487 /* Vertex buffer object tests */
488 if (_mesa_is_bufferobj(ctx->Array.ArrayObj->ElementArrayBufferObj)) {
489 /* use indices in the buffer object */
490 /* make sure count doesn't go outside buffer bounds */
491 if (index_bytes(type, count) > ctx->Array.ArrayObj->ElementArrayBufferObj->Size) {
492 _mesa_warning(ctx, "glDrawRangeElements index out of buffer bounds");
493 return GL_FALSE;
494 }
495 }
496 else {
497 /* not using a VBO */
498 if (!indices)
499 return GL_FALSE;
500 }
501
502 if (!check_index_bounds(ctx, count, type, indices, basevertex))
503 return GL_FALSE;
504
505 return GL_TRUE;
506 }
507
508
509 /**
510 * Called from the tnl module to error check the function parameters and
511 * verify that we really can draw something.
512 * \return GL_TRUE if OK to render, GL_FALSE if error found
513 */
514 GLboolean
515 _mesa_validate_DrawArrays(struct gl_context *ctx,
516 GLenum mode, GLint start, GLsizei count)
517 {
518 struct gl_transform_feedback_object *xfb_obj
519 = ctx->TransformFeedback.CurrentObject;
520 FLUSH_CURRENT(ctx, 0);
521
522 if (count <= 0) {
523 if (count < 0)
524 _mesa_error(ctx, GL_INVALID_VALUE, "glDrawArrays(count)" );
525 return GL_FALSE;
526 }
527
528 if (!_mesa_valid_prim_mode(ctx, mode, "glDrawArrays")) {
529 return GL_FALSE;
530 }
531
532 if (!check_valid_to_render(ctx, "glDrawArrays"))
533 return GL_FALSE;
534
535 if (ctx->Const.CheckArrayBounds) {
536 if (start + count > (GLint) ctx->Array.ArrayObj->_MaxElement)
537 return GL_FALSE;
538 }
539
540 /* From the GLES3 specification, section 2.14.2 (Transform Feedback
541 * Primitive Capture):
542 *
543 * The error INVALID_OPERATION is generated by DrawArrays and
544 * DrawArraysInstanced if recording the vertices of a primitive to the
545 * buffer objects being used for transform feedback purposes would result
546 * in either exceeding the limits of any buffer object’s size, or in
547 * exceeding the end position offset + size − 1, as set by
548 * BindBufferRange.
549 *
550 * This is in contrast to the behaviour of desktop GL, where the extra
551 * primitives are silently dropped from the transform feedback buffer.
552 */
553 if (_mesa_is_gles3(ctx) && _mesa_is_xfb_active_and_unpaused(ctx)) {
554 size_t prim_count = vbo_count_tessellated_primitives(mode, count, 1);
555 if (xfb_obj->GlesRemainingPrims < prim_count) {
556 _mesa_error(ctx, GL_INVALID_OPERATION,
557 "glDrawArrays(exceeds transform feedback size)");
558 return GL_FALSE;
559 }
560 xfb_obj->GlesRemainingPrims -= prim_count;
561 }
562
563 return GL_TRUE;
564 }
565
566
567 GLboolean
568 _mesa_validate_DrawArraysInstanced(struct gl_context *ctx, GLenum mode, GLint first,
569 GLsizei count, GLsizei numInstances)
570 {
571 struct gl_transform_feedback_object *xfb_obj
572 = ctx->TransformFeedback.CurrentObject;
573 FLUSH_CURRENT(ctx, 0);
574
575 if (count <= 0) {
576 if (count < 0)
577 _mesa_error(ctx, GL_INVALID_VALUE,
578 "glDrawArraysInstanced(count=%d)", count);
579 return GL_FALSE;
580 }
581
582 if (first < 0) {
583 _mesa_error(ctx, GL_INVALID_VALUE,
584 "glDrawArraysInstanced(start=%d)", first);
585 return GL_FALSE;
586 }
587
588 if (!_mesa_valid_prim_mode(ctx, mode, "glDrawArraysInstanced")) {
589 return GL_FALSE;
590 }
591
592 if (numInstances <= 0) {
593 if (numInstances < 0)
594 _mesa_error(ctx, GL_INVALID_VALUE,
595 "glDrawArraysInstanced(numInstances=%d)", numInstances);
596 return GL_FALSE;
597 }
598
599 if (!check_valid_to_render(ctx, "glDrawArraysInstanced(invalid to render)"))
600 return GL_FALSE;
601
602 if (ctx->Const.CheckArrayBounds) {
603 if (first + count > (GLint) ctx->Array.ArrayObj->_MaxElement)
604 return GL_FALSE;
605 }
606
607 /* From the GLES3 specification, section 2.14.2 (Transform Feedback
608 * Primitive Capture):
609 *
610 * The error INVALID_OPERATION is generated by DrawArrays and
611 * DrawArraysInstanced if recording the vertices of a primitive to the
612 * buffer objects being used for transform feedback purposes would result
613 * in either exceeding the limits of any buffer object’s size, or in
614 * exceeding the end position offset + size − 1, as set by
615 * BindBufferRange.
616 *
617 * This is in contrast to the behaviour of desktop GL, where the extra
618 * primitives are silently dropped from the transform feedback buffer.
619 */
620 if (_mesa_is_gles3(ctx) && _mesa_is_xfb_active_and_unpaused(ctx)) {
621 size_t prim_count
622 = vbo_count_tessellated_primitives(mode, count, numInstances);
623 if (xfb_obj->GlesRemainingPrims < prim_count) {
624 _mesa_error(ctx, GL_INVALID_OPERATION,
625 "glDrawArraysInstanced(exceeds transform feedback size)");
626 return GL_FALSE;
627 }
628 xfb_obj->GlesRemainingPrims -= prim_count;
629 }
630
631 return GL_TRUE;
632 }
633
634
635 GLboolean
636 _mesa_validate_DrawElementsInstanced(struct gl_context *ctx,
637 GLenum mode, GLsizei count, GLenum type,
638 const GLvoid *indices, GLsizei numInstances,
639 GLint basevertex)
640 {
641 FLUSH_CURRENT(ctx, 0);
642
643 /* From the GLES3 specification, section 2.14.2 (Transform Feedback
644 * Primitive Capture):
645 *
646 * The error INVALID_OPERATION is also generated by DrawElements,
647 * DrawElementsInstanced, and DrawRangeElements while transform feedback
648 * is active and not paused, regardless of mode.
649 */
650 if (_mesa_is_gles3(ctx) && _mesa_is_xfb_active_and_unpaused(ctx)) {
651 _mesa_error(ctx, GL_INVALID_OPERATION,
652 "glDrawElements(transform feedback active)");
653 return GL_FALSE;
654 }
655
656 if (count <= 0) {
657 if (count < 0)
658 _mesa_error(ctx, GL_INVALID_VALUE,
659 "glDrawElementsInstanced(count=%d)", count);
660 return GL_FALSE;
661 }
662
663 if (!_mesa_valid_prim_mode(ctx, mode, "glDrawElementsInstanced")) {
664 return GL_FALSE;
665 }
666
667 if (!valid_elements_type(ctx, type, "glDrawElementsInstanced"))
668 return GL_FALSE;
669
670 if (numInstances <= 0) {
671 if (numInstances < 0)
672 _mesa_error(ctx, GL_INVALID_VALUE,
673 "glDrawElementsInstanced(numInstances=%d)", numInstances);
674 return GL_FALSE;
675 }
676
677 if (!check_valid_to_render(ctx, "glDrawElementsInstanced"))
678 return GL_FALSE;
679
680 /* Vertex buffer object tests */
681 if (_mesa_is_bufferobj(ctx->Array.ArrayObj->ElementArrayBufferObj)) {
682 /* use indices in the buffer object */
683 /* make sure count doesn't go outside buffer bounds */
684 if (index_bytes(type, count) > ctx->Array.ArrayObj->ElementArrayBufferObj->Size) {
685 _mesa_warning(ctx,
686 "glDrawElementsInstanced index out of buffer bounds");
687 return GL_FALSE;
688 }
689 }
690 else {
691 /* not using a VBO */
692 if (!indices)
693 return GL_FALSE;
694 }
695
696 if (!check_index_bounds(ctx, count, type, indices, basevertex))
697 return GL_FALSE;
698
699 return GL_TRUE;
700 }
701
702
703 GLboolean
704 _mesa_validate_DrawTransformFeedback(struct gl_context *ctx,
705 GLenum mode,
706 struct gl_transform_feedback_object *obj,
707 GLuint stream,
708 GLsizei numInstances)
709 {
710 FLUSH_CURRENT(ctx, 0);
711
712 if (!_mesa_valid_prim_mode(ctx, mode, "glDrawTransformFeedback*(mode)")) {
713 return GL_FALSE;
714 }
715
716 if (!obj) {
717 _mesa_error(ctx, GL_INVALID_VALUE, "glDrawTransformFeedback*(name)");
718 return GL_FALSE;
719 }
720
721 if (!obj->EndedAnytime) {
722 _mesa_error(ctx, GL_INVALID_OPERATION, "glDrawTransformFeedback*");
723 return GL_FALSE;
724 }
725
726 if (stream >= ctx->Const.MaxVertexStreams) {
727 _mesa_error(ctx, GL_INVALID_VALUE,
728 "glDrawTransformFeedbackStream*(index>=MaxVertexStream)");
729 return GL_FALSE;
730 }
731
732 if (numInstances <= 0) {
733 if (numInstances < 0)
734 _mesa_error(ctx, GL_INVALID_VALUE,
735 "glDrawTransformFeedback*Instanced(numInstances=%d)",
736 numInstances);
737 return GL_FALSE;
738 }
739
740 if (!check_valid_to_render(ctx, "glDrawTransformFeedback*")) {
741 return GL_FALSE;
742 }
743
744 return GL_TRUE;
745 }