5194523c2457143ce29b5655b39fb2798dd7a5d2
[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 #if FEATURE_NV_vertex_program
467 void GLAPIENTRY
468 _mesa_VertexAttribPointerNV(GLuint index, GLint size, GLenum type,
469 GLsizei stride, const GLvoid *ptr)
470 {
471 GLboolean normalized = GL_FALSE;
472 GLsizei elementSize;
473 GET_CURRENT_CONTEXT(ctx);
474 ASSERT_OUTSIDE_BEGIN_END(ctx);
475
476 if (index >= MAX_VERTEX_PROGRAM_ATTRIBS) {
477 _mesa_error(ctx, GL_INVALID_VALUE, "glVertexAttribPointerNV(index)");
478 return;
479 }
480
481 if (size < 1 || size > 4) {
482 _mesa_error(ctx, GL_INVALID_VALUE, "glVertexAttribPointerNV(size)");
483 return;
484 }
485
486 if (stride < 0) {
487 _mesa_error(ctx, GL_INVALID_VALUE, "glVertexAttribPointerNV(stride)");
488 return;
489 }
490
491 if (type == GL_UNSIGNED_BYTE && size != 4) {
492 _mesa_error(ctx, GL_INVALID_VALUE, "glVertexAttribPointerNV(size!=4)");
493 return;
494 }
495
496 /* check for valid 'type' and compute StrideB right away */
497 switch (type) {
498 case GL_UNSIGNED_BYTE:
499 normalized = GL_TRUE;
500 elementSize = size * sizeof(GLubyte);
501 break;
502 case GL_SHORT:
503 elementSize = size * sizeof(GLshort);
504 break;
505 case GL_FLOAT:
506 elementSize = size * sizeof(GLfloat);
507 break;
508 case GL_DOUBLE:
509 elementSize = size * sizeof(GLdouble);
510 break;
511 default:
512 _mesa_error( ctx, GL_INVALID_ENUM, "glVertexAttribPointerNV(type)" );
513 return;
514 }
515
516 update_array(ctx, &ctx->Array.ArrayObj->VertexAttrib[index],
517 _NEW_ARRAY_ATTRIB(index),
518 elementSize, size, type, stride, normalized, ptr);
519
520 if (ctx->Driver.VertexAttribPointer)
521 ctx->Driver.VertexAttribPointer( ctx, index, size, type, stride, ptr );
522 }
523 #endif
524
525
526 #if FEATURE_ARB_vertex_program
527 void GLAPIENTRY
528 _mesa_VertexAttribPointerARB(GLuint index, GLint size, GLenum type,
529 GLboolean normalized,
530 GLsizei stride, const GLvoid *ptr)
531 {
532 GLsizei elementSize;
533 GET_CURRENT_CONTEXT(ctx);
534 ASSERT_OUTSIDE_BEGIN_END(ctx);
535
536 if (index >= ctx->Const.VertexProgram.MaxAttribs) {
537 _mesa_error(ctx, GL_INVALID_VALUE, "glVertexAttribPointerARB(index)");
538 return;
539 }
540
541 if (size < 1 || size > 4) {
542 _mesa_error(ctx, GL_INVALID_VALUE, "glVertexAttribPointerARB(size)");
543 return;
544 }
545
546 if (stride < 0) {
547 _mesa_error(ctx, GL_INVALID_VALUE, "glVertexAttribPointerARB(stride)");
548 return;
549 }
550
551 /* check for valid 'type' and compute StrideB right away */
552 /* NOTE: more types are supported here than in the NV extension */
553 switch (type) {
554 case GL_BYTE:
555 elementSize = size * sizeof(GLbyte);
556 break;
557 case GL_UNSIGNED_BYTE:
558 elementSize = size * sizeof(GLubyte);
559 break;
560 case GL_SHORT:
561 elementSize = size * sizeof(GLshort);
562 break;
563 case GL_UNSIGNED_SHORT:
564 elementSize = size * sizeof(GLushort);
565 break;
566 case GL_INT:
567 elementSize = size * sizeof(GLint);
568 break;
569 case GL_UNSIGNED_INT:
570 elementSize = size * sizeof(GLuint);
571 break;
572 case GL_FLOAT:
573 elementSize = size * sizeof(GLfloat);
574 break;
575 case GL_DOUBLE:
576 elementSize = size * sizeof(GLdouble);
577 break;
578 default:
579 _mesa_error( ctx, GL_INVALID_ENUM, "glVertexAttribPointerARB(type)" );
580 return;
581 }
582
583 update_array(ctx, &ctx->Array.ArrayObj->VertexAttrib[index],
584 _NEW_ARRAY_ATTRIB(index),
585 elementSize, size, type, stride, normalized, ptr);
586
587 if (ctx->Driver.VertexAttribPointer)
588 ctx->Driver.VertexAttribPointer(ctx, index, size, type, stride, ptr);
589 }
590 #endif
591
592
593 void GLAPIENTRY
594 _mesa_VertexPointerEXT(GLint size, GLenum type, GLsizei stride,
595 GLsizei count, const GLvoid *ptr)
596 {
597 (void) count;
598 _mesa_VertexPointer(size, type, stride, ptr);
599 }
600
601
602 void GLAPIENTRY
603 _mesa_NormalPointerEXT(GLenum type, GLsizei stride, GLsizei count,
604 const GLvoid *ptr)
605 {
606 (void) count;
607 _mesa_NormalPointer(type, stride, ptr);
608 }
609
610
611 void GLAPIENTRY
612 _mesa_ColorPointerEXT(GLint size, GLenum type, GLsizei stride, GLsizei count,
613 const GLvoid *ptr)
614 {
615 (void) count;
616 _mesa_ColorPointer(size, type, stride, ptr);
617 }
618
619
620 void GLAPIENTRY
621 _mesa_IndexPointerEXT(GLenum type, GLsizei stride, GLsizei count,
622 const GLvoid *ptr)
623 {
624 (void) count;
625 _mesa_IndexPointer(type, stride, ptr);
626 }
627
628
629 void GLAPIENTRY
630 _mesa_TexCoordPointerEXT(GLint size, GLenum type, GLsizei stride,
631 GLsizei count, const GLvoid *ptr)
632 {
633 (void) count;
634 _mesa_TexCoordPointer(size, type, stride, ptr);
635 }
636
637
638 void GLAPIENTRY
639 _mesa_EdgeFlagPointerEXT(GLsizei stride, GLsizei count, const GLboolean *ptr)
640 {
641 (void) count;
642 _mesa_EdgeFlagPointer(stride, ptr);
643 }
644
645
646 void GLAPIENTRY
647 _mesa_InterleavedArrays(GLenum format, GLsizei stride, const GLvoid *pointer)
648 {
649 GET_CURRENT_CONTEXT(ctx);
650 GLboolean tflag, cflag, nflag; /* enable/disable flags */
651 GLint tcomps, ccomps, vcomps; /* components per texcoord, color, vertex */
652 GLenum ctype = 0; /* color type */
653 GLint coffset = 0, noffset = 0, voffset;/* color, normal, vertex offsets */
654 const GLint toffset = 0; /* always zero */
655 GLint defstride; /* default stride */
656 GLint c, f;
657
658 ASSERT_OUTSIDE_BEGIN_END_AND_FLUSH(ctx);
659
660 f = sizeof(GLfloat);
661 c = f * ((4 * sizeof(GLubyte) + (f - 1)) / f);
662
663 if (stride < 0) {
664 _mesa_error( ctx, GL_INVALID_VALUE, "glInterleavedArrays(stride)" );
665 return;
666 }
667
668 switch (format) {
669 case GL_V2F:
670 tflag = GL_FALSE; cflag = GL_FALSE; nflag = GL_FALSE;
671 tcomps = 0; ccomps = 0; vcomps = 2;
672 voffset = 0;
673 defstride = 2*f;
674 break;
675 case GL_V3F:
676 tflag = GL_FALSE; cflag = GL_FALSE; nflag = GL_FALSE;
677 tcomps = 0; ccomps = 0; vcomps = 3;
678 voffset = 0;
679 defstride = 3*f;
680 break;
681 case GL_C4UB_V2F:
682 tflag = GL_FALSE; cflag = GL_TRUE; nflag = GL_FALSE;
683 tcomps = 0; ccomps = 4; vcomps = 2;
684 ctype = GL_UNSIGNED_BYTE;
685 coffset = 0;
686 voffset = c;
687 defstride = c + 2*f;
688 break;
689 case GL_C4UB_V3F:
690 tflag = GL_FALSE; cflag = GL_TRUE; nflag = GL_FALSE;
691 tcomps = 0; ccomps = 4; vcomps = 3;
692 ctype = GL_UNSIGNED_BYTE;
693 coffset = 0;
694 voffset = c;
695 defstride = c + 3*f;
696 break;
697 case GL_C3F_V3F:
698 tflag = GL_FALSE; cflag = GL_TRUE; nflag = GL_FALSE;
699 tcomps = 0; ccomps = 3; vcomps = 3;
700 ctype = GL_FLOAT;
701 coffset = 0;
702 voffset = 3*f;
703 defstride = 6*f;
704 break;
705 case GL_N3F_V3F:
706 tflag = GL_FALSE; cflag = GL_FALSE; nflag = GL_TRUE;
707 tcomps = 0; ccomps = 0; vcomps = 3;
708 noffset = 0;
709 voffset = 3*f;
710 defstride = 6*f;
711 break;
712 case GL_C4F_N3F_V3F:
713 tflag = GL_FALSE; cflag = GL_TRUE; nflag = GL_TRUE;
714 tcomps = 0; ccomps = 4; vcomps = 3;
715 ctype = GL_FLOAT;
716 coffset = 0;
717 noffset = 4*f;
718 voffset = 7*f;
719 defstride = 10*f;
720 break;
721 case GL_T2F_V3F:
722 tflag = GL_TRUE; cflag = GL_FALSE; nflag = GL_FALSE;
723 tcomps = 2; ccomps = 0; vcomps = 3;
724 voffset = 2*f;
725 defstride = 5*f;
726 break;
727 case GL_T4F_V4F:
728 tflag = GL_TRUE; cflag = GL_FALSE; nflag = GL_FALSE;
729 tcomps = 4; ccomps = 0; vcomps = 4;
730 voffset = 4*f;
731 defstride = 8*f;
732 break;
733 case GL_T2F_C4UB_V3F:
734 tflag = GL_TRUE; cflag = GL_TRUE; nflag = GL_FALSE;
735 tcomps = 2; ccomps = 4; vcomps = 3;
736 ctype = GL_UNSIGNED_BYTE;
737 coffset = 2*f;
738 voffset = c+2*f;
739 defstride = c+5*f;
740 break;
741 case GL_T2F_C3F_V3F:
742 tflag = GL_TRUE; cflag = GL_TRUE; nflag = GL_FALSE;
743 tcomps = 2; ccomps = 3; vcomps = 3;
744 ctype = GL_FLOAT;
745 coffset = 2*f;
746 voffset = 5*f;
747 defstride = 8*f;
748 break;
749 case GL_T2F_N3F_V3F:
750 tflag = GL_TRUE; cflag = GL_FALSE; nflag = GL_TRUE;
751 tcomps = 2; ccomps = 0; vcomps = 3;
752 noffset = 2*f;
753 voffset = 5*f;
754 defstride = 8*f;
755 break;
756 case GL_T2F_C4F_N3F_V3F:
757 tflag = GL_TRUE; cflag = GL_TRUE; nflag = GL_TRUE;
758 tcomps = 2; ccomps = 4; vcomps = 3;
759 ctype = GL_FLOAT;
760 coffset = 2*f;
761 noffset = 6*f;
762 voffset = 9*f;
763 defstride = 12*f;
764 break;
765 case GL_T4F_C4F_N3F_V4F:
766 tflag = GL_TRUE; cflag = GL_TRUE; nflag = GL_TRUE;
767 tcomps = 4; ccomps = 4; vcomps = 4;
768 ctype = GL_FLOAT;
769 coffset = 4*f;
770 noffset = 8*f;
771 voffset = 11*f;
772 defstride = 15*f;
773 break;
774 default:
775 _mesa_error( ctx, GL_INVALID_ENUM, "glInterleavedArrays(format)" );
776 return;
777 }
778
779 if (stride==0) {
780 stride = defstride;
781 }
782
783 _mesa_DisableClientState( GL_EDGE_FLAG_ARRAY );
784 _mesa_DisableClientState( GL_INDEX_ARRAY );
785 /* XXX also disable secondary color and generic arrays? */
786
787 /* Texcoords */
788 if (tflag) {
789 _mesa_EnableClientState( GL_TEXTURE_COORD_ARRAY );
790 _mesa_TexCoordPointer( tcomps, GL_FLOAT, stride,
791 (GLubyte *) pointer + toffset );
792 }
793 else {
794 _mesa_DisableClientState( GL_TEXTURE_COORD_ARRAY );
795 }
796
797 /* Color */
798 if (cflag) {
799 _mesa_EnableClientState( GL_COLOR_ARRAY );
800 _mesa_ColorPointer( ccomps, ctype, stride,
801 (GLubyte *) pointer + coffset );
802 }
803 else {
804 _mesa_DisableClientState( GL_COLOR_ARRAY );
805 }
806
807
808 /* Normals */
809 if (nflag) {
810 _mesa_EnableClientState( GL_NORMAL_ARRAY );
811 _mesa_NormalPointer( GL_FLOAT, stride, (GLubyte *) pointer + noffset );
812 }
813 else {
814 _mesa_DisableClientState( GL_NORMAL_ARRAY );
815 }
816
817 /* Vertices */
818 _mesa_EnableClientState( GL_VERTEX_ARRAY );
819 _mesa_VertexPointer( vcomps, GL_FLOAT, stride,
820 (GLubyte *) pointer + voffset );
821 }
822
823
824 void GLAPIENTRY
825 _mesa_LockArraysEXT(GLint first, GLsizei count)
826 {
827 GET_CURRENT_CONTEXT(ctx);
828 ASSERT_OUTSIDE_BEGIN_END_AND_FLUSH(ctx);
829
830 if (MESA_VERBOSE & VERBOSE_API)
831 _mesa_debug(ctx, "glLockArrays %d %d\n", first, count);
832
833 if (first < 0) {
834 _mesa_error( ctx, GL_INVALID_VALUE, "glLockArraysEXT(first)" );
835 return;
836 }
837 if (count <= 0) {
838 _mesa_error( ctx, GL_INVALID_VALUE, "glLockArraysEXT(count)" );
839 return;
840 }
841 if (ctx->Array.LockCount != 0) {
842 _mesa_error( ctx, GL_INVALID_OPERATION, "glLockArraysEXT(reentry)" );
843 return;
844 }
845
846 ctx->Array.LockFirst = first;
847 ctx->Array.LockCount = count;
848
849 ctx->NewState |= _NEW_ARRAY;
850 ctx->Array.NewState |= _NEW_ARRAY_ALL;
851
852 if (ctx->Driver.LockArraysEXT)
853 ctx->Driver.LockArraysEXT( ctx, first, count );
854 }
855
856
857 void GLAPIENTRY
858 _mesa_UnlockArraysEXT( void )
859 {
860 GET_CURRENT_CONTEXT(ctx);
861 ASSERT_OUTSIDE_BEGIN_END_AND_FLUSH(ctx);
862
863 if (MESA_VERBOSE & VERBOSE_API)
864 _mesa_debug(ctx, "glUnlockArrays\n");
865
866 if (ctx->Array.LockCount == 0) {
867 _mesa_error( ctx, GL_INVALID_OPERATION, "glUnlockArraysEXT(reexit)" );
868 return;
869 }
870
871 ctx->Array.LockFirst = 0;
872 ctx->Array.LockCount = 0;
873 ctx->NewState |= _NEW_ARRAY;
874 ctx->Array.NewState |= _NEW_ARRAY_ALL;
875
876 if (ctx->Driver.UnlockArraysEXT)
877 ctx->Driver.UnlockArraysEXT( ctx );
878 }
879
880
881 /* GL_EXT_multi_draw_arrays */
882 /* Somebody forgot to spec the first and count parameters as const! <sigh> */
883 void GLAPIENTRY
884 _mesa_MultiDrawArraysEXT( GLenum mode, GLint *first,
885 GLsizei *count, GLsizei primcount )
886 {
887 GET_CURRENT_CONTEXT(ctx);
888 GLint i;
889
890 ASSERT_OUTSIDE_BEGIN_END_AND_FLUSH(ctx);
891
892 for (i = 0; i < primcount; i++) {
893 if (count[i] > 0) {
894 CALL_DrawArrays(ctx->Exec, (mode, first[i], count[i]));
895 }
896 }
897 }
898
899
900 /* GL_EXT_multi_draw_arrays */
901 void GLAPIENTRY
902 _mesa_MultiDrawElementsEXT( GLenum mode, const GLsizei *count, GLenum type,
903 const GLvoid **indices, GLsizei primcount )
904 {
905 GET_CURRENT_CONTEXT(ctx);
906 GLint i;
907
908 ASSERT_OUTSIDE_BEGIN_END_AND_FLUSH(ctx);
909
910 for (i = 0; i < primcount; i++) {
911 if (count[i] > 0) {
912 CALL_DrawElements(ctx->Exec, (mode, count[i], type, indices[i]));
913 }
914 }
915 }
916
917
918 /* GL_IBM_multimode_draw_arrays */
919 void GLAPIENTRY
920 _mesa_MultiModeDrawArraysIBM( const GLenum * mode, const GLint * first,
921 const GLsizei * count,
922 GLsizei primcount, GLint modestride )
923 {
924 GET_CURRENT_CONTEXT(ctx);
925 GLint i;
926
927 ASSERT_OUTSIDE_BEGIN_END_AND_FLUSH(ctx);
928
929 for ( i = 0 ; i < primcount ; i++ ) {
930 if ( count[i] > 0 ) {
931 GLenum m = *((GLenum *) ((GLubyte *) mode + i * modestride));
932 CALL_DrawArrays(ctx->Exec, ( m, first[i], count[i] ));
933 }
934 }
935 }
936
937
938 /* GL_IBM_multimode_draw_arrays */
939 void GLAPIENTRY
940 _mesa_MultiModeDrawElementsIBM( const GLenum * mode, const GLsizei * count,
941 GLenum type, const GLvoid * const * indices,
942 GLsizei primcount, GLint modestride )
943 {
944 GET_CURRENT_CONTEXT(ctx);
945 GLint i;
946
947 ASSERT_OUTSIDE_BEGIN_END_AND_FLUSH(ctx);
948
949 /* XXX not sure about ARB_vertex_buffer_object handling here */
950
951 for ( i = 0 ; i < primcount ; i++ ) {
952 if ( count[i] > 0 ) {
953 GLenum m = *((GLenum *) ((GLubyte *) mode + i * modestride));
954 CALL_DrawElements(ctx->Exec, ( m, count[i], type, indices[i] ));
955 }
956 }
957 }
958
959
960 /**
961 * Initialize vertex array state for given context.
962 */
963 void
964 _mesa_init_varray(GLcontext *ctx)
965 {
966 ctx->Array.DefaultArrayObj = _mesa_new_array_object(ctx, 0);
967 ctx->Array.ArrayObj = ctx->Array.DefaultArrayObj;
968
969 ctx->Array.ActiveTexture = 0; /* GL_ARB_multitexture */
970 }