1 /* $Id: varray.c,v 1.30 2000/11/05 18:40:59 keithw Exp $ */
4 * Mesa 3-D graphics library
7 * Copyright (C) 1999-2000 Brian Paul All Rights Reserved.
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:
16 * The above copyright notice and this permission notice shall be included
17 * in all copies or substantial portions of the Software.
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.
42 #include "translate.h"
48 #include "vbindirect.h"
56 _mesa_VertexPointer(GLint size
, GLenum type
, GLsizei stride
, const GLvoid
*ptr
)
58 GET_CURRENT_CONTEXT(ctx
);
60 if (size
<2 || size
>4) {
61 gl_error( ctx
, GL_INVALID_VALUE
, "glVertexPointer(size)" );
65 gl_error( ctx
, GL_INVALID_VALUE
, "glVertexPointer(stride)" );
69 if (MESA_VERBOSE
&(VERBOSE_VARRAY
|VERBOSE_API
))
70 fprintf(stderr
, "glVertexPointer( sz %d type %s stride %d )\n", size
,
71 gl_lookup_enum_by_nr( type
),
74 ctx
->Array
.Vertex
.StrideB
= stride
;
78 ctx
->Array
.Vertex
.StrideB
= size
*sizeof(GLshort
);
81 ctx
->Array
.Vertex
.StrideB
= size
*sizeof(GLint
);
84 ctx
->Array
.Vertex
.StrideB
= size
*sizeof(GLfloat
);
87 ctx
->Array
.Vertex
.StrideB
= size
*sizeof(GLdouble
);
90 gl_error( ctx
, GL_INVALID_ENUM
, "glVertexPointer(type)" );
94 ctx
->Array
.Vertex
.Size
= size
;
95 ctx
->Array
.Vertex
.Type
= type
;
96 ctx
->Array
.Vertex
.Stride
= stride
;
97 ctx
->Array
.Vertex
.Ptr
= (void *) ptr
;
98 ctx
->Array
._VertexFunc
= gl_trans_4f_tab
[size
][TYPE_IDX(type
)];
99 ctx
->Array
._VertexEltFunc
= gl_trans_elt_4f_tab
[size
][TYPE_IDX(type
)];
100 ctx
->Array
._NewArrayState
|= VERT_OBJ_ANY
;
101 ctx
->NewState
|= _NEW_ARRAY
;
108 _mesa_NormalPointer(GLenum type
, GLsizei stride
, const GLvoid
*ptr
)
110 GET_CURRENT_CONTEXT(ctx
);
113 gl_error( ctx
, GL_INVALID_VALUE
, "glNormalPointer(stride)" );
117 if (MESA_VERBOSE
&(VERBOSE_VARRAY
|VERBOSE_API
))
118 fprintf(stderr
, "glNormalPointer( type %s stride %d )\n",
119 gl_lookup_enum_by_nr( type
),
122 ctx
->Array
.Normal
.StrideB
= stride
;
126 ctx
->Array
.Normal
.StrideB
= 3*sizeof(GLbyte
);
129 ctx
->Array
.Normal
.StrideB
= 3*sizeof(GLshort
);
132 ctx
->Array
.Normal
.StrideB
= 3*sizeof(GLint
);
135 ctx
->Array
.Normal
.StrideB
= 3*sizeof(GLfloat
);
138 ctx
->Array
.Normal
.StrideB
= 3*sizeof(GLdouble
);
141 gl_error( ctx
, GL_INVALID_ENUM
, "glNormalPointer(type)" );
145 ctx
->Array
.Normal
.Type
= type
;
146 ctx
->Array
.Normal
.Stride
= stride
;
147 ctx
->Array
.Normal
.Ptr
= (void *) ptr
;
148 ctx
->Array
._NormalFunc
= gl_trans_3f_tab
[TYPE_IDX(type
)];
149 ctx
->Array
._NormalEltFunc
= gl_trans_elt_3f_tab
[TYPE_IDX(type
)];
150 ctx
->Array
._NewArrayState
|= VERT_NORM
;
151 ctx
->NewState
|= _NEW_ARRAY
;
157 _mesa_ColorPointer(GLint size
, GLenum type
, GLsizei stride
, const GLvoid
*ptr
)
159 GET_CURRENT_CONTEXT(ctx
);
161 if (size
<3 || size
>4) {
162 gl_error( ctx
, GL_INVALID_VALUE
, "glColorPointer(size)" );
166 gl_error( ctx
, GL_INVALID_VALUE
, "glColorPointer(stride)" );
170 if (MESA_VERBOSE
&(VERBOSE_VARRAY
|VERBOSE_API
))
171 fprintf(stderr
, "glColorPointer( sz %d type %s stride %d )\n", size
,
172 gl_lookup_enum_by_nr( type
),
175 ctx
->Array
.Color
.StrideB
= stride
;
179 ctx
->Array
.Color
.StrideB
= size
*sizeof(GLbyte
);
181 case GL_UNSIGNED_BYTE
:
182 ctx
->Array
.Color
.StrideB
= size
*sizeof(GLubyte
);
185 ctx
->Array
.Color
.StrideB
= size
*sizeof(GLshort
);
187 case GL_UNSIGNED_SHORT
:
188 ctx
->Array
.Color
.StrideB
= size
*sizeof(GLushort
);
191 ctx
->Array
.Color
.StrideB
= size
*sizeof(GLint
);
193 case GL_UNSIGNED_INT
:
194 ctx
->Array
.Color
.StrideB
= size
*sizeof(GLuint
);
197 ctx
->Array
.Color
.StrideB
= size
*sizeof(GLfloat
);
200 ctx
->Array
.Color
.StrideB
= size
*sizeof(GLdouble
);
203 gl_error( ctx
, GL_INVALID_ENUM
, "glColorPointer(type)" );
207 ctx
->Array
.Color
.Size
= size
;
208 ctx
->Array
.Color
.Type
= type
;
209 ctx
->Array
.Color
.Stride
= stride
;
210 ctx
->Array
.Color
.Ptr
= (void *) ptr
;
211 ctx
->Array
._ColorFunc
= gl_trans_4ub_tab
[size
][TYPE_IDX(type
)];
212 ctx
->Array
._ColorEltFunc
= gl_trans_elt_4ub_tab
[size
][TYPE_IDX(type
)];
213 ctx
->Array
._NewArrayState
|= VERT_RGBA
;
214 ctx
->NewState
|= _NEW_ARRAY
;
220 _mesa_FogCoordPointerEXT(GLenum type
, GLsizei stride
, const GLvoid
*ptr
)
222 GET_CURRENT_CONTEXT(ctx
);
225 gl_error( ctx
, GL_INVALID_VALUE
, "glFogCoordPointer(stride)" );
229 ctx
->Array
.FogCoord
.StrideB
= stride
;
233 ctx
->Array
.FogCoord
.StrideB
= sizeof(GLfloat
);
236 ctx
->Array
.FogCoord
.StrideB
= sizeof(GLdouble
);
239 gl_error( ctx
, GL_INVALID_ENUM
, "glFogCoordPointer(type)" );
243 ctx
->Array
.FogCoord
.Type
= type
;
244 ctx
->Array
.FogCoord
.Stride
= stride
;
245 ctx
->Array
.FogCoord
.Ptr
= (void *) ptr
;
246 ctx
->Array
._FogCoordFunc
= gl_trans_1f_tab
[TYPE_IDX(type
)];
247 ctx
->Array
._FogCoordEltFunc
= gl_trans_elt_1f_tab
[TYPE_IDX(type
)];
248 ctx
->Array
._NewArrayState
|= VERT_FOG_COORD
;
249 ctx
->NewState
|= _NEW_ARRAY
;
254 _mesa_IndexPointer(GLenum type
, GLsizei stride
, const GLvoid
*ptr
)
256 GET_CURRENT_CONTEXT(ctx
);
259 gl_error( ctx
, GL_INVALID_VALUE
, "glIndexPointer(stride)" );
263 ctx
->Array
.Index
.StrideB
= stride
;
266 case GL_UNSIGNED_BYTE
:
267 ctx
->Array
.Index
.StrideB
= sizeof(GLubyte
);
270 ctx
->Array
.Index
.StrideB
= sizeof(GLshort
);
273 ctx
->Array
.Index
.StrideB
= sizeof(GLint
);
276 ctx
->Array
.Index
.StrideB
= sizeof(GLfloat
);
279 ctx
->Array
.Index
.StrideB
= sizeof(GLdouble
);
282 gl_error( ctx
, GL_INVALID_ENUM
, "glIndexPointer(type)" );
286 ctx
->Array
.Index
.Type
= type
;
287 ctx
->Array
.Index
.Stride
= stride
;
288 ctx
->Array
.Index
.Ptr
= (void *) ptr
;
289 ctx
->Array
._IndexFunc
= gl_trans_1ui_tab
[TYPE_IDX(type
)];
290 ctx
->Array
._IndexEltFunc
= gl_trans_elt_1ui_tab
[TYPE_IDX(type
)];
291 ctx
->Array
._NewArrayState
|= VERT_INDEX
;
292 ctx
->NewState
|= _NEW_ARRAY
;
297 _mesa_SecondaryColorPointerEXT(GLint size
, GLenum type
,
298 GLsizei stride
, const GLvoid
*ptr
)
300 GET_CURRENT_CONTEXT(ctx
);
302 if (size
!= 3 && size
!= 4) {
303 gl_error( ctx
, GL_INVALID_VALUE
, "glColorPointer(size)" );
307 gl_error( ctx
, GL_INVALID_VALUE
, "glColorPointer(stride)" );
311 if (MESA_VERBOSE
&(VERBOSE_VARRAY
|VERBOSE_API
))
312 fprintf(stderr
, "glColorPointer( sz %d type %s stride %d )\n", size
,
313 gl_lookup_enum_by_nr( type
),
316 ctx
->Array
.SecondaryColor
.StrideB
= stride
;
320 ctx
->Array
.SecondaryColor
.StrideB
= size
*sizeof(GLbyte
);
322 case GL_UNSIGNED_BYTE
:
323 ctx
->Array
.SecondaryColor
.StrideB
= size
*sizeof(GLubyte
);
326 ctx
->Array
.SecondaryColor
.StrideB
= size
*sizeof(GLshort
);
328 case GL_UNSIGNED_SHORT
:
329 ctx
->Array
.SecondaryColor
.StrideB
= size
*sizeof(GLushort
);
332 ctx
->Array
.SecondaryColor
.StrideB
= size
*sizeof(GLint
);
334 case GL_UNSIGNED_INT
:
335 ctx
->Array
.SecondaryColor
.StrideB
= size
*sizeof(GLuint
);
338 ctx
->Array
.SecondaryColor
.StrideB
= size
*sizeof(GLfloat
);
341 ctx
->Array
.SecondaryColor
.StrideB
= size
*sizeof(GLdouble
);
344 gl_error( ctx
, GL_INVALID_ENUM
, "glSecondaryColorPointer(type)" );
348 ctx
->Array
.SecondaryColor
.Size
= 3; /* hardwire */
349 ctx
->Array
.SecondaryColor
.Type
= type
;
350 ctx
->Array
.SecondaryColor
.Stride
= stride
;
351 ctx
->Array
.SecondaryColor
.Ptr
= (void *) ptr
;
352 ctx
->Array
._SecondaryColorFunc
= gl_trans_4ub_tab
[size
][TYPE_IDX(type
)];
353 ctx
->Array
._SecondaryColorEltFunc
= gl_trans_elt_4ub_tab
[size
][TYPE_IDX(type
)];
354 ctx
->Array
._NewArrayState
|= VERT_SPEC_RGB
;
355 ctx
->NewState
|= _NEW_ARRAY
;
361 _mesa_TexCoordPointer(GLint size
, GLenum type
, GLsizei stride
, const GLvoid
*ptr
)
363 GET_CURRENT_CONTEXT(ctx
);
366 texUnit
= ctx
->Array
.ActiveTexture
;
368 if (size
<1 || size
>4) {
369 gl_error( ctx
, GL_INVALID_VALUE
, "glTexCoordPointer(size)" );
373 gl_error( ctx
, GL_INVALID_VALUE
, "glTexCoordPointer(stride)" );
377 if (MESA_VERBOSE
&(VERBOSE_VARRAY
|VERBOSE_API
))
378 fprintf(stderr
, "glTexCoordPointer( unit %u sz %d type %s stride %d )\n",
381 gl_lookup_enum_by_nr( type
),
384 ctx
->Array
.TexCoord
[texUnit
].StrideB
= stride
;
388 ctx
->Array
.TexCoord
[texUnit
].StrideB
= size
*sizeof(GLshort
);
391 ctx
->Array
.TexCoord
[texUnit
].StrideB
= size
*sizeof(GLint
);
394 ctx
->Array
.TexCoord
[texUnit
].StrideB
= size
*sizeof(GLfloat
);
397 ctx
->Array
.TexCoord
[texUnit
].StrideB
= size
*sizeof(GLdouble
);
400 gl_error( ctx
, GL_INVALID_ENUM
, "glTexCoordPointer(type)" );
404 ctx
->Array
.TexCoord
[texUnit
].Size
= size
;
405 ctx
->Array
.TexCoord
[texUnit
].Type
= type
;
406 ctx
->Array
.TexCoord
[texUnit
].Stride
= stride
;
407 ctx
->Array
.TexCoord
[texUnit
].Ptr
= (void *) ptr
;
409 ctx
->Array
._TexCoordFunc
[texUnit
] = gl_trans_4f_tab
[size
][TYPE_IDX(type
)];
410 ctx
->Array
._TexCoordEltFunc
[texUnit
] = gl_trans_elt_4f_tab
[size
][TYPE_IDX(type
)];
411 ctx
->Array
._NewArrayState
|= VERT_TEX_ANY(texUnit
);
412 ctx
->NewState
|= _NEW_ARRAY
;
419 _mesa_EdgeFlagPointer(GLsizei stride
, const void *vptr
)
421 GET_CURRENT_CONTEXT(ctx
);
422 const GLboolean
*ptr
= (GLboolean
*)vptr
;
425 gl_error( ctx
, GL_INVALID_VALUE
, "glEdgeFlagPointer(stride)" );
428 ctx
->Array
.EdgeFlag
.Stride
= stride
;
429 ctx
->Array
.EdgeFlag
.StrideB
= stride
? stride
: sizeof(GLboolean
);
430 ctx
->Array
.EdgeFlag
.Ptr
= (GLboolean
*) ptr
;
431 if (stride
!= sizeof(GLboolean
)) {
432 ctx
->Array
._EdgeFlagFunc
= gl_trans_1ub_tab
[TYPE_IDX(GL_UNSIGNED_BYTE
)];
434 ctx
->Array
._EdgeFlagFunc
= 0;
436 ctx
->Array
._EdgeFlagEltFunc
= gl_trans_elt_1ub_tab
[TYPE_IDX(GL_UNSIGNED_BYTE
)];
437 ctx
->Array
._NewArrayState
|= VERT_EDGE
;
438 ctx
->NewState
|= _NEW_ARRAY
;
446 _mesa_VertexPointerEXT(GLint size
, GLenum type
, GLsizei stride
,
447 GLsizei count
, const GLvoid
*ptr
)
450 _mesa_VertexPointer(size
, type
, stride
, ptr
);
455 _mesa_NormalPointerEXT(GLenum type
, GLsizei stride
, GLsizei count
,
459 _mesa_NormalPointer(type
, stride
, ptr
);
464 _mesa_ColorPointerEXT(GLint size
, GLenum type
, GLsizei stride
, GLsizei count
,
468 _mesa_ColorPointer(size
, type
, stride
, ptr
);
473 _mesa_IndexPointerEXT(GLenum type
, GLsizei stride
, GLsizei count
,
477 _mesa_IndexPointer(type
, stride
, ptr
);
482 _mesa_TexCoordPointerEXT(GLint size
, GLenum type
, GLsizei stride
,
483 GLsizei count
, const GLvoid
*ptr
)
486 _mesa_TexCoordPointer(size
, type
, stride
, ptr
);
491 _mesa_EdgeFlagPointerEXT(GLsizei stride
, GLsizei count
, const GLboolean
*ptr
)
494 _mesa_EdgeFlagPointer(stride
, ptr
);
501 /* KW: Batch function to exec all the array elements in the input
502 * buffer prior to transform. Done only the first time a vertex
503 * buffer is executed or compiled.
505 * KW: Have to do this after each glEnd if cva isn't active. (also
506 * have to do it after each full buffer)
508 void gl_exec_array_elements( GLcontext
*ctx
, struct immediate
*IM
,
512 GLuint
*flags
= IM
->Flag
;
513 GLuint
*elts
= IM
->Elt
;
514 GLuint translate
= ctx
->Array
._Flags
;
517 if (MESA_VERBOSE
&VERBOSE_IMMEDIATE
)
518 fprintf(stderr
, "exec_array_elements %d .. %d\n", start
, count
);
520 if (translate
& VERT_OBJ_ANY
)
521 (ctx
->Array
._VertexEltFunc
)( IM
->Obj
,
523 flags
, elts
, (VERT_ELT
|VERT_OBJ_ANY
),
526 if (translate
& VERT_NORM
)
527 (ctx
->Array
._NormalEltFunc
)( IM
->Normal
,
529 flags
, elts
, (VERT_ELT
|VERT_NORM
),
532 if (translate
& VERT_EDGE
)
533 (ctx
->Array
._EdgeFlagEltFunc
)( IM
->EdgeFlag
,
534 &ctx
->Array
.EdgeFlag
,
535 flags
, elts
, (VERT_ELT
|VERT_EDGE
),
538 if (translate
& VERT_RGBA
)
539 (ctx
->Array
._ColorEltFunc
)( IM
->Color
,
541 flags
, elts
, (VERT_ELT
|VERT_RGBA
),
545 if (translate
& VERT_SPEC_RGB
)
546 (ctx
->Array
._SecondaryColorEltFunc
)( IM
->SecondaryColor
,
547 &ctx
->Array
.SecondaryColor
,
548 flags
, elts
, (VERT_ELT
|VERT_SPEC_RGB
),
551 if (translate
& VERT_FOG_COORD
)
552 (ctx
->Array
._FogCoordEltFunc
)( IM
->FogCoord
,
553 &ctx
->Array
.FogCoord
,
554 flags
, elts
, (VERT_ELT
|VERT_FOG_COORD
),
557 if (translate
& VERT_INDEX
)
558 (ctx
->Array
._IndexEltFunc
)( IM
->Index
,
560 flags
, elts
, (VERT_ELT
|VERT_INDEX
),
563 if (translate
& VERT_TEX0_ANY
)
564 (ctx
->Array
._TexCoordEltFunc
[0])( IM
->TexCoord
[0],
565 &ctx
->Array
.TexCoord
[0],
566 flags
, elts
, (VERT_ELT
|VERT_TEX0_ANY
),
569 if (translate
& VERT_TEX1_ANY
)
570 (ctx
->Array
._TexCoordEltFunc
[1])( IM
->TexCoord
[1],
571 &ctx
->Array
.TexCoord
[1],
572 flags
, elts
, (VERT_ELT
|VERT_TEX1_ANY
),
575 #if MAX_TEXTURE_UNITS > 2
576 if (translate
& VERT_TEX2_ANY
)
577 (ctx
->Array
._TexCoordEltFunc
[2])( IM
->TexCoord
[2],
578 &ctx
->Array
.TexCoord
[2],
579 flags
, elts
, (VERT_ELT
|VERT_TEX2_ANY
),
582 #if MAX_TEXTURE_UNITS > 3
583 if (translate
& VERT_TEX3_ANY
)
584 (ctx
->Array
._TexCoordEltFunc
[3])( IM
->TexCoord
[3],
585 &ctx
->Array
.TexCoord
[3],
586 flags
, elts
, (VERT_ELT
|VERT_TEX3_ANY
),
590 for (i
= start
; i
< count
; i
++)
591 if (flags
[i
] & VERT_ELT
)
592 flags
[i
] |= translate
;
598 /* Enough funny business going on in here it might be quicker to use a
601 #define ARRAY_ELT( IM, i ) \
603 GLuint count = IM->Count; \
604 IM->Elt[count] = i; \
605 IM->Flag[count] = ((IM->Flag[count] & IM->ArrayAndFlags) | \
607 IM->FlushElt |= IM->ArrayEltFlush; \
608 IM->Count = count += IM->ArrayIncr; \
609 if (count == VB_MAX) \
610 _mesa_maybe_transform_vb( IM ); \
615 _mesa_ArrayElement( GLint i
)
623 gl_ArrayElement( GLcontext
*CC
, GLint i
)
625 struct immediate
*im
= CC
->input
;
632 _mesa_DrawArrays(GLenum mode
, GLint start
, GLsizei count
)
634 GET_CURRENT_CONTEXT(ctx
);
635 struct vertex_buffer
*VB
= ctx
->VB
;
638 ASSERT_OUTSIDE_BEGIN_END_AND_FLUSH(ctx
, "glDrawArrays");
641 gl_error( ctx
, GL_INVALID_VALUE
, "glDrawArrays(count)" );
645 if (!ctx
->CompileFlag
&& ctx
->Array
.Vertex
.Enabled
) {
646 GLint remaining
= count
;
648 struct gl_client_array
*Normal
;
649 struct gl_client_array
*Color
;
650 struct gl_client_array
*SecondaryColor
;
651 struct gl_client_array
*FogCoord
;
652 struct gl_client_array
*Index
;
653 struct gl_client_array
*TexCoord
[MAX_TEXTURE_UNITS
];
654 struct gl_client_array
*EdgeFlag
;
655 struct immediate
*IM
= VB
->IM
;
656 struct gl_pipeline
*elt
= &ctx
->CVA
.elt
;
658 GLuint fallback
, required
;
661 gl_update_state( ctx
);
663 /* Just turn off cva on this path. Could be useful for multipass
664 * rendering to keep it turned on.
666 relock
= ctx
->CompileCVAFlag
;
669 ctx
->CompileCVAFlag
= 0;
670 elt
->pipeline_valid
= 0;
673 if (!elt
->pipeline_valid
)
674 gl_build_immediate_pipeline( ctx
);
676 required
= elt
->inputs
;
677 fallback
= (elt
->inputs
& ~ctx
->Array
._Summary
);
679 /* The translate function doesn't do anything about size. It
680 * just ensures that type and stride come out right.
682 IM
->v
.Obj
.size
= ctx
->Array
.Vertex
.Size
;
684 if (required
& VERT_RGBA
) {
685 Color
= &ctx
->Array
.Color
;
686 if (fallback
& VERT_RGBA
) {
687 Color
= &ctx
->Fallback
.Color
;
688 ctx
->Array
._ColorFunc
=
689 gl_trans_4ub_tab
[4][TYPE_IDX(GL_UNSIGNED_BYTE
)];
693 if (required
& VERT_SPEC_RGB
)
695 SecondaryColor
= &ctx
->Array
.SecondaryColor
;
696 if (fallback
& VERT_SPEC_RGB
) {
697 SecondaryColor
= &ctx
->Fallback
.SecondaryColor
;
698 ctx
->Array
._SecondaryColorFunc
=
699 gl_trans_4ub_tab
[4][TYPE_IDX(GL_UNSIGNED_BYTE
)];
703 if (required
& VERT_FOG_COORD
)
705 FogCoord
= &ctx
->Array
.FogCoord
;
706 if (fallback
& VERT_FOG_COORD
) {
707 FogCoord
= &ctx
->Fallback
.FogCoord
;
708 ctx
->Array
._FogCoordFunc
=
709 gl_trans_1f_tab
[TYPE_IDX(GL_FLOAT
)];
713 if (required
& VERT_INDEX
) {
714 Index
= &ctx
->Array
.Index
;
715 if (fallback
& VERT_INDEX
) {
716 Index
= &ctx
->Fallback
.Index
;
717 ctx
->Array
._IndexFunc
= gl_trans_1ui_tab
[TYPE_IDX(GL_UNSIGNED_INT
)];
721 for (i
= 0 ; i
< MAX_TEXTURE_UNITS
; i
++) {
722 GLuint flag
= VERT_TEX_ANY(i
);
724 if (required
& flag
) {
725 TexCoord
[i
] = &ctx
->Array
.TexCoord
[i
];
727 if (fallback
& flag
) {
728 TexCoord
[i
] = &ctx
->Fallback
.TexCoord
[i
];
729 TexCoord
[i
]->Size
= gl_texcoord_size( ctx
->Current
.Flag
, i
);
731 ctx
->Array
._TexCoordFunc
[i
] =
732 gl_trans_4f_tab
[TexCoord
[i
]->Size
][TYPE_IDX(GL_FLOAT
)];
737 if (ctx
->Array
._Flags
!= ctx
->Array
._Flag
[0]) {
738 for (i
= 0 ; i
< VB_MAX
; i
++)
739 ctx
->Array
._Flag
[i
] = ctx
->Array
._Flags
;
742 if (required
& VERT_NORM
) {
743 Normal
= &ctx
->Array
.Normal
;
744 if (fallback
& VERT_NORM
) {
745 Normal
= &ctx
->Fallback
.Normal
;
746 ctx
->Array
._NormalFunc
= gl_trans_3f_tab
[TYPE_IDX(GL_FLOAT
)];
750 if ( required
& VERT_EDGE
) {
751 if (mode
== GL_TRIANGLES
||
753 mode
== GL_POLYGON
) {
754 EdgeFlag
= &ctx
->Array
.EdgeFlag
;
755 if (fallback
& VERT_EDGE
) {
756 EdgeFlag
= &ctx
->Fallback
.EdgeFlag
;
757 ctx
->Array
._EdgeFlagFunc
=
758 gl_trans_1ub_tab
[TYPE_IDX(GL_UNSIGNED_BYTE
)];
762 required
&= ~VERT_EDGE
;
765 VB
->Primitive
= IM
->Primitive
;
766 VB
->NextPrimitive
= IM
->NextPrimitive
;
767 VB
->MaterialMask
= IM
->MaterialMask
;
768 VB
->Material
= IM
->Material
;
771 while (remaining
> 0) {
772 GLint vbspace
= VB_MAX
- VB_START
;
775 if (vbspace
>= remaining
) {
777 VB
->LastPrimitive
= VB_START
+ n
;
781 VB
->LastPrimitive
= VB_START
;
786 ctx
->Array
._VertexFunc( IM
->Obj
+ VB_START
,
787 &ctx
->Array
.Vertex
, start
, n
);
789 if (required
& VERT_NORM
) {
790 ctx
->Array
._NormalFunc( IM
->Normal
+ VB_START
,
794 if (required
& VERT_EDGE
) {
795 ctx
->Array
._EdgeFlagFunc( IM
->EdgeFlag
+ VB_START
,
796 EdgeFlag
, start
, n
);
799 if (required
& VERT_RGBA
) {
800 ctx
->Array
._ColorFunc( IM
->Color
+ VB_START
,
804 if (required
& VERT_SPEC_RGB
) {
805 ctx
->Array
._SecondaryColorFunc( IM
->SecondaryColor
+ VB_START
,
806 SecondaryColor
, start
, n
);
809 if (required
& VERT_FOG_COORD
) {
810 ctx
->Array
._FogCoordFunc( IM
->FogCoord
+ VB_START
,
811 FogCoord
, start
, n
);
814 if (required
& VERT_INDEX
) {
815 ctx
->Array
._IndexFunc( IM
->Index
+ VB_START
,
819 if (required
& VERT_TEX0_ANY
) {
820 IM
->v
.TexCoord
[0].size
= TexCoord
[0]->Size
;
821 ctx
->Array
._TexCoordFunc
[0]( IM
->TexCoord
[0] + VB_START
,
822 TexCoord
[0], start
, n
);
825 if (required
& VERT_TEX1_ANY
) {
826 IM
->v
.TexCoord
[1].size
= TexCoord
[1]->Size
;
827 ctx
->Array
._TexCoordFunc
[1]( IM
->TexCoord
[1] + VB_START
,
828 TexCoord
[1], start
, n
);
830 #if MAX_TEXTURE_UNITS > 2
831 if (required
& VERT_TEX2_ANY
) {
832 IM
->v
.TexCoord
[2].size
= TexCoord
[2]->Size
;
833 ctx
->Array
._TexCoordFunc
[2]( IM
->TexCoord
[2] + VB_START
,
834 TexCoord
[2], start
, n
);
837 #if MAX_TEXTURE_UNITS > 3
838 if (required
& VERT_TEX3_ANY
) {
839 IM
->v
.TexCoord
[3].size
= TexCoord
[3]->Size
;
840 ctx
->Array
._TexCoordFunc
[3]( IM
->TexCoord
[3] + VB_START
,
841 TexCoord
[3], start
, n
);
845 VB
->ObjPtr
= &IM
->v
.Obj
;
846 VB
->NormalPtr
= &IM
->v
.Normal
;
847 VB
->ColorPtr
= &IM
->v
.Color
;
848 VB
->Color
[0] = VB
->Color
[1] = VB
->ColorPtr
;
849 VB
->IndexPtr
= &IM
->v
.Index
;
850 VB
->EdgeFlagPtr
= &IM
->v
.EdgeFlag
;
851 VB
->SecondaryColorPtr
= &IM
->v
.SecondaryColor
;
852 VB
->FogCoordPtr
= &IM
->v
.FogCoord
;
853 for (i
= 0; i
< MAX_TEXTURE_UNITS
; i
++) {
854 VB
->TexCoordPtr
[i
] = &IM
->v
.TexCoord
[i
];
857 VB
->Flag
= ctx
->Array
._Flag
;
858 VB
->OrFlag
= ctx
->Array
._Flags
;
860 VB
->Start
= IM
->Start
= VB_START
;
861 count
= VB
->Count
= IM
->Count
= VB_START
+ n
;
863 #define RESET_VEC(v, t, s, c) (v.start = t v.data[s], v.count = c)
865 RESET_VEC(IM
->v
.Obj
, (GLfloat
*), VB_START
, count
);
866 RESET_VEC(IM
->v
.Normal
, (GLfloat
*), VB_START
, count
);
867 for (i
= 0; i
< MAX_TEXTURE_UNITS
; i
++) {
868 RESET_VEC(IM
->v
.TexCoord
[i
], (GLfloat
*), VB_START
, count
);
870 RESET_VEC(IM
->v
.Index
, &, VB_START
, count
);
871 RESET_VEC(IM
->v
.Elt
, &, VB_START
, count
);
872 RESET_VEC(IM
->v
.EdgeFlag
, &, VB_START
, count
);
873 RESET_VEC(IM
->v
.Color
, (GLubyte
*), VB_START
, count
);
874 RESET_VEC(VB
->Clip
, (GLfloat
*), VB_START
, count
);
875 RESET_VEC(VB
->Eye
, (GLfloat
*), VB_START
, count
);
876 RESET_VEC(VB
->Win
, (GLfloat
*), VB_START
, count
);
877 RESET_VEC(VB
->BColor
, (GLubyte
*), VB_START
, count
);
878 RESET_VEC(VB
->BIndex
, &, VB_START
, count
);
880 VB
->NextPrimitive
[VB
->CopyStart
] = VB
->Count
;
881 VB
->Primitive
[VB
->CopyStart
] = mode
;
882 ctx
->Array
._Flag
[count
] |= VERT_END_VB
;
884 /* Transform and render.
886 gl_run_pipeline( VB
);
891 ctx
->Array
._Flag
[count
] = ctx
->Array
._Flags
;
892 ctx
->Array
._Flag
[VB_START
] = ctx
->Array
._Flags
;
898 gl_reset_input( ctx
);
901 ctx
->CompileCVAFlag
= relock
;
902 elt
->pipeline_valid
= 0;
905 else if (ctx
->Array
.Vertex
.Enabled
)
907 /* The GL_COMPILE and GL_COMPILE_AND_EXECUTE cases. These
908 * could be handled by the above code, but it gets a little
909 * complex. The generated list is still of good quality
912 gl_Begin( ctx
, mode
);
913 for (i
=0;i
<count
;i
++) {
914 gl_ArrayElement( ctx
, start
+i
);
920 /* The degenerate case where vertices are not enabled - only
921 * need to process the very final array element, as all of the
922 * preceding ones would be overwritten anyway.
924 gl_Begin( ctx
, mode
);
925 gl_ArrayElement( ctx
, start
+count
);
932 /* KW: Exactly fakes the effects of calling glArrayElement multiple times.
935 #define DRAW_ELT(FUNC, TYPE) \
936 static void FUNC( GLcontext *ctx, GLenum mode, \
937 TYPE *indices, GLuint count ) \
941 gl_Begin( ctx, mode ); \
943 for (j = 0 ; j < count ; ) { \
944 struct immediate *IM = ctx->input; \
945 GLuint start = IM->Start; \
946 GLuint nr = MIN2( VB_MAX, count - j + start ); \
947 GLuint sf = IM->Flag[start]; \
948 IM->FlushElt |= IM->ArrayEltFlush; \
950 for (i = start ; i < nr ; i++) { \
951 IM->Elt[i] = (GLuint) *indices++; \
952 IM->Flag[i] = VERT_ELT; \
955 if (j == 0) IM->Flag[start] |= sf; \
962 _mesa_maybe_transform_vb( IM ); \
966 #define DRAW_ELT(FUNC, TYPE) \
967 static void FUNC( GLcontext *ctx, GLenum mode, \
968 TYPE *indices, GLuint count ) \
972 for (i = 0 ; i < count ; i++) \
973 glArrayElement( indices[i] ); \
979 DRAW_ELT( draw_elt_ubyte
, GLubyte
)
980 DRAW_ELT( draw_elt_ushort
, GLushort
)
981 DRAW_ELT( draw_elt_uint
, GLuint
)
984 static GLuint natural_stride
[0x10] =
986 sizeof(GLbyte
), /* 0 */
987 sizeof(GLubyte
), /* 1 */
988 sizeof(GLshort
), /* 2 */
989 sizeof(GLushort
), /* 3 */
990 sizeof(GLint
), /* 4 */
991 sizeof(GLuint
), /* 5 */
992 sizeof(GLfloat
), /* 6 */
993 2 * sizeof(GLbyte
), /* 7 */
994 3 * sizeof(GLbyte
), /* 8 */
995 4 * sizeof(GLbyte
), /* 9 */
996 sizeof(GLdouble
), /* a */
1006 _mesa_DrawElements(GLenum mode
, GLsizei count
, GLenum type
, const GLvoid
*indices
)
1008 GET_CURRENT_CONTEXT(ctx
);
1012 ASSERT_OUTSIDE_BEGIN_END_AND_FLUSH(ctx
, "glDrawElements");
1016 gl_error( ctx
, GL_INVALID_VALUE
, "glDrawElements(count)" );
1020 if (mode
< 0 || mode
> GL_POLYGON
) {
1021 gl_error( ctx
, GL_INVALID_ENUM
, "glDrawArrays(mode)" );
1025 if (type
!= GL_UNSIGNED_INT
&& type
!= GL_UNSIGNED_BYTE
&& type
!= GL_UNSIGNED_SHORT
)
1027 gl_error( ctx
, GL_INVALID_ENUM
, "glDrawElements(type)" );
1032 gl_update_state(ctx
);
1034 if (ctx
->CompileCVAFlag
)
1036 /* Treat VERT_ELT like a special client array.
1038 ctx
->Array
._NewArrayState
|= VERT_ELT
;
1039 ctx
->Array
._Summary
|= VERT_ELT
;
1040 ctx
->Array
._Flags
|= VERT_ELT
;
1042 cva
->elt_mode
= mode
;
1043 cva
->elt_count
= count
;
1044 cva
->Elt
.Type
= type
;
1045 cva
->Elt
.Ptr
= (void *) indices
;
1046 cva
->Elt
.StrideB
= natural_stride
[TYPE_IDX(type
)];
1047 cva
->EltFunc
= gl_trans_1ui_tab
[TYPE_IDX(type
)];
1049 if (!cva
->pre
.pipeline_valid
)
1050 gl_build_precalc_pipeline( ctx
);
1051 else if (MESA_VERBOSE
& VERBOSE_PIPELINE
)
1052 fprintf(stderr
, ": dont rebuild\n");
1054 gl_cva_force_precalc( ctx
);
1056 /* Did we 'precalculate' the render op?
1058 if (ctx
->CVA
.pre
.ops
& PIPE_OP_RENDER
) {
1059 ctx
->Array
._NewArrayState
|= VERT_ELT
;
1060 ctx
->Array
._Summary
&= ~VERT_ELT
;
1061 ctx
->Array
._Flags
&= ~VERT_ELT
;
1065 if ( (MESA_VERBOSE
&VERBOSE_VARRAY
) )
1066 printf("using immediate\n");
1070 /* Otherwise, have to use the immediate path to render.
1073 case GL_UNSIGNED_BYTE
:
1075 GLubyte
*ub_indices
= (GLubyte
*) indices
;
1076 if (ctx
->Array
._Summary
& VERT_OBJ_ANY
) {
1077 draw_elt_ubyte( ctx
, mode
, ub_indices
, count
);
1079 gl_ArrayElement( ctx
, (GLuint
) ub_indices
[count
-1] );
1083 case GL_UNSIGNED_SHORT
:
1085 GLushort
*us_indices
= (GLushort
*) indices
;
1086 if (ctx
->Array
._Summary
& VERT_OBJ_ANY
) {
1087 draw_elt_ushort( ctx
, mode
, us_indices
, count
);
1089 gl_ArrayElement( ctx
, (GLuint
) us_indices
[count
-1] );
1093 case GL_UNSIGNED_INT
:
1095 GLuint
*ui_indices
= (GLuint
*) indices
;
1096 if (ctx
->Array
._Summary
& VERT_OBJ_ANY
) {
1097 draw_elt_uint( ctx
, mode
, ui_indices
, count
);
1099 gl_ArrayElement( ctx
, ui_indices
[count
-1] );
1104 gl_error( ctx
, GL_INVALID_ENUM
, "glDrawElements(type)" );
1108 if (ctx
->CompileCVAFlag
) {
1109 ctx
->Array
._NewArrayState
|= VERT_ELT
;
1110 ctx
->Array
._Summary
&= ~VERT_ELT
;
1117 _mesa_InterleavedArrays(GLenum format
, GLsizei stride
, const GLvoid
*pointer
)
1119 GET_CURRENT_CONTEXT(ctx
);
1120 GLboolean tflag
, cflag
, nflag
; /* enable/disable flags */
1121 GLint tcomps
, ccomps
, vcomps
; /* components per texcoord, color, vertex */
1123 GLenum ctype
; /* color type */
1124 GLint coffset
, noffset
, voffset
;/* color, normal, vertex offsets */
1125 GLint defstride
; /* default stride */
1127 GLint coordUnitSave
;
1129 f
= sizeof(GLfloat
);
1130 c
= f
* ((4*sizeof(GLubyte
) + (f
-1)) / f
);
1133 gl_error( ctx
, GL_INVALID_VALUE
, "glInterleavedArrays(stride)" );
1139 tflag
= GL_FALSE
; cflag
= GL_FALSE
; nflag
= GL_FALSE
;
1140 tcomps
= 0; ccomps
= 0; vcomps
= 2;
1145 tflag
= GL_FALSE
; cflag
= GL_FALSE
; nflag
= GL_FALSE
;
1146 tcomps
= 0; ccomps
= 0; vcomps
= 3;
1151 tflag
= GL_FALSE
; cflag
= GL_TRUE
; nflag
= GL_FALSE
;
1152 tcomps
= 0; ccomps
= 4; vcomps
= 2;
1153 ctype
= GL_UNSIGNED_BYTE
;
1156 defstride
= c
+ 2*f
;
1159 tflag
= GL_FALSE
; cflag
= GL_TRUE
; nflag
= GL_FALSE
;
1160 tcomps
= 0; ccomps
= 4; vcomps
= 3;
1161 ctype
= GL_UNSIGNED_BYTE
;
1164 defstride
= c
+ 3*f
;
1167 tflag
= GL_FALSE
; cflag
= GL_TRUE
; nflag
= GL_FALSE
;
1168 tcomps
= 0; ccomps
= 3; vcomps
= 3;
1175 tflag
= GL_FALSE
; cflag
= GL_FALSE
; nflag
= GL_TRUE
;
1176 tcomps
= 0; ccomps
= 0; vcomps
= 3;
1181 case GL_C4F_N3F_V3F
:
1182 tflag
= GL_FALSE
; cflag
= GL_TRUE
; nflag
= GL_TRUE
;
1183 tcomps
= 0; ccomps
= 4; vcomps
= 3;
1191 tflag
= GL_TRUE
; cflag
= GL_FALSE
; nflag
= GL_FALSE
;
1192 tcomps
= 2; ccomps
= 0; vcomps
= 3;
1197 tflag
= GL_TRUE
; cflag
= GL_FALSE
; nflag
= GL_FALSE
;
1198 tcomps
= 4; ccomps
= 0; vcomps
= 4;
1202 case GL_T2F_C4UB_V3F
:
1203 tflag
= GL_TRUE
; cflag
= GL_TRUE
; nflag
= GL_FALSE
;
1204 tcomps
= 2; ccomps
= 4; vcomps
= 3;
1205 ctype
= GL_UNSIGNED_BYTE
;
1210 case GL_T2F_C3F_V3F
:
1211 tflag
= GL_TRUE
; cflag
= GL_TRUE
; nflag
= GL_FALSE
;
1212 tcomps
= 2; ccomps
= 3; vcomps
= 3;
1218 case GL_T2F_N3F_V3F
:
1219 tflag
= GL_TRUE
; cflag
= GL_FALSE
; nflag
= GL_TRUE
;
1220 tcomps
= 2; ccomps
= 0; vcomps
= 3;
1225 case GL_T2F_C4F_N3F_V3F
:
1226 tflag
= GL_TRUE
; cflag
= GL_TRUE
; nflag
= GL_TRUE
;
1227 tcomps
= 2; ccomps
= 4; vcomps
= 3;
1234 case GL_T4F_C4F_N3F_V4F
:
1235 tflag
= GL_TRUE
; cflag
= GL_TRUE
; nflag
= GL_TRUE
;
1236 tcomps
= 4; ccomps
= 4; vcomps
= 4;
1244 gl_error( ctx
, GL_INVALID_ENUM
, "glInterleavedArrays(format)" );
1252 _mesa_DisableClientState( GL_EDGE_FLAG_ARRAY
);
1253 _mesa_DisableClientState( GL_INDEX_ARRAY
);
1256 coordUnitSave
= ctx
->Array
.ActiveTexture
;
1259 GLint factor
= ctx
->Array
.TexCoordInterleaveFactor
;
1260 for (i
= 0; i
< factor
; i
++) {
1261 _mesa_ClientActiveTextureARB( (GLenum
) (GL_TEXTURE0_ARB
+ i
) );
1262 _mesa_EnableClientState( GL_TEXTURE_COORD_ARRAY
);
1263 glTexCoordPointer( tcomps
, GL_FLOAT
, stride
,
1264 (GLubyte
*) pointer
+ i
* coffset
);
1266 for (i
= factor
; i
< ctx
->Const
.MaxTextureUnits
; i
++) {
1267 _mesa_ClientActiveTextureARB( (GLenum
) (GL_TEXTURE0_ARB
+ i
) );
1268 _mesa_DisableClientState( GL_TEXTURE_COORD_ARRAY
);
1273 for (i
= 0; i
< ctx
->Const
.MaxTextureUnits
; i
++) {
1274 _mesa_ClientActiveTextureARB( (GLenum
) (GL_TEXTURE0_ARB
+ i
) );
1275 _mesa_DisableClientState( GL_TEXTURE_COORD_ARRAY
);
1278 /* Restore texture coordinate unit index */
1279 _mesa_ClientActiveTextureARB( (GLenum
) (GL_TEXTURE0_ARB
+ coordUnitSave
) );
1284 _mesa_EnableClientState( GL_COLOR_ARRAY
);
1285 glColorPointer( ccomps
, ctype
, stride
,
1286 (GLubyte
*) pointer
+ coffset
);
1289 _mesa_DisableClientState( GL_COLOR_ARRAY
);
1295 _mesa_EnableClientState( GL_NORMAL_ARRAY
);
1296 glNormalPointer( GL_FLOAT
, stride
,
1297 (GLubyte
*) pointer
+ noffset
);
1300 _mesa_DisableClientState( GL_NORMAL_ARRAY
);
1303 _mesa_EnableClientState( GL_VERTEX_ARRAY
);
1304 glVertexPointer( vcomps
, GL_FLOAT
, stride
,
1305 (GLubyte
*) pointer
+ voffset
);
1311 _mesa_DrawRangeElements(GLenum mode
, GLuint start
,
1312 GLuint end
, GLsizei count
,
1313 GLenum type
, const GLvoid
*indices
)
1315 GET_CURRENT_CONTEXT(ctx
);
1318 gl_error(ctx
, GL_INVALID_VALUE
, "glDrawRangeElements( end < start )");
1324 * XXX something in locked arrays is broken! If start = 0,
1325 * end = 1 and count = 2 we'll take the LockArrays path and
1326 * get incorrect results. See Scott McMillan's bug of 3 Jan 2000.
1327 * For now, don't use locked arrays.
1329 if (!ctx
->Array
.LockCount
&& 2*count
> (GLint
) 3*(end
-start
)) {
1330 glLockArraysEXT( start
, end
);
1331 glDrawElements( mode
, count
, type
, indices
);
1332 glUnlockArraysEXT();
1334 glDrawElements( mode
, count
, type
, indices
);
1337 glDrawElements( mode
, count
, type
, indices
);
1343 void gl_update_client_state( GLcontext
*ctx
)
1345 static const GLuint sz_flags
[5] = {
1352 static const GLuint tc_flags
[5] = {
1361 ctx
->Array
._Flags
= 0;
1362 ctx
->Array
._Summary
= 0;
1363 ctx
->input
->ArrayIncr
= 0;
1365 if (ctx
->Array
.Normal
.Enabled
) ctx
->Array
._Flags
|= VERT_NORM
;
1366 if (ctx
->Array
.Color
.Enabled
) ctx
->Array
._Flags
|= VERT_RGBA
;
1367 if (ctx
->Array
.SecondaryColor
.Enabled
) ctx
->Array
._Flags
|= VERT_SPEC_RGB
;
1368 if (ctx
->Array
.FogCoord
.Enabled
) ctx
->Array
._Flags
|= VERT_FOG_COORD
;
1369 if (ctx
->Array
.Index
.Enabled
) ctx
->Array
._Flags
|= VERT_INDEX
;
1370 if (ctx
->Array
.EdgeFlag
.Enabled
) ctx
->Array
._Flags
|= VERT_EDGE
;
1371 if (ctx
->Array
.Vertex
.Enabled
) {
1372 ctx
->Array
._Flags
|= sz_flags
[ctx
->Array
.Vertex
.Size
];
1373 ctx
->input
->ArrayIncr
= 1;
1375 for (i
= 0; i
< ctx
->Const
.MaxTextureUnits
; i
++) {
1376 if (ctx
->Array
.TexCoord
[i
].Enabled
) {
1377 ctx
->Array
._Flags
|= (tc_flags
[ctx
->Array
.TexCoord
[i
].Size
] << (i
* NR_TEXSIZE_BITS
));
1381 /* Not really important any more:
1383 ctx
->Array
._Summary
= ctx
->Array
._Flags
& VERT_DATA
;
1384 ctx
->input
->ArrayAndFlags
= ~ctx
->Array
._Flags
;
1385 ctx
->input
->ArrayEltFlush
= !(ctx
->CompileCVAFlag
);