fix for-loop in _mesa_GetDouble to avoid out of bounds memory read
[mesa.git] / src / mesa / main / varray.c
1 /*
2 * Mesa 3-D graphics library
3 * Version: 6.1
4 *
5 * Copyright (C) 1999-2004 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 ASSERT(array->BufferObj->Name);
64 _mesa_remove_buffer_object( ctx, array->BufferObj );
65 (*ctx->Driver.DeleteBuffer)( ctx, array->BufferObj );
66 }
67 array->BufferObj = ctx->Array.ArrayBufferObj;
68 array->BufferObj->RefCount++;
69 /* Compute the index of the last array element that's inside the buffer.
70 * Later in glDrawArrays we'll check if start + count > _MaxElement to
71 * be sure we won't go out of bounds.
72 */
73 if (ctx->Array.ArrayBufferObj->Name)
74 array->_MaxElement = ((GLsizeiptrARB) ctx->Array.ArrayBufferObj->Size
75 - (GLsizeiptrARB) array->Ptr) / 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 |= dirtyFlag;
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 default:
120 _mesa_error( ctx, GL_INVALID_ENUM, "glVertexPointer(type)" );
121 return;
122 }
123
124 update_array(ctx, &ctx->Array.Vertex, _NEW_ARRAY_VERTEX,
125 elementSize, size, type, stride, GL_FALSE, ptr);
126
127 if (ctx->Driver.VertexPointer)
128 ctx->Driver.VertexPointer( ctx, size, type, stride, ptr );
129 }
130
131
132 void GLAPIENTRY
133 _mesa_NormalPointer(GLenum type, GLsizei stride, const GLvoid *ptr )
134 {
135 GLsizei elementSize;
136 GET_CURRENT_CONTEXT(ctx);
137 ASSERT_OUTSIDE_BEGIN_END_AND_FLUSH(ctx);
138
139 if (stride < 0) {
140 _mesa_error( ctx, GL_INVALID_VALUE, "glNormalPointer(stride)" );
141 return;
142 }
143
144 if (MESA_VERBOSE&(VERBOSE_VARRAY|VERBOSE_API))
145 _mesa_debug(ctx, "glNormalPointer( type %s stride %d )\n",
146 _mesa_lookup_enum_by_nr( type ), stride);
147
148 switch (type) {
149 case GL_BYTE:
150 elementSize = 3 * sizeof(GLbyte);
151 break;
152 case GL_SHORT:
153 elementSize = 3 * sizeof(GLshort);
154 break;
155 case GL_INT:
156 elementSize = 3 * sizeof(GLint);
157 break;
158 case GL_FLOAT:
159 elementSize = 3 * sizeof(GLfloat);
160 break;
161 case GL_DOUBLE:
162 elementSize = 3 * sizeof(GLdouble);
163 break;
164 default:
165 _mesa_error( ctx, GL_INVALID_ENUM, "glNormalPointer(type)" );
166 return;
167 }
168
169 update_array(ctx, &ctx->Array.Normal, _NEW_ARRAY_NORMAL,
170 elementSize, 3, type, stride, GL_FALSE, ptr);
171
172 if (ctx->Driver.NormalPointer)
173 ctx->Driver.NormalPointer( ctx, type, stride, ptr );
174 }
175
176
177 void GLAPIENTRY
178 _mesa_ColorPointer(GLint size, GLenum type, GLsizei stride, const GLvoid *ptr)
179 {
180 GLsizei elementSize;
181 GET_CURRENT_CONTEXT(ctx);
182 ASSERT_OUTSIDE_BEGIN_END_AND_FLUSH(ctx);
183
184 if (size < 3 || size > 4) {
185 _mesa_error( ctx, GL_INVALID_VALUE, "glColorPointer(size)" );
186 return;
187 }
188 if (stride < 0) {
189 _mesa_error( ctx, GL_INVALID_VALUE, "glColorPointer(stride)" );
190 return;
191 }
192
193 if (MESA_VERBOSE&(VERBOSE_VARRAY|VERBOSE_API))
194 _mesa_debug(ctx, "glColorPointer( sz %d type %s stride %d )\n", size,
195 _mesa_lookup_enum_by_nr( type ), stride);
196
197 switch (type) {
198 case GL_BYTE:
199 elementSize = size * sizeof(GLbyte);
200 break;
201 case GL_UNSIGNED_BYTE:
202 elementSize = size * sizeof(GLubyte);
203 break;
204 case GL_SHORT:
205 elementSize = size * sizeof(GLshort);
206 break;
207 case GL_UNSIGNED_SHORT:
208 elementSize = size * sizeof(GLushort);
209 break;
210 case GL_INT:
211 elementSize = size * sizeof(GLint);
212 break;
213 case GL_UNSIGNED_INT:
214 elementSize = size * sizeof(GLuint);
215 break;
216 case GL_FLOAT:
217 elementSize = size * sizeof(GLfloat);
218 break;
219 case GL_DOUBLE:
220 elementSize = size * sizeof(GLdouble);
221 break;
222 default:
223 _mesa_error( ctx, GL_INVALID_ENUM, "glColorPointer(type)" );
224 return;
225 }
226
227 update_array(ctx, &ctx->Array.Color, _NEW_ARRAY_COLOR0,
228 elementSize, size, type, stride, GL_FALSE, ptr);
229
230 if (ctx->Driver.ColorPointer)
231 ctx->Driver.ColorPointer( ctx, size, type, stride, ptr );
232 }
233
234
235 void GLAPIENTRY
236 _mesa_FogCoordPointerEXT(GLenum type, GLsizei stride, const GLvoid *ptr)
237 {
238 GLint elementSize;
239 GET_CURRENT_CONTEXT(ctx);
240 ASSERT_OUTSIDE_BEGIN_END_AND_FLUSH(ctx);
241
242 if (stride < 0) {
243 _mesa_error( ctx, GL_INVALID_VALUE, "glFogCoordPointer(stride)" );
244 return;
245 }
246
247 switch (type) {
248 case GL_FLOAT:
249 elementSize = sizeof(GLfloat);
250 break;
251 case GL_DOUBLE:
252 elementSize = sizeof(GLdouble);
253 break;
254 default:
255 _mesa_error( ctx, GL_INVALID_ENUM, "glFogCoordPointer(type)" );
256 return;
257 }
258
259 update_array(ctx, &ctx->Array.FogCoord, _NEW_ARRAY_FOGCOORD,
260 elementSize, 1, type, stride, GL_FALSE, ptr);
261
262 if (ctx->Driver.FogCoordPointer)
263 ctx->Driver.FogCoordPointer( ctx, type, stride, ptr );
264 }
265
266
267 void GLAPIENTRY
268 _mesa_IndexPointer(GLenum type, GLsizei stride, const GLvoid *ptr)
269 {
270 GLsizei elementSize;
271 GET_CURRENT_CONTEXT(ctx);
272 ASSERT_OUTSIDE_BEGIN_END_AND_FLUSH(ctx);
273
274 if (stride < 0) {
275 _mesa_error( ctx, GL_INVALID_VALUE, "glIndexPointer(stride)" );
276 return;
277 }
278
279 switch (type) {
280 case GL_UNSIGNED_BYTE:
281 elementSize = sizeof(GLubyte);
282 break;
283 case GL_SHORT:
284 elementSize = sizeof(GLshort);
285 break;
286 case GL_INT:
287 elementSize = sizeof(GLint);
288 break;
289 case GL_FLOAT:
290 elementSize = sizeof(GLfloat);
291 break;
292 case GL_DOUBLE:
293 elementSize = sizeof(GLdouble);
294 break;
295 default:
296 _mesa_error( ctx, GL_INVALID_ENUM, "glIndexPointer(type)" );
297 return;
298 }
299
300 update_array(ctx, &ctx->Array.Index, _NEW_ARRAY_INDEX,
301 elementSize, 1, type, stride, GL_FALSE, ptr);
302
303 if (ctx->Driver.IndexPointer)
304 ctx->Driver.IndexPointer( ctx, type, stride, ptr );
305 }
306
307
308 void GLAPIENTRY
309 _mesa_SecondaryColorPointerEXT(GLint size, GLenum type,
310 GLsizei stride, const GLvoid *ptr)
311 {
312 GLsizei elementSize;
313 GET_CURRENT_CONTEXT(ctx);
314 ASSERT_OUTSIDE_BEGIN_END_AND_FLUSH(ctx);
315
316 if (size != 3 && size != 4) {
317 _mesa_error( ctx, GL_INVALID_VALUE, "glSecondaryColorPointer(size)" );
318 return;
319 }
320 if (stride < 0) {
321 _mesa_error( ctx, GL_INVALID_VALUE, "glSecondaryColorPointer(stride)" );
322 return;
323 }
324
325 if (MESA_VERBOSE&(VERBOSE_VARRAY|VERBOSE_API))
326 _mesa_debug(ctx, "glSecondaryColorPointer( sz %d type %s stride %d )\n",
327 size, _mesa_lookup_enum_by_nr( type ), stride);
328
329 switch (type) {
330 case GL_BYTE:
331 elementSize = size * sizeof(GLbyte);
332 break;
333 case GL_UNSIGNED_BYTE:
334 elementSize = size * sizeof(GLubyte);
335 break;
336 case GL_SHORT:
337 elementSize = size * sizeof(GLshort);
338 break;
339 case GL_UNSIGNED_SHORT:
340 elementSize = size * sizeof(GLushort);
341 break;
342 case GL_INT:
343 elementSize = size * sizeof(GLint);
344 break;
345 case GL_UNSIGNED_INT:
346 elementSize = size * sizeof(GLuint);
347 break;
348 case GL_FLOAT:
349 elementSize = size * sizeof(GLfloat);
350 break;
351 case GL_DOUBLE:
352 elementSize = size * sizeof(GLdouble);
353 break;
354 default:
355 _mesa_error( ctx, GL_INVALID_ENUM, "glSecondaryColorPointer(type)" );
356 return;
357 }
358
359 update_array(ctx, &ctx->Array.SecondaryColor, _NEW_ARRAY_COLOR1,
360 elementSize, size, type, stride, GL_FALSE, ptr);
361
362 if (ctx->Driver.SecondaryColorPointer)
363 ctx->Driver.SecondaryColorPointer( ctx, size, type, stride, ptr );
364 }
365
366
367 void GLAPIENTRY
368 _mesa_TexCoordPointer(GLint size, GLenum type, GLsizei stride,
369 const GLvoid *ptr)
370 {
371 GLint elementSize;
372 GET_CURRENT_CONTEXT(ctx);
373 const GLuint unit = ctx->Array.ActiveTexture;
374 ASSERT_OUTSIDE_BEGIN_END_AND_FLUSH(ctx);
375
376 if (size < 1 || size > 4) {
377 _mesa_error( ctx, GL_INVALID_VALUE, "glTexCoordPointer(size)" );
378 return;
379 }
380 if (stride < 0) {
381 _mesa_error( ctx, GL_INVALID_VALUE, "glTexCoordPointer(stride)" );
382 return;
383 }
384
385 if (MESA_VERBOSE&(VERBOSE_VARRAY|VERBOSE_API))
386 _mesa_debug(ctx, "glTexCoordPointer(unit %u sz %d type %s stride %d)\n",
387 unit, size, _mesa_lookup_enum_by_nr( type ), stride);
388
389 /* always need to check that <type> is legal */
390 switch (type) {
391 case GL_SHORT:
392 elementSize = size * sizeof(GLshort);
393 break;
394 case GL_INT:
395 elementSize = size * sizeof(GLint);
396 break;
397 case GL_FLOAT:
398 elementSize = size * sizeof(GLfloat);
399 break;
400 case GL_DOUBLE:
401 elementSize = size * sizeof(GLdouble);
402 break;
403 default:
404 _mesa_error( ctx, GL_INVALID_ENUM, "glTexCoordPointer(type)" );
405 return;
406 }
407
408 update_array(ctx, &ctx->Array.TexCoord[unit], _NEW_ARRAY_TEXCOORD(unit),
409 elementSize, size, type, stride, GL_FALSE, ptr);
410
411 if (ctx->Driver.TexCoordPointer)
412 ctx->Driver.TexCoordPointer( ctx, size, type, stride, ptr );
413 }
414
415
416 void GLAPIENTRY
417 _mesa_EdgeFlagPointer(GLsizei stride, const GLvoid *ptr)
418 {
419 GET_CURRENT_CONTEXT(ctx);
420 ASSERT_OUTSIDE_BEGIN_END_AND_FLUSH(ctx);
421
422 if (stride < 0) {
423 _mesa_error( ctx, GL_INVALID_VALUE, "glEdgeFlagPointer(stride)" );
424 return;
425 }
426
427 update_array(ctx, &ctx->Array.EdgeFlag, _NEW_ARRAY_EDGEFLAG,
428 sizeof(GLboolean), 1, GL_BOOLEAN, stride, GL_FALSE, ptr);
429
430 if (ctx->Driver.EdgeFlagPointer)
431 ctx->Driver.EdgeFlagPointer( ctx, stride, ptr );
432 }
433
434
435 #if FEATURE_NV_vertex_program
436 void GLAPIENTRY
437 _mesa_VertexAttribPointerNV(GLuint index, GLint size, GLenum type,
438 GLsizei stride, const GLvoid *ptr)
439 {
440 GLsizei elementSize;
441 GET_CURRENT_CONTEXT(ctx);
442 ASSERT_OUTSIDE_BEGIN_END(ctx);
443
444 if (index >= VERT_ATTRIB_MAX) {
445 _mesa_error(ctx, GL_INVALID_VALUE, "glVertexAttribPointerNV(index)");
446 return;
447 }
448
449 if (size < 1 || size > 4) {
450 _mesa_error(ctx, GL_INVALID_VALUE, "glVertexAttribPointerNV(size)");
451 return;
452 }
453
454 if (stride < 0) {
455 _mesa_error(ctx, GL_INVALID_VALUE, "glVertexAttribPointerNV(stride)");
456 return;
457 }
458
459 if (type == GL_UNSIGNED_BYTE && size != 4) {
460 _mesa_error(ctx, GL_INVALID_VALUE, "glVertexAttribPointerNV(size!=4)");
461 return;
462 }
463
464 /* check for valid 'type' and compute StrideB right away */
465 switch (type) {
466 case GL_UNSIGNED_BYTE:
467 elementSize = size * sizeof(GLubyte);
468 break;
469 case GL_SHORT:
470 elementSize = size * sizeof(GLshort);
471 break;
472 case GL_FLOAT:
473 elementSize = size * sizeof(GLfloat);
474 break;
475 case GL_DOUBLE:
476 elementSize = size * sizeof(GLdouble);
477 break;
478 default:
479 _mesa_error( ctx, GL_INVALID_ENUM, "glVertexAttribPointerNV(type)" );
480 return;
481 }
482
483 update_array(ctx, &ctx->Array.VertexAttrib[index], _NEW_ARRAY_ATTRIB(index),
484 elementSize, size, type, stride, GL_FALSE, ptr);
485
486 if (ctx->Driver.VertexAttribPointer)
487 ctx->Driver.VertexAttribPointer( ctx, index, size, type, stride, ptr );
488 }
489 #endif
490
491
492 #if FEATURE_ARB_vertex_program
493 void GLAPIENTRY
494 _mesa_VertexAttribPointerARB(GLuint index, GLint size, GLenum type,
495 GLboolean normalized,
496 GLsizei stride, const GLvoid *ptr)
497 {
498 GLsizei elementSize;
499 GET_CURRENT_CONTEXT(ctx);
500 ASSERT_OUTSIDE_BEGIN_END(ctx);
501
502 if (index >= ctx->Const.MaxVertexProgramAttribs) {
503 _mesa_error(ctx, GL_INVALID_VALUE, "glVertexAttribPointerARB(index)");
504 return;
505 }
506
507 if (size < 1 || size > 4) {
508 _mesa_error(ctx, GL_INVALID_VALUE, "glVertexAttribPointerARB(size)");
509 return;
510 }
511
512 if (stride < 0) {
513 _mesa_error(ctx, GL_INVALID_VALUE, "glVertexAttribPointerARB(stride)");
514 return;
515 }
516
517 if (type == GL_UNSIGNED_BYTE && size != 4) {
518 _mesa_error(ctx, GL_INVALID_VALUE, "glVertexAttribPointerARB(size!=4)");
519 return;
520 }
521
522 /* check for valid 'type' and compute StrideB right away */
523 /* NOTE: more types are supported here than in the NV extension */
524 switch (type) {
525 case GL_BYTE:
526 elementSize = size * sizeof(GLbyte);
527 break;
528 case GL_UNSIGNED_BYTE:
529 elementSize = size * sizeof(GLubyte);
530 break;
531 case GL_SHORT:
532 elementSize = size * sizeof(GLshort);
533 break;
534 case GL_UNSIGNED_SHORT:
535 elementSize = size * sizeof(GLushort);
536 break;
537 case GL_INT:
538 elementSize = size * sizeof(GLint);
539 break;
540 case GL_UNSIGNED_INT:
541 elementSize = size * sizeof(GLuint);
542 break;
543 case GL_FLOAT:
544 elementSize = size * sizeof(GLfloat);
545 break;
546 case GL_DOUBLE:
547 elementSize = size * sizeof(GLdouble);
548 break;
549 default:
550 _mesa_error( ctx, GL_INVALID_ENUM, "glVertexAttribPointerARB(type)" );
551 return;
552 }
553
554 update_array(ctx, &ctx->Array.VertexAttrib[index], _NEW_ARRAY_ATTRIB(index),
555 elementSize, size, type, stride, normalized, ptr);
556
557 /* XXX fix
558 if (ctx->Driver.VertexAttribPointer)
559 ctx->Driver.VertexAttribPointer( ctx, index, size, type, stride, ptr );
560 */
561 }
562 #endif
563
564
565 void GLAPIENTRY
566 _mesa_VertexPointerEXT(GLint size, GLenum type, GLsizei stride,
567 GLsizei count, const GLvoid *ptr)
568 {
569 (void) count;
570 _mesa_VertexPointer(size, type, stride, ptr);
571 }
572
573
574 void GLAPIENTRY
575 _mesa_NormalPointerEXT(GLenum type, GLsizei stride, GLsizei count,
576 const GLvoid *ptr)
577 {
578 (void) count;
579 _mesa_NormalPointer(type, stride, ptr);
580 }
581
582
583 void GLAPIENTRY
584 _mesa_ColorPointerEXT(GLint size, GLenum type, GLsizei stride, GLsizei count,
585 const GLvoid *ptr)
586 {
587 (void) count;
588 _mesa_ColorPointer(size, type, stride, ptr);
589 }
590
591
592 void GLAPIENTRY
593 _mesa_IndexPointerEXT(GLenum type, GLsizei stride, GLsizei count,
594 const GLvoid *ptr)
595 {
596 (void) count;
597 _mesa_IndexPointer(type, stride, ptr);
598 }
599
600
601 void GLAPIENTRY
602 _mesa_TexCoordPointerEXT(GLint size, GLenum type, GLsizei stride,
603 GLsizei count, const GLvoid *ptr)
604 {
605 (void) count;
606 _mesa_TexCoordPointer(size, type, stride, ptr);
607 }
608
609
610 void GLAPIENTRY
611 _mesa_EdgeFlagPointerEXT(GLsizei stride, GLsizei count, const GLboolean *ptr)
612 {
613 (void) count;
614 _mesa_EdgeFlagPointer(stride, ptr);
615 }
616
617
618 void GLAPIENTRY
619 _mesa_InterleavedArrays(GLenum format, GLsizei stride, const GLvoid *pointer)
620 {
621 GET_CURRENT_CONTEXT(ctx);
622 GLboolean tflag, cflag, nflag; /* enable/disable flags */
623 GLint tcomps, ccomps, vcomps; /* components per texcoord, color, vertex */
624 GLenum ctype = 0; /* color type */
625 GLint coffset = 0, noffset = 0, voffset;/* color, normal, vertex offsets */
626 const GLint toffset = 0; /* always zero */
627 GLint defstride; /* default stride */
628 GLint c, f;
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 if (tflag) {
760 _mesa_EnableClientState( GL_TEXTURE_COORD_ARRAY );
761 _mesa_TexCoordPointer( tcomps, GL_FLOAT, stride,
762 (GLubyte *) pointer + toffset );
763 }
764 else {
765 _mesa_DisableClientState( GL_TEXTURE_COORD_ARRAY );
766 }
767
768 /* Color */
769 if (cflag) {
770 _mesa_EnableClientState( GL_COLOR_ARRAY );
771 _mesa_ColorPointer( ccomps, ctype, stride,
772 (GLubyte *) pointer + coffset );
773 }
774 else {
775 _mesa_DisableClientState( GL_COLOR_ARRAY );
776 }
777
778
779 /* Normals */
780 if (nflag) {
781 _mesa_EnableClientState( GL_NORMAL_ARRAY );
782 _mesa_NormalPointer( GL_FLOAT, stride, (GLubyte *) pointer + noffset );
783 }
784 else {
785 _mesa_DisableClientState( GL_NORMAL_ARRAY );
786 }
787
788 /* Vertices */
789 _mesa_EnableClientState( GL_VERTEX_ARRAY );
790 _mesa_VertexPointer( vcomps, GL_FLOAT, stride,
791 (GLubyte *) pointer + voffset );
792 }
793
794
795 void GLAPIENTRY
796 _mesa_LockArraysEXT(GLint first, GLsizei count)
797 {
798 GET_CURRENT_CONTEXT(ctx);
799 ASSERT_OUTSIDE_BEGIN_END_AND_FLUSH(ctx);
800
801 if (MESA_VERBOSE & VERBOSE_API)
802 _mesa_debug(ctx, "glLockArrays %d %d\n", first, count);
803
804 if (first == 0 && count > 0 &&
805 count <= (GLint) ctx->Const.MaxArrayLockSize) {
806 ctx->Array.LockFirst = first;
807 ctx->Array.LockCount = count;
808 }
809 else {
810 ctx->Array.LockFirst = 0;
811 ctx->Array.LockCount = 0;
812 }
813
814 ctx->NewState |= _NEW_ARRAY;
815 ctx->Array.NewState |= _NEW_ARRAY_ALL;
816
817 if (ctx->Driver.LockArraysEXT)
818 ctx->Driver.LockArraysEXT( ctx, first, count );
819 }
820
821
822 void GLAPIENTRY
823 _mesa_UnlockArraysEXT( void )
824 {
825 GET_CURRENT_CONTEXT(ctx);
826 ASSERT_OUTSIDE_BEGIN_END_AND_FLUSH(ctx);
827
828 if (MESA_VERBOSE & VERBOSE_API)
829 _mesa_debug(ctx, "glUnlockArrays\n");
830
831 ctx->Array.LockFirst = 0;
832 ctx->Array.LockCount = 0;
833 ctx->NewState |= _NEW_ARRAY;
834 ctx->Array.NewState |= _NEW_ARRAY_ALL;
835
836 if (ctx->Driver.UnlockArraysEXT)
837 ctx->Driver.UnlockArraysEXT( ctx );
838 }
839
840
841 /* GL_EXT_multi_draw_arrays */
842 /* Somebody forgot to spec the first and count parameters as const! <sigh> */
843 void GLAPIENTRY
844 _mesa_MultiDrawArraysEXT( GLenum mode, GLint *first,
845 GLsizei *count, GLsizei primcount )
846 {
847 GET_CURRENT_CONTEXT(ctx);
848 GLint i;
849
850 ASSERT_OUTSIDE_BEGIN_END_AND_FLUSH(ctx);
851
852 for (i = 0; i < primcount; i++) {
853 if (count[i] > 0) {
854 (ctx->Exec->DrawArrays)(mode, first[i], count[i]);
855 }
856 }
857 }
858
859
860 /* GL_EXT_multi_draw_arrays */
861 void GLAPIENTRY
862 _mesa_MultiDrawElementsEXT( GLenum mode, const GLsizei *count, GLenum type,
863 const GLvoid **indices, GLsizei primcount )
864 {
865 GET_CURRENT_CONTEXT(ctx);
866 GLint i;
867
868 ASSERT_OUTSIDE_BEGIN_END_AND_FLUSH(ctx);
869
870 for (i = 0; i < primcount; i++) {
871 if (count[i] > 0) {
872 (ctx->Exec->DrawElements)(mode, count[i], type, indices[i]);
873 }
874 }
875 }
876
877
878 /* GL_IBM_multimode_draw_arrays */
879 void GLAPIENTRY
880 _mesa_MultiModeDrawArraysIBM( const GLenum * mode, const GLint * first,
881 const GLsizei * count,
882 GLsizei primcount, GLint modestride )
883 {
884 GET_CURRENT_CONTEXT(ctx);
885 GLint i;
886
887 ASSERT_OUTSIDE_BEGIN_END_AND_FLUSH(ctx);
888
889 for ( i = 0 ; i < primcount ; i++ ) {
890 if ( count[i] > 0 ) {
891 GLenum m = *((GLenum *) ((GLubyte *) mode + i * modestride));
892 (ctx->Exec->DrawArrays)( m, first[i], count[i] );
893 }
894 }
895 }
896
897
898 /* GL_IBM_multimode_draw_arrays */
899 void GLAPIENTRY
900 _mesa_MultiModeDrawElementsIBM( const GLenum * mode, const GLsizei * count,
901 GLenum type, const GLvoid * const * indices,
902 GLsizei primcount, GLint modestride )
903 {
904 GET_CURRENT_CONTEXT(ctx);
905 GLint i;
906
907 ASSERT_OUTSIDE_BEGIN_END_AND_FLUSH(ctx);
908
909 /* XXX not sure about ARB_vertex_buffer_object handling here */
910
911 for ( i = 0 ; i < primcount ; i++ ) {
912 if ( count[i] > 0 ) {
913 GLenum m = *((GLenum *) ((GLubyte *) mode + i * modestride));
914 (ctx->Exec->DrawElements)( m, count[i], type, indices[i] );
915 }
916 }
917 }
918
919
920 /**********************************************************************/
921 /***** Initialization *****/
922 /**********************************************************************/
923
924 void
925 _mesa_init_varray( GLcontext * ctx )
926 {
927 GLuint i;
928
929 /* Vertex arrays */
930 ctx->Array.Vertex.Size = 4;
931 ctx->Array.Vertex.Type = GL_FLOAT;
932 ctx->Array.Vertex.Stride = 0;
933 ctx->Array.Vertex.StrideB = 0;
934 ctx->Array.Vertex.Ptr = NULL;
935 ctx->Array.Vertex.Enabled = GL_FALSE;
936 ctx->Array.Vertex.Flags = CA_CLIENT_DATA;
937 ctx->Array.Normal.Type = GL_FLOAT;
938 ctx->Array.Normal.Stride = 0;
939 ctx->Array.Normal.StrideB = 0;
940 ctx->Array.Normal.Ptr = NULL;
941 ctx->Array.Normal.Enabled = GL_FALSE;
942 ctx->Array.Normal.Flags = CA_CLIENT_DATA;
943 ctx->Array.Color.Size = 4;
944 ctx->Array.Color.Type = GL_FLOAT;
945 ctx->Array.Color.Stride = 0;
946 ctx->Array.Color.StrideB = 0;
947 ctx->Array.Color.Ptr = NULL;
948 ctx->Array.Color.Enabled = GL_FALSE;
949 ctx->Array.Color.Flags = CA_CLIENT_DATA;
950 ctx->Array.SecondaryColor.Size = 4;
951 ctx->Array.SecondaryColor.Type = GL_FLOAT;
952 ctx->Array.SecondaryColor.Stride = 0;
953 ctx->Array.SecondaryColor.StrideB = 0;
954 ctx->Array.SecondaryColor.Ptr = NULL;
955 ctx->Array.SecondaryColor.Enabled = GL_FALSE;
956 ctx->Array.SecondaryColor.Flags = CA_CLIENT_DATA;
957 ctx->Array.FogCoord.Size = 1;
958 ctx->Array.FogCoord.Type = GL_FLOAT;
959 ctx->Array.FogCoord.Stride = 0;
960 ctx->Array.FogCoord.StrideB = 0;
961 ctx->Array.FogCoord.Ptr = NULL;
962 ctx->Array.FogCoord.Enabled = GL_FALSE;
963 ctx->Array.FogCoord.Flags = CA_CLIENT_DATA;
964 ctx->Array.Index.Type = GL_FLOAT;
965 ctx->Array.Index.Stride = 0;
966 ctx->Array.Index.StrideB = 0;
967 ctx->Array.Index.Ptr = NULL;
968 ctx->Array.Index.Enabled = GL_FALSE;
969 ctx->Array.Index.Flags = CA_CLIENT_DATA;
970 for (i = 0; i < MAX_TEXTURE_UNITS; i++) {
971 ctx->Array.TexCoord[i].Size = 4;
972 ctx->Array.TexCoord[i].Type = GL_FLOAT;
973 ctx->Array.TexCoord[i].Stride = 0;
974 ctx->Array.TexCoord[i].StrideB = 0;
975 ctx->Array.TexCoord[i].Ptr = NULL;
976 ctx->Array.TexCoord[i].Enabled = GL_FALSE;
977 ctx->Array.TexCoord[i].Flags = CA_CLIENT_DATA;
978 }
979 ctx->Array.EdgeFlag.Stride = 0;
980 ctx->Array.EdgeFlag.StrideB = 0;
981 ctx->Array.EdgeFlag.Ptr = NULL;
982 ctx->Array.EdgeFlag.Enabled = GL_FALSE;
983 ctx->Array.EdgeFlag.Flags = CA_CLIENT_DATA;
984 ctx->Array.ActiveTexture = 0; /* GL_ARB_multitexture */
985 for (i = 0; i < VERT_ATTRIB_MAX; i++) {
986 ctx->Array.VertexAttrib[i].Size = 4;
987 ctx->Array.VertexAttrib[i].Type = GL_FLOAT;
988 ctx->Array.VertexAttrib[i].Stride = 0;
989 ctx->Array.VertexAttrib[i].StrideB = 0;
990 ctx->Array.VertexAttrib[i].Ptr = NULL;
991 ctx->Array.VertexAttrib[i].Enabled = GL_FALSE;
992 ctx->Array.VertexAttrib[i].Flags = CA_CLIENT_DATA;
993 }
994 }