Merge commit 'origin/master' into gallium-0.2
[mesa.git] / src / mesa / main / varray.c
1 /*
2 * Mesa 3-D graphics library
3 * Version: 7.2
4 *
5 * Copyright (C) 1999-2008 Brian Paul All Rights Reserved.
6 *
7 * Permission is hereby granted, free of charge, to any person obtaining a
8 * copy of this software and associated documentation files (the "Software"),
9 * to deal in the Software without restriction, including without limitation
10 * the rights to use, copy, modify, merge, publish, distribute, sublicense,
11 * and/or sell copies of the Software, and to permit persons to whom the
12 * Software is furnished to do so, subject to the following conditions:
13 *
14 * The above copyright notice and this permission notice shall be included
15 * in all copies or substantial portions of the Software.
16 *
17 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
18 * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
19 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
20 * BRIAN PAUL BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN
21 * AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
22 * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
23 */
24
25
26 #include "glheader.h"
27 #include "imports.h"
28 #include "bufferobj.h"
29 #include "context.h"
30 #include "enable.h"
31 #include "enums.h"
32 #include "mtypes.h"
33 #include "varray.h"
34 #include "arrayobj.h"
35 #include "glapi/dispatch.h"
36
37
38 /**
39 * Update the fields of a vertex array object.
40 * We need to do a few special things for arrays that live in
41 * vertex buffer objects.
42 *
43 * \param array the array to update
44 * \param dirtyBit which bit to set in ctx->Array.NewState for this array
45 * \param elementSize size of each array element, in bytes
46 * \param size components per element (1, 2, 3 or 4)
47 * \param type datatype of each component (GL_FLOAT, GL_INT, etc)
48 * \param stride stride between elements, in elements
49 * \param normalized are integer types converted to floats in [-1, 1]?
50 * \param ptr the address (or offset inside VBO) of the array data
51 */
52 static void
53 update_array(GLcontext *ctx, struct gl_client_array *array,
54 GLbitfield dirtyBit, GLsizei elementSize,
55 GLint size, GLenum type,
56 GLsizei stride, GLboolean normalized, const GLvoid *ptr)
57 {
58 array->Size = size;
59 array->Type = type;
60 array->Stride = stride;
61 array->StrideB = stride ? stride : elementSize;
62 array->Normalized = normalized;
63 array->Ptr = (const GLubyte *) ptr;
64 #if FEATURE_ARB_vertex_buffer_object
65 _mesa_reference_buffer_object(ctx, &array->BufferObj,
66 ctx->Array.ArrayBufferObj);
67
68 /* Compute the index of the last array element that's inside the buffer.
69 * Later in glDrawArrays we'll check if start + count > _MaxElement to
70 * be sure we won't go out of bounds.
71 */
72 if (ctx->Array.ArrayBufferObj->Name)
73 array->_MaxElement = ((GLsizeiptrARB) ctx->Array.ArrayBufferObj->Size
74 - (GLsizeiptrARB) array->Ptr + array->StrideB
75 - elementSize) / array->StrideB;
76 else
77 #endif
78 array->_MaxElement = 2 * 1000 * 1000 * 1000; /* just a big number */
79
80 ctx->NewState |= _NEW_ARRAY;
81 ctx->Array.NewState |= dirtyBit;
82 }
83
84
85 void GLAPIENTRY
86 _mesa_VertexPointer(GLint size, GLenum type, GLsizei stride, const GLvoid *ptr)
87 {
88 GLsizei elementSize;
89 GET_CURRENT_CONTEXT(ctx);
90 ASSERT_OUTSIDE_BEGIN_END_AND_FLUSH(ctx);
91
92 if (size < 2 || size > 4) {
93 _mesa_error( ctx, GL_INVALID_VALUE, "glVertexPointer(size)" );
94 return;
95 }
96 if (stride < 0) {
97 _mesa_error( ctx, GL_INVALID_VALUE, "glVertexPointer(stride)" );
98 return;
99 }
100
101 if (MESA_VERBOSE&(VERBOSE_VARRAY|VERBOSE_API))
102 _mesa_debug(ctx, "glVertexPointer( sz %d type %s stride %d )\n", size,
103 _mesa_lookup_enum_by_nr( type ), stride);
104
105 /* always need to check that <type> is legal */
106 switch (type) {
107 case GL_SHORT:
108 elementSize = size * sizeof(GLshort);
109 break;
110 case GL_INT:
111 elementSize = size * sizeof(GLint);
112 break;
113 case GL_FLOAT:
114 elementSize = size * sizeof(GLfloat);
115 break;
116 case GL_DOUBLE:
117 elementSize = size * sizeof(GLdouble);
118 break;
119 #if FEATURE_fixedpt
120 case GL_FIXED:
121 elementSize = size * sizeof(GLfixed);
122 break;
123 #endif
124 #if FEATURE_vertex_array_byte
125 case GL_BYTE:
126 elementSize = size * sizeof(GLbyte);
127 break;
128 #endif
129 default:
130 _mesa_error( ctx, GL_INVALID_ENUM, "glVertexPointer(type)" );
131 return;
132 }
133
134 update_array(ctx, &ctx->Array.ArrayObj->Vertex, _NEW_ARRAY_VERTEX,
135 elementSize, size, type, stride, GL_FALSE, ptr);
136
137 if (ctx->Driver.VertexPointer)
138 ctx->Driver.VertexPointer( ctx, size, type, stride, ptr );
139 }
140
141
142 void GLAPIENTRY
143 _mesa_NormalPointer(GLenum type, GLsizei stride, const GLvoid *ptr )
144 {
145 GLsizei elementSize;
146 GET_CURRENT_CONTEXT(ctx);
147 ASSERT_OUTSIDE_BEGIN_END_AND_FLUSH(ctx);
148
149 if (stride < 0) {
150 _mesa_error( ctx, GL_INVALID_VALUE, "glNormalPointer(stride)" );
151 return;
152 }
153
154 if (MESA_VERBOSE&(VERBOSE_VARRAY|VERBOSE_API))
155 _mesa_debug(ctx, "glNormalPointer( type %s stride %d )\n",
156 _mesa_lookup_enum_by_nr( type ), stride);
157
158 switch (type) {
159 case GL_BYTE:
160 elementSize = 3 * sizeof(GLbyte);
161 break;
162 case GL_SHORT:
163 elementSize = 3 * sizeof(GLshort);
164 break;
165 case GL_INT:
166 elementSize = 3 * sizeof(GLint);
167 break;
168 case GL_FLOAT:
169 elementSize = 3 * sizeof(GLfloat);
170 break;
171 case GL_DOUBLE:
172 elementSize = 3 * sizeof(GLdouble);
173 break;
174 #if FEATURE_fixedpt
175 case GL_FIXED:
176 elementSize = 3 * sizeof(GLfixed);
177 break;
178 #endif
179 default:
180 _mesa_error( ctx, GL_INVALID_ENUM, "glNormalPointer(type)" );
181 return;
182 }
183
184 update_array(ctx, &ctx->Array.ArrayObj->Normal, _NEW_ARRAY_NORMAL,
185 elementSize, 3, type, stride, GL_TRUE, ptr);
186
187 if (ctx->Driver.NormalPointer)
188 ctx->Driver.NormalPointer( ctx, type, stride, ptr );
189 }
190
191
192 void GLAPIENTRY
193 _mesa_ColorPointer(GLint size, GLenum type, GLsizei stride, const GLvoid *ptr)
194 {
195 GLsizei elementSize;
196 GET_CURRENT_CONTEXT(ctx);
197 ASSERT_OUTSIDE_BEGIN_END_AND_FLUSH(ctx);
198
199 if (size < 3 || size > 4) {
200 _mesa_error( ctx, GL_INVALID_VALUE, "glColorPointer(size)" );
201 return;
202 }
203 if (stride < 0) {
204 _mesa_error( ctx, GL_INVALID_VALUE, "glColorPointer(stride)" );
205 return;
206 }
207
208 if (MESA_VERBOSE&(VERBOSE_VARRAY|VERBOSE_API))
209 _mesa_debug(ctx, "glColorPointer( sz %d type %s stride %d )\n", size,
210 _mesa_lookup_enum_by_nr( type ), stride);
211
212 switch (type) {
213 case GL_BYTE:
214 elementSize = size * sizeof(GLbyte);
215 break;
216 case GL_UNSIGNED_BYTE:
217 elementSize = size * sizeof(GLubyte);
218 break;
219 case GL_SHORT:
220 elementSize = size * sizeof(GLshort);
221 break;
222 case GL_UNSIGNED_SHORT:
223 elementSize = size * sizeof(GLushort);
224 break;
225 case GL_INT:
226 elementSize = size * sizeof(GLint);
227 break;
228 case GL_UNSIGNED_INT:
229 elementSize = size * sizeof(GLuint);
230 break;
231 case GL_FLOAT:
232 elementSize = size * sizeof(GLfloat);
233 break;
234 case GL_DOUBLE:
235 elementSize = size * sizeof(GLdouble);
236 break;
237 #if FEATURE_fixedpt
238 case GL_FIXED:
239 elementSize = size * sizeof(GLfixed);
240 break;
241 #endif
242 default:
243 _mesa_error( ctx, GL_INVALID_ENUM, "glColorPointer(type)" );
244 return;
245 }
246
247 update_array(ctx, &ctx->Array.ArrayObj->Color, _NEW_ARRAY_COLOR0,
248 elementSize, size, type, stride, GL_TRUE, ptr);
249
250 if (ctx->Driver.ColorPointer)
251 ctx->Driver.ColorPointer( ctx, size, type, stride, ptr );
252 }
253
254
255 void GLAPIENTRY
256 _mesa_FogCoordPointerEXT(GLenum type, GLsizei stride, const GLvoid *ptr)
257 {
258 GLint elementSize;
259 GET_CURRENT_CONTEXT(ctx);
260 ASSERT_OUTSIDE_BEGIN_END_AND_FLUSH(ctx);
261
262 if (stride < 0) {
263 _mesa_error( ctx, GL_INVALID_VALUE, "glFogCoordPointer(stride)" );
264 return;
265 }
266
267 switch (type) {
268 case GL_FLOAT:
269 elementSize = sizeof(GLfloat);
270 break;
271 case GL_DOUBLE:
272 elementSize = sizeof(GLdouble);
273 break;
274 default:
275 _mesa_error( ctx, GL_INVALID_ENUM, "glFogCoordPointer(type)" );
276 return;
277 }
278
279 update_array(ctx, &ctx->Array.ArrayObj->FogCoord, _NEW_ARRAY_FOGCOORD,
280 elementSize, 1, type, stride, GL_FALSE, ptr);
281
282 if (ctx->Driver.FogCoordPointer)
283 ctx->Driver.FogCoordPointer( ctx, type, stride, ptr );
284 }
285
286
287 void GLAPIENTRY
288 _mesa_IndexPointer(GLenum type, GLsizei stride, const GLvoid *ptr)
289 {
290 GLsizei elementSize;
291 GET_CURRENT_CONTEXT(ctx);
292 ASSERT_OUTSIDE_BEGIN_END_AND_FLUSH(ctx);
293
294 if (stride < 0) {
295 _mesa_error( ctx, GL_INVALID_VALUE, "glIndexPointer(stride)" );
296 return;
297 }
298
299 switch (type) {
300 case GL_UNSIGNED_BYTE:
301 elementSize = sizeof(GLubyte);
302 break;
303 case GL_SHORT:
304 elementSize = sizeof(GLshort);
305 break;
306 case GL_INT:
307 elementSize = sizeof(GLint);
308 break;
309 case GL_FLOAT:
310 elementSize = sizeof(GLfloat);
311 break;
312 case GL_DOUBLE:
313 elementSize = sizeof(GLdouble);
314 break;
315 default:
316 _mesa_error( ctx, GL_INVALID_ENUM, "glIndexPointer(type)" );
317 return;
318 }
319
320 update_array(ctx, &ctx->Array.ArrayObj->Index, _NEW_ARRAY_INDEX,
321 elementSize, 1, type, stride, GL_FALSE, ptr);
322
323 if (ctx->Driver.IndexPointer)
324 ctx->Driver.IndexPointer( ctx, type, stride, ptr );
325 }
326
327
328 void GLAPIENTRY
329 _mesa_SecondaryColorPointerEXT(GLint size, GLenum type,
330 GLsizei stride, const GLvoid *ptr)
331 {
332 GLsizei elementSize;
333 GET_CURRENT_CONTEXT(ctx);
334 ASSERT_OUTSIDE_BEGIN_END_AND_FLUSH(ctx);
335
336 if (size != 3 && size != 4) {
337 _mesa_error( ctx, GL_INVALID_VALUE, "glSecondaryColorPointer(size)" );
338 return;
339 }
340 if (stride < 0) {
341 _mesa_error( ctx, GL_INVALID_VALUE, "glSecondaryColorPointer(stride)" );
342 return;
343 }
344
345 if (MESA_VERBOSE&(VERBOSE_VARRAY|VERBOSE_API))
346 _mesa_debug(ctx, "glSecondaryColorPointer( sz %d type %s stride %d )\n",
347 size, _mesa_lookup_enum_by_nr( type ), stride);
348
349 switch (type) {
350 case GL_BYTE:
351 elementSize = size * sizeof(GLbyte);
352 break;
353 case GL_UNSIGNED_BYTE:
354 elementSize = size * sizeof(GLubyte);
355 break;
356 case GL_SHORT:
357 elementSize = size * sizeof(GLshort);
358 break;
359 case GL_UNSIGNED_SHORT:
360 elementSize = size * sizeof(GLushort);
361 break;
362 case GL_INT:
363 elementSize = size * sizeof(GLint);
364 break;
365 case GL_UNSIGNED_INT:
366 elementSize = size * sizeof(GLuint);
367 break;
368 case GL_FLOAT:
369 elementSize = size * sizeof(GLfloat);
370 break;
371 case GL_DOUBLE:
372 elementSize = size * sizeof(GLdouble);
373 break;
374 default:
375 _mesa_error( ctx, GL_INVALID_ENUM, "glSecondaryColorPointer(type)" );
376 return;
377 }
378
379 update_array(ctx, &ctx->Array.ArrayObj->SecondaryColor, _NEW_ARRAY_COLOR1,
380 elementSize, size, type, stride, GL_TRUE, ptr);
381
382 if (ctx->Driver.SecondaryColorPointer)
383 ctx->Driver.SecondaryColorPointer( ctx, size, type, stride, ptr );
384 }
385
386
387 void GLAPIENTRY
388 _mesa_TexCoordPointer(GLint size, GLenum type, GLsizei stride,
389 const GLvoid *ptr)
390 {
391 GLint elementSize;
392 GET_CURRENT_CONTEXT(ctx);
393 const GLuint unit = ctx->Array.ActiveTexture;
394 ASSERT_OUTSIDE_BEGIN_END_AND_FLUSH(ctx);
395
396 if (size < 1 || size > 4) {
397 _mesa_error( ctx, GL_INVALID_VALUE, "glTexCoordPointer(size)" );
398 return;
399 }
400 if (stride < 0) {
401 _mesa_error( ctx, GL_INVALID_VALUE, "glTexCoordPointer(stride)" );
402 return;
403 }
404
405 if (MESA_VERBOSE&(VERBOSE_VARRAY|VERBOSE_API))
406 _mesa_debug(ctx, "glTexCoordPointer(unit %u sz %d type %s stride %d)\n",
407 unit, size, _mesa_lookup_enum_by_nr( type ), stride);
408
409 /* always need to check that <type> is legal */
410 switch (type) {
411 case GL_SHORT:
412 elementSize = size * sizeof(GLshort);
413 break;
414 case GL_INT:
415 elementSize = size * sizeof(GLint);
416 break;
417 case GL_FLOAT:
418 elementSize = size * sizeof(GLfloat);
419 break;
420 case GL_DOUBLE:
421 elementSize = size * sizeof(GLdouble);
422 break;
423 #if FEATURE_fixedpt
424 case GL_FIXED:
425 elementSize = size * sizeof(GLfixed);
426 break;
427 #endif
428 #if FEATURE_vertex_array_byte
429 case GL_BYTE:
430 elementSize = size * sizeof(GLbyte);
431 break;
432 #endif
433 default:
434 _mesa_error( ctx, GL_INVALID_ENUM, "glTexCoordPointer(type)" );
435 return;
436 }
437
438 update_array(ctx, &ctx->Array.ArrayObj->TexCoord[unit],
439 _NEW_ARRAY_TEXCOORD(unit),
440 elementSize, size, type, stride, GL_FALSE, ptr);
441
442 if (ctx->Driver.TexCoordPointer)
443 ctx->Driver.TexCoordPointer( ctx, size, type, stride, ptr );
444 }
445
446
447 void GLAPIENTRY
448 _mesa_EdgeFlagPointer(GLsizei stride, const GLvoid *ptr)
449 {
450 GET_CURRENT_CONTEXT(ctx);
451 ASSERT_OUTSIDE_BEGIN_END_AND_FLUSH(ctx);
452
453 if (stride < 0) {
454 _mesa_error( ctx, GL_INVALID_VALUE, "glEdgeFlagPointer(stride)" );
455 return;
456 }
457
458 update_array(ctx, &ctx->Array.ArrayObj->EdgeFlag, _NEW_ARRAY_EDGEFLAG,
459 sizeof(GLboolean), 1, GL_UNSIGNED_BYTE, stride, GL_FALSE, ptr);
460
461 if (ctx->Driver.EdgeFlagPointer)
462 ctx->Driver.EdgeFlagPointer( ctx, stride, ptr );
463 }
464
465
466 void GLAPIENTRY
467 _mesa_PointSizePointer(GLenum type, GLsizei stride, const GLvoid *ptr)
468 {
469 GLsizei elementSize;
470 GET_CURRENT_CONTEXT(ctx);
471 ASSERT_OUTSIDE_BEGIN_END_AND_FLUSH(ctx);
472
473 if (stride < 0) {
474 _mesa_error( ctx, GL_INVALID_VALUE, "glPointSizePointer(stride)" );
475 return;
476 }
477
478 switch (type) {
479 case GL_FLOAT:
480 elementSize = sizeof(GLfloat);
481 break;
482 #if FEATURE_fixedpt
483 case GL_FIXED:
484 elementSize = sizeof(GLfixed);
485 break;
486 #endif
487 default:
488 _mesa_error( ctx, GL_INVALID_ENUM, "glPointSizePointer(type)" );
489 return;
490 }
491
492 update_array(ctx, &ctx->Array.ArrayObj->PointSize, _NEW_ARRAY_POINT_SIZE,
493 elementSize, 1, type, stride, GL_FALSE, ptr);
494 }
495
496
497 #if FEATURE_NV_vertex_program
498 void GLAPIENTRY
499 _mesa_VertexAttribPointerNV(GLuint index, GLint size, GLenum type,
500 GLsizei stride, const GLvoid *ptr)
501 {
502 GLboolean normalized = GL_FALSE;
503 GLsizei elementSize;
504 GET_CURRENT_CONTEXT(ctx);
505 ASSERT_OUTSIDE_BEGIN_END(ctx);
506
507 if (index >= MAX_VERTEX_PROGRAM_ATTRIBS) {
508 _mesa_error(ctx, GL_INVALID_VALUE, "glVertexAttribPointerNV(index)");
509 return;
510 }
511
512 if (size < 1 || size > 4) {
513 _mesa_error(ctx, GL_INVALID_VALUE, "glVertexAttribPointerNV(size)");
514 return;
515 }
516
517 if (stride < 0) {
518 _mesa_error(ctx, GL_INVALID_VALUE, "glVertexAttribPointerNV(stride)");
519 return;
520 }
521
522 if (type == GL_UNSIGNED_BYTE && size != 4) {
523 _mesa_error(ctx, GL_INVALID_VALUE, "glVertexAttribPointerNV(size!=4)");
524 return;
525 }
526
527 /* check for valid 'type' and compute StrideB right away */
528 switch (type) {
529 case GL_UNSIGNED_BYTE:
530 normalized = GL_TRUE;
531 elementSize = size * sizeof(GLubyte);
532 break;
533 case GL_SHORT:
534 elementSize = size * sizeof(GLshort);
535 break;
536 case GL_FLOAT:
537 elementSize = size * sizeof(GLfloat);
538 break;
539 case GL_DOUBLE:
540 elementSize = size * sizeof(GLdouble);
541 break;
542 default:
543 _mesa_error( ctx, GL_INVALID_ENUM, "glVertexAttribPointerNV(type)" );
544 return;
545 }
546
547 update_array(ctx, &ctx->Array.ArrayObj->VertexAttrib[index],
548 _NEW_ARRAY_ATTRIB(index),
549 elementSize, size, type, stride, normalized, ptr);
550
551 if (ctx->Driver.VertexAttribPointer)
552 ctx->Driver.VertexAttribPointer( ctx, index, size, type, stride, ptr );
553 }
554 #endif
555
556
557 #if FEATURE_ARB_vertex_program
558 void GLAPIENTRY
559 _mesa_VertexAttribPointerARB(GLuint index, GLint size, GLenum type,
560 GLboolean normalized,
561 GLsizei stride, const GLvoid *ptr)
562 {
563 GLsizei elementSize;
564 GET_CURRENT_CONTEXT(ctx);
565 ASSERT_OUTSIDE_BEGIN_END(ctx);
566
567 if (index >= ctx->Const.VertexProgram.MaxAttribs) {
568 _mesa_error(ctx, GL_INVALID_VALUE, "glVertexAttribPointerARB(index)");
569 return;
570 }
571
572 if (size < 1 || size > 4) {
573 _mesa_error(ctx, GL_INVALID_VALUE, "glVertexAttribPointerARB(size)");
574 return;
575 }
576
577 if (stride < 0) {
578 _mesa_error(ctx, GL_INVALID_VALUE, "glVertexAttribPointerARB(stride)");
579 return;
580 }
581
582 /* check for valid 'type' and compute StrideB right away */
583 /* NOTE: more types are supported here than in the NV extension */
584 switch (type) {
585 case GL_BYTE:
586 elementSize = size * sizeof(GLbyte);
587 break;
588 case GL_UNSIGNED_BYTE:
589 elementSize = size * sizeof(GLubyte);
590 break;
591 case GL_SHORT:
592 elementSize = size * sizeof(GLshort);
593 break;
594 case GL_UNSIGNED_SHORT:
595 elementSize = size * sizeof(GLushort);
596 break;
597 case GL_INT:
598 elementSize = size * sizeof(GLint);
599 break;
600 case GL_UNSIGNED_INT:
601 elementSize = size * sizeof(GLuint);
602 break;
603 case GL_FLOAT:
604 elementSize = size * sizeof(GLfloat);
605 break;
606 case GL_DOUBLE:
607 elementSize = size * sizeof(GLdouble);
608 break;
609 #if FEATURE_fixedpt
610 case GL_FIXED:
611 elementSize = size * sizeof(GLfixed);
612 break;
613 #endif
614 default:
615 _mesa_error( ctx, GL_INVALID_ENUM, "glVertexAttribPointerARB(type)" );
616 return;
617 }
618
619 update_array(ctx, &ctx->Array.ArrayObj->VertexAttrib[index],
620 _NEW_ARRAY_ATTRIB(index),
621 elementSize, size, type, stride, normalized, ptr);
622
623 if (ctx->Driver.VertexAttribPointer)
624 ctx->Driver.VertexAttribPointer(ctx, index, size, type, stride, ptr);
625 }
626 #endif
627
628
629 void GLAPIENTRY
630 _mesa_VertexPointerEXT(GLint size, GLenum type, GLsizei stride,
631 GLsizei count, const GLvoid *ptr)
632 {
633 (void) count;
634 _mesa_VertexPointer(size, type, stride, ptr);
635 }
636
637
638 void GLAPIENTRY
639 _mesa_NormalPointerEXT(GLenum type, GLsizei stride, GLsizei count,
640 const GLvoid *ptr)
641 {
642 (void) count;
643 _mesa_NormalPointer(type, stride, ptr);
644 }
645
646
647 void GLAPIENTRY
648 _mesa_ColorPointerEXT(GLint size, GLenum type, GLsizei stride, GLsizei count,
649 const GLvoid *ptr)
650 {
651 (void) count;
652 _mesa_ColorPointer(size, type, stride, ptr);
653 }
654
655
656 void GLAPIENTRY
657 _mesa_IndexPointerEXT(GLenum type, GLsizei stride, GLsizei count,
658 const GLvoid *ptr)
659 {
660 (void) count;
661 _mesa_IndexPointer(type, stride, ptr);
662 }
663
664
665 void GLAPIENTRY
666 _mesa_TexCoordPointerEXT(GLint size, GLenum type, GLsizei stride,
667 GLsizei count, const GLvoid *ptr)
668 {
669 (void) count;
670 _mesa_TexCoordPointer(size, type, stride, ptr);
671 }
672
673
674 void GLAPIENTRY
675 _mesa_EdgeFlagPointerEXT(GLsizei stride, GLsizei count, const GLboolean *ptr)
676 {
677 (void) count;
678 _mesa_EdgeFlagPointer(stride, ptr);
679 }
680
681
682 void GLAPIENTRY
683 _mesa_InterleavedArrays(GLenum format, GLsizei stride, const GLvoid *pointer)
684 {
685 GET_CURRENT_CONTEXT(ctx);
686 GLboolean tflag, cflag, nflag; /* enable/disable flags */
687 GLint tcomps, ccomps, vcomps; /* components per texcoord, color, vertex */
688 GLenum ctype = 0; /* color type */
689 GLint coffset = 0, noffset = 0, voffset;/* color, normal, vertex offsets */
690 const GLint toffset = 0; /* always zero */
691 GLint defstride; /* default stride */
692 GLint c, f;
693
694 ASSERT_OUTSIDE_BEGIN_END_AND_FLUSH(ctx);
695
696 f = sizeof(GLfloat);
697 c = f * ((4 * sizeof(GLubyte) + (f - 1)) / f);
698
699 if (stride < 0) {
700 _mesa_error( ctx, GL_INVALID_VALUE, "glInterleavedArrays(stride)" );
701 return;
702 }
703
704 switch (format) {
705 case GL_V2F:
706 tflag = GL_FALSE; cflag = GL_FALSE; nflag = GL_FALSE;
707 tcomps = 0; ccomps = 0; vcomps = 2;
708 voffset = 0;
709 defstride = 2*f;
710 break;
711 case GL_V3F:
712 tflag = GL_FALSE; cflag = GL_FALSE; nflag = GL_FALSE;
713 tcomps = 0; ccomps = 0; vcomps = 3;
714 voffset = 0;
715 defstride = 3*f;
716 break;
717 case GL_C4UB_V2F:
718 tflag = GL_FALSE; cflag = GL_TRUE; nflag = GL_FALSE;
719 tcomps = 0; ccomps = 4; vcomps = 2;
720 ctype = GL_UNSIGNED_BYTE;
721 coffset = 0;
722 voffset = c;
723 defstride = c + 2*f;
724 break;
725 case GL_C4UB_V3F:
726 tflag = GL_FALSE; cflag = GL_TRUE; nflag = GL_FALSE;
727 tcomps = 0; ccomps = 4; vcomps = 3;
728 ctype = GL_UNSIGNED_BYTE;
729 coffset = 0;
730 voffset = c;
731 defstride = c + 3*f;
732 break;
733 case GL_C3F_V3F:
734 tflag = GL_FALSE; cflag = GL_TRUE; nflag = GL_FALSE;
735 tcomps = 0; ccomps = 3; vcomps = 3;
736 ctype = GL_FLOAT;
737 coffset = 0;
738 voffset = 3*f;
739 defstride = 6*f;
740 break;
741 case GL_N3F_V3F:
742 tflag = GL_FALSE; cflag = GL_FALSE; nflag = GL_TRUE;
743 tcomps = 0; ccomps = 0; vcomps = 3;
744 noffset = 0;
745 voffset = 3*f;
746 defstride = 6*f;
747 break;
748 case GL_C4F_N3F_V3F:
749 tflag = GL_FALSE; cflag = GL_TRUE; nflag = GL_TRUE;
750 tcomps = 0; ccomps = 4; vcomps = 3;
751 ctype = GL_FLOAT;
752 coffset = 0;
753 noffset = 4*f;
754 voffset = 7*f;
755 defstride = 10*f;
756 break;
757 case GL_T2F_V3F:
758 tflag = GL_TRUE; cflag = GL_FALSE; nflag = GL_FALSE;
759 tcomps = 2; ccomps = 0; vcomps = 3;
760 voffset = 2*f;
761 defstride = 5*f;
762 break;
763 case GL_T4F_V4F:
764 tflag = GL_TRUE; cflag = GL_FALSE; nflag = GL_FALSE;
765 tcomps = 4; ccomps = 0; vcomps = 4;
766 voffset = 4*f;
767 defstride = 8*f;
768 break;
769 case GL_T2F_C4UB_V3F:
770 tflag = GL_TRUE; cflag = GL_TRUE; nflag = GL_FALSE;
771 tcomps = 2; ccomps = 4; vcomps = 3;
772 ctype = GL_UNSIGNED_BYTE;
773 coffset = 2*f;
774 voffset = c+2*f;
775 defstride = c+5*f;
776 break;
777 case GL_T2F_C3F_V3F:
778 tflag = GL_TRUE; cflag = GL_TRUE; nflag = GL_FALSE;
779 tcomps = 2; ccomps = 3; vcomps = 3;
780 ctype = GL_FLOAT;
781 coffset = 2*f;
782 voffset = 5*f;
783 defstride = 8*f;
784 break;
785 case GL_T2F_N3F_V3F:
786 tflag = GL_TRUE; cflag = GL_FALSE; nflag = GL_TRUE;
787 tcomps = 2; ccomps = 0; vcomps = 3;
788 noffset = 2*f;
789 voffset = 5*f;
790 defstride = 8*f;
791 break;
792 case GL_T2F_C4F_N3F_V3F:
793 tflag = GL_TRUE; cflag = GL_TRUE; nflag = GL_TRUE;
794 tcomps = 2; ccomps = 4; vcomps = 3;
795 ctype = GL_FLOAT;
796 coffset = 2*f;
797 noffset = 6*f;
798 voffset = 9*f;
799 defstride = 12*f;
800 break;
801 case GL_T4F_C4F_N3F_V4F:
802 tflag = GL_TRUE; cflag = GL_TRUE; nflag = GL_TRUE;
803 tcomps = 4; ccomps = 4; vcomps = 4;
804 ctype = GL_FLOAT;
805 coffset = 4*f;
806 noffset = 8*f;
807 voffset = 11*f;
808 defstride = 15*f;
809 break;
810 default:
811 _mesa_error( ctx, GL_INVALID_ENUM, "glInterleavedArrays(format)" );
812 return;
813 }
814
815 if (stride==0) {
816 stride = defstride;
817 }
818
819 _mesa_DisableClientState( GL_EDGE_FLAG_ARRAY );
820 _mesa_DisableClientState( GL_INDEX_ARRAY );
821 /* XXX also disable secondary color and generic arrays? */
822
823 /* Texcoords */
824 if (tflag) {
825 _mesa_EnableClientState( GL_TEXTURE_COORD_ARRAY );
826 _mesa_TexCoordPointer( tcomps, GL_FLOAT, stride,
827 (GLubyte *) pointer + toffset );
828 }
829 else {
830 _mesa_DisableClientState( GL_TEXTURE_COORD_ARRAY );
831 }
832
833 /* Color */
834 if (cflag) {
835 _mesa_EnableClientState( GL_COLOR_ARRAY );
836 _mesa_ColorPointer( ccomps, ctype, stride,
837 (GLubyte *) pointer + coffset );
838 }
839 else {
840 _mesa_DisableClientState( GL_COLOR_ARRAY );
841 }
842
843
844 /* Normals */
845 if (nflag) {
846 _mesa_EnableClientState( GL_NORMAL_ARRAY );
847 _mesa_NormalPointer( GL_FLOAT, stride, (GLubyte *) pointer + noffset );
848 }
849 else {
850 _mesa_DisableClientState( GL_NORMAL_ARRAY );
851 }
852
853 /* Vertices */
854 _mesa_EnableClientState( GL_VERTEX_ARRAY );
855 _mesa_VertexPointer( vcomps, GL_FLOAT, stride,
856 (GLubyte *) pointer + voffset );
857 }
858
859
860 void GLAPIENTRY
861 _mesa_LockArraysEXT(GLint first, GLsizei count)
862 {
863 GET_CURRENT_CONTEXT(ctx);
864 ASSERT_OUTSIDE_BEGIN_END_AND_FLUSH(ctx);
865
866 if (MESA_VERBOSE & VERBOSE_API)
867 _mesa_debug(ctx, "glLockArrays %d %d\n", first, count);
868
869 if (first < 0) {
870 _mesa_error( ctx, GL_INVALID_VALUE, "glLockArraysEXT(first)" );
871 return;
872 }
873 if (count <= 0) {
874 _mesa_error( ctx, GL_INVALID_VALUE, "glLockArraysEXT(count)" );
875 return;
876 }
877 if (ctx->Array.LockCount != 0) {
878 _mesa_error( ctx, GL_INVALID_OPERATION, "glLockArraysEXT(reentry)" );
879 return;
880 }
881
882 ctx->Array.LockFirst = first;
883 ctx->Array.LockCount = count;
884
885 ctx->NewState |= _NEW_ARRAY;
886 ctx->Array.NewState |= _NEW_ARRAY_ALL;
887
888 if (ctx->Driver.LockArraysEXT)
889 ctx->Driver.LockArraysEXT( ctx, first, count );
890 }
891
892
893 void GLAPIENTRY
894 _mesa_UnlockArraysEXT( void )
895 {
896 GET_CURRENT_CONTEXT(ctx);
897 ASSERT_OUTSIDE_BEGIN_END_AND_FLUSH(ctx);
898
899 if (MESA_VERBOSE & VERBOSE_API)
900 _mesa_debug(ctx, "glUnlockArrays\n");
901
902 if (ctx->Array.LockCount == 0) {
903 _mesa_error( ctx, GL_INVALID_OPERATION, "glUnlockArraysEXT(reexit)" );
904 return;
905 }
906
907 ctx->Array.LockFirst = 0;
908 ctx->Array.LockCount = 0;
909 ctx->NewState |= _NEW_ARRAY;
910 ctx->Array.NewState |= _NEW_ARRAY_ALL;
911
912 if (ctx->Driver.UnlockArraysEXT)
913 ctx->Driver.UnlockArraysEXT( ctx );
914 }
915
916
917 /* GL_EXT_multi_draw_arrays */
918 /* Somebody forgot to spec the first and count parameters as const! <sigh> */
919 void GLAPIENTRY
920 _mesa_MultiDrawArraysEXT( GLenum mode, GLint *first,
921 GLsizei *count, GLsizei primcount )
922 {
923 GET_CURRENT_CONTEXT(ctx);
924 GLint i;
925
926 ASSERT_OUTSIDE_BEGIN_END_AND_FLUSH(ctx);
927
928 for (i = 0; i < primcount; i++) {
929 if (count[i] > 0) {
930 CALL_DrawArrays(ctx->Exec, (mode, first[i], count[i]));
931 }
932 }
933 }
934
935
936 /* GL_EXT_multi_draw_arrays */
937 void GLAPIENTRY
938 _mesa_MultiDrawElementsEXT( GLenum mode, const GLsizei *count, GLenum type,
939 const GLvoid **indices, GLsizei primcount )
940 {
941 GET_CURRENT_CONTEXT(ctx);
942 GLint i;
943
944 ASSERT_OUTSIDE_BEGIN_END_AND_FLUSH(ctx);
945
946 for (i = 0; i < primcount; i++) {
947 if (count[i] > 0) {
948 CALL_DrawElements(ctx->Exec, (mode, count[i], type, indices[i]));
949 }
950 }
951 }
952
953
954 /* GL_IBM_multimode_draw_arrays */
955 void GLAPIENTRY
956 _mesa_MultiModeDrawArraysIBM( const GLenum * mode, const GLint * first,
957 const GLsizei * count,
958 GLsizei primcount, GLint modestride )
959 {
960 GET_CURRENT_CONTEXT(ctx);
961 GLint i;
962
963 ASSERT_OUTSIDE_BEGIN_END_AND_FLUSH(ctx);
964
965 for ( i = 0 ; i < primcount ; i++ ) {
966 if ( count[i] > 0 ) {
967 GLenum m = *((GLenum *) ((GLubyte *) mode + i * modestride));
968 CALL_DrawArrays(ctx->Exec, ( m, first[i], count[i] ));
969 }
970 }
971 }
972
973
974 /* GL_IBM_multimode_draw_arrays */
975 void GLAPIENTRY
976 _mesa_MultiModeDrawElementsIBM( const GLenum * mode, const GLsizei * count,
977 GLenum type, const GLvoid * const * indices,
978 GLsizei primcount, GLint modestride )
979 {
980 GET_CURRENT_CONTEXT(ctx);
981 GLint i;
982
983 ASSERT_OUTSIDE_BEGIN_END_AND_FLUSH(ctx);
984
985 /* XXX not sure about ARB_vertex_buffer_object handling here */
986
987 for ( i = 0 ; i < primcount ; i++ ) {
988 if ( count[i] > 0 ) {
989 GLenum m = *((GLenum *) ((GLubyte *) mode + i * modestride));
990 CALL_DrawElements(ctx->Exec, ( m, count[i], type, indices[i] ));
991 }
992 }
993 }
994
995
996 /**
997 * Initialize vertex array state for given context.
998 */
999 void
1000 _mesa_init_varray(GLcontext *ctx)
1001 {
1002 ctx->Array.DefaultArrayObj = _mesa_new_array_object(ctx, 0);
1003 ctx->Array.ArrayObj = ctx->Array.DefaultArrayObj;
1004
1005 ctx->Array.ActiveTexture = 0; /* GL_ARB_multitexture */
1006 }