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