various pipeline bugs
[mesa.git] / src / mesa / main / varray.c
1 /* $Id: varray.c,v 1.2 1999/08/26 14:50:49 keithw Exp $ */
2
3 /*
4 * Mesa 3-D graphics library
5 * Version: 3.1
6 *
7 * Copyright (C) 1999 Brian Paul All Rights Reserved.
8 *
9 * Permission is hereby granted, free of charge, to any person obtaining a
10 * copy of this software and associated documentation files (the "Software"),
11 * to deal in the Software without restriction, including without limitation
12 * the rights to use, copy, modify, merge, publish, distribute, sublicense,
13 * and/or sell copies of the Software, and to permit persons to whom the
14 * Software is furnished to do so, subject to the following conditions:
15 *
16 * The above copyright notice and this permission notice shall be included
17 * in all copies or substantial portions of the Software.
18 *
19 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
20 * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
21 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
22 * BRIAN PAUL BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN
23 * AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
24 * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
25 */
26
27 #ifdef PC_HEADER
28 #include "all.h"
29 #else
30 #include <stdlib.h>
31 #include <stdio.h>
32 #include <string.h>
33 #include "context.h"
34 #include "api.h"
35 #include "cva.h"
36 #include "enable.h"
37 #include "enums.h"
38 #include "dlist.h"
39 #include "light.h"
40 #include "macros.h"
41 #include "mmath.h"
42 #include "pipeline.h"
43 #include "texstate.h"
44 #include "translate.h"
45 #include "types.h"
46 #include "varray.h"
47 #include "vb.h"
48 #include "vbfill.h"
49 #include "vbrender.h"
50 #include "vbindirect.h"
51 #include "vbxform.h"
52 #include "xform.h"
53 #ifdef XFree86Server
54 #include "GL/xf86glx.h"
55 #endif
56 #endif
57
58
59 void GLAPIENTRY glVertexPointer(CTX_ARG GLint size, GLenum type, GLsizei stride,
60 const GLvoid *ptr )
61 {
62 GLcontext *ctx;
63 GET_CONTEXT;
64 CHECK_CONTEXT;
65 ctx = CC;
66
67 if (size<2 || size>4) {
68 gl_error( ctx, GL_INVALID_VALUE, "glVertexPointer(size)" );
69 return;
70 }
71 if (stride<0) {
72 gl_error( ctx, GL_INVALID_VALUE, "glVertexPointer(stride)" );
73 return;
74 }
75
76 if (MESA_VERBOSE&(VERBOSE_VARRAY|VERBOSE_API))
77 fprintf(stderr, "glVertexPointer( sz %d type %s stride %d )\n", size,
78 gl_lookup_enum_by_nr( type ),
79 stride);
80
81 ctx->Array.Vertex.StrideB = stride;
82 if (!stride) {
83 switch (type) {
84 case GL_SHORT:
85 ctx->Array.Vertex.StrideB = size*sizeof(GLshort);
86 break;
87 case GL_INT:
88 ctx->Array.Vertex.StrideB = size*sizeof(GLint);
89 break;
90 case GL_FLOAT:
91 ctx->Array.Vertex.StrideB = size*sizeof(GLfloat);
92 break;
93 case GL_DOUBLE:
94 ctx->Array.Vertex.StrideB = size*sizeof(GLdouble);
95 break;
96 default:
97 gl_error( ctx, GL_INVALID_ENUM, "glVertexPointer(type)" );
98 return;
99 }
100 }
101 ctx->Array.Vertex.Size = size;
102 ctx->Array.Vertex.Type = type;
103 ctx->Array.Vertex.Stride = stride;
104 ctx->Array.Vertex.Ptr = (void *) ptr;
105 ctx->Array.VertexFunc = gl_trans_4f_tab[size][TYPE_IDX(type)];
106 ctx->Array.VertexEltFunc = gl_trans_elt_4f_tab[size][TYPE_IDX(type)];
107 ctx->Array.NewArrayState |= VERT_OBJ_ANY;
108 ctx->NewState |= NEW_CLIENT_STATE;
109 }
110
111
112
113
114 void GLAPIENTRY glNormalPointer(CTX_ARG GLenum type, GLsizei stride,
115 const GLvoid *ptr )
116 {
117 GLcontext *ctx;
118 GET_CONTEXT;
119 CHECK_CONTEXT;
120 ctx = CC;
121
122 if (stride<0) {
123 gl_error( ctx, GL_INVALID_VALUE, "glNormalPointer(stride)" );
124 return;
125 }
126
127 if (MESA_VERBOSE&(VERBOSE_VARRAY|VERBOSE_API))
128 fprintf(stderr, "glNormalPointer( type %s stride %d )\n",
129 gl_lookup_enum_by_nr( type ),
130 stride);
131
132 ctx->Array.Normal.StrideB = stride;
133 if (!stride) {
134 switch (type) {
135 case GL_BYTE:
136 ctx->Array.Normal.StrideB = 3*sizeof(GLbyte);
137 break;
138 case GL_SHORT:
139 ctx->Array.Normal.StrideB = 3*sizeof(GLshort);
140 break;
141 case GL_INT:
142 ctx->Array.Normal.StrideB = 3*sizeof(GLint);
143 break;
144 case GL_FLOAT:
145 ctx->Array.Normal.StrideB = 3*sizeof(GLfloat);
146 break;
147 case GL_DOUBLE:
148 ctx->Array.Normal.StrideB = 3*sizeof(GLdouble);
149 break;
150 default:
151 gl_error( ctx, GL_INVALID_ENUM, "glNormalPointer(type)" );
152 return;
153 }
154 }
155 ctx->Array.Normal.Type = type;
156 ctx->Array.Normal.Stride = stride;
157 ctx->Array.Normal.Ptr = (void *) ptr;
158 ctx->Array.NormalFunc = gl_trans_3f_tab[TYPE_IDX(type)];
159 ctx->Array.NormalEltFunc = gl_trans_elt_3f_tab[TYPE_IDX(type)];
160 ctx->Array.NewArrayState |= VERT_NORM;
161 ctx->NewState |= NEW_CLIENT_STATE;
162 }
163
164
165
166 void GLAPIENTRY glColorPointer(CTX_ARG GLint size, GLenum type, GLsizei stride,
167 const GLvoid *ptr )
168 {
169 GLcontext *ctx;
170 GET_CONTEXT;
171 CHECK_CONTEXT;
172 ctx = CC;
173 if (size<3 || size>4) {
174 gl_error( ctx, GL_INVALID_VALUE, "glColorPointer(size)" );
175 return;
176 }
177 if (stride<0) {
178 gl_error( ctx, GL_INVALID_VALUE, "glColorPointer(stride)" );
179 return;
180 }
181
182 if (MESA_VERBOSE&(VERBOSE_VARRAY|VERBOSE_API))
183 fprintf(stderr, "glColorPointer( sz %d type %s stride %d )\n", size,
184 gl_lookup_enum_by_nr( type ),
185 stride);
186
187 ctx->Array.Color.StrideB = stride;
188 if (!stride) {
189 switch (type) {
190 case GL_BYTE:
191 ctx->Array.Color.StrideB = size*sizeof(GLbyte);
192 break;
193 case GL_UNSIGNED_BYTE:
194 ctx->Array.Color.StrideB = size*sizeof(GLubyte);
195 break;
196 case GL_SHORT:
197 ctx->Array.Color.StrideB = size*sizeof(GLshort);
198 break;
199 case GL_UNSIGNED_SHORT:
200 ctx->Array.Color.StrideB = size*sizeof(GLushort);
201 break;
202 case GL_INT:
203 ctx->Array.Color.StrideB = size*sizeof(GLint);
204 break;
205 case GL_UNSIGNED_INT:
206 ctx->Array.Color.StrideB = size*sizeof(GLuint);
207 break;
208 case GL_FLOAT:
209 ctx->Array.Color.StrideB = size*sizeof(GLfloat);
210 break;
211 case GL_DOUBLE:
212 ctx->Array.Color.StrideB = size*sizeof(GLdouble);
213 break;
214 default:
215 gl_error( ctx, GL_INVALID_ENUM, "glColorPointer(type)" );
216 return;
217 }
218 }
219 ctx->Array.Color.Size = size;
220 ctx->Array.Color.Type = type;
221 ctx->Array.Color.Stride = stride;
222 ctx->Array.Color.Ptr = (void *) ptr;
223 ctx->Array.ColorFunc = gl_trans_4ub_tab[size][TYPE_IDX(type)];
224 ctx->Array.ColorEltFunc = gl_trans_elt_4ub_tab[size][TYPE_IDX(type)];
225 ctx->Array.NewArrayState |= VERT_RGBA;
226 ctx->NewState |= NEW_CLIENT_STATE;
227 }
228
229
230
231 void GLAPIENTRY glIndexPointer(CTX_ARG GLenum type, GLsizei stride,
232 const GLvoid *ptr )
233 {
234 GLcontext *ctx;
235 GET_CONTEXT;
236 CHECK_CONTEXT;
237 ctx = CC;
238
239 if (stride<0) {
240 gl_error( ctx, GL_INVALID_VALUE, "glIndexPointer(stride)" );
241 return;
242 }
243
244 ctx->Array.Index.StrideB = stride;
245 if (!stride) {
246 switch (type) {
247 case GL_UNSIGNED_BYTE:
248 ctx->Array.Index.StrideB = sizeof(GLubyte);
249 break;
250 case GL_SHORT:
251 ctx->Array.Index.StrideB = sizeof(GLshort);
252 break;
253 case GL_INT:
254 ctx->Array.Index.StrideB = sizeof(GLint);
255 break;
256 case GL_FLOAT:
257 ctx->Array.Index.StrideB = sizeof(GLfloat);
258 break;
259 case GL_DOUBLE:
260 ctx->Array.Index.StrideB = sizeof(GLdouble);
261 break;
262 default:
263 gl_error( ctx, GL_INVALID_ENUM, "glIndexPointer(type)" );
264 return;
265 }
266 }
267 ctx->Array.Index.Type = type;
268 ctx->Array.Index.Stride = stride;
269 ctx->Array.Index.Ptr = (void *) ptr;
270 ctx->Array.IndexFunc = gl_trans_1ui_tab[TYPE_IDX(type)];
271 ctx->Array.IndexEltFunc = gl_trans_elt_1ui_tab[TYPE_IDX(type)];
272 ctx->Array.NewArrayState |= VERT_INDEX;
273 ctx->NewState |= NEW_CLIENT_STATE;
274 }
275
276
277
278 void GLAPIENTRY glTexCoordPointer(CTX_ARG GLint size, GLenum type,
279 GLsizei stride, const GLvoid *ptr )
280 {
281 GLuint texUnit;
282
283 GLcontext *ctx;
284 GET_CONTEXT;
285 CHECK_CONTEXT;
286 ctx = CC;
287
288 texUnit = ctx->TexCoordUnit;
289
290 if (size<1 || size>4) {
291 gl_error( ctx, GL_INVALID_VALUE, "glTexCoordPointer(size)" );
292 return;
293 }
294 if (stride<0) {
295 gl_error( ctx, GL_INVALID_VALUE, "glTexCoordPointer(stride)" );
296 return;
297 }
298
299 if (MESA_VERBOSE&(VERBOSE_VARRAY|VERBOSE_API))
300 fprintf(stderr, "glTexCoordPointer( unit %u sz %d type %s stride %d )\n",
301 texUnit,
302 size,
303 gl_lookup_enum_by_nr( type ),
304 stride);
305
306 ctx->Array.TexCoord[texUnit].StrideB = stride;
307 if (!stride) {
308 switch (type) {
309 case GL_SHORT:
310 ctx->Array.TexCoord[texUnit].StrideB = size*sizeof(GLshort);
311 break;
312 case GL_INT:
313 ctx->Array.TexCoord[texUnit].StrideB = size*sizeof(GLint);
314 break;
315 case GL_FLOAT:
316 ctx->Array.TexCoord[texUnit].StrideB = size*sizeof(GLfloat);
317 break;
318 case GL_DOUBLE:
319 ctx->Array.TexCoord[texUnit].StrideB = size*sizeof(GLdouble);
320 break;
321 default:
322 gl_error( ctx, GL_INVALID_ENUM, "glTexCoordPointer(type)" );
323 return;
324 }
325 }
326 ctx->Array.TexCoord[texUnit].Size = size;
327 ctx->Array.TexCoord[texUnit].Type = type;
328 ctx->Array.TexCoord[texUnit].Stride = stride;
329 ctx->Array.TexCoord[texUnit].Ptr = (void *) ptr;
330
331 ctx->Array.TexCoordFunc[texUnit] = gl_trans_4f_tab[size][TYPE_IDX(type)];
332 ctx->Array.TexCoordEltFunc[texUnit] = gl_trans_elt_4f_tab[size][TYPE_IDX(type)];
333 ctx->Array.NewArrayState |= PIPE_TEX(texUnit);
334 ctx->NewState |= NEW_CLIENT_STATE;
335 }
336
337
338
339
340 void GLAPIENTRY glEdgeFlagPointer(CTX_ARG GLsizei stride, const void *vptr )
341 {
342 const GLboolean *ptr = (GLboolean *)vptr;
343
344 GLcontext *ctx;
345 GET_CONTEXT;
346 CHECK_CONTEXT;
347 ctx = CC;
348
349 if (stride<0) {
350 gl_error( ctx, GL_INVALID_VALUE, "glEdgeFlagPointer(stride)" );
351 return;
352 }
353 ctx->Array.EdgeFlag.Stride = stride;
354 ctx->Array.EdgeFlag.StrideB = stride ? stride : sizeof(GLboolean);
355 ctx->Array.EdgeFlag.Ptr = (GLboolean *) ptr;
356 if (stride != sizeof(GLboolean)) {
357 ctx->Array.EdgeFlagFunc = gl_trans_1ub_tab[TYPE_IDX(GL_UNSIGNED_BYTE)];
358 } else {
359 ctx->Array.EdgeFlagFunc = 0;
360 }
361 ctx->Array.EdgeFlagEltFunc = gl_trans_elt_1ub_tab[TYPE_IDX(GL_UNSIGNED_BYTE)];
362 ctx->Array.NewArrayState |= VERT_EDGE;
363 ctx->NewState |= NEW_CLIENT_STATE;
364 }
365
366
367 /* Called only from gl_DrawElements
368 */
369 void gl_CVAEltPointer( GLcontext *ctx, GLenum type, const GLvoid *ptr )
370 {
371 switch (type) {
372 case GL_UNSIGNED_BYTE:
373 ctx->CVA.Elt.StrideB = sizeof(GLubyte);
374 break;
375 case GL_UNSIGNED_SHORT:
376 ctx->CVA.Elt.StrideB = sizeof(GLushort);
377 break;
378 case GL_UNSIGNED_INT:
379 ctx->CVA.Elt.StrideB = sizeof(GLuint);
380 break;
381 default:
382 gl_error( ctx, GL_INVALID_ENUM, "glEltPointer(type)" );
383 return;
384 }
385 ctx->CVA.Elt.Type = type;
386 ctx->CVA.Elt.Stride = 0;
387 ctx->CVA.Elt.Ptr = (void *) ptr;
388 ctx->CVA.EltFunc = gl_trans_1ui_tab[TYPE_IDX(type)];
389 ctx->Array.NewArrayState |= VERT_ELT; /* ??? */
390 }
391
392
393
394 /* KW: Batch function to exec all the array elements in the input
395 * buffer prior to transform. Done only the first time a vertex
396 * buffer is executed or compiled.
397 */
398 void gl_exec_array_elements( GLcontext *ctx, struct immediate *IM )
399 {
400 GLuint *flags = IM->Flag;
401 GLuint *elts = IM->Elt;
402 GLuint count = IM->Count;
403 GLuint start = IM->Start;
404 GLuint translate = ctx->Array.Flags;
405 GLuint i;
406
407 if (translate & VERT_OBJ_ANY)
408 (ctx->Array.VertexEltFunc)( IM->Obj,
409 &ctx->Array.Vertex,
410 flags, elts, (VERT_ELT|VERT_OBJ_ANY),
411 start, count);
412
413 if (translate & VERT_NORM)
414 (ctx->Array.NormalEltFunc)( IM->Normal,
415 &ctx->Array.Normal,
416 flags, elts, (VERT_ELT|VERT_NORM),
417 start, count);
418
419 if (translate & VERT_EDGE)
420 (ctx->Array.EdgeFlagEltFunc)( IM->EdgeFlag,
421 &ctx->Array.EdgeFlag,
422 flags, elts, (VERT_ELT|VERT_EDGE),
423 start, count);
424
425 if (translate & VERT_RGBA)
426 (ctx->Array.ColorEltFunc)( IM->Color,
427 &ctx->Array.Color,
428 flags, elts, (VERT_ELT|VERT_RGBA),
429 start, count);
430
431 if (translate & VERT_INDEX)
432 (ctx->Array.IndexEltFunc)( IM->Index,
433 &ctx->Array.Index,
434 flags, elts, (VERT_ELT|VERT_INDEX),
435 start, count);
436
437 if (translate & VERT_TEX0_ANY)
438 (ctx->Array.TexCoordEltFunc[0])( IM->TexCoord[0],
439 &ctx->Array.TexCoord[0],
440 flags, elts, (VERT_ELT|VERT_TEX0_ANY),
441 start, count);
442
443 if (translate & VERT_TEX1_ANY)
444 (ctx->Array.TexCoordEltFunc[1])( IM->TexCoord[1],
445 &ctx->Array.TexCoord[1],
446 flags, elts, (VERT_ELT|VERT_TEX1_ANY),
447 start, count);
448
449 IM->OrFlag |= translate;
450
451 /* Lighting ignores the and-flag, so still need to do this.
452 */
453 if (IM->AndFlag & VERT_ELT) {
454 for (i = 0 ; i < count ; i++)
455 flags[i] |= translate;
456 IM->AndFlag |= translate;
457 } else {
458 GLuint andflag = ~0;
459 for (i = 0 ; i < count ; i++) {
460 if (flags[i] & VERT_ELT) flags[i] |= translate;
461 andflag &= flags[i];
462 }
463 IM->AndFlag = andflag;
464 }
465 }
466
467
468
469 /* KW: I think this is moving in the right direction, but it still feels
470 * like we are doing way too much work.
471 */
472 void gl_DrawArrays( GLcontext *ctx, GLenum mode, GLint start, GLsizei count )
473 {
474 struct vertex_buffer *VB = ctx->VB;
475 GLint i;
476
477 ASSERT_OUTSIDE_BEGIN_END_AND_FLUSH(ctx, "glDrawArrays");
478
479 if (count<0) {
480 gl_error( ctx, GL_INVALID_VALUE, "glDrawArrays(count)" );
481 return;
482 }
483
484 if (!ctx->CompileFlag && ctx->Array.Vertex.Enabled)
485 {
486 GLint remaining = count;
487 GLint i;
488 GLvector4f obj;
489 GLvector3f norm;
490 GLvector4f tc[MAX_TEXTURE_UNITS];
491 GLvector4ub col;
492 GLvector1ub edge;
493 GLvector1ui index;
494 GLuint update = 0, translate = 0;
495 struct vertex_array_pointers VSrc;
496 struct immediate *IM = VB->IM;
497 struct gl_client_array *client_data;
498 struct gl_pipeline *elt = &ctx->CVA.elt;
499 GLuint relock;
500 GLuint fallback, required;
501
502 if (ctx->NewState)
503 gl_update_state( ctx );
504
505 /* This will die miserably with CVA... Need more work to support this.
506 */
507 relock = ctx->CompileCVAFlag;
508 ctx->CompileCVAFlag = 0;
509
510 if (!elt->pipeline_valid || relock)
511 gl_build_immediate_pipeline( ctx );
512
513 required = elt->inputs;
514 fallback = (elt->inputs & ~ctx->Array.Summary);
515
516 VSrc.Color = &IM->v.Color;
517 VSrc.Index = &IM->v.Index;
518 VSrc.EdgeFlag = &IM->v.EdgeFlag;
519 VSrc.TexCoord[0] = &IM->v.TexCoord[0];
520 VSrc.TexCoord[1] = &IM->v.TexCoord[1];
521 VSrc.Obj = &IM->v.Obj;
522 VSrc.Normal = &IM->v.Normal;
523
524 if (required & VERT_RGBA)
525 {
526 client_data = &ctx->Array.Color;
527 if (fallback & VERT_RGBA)
528 client_data = &ctx->Fallback.Color;
529
530 if (client_data->Type == GL_UNSIGNED_BYTE &&
531 client_data->Size == 4)
532 {
533 VSrc.Color = &col;
534 col.data = (GLubyte (*)[4]) client_data->Ptr;
535 col.stride = client_data->StrideB;
536 col.flags = VEC_NOT_WRITABLE|VEC_GOOD_STRIDE;
537 if (client_data->StrideB != 4 * sizeof(GLubyte))
538 col.flags ^= VEC_STRIDE_FLAGS;
539
540 update |= VERT_RGBA;
541 } else {
542 translate |= VERT_RGBA;
543 }
544 }
545
546 if (required & VERT_INDEX)
547 {
548 client_data = &ctx->Array.Index;
549 if (fallback & VERT_INDEX)
550 client_data = &ctx->Fallback.Index;
551
552 if (client_data->Type == GL_UNSIGNED_INT)
553 {
554 VSrc.Index = &index;
555 index.data = (GLuint *) client_data->Ptr;
556 index.stride = client_data->StrideB;
557 index.flags = VEC_NOT_WRITABLE|VEC_GOOD_STRIDE;
558 if (client_data->StrideB != sizeof(GLuint))
559 index.flags ^= VEC_STRIDE_FLAGS;
560
561 update |= VERT_INDEX;
562 } else {
563 translate |= VERT_INDEX;
564 }
565 }
566
567 for (i = 0 ; i < MAX_TEXTURE_UNITS ; i++)
568 {
569 GLuint flag = VERT_TEX_ANY(i);
570
571 if (required & flag) {
572
573 client_data = &ctx->Array.TexCoord[i];
574
575 if (fallback & flag)
576 {
577 client_data = &ctx->Fallback.TexCoord[i];
578 client_data->Size = gl_texcoord_size( ctx->Current.Flag, i );
579 }
580
581 if (client_data->Type == GL_FLOAT)
582 {
583 VSrc.TexCoord[i] = &tc[i];
584 tc[i].data = (GLfloat (*)[4]) client_data->Ptr;
585 tc[i].stride = client_data->StrideB;
586 tc[i].size = client_data->Size;
587 tc[i].flags = VEC_NOT_WRITABLE|VEC_GOOD_STRIDE;
588 if (tc[i].stride |= 4 * sizeof(GLfloat))
589 tc[i].flags ^= VEC_STRIDE_FLAGS;
590 update |= flag;
591 } else {
592 translate |= flag;
593 }
594 }
595 }
596
597 if (ctx->Array.Flags != ctx->Array.Flag[0])
598 for (i = 0 ; i < VB_MAX ; i++)
599 ctx->Array.Flag[i] = ctx->Array.Flags;
600
601
602 if (ctx->Array.Vertex.Type == GL_FLOAT)
603 {
604 VSrc.Obj = &obj;
605 obj.data = (GLfloat (*)[4]) ctx->Array.Vertex.Ptr;
606 obj.stride = ctx->Array.Vertex.StrideB;
607 obj.size = ctx->Array.Vertex.Size;
608 obj.flags = VEC_NOT_WRITABLE|VEC_GOOD_STRIDE;
609 if (obj.stride != 4 * sizeof(GLfloat))
610 obj.flags ^= VEC_STRIDE_FLAGS;
611
612 update |= VERT_OBJ_ANY;
613 }
614 else
615 {
616 translate |= VERT_OBJ_ANY;
617 }
618
619 if (required & VERT_NORM)
620 {
621 client_data = &ctx->Array.Normal;
622 if (fallback & VERT_NORM)
623 client_data = &ctx->Fallback.Normal;
624
625 if (client_data->Type == GL_FLOAT)
626 {
627 VSrc.Normal = &norm;
628 norm.flags = 0;
629 norm.data = (GLfloat (*)[3]) client_data->Ptr;
630 norm.stride = client_data->StrideB;
631 update |= VERT_NORM;
632 } else {
633 translate |= VERT_NORM;
634 }
635 }
636
637 if ( (required & VERT_EDGE) &&
638 (mode == GL_TRIANGLES ||
639 mode == GL_QUADS ||
640 mode == GL_POLYGON))
641 {
642 client_data = &ctx->Array.EdgeFlag;
643
644 if (fallback & VERT_EDGE)
645 client_data = &ctx->Fallback.EdgeFlag;
646
647 VSrc.EdgeFlag = &edge;
648 edge.data = (GLboolean *) client_data->Ptr;
649 edge.stride = client_data->StrideB;
650 edge.flags = VEC_NOT_WRITABLE|VEC_GOOD_STRIDE;
651 if (edge.stride != sizeof(GLubyte))
652 edge.flags ^= VEC_STRIDE_FLAGS;
653
654 update |= VERT_EDGE;
655 }
656
657 VB->Primitive = IM->Primitive;
658 VB->NextPrimitive = IM->NextPrimitive;
659 VB->MaterialMask = IM->MaterialMask;
660 VB->Material = IM->Material;
661 VB->BoundsPtr = 0;
662
663 while (remaining > 0) {
664 GLint vbspace = VB_MAX - VB_START;
665 GLuint count, n;
666
667
668 if (vbspace >= remaining) {
669 n = remaining;
670 VB->LastPrimitive = VB_START + n;
671 } else {
672 n = vbspace;
673 VB->LastPrimitive = VB_START;
674 }
675
676 VB->CullMode = 0;
677
678
679 /* Update pointers.
680 */
681 if (update) {
682 if (update & VERT_OBJ_ANY)
683 obj.start = VEC_ELT(&obj, GLfloat, start);
684
685 if (update & VERT_NORM)
686 norm.start = VEC_ELT(&norm, GLfloat, start);
687
688 if (update & VERT_EDGE)
689 edge.start = VEC_ELT(&edge, GLubyte, start);
690
691 if (update & VERT_RGBA)
692 col.start = VEC_ELT(&col, GLubyte, start);
693
694 if (update & VERT_INDEX)
695 index.start = VEC_ELT(&index, GLuint, start);
696
697 if (update & VERT_TEX0_ANY)
698 tc[0].start = VEC_ELT(&tc[0], GLfloat, start);
699
700 if (update & VERT_TEX1_ANY)
701 tc[1].start = VEC_ELT(&tc[1], GLfloat, start);
702 }
703
704
705 /* Translate data to fix up type and stride.
706 */
707 if (translate) {
708 if (translate & VERT_OBJ_ANY) {
709 ctx->Array.VertexFunc( IM->Obj + VB_START,
710 &ctx->Array.Vertex, start, n );
711 }
712
713 if (translate & VERT_NORM) {
714 ctx->Array.NormalFunc( IM->Normal + VB_START,
715 &ctx->Array.Normal, start, n );
716 }
717
718 if (translate & VERT_EDGE) {
719 ctx->Array.EdgeFlagFunc( IM->EdgeFlag + VB_START,
720 &ctx->Array.EdgeFlag, start, n );
721 }
722
723 if (translate & VERT_RGBA) {
724 ctx->Array.ColorFunc( IM->Color + VB_START,
725 &ctx->Array.Color, start, n );
726 }
727
728 if (translate & VERT_INDEX) {
729 ctx->Array.IndexFunc( IM->Index + VB_START,
730 &ctx->Array.Index, start, n );
731 }
732
733 if (translate & VERT_TEX0_ANY) {
734 IM->v.TexCoord[0].size = tc[0].size;
735 ctx->Array.TexCoordFunc[0]( IM->TexCoord[0] + VB_START,
736 &ctx->Array.TexCoord[0], start, n );
737 }
738
739 if (translate & VERT_TEX1_ANY) {
740 IM->v.TexCoord[1].size = tc[1].size;
741 ctx->Array.TexCoordFunc[1]( IM->TexCoord[1] + VB_START,
742 &ctx->Array.TexCoord[1], start, n );
743 }
744 }
745
746
747 VB->ObjPtr = VSrc.Obj;
748 VB->NormalPtr = VSrc.Normal;
749 VB->Color[0] = VB->Color[1] = VB->ColorPtr = VSrc.Color;
750 VB->IndexPtr = VSrc.Index;
751 VB->EdgeFlagPtr = VSrc.EdgeFlag;
752 VB->TexCoordPtr[0] = VSrc.TexCoord[0];
753 VB->TexCoordPtr[1] = VSrc.TexCoord[1];
754
755 VB->Flag = ctx->Array.Flag;
756 VB->AndFlag = ctx->Array.Flags;
757 VB->OrFlag = ctx->Array.Flags;
758
759 count = VB->Count = VB_START + n;
760
761 VB->ObjPtr->count = count;
762 VB->NormalPtr->count = count;
763 VB->ColorPtr->count = count;
764 VB->IndexPtr->count = count;
765 VB->EdgeFlagPtr->count = count;
766 VB->TexCoordPtr[0]->count = count;
767 VB->TexCoordPtr[1]->count = count;
768
769 VB->Flag[count] |= VERT_END_VB;
770 VB->Flag[VB_START] |= VERT_NORM;
771 /* VB->Flag[VB_START] |= (IM->Flag[vb_start] & VERT_MATERIAL); */
772
773 VB->NextPrimitive[VB->CopyStart] = VB->Count;
774 VB->Primitive[VB->CopyStart] = mode;
775
776 /* Transform and render.
777 */
778 gl_run_pipeline( VB );
779 gl_reset_vb( VB );
780
781 ctx->Array.Flag[count] = ctx->Array.Flags;
782 ctx->Array.Flag[VB_START] = ctx->Array.Flags;
783 IM->Flag[VB_START] = 0;
784
785 start += n;
786 remaining -= n;
787 }
788
789 ctx->CompileCVAFlag = relock;
790 }
791 else if (ctx->Array.Vertex.Enabled)
792 {
793 /* The GL_COMPILE and GL_COMPILE_AND_EXECUTE cases. These
794 * could be handled by the above code, but it gets a little
795 * complex.
796 */
797 /* No need to reset - never called from inside a display list */
798 gl_Begin( ctx, mode );
799 for (i=0;i<count;i++) {
800 gl_ArrayElement( ctx, start+i );
801 }
802 gl_End( ctx );
803 }
804 else
805 {
806 /* The degenerate case where vertices are not enabled - only
807 * need to process the very final array element, as all of the
808 * preceding ones would be overwritten anyway.
809 */
810 gl_Begin( ctx, mode );
811 gl_ArrayElement( ctx, start+count );
812 gl_End( ctx );
813 }
814 }
815
816
817
818 /* KW: Exactly fakes the effects of calling glArrayElement multiple times.
819 * Compilation is handled via. the IM->maybe_transform_vb() callback.
820 */
821 #define DRAW_ELT(FUNC, TYPE) \
822 static void FUNC( GLcontext *ctx, GLenum mode, \
823 TYPE *indices, GLuint count ) \
824 { \
825 GLuint i,j; \
826 \
827 if (count) gl_Begin( ctx, mode ); \
828 \
829 for (j = 0 ; j < count ; ) { \
830 GLuint nr = MIN2( VB_MAX, count - j + VB_START ); \
831 struct immediate *IM = ctx->input; \
832 GLuint sf = IM->Flag[VB_START]; \
833 \
834 for (i = VB_START ; i < nr ; i++) { \
835 IM->Elt[i] = (GLuint) *indices++; \
836 IM->Flag[i] = VERT_ELT; \
837 } \
838 \
839 if (j == 0) IM->Flag[VB_START] |= sf; \
840 \
841 IM->Count = nr; \
842 j += nr - VB_START; \
843 \
844 if (j == count) gl_End( ctx ); \
845 \
846 IM->maybe_transform_vb( IM ); \
847 } \
848 }
849
850 DRAW_ELT( draw_elt_ubyte, GLubyte )
851 DRAW_ELT( draw_elt_ushort, GLushort )
852 DRAW_ELT( draw_elt_uint, GLuint )
853
854
855 static GLuint natural_stride[0x10] =
856 {
857 sizeof(GLbyte), /* 0 */
858 sizeof(GLubyte), /* 1 */
859 sizeof(GLshort), /* 2 */
860 sizeof(GLushort), /* 3 */
861 sizeof(GLint), /* 4 */
862 sizeof(GLuint), /* 5 */
863 sizeof(GLfloat), /* 6 */
864 2 * sizeof(GLbyte), /* 7 */
865 3 * sizeof(GLbyte), /* 8 */
866 4 * sizeof(GLbyte), /* 9 */
867 sizeof(GLdouble), /* a */
868 0, /* b */
869 0, /* c */
870 0, /* d */
871 0, /* e */
872 0 /* f */
873 };
874
875 void GLAPIENTRY glDrawElements(CTX_ARG GLenum mode, GLsizei count,
876 GLenum type, const GLvoid *indices )
877 {
878 GLcontext *ctx;
879 struct gl_cva *cva;
880
881 GET_CONTEXT;
882 CHECK_CONTEXT;
883 ctx = CC;
884
885 cva = &ctx->CVA;
886 ASSERT_OUTSIDE_BEGIN_END_AND_FLUSH(ctx, "glDrawElements");
887
888 if (count<0) {
889 gl_error( ctx, GL_INVALID_VALUE, "glDrawElements(count)" );
890 return;
891 }
892
893 if (mode < 0 || mode > GL_POLYGON) {
894 gl_error( ctx, GL_INVALID_ENUM, "glDrawArrays(mode)" );
895 return;
896 }
897
898 if (type != GL_UNSIGNED_INT && type != GL_UNSIGNED_BYTE && type != GL_UNSIGNED_SHORT)
899 {
900 gl_error( ctx, GL_INVALID_ENUM, "glDrawElements(type)" );
901 return;
902 }
903
904 if (ctx->NewState)
905 gl_update_state(ctx);
906
907 if (ctx->CompileCVAFlag)
908 {
909 #if defined(MESA_CVA_PROF)
910 force_init_prof();
911 #endif
912
913 /* Treat VERT_ELT like a special client array.
914 */
915 ctx->Array.NewArrayState |= VERT_ELT;
916 ctx->Array.Summary |= VERT_ELT;
917 ctx->Array.Flags |= VERT_ELT;
918
919 cva->elt_mode = mode;
920 cva->elt_count = count;
921 cva->Elt.Type = type;
922 cva->Elt.Ptr = (void *) indices;
923 cva->Elt.StrideB = natural_stride[TYPE_IDX(type)];
924 cva->EltFunc = gl_trans_1ui_tab[TYPE_IDX(type)];
925
926 if (!cva->pre.pipeline_valid)
927 gl_build_precalc_pipeline( ctx );
928 else if (MESA_VERBOSE & VERBOSE_PIPELINE)
929 fprintf(stderr, ": dont rebuild\n");
930
931 gl_cva_force_precalc( ctx );
932
933 /* Did we 'precalculate' the render op?
934 */
935 if (ctx->CVA.pre.ops & PIPE_OP_RENDER) {
936 ctx->Array.NewArrayState |= VERT_ELT;
937 ctx->Array.Summary &= ~VERT_ELT;
938 ctx->Array.Flags &= ~VERT_ELT;
939 return;
940 }
941
942 if ( (MESA_VERBOSE&VERBOSE_VARRAY) )
943 printf("using immediate\n");
944 }
945
946
947 /* Otherwise, have to use the immediate path to render.
948 */
949 switch (type) {
950 case GL_UNSIGNED_BYTE:
951 {
952 GLubyte *ub_indices = (GLubyte *) indices;
953 if (ctx->Array.Summary & VERT_OBJ_ANY) {
954 draw_elt_ubyte( ctx, mode, ub_indices, count );
955 } else {
956 gl_ArrayElement( ctx, (GLuint) ub_indices[count-1] );
957 }
958 }
959 break;
960 case GL_UNSIGNED_SHORT:
961 {
962 GLushort *us_indices = (GLushort *) indices;
963 if (ctx->Array.Summary & VERT_OBJ_ANY) {
964 draw_elt_ushort( ctx, mode, us_indices, count );
965 } else {
966 gl_ArrayElement( ctx, (GLuint) us_indices[count-1] );
967 }
968 }
969 break;
970 case GL_UNSIGNED_INT:
971 {
972 GLuint *ui_indices = (GLuint *) indices;
973 if (ctx->Array.Summary & VERT_OBJ_ANY) {
974 draw_elt_uint( ctx, mode, ui_indices, count );
975 } else {
976 gl_ArrayElement( ctx, ui_indices[count-1] );
977 }
978 }
979 break;
980 default:
981 gl_error( ctx, GL_INVALID_ENUM, "glDrawElements(type)" );
982 break;
983 }
984
985 if (ctx->CompileCVAFlag) {
986 ctx->Array.NewArrayState |= VERT_ELT;
987 ctx->Array.Summary &= ~VERT_ELT;
988 }
989 }
990
991
992
993 void GLAPIENTRY glInterleavedArrays(CTX_ARG GLenum format, GLsizei stride,
994 const GLvoid *pointer )
995 {
996 GLcontext *ctx;
997 GLboolean tflag, cflag, nflag; /* enable/disable flags */
998 GLint tcomps, ccomps, vcomps; /* components per texcoord, color, vertex */
999
1000 GLenum ctype; /* color type */
1001 GLint coffset, noffset, voffset;/* color, normal, vertex offsets */
1002 GLint defstride; /* default stride */
1003 GLint c, f;
1004 GLint coordUnitSave;
1005
1006 GET_CONTEXT;
1007 CHECK_CONTEXT;
1008 ctx = CC;
1009
1010
1011 f = sizeof(GLfloat);
1012 c = f * ((4*sizeof(GLubyte) + (f-1)) / f);
1013
1014 if (stride<0) {
1015 gl_error( ctx, GL_INVALID_VALUE, "glInterleavedArrays(stride)" );
1016 return;
1017 }
1018
1019 switch (format) {
1020 case GL_V2F:
1021 tflag = GL_FALSE; cflag = GL_FALSE; nflag = GL_FALSE;
1022 tcomps = 0; ccomps = 0; vcomps = 2;
1023 voffset = 0;
1024 defstride = 2*f;
1025 break;
1026 case GL_V3F:
1027 tflag = GL_FALSE; cflag = GL_FALSE; nflag = GL_FALSE;
1028 tcomps = 0; ccomps = 0; vcomps = 3;
1029 voffset = 0;
1030 defstride = 3*f;
1031 break;
1032 case GL_C4UB_V2F:
1033 tflag = GL_FALSE; cflag = GL_TRUE; nflag = GL_FALSE;
1034 tcomps = 0; ccomps = 4; vcomps = 2;
1035 ctype = GL_UNSIGNED_BYTE;
1036 coffset = 0;
1037 voffset = c;
1038 defstride = c + 2*f;
1039 break;
1040 case GL_C4UB_V3F:
1041 tflag = GL_FALSE; cflag = GL_TRUE; nflag = GL_FALSE;
1042 tcomps = 0; ccomps = 4; vcomps = 3;
1043 ctype = GL_UNSIGNED_BYTE;
1044 coffset = 0;
1045 voffset = c;
1046 defstride = c + 3*f;
1047 break;
1048 case GL_C3F_V3F:
1049 tflag = GL_FALSE; cflag = GL_TRUE; nflag = GL_FALSE;
1050 tcomps = 0; ccomps = 3; vcomps = 3;
1051 ctype = GL_FLOAT;
1052 coffset = 0;
1053 voffset = 3*f;
1054 defstride = 6*f;
1055 break;
1056 case GL_N3F_V3F:
1057 tflag = GL_FALSE; cflag = GL_FALSE; nflag = GL_TRUE;
1058 tcomps = 0; ccomps = 0; vcomps = 3;
1059 noffset = 0;
1060 voffset = 3*f;
1061 defstride = 6*f;
1062 break;
1063 case GL_C4F_N3F_V3F:
1064 tflag = GL_FALSE; cflag = GL_TRUE; nflag = GL_TRUE;
1065 tcomps = 0; ccomps = 4; vcomps = 3;
1066 ctype = GL_FLOAT;
1067 coffset = 0;
1068 noffset = 4*f;
1069 voffset = 7*f;
1070 defstride = 10*f;
1071 break;
1072 case GL_T2F_V3F:
1073 tflag = GL_TRUE; cflag = GL_FALSE; nflag = GL_FALSE;
1074 tcomps = 2; ccomps = 0; vcomps = 3;
1075 voffset = 2*f;
1076 defstride = 5*f;
1077 break;
1078 case GL_T4F_V4F:
1079 tflag = GL_TRUE; cflag = GL_FALSE; nflag = GL_FALSE;
1080 tcomps = 4; ccomps = 0; vcomps = 4;
1081 voffset = 4*f;
1082 defstride = 8*f;
1083 break;
1084 case GL_T2F_C4UB_V3F:
1085 tflag = GL_TRUE; cflag = GL_TRUE; nflag = GL_FALSE;
1086 tcomps = 2; ccomps = 4; vcomps = 3;
1087 ctype = GL_UNSIGNED_BYTE;
1088 coffset = 2*f;
1089 voffset = c+2*f;
1090 defstride = c+5*f;
1091 break;
1092 case GL_T2F_C3F_V3F:
1093 tflag = GL_TRUE; cflag = GL_TRUE; nflag = GL_FALSE;
1094 tcomps = 2; ccomps = 3; vcomps = 3;
1095 ctype = GL_FLOAT;
1096 coffset = 2*f;
1097 voffset = 5*f;
1098 defstride = 8*f;
1099 break;
1100 case GL_T2F_N3F_V3F:
1101 tflag = GL_TRUE; cflag = GL_FALSE; nflag = GL_TRUE;
1102 tcomps = 2; ccomps = 0; vcomps = 3;
1103 noffset = 2*f;
1104 voffset = 5*f;
1105 defstride = 8*f;
1106 break;
1107 case GL_T2F_C4F_N3F_V3F:
1108 tflag = GL_TRUE; cflag = GL_TRUE; nflag = GL_TRUE;
1109 tcomps = 2; ccomps = 4; vcomps = 3;
1110 ctype = GL_FLOAT;
1111 coffset = 2*f;
1112 noffset = 6*f;
1113 voffset = 9*f;
1114 defstride = 12*f;
1115 break;
1116 case GL_T4F_C4F_N3F_V4F:
1117 tflag = GL_TRUE; cflag = GL_TRUE; nflag = GL_TRUE;
1118 tcomps = 4; ccomps = 4; vcomps = 4;
1119 ctype = GL_FLOAT;
1120 coffset = 4*f;
1121 noffset = 8*f;
1122 voffset = 11*f;
1123 defstride = 15*f;
1124 break;
1125 default:
1126 gl_error( ctx, GL_INVALID_ENUM, "glInterleavedArrays(format)" );
1127 return;
1128 }
1129
1130 if (stride==0) {
1131 stride = defstride;
1132 }
1133
1134 gl_DisableClientState( ctx, GL_EDGE_FLAG_ARRAY );
1135 gl_DisableClientState( ctx, GL_INDEX_ARRAY );
1136
1137 /* Texcoords */
1138 coordUnitSave = ctx->TexCoordUnit;
1139 if (tflag) {
1140 GLint i;
1141 GLint factor = ctx->Array.TexCoordInterleaveFactor;
1142 for (i = 0; i < factor; i++) {
1143 gl_ActiveTexture( ctx, (GLenum) (GL_TEXTURE0_ARB + i) );
1144 gl_EnableClientState( ctx, GL_TEXTURE_COORD_ARRAY );
1145 glTexCoordPointer(CTX_PRM tcomps, GL_FLOAT, stride,
1146 (GLubyte *) pointer + i * coffset );
1147 }
1148 for (i = factor; i < ctx->Const.MaxTextureUnits; i++) {
1149 gl_ActiveTexture( ctx, (GLenum) (GL_TEXTURE0_ARB + i) );
1150 gl_DisableClientState( ctx, GL_TEXTURE_COORD_ARRAY );
1151 }
1152 }
1153 else {
1154 GLint i;
1155 for (i = 0; i < ctx->Const.MaxTextureUnits; i++) {
1156 gl_ActiveTexture( ctx, (GLenum) (GL_TEXTURE0_ARB + i) );
1157 gl_DisableClientState( ctx, GL_TEXTURE_COORD_ARRAY );
1158 }
1159 }
1160 /* Restore texture coordinate unit index */
1161 gl_ActiveTexture( ctx, (GLenum) (GL_TEXTURE0_ARB + coordUnitSave) );
1162
1163
1164 /* Color */
1165 if (cflag) {
1166 gl_EnableClientState( ctx, GL_COLOR_ARRAY );
1167 glColorPointer(CTX_PRM ccomps, ctype, stride,
1168 (GLubyte*) pointer + coffset );
1169 }
1170 else {
1171 gl_DisableClientState( ctx, GL_COLOR_ARRAY );
1172 }
1173
1174
1175 /* Normals */
1176 if (nflag) {
1177 gl_EnableClientState( ctx, GL_NORMAL_ARRAY );
1178 glNormalPointer(CTX_PRM GL_FLOAT, stride,
1179 (GLubyte*) pointer + noffset );
1180 }
1181 else {
1182 gl_DisableClientState( ctx, GL_NORMAL_ARRAY );
1183 }
1184
1185 gl_EnableClientState( ctx, GL_VERTEX_ARRAY );
1186 glVertexPointer(CTX_PRM vcomps, GL_FLOAT, stride,
1187 (GLubyte *) pointer + voffset );
1188 }
1189
1190
1191
1192 void GLAPIENTRY glDrawRangeElements(CTX_ARG GLenum mode, GLuint start,
1193 GLuint end, GLsizei count,
1194 GLenum type, const GLvoid *indices )
1195 {
1196 GLcontext *ctx;
1197 GET_CONTEXT;
1198 CHECK_CONTEXT;
1199 ctx = CC;
1200
1201 if (end < start) {
1202 gl_error(ctx, GL_INVALID_VALUE, "glDrawRangeElements( end < start )");
1203 return;
1204 }
1205
1206 if (!ctx->Array.LockCount && 2*count > 3*(end-start)) {
1207 glLockArraysEXT(CTX_PRM start, end );
1208 glDrawElements(CTX_PRM mode, count, type, indices );
1209 glUnlockArraysEXT(CTX_VPRM );
1210 } else {
1211 glDrawElements(CTX_PRM mode, count, type, indices );
1212 }
1213 }
1214
1215
1216
1217 void gl_update_client_state( GLcontext *ctx )
1218 {
1219 static GLuint sz_flags[5] = { 0,
1220 0,
1221 VERT_OBJ_2,
1222 VERT_OBJ_23,
1223 VERT_OBJ_234 };
1224
1225 static GLuint tc_flags[5] = { 0,
1226 VERT_TEX0_1,
1227 VERT_TEX0_12,
1228 VERT_TEX0_123,
1229 VERT_TEX0_1234 };
1230
1231 ctx->Array.Flags = 0;
1232 ctx->Array.Summary = 0;
1233 ctx->input->ArrayIncr = 0;
1234
1235 if (ctx->Array.Normal.Enabled) ctx->Array.Flags |= VERT_NORM;
1236 if (ctx->Array.Color.Enabled) ctx->Array.Flags |= VERT_RGBA;
1237 if (ctx->Array.Index.Enabled) ctx->Array.Flags |= VERT_INDEX;
1238 if (ctx->Array.EdgeFlag.Enabled) ctx->Array.Flags |= VERT_EDGE;
1239 if (ctx->Array.Vertex.Enabled) {
1240 ctx->Array.Flags |= sz_flags[ctx->Array.Vertex.Size];
1241 ctx->input->ArrayIncr = 1;
1242 }
1243 if (ctx->Array.TexCoord[0].Enabled) {
1244 ctx->Array.Flags |= tc_flags[ctx->Array.TexCoord[0].Size];
1245 }
1246 if (ctx->Array.TexCoord[1].Enabled) {
1247 ctx->Array.Flags |= (tc_flags[ctx->Array.TexCoord[1].Size] << NR_TEXSIZE_BITS);
1248 }
1249
1250 /* Not really important any more:
1251 */
1252 ctx->Array.Summary = ctx->Array.Flags & VERT_DATA;
1253 ctx->input->ArrayAndFlags = ~ctx->Array.Flags;
1254 ctx->input->ArrayEltFlush = !(ctx->CompileCVAFlag);
1255 }
1256