Merge branch 'arb_half_float_vertex'
[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 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 update_array(ctx, &ctx->Array.ArrayObj->TexCoord[unit],
479 _NEW_ARRAY_TEXCOORD(unit),
480 elementSize, size, type, GL_RGBA, stride, GL_FALSE, ptr);
481 }
482
483
484 void GLAPIENTRY
485 _mesa_EdgeFlagPointer(GLsizei stride, const GLvoid *ptr)
486 {
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, "glEdgeFlagPointer(stride)" );
492 return;
493 }
494
495 update_array(ctx, &ctx->Array.ArrayObj->EdgeFlag, _NEW_ARRAY_EDGEFLAG,
496 sizeof(GLboolean), 1, GL_UNSIGNED_BYTE, GL_RGBA,
497 stride, GL_FALSE, ptr);
498 }
499
500
501 void GLAPIENTRY
502 _mesa_PointSizePointer(GLenum type, GLsizei stride, const GLvoid *ptr)
503 {
504 GLsizei elementSize;
505 GET_CURRENT_CONTEXT(ctx);
506 ASSERT_OUTSIDE_BEGIN_END_AND_FLUSH(ctx);
507
508 if (stride < 0) {
509 _mesa_error( ctx, GL_INVALID_VALUE, "glPointSizePointer(stride)" );
510 return;
511 }
512
513 switch (type) {
514 case GL_FLOAT:
515 elementSize = sizeof(GLfloat);
516 break;
517 #if FEATURE_fixedpt
518 case GL_FIXED:
519 elementSize = sizeof(GLfixed);
520 break;
521 #endif
522 default:
523 _mesa_error( ctx, GL_INVALID_ENUM, "glPointSizePointer(type)" );
524 return;
525 }
526
527 update_array(ctx, &ctx->Array.ArrayObj->PointSize, _NEW_ARRAY_POINT_SIZE,
528 elementSize, 1, type, GL_RGBA, stride, GL_FALSE, ptr);
529 }
530
531
532 #if FEATURE_NV_vertex_program
533 /**
534 * Set a vertex attribute array.
535 * Note that these arrays DO alias the conventional GL vertex arrays
536 * (position, normal, color, fog, texcoord, etc).
537 * The generic attribute slots at #16 and above are not touched.
538 */
539 void GLAPIENTRY
540 _mesa_VertexAttribPointerNV(GLuint index, GLint size, GLenum type,
541 GLsizei stride, const GLvoid *ptr)
542 {
543 GLboolean normalized = GL_FALSE;
544 GLsizei elementSize;
545 GLenum format;
546 GET_CURRENT_CONTEXT(ctx);
547 ASSERT_OUTSIDE_BEGIN_END(ctx);
548
549 if (index >= MAX_NV_VERTEX_PROGRAM_INPUTS) {
550 _mesa_error(ctx, GL_INVALID_VALUE, "glVertexAttribPointerNV(index)");
551 return;
552 }
553
554 if (size < 1 || size > 4) {
555 _mesa_error(ctx, GL_INVALID_VALUE, "glVertexAttribPointerNV(size)");
556 return;
557 }
558
559 if (stride < 0) {
560 _mesa_error(ctx, GL_INVALID_VALUE, "glVertexAttribPointerNV(stride)");
561 return;
562 }
563
564 if (type == GL_UNSIGNED_BYTE && size != 4) {
565 _mesa_error(ctx, GL_INVALID_VALUE, "glVertexAttribPointerNV(size!=4)");
566 return;
567 }
568
569 if (size == GL_BGRA) {
570 if (type != GL_UNSIGNED_BYTE) {
571 _mesa_error(ctx, GL_INVALID_VALUE,
572 "glVertexAttribPointerNV(GL_BGRA/type)");
573 return;
574 }
575
576 format = GL_BGRA;
577 size = 4;
578 normalized = GL_TRUE;
579 }
580 else {
581 format = GL_RGBA;
582 }
583
584 /* check for valid 'type' and compute StrideB right away */
585 switch (type) {
586 case GL_UNSIGNED_BYTE:
587 normalized = GL_TRUE;
588 elementSize = size * sizeof(GLubyte);
589 break;
590 case GL_SHORT:
591 elementSize = size * sizeof(GLshort);
592 break;
593 case GL_FLOAT:
594 elementSize = size * sizeof(GLfloat);
595 break;
596 case GL_DOUBLE:
597 elementSize = size * sizeof(GLdouble);
598 break;
599 default:
600 _mesa_error( ctx, GL_INVALID_ENUM, "glVertexAttribPointerNV(type=%s)",
601 _mesa_lookup_enum_by_nr(type));
602 return;
603 }
604
605 update_array(ctx, &ctx->Array.ArrayObj->VertexAttrib[index],
606 _NEW_ARRAY_ATTRIB(index),
607 elementSize, size, type, format, stride, normalized, ptr);
608 }
609 #endif
610
611
612 #if FEATURE_ARB_vertex_program
613 /**
614 * Set a generic vertex attribute array.
615 * Note that these arrays DO NOT alias the conventional GL vertex arrays
616 * (position, normal, color, fog, texcoord, etc).
617 */
618 void GLAPIENTRY
619 _mesa_VertexAttribPointerARB(GLuint index, GLint size, GLenum type,
620 GLboolean normalized,
621 GLsizei stride, const GLvoid *ptr)
622 {
623 GLsizei elementSize;
624 GLenum format;
625 GET_CURRENT_CONTEXT(ctx);
626 ASSERT_OUTSIDE_BEGIN_END(ctx);
627
628 if (index >= ctx->Const.VertexProgram.MaxAttribs) {
629 _mesa_error(ctx, GL_INVALID_VALUE, "glVertexAttribPointerARB(index)");
630 return;
631 }
632
633 if (size < 1 || size > 4) {
634 if (!ctx->Extensions.EXT_vertex_array_bgra || size != GL_BGRA) {
635 _mesa_error(ctx, GL_INVALID_VALUE, "glVertexAttribPointerARB(size)");
636 return;
637 }
638 }
639
640 if (stride < 0) {
641 _mesa_error(ctx, GL_INVALID_VALUE, "glVertexAttribPointerARB(stride)");
642 return;
643 }
644
645 if (size == GL_BGRA) {
646 if (type != GL_UNSIGNED_BYTE) {
647 _mesa_error(ctx, GL_INVALID_VALUE,
648 "glVertexAttribPointerARB(GL_BGRA/type)");
649 return;
650 }
651 if (normalized != GL_TRUE) {
652 _mesa_error(ctx, GL_INVALID_VALUE,
653 "glVertexAttribPointerARB(GL_BGRA/normalized)");
654 return;
655 }
656
657 format = GL_BGRA;
658 size = 4;
659 }
660 else {
661 format = GL_RGBA;
662 }
663
664 /* check for valid 'type' and compute StrideB right away */
665 /* NOTE: more types are supported here than in the NV extension */
666 switch (type) {
667 case GL_BYTE:
668 elementSize = size * sizeof(GLbyte);
669 break;
670 case GL_UNSIGNED_BYTE:
671 elementSize = size * sizeof(GLubyte);
672 break;
673 case GL_SHORT:
674 elementSize = size * sizeof(GLshort);
675 break;
676 case GL_UNSIGNED_SHORT:
677 elementSize = size * sizeof(GLushort);
678 break;
679 case GL_INT:
680 elementSize = size * sizeof(GLint);
681 break;
682 case GL_UNSIGNED_INT:
683 elementSize = size * sizeof(GLuint);
684 break;
685 case GL_FLOAT:
686 elementSize = size * sizeof(GLfloat);
687 break;
688 case GL_DOUBLE:
689 elementSize = size * sizeof(GLdouble);
690 break;
691 case GL_HALF_FLOAT:
692 elementSize = size * sizeof(GLhalfARB);
693 break;
694 #if FEATURE_fixedpt
695 case GL_FIXED:
696 elementSize = size * sizeof(GLfixed);
697 break;
698 #endif
699 default:
700 _mesa_error( ctx, GL_INVALID_ENUM, "glVertexAttribPointerARB(type)" );
701 return;
702 }
703
704 update_array(ctx, &ctx->Array.ArrayObj->VertexAttrib[index],
705 _NEW_ARRAY_ATTRIB(index),
706 elementSize, size, type, format, stride, normalized, ptr);
707 }
708 #endif
709
710
711 void GLAPIENTRY
712 _mesa_VertexPointerEXT(GLint size, GLenum type, GLsizei stride,
713 GLsizei count, const GLvoid *ptr)
714 {
715 (void) count;
716 _mesa_VertexPointer(size, type, stride, ptr);
717 }
718
719
720 void GLAPIENTRY
721 _mesa_NormalPointerEXT(GLenum type, GLsizei stride, GLsizei count,
722 const GLvoid *ptr)
723 {
724 (void) count;
725 _mesa_NormalPointer(type, stride, ptr);
726 }
727
728
729 void GLAPIENTRY
730 _mesa_ColorPointerEXT(GLint size, GLenum type, GLsizei stride, GLsizei count,
731 const GLvoid *ptr)
732 {
733 (void) count;
734 _mesa_ColorPointer(size, type, stride, ptr);
735 }
736
737
738 void GLAPIENTRY
739 _mesa_IndexPointerEXT(GLenum type, GLsizei stride, GLsizei count,
740 const GLvoid *ptr)
741 {
742 (void) count;
743 _mesa_IndexPointer(type, stride, ptr);
744 }
745
746
747 void GLAPIENTRY
748 _mesa_TexCoordPointerEXT(GLint size, GLenum type, GLsizei stride,
749 GLsizei count, const GLvoid *ptr)
750 {
751 (void) count;
752 _mesa_TexCoordPointer(size, type, stride, ptr);
753 }
754
755
756 void GLAPIENTRY
757 _mesa_EdgeFlagPointerEXT(GLsizei stride, GLsizei count, const GLboolean *ptr)
758 {
759 (void) count;
760 _mesa_EdgeFlagPointer(stride, ptr);
761 }
762
763
764 void GLAPIENTRY
765 _mesa_InterleavedArrays(GLenum format, GLsizei stride, const GLvoid *pointer)
766 {
767 GET_CURRENT_CONTEXT(ctx);
768 GLboolean tflag, cflag, nflag; /* enable/disable flags */
769 GLint tcomps, ccomps, vcomps; /* components per texcoord, color, vertex */
770 GLenum ctype = 0; /* color type */
771 GLint coffset = 0, noffset = 0, voffset;/* color, normal, vertex offsets */
772 const GLint toffset = 0; /* always zero */
773 GLint defstride; /* default stride */
774 GLint c, f;
775
776 ASSERT_OUTSIDE_BEGIN_END_AND_FLUSH(ctx);
777
778 f = sizeof(GLfloat);
779 c = f * ((4 * sizeof(GLubyte) + (f - 1)) / f);
780
781 if (stride < 0) {
782 _mesa_error( ctx, GL_INVALID_VALUE, "glInterleavedArrays(stride)" );
783 return;
784 }
785
786 switch (format) {
787 case GL_V2F:
788 tflag = GL_FALSE; cflag = GL_FALSE; nflag = GL_FALSE;
789 tcomps = 0; ccomps = 0; vcomps = 2;
790 voffset = 0;
791 defstride = 2*f;
792 break;
793 case GL_V3F:
794 tflag = GL_FALSE; cflag = GL_FALSE; nflag = GL_FALSE;
795 tcomps = 0; ccomps = 0; vcomps = 3;
796 voffset = 0;
797 defstride = 3*f;
798 break;
799 case GL_C4UB_V2F:
800 tflag = GL_FALSE; cflag = GL_TRUE; nflag = GL_FALSE;
801 tcomps = 0; ccomps = 4; vcomps = 2;
802 ctype = GL_UNSIGNED_BYTE;
803 coffset = 0;
804 voffset = c;
805 defstride = c + 2*f;
806 break;
807 case GL_C4UB_V3F:
808 tflag = GL_FALSE; cflag = GL_TRUE; nflag = GL_FALSE;
809 tcomps = 0; ccomps = 4; vcomps = 3;
810 ctype = GL_UNSIGNED_BYTE;
811 coffset = 0;
812 voffset = c;
813 defstride = c + 3*f;
814 break;
815 case GL_C3F_V3F:
816 tflag = GL_FALSE; cflag = GL_TRUE; nflag = GL_FALSE;
817 tcomps = 0; ccomps = 3; vcomps = 3;
818 ctype = GL_FLOAT;
819 coffset = 0;
820 voffset = 3*f;
821 defstride = 6*f;
822 break;
823 case GL_N3F_V3F:
824 tflag = GL_FALSE; cflag = GL_FALSE; nflag = GL_TRUE;
825 tcomps = 0; ccomps = 0; vcomps = 3;
826 noffset = 0;
827 voffset = 3*f;
828 defstride = 6*f;
829 break;
830 case GL_C4F_N3F_V3F:
831 tflag = GL_FALSE; cflag = GL_TRUE; nflag = GL_TRUE;
832 tcomps = 0; ccomps = 4; vcomps = 3;
833 ctype = GL_FLOAT;
834 coffset = 0;
835 noffset = 4*f;
836 voffset = 7*f;
837 defstride = 10*f;
838 break;
839 case GL_T2F_V3F:
840 tflag = GL_TRUE; cflag = GL_FALSE; nflag = GL_FALSE;
841 tcomps = 2; ccomps = 0; vcomps = 3;
842 voffset = 2*f;
843 defstride = 5*f;
844 break;
845 case GL_T4F_V4F:
846 tflag = GL_TRUE; cflag = GL_FALSE; nflag = GL_FALSE;
847 tcomps = 4; ccomps = 0; vcomps = 4;
848 voffset = 4*f;
849 defstride = 8*f;
850 break;
851 case GL_T2F_C4UB_V3F:
852 tflag = GL_TRUE; cflag = GL_TRUE; nflag = GL_FALSE;
853 tcomps = 2; ccomps = 4; vcomps = 3;
854 ctype = GL_UNSIGNED_BYTE;
855 coffset = 2*f;
856 voffset = c+2*f;
857 defstride = c+5*f;
858 break;
859 case GL_T2F_C3F_V3F:
860 tflag = GL_TRUE; cflag = GL_TRUE; nflag = GL_FALSE;
861 tcomps = 2; ccomps = 3; vcomps = 3;
862 ctype = GL_FLOAT;
863 coffset = 2*f;
864 voffset = 5*f;
865 defstride = 8*f;
866 break;
867 case GL_T2F_N3F_V3F:
868 tflag = GL_TRUE; cflag = GL_FALSE; nflag = GL_TRUE;
869 tcomps = 2; ccomps = 0; vcomps = 3;
870 noffset = 2*f;
871 voffset = 5*f;
872 defstride = 8*f;
873 break;
874 case GL_T2F_C4F_N3F_V3F:
875 tflag = GL_TRUE; cflag = GL_TRUE; nflag = GL_TRUE;
876 tcomps = 2; ccomps = 4; vcomps = 3;
877 ctype = GL_FLOAT;
878 coffset = 2*f;
879 noffset = 6*f;
880 voffset = 9*f;
881 defstride = 12*f;
882 break;
883 case GL_T4F_C4F_N3F_V4F:
884 tflag = GL_TRUE; cflag = GL_TRUE; nflag = GL_TRUE;
885 tcomps = 4; ccomps = 4; vcomps = 4;
886 ctype = GL_FLOAT;
887 coffset = 4*f;
888 noffset = 8*f;
889 voffset = 11*f;
890 defstride = 15*f;
891 break;
892 default:
893 _mesa_error( ctx, GL_INVALID_ENUM, "glInterleavedArrays(format)" );
894 return;
895 }
896
897 if (stride==0) {
898 stride = defstride;
899 }
900
901 _mesa_DisableClientState( GL_EDGE_FLAG_ARRAY );
902 _mesa_DisableClientState( GL_INDEX_ARRAY );
903 /* XXX also disable secondary color and generic arrays? */
904
905 /* Texcoords */
906 if (tflag) {
907 _mesa_EnableClientState( GL_TEXTURE_COORD_ARRAY );
908 _mesa_TexCoordPointer( tcomps, GL_FLOAT, stride,
909 (GLubyte *) pointer + toffset );
910 }
911 else {
912 _mesa_DisableClientState( GL_TEXTURE_COORD_ARRAY );
913 }
914
915 /* Color */
916 if (cflag) {
917 _mesa_EnableClientState( GL_COLOR_ARRAY );
918 _mesa_ColorPointer( ccomps, ctype, stride,
919 (GLubyte *) pointer + coffset );
920 }
921 else {
922 _mesa_DisableClientState( GL_COLOR_ARRAY );
923 }
924
925
926 /* Normals */
927 if (nflag) {
928 _mesa_EnableClientState( GL_NORMAL_ARRAY );
929 _mesa_NormalPointer( GL_FLOAT, stride, (GLubyte *) pointer + noffset );
930 }
931 else {
932 _mesa_DisableClientState( GL_NORMAL_ARRAY );
933 }
934
935 /* Vertices */
936 _mesa_EnableClientState( GL_VERTEX_ARRAY );
937 _mesa_VertexPointer( vcomps, GL_FLOAT, stride,
938 (GLubyte *) pointer + voffset );
939 }
940
941
942 void GLAPIENTRY
943 _mesa_LockArraysEXT(GLint first, GLsizei count)
944 {
945 GET_CURRENT_CONTEXT(ctx);
946 ASSERT_OUTSIDE_BEGIN_END_AND_FLUSH(ctx);
947
948 if (MESA_VERBOSE & VERBOSE_API)
949 _mesa_debug(ctx, "glLockArrays %d %d\n", first, count);
950
951 if (first < 0) {
952 _mesa_error( ctx, GL_INVALID_VALUE, "glLockArraysEXT(first)" );
953 return;
954 }
955 if (count <= 0) {
956 _mesa_error( ctx, GL_INVALID_VALUE, "glLockArraysEXT(count)" );
957 return;
958 }
959 if (ctx->Array.LockCount != 0) {
960 _mesa_error( ctx, GL_INVALID_OPERATION, "glLockArraysEXT(reentry)" );
961 return;
962 }
963
964 ctx->Array.LockFirst = first;
965 ctx->Array.LockCount = count;
966
967 ctx->NewState |= _NEW_ARRAY;
968 ctx->Array.NewState |= _NEW_ARRAY_ALL;
969 }
970
971
972 void GLAPIENTRY
973 _mesa_UnlockArraysEXT( void )
974 {
975 GET_CURRENT_CONTEXT(ctx);
976 ASSERT_OUTSIDE_BEGIN_END_AND_FLUSH(ctx);
977
978 if (MESA_VERBOSE & VERBOSE_API)
979 _mesa_debug(ctx, "glUnlockArrays\n");
980
981 if (ctx->Array.LockCount == 0) {
982 _mesa_error( ctx, GL_INVALID_OPERATION, "glUnlockArraysEXT(reexit)" );
983 return;
984 }
985
986 ctx->Array.LockFirst = 0;
987 ctx->Array.LockCount = 0;
988 ctx->NewState |= _NEW_ARRAY;
989 ctx->Array.NewState |= _NEW_ARRAY_ALL;
990 }
991
992
993 /* GL_EXT_multi_draw_arrays */
994 /* Somebody forgot to spec the first and count parameters as const! <sigh> */
995 void GLAPIENTRY
996 _mesa_MultiDrawArraysEXT( GLenum mode, GLint *first,
997 GLsizei *count, GLsizei primcount )
998 {
999 GET_CURRENT_CONTEXT(ctx);
1000 GLint i;
1001
1002 ASSERT_OUTSIDE_BEGIN_END_AND_FLUSH(ctx);
1003
1004 for (i = 0; i < primcount; i++) {
1005 if (count[i] > 0) {
1006 CALL_DrawArrays(ctx->Exec, (mode, first[i], count[i]));
1007 }
1008 }
1009 }
1010
1011
1012 /* GL_IBM_multimode_draw_arrays */
1013 void GLAPIENTRY
1014 _mesa_MultiModeDrawArraysIBM( const GLenum * mode, const GLint * first,
1015 const GLsizei * count,
1016 GLsizei primcount, GLint modestride )
1017 {
1018 GET_CURRENT_CONTEXT(ctx);
1019 GLint i;
1020
1021 ASSERT_OUTSIDE_BEGIN_END_AND_FLUSH(ctx);
1022
1023 for ( i = 0 ; i < primcount ; i++ ) {
1024 if ( count[i] > 0 ) {
1025 GLenum m = *((GLenum *) ((GLubyte *) mode + i * modestride));
1026 CALL_DrawArrays(ctx->Exec, ( m, first[i], count[i] ));
1027 }
1028 }
1029 }
1030
1031
1032 /* GL_IBM_multimode_draw_arrays */
1033 void GLAPIENTRY
1034 _mesa_MultiModeDrawElementsIBM( const GLenum * mode, const GLsizei * count,
1035 GLenum type, const GLvoid * const * indices,
1036 GLsizei primcount, GLint modestride )
1037 {
1038 GET_CURRENT_CONTEXT(ctx);
1039 GLint i;
1040
1041 ASSERT_OUTSIDE_BEGIN_END_AND_FLUSH(ctx);
1042
1043 /* XXX not sure about ARB_vertex_buffer_object handling here */
1044
1045 for ( i = 0 ; i < primcount ; i++ ) {
1046 if ( count[i] > 0 ) {
1047 GLenum m = *((GLenum *) ((GLubyte *) mode + i * modestride));
1048 CALL_DrawElements(ctx->Exec, ( m, count[i], type, indices[i] ));
1049 }
1050 }
1051 }
1052
1053
1054 /**
1055 * Copy one client vertex array to another.
1056 */
1057 void
1058 _mesa_copy_client_array(GLcontext *ctx,
1059 struct gl_client_array *dst,
1060 struct gl_client_array *src)
1061 {
1062 dst->Size = src->Size;
1063 dst->Type = src->Type;
1064 dst->Format = src->Format;
1065 dst->Stride = src->Stride;
1066 dst->StrideB = src->StrideB;
1067 dst->Ptr = src->Ptr;
1068 dst->Enabled = src->Enabled;
1069 dst->Normalized = src->Normalized;
1070 dst->_ElementSize = src->_ElementSize;
1071 _mesa_reference_buffer_object(ctx, &dst->BufferObj, src->BufferObj);
1072 dst->_MaxElement = src->_MaxElement;
1073 }
1074
1075
1076
1077 /**
1078 * Print vertex array's fields.
1079 */
1080 static void
1081 print_array(const char *name, GLint index, const struct gl_client_array *array)
1082 {
1083 if (index >= 0)
1084 _mesa_printf(" %s[%d]: ", name, index);
1085 else
1086 _mesa_printf(" %s: ", name);
1087 _mesa_printf("Ptr=%p, Type=0x%x, Size=%d, ElemSize=%u, Stride=%d, Buffer=%u(Size %u), MaxElem=%u\n",
1088 array->Ptr, array->Type, array->Size,
1089 array->_ElementSize, array->StrideB,
1090 array->BufferObj->Name, array->BufferObj->Size,
1091 array->_MaxElement);
1092 }
1093
1094
1095 /**
1096 * Print current vertex object/array info. For debug.
1097 */
1098 void
1099 _mesa_print_arrays(GLcontext *ctx)
1100 {
1101 struct gl_array_object *arrayObj = ctx->Array.ArrayObj;
1102 GLuint i;
1103
1104 _mesa_update_array_object_max_element(ctx, arrayObj);
1105
1106 _mesa_printf("Array Object %u\n", arrayObj->Name);
1107 if (arrayObj->Vertex.Enabled)
1108 print_array("Vertex", -1, &arrayObj->Vertex);
1109 if (arrayObj->Normal.Enabled)
1110 print_array("Normal", -1, &arrayObj->Normal);
1111 if (arrayObj->Color.Enabled)
1112 print_array("Color", -1, &arrayObj->Color);
1113 for (i = 0; i < Elements(arrayObj->TexCoord); i++)
1114 if (arrayObj->TexCoord[i].Enabled)
1115 print_array("TexCoord", i, &arrayObj->TexCoord[i]);
1116 for (i = 0; i < Elements(arrayObj->VertexAttrib); i++)
1117 if (arrayObj->VertexAttrib[i].Enabled)
1118 print_array("Attrib", i, &arrayObj->VertexAttrib[i]);
1119 _mesa_printf(" _MaxElement = %u\n", arrayObj->_MaxElement);
1120 }
1121
1122
1123 /**
1124 * Initialize vertex array state for given context.
1125 */
1126 void
1127 _mesa_init_varray(GLcontext *ctx)
1128 {
1129 ctx->Array.DefaultArrayObj = _mesa_new_array_object(ctx, 0);
1130 _mesa_reference_array_object(ctx, &ctx->Array.ArrayObj,
1131 ctx->Array.DefaultArrayObj);
1132 ctx->Array.ActiveTexture = 0; /* GL_ARB_multitexture */
1133
1134 ctx->Array.Objects = _mesa_NewHashTable();
1135 }
1136
1137
1138 /**
1139 * Callback for deleting an array object. Called by _mesa_HashDeleteAll().
1140 */
1141 static void
1142 delete_arrayobj_cb(GLuint id, void *data, void *userData)
1143 {
1144 struct gl_array_object *arrayObj = (struct gl_array_object *) data;
1145 GLcontext *ctx = (GLcontext *) userData;
1146 _mesa_delete_array_object(ctx, arrayObj);
1147 }
1148
1149
1150 /**
1151 * Free vertex array state for given context.
1152 */
1153 void
1154 _mesa_free_varray_data(GLcontext *ctx)
1155 {
1156 _mesa_HashDeleteAll(ctx->Array.Objects, delete_arrayobj_cb, ctx);
1157 _mesa_DeleteHashTable(ctx->Array.Objects);
1158 }