mesa: added _mesa_VertexAttribIPointer()
[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 /**
714 * New in GL3:
715 * Set an integer-valued vertex attribute array.
716 * Note that these arrays DO NOT alias the conventional GL vertex arrays
717 * (position, normal, color, fog, texcoord, etc).
718 */
719 void GLAPIENTRY
720 _mesa_VertexAttribIPointer(GLuint index, GLint size, GLenum type,
721 GLboolean normalized,
722 GLsizei stride, const GLvoid *ptr)
723 {
724 /* NOTE: until we have integer-valued vertex attributes, just
725 * route this through the regular glVertexAttribPointer() function.
726 */
727 _mesa_VertexAttribPointerARB(index, size, type, normalized, stride, ptr);
728 }
729
730
731
732 void GLAPIENTRY
733 _mesa_VertexPointerEXT(GLint size, GLenum type, GLsizei stride,
734 GLsizei count, const GLvoid *ptr)
735 {
736 (void) count;
737 _mesa_VertexPointer(size, type, stride, ptr);
738 }
739
740
741 void GLAPIENTRY
742 _mesa_NormalPointerEXT(GLenum type, GLsizei stride, GLsizei count,
743 const GLvoid *ptr)
744 {
745 (void) count;
746 _mesa_NormalPointer(type, stride, ptr);
747 }
748
749
750 void GLAPIENTRY
751 _mesa_ColorPointerEXT(GLint size, GLenum type, GLsizei stride, GLsizei count,
752 const GLvoid *ptr)
753 {
754 (void) count;
755 _mesa_ColorPointer(size, type, stride, ptr);
756 }
757
758
759 void GLAPIENTRY
760 _mesa_IndexPointerEXT(GLenum type, GLsizei stride, GLsizei count,
761 const GLvoid *ptr)
762 {
763 (void) count;
764 _mesa_IndexPointer(type, stride, ptr);
765 }
766
767
768 void GLAPIENTRY
769 _mesa_TexCoordPointerEXT(GLint size, GLenum type, GLsizei stride,
770 GLsizei count, const GLvoid *ptr)
771 {
772 (void) count;
773 _mesa_TexCoordPointer(size, type, stride, ptr);
774 }
775
776
777 void GLAPIENTRY
778 _mesa_EdgeFlagPointerEXT(GLsizei stride, GLsizei count, const GLboolean *ptr)
779 {
780 (void) count;
781 _mesa_EdgeFlagPointer(stride, ptr);
782 }
783
784
785 void GLAPIENTRY
786 _mesa_InterleavedArrays(GLenum format, GLsizei stride, const GLvoid *pointer)
787 {
788 GET_CURRENT_CONTEXT(ctx);
789 GLboolean tflag, cflag, nflag; /* enable/disable flags */
790 GLint tcomps, ccomps, vcomps; /* components per texcoord, color, vertex */
791 GLenum ctype = 0; /* color type */
792 GLint coffset = 0, noffset = 0, voffset;/* color, normal, vertex offsets */
793 const GLint toffset = 0; /* always zero */
794 GLint defstride; /* default stride */
795 GLint c, f;
796
797 ASSERT_OUTSIDE_BEGIN_END_AND_FLUSH(ctx);
798
799 f = sizeof(GLfloat);
800 c = f * ((4 * sizeof(GLubyte) + (f - 1)) / f);
801
802 if (stride < 0) {
803 _mesa_error( ctx, GL_INVALID_VALUE, "glInterleavedArrays(stride)" );
804 return;
805 }
806
807 switch (format) {
808 case GL_V2F:
809 tflag = GL_FALSE; cflag = GL_FALSE; nflag = GL_FALSE;
810 tcomps = 0; ccomps = 0; vcomps = 2;
811 voffset = 0;
812 defstride = 2*f;
813 break;
814 case GL_V3F:
815 tflag = GL_FALSE; cflag = GL_FALSE; nflag = GL_FALSE;
816 tcomps = 0; ccomps = 0; vcomps = 3;
817 voffset = 0;
818 defstride = 3*f;
819 break;
820 case GL_C4UB_V2F:
821 tflag = GL_FALSE; cflag = GL_TRUE; nflag = GL_FALSE;
822 tcomps = 0; ccomps = 4; vcomps = 2;
823 ctype = GL_UNSIGNED_BYTE;
824 coffset = 0;
825 voffset = c;
826 defstride = c + 2*f;
827 break;
828 case GL_C4UB_V3F:
829 tflag = GL_FALSE; cflag = GL_TRUE; nflag = GL_FALSE;
830 tcomps = 0; ccomps = 4; vcomps = 3;
831 ctype = GL_UNSIGNED_BYTE;
832 coffset = 0;
833 voffset = c;
834 defstride = c + 3*f;
835 break;
836 case GL_C3F_V3F:
837 tflag = GL_FALSE; cflag = GL_TRUE; nflag = GL_FALSE;
838 tcomps = 0; ccomps = 3; vcomps = 3;
839 ctype = GL_FLOAT;
840 coffset = 0;
841 voffset = 3*f;
842 defstride = 6*f;
843 break;
844 case GL_N3F_V3F:
845 tflag = GL_FALSE; cflag = GL_FALSE; nflag = GL_TRUE;
846 tcomps = 0; ccomps = 0; vcomps = 3;
847 noffset = 0;
848 voffset = 3*f;
849 defstride = 6*f;
850 break;
851 case GL_C4F_N3F_V3F:
852 tflag = GL_FALSE; cflag = GL_TRUE; nflag = GL_TRUE;
853 tcomps = 0; ccomps = 4; vcomps = 3;
854 ctype = GL_FLOAT;
855 coffset = 0;
856 noffset = 4*f;
857 voffset = 7*f;
858 defstride = 10*f;
859 break;
860 case GL_T2F_V3F:
861 tflag = GL_TRUE; cflag = GL_FALSE; nflag = GL_FALSE;
862 tcomps = 2; ccomps = 0; vcomps = 3;
863 voffset = 2*f;
864 defstride = 5*f;
865 break;
866 case GL_T4F_V4F:
867 tflag = GL_TRUE; cflag = GL_FALSE; nflag = GL_FALSE;
868 tcomps = 4; ccomps = 0; vcomps = 4;
869 voffset = 4*f;
870 defstride = 8*f;
871 break;
872 case GL_T2F_C4UB_V3F:
873 tflag = GL_TRUE; cflag = GL_TRUE; nflag = GL_FALSE;
874 tcomps = 2; ccomps = 4; vcomps = 3;
875 ctype = GL_UNSIGNED_BYTE;
876 coffset = 2*f;
877 voffset = c+2*f;
878 defstride = c+5*f;
879 break;
880 case GL_T2F_C3F_V3F:
881 tflag = GL_TRUE; cflag = GL_TRUE; nflag = GL_FALSE;
882 tcomps = 2; ccomps = 3; vcomps = 3;
883 ctype = GL_FLOAT;
884 coffset = 2*f;
885 voffset = 5*f;
886 defstride = 8*f;
887 break;
888 case GL_T2F_N3F_V3F:
889 tflag = GL_TRUE; cflag = GL_FALSE; nflag = GL_TRUE;
890 tcomps = 2; ccomps = 0; vcomps = 3;
891 noffset = 2*f;
892 voffset = 5*f;
893 defstride = 8*f;
894 break;
895 case GL_T2F_C4F_N3F_V3F:
896 tflag = GL_TRUE; cflag = GL_TRUE; nflag = GL_TRUE;
897 tcomps = 2; ccomps = 4; vcomps = 3;
898 ctype = GL_FLOAT;
899 coffset = 2*f;
900 noffset = 6*f;
901 voffset = 9*f;
902 defstride = 12*f;
903 break;
904 case GL_T4F_C4F_N3F_V4F:
905 tflag = GL_TRUE; cflag = GL_TRUE; nflag = GL_TRUE;
906 tcomps = 4; ccomps = 4; vcomps = 4;
907 ctype = GL_FLOAT;
908 coffset = 4*f;
909 noffset = 8*f;
910 voffset = 11*f;
911 defstride = 15*f;
912 break;
913 default:
914 _mesa_error( ctx, GL_INVALID_ENUM, "glInterleavedArrays(format)" );
915 return;
916 }
917
918 if (stride==0) {
919 stride = defstride;
920 }
921
922 _mesa_DisableClientState( GL_EDGE_FLAG_ARRAY );
923 _mesa_DisableClientState( GL_INDEX_ARRAY );
924 /* XXX also disable secondary color and generic arrays? */
925
926 /* Texcoords */
927 if (tflag) {
928 _mesa_EnableClientState( GL_TEXTURE_COORD_ARRAY );
929 _mesa_TexCoordPointer( tcomps, GL_FLOAT, stride,
930 (GLubyte *) pointer + toffset );
931 }
932 else {
933 _mesa_DisableClientState( GL_TEXTURE_COORD_ARRAY );
934 }
935
936 /* Color */
937 if (cflag) {
938 _mesa_EnableClientState( GL_COLOR_ARRAY );
939 _mesa_ColorPointer( ccomps, ctype, stride,
940 (GLubyte *) pointer + coffset );
941 }
942 else {
943 _mesa_DisableClientState( GL_COLOR_ARRAY );
944 }
945
946
947 /* Normals */
948 if (nflag) {
949 _mesa_EnableClientState( GL_NORMAL_ARRAY );
950 _mesa_NormalPointer( GL_FLOAT, stride, (GLubyte *) pointer + noffset );
951 }
952 else {
953 _mesa_DisableClientState( GL_NORMAL_ARRAY );
954 }
955
956 /* Vertices */
957 _mesa_EnableClientState( GL_VERTEX_ARRAY );
958 _mesa_VertexPointer( vcomps, GL_FLOAT, stride,
959 (GLubyte *) pointer + voffset );
960 }
961
962
963 void GLAPIENTRY
964 _mesa_LockArraysEXT(GLint first, GLsizei count)
965 {
966 GET_CURRENT_CONTEXT(ctx);
967 ASSERT_OUTSIDE_BEGIN_END_AND_FLUSH(ctx);
968
969 if (MESA_VERBOSE & VERBOSE_API)
970 _mesa_debug(ctx, "glLockArrays %d %d\n", first, count);
971
972 if (first < 0) {
973 _mesa_error( ctx, GL_INVALID_VALUE, "glLockArraysEXT(first)" );
974 return;
975 }
976 if (count <= 0) {
977 _mesa_error( ctx, GL_INVALID_VALUE, "glLockArraysEXT(count)" );
978 return;
979 }
980 if (ctx->Array.LockCount != 0) {
981 _mesa_error( ctx, GL_INVALID_OPERATION, "glLockArraysEXT(reentry)" );
982 return;
983 }
984
985 ctx->Array.LockFirst = first;
986 ctx->Array.LockCount = count;
987
988 ctx->NewState |= _NEW_ARRAY;
989 ctx->Array.NewState |= _NEW_ARRAY_ALL;
990 }
991
992
993 void GLAPIENTRY
994 _mesa_UnlockArraysEXT( void )
995 {
996 GET_CURRENT_CONTEXT(ctx);
997 ASSERT_OUTSIDE_BEGIN_END_AND_FLUSH(ctx);
998
999 if (MESA_VERBOSE & VERBOSE_API)
1000 _mesa_debug(ctx, "glUnlockArrays\n");
1001
1002 if (ctx->Array.LockCount == 0) {
1003 _mesa_error( ctx, GL_INVALID_OPERATION, "glUnlockArraysEXT(reexit)" );
1004 return;
1005 }
1006
1007 ctx->Array.LockFirst = 0;
1008 ctx->Array.LockCount = 0;
1009 ctx->NewState |= _NEW_ARRAY;
1010 ctx->Array.NewState |= _NEW_ARRAY_ALL;
1011 }
1012
1013
1014 /* GL_EXT_multi_draw_arrays */
1015 /* Somebody forgot to spec the first and count parameters as const! <sigh> */
1016 void GLAPIENTRY
1017 _mesa_MultiDrawArraysEXT( GLenum mode, GLint *first,
1018 GLsizei *count, GLsizei primcount )
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 CALL_DrawArrays(ctx->Exec, (mode, first[i], count[i]));
1028 }
1029 }
1030 }
1031
1032
1033 /* GL_IBM_multimode_draw_arrays */
1034 void GLAPIENTRY
1035 _mesa_MultiModeDrawArraysIBM( const GLenum * mode, const GLint * first,
1036 const GLsizei * count,
1037 GLsizei primcount, GLint modestride )
1038 {
1039 GET_CURRENT_CONTEXT(ctx);
1040 GLint i;
1041
1042 ASSERT_OUTSIDE_BEGIN_END_AND_FLUSH(ctx);
1043
1044 for ( i = 0 ; i < primcount ; i++ ) {
1045 if ( count[i] > 0 ) {
1046 GLenum m = *((GLenum *) ((GLubyte *) mode + i * modestride));
1047 CALL_DrawArrays(ctx->Exec, ( m, first[i], count[i] ));
1048 }
1049 }
1050 }
1051
1052
1053 /* GL_IBM_multimode_draw_arrays */
1054 void GLAPIENTRY
1055 _mesa_MultiModeDrawElementsIBM( const GLenum * mode, const GLsizei * count,
1056 GLenum type, const GLvoid * const * indices,
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 /* XXX not sure about ARB_vertex_buffer_object handling here */
1065
1066 for ( i = 0 ; i < primcount ; i++ ) {
1067 if ( count[i] > 0 ) {
1068 GLenum m = *((GLenum *) ((GLubyte *) mode + i * modestride));
1069 CALL_DrawElements(ctx->Exec, ( m, count[i], type, indices[i] ));
1070 }
1071 }
1072 }
1073
1074
1075 /**
1076 * GL 3.1 glPrimitiveRestartIndex().
1077 */
1078 void GLAPIENTRY
1079 _mesa_PrimitiveRestartIndex(GLuint index)
1080 {
1081 GET_CURRENT_CONTEXT(ctx);
1082
1083 if (ctx->VersionMajor * 10 + ctx->VersionMinor < 31) {
1084 _mesa_error(ctx, GL_INVALID_OPERATION, "glPrimitiveRestartIndex()");
1085 return;
1086 }
1087
1088 ASSERT_OUTSIDE_BEGIN_END_AND_FLUSH(ctx);
1089
1090 FLUSH_VERTICES(ctx, _NEW_TRANSFORM);
1091
1092 ctx->Array.RestartIndex = index;
1093 }
1094
1095
1096 /**
1097 * Copy one client vertex array to another.
1098 */
1099 void
1100 _mesa_copy_client_array(GLcontext *ctx,
1101 struct gl_client_array *dst,
1102 struct gl_client_array *src)
1103 {
1104 dst->Size = src->Size;
1105 dst->Type = src->Type;
1106 dst->Format = src->Format;
1107 dst->Stride = src->Stride;
1108 dst->StrideB = src->StrideB;
1109 dst->Ptr = src->Ptr;
1110 dst->Enabled = src->Enabled;
1111 dst->Normalized = src->Normalized;
1112 dst->_ElementSize = src->_ElementSize;
1113 _mesa_reference_buffer_object(ctx, &dst->BufferObj, src->BufferObj);
1114 dst->_MaxElement = src->_MaxElement;
1115 }
1116
1117
1118
1119 /**
1120 * Print vertex array's fields.
1121 */
1122 static void
1123 print_array(const char *name, GLint index, const struct gl_client_array *array)
1124 {
1125 if (index >= 0)
1126 printf(" %s[%d]: ", name, index);
1127 else
1128 printf(" %s: ", name);
1129 printf("Ptr=%p, Type=0x%x, Size=%d, ElemSize=%u, Stride=%d, Buffer=%u(Size %u), MaxElem=%u\n",
1130 array->Ptr, array->Type, array->Size,
1131 array->_ElementSize, array->StrideB,
1132 array->BufferObj->Name, array->BufferObj->Size,
1133 array->_MaxElement);
1134 }
1135
1136
1137 /**
1138 * Print current vertex object/array info. For debug.
1139 */
1140 void
1141 _mesa_print_arrays(GLcontext *ctx)
1142 {
1143 struct gl_array_object *arrayObj = ctx->Array.ArrayObj;
1144 GLuint i;
1145
1146 _mesa_update_array_object_max_element(ctx, arrayObj);
1147
1148 printf("Array Object %u\n", arrayObj->Name);
1149 if (arrayObj->Vertex.Enabled)
1150 print_array("Vertex", -1, &arrayObj->Vertex);
1151 if (arrayObj->Normal.Enabled)
1152 print_array("Normal", -1, &arrayObj->Normal);
1153 if (arrayObj->Color.Enabled)
1154 print_array("Color", -1, &arrayObj->Color);
1155 for (i = 0; i < Elements(arrayObj->TexCoord); i++)
1156 if (arrayObj->TexCoord[i].Enabled)
1157 print_array("TexCoord", i, &arrayObj->TexCoord[i]);
1158 for (i = 0; i < Elements(arrayObj->VertexAttrib); i++)
1159 if (arrayObj->VertexAttrib[i].Enabled)
1160 print_array("Attrib", i, &arrayObj->VertexAttrib[i]);
1161 printf(" _MaxElement = %u\n", arrayObj->_MaxElement);
1162 }
1163
1164
1165 /**
1166 * Initialize vertex array state for given context.
1167 */
1168 void
1169 _mesa_init_varray(GLcontext *ctx)
1170 {
1171 ctx->Array.DefaultArrayObj = _mesa_new_array_object(ctx, 0);
1172 _mesa_reference_array_object(ctx, &ctx->Array.ArrayObj,
1173 ctx->Array.DefaultArrayObj);
1174 ctx->Array.ActiveTexture = 0; /* GL_ARB_multitexture */
1175
1176 ctx->Array.Objects = _mesa_NewHashTable();
1177 }
1178
1179
1180 /**
1181 * Callback for deleting an array object. Called by _mesa_HashDeleteAll().
1182 */
1183 static void
1184 delete_arrayobj_cb(GLuint id, void *data, void *userData)
1185 {
1186 struct gl_array_object *arrayObj = (struct gl_array_object *) data;
1187 GLcontext *ctx = (GLcontext *) userData;
1188 _mesa_delete_array_object(ctx, arrayObj);
1189 }
1190
1191
1192 /**
1193 * Free vertex array state for given context.
1194 */
1195 void
1196 _mesa_free_varray_data(GLcontext *ctx)
1197 {
1198 _mesa_HashDeleteAll(ctx->Array.Objects, delete_arrayobj_cb, ctx);
1199 _mesa_DeleteHashTable(ctx->Array.Objects);
1200 }