Merge remote branch 'upstream/gallium-0.1' into nouveau-gallium-0.1
[mesa.git] / src / mesa / main / varray.c
1 /*
2 * Mesa 3-D graphics library
3 * Version: 6.5.1
4 *
5 * Copyright (C) 1999-2006 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 array->BufferObj->RefCount--;
66 if (array->BufferObj->RefCount <= 0) {
67 ASSERT(array->BufferObj->Name);
68 _mesa_remove_buffer_object( ctx, array->BufferObj );
69 (*ctx->Driver.DeleteBuffer)( ctx, array->BufferObj );
70 }
71 array->BufferObj = ctx->Array.ArrayBufferObj;
72 array->BufferObj->RefCount++;
73 /* Compute the index of the last array element that's inside the buffer.
74 * Later in glDrawArrays we'll check if start + count > _MaxElement to
75 * be sure we won't go out of bounds.
76 */
77 if (ctx->Array.ArrayBufferObj->Name)
78 array->_MaxElement = ((GLsizeiptrARB) ctx->Array.ArrayBufferObj->Size
79 - (GLsizeiptrARB) array->Ptr + array->StrideB
80 - elementSize) / array->StrideB;
81 else
82 #endif
83 array->_MaxElement = 2 * 1000 * 1000 * 1000; /* just a big number */
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 #if FEATURE_fixedpt
125 case GL_FIXED:
126 elementSize = size * sizeof(GLfixed);
127 break;
128 #endif
129 #if FEATURE_vertex_array_byte
130 case GL_BYTE:
131 elementSize = size * sizeof(GLbyte);
132 break;
133 #endif
134 default:
135 _mesa_error( ctx, GL_INVALID_ENUM, "glVertexPointer(type)" );
136 return;
137 }
138
139 update_array(ctx, &ctx->Array.ArrayObj->Vertex, _NEW_ARRAY_VERTEX,
140 elementSize, size, type, stride, GL_FALSE, ptr);
141
142 if (ctx->Driver.VertexPointer)
143 ctx->Driver.VertexPointer( ctx, size, type, stride, ptr );
144 }
145
146
147 void GLAPIENTRY
148 _mesa_NormalPointer(GLenum type, GLsizei stride, const GLvoid *ptr )
149 {
150 GLsizei elementSize;
151 GET_CURRENT_CONTEXT(ctx);
152 ASSERT_OUTSIDE_BEGIN_END_AND_FLUSH(ctx);
153
154 if (stride < 0) {
155 _mesa_error( ctx, GL_INVALID_VALUE, "glNormalPointer(stride)" );
156 return;
157 }
158
159 if (MESA_VERBOSE&(VERBOSE_VARRAY|VERBOSE_API))
160 _mesa_debug(ctx, "glNormalPointer( type %s stride %d )\n",
161 _mesa_lookup_enum_by_nr( type ), stride);
162
163 switch (type) {
164 case GL_BYTE:
165 elementSize = 3 * sizeof(GLbyte);
166 break;
167 case GL_SHORT:
168 elementSize = 3 * sizeof(GLshort);
169 break;
170 case GL_INT:
171 elementSize = 3 * sizeof(GLint);
172 break;
173 case GL_FLOAT:
174 elementSize = 3 * sizeof(GLfloat);
175 break;
176 case GL_DOUBLE:
177 elementSize = 3 * sizeof(GLdouble);
178 break;
179 #if FEATURE_fixedpt
180 case GL_FIXED:
181 elementSize = 3 * sizeof(GLfixed);
182 break;
183 #endif
184 default:
185 _mesa_error( ctx, GL_INVALID_ENUM, "glNormalPointer(type)" );
186 return;
187 }
188
189 update_array(ctx, &ctx->Array.ArrayObj->Normal, _NEW_ARRAY_NORMAL,
190 elementSize, 3, type, stride, GL_TRUE, ptr);
191
192 if (ctx->Driver.NormalPointer)
193 ctx->Driver.NormalPointer( ctx, type, stride, ptr );
194 }
195
196
197 void GLAPIENTRY
198 _mesa_ColorPointer(GLint size, GLenum type, GLsizei stride, const GLvoid *ptr)
199 {
200 GLsizei elementSize;
201 GET_CURRENT_CONTEXT(ctx);
202 ASSERT_OUTSIDE_BEGIN_END_AND_FLUSH(ctx);
203
204 if (size < 3 || size > 4) {
205 _mesa_error( ctx, GL_INVALID_VALUE, "glColorPointer(size)" );
206 return;
207 }
208 if (stride < 0) {
209 _mesa_error( ctx, GL_INVALID_VALUE, "glColorPointer(stride)" );
210 return;
211 }
212
213 if (MESA_VERBOSE&(VERBOSE_VARRAY|VERBOSE_API))
214 _mesa_debug(ctx, "glColorPointer( sz %d type %s stride %d )\n", size,
215 _mesa_lookup_enum_by_nr( type ), stride);
216
217 switch (type) {
218 case GL_BYTE:
219 elementSize = size * sizeof(GLbyte);
220 break;
221 case GL_UNSIGNED_BYTE:
222 elementSize = size * sizeof(GLubyte);
223 break;
224 case GL_SHORT:
225 elementSize = size * sizeof(GLshort);
226 break;
227 case GL_UNSIGNED_SHORT:
228 elementSize = size * sizeof(GLushort);
229 break;
230 case GL_INT:
231 elementSize = size * sizeof(GLint);
232 break;
233 case GL_UNSIGNED_INT:
234 elementSize = size * sizeof(GLuint);
235 break;
236 case GL_FLOAT:
237 elementSize = size * sizeof(GLfloat);
238 break;
239 case GL_DOUBLE:
240 elementSize = size * sizeof(GLdouble);
241 break;
242 #if FEATURE_fixedpt
243 case GL_FIXED:
244 elementSize = size * sizeof(GLfixed);
245 break;
246 #endif
247 default:
248 _mesa_error( ctx, GL_INVALID_ENUM, "glColorPointer(type)" );
249 return;
250 }
251
252 update_array(ctx, &ctx->Array.ArrayObj->Color, _NEW_ARRAY_COLOR0,
253 elementSize, size, type, stride, GL_TRUE, ptr);
254
255 if (ctx->Driver.ColorPointer)
256 ctx->Driver.ColorPointer( ctx, size, type, stride, ptr );
257 }
258
259
260 void GLAPIENTRY
261 _mesa_FogCoordPointerEXT(GLenum type, GLsizei stride, const GLvoid *ptr)
262 {
263 GLint elementSize;
264 GET_CURRENT_CONTEXT(ctx);
265 ASSERT_OUTSIDE_BEGIN_END_AND_FLUSH(ctx);
266
267 if (stride < 0) {
268 _mesa_error( ctx, GL_INVALID_VALUE, "glFogCoordPointer(stride)" );
269 return;
270 }
271
272 switch (type) {
273 case GL_FLOAT:
274 elementSize = sizeof(GLfloat);
275 break;
276 case GL_DOUBLE:
277 elementSize = sizeof(GLdouble);
278 break;
279 default:
280 _mesa_error( ctx, GL_INVALID_ENUM, "glFogCoordPointer(type)" );
281 return;
282 }
283
284 update_array(ctx, &ctx->Array.ArrayObj->FogCoord, _NEW_ARRAY_FOGCOORD,
285 elementSize, 1, type, stride, GL_FALSE, ptr);
286
287 if (ctx->Driver.FogCoordPointer)
288 ctx->Driver.FogCoordPointer( ctx, type, stride, ptr );
289 }
290
291
292 void GLAPIENTRY
293 _mesa_IndexPointer(GLenum type, GLsizei stride, const GLvoid *ptr)
294 {
295 GLsizei elementSize;
296 GET_CURRENT_CONTEXT(ctx);
297 ASSERT_OUTSIDE_BEGIN_END_AND_FLUSH(ctx);
298
299 if (stride < 0) {
300 _mesa_error( ctx, GL_INVALID_VALUE, "glIndexPointer(stride)" );
301 return;
302 }
303
304 switch (type) {
305 case GL_UNSIGNED_BYTE:
306 elementSize = sizeof(GLubyte);
307 break;
308 case GL_SHORT:
309 elementSize = sizeof(GLshort);
310 break;
311 case GL_INT:
312 elementSize = sizeof(GLint);
313 break;
314 case GL_FLOAT:
315 elementSize = sizeof(GLfloat);
316 break;
317 case GL_DOUBLE:
318 elementSize = sizeof(GLdouble);
319 break;
320 default:
321 _mesa_error( ctx, GL_INVALID_ENUM, "glIndexPointer(type)" );
322 return;
323 }
324
325 update_array(ctx, &ctx->Array.ArrayObj->Index, _NEW_ARRAY_INDEX,
326 elementSize, 1, type, stride, GL_FALSE, ptr);
327
328 if (ctx->Driver.IndexPointer)
329 ctx->Driver.IndexPointer( ctx, type, stride, ptr );
330 }
331
332
333 void GLAPIENTRY
334 _mesa_SecondaryColorPointerEXT(GLint size, GLenum type,
335 GLsizei stride, const GLvoid *ptr)
336 {
337 GLsizei elementSize;
338 GET_CURRENT_CONTEXT(ctx);
339 ASSERT_OUTSIDE_BEGIN_END_AND_FLUSH(ctx);
340
341 if (size != 3 && size != 4) {
342 _mesa_error( ctx, GL_INVALID_VALUE, "glSecondaryColorPointer(size)" );
343 return;
344 }
345 if (stride < 0) {
346 _mesa_error( ctx, GL_INVALID_VALUE, "glSecondaryColorPointer(stride)" );
347 return;
348 }
349
350 if (MESA_VERBOSE&(VERBOSE_VARRAY|VERBOSE_API))
351 _mesa_debug(ctx, "glSecondaryColorPointer( sz %d type %s stride %d )\n",
352 size, _mesa_lookup_enum_by_nr( type ), stride);
353
354 switch (type) {
355 case GL_BYTE:
356 elementSize = size * sizeof(GLbyte);
357 break;
358 case GL_UNSIGNED_BYTE:
359 elementSize = size * sizeof(GLubyte);
360 break;
361 case GL_SHORT:
362 elementSize = size * sizeof(GLshort);
363 break;
364 case GL_UNSIGNED_SHORT:
365 elementSize = size * sizeof(GLushort);
366 break;
367 case GL_INT:
368 elementSize = size * sizeof(GLint);
369 break;
370 case GL_UNSIGNED_INT:
371 elementSize = size * sizeof(GLuint);
372 break;
373 case GL_FLOAT:
374 elementSize = size * sizeof(GLfloat);
375 break;
376 case GL_DOUBLE:
377 elementSize = size * sizeof(GLdouble);
378 break;
379 default:
380 _mesa_error( ctx, GL_INVALID_ENUM, "glSecondaryColorPointer(type)" );
381 return;
382 }
383
384 update_array(ctx, &ctx->Array.ArrayObj->SecondaryColor, _NEW_ARRAY_COLOR1,
385 elementSize, size, type, stride, GL_TRUE, ptr);
386
387 if (ctx->Driver.SecondaryColorPointer)
388 ctx->Driver.SecondaryColorPointer( ctx, size, type, stride, ptr );
389 }
390
391
392 void GLAPIENTRY
393 _mesa_TexCoordPointer(GLint size, GLenum type, GLsizei stride,
394 const GLvoid *ptr)
395 {
396 GLint elementSize;
397 GET_CURRENT_CONTEXT(ctx);
398 const GLuint unit = ctx->Array.ActiveTexture;
399 ASSERT_OUTSIDE_BEGIN_END_AND_FLUSH(ctx);
400
401 if (size < 1 || size > 4) {
402 _mesa_error( ctx, GL_INVALID_VALUE, "glTexCoordPointer(size)" );
403 return;
404 }
405 if (stride < 0) {
406 _mesa_error( ctx, GL_INVALID_VALUE, "glTexCoordPointer(stride)" );
407 return;
408 }
409
410 if (MESA_VERBOSE&(VERBOSE_VARRAY|VERBOSE_API))
411 _mesa_debug(ctx, "glTexCoordPointer(unit %u sz %d type %s stride %d)\n",
412 unit, size, _mesa_lookup_enum_by_nr( type ), stride);
413
414 /* always need to check that <type> is legal */
415 switch (type) {
416 case GL_SHORT:
417 elementSize = size * sizeof(GLshort);
418 break;
419 case GL_INT:
420 elementSize = size * sizeof(GLint);
421 break;
422 case GL_FLOAT:
423 elementSize = size * sizeof(GLfloat);
424 break;
425 case GL_DOUBLE:
426 elementSize = size * sizeof(GLdouble);
427 break;
428 #if FEATURE_fixedpt
429 case GL_FIXED:
430 elementSize = size * sizeof(GLfixed);
431 break;
432 #endif
433 #if FEATURE_vertex_array_byte
434 case GL_BYTE:
435 elementSize = size * sizeof(GLbyte);
436 break;
437 #endif
438 default:
439 _mesa_error( ctx, GL_INVALID_ENUM, "glTexCoordPointer(type)" );
440 return;
441 }
442
443 update_array(ctx, &ctx->Array.ArrayObj->TexCoord[unit],
444 _NEW_ARRAY_TEXCOORD(unit),
445 elementSize, size, type, stride, GL_FALSE, ptr);
446
447 if (ctx->Driver.TexCoordPointer)
448 ctx->Driver.TexCoordPointer( ctx, size, type, stride, ptr );
449 }
450
451
452 void GLAPIENTRY
453 _mesa_EdgeFlagPointer(GLsizei stride, const GLvoid *ptr)
454 {
455 GET_CURRENT_CONTEXT(ctx);
456 ASSERT_OUTSIDE_BEGIN_END_AND_FLUSH(ctx);
457
458 if (stride < 0) {
459 _mesa_error( ctx, GL_INVALID_VALUE, "glEdgeFlagPointer(stride)" );
460 return;
461 }
462
463 update_array(ctx, &ctx->Array.ArrayObj->EdgeFlag, _NEW_ARRAY_EDGEFLAG,
464 sizeof(GLboolean), 1, GL_UNSIGNED_BYTE, stride, GL_FALSE, ptr);
465
466 if (ctx->Driver.EdgeFlagPointer)
467 ctx->Driver.EdgeFlagPointer( ctx, stride, ptr );
468 }
469
470
471 #if FEATURE_NV_vertex_program
472 void GLAPIENTRY
473 _mesa_VertexAttribPointerNV(GLuint index, GLint size, GLenum type,
474 GLsizei stride, const GLvoid *ptr)
475 {
476 const GLboolean normalized = GL_FALSE;
477 GLsizei elementSize;
478 GET_CURRENT_CONTEXT(ctx);
479 ASSERT_OUTSIDE_BEGIN_END(ctx);
480
481 if (index >= MAX_VERTEX_PROGRAM_ATTRIBS) {
482 _mesa_error(ctx, GL_INVALID_VALUE, "glVertexAttribPointerNV(index)");
483 return;
484 }
485
486 if (size < 1 || size > 4) {
487 _mesa_error(ctx, GL_INVALID_VALUE, "glVertexAttribPointerNV(size)");
488 return;
489 }
490
491 if (stride < 0) {
492 _mesa_error(ctx, GL_INVALID_VALUE, "glVertexAttribPointerNV(stride)");
493 return;
494 }
495
496 if (type == GL_UNSIGNED_BYTE && size != 4) {
497 _mesa_error(ctx, GL_INVALID_VALUE, "glVertexAttribPointerNV(size!=4)");
498 return;
499 }
500
501 /* check for valid 'type' and compute StrideB right away */
502 switch (type) {
503 case GL_UNSIGNED_BYTE:
504 elementSize = size * sizeof(GLubyte);
505 break;
506 case GL_SHORT:
507 elementSize = size * sizeof(GLshort);
508 break;
509 case GL_FLOAT:
510 elementSize = size * sizeof(GLfloat);
511 break;
512 case GL_DOUBLE:
513 elementSize = size * sizeof(GLdouble);
514 break;
515 default:
516 _mesa_error( ctx, GL_INVALID_ENUM, "glVertexAttribPointerNV(type)" );
517 return;
518 }
519
520 update_array(ctx, &ctx->Array.ArrayObj->VertexAttrib[index],
521 _NEW_ARRAY_ATTRIB(index),
522 elementSize, size, type, stride, normalized, ptr);
523
524 if (ctx->Driver.VertexAttribPointer)
525 ctx->Driver.VertexAttribPointer( ctx, index, size, type, stride, ptr );
526 }
527 #endif
528
529
530 #if FEATURE_ARB_vertex_program
531 void GLAPIENTRY
532 _mesa_VertexAttribPointerARB(GLuint index, GLint size, GLenum type,
533 GLboolean normalized,
534 GLsizei stride, const GLvoid *ptr)
535 {
536 GLsizei elementSize;
537 GET_CURRENT_CONTEXT(ctx);
538 ASSERT_OUTSIDE_BEGIN_END(ctx);
539
540 if (index >= ctx->Const.VertexProgram.MaxAttribs) {
541 _mesa_error(ctx, GL_INVALID_VALUE, "glVertexAttribPointerARB(index)");
542 return;
543 }
544
545 if (size < 1 || size > 4) {
546 _mesa_error(ctx, GL_INVALID_VALUE, "glVertexAttribPointerARB(size)");
547 return;
548 }
549
550 if (stride < 0) {
551 _mesa_error(ctx, GL_INVALID_VALUE, "glVertexAttribPointerARB(stride)");
552 return;
553 }
554
555 if (type == GL_UNSIGNED_BYTE && size != 4) {
556 _mesa_error(ctx, GL_INVALID_VALUE, "glVertexAttribPointerARB(size!=4)");
557 return;
558 }
559
560 /* check for valid 'type' and compute StrideB right away */
561 /* NOTE: more types are supported here than in the NV extension */
562 switch (type) {
563 case GL_BYTE:
564 elementSize = size * sizeof(GLbyte);
565 break;
566 case GL_UNSIGNED_BYTE:
567 elementSize = size * sizeof(GLubyte);
568 break;
569 case GL_SHORT:
570 elementSize = size * sizeof(GLshort);
571 break;
572 case GL_UNSIGNED_SHORT:
573 elementSize = size * sizeof(GLushort);
574 break;
575 case GL_INT:
576 elementSize = size * sizeof(GLint);
577 break;
578 case GL_UNSIGNED_INT:
579 elementSize = size * sizeof(GLuint);
580 break;
581 case GL_FLOAT:
582 elementSize = size * sizeof(GLfloat);
583 break;
584 case GL_DOUBLE:
585 elementSize = size * sizeof(GLdouble);
586 break;
587 default:
588 _mesa_error( ctx, GL_INVALID_ENUM, "glVertexAttribPointerARB(type)" );
589 return;
590 }
591
592 update_array(ctx, &ctx->Array.ArrayObj->VertexAttrib[index],
593 _NEW_ARRAY_ATTRIB(index),
594 elementSize, size, type, stride, normalized, ptr);
595
596 if (ctx->Driver.VertexAttribPointer)
597 ctx->Driver.VertexAttribPointer(ctx, index, size, type, stride, ptr);
598 }
599 #endif
600
601
602 void GLAPIENTRY
603 _mesa_VertexPointerEXT(GLint size, GLenum type, GLsizei stride,
604 GLsizei count, const GLvoid *ptr)
605 {
606 (void) count;
607 _mesa_VertexPointer(size, type, stride, ptr);
608 }
609
610
611 void GLAPIENTRY
612 _mesa_NormalPointerEXT(GLenum type, GLsizei stride, GLsizei count,
613 const GLvoid *ptr)
614 {
615 (void) count;
616 _mesa_NormalPointer(type, stride, ptr);
617 }
618
619
620 void GLAPIENTRY
621 _mesa_ColorPointerEXT(GLint size, GLenum type, GLsizei stride, GLsizei count,
622 const GLvoid *ptr)
623 {
624 (void) count;
625 _mesa_ColorPointer(size, type, stride, ptr);
626 }
627
628
629 void GLAPIENTRY
630 _mesa_IndexPointerEXT(GLenum type, GLsizei stride, GLsizei count,
631 const GLvoid *ptr)
632 {
633 (void) count;
634 _mesa_IndexPointer(type, stride, ptr);
635 }
636
637
638 void GLAPIENTRY
639 _mesa_TexCoordPointerEXT(GLint size, GLenum type, GLsizei stride,
640 GLsizei count, const GLvoid *ptr)
641 {
642 (void) count;
643 _mesa_TexCoordPointer(size, type, stride, ptr);
644 }
645
646
647 void GLAPIENTRY
648 _mesa_EdgeFlagPointerEXT(GLsizei stride, GLsizei count, const GLboolean *ptr)
649 {
650 (void) count;
651 _mesa_EdgeFlagPointer(stride, ptr);
652 }
653
654
655 void GLAPIENTRY
656 _mesa_InterleavedArrays(GLenum format, GLsizei stride, const GLvoid *pointer)
657 {
658 GET_CURRENT_CONTEXT(ctx);
659 GLboolean tflag, cflag, nflag; /* enable/disable flags */
660 GLint tcomps, ccomps, vcomps; /* components per texcoord, color, vertex */
661 GLenum ctype = 0; /* color type */
662 GLint coffset = 0, noffset = 0, voffset;/* color, normal, vertex offsets */
663 const GLint toffset = 0; /* always zero */
664 GLint defstride; /* default stride */
665 GLint c, f;
666
667 ASSERT_OUTSIDE_BEGIN_END_AND_FLUSH(ctx);
668
669 f = sizeof(GLfloat);
670 c = f * ((4 * sizeof(GLubyte) + (f - 1)) / f);
671
672 if (stride < 0) {
673 _mesa_error( ctx, GL_INVALID_VALUE, "glInterleavedArrays(stride)" );
674 return;
675 }
676
677 switch (format) {
678 case GL_V2F:
679 tflag = GL_FALSE; cflag = GL_FALSE; nflag = GL_FALSE;
680 tcomps = 0; ccomps = 0; vcomps = 2;
681 voffset = 0;
682 defstride = 2*f;
683 break;
684 case GL_V3F:
685 tflag = GL_FALSE; cflag = GL_FALSE; nflag = GL_FALSE;
686 tcomps = 0; ccomps = 0; vcomps = 3;
687 voffset = 0;
688 defstride = 3*f;
689 break;
690 case GL_C4UB_V2F:
691 tflag = GL_FALSE; cflag = GL_TRUE; nflag = GL_FALSE;
692 tcomps = 0; ccomps = 4; vcomps = 2;
693 ctype = GL_UNSIGNED_BYTE;
694 coffset = 0;
695 voffset = c;
696 defstride = c + 2*f;
697 break;
698 case GL_C4UB_V3F:
699 tflag = GL_FALSE; cflag = GL_TRUE; nflag = GL_FALSE;
700 tcomps = 0; ccomps = 4; vcomps = 3;
701 ctype = GL_UNSIGNED_BYTE;
702 coffset = 0;
703 voffset = c;
704 defstride = c + 3*f;
705 break;
706 case GL_C3F_V3F:
707 tflag = GL_FALSE; cflag = GL_TRUE; nflag = GL_FALSE;
708 tcomps = 0; ccomps = 3; vcomps = 3;
709 ctype = GL_FLOAT;
710 coffset = 0;
711 voffset = 3*f;
712 defstride = 6*f;
713 break;
714 case GL_N3F_V3F:
715 tflag = GL_FALSE; cflag = GL_FALSE; nflag = GL_TRUE;
716 tcomps = 0; ccomps = 0; vcomps = 3;
717 noffset = 0;
718 voffset = 3*f;
719 defstride = 6*f;
720 break;
721 case GL_C4F_N3F_V3F:
722 tflag = GL_FALSE; cflag = GL_TRUE; nflag = GL_TRUE;
723 tcomps = 0; ccomps = 4; vcomps = 3;
724 ctype = GL_FLOAT;
725 coffset = 0;
726 noffset = 4*f;
727 voffset = 7*f;
728 defstride = 10*f;
729 break;
730 case GL_T2F_V3F:
731 tflag = GL_TRUE; cflag = GL_FALSE; nflag = GL_FALSE;
732 tcomps = 2; ccomps = 0; vcomps = 3;
733 voffset = 2*f;
734 defstride = 5*f;
735 break;
736 case GL_T4F_V4F:
737 tflag = GL_TRUE; cflag = GL_FALSE; nflag = GL_FALSE;
738 tcomps = 4; ccomps = 0; vcomps = 4;
739 voffset = 4*f;
740 defstride = 8*f;
741 break;
742 case GL_T2F_C4UB_V3F:
743 tflag = GL_TRUE; cflag = GL_TRUE; nflag = GL_FALSE;
744 tcomps = 2; ccomps = 4; vcomps = 3;
745 ctype = GL_UNSIGNED_BYTE;
746 coffset = 2*f;
747 voffset = c+2*f;
748 defstride = c+5*f;
749 break;
750 case GL_T2F_C3F_V3F:
751 tflag = GL_TRUE; cflag = GL_TRUE; nflag = GL_FALSE;
752 tcomps = 2; ccomps = 3; vcomps = 3;
753 ctype = GL_FLOAT;
754 coffset = 2*f;
755 voffset = 5*f;
756 defstride = 8*f;
757 break;
758 case GL_T2F_N3F_V3F:
759 tflag = GL_TRUE; cflag = GL_FALSE; nflag = GL_TRUE;
760 tcomps = 2; ccomps = 0; vcomps = 3;
761 noffset = 2*f;
762 voffset = 5*f;
763 defstride = 8*f;
764 break;
765 case GL_T2F_C4F_N3F_V3F:
766 tflag = GL_TRUE; cflag = GL_TRUE; nflag = GL_TRUE;
767 tcomps = 2; ccomps = 4; vcomps = 3;
768 ctype = GL_FLOAT;
769 coffset = 2*f;
770 noffset = 6*f;
771 voffset = 9*f;
772 defstride = 12*f;
773 break;
774 case GL_T4F_C4F_N3F_V4F:
775 tflag = GL_TRUE; cflag = GL_TRUE; nflag = GL_TRUE;
776 tcomps = 4; ccomps = 4; vcomps = 4;
777 ctype = GL_FLOAT;
778 coffset = 4*f;
779 noffset = 8*f;
780 voffset = 11*f;
781 defstride = 15*f;
782 break;
783 default:
784 _mesa_error( ctx, GL_INVALID_ENUM, "glInterleavedArrays(format)" );
785 return;
786 }
787
788 if (stride==0) {
789 stride = defstride;
790 }
791
792 _mesa_DisableClientState( GL_EDGE_FLAG_ARRAY );
793 _mesa_DisableClientState( GL_INDEX_ARRAY );
794 /* XXX also disable secondary color and generic arrays? */
795
796 /* Texcoords */
797 if (tflag) {
798 _mesa_EnableClientState( GL_TEXTURE_COORD_ARRAY );
799 _mesa_TexCoordPointer( tcomps, GL_FLOAT, stride,
800 (GLubyte *) pointer + toffset );
801 }
802 else {
803 _mesa_DisableClientState( GL_TEXTURE_COORD_ARRAY );
804 }
805
806 /* Color */
807 if (cflag) {
808 _mesa_EnableClientState( GL_COLOR_ARRAY );
809 _mesa_ColorPointer( ccomps, ctype, stride,
810 (GLubyte *) pointer + coffset );
811 }
812 else {
813 _mesa_DisableClientState( GL_COLOR_ARRAY );
814 }
815
816
817 /* Normals */
818 if (nflag) {
819 _mesa_EnableClientState( GL_NORMAL_ARRAY );
820 _mesa_NormalPointer( GL_FLOAT, stride, (GLubyte *) pointer + noffset );
821 }
822 else {
823 _mesa_DisableClientState( GL_NORMAL_ARRAY );
824 }
825
826 /* Vertices */
827 _mesa_EnableClientState( GL_VERTEX_ARRAY );
828 _mesa_VertexPointer( vcomps, GL_FLOAT, stride,
829 (GLubyte *) pointer + voffset );
830 }
831
832
833 void GLAPIENTRY
834 _mesa_LockArraysEXT(GLint first, GLsizei count)
835 {
836 GET_CURRENT_CONTEXT(ctx);
837 ASSERT_OUTSIDE_BEGIN_END_AND_FLUSH(ctx);
838
839 if (MESA_VERBOSE & VERBOSE_API)
840 _mesa_debug(ctx, "glLockArrays %d %d\n", first, count);
841
842 if (first == 0 && count > 0 &&
843 count <= (GLint) ctx->Const.MaxArrayLockSize) {
844 ctx->Array.LockFirst = first;
845 ctx->Array.LockCount = count;
846 }
847 else {
848 ctx->Array.LockFirst = 0;
849 ctx->Array.LockCount = 0;
850 }
851
852 ctx->NewState |= _NEW_ARRAY;
853 ctx->Array.NewState |= _NEW_ARRAY_ALL;
854
855 if (ctx->Driver.LockArraysEXT)
856 ctx->Driver.LockArraysEXT( ctx, first, count );
857 }
858
859
860 void GLAPIENTRY
861 _mesa_UnlockArraysEXT( void )
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, "glUnlockArrays\n");
868
869 ctx->Array.LockFirst = 0;
870 ctx->Array.LockCount = 0;
871 ctx->NewState |= _NEW_ARRAY;
872 ctx->Array.NewState |= _NEW_ARRAY_ALL;
873
874 if (ctx->Driver.UnlockArraysEXT)
875 ctx->Driver.UnlockArraysEXT( ctx );
876 }
877
878
879 /* GL_EXT_multi_draw_arrays */
880 /* Somebody forgot to spec the first and count parameters as const! <sigh> */
881 void GLAPIENTRY
882 _mesa_MultiDrawArraysEXT( GLenum mode, GLint *first,
883 GLsizei *count, GLsizei primcount )
884 {
885 GET_CURRENT_CONTEXT(ctx);
886 GLint i;
887
888 ASSERT_OUTSIDE_BEGIN_END_AND_FLUSH(ctx);
889
890 for (i = 0; i < primcount; i++) {
891 if (count[i] > 0) {
892 CALL_DrawArrays(ctx->Exec, (mode, first[i], count[i]));
893 }
894 }
895 }
896
897
898 /* GL_EXT_multi_draw_arrays */
899 void GLAPIENTRY
900 _mesa_MultiDrawElementsEXT( GLenum mode, const GLsizei *count, GLenum type,
901 const GLvoid **indices, GLsizei primcount )
902 {
903 GET_CURRENT_CONTEXT(ctx);
904 GLint i;
905
906 ASSERT_OUTSIDE_BEGIN_END_AND_FLUSH(ctx);
907
908 for (i = 0; i < primcount; i++) {
909 if (count[i] > 0) {
910 CALL_DrawElements(ctx->Exec, (mode, count[i], type, indices[i]));
911 }
912 }
913 }
914
915
916 /* GL_IBM_multimode_draw_arrays */
917 void GLAPIENTRY
918 _mesa_MultiModeDrawArraysIBM( const GLenum * mode, const GLint * first,
919 const GLsizei * count,
920 GLsizei primcount, GLint modestride )
921 {
922 GET_CURRENT_CONTEXT(ctx);
923 GLint i;
924
925 ASSERT_OUTSIDE_BEGIN_END_AND_FLUSH(ctx);
926
927 for ( i = 0 ; i < primcount ; i++ ) {
928 if ( count[i] > 0 ) {
929 GLenum m = *((GLenum *) ((GLubyte *) mode + i * modestride));
930 CALL_DrawArrays(ctx->Exec, ( m, first[i], count[i] ));
931 }
932 }
933 }
934
935
936 /* GL_IBM_multimode_draw_arrays */
937 void GLAPIENTRY
938 _mesa_MultiModeDrawElementsIBM( const GLenum * mode, const GLsizei * count,
939 GLenum type, const GLvoid * const * indices,
940 GLsizei primcount, GLint modestride )
941 {
942 GET_CURRENT_CONTEXT(ctx);
943 GLint i;
944
945 ASSERT_OUTSIDE_BEGIN_END_AND_FLUSH(ctx);
946
947 /* XXX not sure about ARB_vertex_buffer_object handling here */
948
949 for ( i = 0 ; i < primcount ; i++ ) {
950 if ( count[i] > 0 ) {
951 GLenum m = *((GLenum *) ((GLubyte *) mode + i * modestride));
952 CALL_DrawElements(ctx->Exec, ( m, count[i], type, indices[i] ));
953 }
954 }
955 }
956
957
958 /**
959 * Initialize vertex array state for given context.
960 */
961 void
962 _mesa_init_varray(GLcontext *ctx)
963 {
964 ctx->Array.DefaultArrayObj = _mesa_new_array_object(ctx, 0);
965 ctx->Array.ArrayObj = ctx->Array.DefaultArrayObj;
966
967 ctx->Array.ActiveTexture = 0; /* GL_ARB_multitexture */
968 }