Merge branch 'llvm-cliptest-viewport'
[mesa.git] / src / mesa / main / varray.c
1 /*
2 * Mesa 3-D graphics library
3 * Version: 7.6
4 *
5 * Copyright (C) 1999-2008 Brian Paul All Rights Reserved.
6 * Copyright (C) 2009 VMware, Inc. All Rights Reserved.
7 *
8 * Permission is hereby granted, free of charge, to any person obtaining a
9 * copy of this software and associated documentation files (the "Software"),
10 * to deal in the Software without restriction, including without limitation
11 * the rights to use, copy, modify, merge, publish, distribute, sublicense,
12 * and/or sell copies of the Software, and to permit persons to whom the
13 * Software is furnished to do so, subject to the following conditions:
14 *
15 * The above copyright notice and this permission notice shall be included
16 * in all copies or substantial portions of the Software.
17 *
18 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
19 * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
20 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
21 * BRIAN PAUL BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN
22 * AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
23 * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
24 */
25
26
27 #include "glheader.h"
28 #include "imports.h"
29 #include "bufferobj.h"
30 #include "context.h"
31 #include "enable.h"
32 #include "enums.h"
33 #include "hash.h"
34 #include "macros.h"
35 #include "mtypes.h"
36 #include "varray.h"
37 #include "arrayobj.h"
38 #include "main/dispatch.h"
39
40
41 /**
42 * Set the fields of a vertex array.
43 * Also do an error check for GL_ARB_vertex_array_object: check that
44 * all arrays reside in VBOs when using a vertex array object.
45 *
46 * \param array the array to update
47 * \param dirtyBit which bit to set in ctx->Array.NewState for this array
48 * \param elementSize size of each array element, in bytes
49 * \param size components per element (1, 2, 3 or 4)
50 * \param type datatype of each component (GL_FLOAT, GL_INT, etc)
51 * \param format either GL_RGBA or GL_BGRA
52 * \param stride stride between elements, in elements
53 * \param normalized are integer types converted to floats in [-1, 1]?
54 * \param ptr the address (or offset inside VBO) of the array data
55 */
56 static void
57 update_array(struct gl_context *ctx, struct gl_client_array *array,
58 GLbitfield dirtyBit, GLsizei elementSize,
59 GLint size, GLenum type, GLenum format,
60 GLsizei stride, GLboolean normalized, const GLvoid *ptr)
61 {
62 ASSERT(format == GL_RGBA || format == GL_BGRA);
63
64 if (ctx->Array.ArrayObj->VBOonly &&
65 ctx->Array.ArrayBufferObj->Name == 0) {
66 /* GL_ARB_vertex_array_object requires that all arrays reside in VBOs.
67 * Generate GL_INVALID_OPERATION if that's not true.
68 */
69 _mesa_error(ctx, GL_INVALID_OPERATION,
70 "glVertex/Normal/EtcPointer(non-VBO array)");
71 return;
72 }
73
74 array->Size = size;
75 array->Type = type;
76 array->Format = format;
77 array->Stride = stride;
78 array->StrideB = stride ? stride : elementSize;
79 array->Normalized = normalized;
80 array->Ptr = (const GLubyte *) ptr;
81 array->_ElementSize = elementSize;
82
83 _mesa_reference_buffer_object(ctx, &array->BufferObj,
84 ctx->Array.ArrayBufferObj);
85
86 ctx->NewState |= _NEW_ARRAY;
87 ctx->Array.NewState |= dirtyBit;
88 }
89
90
91 void GLAPIENTRY
92 _mesa_VertexPointer(GLint size, GLenum type, GLsizei stride, const GLvoid *ptr)
93 {
94 GLsizei elementSize;
95 GET_CURRENT_CONTEXT(ctx);
96 ASSERT_OUTSIDE_BEGIN_END_AND_FLUSH(ctx);
97
98 if (size < 2 || size > 4) {
99 _mesa_error( ctx, GL_INVALID_VALUE, "glVertexPointer(size)" );
100 return;
101 }
102 if (stride < 0) {
103 _mesa_error( ctx, GL_INVALID_VALUE, "glVertexPointer(stride)" );
104 return;
105 }
106
107 if (MESA_VERBOSE&(VERBOSE_VARRAY|VERBOSE_API))
108 _mesa_debug(ctx, "glVertexPointer( sz %d type %s stride %d )\n", size,
109 _mesa_lookup_enum_by_nr( type ), stride);
110
111 /* always need to check that <type> is legal */
112 switch (type) {
113 case GL_SHORT:
114 elementSize = size * sizeof(GLshort);
115 break;
116 case GL_INT:
117 elementSize = size * sizeof(GLint);
118 break;
119 case GL_FLOAT:
120 elementSize = size * sizeof(GLfloat);
121 break;
122 case GL_DOUBLE:
123 elementSize = size * sizeof(GLdouble);
124 break;
125 case GL_HALF_FLOAT:
126 elementSize = size * sizeof(GLhalfARB);
127 break;
128 #if FEATURE_fixedpt
129 case GL_FIXED:
130 elementSize = size * sizeof(GLfixed);
131 break;
132 #endif
133 #if FEATURE_vertex_array_byte
134 case GL_BYTE:
135 elementSize = size * sizeof(GLbyte);
136 break;
137 #endif
138 default:
139 _mesa_error( ctx, GL_INVALID_ENUM, "glVertexPointer(type=%s)",
140 _mesa_lookup_enum_by_nr(type));
141 return;
142 }
143
144 update_array(ctx, &ctx->Array.ArrayObj->Vertex, _NEW_ARRAY_VERTEX,
145 elementSize, size, type, GL_RGBA, stride, GL_FALSE, ptr);
146 }
147
148
149 void GLAPIENTRY
150 _mesa_NormalPointer(GLenum type, GLsizei stride, const GLvoid *ptr )
151 {
152 GLsizei elementSize;
153 GET_CURRENT_CONTEXT(ctx);
154 ASSERT_OUTSIDE_BEGIN_END_AND_FLUSH(ctx);
155
156 if (stride < 0) {
157 _mesa_error( ctx, GL_INVALID_VALUE, "glNormalPointer(stride)" );
158 return;
159 }
160
161 if (MESA_VERBOSE&(VERBOSE_VARRAY|VERBOSE_API))
162 _mesa_debug(ctx, "glNormalPointer( type %s stride %d )\n",
163 _mesa_lookup_enum_by_nr( type ), stride);
164
165 switch (type) {
166 case GL_BYTE:
167 elementSize = 3 * sizeof(GLbyte);
168 break;
169 case GL_SHORT:
170 elementSize = 3 * sizeof(GLshort);
171 break;
172 case GL_INT:
173 elementSize = 3 * sizeof(GLint);
174 break;
175 case GL_FLOAT:
176 elementSize = 3 * sizeof(GLfloat);
177 break;
178 case GL_DOUBLE:
179 elementSize = 3 * sizeof(GLdouble);
180 break;
181 case GL_HALF_FLOAT:
182 elementSize = 3 * sizeof(GLhalfARB);
183 break;
184 #if FEATURE_fixedpt
185 case GL_FIXED:
186 elementSize = 3 * sizeof(GLfixed);
187 break;
188 #endif
189 default:
190 _mesa_error( ctx, GL_INVALID_ENUM, "glNormalPointer(type=%s)",
191 _mesa_lookup_enum_by_nr(type));
192 return;
193 }
194
195 update_array(ctx, &ctx->Array.ArrayObj->Normal, _NEW_ARRAY_NORMAL,
196 elementSize, 3, type, GL_RGBA, stride, GL_TRUE, ptr);
197 }
198
199
200 void GLAPIENTRY
201 _mesa_ColorPointer(GLint size, GLenum type, GLsizei stride, const GLvoid *ptr)
202 {
203 GLsizei elementSize;
204 GLenum format;
205 GET_CURRENT_CONTEXT(ctx);
206 ASSERT_OUTSIDE_BEGIN_END_AND_FLUSH(ctx);
207
208 if (size < 3 || size > 4) {
209 if (!ctx->Extensions.EXT_vertex_array_bgra || size != GL_BGRA) {
210 _mesa_error(ctx, GL_INVALID_VALUE, "glColorPointer(size)");
211 return;
212 }
213 }
214 if (stride < 0) {
215 _mesa_error( ctx, GL_INVALID_VALUE, "glColorPointer(stride)" );
216 return;
217 }
218
219 if (MESA_VERBOSE&(VERBOSE_VARRAY|VERBOSE_API))
220 _mesa_debug(ctx, "glColorPointer( sz %d type %s stride %d )\n", size,
221 _mesa_lookup_enum_by_nr( type ), stride);
222
223 if (size == GL_BGRA) {
224 if (type != GL_UNSIGNED_BYTE) {
225 _mesa_error(ctx, GL_INVALID_VALUE, "glColorPointer(GL_BGRA/GLubyte)");
226 return;
227 }
228 format = GL_BGRA;
229 size = 4;
230 }
231 else {
232 format = GL_RGBA;
233 }
234
235 switch (type) {
236 case GL_BYTE:
237 elementSize = size * sizeof(GLbyte);
238 break;
239 case GL_UNSIGNED_BYTE:
240 elementSize = size * sizeof(GLubyte);
241 break;
242 case GL_SHORT:
243 elementSize = size * sizeof(GLshort);
244 break;
245 case GL_UNSIGNED_SHORT:
246 elementSize = size * sizeof(GLushort);
247 break;
248 case GL_INT:
249 elementSize = size * sizeof(GLint);
250 break;
251 case GL_UNSIGNED_INT:
252 elementSize = size * sizeof(GLuint);
253 break;
254 case GL_FLOAT:
255 elementSize = size * sizeof(GLfloat);
256 break;
257 case GL_DOUBLE:
258 elementSize = size * sizeof(GLdouble);
259 break;
260 case GL_HALF_FLOAT:
261 elementSize = size * sizeof(GLhalfARB);
262 break;
263 #if FEATURE_fixedpt
264 case GL_FIXED:
265 elementSize = size * sizeof(GLfixed);
266 break;
267 #endif
268 default:
269 _mesa_error( ctx, GL_INVALID_ENUM, "glColorPointer(type=%s)",
270 _mesa_lookup_enum_by_nr(type));
271 return;
272 }
273
274 update_array(ctx, &ctx->Array.ArrayObj->Color, _NEW_ARRAY_COLOR0,
275 elementSize, size, type, format, stride, GL_TRUE, ptr);
276 }
277
278
279 void GLAPIENTRY
280 _mesa_FogCoordPointerEXT(GLenum type, GLsizei stride, const GLvoid *ptr)
281 {
282 GLint elementSize;
283 GET_CURRENT_CONTEXT(ctx);
284 ASSERT_OUTSIDE_BEGIN_END_AND_FLUSH(ctx);
285
286 if (stride < 0) {
287 _mesa_error( ctx, GL_INVALID_VALUE, "glFogCoordPointer(stride)" );
288 return;
289 }
290
291 switch (type) {
292 case GL_FLOAT:
293 elementSize = sizeof(GLfloat);
294 break;
295 case GL_DOUBLE:
296 elementSize = sizeof(GLdouble);
297 break;
298 case GL_HALF_FLOAT:
299 elementSize = sizeof(GLhalfARB);
300 break;
301 default:
302 _mesa_error( ctx, GL_INVALID_ENUM, "glFogCoordPointer(type)" );
303 return;
304 }
305
306 update_array(ctx, &ctx->Array.ArrayObj->FogCoord, _NEW_ARRAY_FOGCOORD,
307 elementSize, 1, type, GL_RGBA, stride, GL_FALSE, ptr);
308 }
309
310
311 void GLAPIENTRY
312 _mesa_IndexPointer(GLenum type, GLsizei stride, const GLvoid *ptr)
313 {
314 GLsizei elementSize;
315 GET_CURRENT_CONTEXT(ctx);
316 ASSERT_OUTSIDE_BEGIN_END_AND_FLUSH(ctx);
317
318 if (stride < 0) {
319 _mesa_error( ctx, GL_INVALID_VALUE, "glIndexPointer(stride)" );
320 return;
321 }
322
323 switch (type) {
324 case GL_UNSIGNED_BYTE:
325 elementSize = sizeof(GLubyte);
326 break;
327 case GL_SHORT:
328 elementSize = sizeof(GLshort);
329 break;
330 case GL_INT:
331 elementSize = sizeof(GLint);
332 break;
333 case GL_FLOAT:
334 elementSize = sizeof(GLfloat);
335 break;
336 case GL_DOUBLE:
337 elementSize = sizeof(GLdouble);
338 break;
339 default:
340 _mesa_error( ctx, GL_INVALID_ENUM, "glIndexPointer(type)" );
341 return;
342 }
343
344 update_array(ctx, &ctx->Array.ArrayObj->Index, _NEW_ARRAY_INDEX,
345 elementSize, 1, type, GL_RGBA, stride, GL_FALSE, ptr);
346 }
347
348
349 void GLAPIENTRY
350 _mesa_SecondaryColorPointerEXT(GLint size, GLenum type,
351 GLsizei stride, const GLvoid *ptr)
352 {
353 GLsizei elementSize;
354 GLenum format;
355 GET_CURRENT_CONTEXT(ctx);
356 ASSERT_OUTSIDE_BEGIN_END_AND_FLUSH(ctx);
357
358 if (size != 3 && size != 4) {
359 if (!ctx->Extensions.EXT_vertex_array_bgra || size != GL_BGRA) {
360 _mesa_error(ctx, GL_INVALID_VALUE, "glSecondaryColorPointer(size)");
361 return;
362 }
363 }
364 if (stride < 0) {
365 _mesa_error( ctx, GL_INVALID_VALUE, "glSecondaryColorPointer(stride)" );
366 return;
367 }
368
369 if (MESA_VERBOSE&(VERBOSE_VARRAY|VERBOSE_API))
370 _mesa_debug(ctx, "glSecondaryColorPointer( sz %d type %s stride %d )\n",
371 size, _mesa_lookup_enum_by_nr( type ), stride);
372
373 if (size == GL_BGRA) {
374 if (type != GL_UNSIGNED_BYTE) {
375 _mesa_error(ctx, GL_INVALID_VALUE, "glColorPointer(GL_BGRA/GLubyte)");
376 return;
377 }
378 format = GL_BGRA;
379 size = 4;
380 }
381 else {
382 format = GL_RGBA;
383 }
384
385 switch (type) {
386 case GL_BYTE:
387 elementSize = size * sizeof(GLbyte);
388 break;
389 case GL_UNSIGNED_BYTE:
390 elementSize = size * sizeof(GLubyte);
391 break;
392 case GL_SHORT:
393 elementSize = size * sizeof(GLshort);
394 break;
395 case GL_UNSIGNED_SHORT:
396 elementSize = size * sizeof(GLushort);
397 break;
398 case GL_INT:
399 elementSize = size * sizeof(GLint);
400 break;
401 case GL_UNSIGNED_INT:
402 elementSize = size * sizeof(GLuint);
403 break;
404 case GL_FLOAT:
405 elementSize = size * sizeof(GLfloat);
406 break;
407 case GL_DOUBLE:
408 elementSize = size * sizeof(GLdouble);
409 break;
410 case GL_HALF_FLOAT:
411 elementSize = size * sizeof(GLhalfARB);
412 break;
413 default:
414 _mesa_error( ctx, GL_INVALID_ENUM, "glSecondaryColorPointer(type=%s)",
415 _mesa_lookup_enum_by_nr(type));
416 return;
417 }
418
419 update_array(ctx, &ctx->Array.ArrayObj->SecondaryColor, _NEW_ARRAY_COLOR1,
420 elementSize, size, type, format, stride, GL_TRUE, ptr);
421 }
422
423
424 void GLAPIENTRY
425 _mesa_TexCoordPointer(GLint size, GLenum type, GLsizei stride,
426 const GLvoid *ptr)
427 {
428 GLint elementSize;
429 GET_CURRENT_CONTEXT(ctx);
430 const GLuint unit = ctx->Array.ActiveTexture;
431 ASSERT_OUTSIDE_BEGIN_END_AND_FLUSH(ctx);
432
433 if (size < 1 || size > 4) {
434 _mesa_error( ctx, GL_INVALID_VALUE, "glTexCoordPointer(size)" );
435 return;
436 }
437 if (stride < 0) {
438 _mesa_error( ctx, GL_INVALID_VALUE, "glTexCoordPointer(stride)" );
439 return;
440 }
441
442 if (MESA_VERBOSE&(VERBOSE_VARRAY|VERBOSE_API))
443 _mesa_debug(ctx, "glTexCoordPointer(unit %u sz %d type %s stride %d)\n",
444 unit, size, _mesa_lookup_enum_by_nr( type ), stride);
445
446 /* always need to check that <type> is legal */
447 switch (type) {
448 case GL_SHORT:
449 elementSize = size * sizeof(GLshort);
450 break;
451 case GL_INT:
452 elementSize = size * sizeof(GLint);
453 break;
454 case GL_FLOAT:
455 elementSize = size * sizeof(GLfloat);
456 break;
457 case GL_DOUBLE:
458 elementSize = size * sizeof(GLdouble);
459 break;
460 case GL_HALF_FLOAT:
461 elementSize = size * sizeof(GLhalfARB);
462 break;
463 #if FEATURE_fixedpt
464 case GL_FIXED:
465 elementSize = size * sizeof(GLfixed);
466 break;
467 #endif
468 #if FEATURE_vertex_array_byte
469 case GL_BYTE:
470 elementSize = size * sizeof(GLbyte);
471 break;
472 #endif
473 default:
474 _mesa_error( ctx, GL_INVALID_ENUM, "glTexCoordPointer(type=%s)",
475 _mesa_lookup_enum_by_nr(type));
476 return;
477 }
478
479 ASSERT(unit < Elements(ctx->Array.ArrayObj->TexCoord));
480
481 update_array(ctx, &ctx->Array.ArrayObj->TexCoord[unit],
482 _NEW_ARRAY_TEXCOORD(unit),
483 elementSize, size, type, GL_RGBA, stride, GL_FALSE, ptr);
484 }
485
486
487 void GLAPIENTRY
488 _mesa_EdgeFlagPointer(GLsizei stride, const GLvoid *ptr)
489 {
490 GET_CURRENT_CONTEXT(ctx);
491 ASSERT_OUTSIDE_BEGIN_END_AND_FLUSH(ctx);
492
493 if (stride < 0) {
494 _mesa_error( ctx, GL_INVALID_VALUE, "glEdgeFlagPointer(stride)" );
495 return;
496 }
497
498 update_array(ctx, &ctx->Array.ArrayObj->EdgeFlag, _NEW_ARRAY_EDGEFLAG,
499 sizeof(GLboolean), 1, GL_UNSIGNED_BYTE, GL_RGBA,
500 stride, GL_FALSE, ptr);
501 }
502
503
504 void GLAPIENTRY
505 _mesa_PointSizePointer(GLenum type, GLsizei stride, const GLvoid *ptr)
506 {
507 GLsizei elementSize;
508 GET_CURRENT_CONTEXT(ctx);
509 ASSERT_OUTSIDE_BEGIN_END_AND_FLUSH(ctx);
510
511 if (stride < 0) {
512 _mesa_error( ctx, GL_INVALID_VALUE, "glPointSizePointer(stride)" );
513 return;
514 }
515
516 switch (type) {
517 case GL_FLOAT:
518 elementSize = sizeof(GLfloat);
519 break;
520 #if FEATURE_fixedpt
521 case GL_FIXED:
522 elementSize = sizeof(GLfixed);
523 break;
524 #endif
525 default:
526 _mesa_error( ctx, GL_INVALID_ENUM, "glPointSizePointer(type)" );
527 return;
528 }
529
530 update_array(ctx, &ctx->Array.ArrayObj->PointSize, _NEW_ARRAY_POINT_SIZE,
531 elementSize, 1, type, GL_RGBA, stride, GL_FALSE, ptr);
532 }
533
534
535 #if FEATURE_NV_vertex_program
536 /**
537 * Set a vertex attribute array.
538 * Note that these arrays DO alias the conventional GL vertex arrays
539 * (position, normal, color, fog, texcoord, etc).
540 * The generic attribute slots at #16 and above are not touched.
541 */
542 void GLAPIENTRY
543 _mesa_VertexAttribPointerNV(GLuint index, GLint size, GLenum type,
544 GLsizei stride, const GLvoid *ptr)
545 {
546 GLboolean normalized = GL_FALSE;
547 GLsizei elementSize;
548 GLenum format;
549 GET_CURRENT_CONTEXT(ctx);
550 ASSERT_OUTSIDE_BEGIN_END(ctx);
551
552 if (index >= MAX_NV_VERTEX_PROGRAM_INPUTS) {
553 _mesa_error(ctx, GL_INVALID_VALUE, "glVertexAttribPointerNV(index)");
554 return;
555 }
556
557 if (size < 1 || size > 4) {
558 _mesa_error(ctx, GL_INVALID_VALUE, "glVertexAttribPointerNV(size)");
559 return;
560 }
561
562 if (stride < 0) {
563 _mesa_error(ctx, GL_INVALID_VALUE, "glVertexAttribPointerNV(stride)");
564 return;
565 }
566
567 if (type == GL_UNSIGNED_BYTE && size != 4) {
568 _mesa_error(ctx, GL_INVALID_VALUE, "glVertexAttribPointerNV(size!=4)");
569 return;
570 }
571
572 if (size == GL_BGRA) {
573 if (type != GL_UNSIGNED_BYTE) {
574 _mesa_error(ctx, GL_INVALID_VALUE,
575 "glVertexAttribPointerNV(GL_BGRA/type)");
576 return;
577 }
578
579 format = GL_BGRA;
580 size = 4;
581 normalized = GL_TRUE;
582 }
583 else {
584 format = GL_RGBA;
585 }
586
587 /* check for valid 'type' and compute StrideB right away */
588 switch (type) {
589 case GL_UNSIGNED_BYTE:
590 normalized = GL_TRUE;
591 elementSize = size * sizeof(GLubyte);
592 break;
593 case GL_SHORT:
594 elementSize = size * sizeof(GLshort);
595 break;
596 case GL_FLOAT:
597 elementSize = size * sizeof(GLfloat);
598 break;
599 case GL_DOUBLE:
600 elementSize = size * sizeof(GLdouble);
601 break;
602 default:
603 _mesa_error( ctx, GL_INVALID_ENUM, "glVertexAttribPointerNV(type=%s)",
604 _mesa_lookup_enum_by_nr(type));
605 return;
606 }
607
608 update_array(ctx, &ctx->Array.ArrayObj->VertexAttrib[index],
609 _NEW_ARRAY_ATTRIB(index),
610 elementSize, size, type, format, stride, normalized, ptr);
611 }
612 #endif
613
614
615 #if FEATURE_ARB_vertex_program
616 /**
617 * Set a generic vertex attribute array.
618 * Note that these arrays DO NOT alias the conventional GL vertex arrays
619 * (position, normal, color, fog, texcoord, etc).
620 */
621 void GLAPIENTRY
622 _mesa_VertexAttribPointerARB(GLuint index, GLint size, GLenum type,
623 GLboolean normalized,
624 GLsizei stride, const GLvoid *ptr)
625 {
626 GLsizei elementSize;
627 GLenum format;
628 GET_CURRENT_CONTEXT(ctx);
629 ASSERT_OUTSIDE_BEGIN_END(ctx);
630
631 if (index >= ctx->Const.VertexProgram.MaxAttribs) {
632 _mesa_error(ctx, GL_INVALID_VALUE, "glVertexAttribPointerARB(index)");
633 return;
634 }
635
636 if (size < 1 || size > 4) {
637 if (!ctx->Extensions.EXT_vertex_array_bgra || size != GL_BGRA) {
638 _mesa_error(ctx, GL_INVALID_VALUE, "glVertexAttribPointerARB(size)");
639 return;
640 }
641 }
642
643 if (stride < 0) {
644 _mesa_error(ctx, GL_INVALID_VALUE, "glVertexAttribPointerARB(stride)");
645 return;
646 }
647
648 if (size == GL_BGRA) {
649 if (type != GL_UNSIGNED_BYTE) {
650 _mesa_error(ctx, GL_INVALID_VALUE,
651 "glVertexAttribPointerARB(GL_BGRA/type)");
652 return;
653 }
654 if (normalized != GL_TRUE) {
655 _mesa_error(ctx, GL_INVALID_VALUE,
656 "glVertexAttribPointerARB(GL_BGRA/normalized)");
657 return;
658 }
659
660 format = GL_BGRA;
661 size = 4;
662 }
663 else {
664 format = GL_RGBA;
665 }
666
667 /* check for valid 'type' and compute StrideB right away */
668 /* NOTE: more types are supported here than in the NV extension */
669 switch (type) {
670 case GL_BYTE:
671 elementSize = size * sizeof(GLbyte);
672 break;
673 case GL_UNSIGNED_BYTE:
674 elementSize = size * sizeof(GLubyte);
675 break;
676 case GL_SHORT:
677 elementSize = size * sizeof(GLshort);
678 break;
679 case GL_UNSIGNED_SHORT:
680 elementSize = size * sizeof(GLushort);
681 break;
682 case GL_INT:
683 elementSize = size * sizeof(GLint);
684 break;
685 case GL_UNSIGNED_INT:
686 elementSize = size * sizeof(GLuint);
687 break;
688 case GL_FLOAT:
689 elementSize = size * sizeof(GLfloat);
690 break;
691 case GL_DOUBLE:
692 elementSize = size * sizeof(GLdouble);
693 break;
694 case GL_HALF_FLOAT:
695 elementSize = size * sizeof(GLhalfARB);
696 break;
697 #if FEATURE_fixedpt
698 case GL_FIXED:
699 elementSize = size * sizeof(GLfixed);
700 break;
701 #endif
702 default:
703 _mesa_error( ctx, GL_INVALID_ENUM, "glVertexAttribPointerARB(type)" );
704 return;
705 }
706
707 update_array(ctx, &ctx->Array.ArrayObj->VertexAttrib[index],
708 _NEW_ARRAY_ATTRIB(index),
709 elementSize, size, type, format, stride, normalized, ptr);
710 }
711 #endif
712
713
714 /**
715 * New in GL3:
716 * Set an integer-valued vertex attribute array.
717 * Note that these arrays DO NOT alias the conventional GL vertex arrays
718 * (position, normal, color, fog, texcoord, etc).
719 */
720 void GLAPIENTRY
721 _mesa_VertexAttribIPointer(GLuint index, GLint size, GLenum type,
722 GLboolean normalized,
723 GLsizei stride, const GLvoid *ptr)
724 {
725 /* NOTE: until we have integer-valued vertex attributes, just
726 * route this through the regular glVertexAttribPointer() function.
727 */
728 _mesa_VertexAttribPointerARB(index, size, type, normalized, stride, ptr);
729 }
730
731
732
733 void GLAPIENTRY
734 _mesa_EnableVertexAttribArrayARB(GLuint index)
735 {
736 GET_CURRENT_CONTEXT(ctx);
737 ASSERT_OUTSIDE_BEGIN_END(ctx);
738
739 if (index >= ctx->Const.VertexProgram.MaxAttribs) {
740 _mesa_error(ctx, GL_INVALID_VALUE,
741 "glEnableVertexAttribArrayARB(index)");
742 return;
743 }
744
745 ASSERT(index < Elements(ctx->Array.ArrayObj->VertexAttrib));
746
747 FLUSH_VERTICES(ctx, _NEW_ARRAY);
748 ctx->Array.ArrayObj->VertexAttrib[index].Enabled = GL_TRUE;
749 ctx->Array.ArrayObj->_Enabled |= _NEW_ARRAY_ATTRIB(index);
750 ctx->Array.NewState |= _NEW_ARRAY_ATTRIB(index);
751 }
752
753
754 void GLAPIENTRY
755 _mesa_DisableVertexAttribArrayARB(GLuint index)
756 {
757 GET_CURRENT_CONTEXT(ctx);
758 ASSERT_OUTSIDE_BEGIN_END(ctx);
759
760 if (index >= ctx->Const.VertexProgram.MaxAttribs) {
761 _mesa_error(ctx, GL_INVALID_VALUE,
762 "glEnableVertexAttribArrayARB(index)");
763 return;
764 }
765
766 ASSERT(index < Elements(ctx->Array.ArrayObj->VertexAttrib));
767
768 FLUSH_VERTICES(ctx, _NEW_ARRAY);
769 ctx->Array.ArrayObj->VertexAttrib[index].Enabled = GL_FALSE;
770 ctx->Array.ArrayObj->_Enabled &= ~_NEW_ARRAY_ATTRIB(index);
771 ctx->Array.NewState |= _NEW_ARRAY_ATTRIB(index);
772 }
773
774
775 /**
776 * Return info for a vertex attribute array (no alias with legacy
777 * vertex attributes (pos, normal, color, etc)). This function does
778 * not handle the 4-element GL_CURRENT_VERTEX_ATTRIB_ARB query.
779 */
780 static GLuint
781 get_vertex_array_attrib(struct gl_context *ctx, GLuint index, GLenum pname,
782 const char *caller)
783 {
784 const struct gl_client_array *array;
785
786 if (index >= MAX_VERTEX_GENERIC_ATTRIBS) {
787 _mesa_error(ctx, GL_INVALID_VALUE, "%s(index=%u)", caller, index);
788 return 0;
789 }
790
791 ASSERT(index < Elements(ctx->Array.ArrayObj->VertexAttrib));
792
793 array = &ctx->Array.ArrayObj->VertexAttrib[index];
794
795 switch (pname) {
796 case GL_VERTEX_ATTRIB_ARRAY_ENABLED_ARB:
797 return array->Enabled;
798 case GL_VERTEX_ATTRIB_ARRAY_SIZE_ARB:
799 return array->Size;
800 case GL_VERTEX_ATTRIB_ARRAY_STRIDE_ARB:
801 return array->Stride;
802 case GL_VERTEX_ATTRIB_ARRAY_TYPE_ARB:
803 return array->Type;
804 case GL_VERTEX_ATTRIB_ARRAY_NORMALIZED_ARB:
805 return array->Normalized;
806 case GL_VERTEX_ATTRIB_ARRAY_BUFFER_BINDING_ARB:
807 return array->BufferObj->Name;
808 default:
809 _mesa_error(ctx, GL_INVALID_ENUM, "%s(pname=0x%x)", caller, pname);
810 return 0;
811 }
812 }
813
814
815 void GLAPIENTRY
816 _mesa_GetVertexAttribfvARB(GLuint index, GLenum pname, GLfloat *params)
817 {
818 GET_CURRENT_CONTEXT(ctx);
819 ASSERT_OUTSIDE_BEGIN_END(ctx);
820
821 if (pname == GL_CURRENT_VERTEX_ATTRIB_ARB) {
822 if (index == 0) {
823 _mesa_error(ctx, GL_INVALID_OPERATION,
824 "glGetVertexAttribfv(index==0)");
825 }
826 else {
827 const GLfloat *v = ctx->Current.Attrib[VERT_ATTRIB_GENERIC0 + index];
828 FLUSH_CURRENT(ctx, 0);
829 COPY_4V(params, v);
830 }
831 }
832 else {
833 params[0] = (GLfloat) get_vertex_array_attrib(ctx, index, pname,
834 "glGetVertexAttribfv");
835 }
836 }
837
838
839 void GLAPIENTRY
840 _mesa_GetVertexAttribdvARB(GLuint index, GLenum pname, GLdouble *params)
841 {
842 GET_CURRENT_CONTEXT(ctx);
843 ASSERT_OUTSIDE_BEGIN_END(ctx);
844
845 if (pname == GL_CURRENT_VERTEX_ATTRIB_ARB) {
846 if (index == 0) {
847 _mesa_error(ctx, GL_INVALID_OPERATION,
848 "glGetVertexAttribdv(index==0)");
849 }
850 else {
851 const GLfloat *v = ctx->Current.Attrib[VERT_ATTRIB_GENERIC0 + index];
852 FLUSH_CURRENT(ctx, 0);
853 params[0] = (GLdouble) v[0];
854 params[1] = (GLdouble) v[1];
855 params[2] = (GLdouble) v[2];
856 params[3] = (GLdouble) v[3];
857 }
858 }
859 else {
860 params[0] = (GLdouble) get_vertex_array_attrib(ctx, index, pname,
861 "glGetVertexAttribdv");
862 }
863 }
864
865
866 void GLAPIENTRY
867 _mesa_GetVertexAttribivARB(GLuint index, GLenum pname, GLint *params)
868 {
869 GET_CURRENT_CONTEXT(ctx);
870 ASSERT_OUTSIDE_BEGIN_END(ctx);
871
872 if (pname == GL_CURRENT_VERTEX_ATTRIB_ARB) {
873 if (index == 0) {
874 _mesa_error(ctx, GL_INVALID_OPERATION,
875 "glGetVertexAttribiv(index==0)");
876 }
877 else {
878 const GLfloat *v = ctx->Current.Attrib[VERT_ATTRIB_GENERIC0 + index];
879 FLUSH_CURRENT(ctx, 0);
880 /* XXX should floats in[0,1] be scaled to full int range? */
881 params[0] = (GLint) v[0];
882 params[1] = (GLint) v[1];
883 params[2] = (GLint) v[2];
884 params[3] = (GLint) v[3];
885 }
886 }
887 else {
888 params[0] = (GLint) get_vertex_array_attrib(ctx, index, pname,
889 "glGetVertexAttribiv");
890 }
891 }
892
893
894 /** GL 3.0 */
895 void GLAPIENTRY
896 _mesa_GetVertexAttribIiv(GLuint index, GLenum pname, GLint *params)
897 {
898 GET_CURRENT_CONTEXT(ctx);
899 ASSERT_OUTSIDE_BEGIN_END(ctx);
900
901 if (pname == GL_CURRENT_VERTEX_ATTRIB_ARB) {
902 if (index == 0) {
903 _mesa_error(ctx, GL_INVALID_OPERATION,
904 "glGetVertexAttribIiv(index==0)");
905 }
906 else {
907 const GLfloat *v = ctx->Current.Attrib[VERT_ATTRIB_GENERIC0 + index];
908 FLUSH_CURRENT(ctx, 0);
909 /* XXX we don't have true integer-valued vertex attribs yet */
910 params[0] = (GLint) v[0];
911 params[1] = (GLint) v[1];
912 params[2] = (GLint) v[2];
913 params[3] = (GLint) v[3];
914 }
915 }
916 else {
917 params[0] = (GLint) get_vertex_array_attrib(ctx, index, pname,
918 "glGetVertexAttribIiv");
919 }
920 }
921
922
923 /** GL 3.0 */
924 void GLAPIENTRY
925 _mesa_GetVertexAttribIuiv(GLuint index, GLenum pname, GLuint *params)
926 {
927 GET_CURRENT_CONTEXT(ctx);
928 ASSERT_OUTSIDE_BEGIN_END(ctx);
929
930 if (pname == GL_CURRENT_VERTEX_ATTRIB_ARB) {
931 if (index == 0) {
932 _mesa_error(ctx, GL_INVALID_OPERATION,
933 "glGetVertexAttribIuiv(index==0)");
934 }
935 else {
936 const GLfloat *v = ctx->Current.Attrib[VERT_ATTRIB_GENERIC0 + index];
937 FLUSH_CURRENT(ctx, 0);
938 /* XXX we don't have true integer-valued vertex attribs yet */
939 params[0] = (GLuint) v[0];
940 params[1] = (GLuint) v[1];
941 params[2] = (GLuint) v[2];
942 params[3] = (GLuint) v[3];
943 }
944 }
945 else {
946 params[0] = get_vertex_array_attrib(ctx, index, pname,
947 "glGetVertexAttribIuiv");
948 }
949 }
950
951
952 void GLAPIENTRY
953 _mesa_GetVertexAttribPointervARB(GLuint index, GLenum pname, GLvoid **pointer)
954 {
955 GET_CURRENT_CONTEXT(ctx);
956 ASSERT_OUTSIDE_BEGIN_END(ctx);
957
958 if (index >= ctx->Const.VertexProgram.MaxAttribs) {
959 _mesa_error(ctx, GL_INVALID_VALUE, "glGetVertexAttribPointerARB(index)");
960 return;
961 }
962
963 if (pname != GL_VERTEX_ATTRIB_ARRAY_POINTER_ARB) {
964 _mesa_error(ctx, GL_INVALID_ENUM, "glGetVertexAttribPointerARB(pname)");
965 return;
966 }
967
968 ASSERT(index < Elements(ctx->Array.ArrayObj->VertexAttrib));
969
970 *pointer = (GLvoid *) ctx->Array.ArrayObj->VertexAttrib[index].Ptr;
971 }
972
973
974 void GLAPIENTRY
975 _mesa_VertexPointerEXT(GLint size, GLenum type, GLsizei stride,
976 GLsizei count, const GLvoid *ptr)
977 {
978 (void) count;
979 _mesa_VertexPointer(size, type, stride, ptr);
980 }
981
982
983 void GLAPIENTRY
984 _mesa_NormalPointerEXT(GLenum type, GLsizei stride, GLsizei count,
985 const GLvoid *ptr)
986 {
987 (void) count;
988 _mesa_NormalPointer(type, stride, ptr);
989 }
990
991
992 void GLAPIENTRY
993 _mesa_ColorPointerEXT(GLint size, GLenum type, GLsizei stride, GLsizei count,
994 const GLvoid *ptr)
995 {
996 (void) count;
997 _mesa_ColorPointer(size, type, stride, ptr);
998 }
999
1000
1001 void GLAPIENTRY
1002 _mesa_IndexPointerEXT(GLenum type, GLsizei stride, GLsizei count,
1003 const GLvoid *ptr)
1004 {
1005 (void) count;
1006 _mesa_IndexPointer(type, stride, ptr);
1007 }
1008
1009
1010 void GLAPIENTRY
1011 _mesa_TexCoordPointerEXT(GLint size, GLenum type, GLsizei stride,
1012 GLsizei count, const GLvoid *ptr)
1013 {
1014 (void) count;
1015 _mesa_TexCoordPointer(size, type, stride, ptr);
1016 }
1017
1018
1019 void GLAPIENTRY
1020 _mesa_EdgeFlagPointerEXT(GLsizei stride, GLsizei count, const GLboolean *ptr)
1021 {
1022 (void) count;
1023 _mesa_EdgeFlagPointer(stride, ptr);
1024 }
1025
1026
1027 void GLAPIENTRY
1028 _mesa_InterleavedArrays(GLenum format, GLsizei stride, const GLvoid *pointer)
1029 {
1030 GET_CURRENT_CONTEXT(ctx);
1031 GLboolean tflag, cflag, nflag; /* enable/disable flags */
1032 GLint tcomps, ccomps, vcomps; /* components per texcoord, color, vertex */
1033 GLenum ctype = 0; /* color type */
1034 GLint coffset = 0, noffset = 0, voffset;/* color, normal, vertex offsets */
1035 const GLint toffset = 0; /* always zero */
1036 GLint defstride; /* default stride */
1037 GLint c, f;
1038
1039 ASSERT_OUTSIDE_BEGIN_END_AND_FLUSH(ctx);
1040
1041 f = sizeof(GLfloat);
1042 c = f * ((4 * sizeof(GLubyte) + (f - 1)) / f);
1043
1044 if (stride < 0) {
1045 _mesa_error( ctx, GL_INVALID_VALUE, "glInterleavedArrays(stride)" );
1046 return;
1047 }
1048
1049 switch (format) {
1050 case GL_V2F:
1051 tflag = GL_FALSE; cflag = GL_FALSE; nflag = GL_FALSE;
1052 tcomps = 0; ccomps = 0; vcomps = 2;
1053 voffset = 0;
1054 defstride = 2*f;
1055 break;
1056 case GL_V3F:
1057 tflag = GL_FALSE; cflag = GL_FALSE; nflag = GL_FALSE;
1058 tcomps = 0; ccomps = 0; vcomps = 3;
1059 voffset = 0;
1060 defstride = 3*f;
1061 break;
1062 case GL_C4UB_V2F:
1063 tflag = GL_FALSE; cflag = GL_TRUE; nflag = GL_FALSE;
1064 tcomps = 0; ccomps = 4; vcomps = 2;
1065 ctype = GL_UNSIGNED_BYTE;
1066 coffset = 0;
1067 voffset = c;
1068 defstride = c + 2*f;
1069 break;
1070 case GL_C4UB_V3F:
1071 tflag = GL_FALSE; cflag = GL_TRUE; nflag = GL_FALSE;
1072 tcomps = 0; ccomps = 4; vcomps = 3;
1073 ctype = GL_UNSIGNED_BYTE;
1074 coffset = 0;
1075 voffset = c;
1076 defstride = c + 3*f;
1077 break;
1078 case GL_C3F_V3F:
1079 tflag = GL_FALSE; cflag = GL_TRUE; nflag = GL_FALSE;
1080 tcomps = 0; ccomps = 3; vcomps = 3;
1081 ctype = GL_FLOAT;
1082 coffset = 0;
1083 voffset = 3*f;
1084 defstride = 6*f;
1085 break;
1086 case GL_N3F_V3F:
1087 tflag = GL_FALSE; cflag = GL_FALSE; nflag = GL_TRUE;
1088 tcomps = 0; ccomps = 0; vcomps = 3;
1089 noffset = 0;
1090 voffset = 3*f;
1091 defstride = 6*f;
1092 break;
1093 case GL_C4F_N3F_V3F:
1094 tflag = GL_FALSE; cflag = GL_TRUE; nflag = GL_TRUE;
1095 tcomps = 0; ccomps = 4; vcomps = 3;
1096 ctype = GL_FLOAT;
1097 coffset = 0;
1098 noffset = 4*f;
1099 voffset = 7*f;
1100 defstride = 10*f;
1101 break;
1102 case GL_T2F_V3F:
1103 tflag = GL_TRUE; cflag = GL_FALSE; nflag = GL_FALSE;
1104 tcomps = 2; ccomps = 0; vcomps = 3;
1105 voffset = 2*f;
1106 defstride = 5*f;
1107 break;
1108 case GL_T4F_V4F:
1109 tflag = GL_TRUE; cflag = GL_FALSE; nflag = GL_FALSE;
1110 tcomps = 4; ccomps = 0; vcomps = 4;
1111 voffset = 4*f;
1112 defstride = 8*f;
1113 break;
1114 case GL_T2F_C4UB_V3F:
1115 tflag = GL_TRUE; cflag = GL_TRUE; nflag = GL_FALSE;
1116 tcomps = 2; ccomps = 4; vcomps = 3;
1117 ctype = GL_UNSIGNED_BYTE;
1118 coffset = 2*f;
1119 voffset = c+2*f;
1120 defstride = c+5*f;
1121 break;
1122 case GL_T2F_C3F_V3F:
1123 tflag = GL_TRUE; cflag = GL_TRUE; nflag = GL_FALSE;
1124 tcomps = 2; ccomps = 3; vcomps = 3;
1125 ctype = GL_FLOAT;
1126 coffset = 2*f;
1127 voffset = 5*f;
1128 defstride = 8*f;
1129 break;
1130 case GL_T2F_N3F_V3F:
1131 tflag = GL_TRUE; cflag = GL_FALSE; nflag = GL_TRUE;
1132 tcomps = 2; ccomps = 0; vcomps = 3;
1133 noffset = 2*f;
1134 voffset = 5*f;
1135 defstride = 8*f;
1136 break;
1137 case GL_T2F_C4F_N3F_V3F:
1138 tflag = GL_TRUE; cflag = GL_TRUE; nflag = GL_TRUE;
1139 tcomps = 2; ccomps = 4; vcomps = 3;
1140 ctype = GL_FLOAT;
1141 coffset = 2*f;
1142 noffset = 6*f;
1143 voffset = 9*f;
1144 defstride = 12*f;
1145 break;
1146 case GL_T4F_C4F_N3F_V4F:
1147 tflag = GL_TRUE; cflag = GL_TRUE; nflag = GL_TRUE;
1148 tcomps = 4; ccomps = 4; vcomps = 4;
1149 ctype = GL_FLOAT;
1150 coffset = 4*f;
1151 noffset = 8*f;
1152 voffset = 11*f;
1153 defstride = 15*f;
1154 break;
1155 default:
1156 _mesa_error( ctx, GL_INVALID_ENUM, "glInterleavedArrays(format)" );
1157 return;
1158 }
1159
1160 if (stride==0) {
1161 stride = defstride;
1162 }
1163
1164 _mesa_DisableClientState( GL_EDGE_FLAG_ARRAY );
1165 _mesa_DisableClientState( GL_INDEX_ARRAY );
1166 /* XXX also disable secondary color and generic arrays? */
1167
1168 /* Texcoords */
1169 if (tflag) {
1170 _mesa_EnableClientState( GL_TEXTURE_COORD_ARRAY );
1171 _mesa_TexCoordPointer( tcomps, GL_FLOAT, stride,
1172 (GLubyte *) pointer + toffset );
1173 }
1174 else {
1175 _mesa_DisableClientState( GL_TEXTURE_COORD_ARRAY );
1176 }
1177
1178 /* Color */
1179 if (cflag) {
1180 _mesa_EnableClientState( GL_COLOR_ARRAY );
1181 _mesa_ColorPointer( ccomps, ctype, stride,
1182 (GLubyte *) pointer + coffset );
1183 }
1184 else {
1185 _mesa_DisableClientState( GL_COLOR_ARRAY );
1186 }
1187
1188
1189 /* Normals */
1190 if (nflag) {
1191 _mesa_EnableClientState( GL_NORMAL_ARRAY );
1192 _mesa_NormalPointer( GL_FLOAT, stride, (GLubyte *) pointer + noffset );
1193 }
1194 else {
1195 _mesa_DisableClientState( GL_NORMAL_ARRAY );
1196 }
1197
1198 /* Vertices */
1199 _mesa_EnableClientState( GL_VERTEX_ARRAY );
1200 _mesa_VertexPointer( vcomps, GL_FLOAT, stride,
1201 (GLubyte *) pointer + voffset );
1202 }
1203
1204
1205 void GLAPIENTRY
1206 _mesa_LockArraysEXT(GLint first, GLsizei count)
1207 {
1208 GET_CURRENT_CONTEXT(ctx);
1209 ASSERT_OUTSIDE_BEGIN_END_AND_FLUSH(ctx);
1210
1211 if (MESA_VERBOSE & VERBOSE_API)
1212 _mesa_debug(ctx, "glLockArrays %d %d\n", first, count);
1213
1214 if (first < 0) {
1215 _mesa_error( ctx, GL_INVALID_VALUE, "glLockArraysEXT(first)" );
1216 return;
1217 }
1218 if (count <= 0) {
1219 _mesa_error( ctx, GL_INVALID_VALUE, "glLockArraysEXT(count)" );
1220 return;
1221 }
1222 if (ctx->Array.LockCount != 0) {
1223 _mesa_error( ctx, GL_INVALID_OPERATION, "glLockArraysEXT(reentry)" );
1224 return;
1225 }
1226
1227 ctx->Array.LockFirst = first;
1228 ctx->Array.LockCount = count;
1229
1230 ctx->NewState |= _NEW_ARRAY;
1231 ctx->Array.NewState |= _NEW_ARRAY_ALL;
1232 }
1233
1234
1235 void GLAPIENTRY
1236 _mesa_UnlockArraysEXT( void )
1237 {
1238 GET_CURRENT_CONTEXT(ctx);
1239 ASSERT_OUTSIDE_BEGIN_END_AND_FLUSH(ctx);
1240
1241 if (MESA_VERBOSE & VERBOSE_API)
1242 _mesa_debug(ctx, "glUnlockArrays\n");
1243
1244 if (ctx->Array.LockCount == 0) {
1245 _mesa_error( ctx, GL_INVALID_OPERATION, "glUnlockArraysEXT(reexit)" );
1246 return;
1247 }
1248
1249 ctx->Array.LockFirst = 0;
1250 ctx->Array.LockCount = 0;
1251 ctx->NewState |= _NEW_ARRAY;
1252 ctx->Array.NewState |= _NEW_ARRAY_ALL;
1253 }
1254
1255
1256 /* GL_EXT_multi_draw_arrays */
1257 /* Somebody forgot to spec the first and count parameters as const! <sigh> */
1258 void GLAPIENTRY
1259 _mesa_MultiDrawArraysEXT( GLenum mode, const GLint *first,
1260 const GLsizei *count, GLsizei primcount )
1261 {
1262 GET_CURRENT_CONTEXT(ctx);
1263 GLint i;
1264
1265 ASSERT_OUTSIDE_BEGIN_END_AND_FLUSH(ctx);
1266
1267 for (i = 0; i < primcount; i++) {
1268 if (count[i] > 0) {
1269 CALL_DrawArrays(ctx->Exec, (mode, first[i], count[i]));
1270 }
1271 }
1272 }
1273
1274
1275 /* GL_IBM_multimode_draw_arrays */
1276 void GLAPIENTRY
1277 _mesa_MultiModeDrawArraysIBM( const GLenum * mode, const GLint * first,
1278 const GLsizei * count,
1279 GLsizei primcount, GLint modestride )
1280 {
1281 GET_CURRENT_CONTEXT(ctx);
1282 GLint i;
1283
1284 ASSERT_OUTSIDE_BEGIN_END_AND_FLUSH(ctx);
1285
1286 for ( i = 0 ; i < primcount ; i++ ) {
1287 if ( count[i] > 0 ) {
1288 GLenum m = *((GLenum *) ((GLubyte *) mode + i * modestride));
1289 CALL_DrawArrays(ctx->Exec, ( m, first[i], count[i] ));
1290 }
1291 }
1292 }
1293
1294
1295 /* GL_IBM_multimode_draw_arrays */
1296 void GLAPIENTRY
1297 _mesa_MultiModeDrawElementsIBM( const GLenum * mode, const GLsizei * count,
1298 GLenum type, const GLvoid * const * indices,
1299 GLsizei primcount, GLint modestride )
1300 {
1301 GET_CURRENT_CONTEXT(ctx);
1302 GLint i;
1303
1304 ASSERT_OUTSIDE_BEGIN_END_AND_FLUSH(ctx);
1305
1306 /* XXX not sure about ARB_vertex_buffer_object handling here */
1307
1308 for ( i = 0 ; i < primcount ; i++ ) {
1309 if ( count[i] > 0 ) {
1310 GLenum m = *((GLenum *) ((GLubyte *) mode + i * modestride));
1311 CALL_DrawElements(ctx->Exec, ( m, count[i], type, indices[i] ));
1312 }
1313 }
1314 }
1315
1316
1317 /**
1318 * GL 3.1 glPrimitiveRestartIndex().
1319 */
1320 void GLAPIENTRY
1321 _mesa_PrimitiveRestartIndex(GLuint index)
1322 {
1323 GET_CURRENT_CONTEXT(ctx);
1324
1325 if (ctx->VersionMajor * 10 + ctx->VersionMinor < 31) {
1326 _mesa_error(ctx, GL_INVALID_OPERATION, "glPrimitiveRestartIndex()");
1327 return;
1328 }
1329
1330 ASSERT_OUTSIDE_BEGIN_END_AND_FLUSH(ctx);
1331
1332 FLUSH_VERTICES(ctx, _NEW_TRANSFORM);
1333
1334 ctx->Array.RestartIndex = index;
1335 }
1336
1337
1338 /**
1339 * Copy one client vertex array to another.
1340 */
1341 void
1342 _mesa_copy_client_array(struct gl_context *ctx,
1343 struct gl_client_array *dst,
1344 struct gl_client_array *src)
1345 {
1346 dst->Size = src->Size;
1347 dst->Type = src->Type;
1348 dst->Format = src->Format;
1349 dst->Stride = src->Stride;
1350 dst->StrideB = src->StrideB;
1351 dst->Ptr = src->Ptr;
1352 dst->Enabled = src->Enabled;
1353 dst->Normalized = src->Normalized;
1354 dst->_ElementSize = src->_ElementSize;
1355 _mesa_reference_buffer_object(ctx, &dst->BufferObj, src->BufferObj);
1356 dst->_MaxElement = src->_MaxElement;
1357 }
1358
1359
1360
1361 /**
1362 * Print vertex array's fields.
1363 */
1364 static void
1365 print_array(const char *name, GLint index, const struct gl_client_array *array)
1366 {
1367 if (index >= 0)
1368 printf(" %s[%d]: ", name, index);
1369 else
1370 printf(" %s: ", name);
1371 printf("Ptr=%p, Type=0x%x, Size=%d, ElemSize=%u, Stride=%d, Buffer=%u(Size %lu), MaxElem=%u\n",
1372 array->Ptr, array->Type, array->Size,
1373 array->_ElementSize, array->StrideB,
1374 array->BufferObj->Name, (unsigned long) array->BufferObj->Size,
1375 array->_MaxElement);
1376 }
1377
1378
1379 /**
1380 * Print current vertex object/array info. For debug.
1381 */
1382 void
1383 _mesa_print_arrays(struct gl_context *ctx)
1384 {
1385 struct gl_array_object *arrayObj = ctx->Array.ArrayObj;
1386 GLuint i;
1387
1388 _mesa_update_array_object_max_element(ctx, arrayObj);
1389
1390 printf("Array Object %u\n", arrayObj->Name);
1391 if (arrayObj->Vertex.Enabled)
1392 print_array("Vertex", -1, &arrayObj->Vertex);
1393 if (arrayObj->Normal.Enabled)
1394 print_array("Normal", -1, &arrayObj->Normal);
1395 if (arrayObj->Color.Enabled)
1396 print_array("Color", -1, &arrayObj->Color);
1397 for (i = 0; i < Elements(arrayObj->TexCoord); i++)
1398 if (arrayObj->TexCoord[i].Enabled)
1399 print_array("TexCoord", i, &arrayObj->TexCoord[i]);
1400 for (i = 0; i < Elements(arrayObj->VertexAttrib); i++)
1401 if (arrayObj->VertexAttrib[i].Enabled)
1402 print_array("Attrib", i, &arrayObj->VertexAttrib[i]);
1403 printf(" _MaxElement = %u\n", arrayObj->_MaxElement);
1404 }
1405
1406
1407 /**
1408 * Initialize vertex array state for given context.
1409 */
1410 void
1411 _mesa_init_varray(struct gl_context *ctx)
1412 {
1413 ctx->Array.DefaultArrayObj = _mesa_new_array_object(ctx, 0);
1414 _mesa_reference_array_object(ctx, &ctx->Array.ArrayObj,
1415 ctx->Array.DefaultArrayObj);
1416 ctx->Array.ActiveTexture = 0; /* GL_ARB_multitexture */
1417
1418 ctx->Array.Objects = _mesa_NewHashTable();
1419 }
1420
1421
1422 /**
1423 * Callback for deleting an array object. Called by _mesa_HashDeleteAll().
1424 */
1425 static void
1426 delete_arrayobj_cb(GLuint id, void *data, void *userData)
1427 {
1428 struct gl_array_object *arrayObj = (struct gl_array_object *) data;
1429 struct gl_context *ctx = (struct gl_context *) userData;
1430 _mesa_delete_array_object(ctx, arrayObj);
1431 }
1432
1433
1434 /**
1435 * Free vertex array state for given context.
1436 */
1437 void
1438 _mesa_free_varray_data(struct gl_context *ctx)
1439 {
1440 _mesa_HashDeleteAll(ctx->Array.Objects, delete_arrayobj_cb, ctx);
1441 _mesa_DeleteHashTable(ctx->Array.Objects);
1442 }