1 /* $Id: varray.c,v 1.10 1999/11/09 09:18:40 keithw 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.
35 #include "GL/xf86glx.h"
48 #include "translate.h"
54 #include "vbindirect.h"
58 #include "GL/xf86glx.h"
62 #if defined(GLX_DIRECT_RENDERING) && !defined(XFree86Server) && !defined(GLX_USE_DLOPEN)
63 #define NEED_MESA_FUNCS_WRAPPED
68 void GLAPIENTRY
glVertexPointer(CTX_ARG GLint size
, GLenum type
, GLsizei stride
,
76 if (size
<2 || size
>4) {
77 gl_error( ctx
, GL_INVALID_VALUE
, "glVertexPointer(size)" );
81 gl_error( ctx
, GL_INVALID_VALUE
, "glVertexPointer(stride)" );
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
),
90 ctx
->Array
.Vertex
.StrideB
= stride
;
94 ctx
->Array
.Vertex
.StrideB
= size
*sizeof(GLshort
);
97 ctx
->Array
.Vertex
.StrideB
= size
*sizeof(GLint
);
100 ctx
->Array
.Vertex
.StrideB
= size
*sizeof(GLfloat
);
103 ctx
->Array
.Vertex
.StrideB
= size
*sizeof(GLdouble
);
106 gl_error( ctx
, GL_INVALID_ENUM
, "glVertexPointer(type)" );
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
;
123 void GLAPIENTRY
glNormalPointer(CTX_ARG GLenum type
, GLsizei stride
,
132 gl_error( ctx
, GL_INVALID_VALUE
, "glNormalPointer(stride)" );
136 if (MESA_VERBOSE
&(VERBOSE_VARRAY
|VERBOSE_API
))
137 fprintf(stderr
, "glNormalPointer( type %s stride %d )\n",
138 gl_lookup_enum_by_nr( type
),
141 ctx
->Array
.Normal
.StrideB
= stride
;
145 ctx
->Array
.Normal
.StrideB
= 3*sizeof(GLbyte
);
148 ctx
->Array
.Normal
.StrideB
= 3*sizeof(GLshort
);
151 ctx
->Array
.Normal
.StrideB
= 3*sizeof(GLint
);
154 ctx
->Array
.Normal
.StrideB
= 3*sizeof(GLfloat
);
157 ctx
->Array
.Normal
.StrideB
= 3*sizeof(GLdouble
);
160 gl_error( ctx
, GL_INVALID_ENUM
, "glNormalPointer(type)" );
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
;
175 void GLAPIENTRY
glColorPointer(CTX_ARG GLint size
, GLenum type
, GLsizei stride
,
182 if (size
<3 || size
>4) {
183 gl_error( ctx
, GL_INVALID_VALUE
, "glColorPointer(size)" );
187 gl_error( ctx
, GL_INVALID_VALUE
, "glColorPointer(stride)" );
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
),
196 ctx
->Array
.Color
.StrideB
= stride
;
200 ctx
->Array
.Color
.StrideB
= size
*sizeof(GLbyte
);
202 case GL_UNSIGNED_BYTE
:
203 ctx
->Array
.Color
.StrideB
= size
*sizeof(GLubyte
);
206 ctx
->Array
.Color
.StrideB
= size
*sizeof(GLshort
);
208 case GL_UNSIGNED_SHORT
:
209 ctx
->Array
.Color
.StrideB
= size
*sizeof(GLushort
);
212 ctx
->Array
.Color
.StrideB
= size
*sizeof(GLint
);
214 case GL_UNSIGNED_INT
:
215 ctx
->Array
.Color
.StrideB
= size
*sizeof(GLuint
);
218 ctx
->Array
.Color
.StrideB
= size
*sizeof(GLfloat
);
221 ctx
->Array
.Color
.StrideB
= size
*sizeof(GLdouble
);
224 gl_error( ctx
, GL_INVALID_ENUM
, "glColorPointer(type)" );
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
;
240 void GLAPIENTRY
glIndexPointer(CTX_ARG GLenum type
, GLsizei stride
,
249 gl_error( ctx
, GL_INVALID_VALUE
, "glIndexPointer(stride)" );
253 ctx
->Array
.Index
.StrideB
= stride
;
256 case GL_UNSIGNED_BYTE
:
257 ctx
->Array
.Index
.StrideB
= sizeof(GLubyte
);
260 ctx
->Array
.Index
.StrideB
= sizeof(GLshort
);
263 ctx
->Array
.Index
.StrideB
= sizeof(GLint
);
266 ctx
->Array
.Index
.StrideB
= sizeof(GLfloat
);
269 ctx
->Array
.Index
.StrideB
= sizeof(GLdouble
);
272 gl_error( ctx
, GL_INVALID_ENUM
, "glIndexPointer(type)" );
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
;
287 void GLAPIENTRY
glTexCoordPointer(CTX_ARG GLint size
, GLenum type
,
288 GLsizei stride
, const GLvoid
*ptr
)
297 texUnit
= ctx
->Array
.ActiveTexture
;
299 if (size
<1 || size
>4) {
300 gl_error( ctx
, GL_INVALID_VALUE
, "glTexCoordPointer(size)" );
304 gl_error( ctx
, GL_INVALID_VALUE
, "glTexCoordPointer(stride)" );
308 if (MESA_VERBOSE
&(VERBOSE_VARRAY
|VERBOSE_API
))
309 fprintf(stderr
, "glTexCoordPointer( unit %u sz %d type %s stride %d )\n",
312 gl_lookup_enum_by_nr( type
),
315 ctx
->Array
.TexCoord
[texUnit
].StrideB
= stride
;
319 ctx
->Array
.TexCoord
[texUnit
].StrideB
= size
*sizeof(GLshort
);
322 ctx
->Array
.TexCoord
[texUnit
].StrideB
= size
*sizeof(GLint
);
325 ctx
->Array
.TexCoord
[texUnit
].StrideB
= size
*sizeof(GLfloat
);
328 ctx
->Array
.TexCoord
[texUnit
].StrideB
= size
*sizeof(GLdouble
);
331 gl_error( ctx
, GL_INVALID_ENUM
, "glTexCoordPointer(type)" );
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
;
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
;
349 void GLAPIENTRY
glEdgeFlagPointer(CTX_ARG GLsizei stride
, const void *vptr
)
351 const GLboolean
*ptr
= (GLboolean
*)vptr
;
359 gl_error( ctx
, GL_INVALID_VALUE
, "glEdgeFlagPointer(stride)" );
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
)];
368 ctx
->Array
.EdgeFlagFunc
= 0;
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
;
376 /* Called only from gl_DrawElements
378 void gl_CVAEltPointer( GLcontext
*ctx
, GLenum type
, const GLvoid
*ptr
)
381 case GL_UNSIGNED_BYTE
:
382 ctx
->CVA
.Elt
.StrideB
= sizeof(GLubyte
);
384 case GL_UNSIGNED_SHORT
:
385 ctx
->CVA
.Elt
.StrideB
= sizeof(GLushort
);
387 case GL_UNSIGNED_INT
:
388 ctx
->CVA
.Elt
.StrideB
= sizeof(GLuint
);
391 gl_error( ctx
, GL_INVALID_ENUM
, "glEltPointer(type)" );
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
; /* ??? */
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.
407 * KW: Have to do this after each glEnd if cva isn't active. (also
408 * have to do it after each full buffer)
410 void gl_exec_array_elements( GLcontext
*ctx
, struct immediate
*IM
,
414 GLuint
*flags
= IM
->Flag
;
415 GLuint
*elts
= IM
->Elt
;
416 GLuint translate
= ctx
->Array
.Flags
;
419 if (MESA_VERBOSE
&VERBOSE_IMMEDIATE
)
420 fprintf(stderr
, "exec_array_elements %d .. %d\n", start
, count
);
422 if (translate
& VERT_OBJ_ANY
)
423 (ctx
->Array
.VertexEltFunc
)( IM
->Obj
,
425 flags
, elts
, (VERT_ELT
|VERT_OBJ_ANY
),
428 if (translate
& VERT_NORM
)
429 (ctx
->Array
.NormalEltFunc
)( IM
->Normal
,
431 flags
, elts
, (VERT_ELT
|VERT_NORM
),
434 if (translate
& VERT_EDGE
)
435 (ctx
->Array
.EdgeFlagEltFunc
)( IM
->EdgeFlag
,
436 &ctx
->Array
.EdgeFlag
,
437 flags
, elts
, (VERT_ELT
|VERT_EDGE
),
440 if (translate
& VERT_RGBA
)
441 (ctx
->Array
.ColorEltFunc
)( IM
->Color
,
443 flags
, elts
, (VERT_ELT
|VERT_RGBA
),
446 if (translate
& VERT_INDEX
)
447 (ctx
->Array
.IndexEltFunc
)( IM
->Index
,
449 flags
, elts
, (VERT_ELT
|VERT_INDEX
),
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
),
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
),
464 /* Lighting ignores the and-flag, so still need to do this.
466 /* fprintf(stderr, "start %d count %d\n", start, count); */
467 /* gl_print_vert_flags("translate", translate); */
469 for (i
= start
; i
< count
; i
++)
470 if (flags
[i
] & VERT_ELT
) {
471 /* flags[i] &= ~VERT_ELT; */
472 flags
[i
] |= translate
;
478 /* KW: I think this is moving in the right direction, but it still feels
479 * like we are doing way too much work.
481 void gl_DrawArrays( GLcontext
*ctx
, GLenum mode
, GLint start
, GLsizei count
)
483 struct vertex_buffer
*VB
= ctx
->VB
;
486 ASSERT_OUTSIDE_BEGIN_END_AND_FLUSH(ctx
, "glDrawArrays");
489 gl_error( ctx
, GL_INVALID_VALUE
, "glDrawArrays(count)" );
493 if (!ctx
->CompileFlag
&& ctx
->Array
.Vertex
.Enabled
)
495 GLint remaining
= count
;
499 GLvector4f tc
[MAX_TEXTURE_UNITS
];
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
;
509 GLuint fallback
, required
;
512 gl_update_state( ctx
);
514 /* This will die miserably with CVA... Need more work to support this.
516 relock
= ctx
->CompileCVAFlag
;
517 ctx
->CompileCVAFlag
= 0;
519 if (!elt
->pipeline_valid
|| relock
)
520 gl_build_immediate_pipeline( ctx
);
522 required
= elt
->inputs
;
523 fallback
= (elt
->inputs
& ~ctx
->Array
.Summary
);
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
;
533 if (required
& VERT_RGBA
)
535 client_data
= &ctx
->Array
.Color
;
536 if (fallback
& VERT_RGBA
)
537 client_data
= &ctx
->Fallback
.Color
;
539 translate
|= VERT_RGBA
;
542 if (required
& VERT_INDEX
)
544 client_data
= &ctx
->Array
.Index
;
545 if (fallback
& VERT_INDEX
)
546 client_data
= &ctx
->Fallback
.Index
;
548 translate
|= VERT_INDEX
;
551 for (i
= 0 ; i
< MAX_TEXTURE_UNITS
; i
++)
553 GLuint flag
= VERT_TEX_ANY(i
);
555 if (required
& flag
) {
557 client_data
= &ctx
->Array
.TexCoord
[i
];
561 client_data
= &ctx
->Fallback
.TexCoord
[i
];
562 client_data
->Size
= gl_texcoord_size( ctx
->Current
.Flag
, i
);
569 if (ctx
->Array
.Flags
!= ctx
->Array
.Flag
[0])
570 for (i
= 0 ; i
< VB_MAX
; i
++)
571 ctx
->Array
.Flag
[i
] = ctx
->Array
.Flags
;
574 translate
|= VERT_OBJ_ANY
;
576 if (required
& VERT_NORM
)
578 client_data
= &ctx
->Array
.Normal
;
579 if (fallback
& VERT_NORM
)
580 client_data
= &ctx
->Fallback
.Normal
;
582 translate
|= VERT_NORM
;
585 if ( (required
& VERT_EDGE
) &&
586 (mode
== GL_TRIANGLES
||
590 client_data
= &ctx
->Array
.EdgeFlag
;
592 if (fallback
& VERT_EDGE
)
593 client_data
= &ctx
->Fallback
.EdgeFlag
;
595 translate
|= VERT_EDGE
;
598 VB
->Primitive
= IM
->Primitive
;
599 VB
->NextPrimitive
= IM
->NextPrimitive
;
600 VB
->MaterialMask
= IM
->MaterialMask
;
601 VB
->Material
= IM
->Material
;
604 while (remaining
> 0) {
605 GLint vbspace
= VB_MAX
- VB_START
;
609 if (vbspace
>= remaining
) {
611 VB
->LastPrimitive
= VB_START
+ n
;
614 VB
->LastPrimitive
= VB_START
;
622 /* Disabled - always do the copy. No real loss
623 * until we improve vertex copying anyway.
626 if (update
& VERT_OBJ_ANY
)
627 obj
.start
= VEC_ELT(&obj
, GLfloat
, start
);
629 if (update
& VERT_NORM
)
630 norm
.start
= VEC_ELT(&norm
, GLfloat
, start
);
632 if (update
& VERT_EDGE
)
633 edge
.start
= VEC_ELT(&edge
, GLubyte
, start
);
635 if (update
& VERT_RGBA
)
636 col
.start
= VEC_ELT(&col
, GLubyte
, start
);
638 if (update
& VERT_INDEX
)
639 index
.start
= VEC_ELT(&index
, GLuint
, start
);
641 if (update
& VERT_TEX0_ANY
)
642 tc
[0].start
= VEC_ELT(&tc
[0], GLfloat
, start
);
644 if (update
& VERT_TEX1_ANY
)
645 tc
[1].start
= VEC_ELT(&tc
[1], GLfloat
, start
);
649 /* Translate data to fix up type and stride.
652 if (translate
& VERT_OBJ_ANY
) {
653 ctx
->Array
.VertexFunc( IM
->Obj
+ VB_START
,
654 &ctx
->Array
.Vertex
, start
, n
);
657 if (translate
& VERT_NORM
) {
658 ctx
->Array
.NormalFunc( IM
->Normal
+ VB_START
,
659 &ctx
->Array
.Normal
, start
, n
);
662 if (translate
& VERT_EDGE
) {
663 ctx
->Array
.EdgeFlagFunc( IM
->EdgeFlag
+ VB_START
,
664 &ctx
->Array
.EdgeFlag
, start
, n
);
667 if (translate
& VERT_RGBA
) {
668 ctx
->Array
.ColorFunc( IM
->Color
+ VB_START
,
669 &ctx
->Array
.Color
, start
, n
);
672 if (translate
& VERT_INDEX
) {
673 ctx
->Array
.IndexFunc( IM
->Index
+ VB_START
,
674 &ctx
->Array
.Index
, start
, n
);
677 if (translate
& VERT_TEX0_ANY
) {
678 IM
->v
.TexCoord
[0].size
= tc
[0].size
;
679 ctx
->Array
.TexCoordFunc
[0]( IM
->TexCoord
[0] + VB_START
,
680 &ctx
->Array
.TexCoord
[0], start
, n
);
683 if (translate
& VERT_TEX1_ANY
) {
684 IM
->v
.TexCoord
[1].size
= tc
[1].size
;
685 ctx
->Array
.TexCoordFunc
[1]( IM
->TexCoord
[1] + VB_START
,
686 &ctx
->Array
.TexCoord
[1], start
, n
);
691 VB
->ObjPtr
= VSrc
.Obj
;
692 VB
->NormalPtr
= VSrc
.Normal
;
693 VB
->Color
[0] = VB
->Color
[1] = VB
->ColorPtr
= VSrc
.Color
;
694 VB
->IndexPtr
= VSrc
.Index
;
695 VB
->EdgeFlagPtr
= VSrc
.EdgeFlag
;
696 VB
->TexCoordPtr
[0] = VSrc
.TexCoord
[0];
697 VB
->TexCoordPtr
[1] = VSrc
.TexCoord
[1];
699 VB
->Flag
= ctx
->Array
.Flag
;
700 VB
->OrFlag
= ctx
->Array
.Flags
;
702 count
= VB
->Count
= VB_START
+ n
;
704 VB
->ObjPtr
->count
= count
;
705 VB
->NormalPtr
->count
= count
;
706 VB
->ColorPtr
->count
= count
;
707 VB
->IndexPtr
->count
= count
;
708 VB
->EdgeFlagPtr
->count
= count
;
709 VB
->TexCoordPtr
[0]->count
= count
;
710 VB
->TexCoordPtr
[1]->count
= count
;
712 VB
->Flag
[count
] |= VERT_END_VB
;
713 VB
->Flag
[VB_START
] |= VERT_NORM
;
715 VB
->NextPrimitive
[VB
->CopyStart
] = VB
->Count
;
716 VB
->Primitive
[VB
->CopyStart
] = mode
;
718 /* Transform and render.
720 gl_run_pipeline( VB
);
723 ctx
->Array
.Flag
[count
] = ctx
->Array
.Flags
;
724 ctx
->Array
.Flag
[VB_START
] = ctx
->Array
.Flags
;
725 IM
->Flag
[VB_START
] = 0;
731 ctx
->CompileCVAFlag
= relock
;
733 else if (ctx
->Array
.Vertex
.Enabled
)
735 /* The GL_COMPILE and GL_COMPILE_AND_EXECUTE cases. These
736 * could be handled by the above code, but it gets a little
739 /* No need to reset - never called from inside a display list */
740 gl_Begin( ctx
, mode
);
741 for (i
=0;i
<count
;i
++) {
742 gl_ArrayElement( ctx
, start
+i
);
748 /* The degenerate case where vertices are not enabled - only
749 * need to process the very final array element, as all of the
750 * preceding ones would be overwritten anyway.
752 gl_Begin( ctx
, mode
);
753 gl_ArrayElement( ctx
, start
+count
);
760 /* KW: Exactly fakes the effects of calling glArrayElement multiple times.
761 * Compilation is handled via. the IM->maybe_transform_vb() callback.
764 #define DRAW_ELT(FUNC, TYPE) \
765 static void FUNC( GLcontext *ctx, GLenum mode, \
766 TYPE *indices, GLuint count ) \
770 gl_Begin( ctx, mode ); \
772 for (j = 0 ; j < count ; ) { \
773 struct immediate *IM = ctx->input; \
774 GLuint start = IM->Start; \
775 GLuint nr = MIN2( VB_MAX, count - j + start ); \
776 GLuint sf = IM->Flag[start]; \
777 IM->FlushElt |= IM->ArrayEltFlush; \
779 for (i = start ; i < nr ; i++) { \
780 IM->Elt[i] = (GLuint) *indices++; \
781 IM->Flag[i] = VERT_ELT; \
784 if (j == 0) IM->Flag[start] |= sf; \
789 if (j == count) gl_End( ctx ); \
790 IM->maybe_transform_vb( IM ); \
794 #define DRAW_ELT(FUNC, TYPE) \
795 static void FUNC( GLcontext *ctx, GLenum mode, \
796 TYPE *indices, GLuint count ) \
800 for (i = 0 ; i < count ; i++) \
801 glArrayElement( indices[i] ); \
807 DRAW_ELT( draw_elt_ubyte
, GLubyte
)
808 DRAW_ELT( draw_elt_ushort
, GLushort
)
809 DRAW_ELT( draw_elt_uint
, GLuint
)
812 static GLuint natural_stride
[0x10] =
814 sizeof(GLbyte
), /* 0 */
815 sizeof(GLubyte
), /* 1 */
816 sizeof(GLshort
), /* 2 */
817 sizeof(GLushort
), /* 3 */
818 sizeof(GLint
), /* 4 */
819 sizeof(GLuint
), /* 5 */
820 sizeof(GLfloat
), /* 6 */
821 2 * sizeof(GLbyte
), /* 7 */
822 3 * sizeof(GLbyte
), /* 8 */
823 4 * sizeof(GLbyte
), /* 9 */
824 sizeof(GLdouble
), /* a */
832 void GLAPIENTRY
glDrawElements(CTX_ARG GLenum mode
, GLsizei count
,
833 GLenum type
, const GLvoid
*indices
)
843 ASSERT_OUTSIDE_BEGIN_END_AND_FLUSH(ctx
, "glDrawElements");
847 gl_error( ctx
, GL_INVALID_VALUE
, "glDrawElements(count)" );
851 if (mode
< 0 || mode
> GL_POLYGON
) {
852 gl_error( ctx
, GL_INVALID_ENUM
, "glDrawArrays(mode)" );
856 if (type
!= GL_UNSIGNED_INT
&& type
!= GL_UNSIGNED_BYTE
&& type
!= GL_UNSIGNED_SHORT
)
858 gl_error( ctx
, GL_INVALID_ENUM
, "glDrawElements(type)" );
863 gl_update_state(ctx
);
865 if (ctx
->CompileCVAFlag
)
867 #if defined(MESA_CVA_PROF)
871 /* Treat VERT_ELT like a special client array.
873 ctx
->Array
.NewArrayState
|= VERT_ELT
;
874 ctx
->Array
.Summary
|= VERT_ELT
;
875 ctx
->Array
.Flags
|= VERT_ELT
;
877 cva
->elt_mode
= mode
;
878 cva
->elt_count
= count
;
879 cva
->Elt
.Type
= type
;
880 cva
->Elt
.Ptr
= (void *) indices
;
881 cva
->Elt
.StrideB
= natural_stride
[TYPE_IDX(type
)];
882 cva
->EltFunc
= gl_trans_1ui_tab
[TYPE_IDX(type
)];
884 if (!cva
->pre
.pipeline_valid
)
885 gl_build_precalc_pipeline( ctx
);
886 else if (MESA_VERBOSE
& VERBOSE_PIPELINE
)
887 fprintf(stderr
, ": dont rebuild\n");
889 gl_cva_force_precalc( ctx
);
891 /* Did we 'precalculate' the render op?
893 if (ctx
->CVA
.pre
.ops
& PIPE_OP_RENDER
) {
894 ctx
->Array
.NewArrayState
|= VERT_ELT
;
895 ctx
->Array
.Summary
&= ~VERT_ELT
;
896 ctx
->Array
.Flags
&= ~VERT_ELT
;
900 if ( (MESA_VERBOSE
&VERBOSE_VARRAY
) )
901 printf("using immediate\n");
905 /* Otherwise, have to use the immediate path to render.
908 case GL_UNSIGNED_BYTE
:
910 GLubyte
*ub_indices
= (GLubyte
*) indices
;
911 if (ctx
->Array
.Summary
& VERT_OBJ_ANY
) {
912 draw_elt_ubyte( ctx
, mode
, ub_indices
, count
);
914 gl_ArrayElement( ctx
, (GLuint
) ub_indices
[count
-1] );
918 case GL_UNSIGNED_SHORT
:
920 GLushort
*us_indices
= (GLushort
*) indices
;
921 if (ctx
->Array
.Summary
& VERT_OBJ_ANY
) {
922 draw_elt_ushort( ctx
, mode
, us_indices
, count
);
924 gl_ArrayElement( ctx
, (GLuint
) us_indices
[count
-1] );
928 case GL_UNSIGNED_INT
:
930 GLuint
*ui_indices
= (GLuint
*) indices
;
931 if (ctx
->Array
.Summary
& VERT_OBJ_ANY
) {
932 draw_elt_uint( ctx
, mode
, ui_indices
, count
);
934 gl_ArrayElement( ctx
, ui_indices
[count
-1] );
939 gl_error( ctx
, GL_INVALID_ENUM
, "glDrawElements(type)" );
943 if (ctx
->CompileCVAFlag
) {
944 ctx
->Array
.NewArrayState
|= VERT_ELT
;
945 ctx
->Array
.Summary
&= ~VERT_ELT
;
951 void GLAPIENTRY
glInterleavedArrays(CTX_ARG GLenum format
, GLsizei stride
,
952 const GLvoid
*pointer
)
955 GLboolean tflag
, cflag
, nflag
; /* enable/disable flags */
956 GLint tcomps
, ccomps
, vcomps
; /* components per texcoord, color, vertex */
958 GLenum ctype
; /* color type */
959 GLint coffset
, noffset
, voffset
;/* color, normal, vertex offsets */
960 GLint defstride
; /* default stride */
970 c
= f
* ((4*sizeof(GLubyte
) + (f
-1)) / f
);
973 gl_error( ctx
, GL_INVALID_VALUE
, "glInterleavedArrays(stride)" );
979 tflag
= GL_FALSE
; cflag
= GL_FALSE
; nflag
= GL_FALSE
;
980 tcomps
= 0; ccomps
= 0; vcomps
= 2;
985 tflag
= GL_FALSE
; cflag
= GL_FALSE
; nflag
= GL_FALSE
;
986 tcomps
= 0; ccomps
= 0; vcomps
= 3;
991 tflag
= GL_FALSE
; cflag
= GL_TRUE
; nflag
= GL_FALSE
;
992 tcomps
= 0; ccomps
= 4; vcomps
= 2;
993 ctype
= GL_UNSIGNED_BYTE
;
999 tflag
= GL_FALSE
; cflag
= GL_TRUE
; nflag
= GL_FALSE
;
1000 tcomps
= 0; ccomps
= 4; vcomps
= 3;
1001 ctype
= GL_UNSIGNED_BYTE
;
1004 defstride
= c
+ 3*f
;
1007 tflag
= GL_FALSE
; cflag
= GL_TRUE
; nflag
= GL_FALSE
;
1008 tcomps
= 0; ccomps
= 3; vcomps
= 3;
1015 tflag
= GL_FALSE
; cflag
= GL_FALSE
; nflag
= GL_TRUE
;
1016 tcomps
= 0; ccomps
= 0; vcomps
= 3;
1021 case GL_C4F_N3F_V3F
:
1022 tflag
= GL_FALSE
; cflag
= GL_TRUE
; nflag
= GL_TRUE
;
1023 tcomps
= 0; ccomps
= 4; vcomps
= 3;
1031 tflag
= GL_TRUE
; cflag
= GL_FALSE
; nflag
= GL_FALSE
;
1032 tcomps
= 2; ccomps
= 0; vcomps
= 3;
1037 tflag
= GL_TRUE
; cflag
= GL_FALSE
; nflag
= GL_FALSE
;
1038 tcomps
= 4; ccomps
= 0; vcomps
= 4;
1042 case GL_T2F_C4UB_V3F
:
1043 tflag
= GL_TRUE
; cflag
= GL_TRUE
; nflag
= GL_FALSE
;
1044 tcomps
= 2; ccomps
= 4; vcomps
= 3;
1045 ctype
= GL_UNSIGNED_BYTE
;
1050 case GL_T2F_C3F_V3F
:
1051 tflag
= GL_TRUE
; cflag
= GL_TRUE
; nflag
= GL_FALSE
;
1052 tcomps
= 2; ccomps
= 3; vcomps
= 3;
1058 case GL_T2F_N3F_V3F
:
1059 tflag
= GL_TRUE
; cflag
= GL_FALSE
; nflag
= GL_TRUE
;
1060 tcomps
= 2; ccomps
= 0; vcomps
= 3;
1065 case GL_T2F_C4F_N3F_V3F
:
1066 tflag
= GL_TRUE
; cflag
= GL_TRUE
; nflag
= GL_TRUE
;
1067 tcomps
= 2; ccomps
= 4; vcomps
= 3;
1074 case GL_T4F_C4F_N3F_V4F
:
1075 tflag
= GL_TRUE
; cflag
= GL_TRUE
; nflag
= GL_TRUE
;
1076 tcomps
= 4; ccomps
= 4; vcomps
= 4;
1084 gl_error( ctx
, GL_INVALID_ENUM
, "glInterleavedArrays(format)" );
1092 gl_DisableClientState( ctx
, GL_EDGE_FLAG_ARRAY
);
1093 gl_DisableClientState( ctx
, GL_INDEX_ARRAY
);
1096 coordUnitSave
= ctx
->Array
.ActiveTexture
;
1099 GLint factor
= ctx
->Array
.TexCoordInterleaveFactor
;
1100 for (i
= 0; i
< factor
; i
++) {
1101 gl_ActiveTexture( ctx
, (GLenum
) (GL_TEXTURE0_ARB
+ i
) );
1102 gl_EnableClientState( ctx
, GL_TEXTURE_COORD_ARRAY
);
1103 glTexCoordPointer(CTX_PRM tcomps
, GL_FLOAT
, stride
,
1104 (GLubyte
*) pointer
+ i
* coffset
);
1106 for (i
= factor
; i
< ctx
->Const
.MaxTextureUnits
; i
++) {
1107 gl_ActiveTexture( ctx
, (GLenum
) (GL_TEXTURE0_ARB
+ i
) );
1108 gl_DisableClientState( ctx
, GL_TEXTURE_COORD_ARRAY
);
1113 for (i
= 0; i
< ctx
->Const
.MaxTextureUnits
; i
++) {
1114 gl_ActiveTexture( ctx
, (GLenum
) (GL_TEXTURE0_ARB
+ i
) );
1115 gl_DisableClientState( ctx
, GL_TEXTURE_COORD_ARRAY
);
1118 /* Restore texture coordinate unit index */
1119 gl_ActiveTexture( ctx
, (GLenum
) (GL_TEXTURE0_ARB
+ coordUnitSave
) );
1124 gl_EnableClientState( ctx
, GL_COLOR_ARRAY
);
1125 glColorPointer(CTX_PRM ccomps
, ctype
, stride
,
1126 (GLubyte
*) pointer
+ coffset
);
1129 gl_DisableClientState( ctx
, GL_COLOR_ARRAY
);
1135 gl_EnableClientState( ctx
, GL_NORMAL_ARRAY
);
1136 glNormalPointer(CTX_PRM GL_FLOAT
, stride
,
1137 (GLubyte
*) pointer
+ noffset
);
1140 gl_DisableClientState( ctx
, GL_NORMAL_ARRAY
);
1143 gl_EnableClientState( ctx
, GL_VERTEX_ARRAY
);
1144 glVertexPointer(CTX_PRM vcomps
, GL_FLOAT
, stride
,
1145 (GLubyte
*) pointer
+ voffset
);
1150 void GLAPIENTRY
glDrawRangeElements(CTX_ARG GLenum mode
, GLuint start
,
1151 GLuint end
, GLsizei count
,
1152 GLenum type
, const GLvoid
*indices
)
1160 gl_error(ctx
, GL_INVALID_VALUE
, "glDrawRangeElements( end < start )");
1164 if (!ctx
->Array
.LockCount
&& 2*count
> (GLint
) 3*(end
-start
)) {
1165 glLockArraysEXT(CTX_PRM start
, end
);
1166 glDrawElements(CTX_PRM mode
, count
, type
, indices
);
1167 glUnlockArraysEXT(CTX_VPRM
);
1169 glDrawElements(CTX_PRM mode
, count
, type
, indices
);
1175 void gl_update_client_state( GLcontext
*ctx
)
1177 static GLuint sz_flags
[5] = { 0,
1183 static GLuint tc_flags
[5] = { 0,
1189 ctx
->Array
.Flags
= 0;
1190 ctx
->Array
.Summary
= 0;
1191 ctx
->input
->ArrayIncr
= 0;
1193 if (ctx
->Array
.Normal
.Enabled
) ctx
->Array
.Flags
|= VERT_NORM
;
1194 if (ctx
->Array
.Color
.Enabled
) ctx
->Array
.Flags
|= VERT_RGBA
;
1195 if (ctx
->Array
.Index
.Enabled
) ctx
->Array
.Flags
|= VERT_INDEX
;
1196 if (ctx
->Array
.EdgeFlag
.Enabled
) ctx
->Array
.Flags
|= VERT_EDGE
;
1197 if (ctx
->Array
.Vertex
.Enabled
) {
1198 ctx
->Array
.Flags
|= sz_flags
[ctx
->Array
.Vertex
.Size
];
1199 ctx
->input
->ArrayIncr
= 1;
1201 if (ctx
->Array
.TexCoord
[0].Enabled
) {
1202 ctx
->Array
.Flags
|= tc_flags
[ctx
->Array
.TexCoord
[0].Size
];
1204 if (ctx
->Array
.TexCoord
[1].Enabled
) {
1205 ctx
->Array
.Flags
|= (tc_flags
[ctx
->Array
.TexCoord
[1].Size
] << NR_TEXSIZE_BITS
);
1208 /* Not really important any more:
1210 ctx
->Array
.Summary
= ctx
->Array
.Flags
& VERT_DATA
;
1211 ctx
->input
->ArrayAndFlags
= ~ctx
->Array
.Flags
;
1212 ctx
->input
->ArrayEltFlush
= !(ctx
->CompileCVAFlag
);