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