Merge branch 'mesa_7_6_branch' into mesa_7_7_branch
[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 "mtypes.h"
35 #include "varray.h"
36 #include "arrayobj.h"
37 #include "glapi/dispatch.h"
38
39
40 /**
41 * Set the fields of a vertex array.
42 * Also do an error check for GL_ARB_vertex_array_object: check that
43 * all arrays reside in VBOs when using a vertex array object.
44 *
45 * \param array the array to update
46 * \param dirtyBit which bit to set in ctx->Array.NewState for this array
47 * \param elementSize size of each array element, in bytes
48 * \param size components per element (1, 2, 3 or 4)
49 * \param type datatype of each component (GL_FLOAT, GL_INT, etc)
50 * \param format either GL_RGBA or GL_BGRA
51 * \param stride stride between elements, in elements
52 * \param normalized are integer types converted to floats in [-1, 1]?
53 * \param ptr the address (or offset inside VBO) of the array data
54 */
55 static void
56 update_array(GLcontext *ctx, struct gl_client_array *array,
57 GLbitfield dirtyBit, GLsizei elementSize,
58 GLint size, GLenum type, GLenum format,
59 GLsizei stride, GLboolean normalized, const GLvoid *ptr)
60 {
61 ASSERT(format == GL_RGBA || format == GL_BGRA);
62
63 if (ctx->Array.ArrayObj->VBOonly &&
64 ctx->Array.ArrayBufferObj->Name == 0) {
65 /* GL_ARB_vertex_array_object requires that all arrays reside in VBOs.
66 * Generate GL_INVALID_OPERATION if that's not true.
67 */
68 _mesa_error(ctx, GL_INVALID_OPERATION,
69 "glVertex/Normal/EtcPointer(non-VBO array)");
70 return;
71 }
72
73 array->Size = size;
74 array->Type = type;
75 array->Format = format;
76 array->Stride = stride;
77 array->StrideB = stride ? stride : elementSize;
78 array->Normalized = normalized;
79 array->Ptr = (const GLubyte *) ptr;
80 array->_ElementSize = elementSize;
81
82 _mesa_reference_buffer_object(ctx, &array->BufferObj,
83 ctx->Array.ArrayBufferObj);
84
85 ctx->NewState |= _NEW_ARRAY;
86 ctx->Array.NewState |= dirtyBit;
87 }
88
89
90 void GLAPIENTRY
91 _mesa_VertexPointer(GLint size, GLenum type, GLsizei stride, const GLvoid *ptr)
92 {
93 GLsizei elementSize;
94 GET_CURRENT_CONTEXT(ctx);
95 ASSERT_OUTSIDE_BEGIN_END_AND_FLUSH(ctx);
96
97 if (size < 2 || size > 4) {
98 _mesa_error( ctx, GL_INVALID_VALUE, "glVertexPointer(size)" );
99 return;
100 }
101 if (stride < 0) {
102 _mesa_error( ctx, GL_INVALID_VALUE, "glVertexPointer(stride)" );
103 return;
104 }
105
106 if (MESA_VERBOSE&(VERBOSE_VARRAY|VERBOSE_API))
107 _mesa_debug(ctx, "glVertexPointer( sz %d type %s stride %d )\n", size,
108 _mesa_lookup_enum_by_nr( type ), stride);
109
110 /* always need to check that <type> is legal */
111 switch (type) {
112 case GL_SHORT:
113 elementSize = size * sizeof(GLshort);
114 break;
115 case GL_INT:
116 elementSize = size * sizeof(GLint);
117 break;
118 case GL_FLOAT:
119 elementSize = size * sizeof(GLfloat);
120 break;
121 case GL_DOUBLE:
122 elementSize = size * sizeof(GLdouble);
123 break;
124 #if FEATURE_fixedpt
125 case GL_FIXED:
126 elementSize = size * sizeof(GLfixed);
127 break;
128 #endif
129 #if FEATURE_vertex_array_byte
130 case GL_BYTE:
131 elementSize = size * sizeof(GLbyte);
132 break;
133 #endif
134 default:
135 _mesa_error( ctx, GL_INVALID_ENUM, "glVertexPointer(type=%s)",
136 _mesa_lookup_enum_by_nr(type));
137 return;
138 }
139
140 update_array(ctx, &ctx->Array.ArrayObj->Vertex, _NEW_ARRAY_VERTEX,
141 elementSize, size, type, GL_RGBA, stride, GL_FALSE, ptr);
142 }
143
144
145 void GLAPIENTRY
146 _mesa_NormalPointer(GLenum type, GLsizei stride, const GLvoid *ptr )
147 {
148 GLsizei elementSize;
149 GET_CURRENT_CONTEXT(ctx);
150 ASSERT_OUTSIDE_BEGIN_END_AND_FLUSH(ctx);
151
152 if (stride < 0) {
153 _mesa_error( ctx, GL_INVALID_VALUE, "glNormalPointer(stride)" );
154 return;
155 }
156
157 if (MESA_VERBOSE&(VERBOSE_VARRAY|VERBOSE_API))
158 _mesa_debug(ctx, "glNormalPointer( type %s stride %d )\n",
159 _mesa_lookup_enum_by_nr( type ), stride);
160
161 switch (type) {
162 case GL_BYTE:
163 elementSize = 3 * sizeof(GLbyte);
164 break;
165 case GL_SHORT:
166 elementSize = 3 * sizeof(GLshort);
167 break;
168 case GL_INT:
169 elementSize = 3 * sizeof(GLint);
170 break;
171 case GL_FLOAT:
172 elementSize = 3 * sizeof(GLfloat);
173 break;
174 case GL_DOUBLE:
175 elementSize = 3 * sizeof(GLdouble);
176 break;
177 #if FEATURE_fixedpt
178 case GL_FIXED:
179 elementSize = 3 * sizeof(GLfixed);
180 break;
181 #endif
182 default:
183 _mesa_error( ctx, GL_INVALID_ENUM, "glNormalPointer(type=%s)",
184 _mesa_lookup_enum_by_nr(type));
185 return;
186 }
187
188 update_array(ctx, &ctx->Array.ArrayObj->Normal, _NEW_ARRAY_NORMAL,
189 elementSize, 3, type, GL_RGBA, stride, GL_TRUE, ptr);
190 }
191
192
193 void GLAPIENTRY
194 _mesa_ColorPointer(GLint size, GLenum type, GLsizei stride, const GLvoid *ptr)
195 {
196 GLsizei elementSize;
197 GLenum format;
198 GET_CURRENT_CONTEXT(ctx);
199 ASSERT_OUTSIDE_BEGIN_END_AND_FLUSH(ctx);
200
201 if (size < 3 || size > 4) {
202 if (!ctx->Extensions.EXT_vertex_array_bgra || size != GL_BGRA) {
203 _mesa_error(ctx, GL_INVALID_VALUE, "glColorPointer(size)");
204 return;
205 }
206 }
207 if (stride < 0) {
208 _mesa_error( ctx, GL_INVALID_VALUE, "glColorPointer(stride)" );
209 return;
210 }
211
212 if (MESA_VERBOSE&(VERBOSE_VARRAY|VERBOSE_API))
213 _mesa_debug(ctx, "glColorPointer( sz %d type %s stride %d )\n", size,
214 _mesa_lookup_enum_by_nr( type ), stride);
215
216 if (size == GL_BGRA) {
217 if (type != GL_UNSIGNED_BYTE) {
218 _mesa_error(ctx, GL_INVALID_VALUE, "glColorPointer(GL_BGRA/GLubyte)");
219 return;
220 }
221 format = GL_BGRA;
222 size = 4;
223 }
224 else {
225 format = GL_RGBA;
226 }
227
228 switch (type) {
229 case GL_BYTE:
230 elementSize = size * sizeof(GLbyte);
231 break;
232 case GL_UNSIGNED_BYTE:
233 elementSize = size * sizeof(GLubyte);
234 break;
235 case GL_SHORT:
236 elementSize = size * sizeof(GLshort);
237 break;
238 case GL_UNSIGNED_SHORT:
239 elementSize = size * sizeof(GLushort);
240 break;
241 case GL_INT:
242 elementSize = size * sizeof(GLint);
243 break;
244 case GL_UNSIGNED_INT:
245 elementSize = size * sizeof(GLuint);
246 break;
247 case GL_FLOAT:
248 elementSize = size * sizeof(GLfloat);
249 break;
250 case GL_DOUBLE:
251 elementSize = size * sizeof(GLdouble);
252 break;
253 #if FEATURE_fixedpt
254 case GL_FIXED:
255 elementSize = size * sizeof(GLfixed);
256 break;
257 #endif
258 default:
259 _mesa_error( ctx, GL_INVALID_ENUM, "glColorPointer(type=%s)",
260 _mesa_lookup_enum_by_nr(type));
261 return;
262 }
263
264 update_array(ctx, &ctx->Array.ArrayObj->Color, _NEW_ARRAY_COLOR0,
265 elementSize, size, type, format, stride, GL_TRUE, ptr);
266 }
267
268
269 void GLAPIENTRY
270 _mesa_FogCoordPointerEXT(GLenum type, GLsizei stride, const GLvoid *ptr)
271 {
272 GLint elementSize;
273 GET_CURRENT_CONTEXT(ctx);
274 ASSERT_OUTSIDE_BEGIN_END_AND_FLUSH(ctx);
275
276 if (stride < 0) {
277 _mesa_error( ctx, GL_INVALID_VALUE, "glFogCoordPointer(stride)" );
278 return;
279 }
280
281 switch (type) {
282 case GL_FLOAT:
283 elementSize = sizeof(GLfloat);
284 break;
285 case GL_DOUBLE:
286 elementSize = sizeof(GLdouble);
287 break;
288 default:
289 _mesa_error( ctx, GL_INVALID_ENUM, "glFogCoordPointer(type)" );
290 return;
291 }
292
293 update_array(ctx, &ctx->Array.ArrayObj->FogCoord, _NEW_ARRAY_FOGCOORD,
294 elementSize, 1, type, GL_RGBA, stride, GL_FALSE, ptr);
295 }
296
297
298 void GLAPIENTRY
299 _mesa_IndexPointer(GLenum type, GLsizei stride, const GLvoid *ptr)
300 {
301 GLsizei elementSize;
302 GET_CURRENT_CONTEXT(ctx);
303 ASSERT_OUTSIDE_BEGIN_END_AND_FLUSH(ctx);
304
305 if (stride < 0) {
306 _mesa_error( ctx, GL_INVALID_VALUE, "glIndexPointer(stride)" );
307 return;
308 }
309
310 switch (type) {
311 case GL_UNSIGNED_BYTE:
312 elementSize = sizeof(GLubyte);
313 break;
314 case GL_SHORT:
315 elementSize = sizeof(GLshort);
316 break;
317 case GL_INT:
318 elementSize = sizeof(GLint);
319 break;
320 case GL_FLOAT:
321 elementSize = sizeof(GLfloat);
322 break;
323 case GL_DOUBLE:
324 elementSize = sizeof(GLdouble);
325 break;
326 default:
327 _mesa_error( ctx, GL_INVALID_ENUM, "glIndexPointer(type)" );
328 return;
329 }
330
331 update_array(ctx, &ctx->Array.ArrayObj->Index, _NEW_ARRAY_INDEX,
332 elementSize, 1, type, GL_RGBA, stride, GL_FALSE, ptr);
333 }
334
335
336 void GLAPIENTRY
337 _mesa_SecondaryColorPointerEXT(GLint size, GLenum type,
338 GLsizei stride, const GLvoid *ptr)
339 {
340 GLsizei elementSize;
341 GLenum format;
342 GET_CURRENT_CONTEXT(ctx);
343 ASSERT_OUTSIDE_BEGIN_END_AND_FLUSH(ctx);
344
345 if (size != 3 && size != 4) {
346 if (!ctx->Extensions.EXT_vertex_array_bgra || size != GL_BGRA) {
347 _mesa_error(ctx, GL_INVALID_VALUE, "glSecondaryColorPointer(size)");
348 return;
349 }
350 }
351 if (stride < 0) {
352 _mesa_error( ctx, GL_INVALID_VALUE, "glSecondaryColorPointer(stride)" );
353 return;
354 }
355
356 if (MESA_VERBOSE&(VERBOSE_VARRAY|VERBOSE_API))
357 _mesa_debug(ctx, "glSecondaryColorPointer( sz %d type %s stride %d )\n",
358 size, _mesa_lookup_enum_by_nr( type ), stride);
359
360 if (size == GL_BGRA) {
361 if (type != GL_UNSIGNED_BYTE) {
362 _mesa_error(ctx, GL_INVALID_VALUE, "glColorPointer(GL_BGRA/GLubyte)");
363 return;
364 }
365 format = GL_BGRA;
366 size = 4;
367 }
368 else {
369 format = GL_RGBA;
370 }
371
372 switch (type) {
373 case GL_BYTE:
374 elementSize = size * sizeof(GLbyte);
375 break;
376 case GL_UNSIGNED_BYTE:
377 elementSize = size * sizeof(GLubyte);
378 break;
379 case GL_SHORT:
380 elementSize = size * sizeof(GLshort);
381 break;
382 case GL_UNSIGNED_SHORT:
383 elementSize = size * sizeof(GLushort);
384 break;
385 case GL_INT:
386 elementSize = size * sizeof(GLint);
387 break;
388 case GL_UNSIGNED_INT:
389 elementSize = size * sizeof(GLuint);
390 break;
391 case GL_FLOAT:
392 elementSize = size * sizeof(GLfloat);
393 break;
394 case GL_DOUBLE:
395 elementSize = size * sizeof(GLdouble);
396 break;
397 default:
398 _mesa_error( ctx, GL_INVALID_ENUM, "glSecondaryColorPointer(type=%s)",
399 _mesa_lookup_enum_by_nr(type));
400 return;
401 }
402
403 update_array(ctx, &ctx->Array.ArrayObj->SecondaryColor, _NEW_ARRAY_COLOR1,
404 elementSize, size, type, format, stride, GL_TRUE, ptr);
405 }
406
407
408 void GLAPIENTRY
409 _mesa_TexCoordPointer(GLint size, GLenum type, GLsizei stride,
410 const GLvoid *ptr)
411 {
412 GLint elementSize;
413 GET_CURRENT_CONTEXT(ctx);
414 const GLuint unit = ctx->Array.ActiveTexture;
415 ASSERT_OUTSIDE_BEGIN_END_AND_FLUSH(ctx);
416
417 if (size < 1 || size > 4) {
418 _mesa_error( ctx, GL_INVALID_VALUE, "glTexCoordPointer(size)" );
419 return;
420 }
421 if (stride < 0) {
422 _mesa_error( ctx, GL_INVALID_VALUE, "glTexCoordPointer(stride)" );
423 return;
424 }
425
426 if (MESA_VERBOSE&(VERBOSE_VARRAY|VERBOSE_API))
427 _mesa_debug(ctx, "glTexCoordPointer(unit %u sz %d type %s stride %d)\n",
428 unit, size, _mesa_lookup_enum_by_nr( type ), stride);
429
430 /* always need to check that <type> is legal */
431 switch (type) {
432 case GL_SHORT:
433 elementSize = size * sizeof(GLshort);
434 break;
435 case GL_INT:
436 elementSize = size * sizeof(GLint);
437 break;
438 case GL_FLOAT:
439 elementSize = size * sizeof(GLfloat);
440 break;
441 case GL_DOUBLE:
442 elementSize = size * sizeof(GLdouble);
443 break;
444 #if FEATURE_fixedpt
445 case GL_FIXED:
446 elementSize = size * sizeof(GLfixed);
447 break;
448 #endif
449 #if FEATURE_vertex_array_byte
450 case GL_BYTE:
451 elementSize = size * sizeof(GLbyte);
452 break;
453 #endif
454 default:
455 _mesa_error( ctx, GL_INVALID_ENUM, "glTexCoordPointer(type=%s)",
456 _mesa_lookup_enum_by_nr(type));
457 return;
458 }
459
460 update_array(ctx, &ctx->Array.ArrayObj->TexCoord[unit],
461 _NEW_ARRAY_TEXCOORD(unit),
462 elementSize, size, type, GL_RGBA, stride, GL_FALSE, ptr);
463 }
464
465
466 void GLAPIENTRY
467 _mesa_EdgeFlagPointer(GLsizei stride, const GLvoid *ptr)
468 {
469 GET_CURRENT_CONTEXT(ctx);
470 ASSERT_OUTSIDE_BEGIN_END_AND_FLUSH(ctx);
471
472 if (stride < 0) {
473 _mesa_error( ctx, GL_INVALID_VALUE, "glEdgeFlagPointer(stride)" );
474 return;
475 }
476
477 update_array(ctx, &ctx->Array.ArrayObj->EdgeFlag, _NEW_ARRAY_EDGEFLAG,
478 sizeof(GLboolean), 1, GL_UNSIGNED_BYTE, GL_RGBA,
479 stride, GL_FALSE, ptr);
480 }
481
482
483 void GLAPIENTRY
484 _mesa_PointSizePointer(GLenum type, GLsizei stride, const GLvoid *ptr)
485 {
486 GLsizei elementSize;
487 GET_CURRENT_CONTEXT(ctx);
488 ASSERT_OUTSIDE_BEGIN_END_AND_FLUSH(ctx);
489
490 if (stride < 0) {
491 _mesa_error( ctx, GL_INVALID_VALUE, "glPointSizePointer(stride)" );
492 return;
493 }
494
495 switch (type) {
496 case GL_FLOAT:
497 elementSize = sizeof(GLfloat);
498 break;
499 #if FEATURE_fixedpt
500 case GL_FIXED:
501 elementSize = sizeof(GLfixed);
502 break;
503 #endif
504 default:
505 _mesa_error( ctx, GL_INVALID_ENUM, "glPointSizePointer(type)" );
506 return;
507 }
508
509 update_array(ctx, &ctx->Array.ArrayObj->PointSize, _NEW_ARRAY_POINT_SIZE,
510 elementSize, 1, type, GL_RGBA, stride, GL_FALSE, ptr);
511 }
512
513
514 #if FEATURE_NV_vertex_program
515 /**
516 * Set a vertex attribute array.
517 * Note that these arrays DO alias the conventional GL vertex arrays
518 * (position, normal, color, fog, texcoord, etc).
519 * The generic attribute slots at #16 and above are not touched.
520 */
521 void GLAPIENTRY
522 _mesa_VertexAttribPointerNV(GLuint index, GLint size, GLenum type,
523 GLsizei stride, const GLvoid *ptr)
524 {
525 GLboolean normalized = GL_FALSE;
526 GLsizei elementSize;
527 GLenum format;
528 GET_CURRENT_CONTEXT(ctx);
529 ASSERT_OUTSIDE_BEGIN_END(ctx);
530
531 if (index >= MAX_NV_VERTEX_PROGRAM_INPUTS) {
532 _mesa_error(ctx, GL_INVALID_VALUE, "glVertexAttribPointerNV(index)");
533 return;
534 }
535
536 if (size < 1 || size > 4) {
537 _mesa_error(ctx, GL_INVALID_VALUE, "glVertexAttribPointerNV(size)");
538 return;
539 }
540
541 if (stride < 0) {
542 _mesa_error(ctx, GL_INVALID_VALUE, "glVertexAttribPointerNV(stride)");
543 return;
544 }
545
546 if (type == GL_UNSIGNED_BYTE && size != 4) {
547 _mesa_error(ctx, GL_INVALID_VALUE, "glVertexAttribPointerNV(size!=4)");
548 return;
549 }
550
551 if (size == GL_BGRA) {
552 if (type != GL_UNSIGNED_BYTE) {
553 _mesa_error(ctx, GL_INVALID_VALUE,
554 "glVertexAttribPointerNV(GL_BGRA/type)");
555 return;
556 }
557
558 format = GL_BGRA;
559 size = 4;
560 normalized = GL_TRUE;
561 }
562 else {
563 format = GL_RGBA;
564 }
565
566 /* check for valid 'type' and compute StrideB right away */
567 switch (type) {
568 case GL_UNSIGNED_BYTE:
569 normalized = GL_TRUE;
570 elementSize = size * sizeof(GLubyte);
571 break;
572 case GL_SHORT:
573 elementSize = size * sizeof(GLshort);
574 break;
575 case GL_FLOAT:
576 elementSize = size * sizeof(GLfloat);
577 break;
578 case GL_DOUBLE:
579 elementSize = size * sizeof(GLdouble);
580 break;
581 default:
582 _mesa_error( ctx, GL_INVALID_ENUM, "glVertexAttribPointerNV(type=%s)",
583 _mesa_lookup_enum_by_nr(type));
584 return;
585 }
586
587 update_array(ctx, &ctx->Array.ArrayObj->VertexAttrib[index],
588 _NEW_ARRAY_ATTRIB(index),
589 elementSize, size, type, format, stride, normalized, ptr);
590 }
591 #endif
592
593
594 #if FEATURE_ARB_vertex_program
595 /**
596 * Set a generic vertex attribute array.
597 * Note that these arrays DO NOT alias the conventional GL vertex arrays
598 * (position, normal, color, fog, texcoord, etc).
599 */
600 void GLAPIENTRY
601 _mesa_VertexAttribPointerARB(GLuint index, GLint size, GLenum type,
602 GLboolean normalized,
603 GLsizei stride, const GLvoid *ptr)
604 {
605 GLsizei elementSize;
606 GLenum format;
607 GET_CURRENT_CONTEXT(ctx);
608 ASSERT_OUTSIDE_BEGIN_END(ctx);
609
610 if (index >= ctx->Const.VertexProgram.MaxAttribs) {
611 _mesa_error(ctx, GL_INVALID_VALUE, "glVertexAttribPointerARB(index)");
612 return;
613 }
614
615 if (size < 1 || size > 4) {
616 if (!ctx->Extensions.EXT_vertex_array_bgra || size != GL_BGRA) {
617 _mesa_error(ctx, GL_INVALID_VALUE, "glVertexAttribPointerARB(size)");
618 return;
619 }
620 }
621
622 if (stride < 0) {
623 _mesa_error(ctx, GL_INVALID_VALUE, "glVertexAttribPointerARB(stride)");
624 return;
625 }
626
627 if (size == GL_BGRA) {
628 if (type != GL_UNSIGNED_BYTE) {
629 _mesa_error(ctx, GL_INVALID_VALUE,
630 "glVertexAttribPointerARB(GL_BGRA/type)");
631 return;
632 }
633 if (normalized != GL_TRUE) {
634 _mesa_error(ctx, GL_INVALID_VALUE,
635 "glVertexAttribPointerARB(GL_BGRA/normalized)");
636 return;
637 }
638
639 format = GL_BGRA;
640 size = 4;
641 }
642 else {
643 format = GL_RGBA;
644 }
645
646 /* check for valid 'type' and compute StrideB right away */
647 /* NOTE: more types are supported here than in the NV extension */
648 switch (type) {
649 case GL_BYTE:
650 elementSize = size * sizeof(GLbyte);
651 break;
652 case GL_UNSIGNED_BYTE:
653 elementSize = size * sizeof(GLubyte);
654 break;
655 case GL_SHORT:
656 elementSize = size * sizeof(GLshort);
657 break;
658 case GL_UNSIGNED_SHORT:
659 elementSize = size * sizeof(GLushort);
660 break;
661 case GL_INT:
662 elementSize = size * sizeof(GLint);
663 break;
664 case GL_UNSIGNED_INT:
665 elementSize = size * sizeof(GLuint);
666 break;
667 case GL_FLOAT:
668 elementSize = size * sizeof(GLfloat);
669 break;
670 case GL_DOUBLE:
671 elementSize = size * sizeof(GLdouble);
672 break;
673 #if FEATURE_fixedpt
674 case GL_FIXED:
675 elementSize = size * sizeof(GLfixed);
676 break;
677 #endif
678 default:
679 _mesa_error( ctx, GL_INVALID_ENUM, "glVertexAttribPointerARB(type)" );
680 return;
681 }
682
683 update_array(ctx, &ctx->Array.ArrayObj->VertexAttrib[index],
684 _NEW_ARRAY_ATTRIB(index),
685 elementSize, size, type, format, stride, normalized, ptr);
686 }
687 #endif
688
689
690 void GLAPIENTRY
691 _mesa_VertexPointerEXT(GLint size, GLenum type, GLsizei stride,
692 GLsizei count, const GLvoid *ptr)
693 {
694 (void) count;
695 _mesa_VertexPointer(size, type, stride, ptr);
696 }
697
698
699 void GLAPIENTRY
700 _mesa_NormalPointerEXT(GLenum type, GLsizei stride, GLsizei count,
701 const GLvoid *ptr)
702 {
703 (void) count;
704 _mesa_NormalPointer(type, stride, ptr);
705 }
706
707
708 void GLAPIENTRY
709 _mesa_ColorPointerEXT(GLint size, GLenum type, GLsizei stride, GLsizei count,
710 const GLvoid *ptr)
711 {
712 (void) count;
713 _mesa_ColorPointer(size, type, stride, ptr);
714 }
715
716
717 void GLAPIENTRY
718 _mesa_IndexPointerEXT(GLenum type, GLsizei stride, GLsizei count,
719 const GLvoid *ptr)
720 {
721 (void) count;
722 _mesa_IndexPointer(type, stride, ptr);
723 }
724
725
726 void GLAPIENTRY
727 _mesa_TexCoordPointerEXT(GLint size, GLenum type, GLsizei stride,
728 GLsizei count, const GLvoid *ptr)
729 {
730 (void) count;
731 _mesa_TexCoordPointer(size, type, stride, ptr);
732 }
733
734
735 void GLAPIENTRY
736 _mesa_EdgeFlagPointerEXT(GLsizei stride, GLsizei count, const GLboolean *ptr)
737 {
738 (void) count;
739 _mesa_EdgeFlagPointer(stride, ptr);
740 }
741
742
743 void GLAPIENTRY
744 _mesa_InterleavedArrays(GLenum format, GLsizei stride, const GLvoid *pointer)
745 {
746 GET_CURRENT_CONTEXT(ctx);
747 GLboolean tflag, cflag, nflag; /* enable/disable flags */
748 GLint tcomps, ccomps, vcomps; /* components per texcoord, color, vertex */
749 GLenum ctype = 0; /* color type */
750 GLint coffset = 0, noffset = 0, voffset;/* color, normal, vertex offsets */
751 const GLint toffset = 0; /* always zero */
752 GLint defstride; /* default stride */
753 GLint c, f;
754
755 ASSERT_OUTSIDE_BEGIN_END_AND_FLUSH(ctx);
756
757 f = sizeof(GLfloat);
758 c = f * ((4 * sizeof(GLubyte) + (f - 1)) / f);
759
760 if (stride < 0) {
761 _mesa_error( ctx, GL_INVALID_VALUE, "glInterleavedArrays(stride)" );
762 return;
763 }
764
765 switch (format) {
766 case GL_V2F:
767 tflag = GL_FALSE; cflag = GL_FALSE; nflag = GL_FALSE;
768 tcomps = 0; ccomps = 0; vcomps = 2;
769 voffset = 0;
770 defstride = 2*f;
771 break;
772 case GL_V3F:
773 tflag = GL_FALSE; cflag = GL_FALSE; nflag = GL_FALSE;
774 tcomps = 0; ccomps = 0; vcomps = 3;
775 voffset = 0;
776 defstride = 3*f;
777 break;
778 case GL_C4UB_V2F:
779 tflag = GL_FALSE; cflag = GL_TRUE; nflag = GL_FALSE;
780 tcomps = 0; ccomps = 4; vcomps = 2;
781 ctype = GL_UNSIGNED_BYTE;
782 coffset = 0;
783 voffset = c;
784 defstride = c + 2*f;
785 break;
786 case GL_C4UB_V3F:
787 tflag = GL_FALSE; cflag = GL_TRUE; nflag = GL_FALSE;
788 tcomps = 0; ccomps = 4; vcomps = 3;
789 ctype = GL_UNSIGNED_BYTE;
790 coffset = 0;
791 voffset = c;
792 defstride = c + 3*f;
793 break;
794 case GL_C3F_V3F:
795 tflag = GL_FALSE; cflag = GL_TRUE; nflag = GL_FALSE;
796 tcomps = 0; ccomps = 3; vcomps = 3;
797 ctype = GL_FLOAT;
798 coffset = 0;
799 voffset = 3*f;
800 defstride = 6*f;
801 break;
802 case GL_N3F_V3F:
803 tflag = GL_FALSE; cflag = GL_FALSE; nflag = GL_TRUE;
804 tcomps = 0; ccomps = 0; vcomps = 3;
805 noffset = 0;
806 voffset = 3*f;
807 defstride = 6*f;
808 break;
809 case GL_C4F_N3F_V3F:
810 tflag = GL_FALSE; cflag = GL_TRUE; nflag = GL_TRUE;
811 tcomps = 0; ccomps = 4; vcomps = 3;
812 ctype = GL_FLOAT;
813 coffset = 0;
814 noffset = 4*f;
815 voffset = 7*f;
816 defstride = 10*f;
817 break;
818 case GL_T2F_V3F:
819 tflag = GL_TRUE; cflag = GL_FALSE; nflag = GL_FALSE;
820 tcomps = 2; ccomps = 0; vcomps = 3;
821 voffset = 2*f;
822 defstride = 5*f;
823 break;
824 case GL_T4F_V4F:
825 tflag = GL_TRUE; cflag = GL_FALSE; nflag = GL_FALSE;
826 tcomps = 4; ccomps = 0; vcomps = 4;
827 voffset = 4*f;
828 defstride = 8*f;
829 break;
830 case GL_T2F_C4UB_V3F:
831 tflag = GL_TRUE; cflag = GL_TRUE; nflag = GL_FALSE;
832 tcomps = 2; ccomps = 4; vcomps = 3;
833 ctype = GL_UNSIGNED_BYTE;
834 coffset = 2*f;
835 voffset = c+2*f;
836 defstride = c+5*f;
837 break;
838 case GL_T2F_C3F_V3F:
839 tflag = GL_TRUE; cflag = GL_TRUE; nflag = GL_FALSE;
840 tcomps = 2; ccomps = 3; vcomps = 3;
841 ctype = GL_FLOAT;
842 coffset = 2*f;
843 voffset = 5*f;
844 defstride = 8*f;
845 break;
846 case GL_T2F_N3F_V3F:
847 tflag = GL_TRUE; cflag = GL_FALSE; nflag = GL_TRUE;
848 tcomps = 2; ccomps = 0; vcomps = 3;
849 noffset = 2*f;
850 voffset = 5*f;
851 defstride = 8*f;
852 break;
853 case GL_T2F_C4F_N3F_V3F:
854 tflag = GL_TRUE; cflag = GL_TRUE; nflag = GL_TRUE;
855 tcomps = 2; ccomps = 4; vcomps = 3;
856 ctype = GL_FLOAT;
857 coffset = 2*f;
858 noffset = 6*f;
859 voffset = 9*f;
860 defstride = 12*f;
861 break;
862 case GL_T4F_C4F_N3F_V4F:
863 tflag = GL_TRUE; cflag = GL_TRUE; nflag = GL_TRUE;
864 tcomps = 4; ccomps = 4; vcomps = 4;
865 ctype = GL_FLOAT;
866 coffset = 4*f;
867 noffset = 8*f;
868 voffset = 11*f;
869 defstride = 15*f;
870 break;
871 default:
872 _mesa_error( ctx, GL_INVALID_ENUM, "glInterleavedArrays(format)" );
873 return;
874 }
875
876 if (stride==0) {
877 stride = defstride;
878 }
879
880 _mesa_DisableClientState( GL_EDGE_FLAG_ARRAY );
881 _mesa_DisableClientState( GL_INDEX_ARRAY );
882 /* XXX also disable secondary color and generic arrays? */
883
884 /* Texcoords */
885 if (tflag) {
886 _mesa_EnableClientState( GL_TEXTURE_COORD_ARRAY );
887 _mesa_TexCoordPointer( tcomps, GL_FLOAT, stride,
888 (GLubyte *) pointer + toffset );
889 }
890 else {
891 _mesa_DisableClientState( GL_TEXTURE_COORD_ARRAY );
892 }
893
894 /* Color */
895 if (cflag) {
896 _mesa_EnableClientState( GL_COLOR_ARRAY );
897 _mesa_ColorPointer( ccomps, ctype, stride,
898 (GLubyte *) pointer + coffset );
899 }
900 else {
901 _mesa_DisableClientState( GL_COLOR_ARRAY );
902 }
903
904
905 /* Normals */
906 if (nflag) {
907 _mesa_EnableClientState( GL_NORMAL_ARRAY );
908 _mesa_NormalPointer( GL_FLOAT, stride, (GLubyte *) pointer + noffset );
909 }
910 else {
911 _mesa_DisableClientState( GL_NORMAL_ARRAY );
912 }
913
914 /* Vertices */
915 _mesa_EnableClientState( GL_VERTEX_ARRAY );
916 _mesa_VertexPointer( vcomps, GL_FLOAT, stride,
917 (GLubyte *) pointer + voffset );
918 }
919
920
921 void GLAPIENTRY
922 _mesa_LockArraysEXT(GLint first, GLsizei count)
923 {
924 GET_CURRENT_CONTEXT(ctx);
925 ASSERT_OUTSIDE_BEGIN_END_AND_FLUSH(ctx);
926
927 if (MESA_VERBOSE & VERBOSE_API)
928 _mesa_debug(ctx, "glLockArrays %d %d\n", first, count);
929
930 if (first < 0) {
931 _mesa_error( ctx, GL_INVALID_VALUE, "glLockArraysEXT(first)" );
932 return;
933 }
934 if (count <= 0) {
935 _mesa_error( ctx, GL_INVALID_VALUE, "glLockArraysEXT(count)" );
936 return;
937 }
938 if (ctx->Array.LockCount != 0) {
939 _mesa_error( ctx, GL_INVALID_OPERATION, "glLockArraysEXT(reentry)" );
940 return;
941 }
942
943 ctx->Array.LockFirst = first;
944 ctx->Array.LockCount = count;
945
946 ctx->NewState |= _NEW_ARRAY;
947 ctx->Array.NewState |= _NEW_ARRAY_ALL;
948 }
949
950
951 void GLAPIENTRY
952 _mesa_UnlockArraysEXT( void )
953 {
954 GET_CURRENT_CONTEXT(ctx);
955 ASSERT_OUTSIDE_BEGIN_END_AND_FLUSH(ctx);
956
957 if (MESA_VERBOSE & VERBOSE_API)
958 _mesa_debug(ctx, "glUnlockArrays\n");
959
960 if (ctx->Array.LockCount == 0) {
961 _mesa_error( ctx, GL_INVALID_OPERATION, "glUnlockArraysEXT(reexit)" );
962 return;
963 }
964
965 ctx->Array.LockFirst = 0;
966 ctx->Array.LockCount = 0;
967 ctx->NewState |= _NEW_ARRAY;
968 ctx->Array.NewState |= _NEW_ARRAY_ALL;
969 }
970
971
972 /* GL_EXT_multi_draw_arrays */
973 /* Somebody forgot to spec the first and count parameters as const! <sigh> */
974 void GLAPIENTRY
975 _mesa_MultiDrawArraysEXT( GLenum mode, GLint *first,
976 GLsizei *count, GLsizei primcount )
977 {
978 GET_CURRENT_CONTEXT(ctx);
979 GLint i;
980
981 ASSERT_OUTSIDE_BEGIN_END_AND_FLUSH(ctx);
982
983 for (i = 0; i < primcount; i++) {
984 if (count[i] > 0) {
985 CALL_DrawArrays(ctx->Exec, (mode, first[i], count[i]));
986 }
987 }
988 }
989
990
991 /* GL_IBM_multimode_draw_arrays */
992 void GLAPIENTRY
993 _mesa_MultiModeDrawArraysIBM( const GLenum * mode, const GLint * first,
994 const GLsizei * count,
995 GLsizei primcount, GLint modestride )
996 {
997 GET_CURRENT_CONTEXT(ctx);
998 GLint i;
999
1000 ASSERT_OUTSIDE_BEGIN_END_AND_FLUSH(ctx);
1001
1002 for ( i = 0 ; i < primcount ; i++ ) {
1003 if ( count[i] > 0 ) {
1004 GLenum m = *((GLenum *) ((GLubyte *) mode + i * modestride));
1005 CALL_DrawArrays(ctx->Exec, ( m, first[i], count[i] ));
1006 }
1007 }
1008 }
1009
1010
1011 /* GL_IBM_multimode_draw_arrays */
1012 void GLAPIENTRY
1013 _mesa_MultiModeDrawElementsIBM( const GLenum * mode, const GLsizei * count,
1014 GLenum type, const GLvoid * const * indices,
1015 GLsizei primcount, GLint modestride )
1016 {
1017 GET_CURRENT_CONTEXT(ctx);
1018 GLint i;
1019
1020 ASSERT_OUTSIDE_BEGIN_END_AND_FLUSH(ctx);
1021
1022 /* XXX not sure about ARB_vertex_buffer_object handling here */
1023
1024 for ( i = 0 ; i < primcount ; i++ ) {
1025 if ( count[i] > 0 ) {
1026 GLenum m = *((GLenum *) ((GLubyte *) mode + i * modestride));
1027 CALL_DrawElements(ctx->Exec, ( m, count[i], type, indices[i] ));
1028 }
1029 }
1030 }
1031
1032
1033 /**
1034 * Copy one client vertex array to another.
1035 */
1036 void
1037 _mesa_copy_client_array(GLcontext *ctx,
1038 struct gl_client_array *dst,
1039 struct gl_client_array *src)
1040 {
1041 dst->Size = src->Size;
1042 dst->Type = src->Type;
1043 dst->Format = src->Format;
1044 dst->Stride = src->Stride;
1045 dst->StrideB = src->StrideB;
1046 dst->Ptr = src->Ptr;
1047 dst->Enabled = src->Enabled;
1048 dst->Normalized = src->Normalized;
1049 dst->_ElementSize = src->_ElementSize;
1050 _mesa_reference_buffer_object(ctx, &dst->BufferObj, src->BufferObj);
1051 dst->_MaxElement = src->_MaxElement;
1052 }
1053
1054
1055
1056 /**
1057 * Print vertex array's fields.
1058 */
1059 static void
1060 print_array(const char *name, GLint index, const struct gl_client_array *array)
1061 {
1062 if (index >= 0)
1063 _mesa_printf(" %s[%d]: ", name, index);
1064 else
1065 _mesa_printf(" %s: ", name);
1066 _mesa_printf("Ptr=%p, Type=0x%x, Size=%d, ElemSize=%u, Stride=%d, Buffer=%u(Size %u), MaxElem=%u\n",
1067 array->Ptr, array->Type, array->Size,
1068 array->_ElementSize, array->StrideB,
1069 array->BufferObj->Name, array->BufferObj->Size,
1070 array->_MaxElement);
1071 }
1072
1073
1074 /**
1075 * Print current vertex object/array info. For debug.
1076 */
1077 void
1078 _mesa_print_arrays(GLcontext *ctx)
1079 {
1080 struct gl_array_object *arrayObj = ctx->Array.ArrayObj;
1081 GLuint i;
1082
1083 _mesa_update_array_object_max_element(ctx, arrayObj);
1084
1085 _mesa_printf("Array Object %u\n", arrayObj->Name);
1086 if (arrayObj->Vertex.Enabled)
1087 print_array("Vertex", -1, &arrayObj->Vertex);
1088 if (arrayObj->Normal.Enabled)
1089 print_array("Normal", -1, &arrayObj->Normal);
1090 if (arrayObj->Color.Enabled)
1091 print_array("Color", -1, &arrayObj->Color);
1092 for (i = 0; i < Elements(arrayObj->TexCoord); i++)
1093 if (arrayObj->TexCoord[i].Enabled)
1094 print_array("TexCoord", i, &arrayObj->TexCoord[i]);
1095 for (i = 0; i < Elements(arrayObj->VertexAttrib); i++)
1096 if (arrayObj->VertexAttrib[i].Enabled)
1097 print_array("Attrib", i, &arrayObj->VertexAttrib[i]);
1098 _mesa_printf(" _MaxElement = %u\n", arrayObj->_MaxElement);
1099 }
1100
1101
1102 /**
1103 * Initialize vertex array state for given context.
1104 */
1105 void
1106 _mesa_init_varray(GLcontext *ctx)
1107 {
1108 ctx->Array.DefaultArrayObj = _mesa_new_array_object(ctx, 0);
1109 _mesa_reference_array_object(ctx, &ctx->Array.ArrayObj,
1110 ctx->Array.DefaultArrayObj);
1111 ctx->Array.ActiveTexture = 0; /* GL_ARB_multitexture */
1112
1113 ctx->Array.Objects = _mesa_NewHashTable();
1114 }
1115
1116
1117 /**
1118 * Callback for deleting an array object. Called by _mesa_HashDeleteAll().
1119 */
1120 static void
1121 delete_arrayobj_cb(GLuint id, void *data, void *userData)
1122 {
1123 struct gl_array_object *arrayObj = (struct gl_array_object *) data;
1124 GLcontext *ctx = (GLcontext *) userData;
1125 _mesa_delete_array_object(ctx, arrayObj);
1126 }
1127
1128
1129 /**
1130 * Free vertex array state for given context.
1131 */
1132 void
1133 _mesa_free_varray_data(GLcontext *ctx)
1134 {
1135 _mesa_HashDeleteAll(ctx->Array.Objects, delete_arrayobj_cb, ctx);
1136 _mesa_DeleteHashTable(ctx->Array.Objects);
1137 }