added memory macros
[mesa.git] / src / mesa / main / varray.c
1 /* $Id: varray.c,v 1.4 1999/10/08 09:27:11 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 void gl_exec_array_elements( GLcontext *ctx, struct immediate *IM )
408 {
409 GLuint *flags = IM->Flag;
410 GLuint *elts = IM->Elt;
411 GLuint count = IM->Count;
412 GLuint start = IM->Start;
413 GLuint translate = ctx->Array.Flags;
414 GLuint i;
415
416 if (translate & VERT_OBJ_ANY)
417 (ctx->Array.VertexEltFunc)( IM->Obj,
418 &ctx->Array.Vertex,
419 flags, elts, (VERT_ELT|VERT_OBJ_ANY),
420 start, count);
421
422 if (translate & VERT_NORM)
423 (ctx->Array.NormalEltFunc)( IM->Normal,
424 &ctx->Array.Normal,
425 flags, elts, (VERT_ELT|VERT_NORM),
426 start, count);
427
428 if (translate & VERT_EDGE)
429 (ctx->Array.EdgeFlagEltFunc)( IM->EdgeFlag,
430 &ctx->Array.EdgeFlag,
431 flags, elts, (VERT_ELT|VERT_EDGE),
432 start, count);
433
434 if (translate & VERT_RGBA)
435 (ctx->Array.ColorEltFunc)( IM->Color,
436 &ctx->Array.Color,
437 flags, elts, (VERT_ELT|VERT_RGBA),
438 start, count);
439
440 if (translate & VERT_INDEX)
441 (ctx->Array.IndexEltFunc)( IM->Index,
442 &ctx->Array.Index,
443 flags, elts, (VERT_ELT|VERT_INDEX),
444 start, count);
445
446 if (translate & VERT_TEX0_ANY)
447 (ctx->Array.TexCoordEltFunc[0])( IM->TexCoord[0],
448 &ctx->Array.TexCoord[0],
449 flags, elts, (VERT_ELT|VERT_TEX0_ANY),
450 start, count);
451
452 if (translate & VERT_TEX1_ANY)
453 (ctx->Array.TexCoordEltFunc[1])( IM->TexCoord[1],
454 &ctx->Array.TexCoord[1],
455 flags, elts, (VERT_ELT|VERT_TEX1_ANY),
456 start, count);
457
458 IM->OrFlag |= translate;
459
460 /* Lighting ignores the and-flag, so still need to do this.
461 */
462 if (IM->AndFlag & VERT_ELT) {
463 for (i = 0 ; i < count ; i++)
464 flags[i] |= translate;
465 IM->AndFlag |= translate;
466 } else {
467 GLuint andflag = ~0;
468 for (i = 0 ; i < count ; i++) {
469 if (flags[i] & VERT_ELT) flags[i] |= translate;
470 andflag &= flags[i];
471 }
472 IM->AndFlag = andflag;
473 }
474 }
475
476
477
478 /* KW: I think this is moving in the right direction, but it still feels
479 * like we are doing way too much work.
480 */
481 void gl_DrawArrays( GLcontext *ctx, GLenum mode, GLint start, GLsizei count )
482 {
483 struct vertex_buffer *VB = ctx->VB;
484 GLint i;
485
486 ASSERT_OUTSIDE_BEGIN_END_AND_FLUSH(ctx, "glDrawArrays");
487
488 if (count<0) {
489 gl_error( ctx, GL_INVALID_VALUE, "glDrawArrays(count)" );
490 return;
491 }
492
493 if (!ctx->CompileFlag && ctx->Array.Vertex.Enabled)
494 {
495 GLint remaining = count;
496 GLint i;
497 GLvector4f obj;
498 GLvector3f norm;
499 GLvector4f tc[MAX_TEXTURE_UNITS];
500 GLvector4ub col;
501 GLvector1ub edge;
502 GLvector1ui index;
503 GLuint update = 0, translate = 0;
504 struct vertex_array_pointers VSrc;
505 struct immediate *IM = VB->IM;
506 struct gl_client_array *client_data;
507 struct gl_pipeline *elt = &ctx->CVA.elt;
508 GLuint relock;
509 GLuint fallback, required;
510
511 if (ctx->NewState)
512 gl_update_state( ctx );
513
514 /* This will die miserably with CVA... Need more work to support this.
515 */
516 relock = ctx->CompileCVAFlag;
517 ctx->CompileCVAFlag = 0;
518
519 if (!elt->pipeline_valid || relock)
520 gl_build_immediate_pipeline( ctx );
521
522 required = elt->inputs;
523 fallback = (elt->inputs & ~ctx->Array.Summary);
524
525 VSrc.Color = &IM->v.Color;
526 VSrc.Index = &IM->v.Index;
527 VSrc.EdgeFlag = &IM->v.EdgeFlag;
528 VSrc.TexCoord[0] = &IM->v.TexCoord[0];
529 VSrc.TexCoord[1] = &IM->v.TexCoord[1];
530 VSrc.Obj = &IM->v.Obj;
531 VSrc.Normal = &IM->v.Normal;
532
533 if (required & VERT_RGBA)
534 {
535 client_data = &ctx->Array.Color;
536 if (fallback & VERT_RGBA)
537 client_data = &ctx->Fallback.Color;
538
539 if (client_data->Type == GL_UNSIGNED_BYTE &&
540 client_data->Size == 4)
541 {
542 VSrc.Color = &col;
543 col.data = (GLubyte (*)[4]) client_data->Ptr;
544 col.stride = client_data->StrideB;
545 col.flags = VEC_NOT_WRITABLE|VEC_GOOD_STRIDE;
546 if (client_data->StrideB != 4 * sizeof(GLubyte))
547 col.flags ^= VEC_STRIDE_FLAGS;
548
549 update |= VERT_RGBA;
550 } else {
551 translate |= VERT_RGBA;
552 }
553 }
554
555 if (required & VERT_INDEX)
556 {
557 client_data = &ctx->Array.Index;
558 if (fallback & VERT_INDEX)
559 client_data = &ctx->Fallback.Index;
560
561 if (client_data->Type == GL_UNSIGNED_INT)
562 {
563 VSrc.Index = &index;
564 index.data = (GLuint *) client_data->Ptr;
565 index.stride = client_data->StrideB;
566 index.flags = VEC_NOT_WRITABLE|VEC_GOOD_STRIDE;
567 if (client_data->StrideB != sizeof(GLuint))
568 index.flags ^= VEC_STRIDE_FLAGS;
569
570 update |= VERT_INDEX;
571 } else {
572 translate |= VERT_INDEX;
573 }
574 }
575
576 for (i = 0 ; i < MAX_TEXTURE_UNITS ; i++)
577 {
578 GLuint flag = VERT_TEX_ANY(i);
579
580 if (required & flag) {
581
582 client_data = &ctx->Array.TexCoord[i];
583
584 if (fallback & flag)
585 {
586 client_data = &ctx->Fallback.TexCoord[i];
587 client_data->Size = gl_texcoord_size( ctx->Current.Flag, i );
588 }
589
590 if (client_data->Type == GL_FLOAT)
591 {
592 VSrc.TexCoord[i] = &tc[i];
593 tc[i].data = (GLfloat (*)[4]) client_data->Ptr;
594 tc[i].stride = client_data->StrideB;
595 tc[i].size = client_data->Size;
596 tc[i].flags = VEC_NOT_WRITABLE|VEC_GOOD_STRIDE;
597 if (tc[i].stride |= 4 * sizeof(GLfloat))
598 tc[i].flags ^= VEC_STRIDE_FLAGS;
599 update |= flag;
600 } else {
601 translate |= flag;
602 }
603 }
604 }
605
606 if (ctx->Array.Flags != ctx->Array.Flag[0])
607 for (i = 0 ; i < VB_MAX ; i++)
608 ctx->Array.Flag[i] = ctx->Array.Flags;
609
610
611 if (ctx->Array.Vertex.Type == GL_FLOAT)
612 {
613 VSrc.Obj = &obj;
614 obj.data = (GLfloat (*)[4]) ctx->Array.Vertex.Ptr;
615 obj.stride = ctx->Array.Vertex.StrideB;
616 obj.size = ctx->Array.Vertex.Size;
617 obj.flags = VEC_NOT_WRITABLE|VEC_GOOD_STRIDE;
618 if (obj.stride != 4 * sizeof(GLfloat))
619 obj.flags ^= VEC_STRIDE_FLAGS;
620
621 update |= VERT_OBJ_ANY;
622 }
623 else
624 {
625 translate |= VERT_OBJ_ANY;
626 }
627
628 if (required & VERT_NORM)
629 {
630 client_data = &ctx->Array.Normal;
631 if (fallback & VERT_NORM)
632 client_data = &ctx->Fallback.Normal;
633
634 if (client_data->Type == GL_FLOAT)
635 {
636 VSrc.Normal = &norm;
637 norm.flags = 0;
638 norm.data = (GLfloat (*)[3]) client_data->Ptr;
639 norm.stride = client_data->StrideB;
640 update |= VERT_NORM;
641 } else {
642 translate |= VERT_NORM;
643 }
644 }
645
646 if ( (required & VERT_EDGE) &&
647 (mode == GL_TRIANGLES ||
648 mode == GL_QUADS ||
649 mode == GL_POLYGON))
650 {
651 client_data = &ctx->Array.EdgeFlag;
652
653 if (fallback & VERT_EDGE)
654 client_data = &ctx->Fallback.EdgeFlag;
655
656 VSrc.EdgeFlag = &edge;
657 edge.data = (GLboolean *) client_data->Ptr;
658 edge.stride = client_data->StrideB;
659 edge.flags = VEC_NOT_WRITABLE|VEC_GOOD_STRIDE;
660 if (edge.stride != sizeof(GLubyte))
661 edge.flags ^= VEC_STRIDE_FLAGS;
662
663 update |= VERT_EDGE;
664 }
665
666 VB->Primitive = IM->Primitive;
667 VB->NextPrimitive = IM->NextPrimitive;
668 VB->MaterialMask = IM->MaterialMask;
669 VB->Material = IM->Material;
670 VB->BoundsPtr = 0;
671
672 while (remaining > 0) {
673 GLint vbspace = VB_MAX - VB_START;
674 GLuint count, n;
675
676
677 if (vbspace >= remaining) {
678 n = remaining;
679 VB->LastPrimitive = VB_START + n;
680 } else {
681 n = vbspace;
682 VB->LastPrimitive = VB_START;
683 }
684
685 VB->CullMode = 0;
686
687
688 /* Update pointers.
689 */
690 if (update) {
691 if (update & VERT_OBJ_ANY)
692 obj.start = VEC_ELT(&obj, GLfloat, start);
693
694 if (update & VERT_NORM)
695 norm.start = VEC_ELT(&norm, GLfloat, start);
696
697 if (update & VERT_EDGE)
698 edge.start = VEC_ELT(&edge, GLubyte, start);
699
700 if (update & VERT_RGBA)
701 col.start = VEC_ELT(&col, GLubyte, start);
702
703 if (update & VERT_INDEX)
704 index.start = VEC_ELT(&index, GLuint, start);
705
706 if (update & VERT_TEX0_ANY)
707 tc[0].start = VEC_ELT(&tc[0], GLfloat, start);
708
709 if (update & VERT_TEX1_ANY)
710 tc[1].start = VEC_ELT(&tc[1], GLfloat, start);
711 }
712
713
714 /* Translate data to fix up type and stride.
715 */
716 if (translate) {
717 if (translate & VERT_OBJ_ANY) {
718 ctx->Array.VertexFunc( IM->Obj + VB_START,
719 &ctx->Array.Vertex, start, n );
720 }
721
722 if (translate & VERT_NORM) {
723 ctx->Array.NormalFunc( IM->Normal + VB_START,
724 &ctx->Array.Normal, start, n );
725 }
726
727 if (translate & VERT_EDGE) {
728 ctx->Array.EdgeFlagFunc( IM->EdgeFlag + VB_START,
729 &ctx->Array.EdgeFlag, start, n );
730 }
731
732 if (translate & VERT_RGBA) {
733 ctx->Array.ColorFunc( IM->Color + VB_START,
734 &ctx->Array.Color, start, n );
735 }
736
737 if (translate & VERT_INDEX) {
738 ctx->Array.IndexFunc( IM->Index + VB_START,
739 &ctx->Array.Index, start, n );
740 }
741
742 if (translate & VERT_TEX0_ANY) {
743 IM->v.TexCoord[0].size = tc[0].size;
744 ctx->Array.TexCoordFunc[0]( IM->TexCoord[0] + VB_START,
745 &ctx->Array.TexCoord[0], start, n );
746 }
747
748 if (translate & VERT_TEX1_ANY) {
749 IM->v.TexCoord[1].size = tc[1].size;
750 ctx->Array.TexCoordFunc[1]( IM->TexCoord[1] + VB_START,
751 &ctx->Array.TexCoord[1], start, n );
752 }
753 }
754
755
756 VB->ObjPtr = VSrc.Obj;
757 VB->NormalPtr = VSrc.Normal;
758 VB->Color[0] = VB->Color[1] = VB->ColorPtr = VSrc.Color;
759 VB->IndexPtr = VSrc.Index;
760 VB->EdgeFlagPtr = VSrc.EdgeFlag;
761 VB->TexCoordPtr[0] = VSrc.TexCoord[0];
762 VB->TexCoordPtr[1] = VSrc.TexCoord[1];
763
764 VB->Flag = ctx->Array.Flag;
765 VB->AndFlag = ctx->Array.Flags;
766 VB->OrFlag = ctx->Array.Flags;
767
768 count = VB->Count = VB_START + n;
769
770 VB->ObjPtr->count = count;
771 VB->NormalPtr->count = count;
772 VB->ColorPtr->count = count;
773 VB->IndexPtr->count = count;
774 VB->EdgeFlagPtr->count = count;
775 VB->TexCoordPtr[0]->count = count;
776 VB->TexCoordPtr[1]->count = count;
777
778 VB->Flag[count] |= VERT_END_VB;
779 VB->Flag[VB_START] |= VERT_NORM;
780 /* VB->Flag[VB_START] |= (IM->Flag[vb_start] & VERT_MATERIAL); */
781
782 VB->NextPrimitive[VB->CopyStart] = VB->Count;
783 VB->Primitive[VB->CopyStart] = mode;
784
785 /* Transform and render.
786 */
787 gl_run_pipeline( VB );
788 gl_reset_vb( VB );
789
790 ctx->Array.Flag[count] = ctx->Array.Flags;
791 ctx->Array.Flag[VB_START] = ctx->Array.Flags;
792 IM->Flag[VB_START] = 0;
793
794 start += n;
795 remaining -= n;
796 }
797
798 ctx->CompileCVAFlag = relock;
799 }
800 else if (ctx->Array.Vertex.Enabled)
801 {
802 /* The GL_COMPILE and GL_COMPILE_AND_EXECUTE cases. These
803 * could be handled by the above code, but it gets a little
804 * complex.
805 */
806 /* No need to reset - never called from inside a display list */
807 gl_Begin( ctx, mode );
808 for (i=0;i<count;i++) {
809 gl_ArrayElement( ctx, start+i );
810 }
811 gl_End( ctx );
812 }
813 else
814 {
815 /* The degenerate case where vertices are not enabled - only
816 * need to process the very final array element, as all of the
817 * preceding ones would be overwritten anyway.
818 */
819 gl_Begin( ctx, mode );
820 gl_ArrayElement( ctx, start+count );
821 gl_End( ctx );
822 }
823 }
824
825
826
827 /* KW: Exactly fakes the effects of calling glArrayElement multiple times.
828 * Compilation is handled via. the IM->maybe_transform_vb() callback.
829 */
830 #define DRAW_ELT(FUNC, TYPE) \
831 static void FUNC( GLcontext *ctx, GLenum mode, \
832 TYPE *indices, GLuint count ) \
833 { \
834 GLuint i,j; \
835 \
836 if (count) gl_Begin( ctx, mode ); \
837 \
838 for (j = 0 ; j < count ; ) { \
839 GLuint nr = MIN2( VB_MAX, count - j + VB_START ); \
840 struct immediate *IM = ctx->input; \
841 GLuint sf = IM->Flag[VB_START]; \
842 \
843 for (i = VB_START ; i < nr ; i++) { \
844 IM->Elt[i] = (GLuint) *indices++; \
845 IM->Flag[i] = VERT_ELT; \
846 } \
847 \
848 if (j == 0) IM->Flag[VB_START] |= sf; \
849 \
850 IM->Count = nr; \
851 j += nr - VB_START; \
852 \
853 if (j == count) gl_End( ctx ); \
854 \
855 IM->maybe_transform_vb( IM ); \
856 } \
857 }
858
859 DRAW_ELT( draw_elt_ubyte, GLubyte )
860 DRAW_ELT( draw_elt_ushort, GLushort )
861 DRAW_ELT( draw_elt_uint, GLuint )
862
863
864 static GLuint natural_stride[0x10] =
865 {
866 sizeof(GLbyte), /* 0 */
867 sizeof(GLubyte), /* 1 */
868 sizeof(GLshort), /* 2 */
869 sizeof(GLushort), /* 3 */
870 sizeof(GLint), /* 4 */
871 sizeof(GLuint), /* 5 */
872 sizeof(GLfloat), /* 6 */
873 2 * sizeof(GLbyte), /* 7 */
874 3 * sizeof(GLbyte), /* 8 */
875 4 * sizeof(GLbyte), /* 9 */
876 sizeof(GLdouble), /* a */
877 0, /* b */
878 0, /* c */
879 0, /* d */
880 0, /* e */
881 0 /* f */
882 };
883
884 void GLAPIENTRY glDrawElements(CTX_ARG GLenum mode, GLsizei count,
885 GLenum type, const GLvoid *indices )
886 {
887 GLcontext *ctx;
888 struct gl_cva *cva;
889
890 GET_CONTEXT;
891 CHECK_CONTEXT;
892 ctx = CC;
893
894 cva = &ctx->CVA;
895 ASSERT_OUTSIDE_BEGIN_END_AND_FLUSH(ctx, "glDrawElements");
896
897 if (count<0) {
898 gl_error( ctx, GL_INVALID_VALUE, "glDrawElements(count)" );
899 return;
900 }
901
902 if (mode < 0 || mode > GL_POLYGON) {
903 gl_error( ctx, GL_INVALID_ENUM, "glDrawArrays(mode)" );
904 return;
905 }
906
907 if (type != GL_UNSIGNED_INT && type != GL_UNSIGNED_BYTE && type != GL_UNSIGNED_SHORT)
908 {
909 gl_error( ctx, GL_INVALID_ENUM, "glDrawElements(type)" );
910 return;
911 }
912
913 if (ctx->NewState)
914 gl_update_state(ctx);
915
916 if (ctx->CompileCVAFlag)
917 {
918 #if defined(MESA_CVA_PROF)
919 force_init_prof();
920 #endif
921
922 /* Treat VERT_ELT like a special client array.
923 */
924 ctx->Array.NewArrayState |= VERT_ELT;
925 ctx->Array.Summary |= VERT_ELT;
926 ctx->Array.Flags |= VERT_ELT;
927
928 cva->elt_mode = mode;
929 cva->elt_count = count;
930 cva->Elt.Type = type;
931 cva->Elt.Ptr = (void *) indices;
932 cva->Elt.StrideB = natural_stride[TYPE_IDX(type)];
933 cva->EltFunc = gl_trans_1ui_tab[TYPE_IDX(type)];
934
935 if (!cva->pre.pipeline_valid)
936 gl_build_precalc_pipeline( ctx );
937 else if (MESA_VERBOSE & VERBOSE_PIPELINE)
938 fprintf(stderr, ": dont rebuild\n");
939
940 gl_cva_force_precalc( ctx );
941
942 /* Did we 'precalculate' the render op?
943 */
944 if (ctx->CVA.pre.ops & PIPE_OP_RENDER) {
945 ctx->Array.NewArrayState |= VERT_ELT;
946 ctx->Array.Summary &= ~VERT_ELT;
947 ctx->Array.Flags &= ~VERT_ELT;
948 return;
949 }
950
951 if ( (MESA_VERBOSE&VERBOSE_VARRAY) )
952 printf("using immediate\n");
953 }
954
955
956 /* Otherwise, have to use the immediate path to render.
957 */
958 switch (type) {
959 case GL_UNSIGNED_BYTE:
960 {
961 GLubyte *ub_indices = (GLubyte *) indices;
962 if (ctx->Array.Summary & VERT_OBJ_ANY) {
963 draw_elt_ubyte( ctx, mode, ub_indices, count );
964 } else {
965 gl_ArrayElement( ctx, (GLuint) ub_indices[count-1] );
966 }
967 }
968 break;
969 case GL_UNSIGNED_SHORT:
970 {
971 GLushort *us_indices = (GLushort *) indices;
972 if (ctx->Array.Summary & VERT_OBJ_ANY) {
973 draw_elt_ushort( ctx, mode, us_indices, count );
974 } else {
975 gl_ArrayElement( ctx, (GLuint) us_indices[count-1] );
976 }
977 }
978 break;
979 case GL_UNSIGNED_INT:
980 {
981 GLuint *ui_indices = (GLuint *) indices;
982 if (ctx->Array.Summary & VERT_OBJ_ANY) {
983 draw_elt_uint( ctx, mode, ui_indices, count );
984 } else {
985 gl_ArrayElement( ctx, ui_indices[count-1] );
986 }
987 }
988 break;
989 default:
990 gl_error( ctx, GL_INVALID_ENUM, "glDrawElements(type)" );
991 break;
992 }
993
994 if (ctx->CompileCVAFlag) {
995 ctx->Array.NewArrayState |= VERT_ELT;
996 ctx->Array.Summary &= ~VERT_ELT;
997 }
998 }
999
1000
1001
1002 void GLAPIENTRY glInterleavedArrays(CTX_ARG GLenum format, GLsizei stride,
1003 const GLvoid *pointer )
1004 {
1005 GLcontext *ctx;
1006 GLboolean tflag, cflag, nflag; /* enable/disable flags */
1007 GLint tcomps, ccomps, vcomps; /* components per texcoord, color, vertex */
1008
1009 GLenum ctype; /* color type */
1010 GLint coffset, noffset, voffset;/* color, normal, vertex offsets */
1011 GLint defstride; /* default stride */
1012 GLint c, f;
1013 GLint coordUnitSave;
1014
1015 GET_CONTEXT;
1016 CHECK_CONTEXT;
1017 ctx = CC;
1018
1019
1020 f = sizeof(GLfloat);
1021 c = f * ((4*sizeof(GLubyte) + (f-1)) / f);
1022
1023 if (stride<0) {
1024 gl_error( ctx, GL_INVALID_VALUE, "glInterleavedArrays(stride)" );
1025 return;
1026 }
1027
1028 switch (format) {
1029 case GL_V2F:
1030 tflag = GL_FALSE; cflag = GL_FALSE; nflag = GL_FALSE;
1031 tcomps = 0; ccomps = 0; vcomps = 2;
1032 voffset = 0;
1033 defstride = 2*f;
1034 break;
1035 case GL_V3F:
1036 tflag = GL_FALSE; cflag = GL_FALSE; nflag = GL_FALSE;
1037 tcomps = 0; ccomps = 0; vcomps = 3;
1038 voffset = 0;
1039 defstride = 3*f;
1040 break;
1041 case GL_C4UB_V2F:
1042 tflag = GL_FALSE; cflag = GL_TRUE; nflag = GL_FALSE;
1043 tcomps = 0; ccomps = 4; vcomps = 2;
1044 ctype = GL_UNSIGNED_BYTE;
1045 coffset = 0;
1046 voffset = c;
1047 defstride = c + 2*f;
1048 break;
1049 case GL_C4UB_V3F:
1050 tflag = GL_FALSE; cflag = GL_TRUE; nflag = GL_FALSE;
1051 tcomps = 0; ccomps = 4; vcomps = 3;
1052 ctype = GL_UNSIGNED_BYTE;
1053 coffset = 0;
1054 voffset = c;
1055 defstride = c + 3*f;
1056 break;
1057 case GL_C3F_V3F:
1058 tflag = GL_FALSE; cflag = GL_TRUE; nflag = GL_FALSE;
1059 tcomps = 0; ccomps = 3; vcomps = 3;
1060 ctype = GL_FLOAT;
1061 coffset = 0;
1062 voffset = 3*f;
1063 defstride = 6*f;
1064 break;
1065 case GL_N3F_V3F:
1066 tflag = GL_FALSE; cflag = GL_FALSE; nflag = GL_TRUE;
1067 tcomps = 0; ccomps = 0; vcomps = 3;
1068 noffset = 0;
1069 voffset = 3*f;
1070 defstride = 6*f;
1071 break;
1072 case GL_C4F_N3F_V3F:
1073 tflag = GL_FALSE; cflag = GL_TRUE; nflag = GL_TRUE;
1074 tcomps = 0; ccomps = 4; vcomps = 3;
1075 ctype = GL_FLOAT;
1076 coffset = 0;
1077 noffset = 4*f;
1078 voffset = 7*f;
1079 defstride = 10*f;
1080 break;
1081 case GL_T2F_V3F:
1082 tflag = GL_TRUE; cflag = GL_FALSE; nflag = GL_FALSE;
1083 tcomps = 2; ccomps = 0; vcomps = 3;
1084 voffset = 2*f;
1085 defstride = 5*f;
1086 break;
1087 case GL_T4F_V4F:
1088 tflag = GL_TRUE; cflag = GL_FALSE; nflag = GL_FALSE;
1089 tcomps = 4; ccomps = 0; vcomps = 4;
1090 voffset = 4*f;
1091 defstride = 8*f;
1092 break;
1093 case GL_T2F_C4UB_V3F:
1094 tflag = GL_TRUE; cflag = GL_TRUE; nflag = GL_FALSE;
1095 tcomps = 2; ccomps = 4; vcomps = 3;
1096 ctype = GL_UNSIGNED_BYTE;
1097 coffset = 2*f;
1098 voffset = c+2*f;
1099 defstride = c+5*f;
1100 break;
1101 case GL_T2F_C3F_V3F:
1102 tflag = GL_TRUE; cflag = GL_TRUE; nflag = GL_FALSE;
1103 tcomps = 2; ccomps = 3; vcomps = 3;
1104 ctype = GL_FLOAT;
1105 coffset = 2*f;
1106 voffset = 5*f;
1107 defstride = 8*f;
1108 break;
1109 case GL_T2F_N3F_V3F:
1110 tflag = GL_TRUE; cflag = GL_FALSE; nflag = GL_TRUE;
1111 tcomps = 2; ccomps = 0; vcomps = 3;
1112 noffset = 2*f;
1113 voffset = 5*f;
1114 defstride = 8*f;
1115 break;
1116 case GL_T2F_C4F_N3F_V3F:
1117 tflag = GL_TRUE; cflag = GL_TRUE; nflag = GL_TRUE;
1118 tcomps = 2; ccomps = 4; vcomps = 3;
1119 ctype = GL_FLOAT;
1120 coffset = 2*f;
1121 noffset = 6*f;
1122 voffset = 9*f;
1123 defstride = 12*f;
1124 break;
1125 case GL_T4F_C4F_N3F_V4F:
1126 tflag = GL_TRUE; cflag = GL_TRUE; nflag = GL_TRUE;
1127 tcomps = 4; ccomps = 4; vcomps = 4;
1128 ctype = GL_FLOAT;
1129 coffset = 4*f;
1130 noffset = 8*f;
1131 voffset = 11*f;
1132 defstride = 15*f;
1133 break;
1134 default:
1135 gl_error( ctx, GL_INVALID_ENUM, "glInterleavedArrays(format)" );
1136 return;
1137 }
1138
1139 if (stride==0) {
1140 stride = defstride;
1141 }
1142
1143 gl_DisableClientState( ctx, GL_EDGE_FLAG_ARRAY );
1144 gl_DisableClientState( ctx, GL_INDEX_ARRAY );
1145
1146 /* Texcoords */
1147 coordUnitSave = ctx->Array.ActiveTexture;
1148 if (tflag) {
1149 GLint i;
1150 GLint factor = ctx->Array.TexCoordInterleaveFactor;
1151 for (i = 0; i < factor; i++) {
1152 gl_ActiveTexture( ctx, (GLenum) (GL_TEXTURE0_ARB + i) );
1153 gl_EnableClientState( ctx, GL_TEXTURE_COORD_ARRAY );
1154 glTexCoordPointer(CTX_PRM tcomps, GL_FLOAT, stride,
1155 (GLubyte *) pointer + i * coffset );
1156 }
1157 for (i = factor; i < ctx->Const.MaxTextureUnits; i++) {
1158 gl_ActiveTexture( ctx, (GLenum) (GL_TEXTURE0_ARB + i) );
1159 gl_DisableClientState( ctx, GL_TEXTURE_COORD_ARRAY );
1160 }
1161 }
1162 else {
1163 GLint i;
1164 for (i = 0; i < ctx->Const.MaxTextureUnits; i++) {
1165 gl_ActiveTexture( ctx, (GLenum) (GL_TEXTURE0_ARB + i) );
1166 gl_DisableClientState( ctx, GL_TEXTURE_COORD_ARRAY );
1167 }
1168 }
1169 /* Restore texture coordinate unit index */
1170 gl_ActiveTexture( ctx, (GLenum) (GL_TEXTURE0_ARB + coordUnitSave) );
1171
1172
1173 /* Color */
1174 if (cflag) {
1175 gl_EnableClientState( ctx, GL_COLOR_ARRAY );
1176 glColorPointer(CTX_PRM ccomps, ctype, stride,
1177 (GLubyte*) pointer + coffset );
1178 }
1179 else {
1180 gl_DisableClientState( ctx, GL_COLOR_ARRAY );
1181 }
1182
1183
1184 /* Normals */
1185 if (nflag) {
1186 gl_EnableClientState( ctx, GL_NORMAL_ARRAY );
1187 glNormalPointer(CTX_PRM GL_FLOAT, stride,
1188 (GLubyte*) pointer + noffset );
1189 }
1190 else {
1191 gl_DisableClientState( ctx, GL_NORMAL_ARRAY );
1192 }
1193
1194 gl_EnableClientState( ctx, GL_VERTEX_ARRAY );
1195 glVertexPointer(CTX_PRM vcomps, GL_FLOAT, stride,
1196 (GLubyte *) pointer + voffset );
1197 }
1198
1199
1200
1201 void GLAPIENTRY glDrawRangeElements(CTX_ARG GLenum mode, GLuint start,
1202 GLuint end, GLsizei count,
1203 GLenum type, const GLvoid *indices )
1204 {
1205 GLcontext *ctx;
1206 GET_CONTEXT;
1207 CHECK_CONTEXT;
1208 ctx = CC;
1209
1210 if (end < start) {
1211 gl_error(ctx, GL_INVALID_VALUE, "glDrawRangeElements( end < start )");
1212 return;
1213 }
1214
1215 if (!ctx->Array.LockCount && 2*count > 3*(end-start)) {
1216 glLockArraysEXT(CTX_PRM start, end );
1217 glDrawElements(CTX_PRM mode, count, type, indices );
1218 glUnlockArraysEXT(CTX_VPRM );
1219 } else {
1220 glDrawElements(CTX_PRM mode, count, type, indices );
1221 }
1222 }
1223
1224
1225
1226 void gl_update_client_state( GLcontext *ctx )
1227 {
1228 static GLuint sz_flags[5] = { 0,
1229 0,
1230 VERT_OBJ_2,
1231 VERT_OBJ_23,
1232 VERT_OBJ_234 };
1233
1234 static GLuint tc_flags[5] = { 0,
1235 VERT_TEX0_1,
1236 VERT_TEX0_12,
1237 VERT_TEX0_123,
1238 VERT_TEX0_1234 };
1239
1240 ctx->Array.Flags = 0;
1241 ctx->Array.Summary = 0;
1242 ctx->input->ArrayIncr = 0;
1243
1244 if (ctx->Array.Normal.Enabled) ctx->Array.Flags |= VERT_NORM;
1245 if (ctx->Array.Color.Enabled) ctx->Array.Flags |= VERT_RGBA;
1246 if (ctx->Array.Index.Enabled) ctx->Array.Flags |= VERT_INDEX;
1247 if (ctx->Array.EdgeFlag.Enabled) ctx->Array.Flags |= VERT_EDGE;
1248 if (ctx->Array.Vertex.Enabled) {
1249 ctx->Array.Flags |= sz_flags[ctx->Array.Vertex.Size];
1250 ctx->input->ArrayIncr = 1;
1251 }
1252 if (ctx->Array.TexCoord[0].Enabled) {
1253 ctx->Array.Flags |= tc_flags[ctx->Array.TexCoord[0].Size];
1254 }
1255 if (ctx->Array.TexCoord[1].Enabled) {
1256 ctx->Array.Flags |= (tc_flags[ctx->Array.TexCoord[1].Size] << NR_TEXSIZE_BITS);
1257 }
1258
1259 /* Not really important any more:
1260 */
1261 ctx->Array.Summary = ctx->Array.Flags & VERT_DATA;
1262 ctx->input->ArrayAndFlags = ~ctx->Array.Flags;
1263 ctx->input->ArrayEltFlush = !(ctx->CompileCVAFlag);
1264 }
1265