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