source: trunk/src/opengl/mesa/varray.c@ 3100

Last change on this file since 3100 was 2962, checked in by jeroen, 25 years ago

* empty log message *

File size: 32.2 KB
Line 
1/* $Id: varray.c,v 1.2 2000-03-01 18:49:38 jeroen 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 "types.h"
38#include "context.h"
39#include "api.h"
40#include "cva.h"
41#include "enable.h"
42#include "enums.h"
43#include "dlist.h"
44#include "light.h"
45#include "macros.h"
46#include "mmath.h"
47#include "pipeline.h"
48#include "texstate.h"
49#include "translate.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
68void 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
123void 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
175void 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
240void 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
287void 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
349void 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 */
378void 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 */
410void 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
465 for (i = start ; i < count ; i++)
466 if (flags[i] & VERT_ELT)
467 flags[i] |= translate;
468
469}
470
471
472
473void gl_DrawArrays( GLcontext *ctx, GLenum mode, GLint start, GLsizei count )
474{
475 struct vertex_buffer *VB = ctx->VB;
476 GLint i;
477
478 ASSERT_OUTSIDE_BEGIN_END_AND_FLUSH(ctx, "glDrawArrays");
479
480 if (count<0) {
481 gl_error( ctx, GL_INVALID_VALUE, "glDrawArrays(count)" );
482 return;
483 }
484
485 if (!ctx->CompileFlag && ctx->Array.Vertex.Enabled)
486 {
487 GLint remaining = count;
488 GLint i;
489 struct gl_client_array *Normal;
490 struct gl_client_array *Color;
491 struct gl_client_array *Index;
492 struct gl_client_array *TexCoord[MAX_TEXTURE_UNITS];
493 struct gl_client_array *EdgeFlag;
494 struct immediate *IM = VB->IM;
495 struct gl_pipeline *elt = &ctx->CVA.elt;
496 GLboolean relock;
497 GLuint fallback, required;
498
499 if (ctx->NewState)
500 gl_update_state( ctx );
501
502 /* Just turn off cva on this path. Could be useful for multipass
503 * rendering to keep it turned on.
504 */
505 relock = ctx->CompileCVAFlag;
506
507 if (relock) {
508 ctx->CompileCVAFlag = 0;
509 elt->pipeline_valid = 0;
510 }
511
512 if (!elt->pipeline_valid)
513 gl_build_immediate_pipeline( ctx );
514
515 required = elt->inputs;
516 fallback = (elt->inputs & ~ctx->Array.Summary);
517
518 /* The translate function doesn't do anything about size. It
519 * just ensures that type and stride come out right.
520 */
521 IM->v.Obj.size = ctx->Array.Vertex.Size;
522
523 if (required & VERT_RGBA)
524 {
525 Color = &ctx->Array.Color;
526 if (fallback & VERT_RGBA) {
527 Color = &ctx->Fallback.Color;
528 ctx->Array.ColorFunc =
529 gl_trans_4ub_tab[4][TYPE_IDX(GL_UNSIGNED_BYTE)];
530 }
531 }
532
533 if (required & VERT_INDEX)
534 {
535 Index = &ctx->Array.Index;
536 if (fallback & VERT_INDEX) {
537 Index = &ctx->Fallback.Index;
538 ctx->Array.IndexFunc = gl_trans_1ui_tab[TYPE_IDX(GL_UNSIGNED_INT)];
539 }
540 }
541
542 for (i = 0 ; i < MAX_TEXTURE_UNITS ; i++)
543 {
544 GLuint flag = VERT_TEX_ANY(i);
545
546 if (required & flag) {
547 TexCoord[i] = &ctx->Array.TexCoord[i];
548
549 if (fallback & flag)
550 {
551 TexCoord[i] = &ctx->Fallback.TexCoord[i];
552 TexCoord[i]->Size = gl_texcoord_size( ctx->Current.Flag, i );
553
554 ctx->Array.TexCoordFunc[i] =
555 gl_trans_4f_tab[TexCoord[i]->Size][TYPE_IDX(GL_FLOAT)];
556 }
557 }
558 }
559
560 if (ctx->Array.Flags != ctx->Array.Flag[0])
561 for (i = 0 ; i < VB_MAX ; i++)
562 ctx->Array.Flag[i] = ctx->Array.Flags;
563
564
565 if (required & VERT_NORM)
566 {
567 Normal = &ctx->Array.Normal;
568 if (fallback & VERT_NORM) {
569 Normal = &ctx->Fallback.Normal;
570 ctx->Array.NormalFunc = gl_trans_3f_tab[TYPE_IDX(GL_FLOAT)];
571 }
572 }
573
574 if ( required & VERT_EDGE )
575 {
576 if (mode == GL_TRIANGLES ||
577 mode == GL_QUADS ||
578 mode == GL_POLYGON)
579 {
580 EdgeFlag = &ctx->Array.EdgeFlag;
581 if (fallback & VERT_EDGE) {
582 EdgeFlag = &ctx->Fallback.EdgeFlag;
583 ctx->Array.EdgeFlagFunc =
584 gl_trans_1ub_tab[TYPE_IDX(GL_UNSIGNED_BYTE)];
585 }
586 }
587 else
588 required &= ~VERT_EDGE;
589 }
590
591 VB->Primitive = IM->Primitive;
592 VB->NextPrimitive = IM->NextPrimitive;
593 VB->MaterialMask = IM->MaterialMask;
594 VB->Material = IM->Material;
595 VB->BoundsPtr = 0;
596
597 while (remaining > 0) {
598 GLint vbspace = VB_MAX - VB_START;
599 GLuint count, n;
600
601 if (vbspace >= remaining) {
602 n = remaining;
603 VB->LastPrimitive = VB_START + n;
604 } else {
605 n = vbspace;
606 VB->LastPrimitive = VB_START;
607 }
608
609 VB->CullMode = 0;
610
611 ctx->Array.VertexFunc( IM->Obj + VB_START,
612 &ctx->Array.Vertex, start, n );
613
614 if (required & VERT_NORM) {
615 ctx->Array.NormalFunc( IM->Normal + VB_START,
616 Normal, start, n );
617 }
618
619 if (required & VERT_EDGE) {
620 ctx->Array.EdgeFlagFunc( IM->EdgeFlag + VB_START,
621 EdgeFlag, start, n );
622 }
623
624 if (required & VERT_RGBA) {
625 ctx->Array.ColorFunc( IM->Color + VB_START,
626 Color, start, n );
627 }
628
629 if (required & VERT_INDEX) {
630 ctx->Array.IndexFunc( IM->Index + VB_START,
631 Index, start, n );
632 }
633
634 if (required & VERT_TEX0_ANY) {
635 IM->v.TexCoord[0].size = TexCoord[0]->Size;
636 ctx->Array.TexCoordFunc[0]( IM->TexCoord[0] + VB_START,
637 TexCoord[0], start, n );
638 }
639
640 if (required & VERT_TEX1_ANY) {
641 IM->v.TexCoord[1].size = TexCoord[1]->Size;
642 ctx->Array.TexCoordFunc[1]( IM->TexCoord[1] + VB_START,
643 TexCoord[1], start, n );
644 }
645
646 VB->ObjPtr = &IM->v.Obj;
647 VB->NormalPtr = &IM->v.Normal;
648 VB->ColorPtr = &IM->v.Color;
649 VB->Color[0] = VB->Color[1] = VB->ColorPtr;
650 VB->IndexPtr = &IM->v.Index;
651 VB->EdgeFlagPtr = &IM->v.EdgeFlag;
652 VB->TexCoordPtr[0] = &IM->v.TexCoord[0];
653 VB->TexCoordPtr[1] = &IM->v.TexCoord[1];
654
655 VB->Flag = ctx->Array.Flag;
656 VB->OrFlag = ctx->Array.Flags;
657
658 VB->Start = IM->Start = VB_START;
659 count = VB->Count = IM->Count = VB_START + n;
660
661#define RESET_VEC(v, t, s, c) (v.start = t v.data[s], v.count = c)
662
663 RESET_VEC(IM->v.Obj, (GLfloat *), VB_START, count);
664 RESET_VEC(IM->v.Normal, (GLfloat *), VB_START, count);
665 RESET_VEC(IM->v.TexCoord[0], (GLfloat *), VB_START, count);
666 RESET_VEC(IM->v.TexCoord[1], (GLfloat *), VB_START, count);
667 RESET_VEC(IM->v.Index, &, VB_START, count);
668 RESET_VEC(IM->v.Elt, &, VB_START, count);
669 RESET_VEC(IM->v.EdgeFlag, &, VB_START, count);
670 RESET_VEC(IM->v.Color, (GLubyte *), VB_START, count);
671 RESET_VEC(VB->Clip, (GLfloat *), VB_START, count);
672 RESET_VEC(VB->Eye, (GLfloat *), VB_START, count);
673 RESET_VEC(VB->Win, (GLfloat *), VB_START, count);
674 RESET_VEC(VB->BColor, (GLubyte *), VB_START, count);
675 RESET_VEC(VB->BIndex, &, VB_START, count);
676
677 VB->NextPrimitive[VB->CopyStart] = VB->Count;
678 VB->Primitive[VB->CopyStart] = mode;
679 ctx->Array.Flag[count] |= VERT_END_VB;
680
681 /* Transform and render.
682 */
683 gl_run_pipeline( VB );
684 gl_reset_vb( VB );
685
686 ctx->Array.Flag[count] = ctx->Array.Flags;
687 ctx->Array.Flag[VB_START] = ctx->Array.Flags;
688
689 start += n;
690 remaining -= n;
691 }
692
693 gl_reset_input( ctx );
694
695 if (relock) {
696 ctx->CompileCVAFlag = relock;
697 elt->pipeline_valid = 0;
698 }
699 }
700 else if (ctx->Array.Vertex.Enabled)
701 {
702 /* The GL_COMPILE and GL_COMPILE_AND_EXECUTE cases. These
703 * could be handled by the above code, but it gets a little
704 * complex. The generated list is still of good quality
705 * this way.
706 */
707 gl_Begin( ctx, mode );
708 for (i=0;i<count;i++) {
709 gl_ArrayElement( ctx, start+i );
710 }
711 gl_End( ctx );
712 }
713 else
714 {
715 /* The degenerate case where vertices are not enabled - only
716 * need to process the very final array element, as all of the
717 * preceding ones would be overwritten anyway.
718 */
719 gl_Begin( ctx, mode );
720 gl_ArrayElement( ctx, start+count );
721 gl_End( ctx );
722 }
723}
724
725
726
727/* KW: Exactly fakes the effects of calling glArrayElement multiple times.
728 * Compilation is handled via. the IM->maybe_transform_vb() callback.
729 */
730#if 1
731#define DRAW_ELT(FUNC, TYPE) \
732static void FUNC( GLcontext *ctx, GLenum mode, \
733 TYPE *indices, GLuint count ) \
734{ \
735 GLuint i,j; \
736 \
737 gl_Begin( ctx, mode ); \
738 \
739 for (j = 0 ; j < count ; ) { \
740 struct immediate *IM = ctx->input; \
741 GLuint start = IM->Start; \
742 GLuint nr = MIN2( VB_MAX, count - j + start ); \
743 GLuint sf = IM->Flag[start]; \
744 IM->FlushElt |= IM->ArrayEltFlush; \
745 \
746 for (i = start ; i < nr ; i++) { \
747 IM->Elt[i] = (GLuint) *indices++; \
748 IM->Flag[i] = VERT_ELT; \
749 } \
750 \
751 if (j == 0) IM->Flag[start] |= sf; \
752 \
753 IM->Count = nr; \
754 j += nr - start; \
755 \
756 if (j == count) gl_End( ctx ); \
757 IM->maybe_transform_vb( IM ); \
758 } \
759}
760#else
761#define DRAW_ELT(FUNC, TYPE) \
762static void FUNC( GLcontext *ctx, GLenum mode, \
763 TYPE *indices, GLuint count ) \
764{ \
765 int i; \
766 glBegin(mode); \
767 for (i = 0 ; i < count ; i++) \
768 glArrayElement( indices[i] ); \
769 glEnd(); \
770}
771#endif
772
773
774DRAW_ELT( draw_elt_ubyte, GLubyte )
775DRAW_ELT( draw_elt_ushort, GLushort )
776DRAW_ELT( draw_elt_uint, GLuint )
777
778
779static GLuint natural_stride[0x10] =
780{
781 sizeof(GLbyte), /* 0 */
782 sizeof(GLubyte), /* 1 */
783 sizeof(GLshort), /* 2 */
784 sizeof(GLushort), /* 3 */
785 sizeof(GLint), /* 4 */
786 sizeof(GLuint), /* 5 */
787 sizeof(GLfloat), /* 6 */
788 2 * sizeof(GLbyte), /* 7 */
789 3 * sizeof(GLbyte), /* 8 */
790 4 * sizeof(GLbyte), /* 9 */
791 sizeof(GLdouble), /* a */
792 0, /* b */
793 0, /* c */
794 0, /* d */
795 0, /* e */
796 0 /* f */
797};
798
799void GLAPIENTRY glDrawElements(CTX_ARG GLenum mode, GLsizei count,
800 GLenum type, const GLvoid *indices )
801{
802 GLcontext *ctx;
803 struct gl_cva *cva;
804
805 GET_CONTEXT;
806 CHECK_CONTEXT;
807 ctx = CC;
808
809 cva = &ctx->CVA;
810 ASSERT_OUTSIDE_BEGIN_END_AND_FLUSH(ctx, "glDrawElements");
811
812 if (count <= 0) {
813 if (count < 0)
814 gl_error( ctx, GL_INVALID_VALUE, "glDrawElements(count)" );
815 return;
816 }
817
818 if (mode < 0 || mode > GL_POLYGON) {
819 gl_error( ctx, GL_INVALID_ENUM, "glDrawArrays(mode)" );
820 return;
821 }
822
823 if (type != GL_UNSIGNED_INT && type != GL_UNSIGNED_BYTE && type != GL_UNSIGNED_SHORT)
824 {
825 gl_error( ctx, GL_INVALID_ENUM, "glDrawElements(type)" );
826 return;
827 }
828
829 if (ctx->NewState)
830 gl_update_state(ctx);
831
832 if (ctx->CompileCVAFlag)
833 {
834#if defined(MESA_CVA_PROF)
835 force_init_prof();
836#endif
837
838 /* Treat VERT_ELT like a special client array.
839 */
840 ctx->Array.NewArrayState |= VERT_ELT;
841 ctx->Array.Summary |= VERT_ELT;
842 ctx->Array.Flags |= VERT_ELT;
843
844 cva->elt_mode = mode;
845 cva->elt_count = count;
846 cva->Elt.Type = type;
847 cva->Elt.Ptr = (void *) indices;
848 cva->Elt.StrideB = natural_stride[TYPE_IDX(type)];
849 cva->EltFunc = gl_trans_1ui_tab[TYPE_IDX(type)];
850
851 if (!cva->pre.pipeline_valid)
852 gl_build_precalc_pipeline( ctx );
853 else if (MESA_VERBOSE & VERBOSE_PIPELINE)
854 fprintf(stderr, ": dont rebuild\n");
855
856 gl_cva_force_precalc( ctx );
857
858 /* Did we 'precalculate' the render op?
859 */
860 if (ctx->CVA.pre.ops & PIPE_OP_RENDER) {
861 ctx->Array.NewArrayState |= VERT_ELT;
862 ctx->Array.Summary &= ~VERT_ELT;
863 ctx->Array.Flags &= ~VERT_ELT;
864 return;
865 }
866
867 if ( (MESA_VERBOSE&VERBOSE_VARRAY) )
868 printf("using immediate\n");
869 }
870
871
872 /* Otherwise, have to use the immediate path to render.
873 */
874 switch (type) {
875 case GL_UNSIGNED_BYTE:
876 {
877 GLubyte *ub_indices = (GLubyte *) indices;
878 if (ctx->Array.Summary & VERT_OBJ_ANY) {
879 draw_elt_ubyte( ctx, mode, ub_indices, count );
880 } else {
881 gl_ArrayElement( ctx, (GLuint) ub_indices[count-1] );
882 }
883 }
884 break;
885 case GL_UNSIGNED_SHORT:
886 {
887 GLushort *us_indices = (GLushort *) indices;
888 if (ctx->Array.Summary & VERT_OBJ_ANY) {
889 draw_elt_ushort( ctx, mode, us_indices, count );
890 } else {
891 gl_ArrayElement( ctx, (GLuint) us_indices[count-1] );
892 }
893 }
894 break;
895 case GL_UNSIGNED_INT:
896 {
897 GLuint *ui_indices = (GLuint *) indices;
898 if (ctx->Array.Summary & VERT_OBJ_ANY) {
899 draw_elt_uint( ctx, mode, ui_indices, count );
900 } else {
901 gl_ArrayElement( ctx, ui_indices[count-1] );
902 }
903 }
904 break;
905 default:
906 gl_error( ctx, GL_INVALID_ENUM, "glDrawElements(type)" );
907 break;
908 }
909
910 if (ctx->CompileCVAFlag) {
911 ctx->Array.NewArrayState |= VERT_ELT;
912 ctx->Array.Summary &= ~VERT_ELT;
913 }
914}
915
916
917
918void GLAPIENTRY glInterleavedArrays(CTX_ARG GLenum format, GLsizei stride,
919 const GLvoid *pointer )
920{
921 GLcontext *ctx;
922 GLboolean tflag, cflag, nflag; /* enable/disable flags */
923 GLint tcomps, ccomps, vcomps; /* components per texcoord, color, vertex */
924
925 GLenum ctype; /* color type */
926 GLint coffset, noffset, voffset;/* color, normal, vertex offsets */
927 GLint defstride; /* default stride */
928 GLint c, f;
929 GLint coordUnitSave;
930
931 GET_CONTEXT;
932 CHECK_CONTEXT;
933 ctx = CC;
934
935
936 f = sizeof(GLfloat);
937 c = f * ((4*sizeof(GLubyte) + (f-1)) / f);
938
939 if (stride<0) {
940 gl_error( ctx, GL_INVALID_VALUE, "glInterleavedArrays(stride)" );
941 return;
942 }
943
944 switch (format) {
945 case GL_V2F:
946 tflag = GL_FALSE; cflag = GL_FALSE; nflag = GL_FALSE;
947 tcomps = 0; ccomps = 0; vcomps = 2;
948 voffset = 0;
949 defstride = 2*f;
950 break;
951 case GL_V3F:
952 tflag = GL_FALSE; cflag = GL_FALSE; nflag = GL_FALSE;
953 tcomps = 0; ccomps = 0; vcomps = 3;
954 voffset = 0;
955 defstride = 3*f;
956 break;
957 case GL_C4UB_V2F:
958 tflag = GL_FALSE; cflag = GL_TRUE; nflag = GL_FALSE;
959 tcomps = 0; ccomps = 4; vcomps = 2;
960 ctype = GL_UNSIGNED_BYTE;
961 coffset = 0;
962 voffset = c;
963 defstride = c + 2*f;
964 break;
965 case GL_C4UB_V3F:
966 tflag = GL_FALSE; cflag = GL_TRUE; nflag = GL_FALSE;
967 tcomps = 0; ccomps = 4; vcomps = 3;
968 ctype = GL_UNSIGNED_BYTE;
969 coffset = 0;
970 voffset = c;
971 defstride = c + 3*f;
972 break;
973 case GL_C3F_V3F:
974 tflag = GL_FALSE; cflag = GL_TRUE; nflag = GL_FALSE;
975 tcomps = 0; ccomps = 3; vcomps = 3;
976 ctype = GL_FLOAT;
977 coffset = 0;
978 voffset = 3*f;
979 defstride = 6*f;
980 break;
981 case GL_N3F_V3F:
982 tflag = GL_FALSE; cflag = GL_FALSE; nflag = GL_TRUE;
983 tcomps = 0; ccomps = 0; vcomps = 3;
984 noffset = 0;
985 voffset = 3*f;
986 defstride = 6*f;
987 break;
988 case GL_C4F_N3F_V3F:
989 tflag = GL_FALSE; cflag = GL_TRUE; nflag = GL_TRUE;
990 tcomps = 0; ccomps = 4; vcomps = 3;
991 ctype = GL_FLOAT;
992 coffset = 0;
993 noffset = 4*f;
994 voffset = 7*f;
995 defstride = 10*f;
996 break;
997 case GL_T2F_V3F:
998 tflag = GL_TRUE; cflag = GL_FALSE; nflag = GL_FALSE;
999 tcomps = 2; ccomps = 0; vcomps = 3;
1000 voffset = 2*f;
1001 defstride = 5*f;
1002 break;
1003 case GL_T4F_V4F:
1004 tflag = GL_TRUE; cflag = GL_FALSE; nflag = GL_FALSE;
1005 tcomps = 4; ccomps = 0; vcomps = 4;
1006 voffset = 4*f;
1007 defstride = 8*f;
1008 break;
1009 case GL_T2F_C4UB_V3F:
1010 tflag = GL_TRUE; cflag = GL_TRUE; nflag = GL_FALSE;
1011 tcomps = 2; ccomps = 4; vcomps = 3;
1012 ctype = GL_UNSIGNED_BYTE;
1013 coffset = 2*f;
1014 voffset = c+2*f;
1015 defstride = c+5*f;
1016 break;
1017 case GL_T2F_C3F_V3F:
1018 tflag = GL_TRUE; cflag = GL_TRUE; nflag = GL_FALSE;
1019 tcomps = 2; ccomps = 3; vcomps = 3;
1020 ctype = GL_FLOAT;
1021 coffset = 2*f;
1022 voffset = 5*f;
1023 defstride = 8*f;
1024 break;
1025 case GL_T2F_N3F_V3F:
1026 tflag = GL_TRUE; cflag = GL_FALSE; nflag = GL_TRUE;
1027 tcomps = 2; ccomps = 0; vcomps = 3;
1028 noffset = 2*f;
1029 voffset = 5*f;
1030 defstride = 8*f;
1031 break;
1032 case GL_T2F_C4F_N3F_V3F:
1033 tflag = GL_TRUE; cflag = GL_TRUE; nflag = GL_TRUE;
1034 tcomps = 2; ccomps = 4; vcomps = 3;
1035 ctype = GL_FLOAT;
1036 coffset = 2*f;
1037 noffset = 6*f;
1038 voffset = 9*f;
1039 defstride = 12*f;
1040 break;
1041 case GL_T4F_C4F_N3F_V4F:
1042 tflag = GL_TRUE; cflag = GL_TRUE; nflag = GL_TRUE;
1043 tcomps = 4; ccomps = 4; vcomps = 4;
1044 ctype = GL_FLOAT;
1045 coffset = 4*f;
1046 noffset = 8*f;
1047 voffset = 11*f;
1048 defstride = 15*f;
1049 break;
1050 default:
1051 gl_error( ctx, GL_INVALID_ENUM, "glInterleavedArrays(format)" );
1052 return;
1053 }
1054
1055 if (stride==0) {
1056 stride = defstride;
1057 }
1058
1059 gl_DisableClientState( ctx, GL_EDGE_FLAG_ARRAY );
1060 gl_DisableClientState( ctx, GL_INDEX_ARRAY );
1061
1062 /* Texcoords */
1063 coordUnitSave = ctx->Array.ActiveTexture;
1064 if (tflag) {
1065 GLint i;
1066 GLint factor = ctx->Array.TexCoordInterleaveFactor;
1067 for (i = 0; i < factor; i++) {
1068 gl_ClientActiveTexture( ctx, (GLenum) (GL_TEXTURE0_ARB + i) );
1069 gl_EnableClientState( ctx, GL_TEXTURE_COORD_ARRAY );
1070 glTexCoordPointer(CTX_PRM tcomps, GL_FLOAT, stride,
1071 (GLubyte *) pointer + i * coffset );
1072 }
1073 for (i = factor; i < ctx->Const.MaxTextureUnits; i++) {
1074 gl_ClientActiveTexture( ctx, (GLenum) (GL_TEXTURE0_ARB + i) );
1075 gl_DisableClientState( ctx, GL_TEXTURE_COORD_ARRAY );
1076 }
1077 }
1078 else {
1079 GLint i;
1080 for (i = 0; i < ctx->Const.MaxTextureUnits; i++) {
1081 gl_ClientActiveTexture( ctx, (GLenum) (GL_TEXTURE0_ARB + i) );
1082 gl_DisableClientState( ctx, GL_TEXTURE_COORD_ARRAY );
1083 }
1084 }
1085 /* Restore texture coordinate unit index */
1086 gl_ClientActiveTexture( ctx, (GLenum) (GL_TEXTURE0_ARB + coordUnitSave) );
1087
1088
1089 /* Color */
1090 if (cflag) {
1091 gl_EnableClientState( ctx, GL_COLOR_ARRAY );
1092 glColorPointer(CTX_PRM ccomps, ctype, stride,
1093 (GLubyte*) pointer + coffset );
1094 }
1095 else {
1096 gl_DisableClientState( ctx, GL_COLOR_ARRAY );
1097 }
1098
1099
1100 /* Normals */
1101 if (nflag) {
1102 gl_EnableClientState( ctx, GL_NORMAL_ARRAY );
1103 glNormalPointer(CTX_PRM GL_FLOAT, stride,
1104 (GLubyte*) pointer + noffset );
1105 }
1106 else {
1107 gl_DisableClientState( ctx, GL_NORMAL_ARRAY );
1108 }
1109
1110 gl_EnableClientState( ctx, GL_VERTEX_ARRAY );
1111 glVertexPointer(CTX_PRM vcomps, GL_FLOAT, stride,
1112 (GLubyte *) pointer + voffset );
1113}
1114
1115
1116
1117void GLAPIENTRY glDrawRangeElements(CTX_ARG GLenum mode, GLuint start,
1118 GLuint end, GLsizei count,
1119 GLenum type, const GLvoid *indices )
1120{
1121 GLcontext *ctx;
1122 GET_CONTEXT;
1123 CHECK_CONTEXT;
1124 ctx = CC;
1125
1126 if (end < start) {
1127 gl_error(ctx, GL_INVALID_VALUE, "glDrawRangeElements( end < start )");
1128 return;
1129 }
1130
1131 if (!ctx->Array.LockCount && 2*count > (GLint) 3*(end-start)) {
1132 glLockArraysEXT(CTX_PRM start, end );
1133 glDrawElements(CTX_PRM mode, count, type, indices );
1134 glUnlockArraysEXT(CTX_VPRM );
1135 } else {
1136 glDrawElements(CTX_PRM mode, count, type, indices );
1137 }
1138}
1139
1140
1141
1142void gl_update_client_state( GLcontext *ctx )
1143{
1144 static GLuint sz_flags[5] = { 0,
1145 0,
1146 VERT_OBJ_2,
1147 VERT_OBJ_23,
1148 VERT_OBJ_234 };
1149
1150 static GLuint tc_flags[5] = { 0,
1151 VERT_TEX0_1,
1152 VERT_TEX0_12,
1153 VERT_TEX0_123,
1154 VERT_TEX0_1234 };
1155
1156 ctx->Array.Flags = 0;
1157 ctx->Array.Summary = 0;
1158 ctx->input->ArrayIncr = 0;
1159
1160 if (ctx->Array.Normal.Enabled) ctx->Array.Flags |= VERT_NORM;
1161 if (ctx->Array.Color.Enabled) ctx->Array.Flags |= VERT_RGBA;
1162 if (ctx->Array.Index.Enabled) ctx->Array.Flags |= VERT_INDEX;
1163 if (ctx->Array.EdgeFlag.Enabled) ctx->Array.Flags |= VERT_EDGE;
1164 if (ctx->Array.Vertex.Enabled) {
1165 ctx->Array.Flags |= sz_flags[ctx->Array.Vertex.Size];
1166 ctx->input->ArrayIncr = 1;
1167 }
1168 if (ctx->Array.TexCoord[0].Enabled) {
1169 ctx->Array.Flags |= tc_flags[ctx->Array.TexCoord[0].Size];
1170 }
1171 if (ctx->Array.TexCoord[1].Enabled) {
1172 ctx->Array.Flags |= (tc_flags[ctx->Array.TexCoord[1].Size] << NR_TEXSIZE_BITS);
1173 }
1174
1175 /* Not really important any more:
1176 */
1177 ctx->Array.Summary = ctx->Array.Flags & VERT_DATA;
1178 ctx->input->ArrayAndFlags = ~ctx->Array.Flags;
1179 ctx->input->ArrayEltFlush = !(ctx->CompileCVAFlag);
1180}
1181
Note: See TracBrowser for help on using the repository browser.