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