1 /* $Id: varray.c,v 1.3 1999/09/07 22:31:30 brianp Exp $ */
4 * Mesa 3-D graphics library
7 * Copyright (C) 1999 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.
44 #include "translate.h"
50 #include "vbindirect.h"
54 #include "GL/xf86glx.h"
59 void GLAPIENTRY
glVertexPointer(CTX_ARG GLint size
, GLenum type
, GLsizei stride
,
67 if (size
<2 || size
>4) {
68 gl_error( ctx
, GL_INVALID_VALUE
, "glVertexPointer(size)" );
72 gl_error( ctx
, GL_INVALID_VALUE
, "glVertexPointer(stride)" );
76 if (MESA_VERBOSE
&(VERBOSE_VARRAY
|VERBOSE_API
))
77 fprintf(stderr
, "glVertexPointer( sz %d type %s stride %d )\n", size
,
78 gl_lookup_enum_by_nr( type
),
81 ctx
->Array
.Vertex
.StrideB
= stride
;
85 ctx
->Array
.Vertex
.StrideB
= size
*sizeof(GLshort
);
88 ctx
->Array
.Vertex
.StrideB
= size
*sizeof(GLint
);
91 ctx
->Array
.Vertex
.StrideB
= size
*sizeof(GLfloat
);
94 ctx
->Array
.Vertex
.StrideB
= size
*sizeof(GLdouble
);
97 gl_error( ctx
, GL_INVALID_ENUM
, "glVertexPointer(type)" );
101 ctx
->Array
.Vertex
.Size
= size
;
102 ctx
->Array
.Vertex
.Type
= type
;
103 ctx
->Array
.Vertex
.Stride
= stride
;
104 ctx
->Array
.Vertex
.Ptr
= (void *) ptr
;
105 ctx
->Array
.VertexFunc
= gl_trans_4f_tab
[size
][TYPE_IDX(type
)];
106 ctx
->Array
.VertexEltFunc
= gl_trans_elt_4f_tab
[size
][TYPE_IDX(type
)];
107 ctx
->Array
.NewArrayState
|= VERT_OBJ_ANY
;
108 ctx
->NewState
|= NEW_CLIENT_STATE
;
114 void GLAPIENTRY
glNormalPointer(CTX_ARG GLenum type
, GLsizei stride
,
123 gl_error( ctx
, GL_INVALID_VALUE
, "glNormalPointer(stride)" );
127 if (MESA_VERBOSE
&(VERBOSE_VARRAY
|VERBOSE_API
))
128 fprintf(stderr
, "glNormalPointer( type %s stride %d )\n",
129 gl_lookup_enum_by_nr( type
),
132 ctx
->Array
.Normal
.StrideB
= stride
;
136 ctx
->Array
.Normal
.StrideB
= 3*sizeof(GLbyte
);
139 ctx
->Array
.Normal
.StrideB
= 3*sizeof(GLshort
);
142 ctx
->Array
.Normal
.StrideB
= 3*sizeof(GLint
);
145 ctx
->Array
.Normal
.StrideB
= 3*sizeof(GLfloat
);
148 ctx
->Array
.Normal
.StrideB
= 3*sizeof(GLdouble
);
151 gl_error( ctx
, GL_INVALID_ENUM
, "glNormalPointer(type)" );
155 ctx
->Array
.Normal
.Type
= type
;
156 ctx
->Array
.Normal
.Stride
= stride
;
157 ctx
->Array
.Normal
.Ptr
= (void *) ptr
;
158 ctx
->Array
.NormalFunc
= gl_trans_3f_tab
[TYPE_IDX(type
)];
159 ctx
->Array
.NormalEltFunc
= gl_trans_elt_3f_tab
[TYPE_IDX(type
)];
160 ctx
->Array
.NewArrayState
|= VERT_NORM
;
161 ctx
->NewState
|= NEW_CLIENT_STATE
;
166 void GLAPIENTRY
glColorPointer(CTX_ARG GLint size
, GLenum type
, GLsizei stride
,
173 if (size
<3 || size
>4) {
174 gl_error( ctx
, GL_INVALID_VALUE
, "glColorPointer(size)" );
178 gl_error( ctx
, GL_INVALID_VALUE
, "glColorPointer(stride)" );
182 if (MESA_VERBOSE
&(VERBOSE_VARRAY
|VERBOSE_API
))
183 fprintf(stderr
, "glColorPointer( sz %d type %s stride %d )\n", size
,
184 gl_lookup_enum_by_nr( type
),
187 ctx
->Array
.Color
.StrideB
= stride
;
191 ctx
->Array
.Color
.StrideB
= size
*sizeof(GLbyte
);
193 case GL_UNSIGNED_BYTE
:
194 ctx
->Array
.Color
.StrideB
= size
*sizeof(GLubyte
);
197 ctx
->Array
.Color
.StrideB
= size
*sizeof(GLshort
);
199 case GL_UNSIGNED_SHORT
:
200 ctx
->Array
.Color
.StrideB
= size
*sizeof(GLushort
);
203 ctx
->Array
.Color
.StrideB
= size
*sizeof(GLint
);
205 case GL_UNSIGNED_INT
:
206 ctx
->Array
.Color
.StrideB
= size
*sizeof(GLuint
);
209 ctx
->Array
.Color
.StrideB
= size
*sizeof(GLfloat
);
212 ctx
->Array
.Color
.StrideB
= size
*sizeof(GLdouble
);
215 gl_error( ctx
, GL_INVALID_ENUM
, "glColorPointer(type)" );
219 ctx
->Array
.Color
.Size
= size
;
220 ctx
->Array
.Color
.Type
= type
;
221 ctx
->Array
.Color
.Stride
= stride
;
222 ctx
->Array
.Color
.Ptr
= (void *) ptr
;
223 ctx
->Array
.ColorFunc
= gl_trans_4ub_tab
[size
][TYPE_IDX(type
)];
224 ctx
->Array
.ColorEltFunc
= gl_trans_elt_4ub_tab
[size
][TYPE_IDX(type
)];
225 ctx
->Array
.NewArrayState
|= VERT_RGBA
;
226 ctx
->NewState
|= NEW_CLIENT_STATE
;
231 void GLAPIENTRY
glIndexPointer(CTX_ARG GLenum type
, GLsizei stride
,
240 gl_error( ctx
, GL_INVALID_VALUE
, "glIndexPointer(stride)" );
244 ctx
->Array
.Index
.StrideB
= stride
;
247 case GL_UNSIGNED_BYTE
:
248 ctx
->Array
.Index
.StrideB
= sizeof(GLubyte
);
251 ctx
->Array
.Index
.StrideB
= sizeof(GLshort
);
254 ctx
->Array
.Index
.StrideB
= sizeof(GLint
);
257 ctx
->Array
.Index
.StrideB
= sizeof(GLfloat
);
260 ctx
->Array
.Index
.StrideB
= sizeof(GLdouble
);
263 gl_error( ctx
, GL_INVALID_ENUM
, "glIndexPointer(type)" );
267 ctx
->Array
.Index
.Type
= type
;
268 ctx
->Array
.Index
.Stride
= stride
;
269 ctx
->Array
.Index
.Ptr
= (void *) ptr
;
270 ctx
->Array
.IndexFunc
= gl_trans_1ui_tab
[TYPE_IDX(type
)];
271 ctx
->Array
.IndexEltFunc
= gl_trans_elt_1ui_tab
[TYPE_IDX(type
)];
272 ctx
->Array
.NewArrayState
|= VERT_INDEX
;
273 ctx
->NewState
|= NEW_CLIENT_STATE
;
278 void GLAPIENTRY
glTexCoordPointer(CTX_ARG GLint size
, GLenum type
,
279 GLsizei stride
, const GLvoid
*ptr
)
288 texUnit
= ctx
->Array
.ActiveTexture
;
290 if (size
<1 || size
>4) {
291 gl_error( ctx
, GL_INVALID_VALUE
, "glTexCoordPointer(size)" );
295 gl_error( ctx
, GL_INVALID_VALUE
, "glTexCoordPointer(stride)" );
299 if (MESA_VERBOSE
&(VERBOSE_VARRAY
|VERBOSE_API
))
300 fprintf(stderr
, "glTexCoordPointer( unit %u sz %d type %s stride %d )\n",
303 gl_lookup_enum_by_nr( type
),
306 ctx
->Array
.TexCoord
[texUnit
].StrideB
= stride
;
310 ctx
->Array
.TexCoord
[texUnit
].StrideB
= size
*sizeof(GLshort
);
313 ctx
->Array
.TexCoord
[texUnit
].StrideB
= size
*sizeof(GLint
);
316 ctx
->Array
.TexCoord
[texUnit
].StrideB
= size
*sizeof(GLfloat
);
319 ctx
->Array
.TexCoord
[texUnit
].StrideB
= size
*sizeof(GLdouble
);
322 gl_error( ctx
, GL_INVALID_ENUM
, "glTexCoordPointer(type)" );
326 ctx
->Array
.TexCoord
[texUnit
].Size
= size
;
327 ctx
->Array
.TexCoord
[texUnit
].Type
= type
;
328 ctx
->Array
.TexCoord
[texUnit
].Stride
= stride
;
329 ctx
->Array
.TexCoord
[texUnit
].Ptr
= (void *) ptr
;
331 ctx
->Array
.TexCoordFunc
[texUnit
] = gl_trans_4f_tab
[size
][TYPE_IDX(type
)];
332 ctx
->Array
.TexCoordEltFunc
[texUnit
] = gl_trans_elt_4f_tab
[size
][TYPE_IDX(type
)];
333 ctx
->Array
.NewArrayState
|= PIPE_TEX(texUnit
);
334 ctx
->NewState
|= NEW_CLIENT_STATE
;
340 void GLAPIENTRY
glEdgeFlagPointer(CTX_ARG GLsizei stride
, const void *vptr
)
342 const GLboolean
*ptr
= (GLboolean
*)vptr
;
350 gl_error( ctx
, GL_INVALID_VALUE
, "glEdgeFlagPointer(stride)" );
353 ctx
->Array
.EdgeFlag
.Stride
= stride
;
354 ctx
->Array
.EdgeFlag
.StrideB
= stride
? stride
: sizeof(GLboolean
);
355 ctx
->Array
.EdgeFlag
.Ptr
= (GLboolean
*) ptr
;
356 if (stride
!= sizeof(GLboolean
)) {
357 ctx
->Array
.EdgeFlagFunc
= gl_trans_1ub_tab
[TYPE_IDX(GL_UNSIGNED_BYTE
)];
359 ctx
->Array
.EdgeFlagFunc
= 0;
361 ctx
->Array
.EdgeFlagEltFunc
= gl_trans_elt_1ub_tab
[TYPE_IDX(GL_UNSIGNED_BYTE
)];
362 ctx
->Array
.NewArrayState
|= VERT_EDGE
;
363 ctx
->NewState
|= NEW_CLIENT_STATE
;
367 /* Called only from gl_DrawElements
369 void gl_CVAEltPointer( GLcontext
*ctx
, GLenum type
, const GLvoid
*ptr
)
372 case GL_UNSIGNED_BYTE
:
373 ctx
->CVA
.Elt
.StrideB
= sizeof(GLubyte
);
375 case GL_UNSIGNED_SHORT
:
376 ctx
->CVA
.Elt
.StrideB
= sizeof(GLushort
);
378 case GL_UNSIGNED_INT
:
379 ctx
->CVA
.Elt
.StrideB
= sizeof(GLuint
);
382 gl_error( ctx
, GL_INVALID_ENUM
, "glEltPointer(type)" );
385 ctx
->CVA
.Elt
.Type
= type
;
386 ctx
->CVA
.Elt
.Stride
= 0;
387 ctx
->CVA
.Elt
.Ptr
= (void *) ptr
;
388 ctx
->CVA
.EltFunc
= gl_trans_1ui_tab
[TYPE_IDX(type
)];
389 ctx
->Array
.NewArrayState
|= VERT_ELT
; /* ??? */
394 /* KW: Batch function to exec all the array elements in the input
395 * buffer prior to transform. Done only the first time a vertex
396 * buffer is executed or compiled.
398 void gl_exec_array_elements( GLcontext
*ctx
, struct immediate
*IM
)
400 GLuint
*flags
= IM
->Flag
;
401 GLuint
*elts
= IM
->Elt
;
402 GLuint count
= IM
->Count
;
403 GLuint start
= IM
->Start
;
404 GLuint translate
= ctx
->Array
.Flags
;
407 if (translate
& VERT_OBJ_ANY
)
408 (ctx
->Array
.VertexEltFunc
)( IM
->Obj
,
410 flags
, elts
, (VERT_ELT
|VERT_OBJ_ANY
),
413 if (translate
& VERT_NORM
)
414 (ctx
->Array
.NormalEltFunc
)( IM
->Normal
,
416 flags
, elts
, (VERT_ELT
|VERT_NORM
),
419 if (translate
& VERT_EDGE
)
420 (ctx
->Array
.EdgeFlagEltFunc
)( IM
->EdgeFlag
,
421 &ctx
->Array
.EdgeFlag
,
422 flags
, elts
, (VERT_ELT
|VERT_EDGE
),
425 if (translate
& VERT_RGBA
)
426 (ctx
->Array
.ColorEltFunc
)( IM
->Color
,
428 flags
, elts
, (VERT_ELT
|VERT_RGBA
),
431 if (translate
& VERT_INDEX
)
432 (ctx
->Array
.IndexEltFunc
)( IM
->Index
,
434 flags
, elts
, (VERT_ELT
|VERT_INDEX
),
437 if (translate
& VERT_TEX0_ANY
)
438 (ctx
->Array
.TexCoordEltFunc
[0])( IM
->TexCoord
[0],
439 &ctx
->Array
.TexCoord
[0],
440 flags
, elts
, (VERT_ELT
|VERT_TEX0_ANY
),
443 if (translate
& VERT_TEX1_ANY
)
444 (ctx
->Array
.TexCoordEltFunc
[1])( IM
->TexCoord
[1],
445 &ctx
->Array
.TexCoord
[1],
446 flags
, elts
, (VERT_ELT
|VERT_TEX1_ANY
),
449 IM
->OrFlag
|= translate
;
451 /* Lighting ignores the and-flag, so still need to do this.
453 if (IM
->AndFlag
& VERT_ELT
) {
454 for (i
= 0 ; i
< count
; i
++)
455 flags
[i
] |= translate
;
456 IM
->AndFlag
|= translate
;
459 for (i
= 0 ; i
< count
; i
++) {
460 if (flags
[i
] & VERT_ELT
) flags
[i
] |= translate
;
463 IM
->AndFlag
= andflag
;
469 /* KW: I think this is moving in the right direction, but it still feels
470 * like we are doing way too much work.
472 void gl_DrawArrays( GLcontext
*ctx
, GLenum mode
, GLint start
, GLsizei count
)
474 struct vertex_buffer
*VB
= ctx
->VB
;
477 ASSERT_OUTSIDE_BEGIN_END_AND_FLUSH(ctx
, "glDrawArrays");
480 gl_error( ctx
, GL_INVALID_VALUE
, "glDrawArrays(count)" );
484 if (!ctx
->CompileFlag
&& ctx
->Array
.Vertex
.Enabled
)
486 GLint remaining
= count
;
490 GLvector4f tc
[MAX_TEXTURE_UNITS
];
494 GLuint update
= 0, translate
= 0;
495 struct vertex_array_pointers VSrc
;
496 struct immediate
*IM
= VB
->IM
;
497 struct gl_client_array
*client_data
;
498 struct gl_pipeline
*elt
= &ctx
->CVA
.elt
;
500 GLuint fallback
, required
;
503 gl_update_state( ctx
);
505 /* This will die miserably with CVA... Need more work to support this.
507 relock
= ctx
->CompileCVAFlag
;
508 ctx
->CompileCVAFlag
= 0;
510 if (!elt
->pipeline_valid
|| relock
)
511 gl_build_immediate_pipeline( ctx
);
513 required
= elt
->inputs
;
514 fallback
= (elt
->inputs
& ~ctx
->Array
.Summary
);
516 VSrc
.Color
= &IM
->v
.Color
;
517 VSrc
.Index
= &IM
->v
.Index
;
518 VSrc
.EdgeFlag
= &IM
->v
.EdgeFlag
;
519 VSrc
.TexCoord
[0] = &IM
->v
.TexCoord
[0];
520 VSrc
.TexCoord
[1] = &IM
->v
.TexCoord
[1];
521 VSrc
.Obj
= &IM
->v
.Obj
;
522 VSrc
.Normal
= &IM
->v
.Normal
;
524 if (required
& VERT_RGBA
)
526 client_data
= &ctx
->Array
.Color
;
527 if (fallback
& VERT_RGBA
)
528 client_data
= &ctx
->Fallback
.Color
;
530 if (client_data
->Type
== GL_UNSIGNED_BYTE
&&
531 client_data
->Size
== 4)
534 col
.data
= (GLubyte (*)[4]) client_data
->Ptr
;
535 col
.stride
= client_data
->StrideB
;
536 col
.flags
= VEC_NOT_WRITABLE
|VEC_GOOD_STRIDE
;
537 if (client_data
->StrideB
!= 4 * sizeof(GLubyte
))
538 col
.flags
^= VEC_STRIDE_FLAGS
;
542 translate
|= VERT_RGBA
;
546 if (required
& VERT_INDEX
)
548 client_data
= &ctx
->Array
.Index
;
549 if (fallback
& VERT_INDEX
)
550 client_data
= &ctx
->Fallback
.Index
;
552 if (client_data
->Type
== GL_UNSIGNED_INT
)
555 index
.data
= (GLuint
*) client_data
->Ptr
;
556 index
.stride
= client_data
->StrideB
;
557 index
.flags
= VEC_NOT_WRITABLE
|VEC_GOOD_STRIDE
;
558 if (client_data
->StrideB
!= sizeof(GLuint
))
559 index
.flags
^= VEC_STRIDE_FLAGS
;
561 update
|= VERT_INDEX
;
563 translate
|= VERT_INDEX
;
567 for (i
= 0 ; i
< MAX_TEXTURE_UNITS
; i
++)
569 GLuint flag
= VERT_TEX_ANY(i
);
571 if (required
& flag
) {
573 client_data
= &ctx
->Array
.TexCoord
[i
];
577 client_data
= &ctx
->Fallback
.TexCoord
[i
];
578 client_data
->Size
= gl_texcoord_size( ctx
->Current
.Flag
, i
);
581 if (client_data
->Type
== GL_FLOAT
)
583 VSrc
.TexCoord
[i
] = &tc
[i
];
584 tc
[i
].data
= (GLfloat (*)[4]) client_data
->Ptr
;
585 tc
[i
].stride
= client_data
->StrideB
;
586 tc
[i
].size
= client_data
->Size
;
587 tc
[i
].flags
= VEC_NOT_WRITABLE
|VEC_GOOD_STRIDE
;
588 if (tc
[i
].stride
|= 4 * sizeof(GLfloat
))
589 tc
[i
].flags
^= VEC_STRIDE_FLAGS
;
597 if (ctx
->Array
.Flags
!= ctx
->Array
.Flag
[0])
598 for (i
= 0 ; i
< VB_MAX
; i
++)
599 ctx
->Array
.Flag
[i
] = ctx
->Array
.Flags
;
602 if (ctx
->Array
.Vertex
.Type
== GL_FLOAT
)
605 obj
.data
= (GLfloat (*)[4]) ctx
->Array
.Vertex
.Ptr
;
606 obj
.stride
= ctx
->Array
.Vertex
.StrideB
;
607 obj
.size
= ctx
->Array
.Vertex
.Size
;
608 obj
.flags
= VEC_NOT_WRITABLE
|VEC_GOOD_STRIDE
;
609 if (obj
.stride
!= 4 * sizeof(GLfloat
))
610 obj
.flags
^= VEC_STRIDE_FLAGS
;
612 update
|= VERT_OBJ_ANY
;
616 translate
|= VERT_OBJ_ANY
;
619 if (required
& VERT_NORM
)
621 client_data
= &ctx
->Array
.Normal
;
622 if (fallback
& VERT_NORM
)
623 client_data
= &ctx
->Fallback
.Normal
;
625 if (client_data
->Type
== GL_FLOAT
)
629 norm
.data
= (GLfloat (*)[3]) client_data
->Ptr
;
630 norm
.stride
= client_data
->StrideB
;
633 translate
|= VERT_NORM
;
637 if ( (required
& VERT_EDGE
) &&
638 (mode
== GL_TRIANGLES
||
642 client_data
= &ctx
->Array
.EdgeFlag
;
644 if (fallback
& VERT_EDGE
)
645 client_data
= &ctx
->Fallback
.EdgeFlag
;
647 VSrc
.EdgeFlag
= &edge
;
648 edge
.data
= (GLboolean
*) client_data
->Ptr
;
649 edge
.stride
= client_data
->StrideB
;
650 edge
.flags
= VEC_NOT_WRITABLE
|VEC_GOOD_STRIDE
;
651 if (edge
.stride
!= sizeof(GLubyte
))
652 edge
.flags
^= VEC_STRIDE_FLAGS
;
657 VB
->Primitive
= IM
->Primitive
;
658 VB
->NextPrimitive
= IM
->NextPrimitive
;
659 VB
->MaterialMask
= IM
->MaterialMask
;
660 VB
->Material
= IM
->Material
;
663 while (remaining
> 0) {
664 GLint vbspace
= VB_MAX
- VB_START
;
668 if (vbspace
>= remaining
) {
670 VB
->LastPrimitive
= VB_START
+ n
;
673 VB
->LastPrimitive
= VB_START
;
682 if (update
& VERT_OBJ_ANY
)
683 obj
.start
= VEC_ELT(&obj
, GLfloat
, start
);
685 if (update
& VERT_NORM
)
686 norm
.start
= VEC_ELT(&norm
, GLfloat
, start
);
688 if (update
& VERT_EDGE
)
689 edge
.start
= VEC_ELT(&edge
, GLubyte
, start
);
691 if (update
& VERT_RGBA
)
692 col
.start
= VEC_ELT(&col
, GLubyte
, start
);
694 if (update
& VERT_INDEX
)
695 index
.start
= VEC_ELT(&index
, GLuint
, start
);
697 if (update
& VERT_TEX0_ANY
)
698 tc
[0].start
= VEC_ELT(&tc
[0], GLfloat
, start
);
700 if (update
& VERT_TEX1_ANY
)
701 tc
[1].start
= VEC_ELT(&tc
[1], GLfloat
, start
);
705 /* Translate data to fix up type and stride.
708 if (translate
& VERT_OBJ_ANY
) {
709 ctx
->Array
.VertexFunc( IM
->Obj
+ VB_START
,
710 &ctx
->Array
.Vertex
, start
, n
);
713 if (translate
& VERT_NORM
) {
714 ctx
->Array
.NormalFunc( IM
->Normal
+ VB_START
,
715 &ctx
->Array
.Normal
, start
, n
);
718 if (translate
& VERT_EDGE
) {
719 ctx
->Array
.EdgeFlagFunc( IM
->EdgeFlag
+ VB_START
,
720 &ctx
->Array
.EdgeFlag
, start
, n
);
723 if (translate
& VERT_RGBA
) {
724 ctx
->Array
.ColorFunc( IM
->Color
+ VB_START
,
725 &ctx
->Array
.Color
, start
, n
);
728 if (translate
& VERT_INDEX
) {
729 ctx
->Array
.IndexFunc( IM
->Index
+ VB_START
,
730 &ctx
->Array
.Index
, start
, n
);
733 if (translate
& VERT_TEX0_ANY
) {
734 IM
->v
.TexCoord
[0].size
= tc
[0].size
;
735 ctx
->Array
.TexCoordFunc
[0]( IM
->TexCoord
[0] + VB_START
,
736 &ctx
->Array
.TexCoord
[0], start
, n
);
739 if (translate
& VERT_TEX1_ANY
) {
740 IM
->v
.TexCoord
[1].size
= tc
[1].size
;
741 ctx
->Array
.TexCoordFunc
[1]( IM
->TexCoord
[1] + VB_START
,
742 &ctx
->Array
.TexCoord
[1], start
, n
);
747 VB
->ObjPtr
= VSrc
.Obj
;
748 VB
->NormalPtr
= VSrc
.Normal
;
749 VB
->Color
[0] = VB
->Color
[1] = VB
->ColorPtr
= VSrc
.Color
;
750 VB
->IndexPtr
= VSrc
.Index
;
751 VB
->EdgeFlagPtr
= VSrc
.EdgeFlag
;
752 VB
->TexCoordPtr
[0] = VSrc
.TexCoord
[0];
753 VB
->TexCoordPtr
[1] = VSrc
.TexCoord
[1];
755 VB
->Flag
= ctx
->Array
.Flag
;
756 VB
->AndFlag
= ctx
->Array
.Flags
;
757 VB
->OrFlag
= ctx
->Array
.Flags
;
759 count
= VB
->Count
= VB_START
+ n
;
761 VB
->ObjPtr
->count
= count
;
762 VB
->NormalPtr
->count
= count
;
763 VB
->ColorPtr
->count
= count
;
764 VB
->IndexPtr
->count
= count
;
765 VB
->EdgeFlagPtr
->count
= count
;
766 VB
->TexCoordPtr
[0]->count
= count
;
767 VB
->TexCoordPtr
[1]->count
= count
;
769 VB
->Flag
[count
] |= VERT_END_VB
;
770 VB
->Flag
[VB_START
] |= VERT_NORM
;
771 /* VB->Flag[VB_START] |= (IM->Flag[vb_start] & VERT_MATERIAL); */
773 VB
->NextPrimitive
[VB
->CopyStart
] = VB
->Count
;
774 VB
->Primitive
[VB
->CopyStart
] = mode
;
776 /* Transform and render.
778 gl_run_pipeline( VB
);
781 ctx
->Array
.Flag
[count
] = ctx
->Array
.Flags
;
782 ctx
->Array
.Flag
[VB_START
] = ctx
->Array
.Flags
;
783 IM
->Flag
[VB_START
] = 0;
789 ctx
->CompileCVAFlag
= relock
;
791 else if (ctx
->Array
.Vertex
.Enabled
)
793 /* The GL_COMPILE and GL_COMPILE_AND_EXECUTE cases. These
794 * could be handled by the above code, but it gets a little
797 /* No need to reset - never called from inside a display list */
798 gl_Begin( ctx
, mode
);
799 for (i
=0;i
<count
;i
++) {
800 gl_ArrayElement( ctx
, start
+i
);
806 /* The degenerate case where vertices are not enabled - only
807 * need to process the very final array element, as all of the
808 * preceding ones would be overwritten anyway.
810 gl_Begin( ctx
, mode
);
811 gl_ArrayElement( ctx
, start
+count
);
818 /* KW: Exactly fakes the effects of calling glArrayElement multiple times.
819 * Compilation is handled via. the IM->maybe_transform_vb() callback.
821 #define DRAW_ELT(FUNC, TYPE) \
822 static void FUNC( GLcontext *ctx, GLenum mode, \
823 TYPE *indices, GLuint count ) \
827 if (count) gl_Begin( ctx, mode ); \
829 for (j = 0 ; j < count ; ) { \
830 GLuint nr = MIN2( VB_MAX, count - j + VB_START ); \
831 struct immediate *IM = ctx->input; \
832 GLuint sf = IM->Flag[VB_START]; \
834 for (i = VB_START ; i < nr ; i++) { \
835 IM->Elt[i] = (GLuint) *indices++; \
836 IM->Flag[i] = VERT_ELT; \
839 if (j == 0) IM->Flag[VB_START] |= sf; \
842 j += nr - VB_START; \
844 if (j == count) gl_End( ctx ); \
846 IM->maybe_transform_vb( IM ); \
850 DRAW_ELT( draw_elt_ubyte
, GLubyte
)
851 DRAW_ELT( draw_elt_ushort
, GLushort
)
852 DRAW_ELT( draw_elt_uint
, GLuint
)
855 static GLuint natural_stride
[0x10] =
857 sizeof(GLbyte
), /* 0 */
858 sizeof(GLubyte
), /* 1 */
859 sizeof(GLshort
), /* 2 */
860 sizeof(GLushort
), /* 3 */
861 sizeof(GLint
), /* 4 */
862 sizeof(GLuint
), /* 5 */
863 sizeof(GLfloat
), /* 6 */
864 2 * sizeof(GLbyte
), /* 7 */
865 3 * sizeof(GLbyte
), /* 8 */
866 4 * sizeof(GLbyte
), /* 9 */
867 sizeof(GLdouble
), /* a */
875 void GLAPIENTRY
glDrawElements(CTX_ARG GLenum mode
, GLsizei count
,
876 GLenum type
, const GLvoid
*indices
)
886 ASSERT_OUTSIDE_BEGIN_END_AND_FLUSH(ctx
, "glDrawElements");
889 gl_error( ctx
, GL_INVALID_VALUE
, "glDrawElements(count)" );
893 if (mode
< 0 || mode
> GL_POLYGON
) {
894 gl_error( ctx
, GL_INVALID_ENUM
, "glDrawArrays(mode)" );
898 if (type
!= GL_UNSIGNED_INT
&& type
!= GL_UNSIGNED_BYTE
&& type
!= GL_UNSIGNED_SHORT
)
900 gl_error( ctx
, GL_INVALID_ENUM
, "glDrawElements(type)" );
905 gl_update_state(ctx
);
907 if (ctx
->CompileCVAFlag
)
909 #if defined(MESA_CVA_PROF)
913 /* Treat VERT_ELT like a special client array.
915 ctx
->Array
.NewArrayState
|= VERT_ELT
;
916 ctx
->Array
.Summary
|= VERT_ELT
;
917 ctx
->Array
.Flags
|= VERT_ELT
;
919 cva
->elt_mode
= mode
;
920 cva
->elt_count
= count
;
921 cva
->Elt
.Type
= type
;
922 cva
->Elt
.Ptr
= (void *) indices
;
923 cva
->Elt
.StrideB
= natural_stride
[TYPE_IDX(type
)];
924 cva
->EltFunc
= gl_trans_1ui_tab
[TYPE_IDX(type
)];
926 if (!cva
->pre
.pipeline_valid
)
927 gl_build_precalc_pipeline( ctx
);
928 else if (MESA_VERBOSE
& VERBOSE_PIPELINE
)
929 fprintf(stderr
, ": dont rebuild\n");
931 gl_cva_force_precalc( ctx
);
933 /* Did we 'precalculate' the render op?
935 if (ctx
->CVA
.pre
.ops
& PIPE_OP_RENDER
) {
936 ctx
->Array
.NewArrayState
|= VERT_ELT
;
937 ctx
->Array
.Summary
&= ~VERT_ELT
;
938 ctx
->Array
.Flags
&= ~VERT_ELT
;
942 if ( (MESA_VERBOSE
&VERBOSE_VARRAY
) )
943 printf("using immediate\n");
947 /* Otherwise, have to use the immediate path to render.
950 case GL_UNSIGNED_BYTE
:
952 GLubyte
*ub_indices
= (GLubyte
*) indices
;
953 if (ctx
->Array
.Summary
& VERT_OBJ_ANY
) {
954 draw_elt_ubyte( ctx
, mode
, ub_indices
, count
);
956 gl_ArrayElement( ctx
, (GLuint
) ub_indices
[count
-1] );
960 case GL_UNSIGNED_SHORT
:
962 GLushort
*us_indices
= (GLushort
*) indices
;
963 if (ctx
->Array
.Summary
& VERT_OBJ_ANY
) {
964 draw_elt_ushort( ctx
, mode
, us_indices
, count
);
966 gl_ArrayElement( ctx
, (GLuint
) us_indices
[count
-1] );
970 case GL_UNSIGNED_INT
:
972 GLuint
*ui_indices
= (GLuint
*) indices
;
973 if (ctx
->Array
.Summary
& VERT_OBJ_ANY
) {
974 draw_elt_uint( ctx
, mode
, ui_indices
, count
);
976 gl_ArrayElement( ctx
, ui_indices
[count
-1] );
981 gl_error( ctx
, GL_INVALID_ENUM
, "glDrawElements(type)" );
985 if (ctx
->CompileCVAFlag
) {
986 ctx
->Array
.NewArrayState
|= VERT_ELT
;
987 ctx
->Array
.Summary
&= ~VERT_ELT
;
993 void GLAPIENTRY
glInterleavedArrays(CTX_ARG GLenum format
, GLsizei stride
,
994 const GLvoid
*pointer
)
997 GLboolean tflag
, cflag
, nflag
; /* enable/disable flags */
998 GLint tcomps
, ccomps
, vcomps
; /* components per texcoord, color, vertex */
1000 GLenum ctype
; /* color type */
1001 GLint coffset
, noffset
, voffset
;/* color, normal, vertex offsets */
1002 GLint defstride
; /* default stride */
1004 GLint coordUnitSave
;
1011 f
= sizeof(GLfloat
);
1012 c
= f
* ((4*sizeof(GLubyte
) + (f
-1)) / f
);
1015 gl_error( ctx
, GL_INVALID_VALUE
, "glInterleavedArrays(stride)" );
1021 tflag
= GL_FALSE
; cflag
= GL_FALSE
; nflag
= GL_FALSE
;
1022 tcomps
= 0; ccomps
= 0; vcomps
= 2;
1027 tflag
= GL_FALSE
; cflag
= GL_FALSE
; nflag
= GL_FALSE
;
1028 tcomps
= 0; ccomps
= 0; vcomps
= 3;
1033 tflag
= GL_FALSE
; cflag
= GL_TRUE
; nflag
= GL_FALSE
;
1034 tcomps
= 0; ccomps
= 4; vcomps
= 2;
1035 ctype
= GL_UNSIGNED_BYTE
;
1038 defstride
= c
+ 2*f
;
1041 tflag
= GL_FALSE
; cflag
= GL_TRUE
; nflag
= GL_FALSE
;
1042 tcomps
= 0; ccomps
= 4; vcomps
= 3;
1043 ctype
= GL_UNSIGNED_BYTE
;
1046 defstride
= c
+ 3*f
;
1049 tflag
= GL_FALSE
; cflag
= GL_TRUE
; nflag
= GL_FALSE
;
1050 tcomps
= 0; ccomps
= 3; vcomps
= 3;
1057 tflag
= GL_FALSE
; cflag
= GL_FALSE
; nflag
= GL_TRUE
;
1058 tcomps
= 0; ccomps
= 0; vcomps
= 3;
1063 case GL_C4F_N3F_V3F
:
1064 tflag
= GL_FALSE
; cflag
= GL_TRUE
; nflag
= GL_TRUE
;
1065 tcomps
= 0; ccomps
= 4; vcomps
= 3;
1073 tflag
= GL_TRUE
; cflag
= GL_FALSE
; nflag
= GL_FALSE
;
1074 tcomps
= 2; ccomps
= 0; vcomps
= 3;
1079 tflag
= GL_TRUE
; cflag
= GL_FALSE
; nflag
= GL_FALSE
;
1080 tcomps
= 4; ccomps
= 0; vcomps
= 4;
1084 case GL_T2F_C4UB_V3F
:
1085 tflag
= GL_TRUE
; cflag
= GL_TRUE
; nflag
= GL_FALSE
;
1086 tcomps
= 2; ccomps
= 4; vcomps
= 3;
1087 ctype
= GL_UNSIGNED_BYTE
;
1092 case GL_T2F_C3F_V3F
:
1093 tflag
= GL_TRUE
; cflag
= GL_TRUE
; nflag
= GL_FALSE
;
1094 tcomps
= 2; ccomps
= 3; vcomps
= 3;
1100 case GL_T2F_N3F_V3F
:
1101 tflag
= GL_TRUE
; cflag
= GL_FALSE
; nflag
= GL_TRUE
;
1102 tcomps
= 2; ccomps
= 0; vcomps
= 3;
1107 case GL_T2F_C4F_N3F_V3F
:
1108 tflag
= GL_TRUE
; cflag
= GL_TRUE
; nflag
= GL_TRUE
;
1109 tcomps
= 2; ccomps
= 4; vcomps
= 3;
1116 case GL_T4F_C4F_N3F_V4F
:
1117 tflag
= GL_TRUE
; cflag
= GL_TRUE
; nflag
= GL_TRUE
;
1118 tcomps
= 4; ccomps
= 4; vcomps
= 4;
1126 gl_error( ctx
, GL_INVALID_ENUM
, "glInterleavedArrays(format)" );
1134 gl_DisableClientState( ctx
, GL_EDGE_FLAG_ARRAY
);
1135 gl_DisableClientState( ctx
, GL_INDEX_ARRAY
);
1138 coordUnitSave
= ctx
->Array
.ActiveTexture
;
1141 GLint factor
= ctx
->Array
.TexCoordInterleaveFactor
;
1142 for (i
= 0; i
< factor
; i
++) {
1143 gl_ActiveTexture( ctx
, (GLenum
) (GL_TEXTURE0_ARB
+ i
) );
1144 gl_EnableClientState( ctx
, GL_TEXTURE_COORD_ARRAY
);
1145 glTexCoordPointer(CTX_PRM tcomps
, GL_FLOAT
, stride
,
1146 (GLubyte
*) pointer
+ i
* coffset
);
1148 for (i
= factor
; i
< ctx
->Const
.MaxTextureUnits
; i
++) {
1149 gl_ActiveTexture( ctx
, (GLenum
) (GL_TEXTURE0_ARB
+ i
) );
1150 gl_DisableClientState( ctx
, GL_TEXTURE_COORD_ARRAY
);
1155 for (i
= 0; i
< ctx
->Const
.MaxTextureUnits
; i
++) {
1156 gl_ActiveTexture( ctx
, (GLenum
) (GL_TEXTURE0_ARB
+ i
) );
1157 gl_DisableClientState( ctx
, GL_TEXTURE_COORD_ARRAY
);
1160 /* Restore texture coordinate unit index */
1161 gl_ActiveTexture( ctx
, (GLenum
) (GL_TEXTURE0_ARB
+ coordUnitSave
) );
1166 gl_EnableClientState( ctx
, GL_COLOR_ARRAY
);
1167 glColorPointer(CTX_PRM ccomps
, ctype
, stride
,
1168 (GLubyte
*) pointer
+ coffset
);
1171 gl_DisableClientState( ctx
, GL_COLOR_ARRAY
);
1177 gl_EnableClientState( ctx
, GL_NORMAL_ARRAY
);
1178 glNormalPointer(CTX_PRM GL_FLOAT
, stride
,
1179 (GLubyte
*) pointer
+ noffset
);
1182 gl_DisableClientState( ctx
, GL_NORMAL_ARRAY
);
1185 gl_EnableClientState( ctx
, GL_VERTEX_ARRAY
);
1186 glVertexPointer(CTX_PRM vcomps
, GL_FLOAT
, stride
,
1187 (GLubyte
*) pointer
+ voffset
);
1192 void GLAPIENTRY
glDrawRangeElements(CTX_ARG GLenum mode
, GLuint start
,
1193 GLuint end
, GLsizei count
,
1194 GLenum type
, const GLvoid
*indices
)
1202 gl_error(ctx
, GL_INVALID_VALUE
, "glDrawRangeElements( end < start )");
1206 if (!ctx
->Array
.LockCount
&& 2*count
> 3*(end
-start
)) {
1207 glLockArraysEXT(CTX_PRM start
, end
);
1208 glDrawElements(CTX_PRM mode
, count
, type
, indices
);
1209 glUnlockArraysEXT(CTX_VPRM
);
1211 glDrawElements(CTX_PRM mode
, count
, type
, indices
);
1217 void gl_update_client_state( GLcontext
*ctx
)
1219 static GLuint sz_flags
[5] = { 0,
1225 static GLuint tc_flags
[5] = { 0,
1231 ctx
->Array
.Flags
= 0;
1232 ctx
->Array
.Summary
= 0;
1233 ctx
->input
->ArrayIncr
= 0;
1235 if (ctx
->Array
.Normal
.Enabled
) ctx
->Array
.Flags
|= VERT_NORM
;
1236 if (ctx
->Array
.Color
.Enabled
) ctx
->Array
.Flags
|= VERT_RGBA
;
1237 if (ctx
->Array
.Index
.Enabled
) ctx
->Array
.Flags
|= VERT_INDEX
;
1238 if (ctx
->Array
.EdgeFlag
.Enabled
) ctx
->Array
.Flags
|= VERT_EDGE
;
1239 if (ctx
->Array
.Vertex
.Enabled
) {
1240 ctx
->Array
.Flags
|= sz_flags
[ctx
->Array
.Vertex
.Size
];
1241 ctx
->input
->ArrayIncr
= 1;
1243 if (ctx
->Array
.TexCoord
[0].Enabled
) {
1244 ctx
->Array
.Flags
|= tc_flags
[ctx
->Array
.TexCoord
[0].Size
];
1246 if (ctx
->Array
.TexCoord
[1].Enabled
) {
1247 ctx
->Array
.Flags
|= (tc_flags
[ctx
->Array
.TexCoord
[1].Size
] << NR_TEXSIZE_BITS
);
1250 /* Not really important any more:
1252 ctx
->Array
.Summary
= ctx
->Array
.Flags
& VERT_DATA
;
1253 ctx
->input
->ArrayAndFlags
= ~ctx
->Array
.Flags
;
1254 ctx
->input
->ArrayEltFlush
= !(ctx
->CompileCVAFlag
);