1 /* $Id: varray.c,v 1.14 1999/11/11 01:22:28 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.
41 #include "translate.h"
47 #include "vbindirect.h"
55 _mesa_VertexPointer(GLint size
, GLenum type
, GLsizei stride
, const GLvoid
*ptr
)
57 GET_CURRENT_CONTEXT(ctx
);
59 if (size
<2 || size
>4) {
60 gl_error( ctx
, GL_INVALID_VALUE
, "glVertexPointer(size)" );
64 gl_error( ctx
, GL_INVALID_VALUE
, "glVertexPointer(stride)" );
68 if (MESA_VERBOSE
&(VERBOSE_VARRAY
|VERBOSE_API
))
69 fprintf(stderr
, "glVertexPointer( sz %d type %s stride %d )\n", size
,
70 gl_lookup_enum_by_nr( type
),
73 ctx
->Array
.Vertex
.StrideB
= stride
;
77 ctx
->Array
.Vertex
.StrideB
= size
*sizeof(GLshort
);
80 ctx
->Array
.Vertex
.StrideB
= size
*sizeof(GLint
);
83 ctx
->Array
.Vertex
.StrideB
= size
*sizeof(GLfloat
);
86 ctx
->Array
.Vertex
.StrideB
= size
*sizeof(GLdouble
);
89 gl_error( ctx
, GL_INVALID_ENUM
, "glVertexPointer(type)" );
93 ctx
->Array
.Vertex
.Size
= size
;
94 ctx
->Array
.Vertex
.Type
= type
;
95 ctx
->Array
.Vertex
.Stride
= stride
;
96 ctx
->Array
.Vertex
.Ptr
= (void *) ptr
;
97 ctx
->Array
.VertexFunc
= gl_trans_4f_tab
[size
][TYPE_IDX(type
)];
98 ctx
->Array
.VertexEltFunc
= gl_trans_elt_4f_tab
[size
][TYPE_IDX(type
)];
99 ctx
->Array
.NewArrayState
|= VERT_OBJ_ANY
;
100 ctx
->NewState
|= NEW_CLIENT_STATE
;
107 _mesa_NormalPointer(GLenum type
, GLsizei stride
, const GLvoid
*ptr
)
109 GET_CURRENT_CONTEXT(ctx
);
112 gl_error( ctx
, GL_INVALID_VALUE
, "glNormalPointer(stride)" );
116 if (MESA_VERBOSE
&(VERBOSE_VARRAY
|VERBOSE_API
))
117 fprintf(stderr
, "glNormalPointer( type %s stride %d )\n",
118 gl_lookup_enum_by_nr( type
),
121 ctx
->Array
.Normal
.StrideB
= stride
;
125 ctx
->Array
.Normal
.StrideB
= 3*sizeof(GLbyte
);
128 ctx
->Array
.Normal
.StrideB
= 3*sizeof(GLshort
);
131 ctx
->Array
.Normal
.StrideB
= 3*sizeof(GLint
);
134 ctx
->Array
.Normal
.StrideB
= 3*sizeof(GLfloat
);
137 ctx
->Array
.Normal
.StrideB
= 3*sizeof(GLdouble
);
140 gl_error( ctx
, GL_INVALID_ENUM
, "glNormalPointer(type)" );
144 ctx
->Array
.Normal
.Type
= type
;
145 ctx
->Array
.Normal
.Stride
= stride
;
146 ctx
->Array
.Normal
.Ptr
= (void *) ptr
;
147 ctx
->Array
.NormalFunc
= gl_trans_3f_tab
[TYPE_IDX(type
)];
148 ctx
->Array
.NormalEltFunc
= gl_trans_elt_3f_tab
[TYPE_IDX(type
)];
149 ctx
->Array
.NewArrayState
|= VERT_NORM
;
150 ctx
->NewState
|= NEW_CLIENT_STATE
;
156 _mesa_ColorPointer(GLint size
, GLenum type
, GLsizei stride
, const GLvoid
*ptr
)
158 GET_CURRENT_CONTEXT(ctx
);
160 if (size
<3 || size
>4) {
161 gl_error( ctx
, GL_INVALID_VALUE
, "glColorPointer(size)" );
165 gl_error( ctx
, GL_INVALID_VALUE
, "glColorPointer(stride)" );
169 if (MESA_VERBOSE
&(VERBOSE_VARRAY
|VERBOSE_API
))
170 fprintf(stderr
, "glColorPointer( sz %d type %s stride %d )\n", size
,
171 gl_lookup_enum_by_nr( type
),
174 ctx
->Array
.Color
.StrideB
= stride
;
178 ctx
->Array
.Color
.StrideB
= size
*sizeof(GLbyte
);
180 case GL_UNSIGNED_BYTE
:
181 ctx
->Array
.Color
.StrideB
= size
*sizeof(GLubyte
);
184 ctx
->Array
.Color
.StrideB
= size
*sizeof(GLshort
);
186 case GL_UNSIGNED_SHORT
:
187 ctx
->Array
.Color
.StrideB
= size
*sizeof(GLushort
);
190 ctx
->Array
.Color
.StrideB
= size
*sizeof(GLint
);
192 case GL_UNSIGNED_INT
:
193 ctx
->Array
.Color
.StrideB
= size
*sizeof(GLuint
);
196 ctx
->Array
.Color
.StrideB
= size
*sizeof(GLfloat
);
199 ctx
->Array
.Color
.StrideB
= size
*sizeof(GLdouble
);
202 gl_error( ctx
, GL_INVALID_ENUM
, "glColorPointer(type)" );
206 ctx
->Array
.Color
.Size
= size
;
207 ctx
->Array
.Color
.Type
= type
;
208 ctx
->Array
.Color
.Stride
= stride
;
209 ctx
->Array
.Color
.Ptr
= (void *) ptr
;
210 ctx
->Array
.ColorFunc
= gl_trans_4ub_tab
[size
][TYPE_IDX(type
)];
211 ctx
->Array
.ColorEltFunc
= gl_trans_elt_4ub_tab
[size
][TYPE_IDX(type
)];
212 ctx
->Array
.NewArrayState
|= VERT_RGBA
;
213 ctx
->NewState
|= NEW_CLIENT_STATE
;
219 _mesa_IndexPointer(GLenum type
, GLsizei stride
, const GLvoid
*ptr
)
221 GET_CURRENT_CONTEXT(ctx
);
224 gl_error( ctx
, GL_INVALID_VALUE
, "glIndexPointer(stride)" );
228 ctx
->Array
.Index
.StrideB
= stride
;
231 case GL_UNSIGNED_BYTE
:
232 ctx
->Array
.Index
.StrideB
= sizeof(GLubyte
);
235 ctx
->Array
.Index
.StrideB
= sizeof(GLshort
);
238 ctx
->Array
.Index
.StrideB
= sizeof(GLint
);
241 ctx
->Array
.Index
.StrideB
= sizeof(GLfloat
);
244 ctx
->Array
.Index
.StrideB
= sizeof(GLdouble
);
247 gl_error( ctx
, GL_INVALID_ENUM
, "glIndexPointer(type)" );
251 ctx
->Array
.Index
.Type
= type
;
252 ctx
->Array
.Index
.Stride
= stride
;
253 ctx
->Array
.Index
.Ptr
= (void *) ptr
;
254 ctx
->Array
.IndexFunc
= gl_trans_1ui_tab
[TYPE_IDX(type
)];
255 ctx
->Array
.IndexEltFunc
= gl_trans_elt_1ui_tab
[TYPE_IDX(type
)];
256 ctx
->Array
.NewArrayState
|= VERT_INDEX
;
257 ctx
->NewState
|= NEW_CLIENT_STATE
;
263 _mesa_TexCoordPointer(GLint size
, GLenum type
, GLsizei stride
, const GLvoid
*ptr
)
265 GET_CURRENT_CONTEXT(ctx
);
268 texUnit
= ctx
->Array
.ActiveTexture
;
270 if (size
<1 || size
>4) {
271 gl_error( ctx
, GL_INVALID_VALUE
, "glTexCoordPointer(size)" );
275 gl_error( ctx
, GL_INVALID_VALUE
, "glTexCoordPointer(stride)" );
279 if (MESA_VERBOSE
&(VERBOSE_VARRAY
|VERBOSE_API
))
280 fprintf(stderr
, "glTexCoordPointer( unit %u sz %d type %s stride %d )\n",
283 gl_lookup_enum_by_nr( type
),
286 ctx
->Array
.TexCoord
[texUnit
].StrideB
= stride
;
290 ctx
->Array
.TexCoord
[texUnit
].StrideB
= size
*sizeof(GLshort
);
293 ctx
->Array
.TexCoord
[texUnit
].StrideB
= size
*sizeof(GLint
);
296 ctx
->Array
.TexCoord
[texUnit
].StrideB
= size
*sizeof(GLfloat
);
299 ctx
->Array
.TexCoord
[texUnit
].StrideB
= size
*sizeof(GLdouble
);
302 gl_error( ctx
, GL_INVALID_ENUM
, "glTexCoordPointer(type)" );
306 ctx
->Array
.TexCoord
[texUnit
].Size
= size
;
307 ctx
->Array
.TexCoord
[texUnit
].Type
= type
;
308 ctx
->Array
.TexCoord
[texUnit
].Stride
= stride
;
309 ctx
->Array
.TexCoord
[texUnit
].Ptr
= (void *) ptr
;
311 ctx
->Array
.TexCoordFunc
[texUnit
] = gl_trans_4f_tab
[size
][TYPE_IDX(type
)];
312 ctx
->Array
.TexCoordEltFunc
[texUnit
] = gl_trans_elt_4f_tab
[size
][TYPE_IDX(type
)];
313 ctx
->Array
.NewArrayState
|= PIPE_TEX(texUnit
);
314 ctx
->NewState
|= NEW_CLIENT_STATE
;
321 _mesa_EdgeFlagPointer(GLsizei stride
, const void *vptr
)
323 GET_CURRENT_CONTEXT(ctx
);
324 const GLboolean
*ptr
= (GLboolean
*)vptr
;
327 gl_error( ctx
, GL_INVALID_VALUE
, "glEdgeFlagPointer(stride)" );
330 ctx
->Array
.EdgeFlag
.Stride
= stride
;
331 ctx
->Array
.EdgeFlag
.StrideB
= stride
? stride
: sizeof(GLboolean
);
332 ctx
->Array
.EdgeFlag
.Ptr
= (GLboolean
*) ptr
;
333 if (stride
!= sizeof(GLboolean
)) {
334 ctx
->Array
.EdgeFlagFunc
= gl_trans_1ub_tab
[TYPE_IDX(GL_UNSIGNED_BYTE
)];
336 ctx
->Array
.EdgeFlagFunc
= 0;
338 ctx
->Array
.EdgeFlagEltFunc
= gl_trans_elt_1ub_tab
[TYPE_IDX(GL_UNSIGNED_BYTE
)];
339 ctx
->Array
.NewArrayState
|= VERT_EDGE
;
340 ctx
->NewState
|= NEW_CLIENT_STATE
;
344 /* Called only from gl_DrawElements
346 void gl_CVAEltPointer( GLcontext
*ctx
, GLenum type
, const GLvoid
*ptr
)
349 case GL_UNSIGNED_BYTE
:
350 ctx
->CVA
.Elt
.StrideB
= sizeof(GLubyte
);
352 case GL_UNSIGNED_SHORT
:
353 ctx
->CVA
.Elt
.StrideB
= sizeof(GLushort
);
355 case GL_UNSIGNED_INT
:
356 ctx
->CVA
.Elt
.StrideB
= sizeof(GLuint
);
359 gl_error( ctx
, GL_INVALID_ENUM
, "glEltPointer(type)" );
362 ctx
->CVA
.Elt
.Type
= type
;
363 ctx
->CVA
.Elt
.Stride
= 0;
364 ctx
->CVA
.Elt
.Ptr
= (void *) ptr
;
365 ctx
->CVA
.EltFunc
= gl_trans_1ui_tab
[TYPE_IDX(type
)];
366 ctx
->Array
.NewArrayState
|= VERT_ELT
; /* ??? */
371 /* KW: Batch function to exec all the array elements in the input
372 * buffer prior to transform. Done only the first time a vertex
373 * buffer is executed or compiled.
375 * KW: Have to do this after each glEnd if cva isn't active. (also
376 * have to do it after each full buffer)
378 void gl_exec_array_elements( GLcontext
*ctx
, struct immediate
*IM
,
382 GLuint
*flags
= IM
->Flag
;
383 GLuint
*elts
= IM
->Elt
;
384 GLuint translate
= ctx
->Array
.Flags
;
387 if (MESA_VERBOSE
&VERBOSE_IMMEDIATE
)
388 fprintf(stderr
, "exec_array_elements %d .. %d\n", start
, count
);
390 if (translate
& VERT_OBJ_ANY
)
391 (ctx
->Array
.VertexEltFunc
)( IM
->Obj
,
393 flags
, elts
, (VERT_ELT
|VERT_OBJ_ANY
),
396 if (translate
& VERT_NORM
)
397 (ctx
->Array
.NormalEltFunc
)( IM
->Normal
,
399 flags
, elts
, (VERT_ELT
|VERT_NORM
),
402 if (translate
& VERT_EDGE
)
403 (ctx
->Array
.EdgeFlagEltFunc
)( IM
->EdgeFlag
,
404 &ctx
->Array
.EdgeFlag
,
405 flags
, elts
, (VERT_ELT
|VERT_EDGE
),
408 if (translate
& VERT_RGBA
)
409 (ctx
->Array
.ColorEltFunc
)( IM
->Color
,
411 flags
, elts
, (VERT_ELT
|VERT_RGBA
),
414 if (translate
& VERT_INDEX
)
415 (ctx
->Array
.IndexEltFunc
)( IM
->Index
,
417 flags
, elts
, (VERT_ELT
|VERT_INDEX
),
420 if (translate
& VERT_TEX0_ANY
)
421 (ctx
->Array
.TexCoordEltFunc
[0])( IM
->TexCoord
[0],
422 &ctx
->Array
.TexCoord
[0],
423 flags
, elts
, (VERT_ELT
|VERT_TEX0_ANY
),
426 if (translate
& VERT_TEX1_ANY
)
427 (ctx
->Array
.TexCoordEltFunc
[1])( IM
->TexCoord
[1],
428 &ctx
->Array
.TexCoord
[1],
429 flags
, elts
, (VERT_ELT
|VERT_TEX1_ANY
),
433 for (i
= start
; i
< count
; i
++)
434 if (flags
[i
] & VERT_ELT
)
435 flags
[i
] |= translate
;
441 /* Enough funny business going on in here it might be quicker to use a
444 #define ARRAY_ELT( IM, i ) \
446 GLuint count = IM->Count; \
447 IM->Elt[count] = i; \
448 IM->Flag[count] = ((IM->Flag[count] & IM->ArrayAndFlags) | \
450 IM->FlushElt |= IM->ArrayEltFlush; \
451 IM->Count = count += IM->ArrayIncr; \
452 if (count == VB_MAX) \
453 IM->maybe_transform_vb( IM ); \
458 _mesa_ArrayElement( GLint i
)
465 void gl_ArrayElement( GLcontext
*CC
, GLint i
)
467 struct immediate
*im
= CC
->input
;
474 _mesa_DrawArrays(GLenum mode
, GLint start
, GLsizei count
)
476 GET_CURRENT_CONTEXT(ctx
);
477 struct vertex_buffer
*VB
= ctx
->VB
;
480 ASSERT_OUTSIDE_BEGIN_END_AND_FLUSH(ctx
, "glDrawArrays");
483 gl_error( ctx
, GL_INVALID_VALUE
, "glDrawArrays(count)" );
487 if (!ctx
->CompileFlag
&& ctx
->Array
.Vertex
.Enabled
)
489 GLint remaining
= count
;
491 struct gl_client_array
*Normal
;
492 struct gl_client_array
*Color
;
493 struct gl_client_array
*Index
;
494 struct gl_client_array
*TexCoord
[MAX_TEXTURE_UNITS
];
495 struct gl_client_array
*EdgeFlag
;
496 struct immediate
*IM
= VB
->IM
;
497 struct gl_pipeline
*elt
= &ctx
->CVA
.elt
;
499 GLuint fallback
, required
;
502 gl_update_state( ctx
);
504 /* Just turn off cva on this path. Could be useful for multipass
505 * rendering to keep it turned on.
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 if (required
& VERT_RGBA
)
518 Color
= &ctx
->Array
.Color
;
519 if (fallback
& VERT_RGBA
) {
520 Color
= &ctx
->Fallback
.Color
;
521 ctx
->Array
.ColorFunc
=
522 gl_trans_4ub_tab
[4][TYPE_IDX(GL_UNSIGNED_BYTE
)];
526 if (required
& VERT_INDEX
)
528 Index
= &ctx
->Array
.Index
;
529 if (fallback
& VERT_INDEX
) {
530 Index
= &ctx
->Fallback
.Index
;
531 ctx
->Array
.IndexFunc
= gl_trans_1ui_tab
[TYPE_IDX(GL_UNSIGNED_INT
)];
535 for (i
= 0 ; i
< MAX_TEXTURE_UNITS
; i
++)
537 GLuint flag
= VERT_TEX_ANY(i
);
539 if (required
& flag
) {
540 TexCoord
[i
] = &ctx
->Array
.TexCoord
[i
];
544 TexCoord
[i
] = &ctx
->Fallback
.TexCoord
[i
];
545 TexCoord
[i
]->Size
= gl_texcoord_size( ctx
->Current
.Flag
, i
);
547 ctx
->Array
.TexCoordFunc
[i
] =
548 gl_trans_4f_tab
[TexCoord
[i
]->Size
][TYPE_IDX(GL_FLOAT
)];
553 if (ctx
->Array
.Flags
!= ctx
->Array
.Flag
[0])
554 for (i
= 0 ; i
< VB_MAX
; i
++)
555 ctx
->Array
.Flag
[i
] = ctx
->Array
.Flags
;
558 if (required
& VERT_NORM
)
560 Normal
= &ctx
->Array
.Normal
;
561 if (fallback
& VERT_NORM
) {
562 Normal
= &ctx
->Fallback
.Normal
;
563 ctx
->Array
.NormalFunc
= gl_trans_3f_tab
[TYPE_IDX(GL_FLOAT
)];
567 if ( required
& VERT_EDGE
)
569 if (mode
== GL_TRIANGLES
||
573 EdgeFlag
= &ctx
->Array
.EdgeFlag
;
574 if (fallback
& VERT_EDGE
) {
575 EdgeFlag
= &ctx
->Fallback
.EdgeFlag
;
576 ctx
->Array
.EdgeFlagFunc
=
577 gl_trans_1ub_tab
[TYPE_IDX(GL_UNSIGNED_BYTE
)];
581 required
&= ~VERT_EDGE
;
584 VB
->Primitive
= IM
->Primitive
;
585 VB
->NextPrimitive
= IM
->NextPrimitive
;
586 VB
->MaterialMask
= IM
->MaterialMask
;
587 VB
->Material
= IM
->Material
;
590 while (remaining
> 0) {
591 GLint vbspace
= VB_MAX
- VB_START
;
594 if (vbspace
>= remaining
) {
596 VB
->LastPrimitive
= VB_START
+ n
;
599 VB
->LastPrimitive
= VB_START
;
604 ctx
->Array
.VertexFunc( IM
->Obj
+ VB_START
,
605 &ctx
->Array
.Vertex
, start
, n
);
607 if (required
& VERT_NORM
) {
608 ctx
->Array
.NormalFunc( IM
->Normal
+ VB_START
,
612 if (required
& VERT_EDGE
) {
613 ctx
->Array
.EdgeFlagFunc( IM
->EdgeFlag
+ VB_START
,
614 EdgeFlag
, start
, n
);
617 if (required
& VERT_RGBA
) {
618 ctx
->Array
.ColorFunc( IM
->Color
+ VB_START
,
622 if (required
& VERT_INDEX
) {
623 ctx
->Array
.IndexFunc( IM
->Index
+ VB_START
,
627 if (required
& VERT_TEX0_ANY
) {
628 IM
->v
.TexCoord
[0].size
= TexCoord
[0]->Size
;
629 ctx
->Array
.TexCoordFunc
[0]( IM
->TexCoord
[0] + VB_START
,
630 TexCoord
[0], start
, n
);
633 if (required
& VERT_TEX1_ANY
) {
634 IM
->v
.TexCoord
[1].size
= TexCoord
[1]->Size
;
635 ctx
->Array
.TexCoordFunc
[1]( IM
->TexCoord
[1] + VB_START
,
636 TexCoord
[1], start
, n
);
639 VB
->ObjPtr
= &IM
->v
.Obj
;
640 VB
->NormalPtr
= &IM
->v
.Normal
;
641 VB
->ColorPtr
= &IM
->v
.Color
;
642 VB
->Color
[0] = VB
->Color
[1] = VB
->ColorPtr
;
643 VB
->IndexPtr
= &IM
->v
.Index
;
644 VB
->EdgeFlagPtr
= &IM
->v
.EdgeFlag
;
645 VB
->TexCoordPtr
[0] = &IM
->v
.TexCoord
[0];
646 VB
->TexCoordPtr
[1] = &IM
->v
.TexCoord
[1];
648 VB
->Flag
= ctx
->Array
.Flag
;
649 VB
->OrFlag
= ctx
->Array
.Flags
;
651 VB
->Start
= IM
->Start
= VB_START
;
652 count
= VB
->Count
= IM
->Count
= VB_START
+ n
;
654 #define RESET_VEC(v, t, s, c) (v.start = t v.data[s], v.count = c)
656 RESET_VEC(IM
->v
.Obj
, (GLfloat
*), VB_START
, count
);
657 RESET_VEC(IM
->v
.Normal
, (GLfloat
*), VB_START
, count
);
658 RESET_VEC(IM
->v
.TexCoord
[0], (GLfloat
*), VB_START
, count
);
659 RESET_VEC(IM
->v
.TexCoord
[1], (GLfloat
*), VB_START
, count
);
660 RESET_VEC(IM
->v
.Index
, &, VB_START
, count
);
661 RESET_VEC(IM
->v
.Elt
, &, VB_START
, count
);
662 RESET_VEC(IM
->v
.EdgeFlag
, &, VB_START
, count
);
663 RESET_VEC(IM
->v
.Color
, (GLubyte
*), VB_START
, count
);
664 RESET_VEC(VB
->Clip
, (GLfloat
*), VB_START
, count
);
665 RESET_VEC(VB
->Eye
, (GLfloat
*), VB_START
, count
);
666 RESET_VEC(VB
->Win
, (GLfloat
*), VB_START
, count
);
667 RESET_VEC(VB
->BColor
, (GLubyte
*), VB_START
, count
);
668 RESET_VEC(VB
->BIndex
, &, VB_START
, count
);
670 VB
->NextPrimitive
[VB
->CopyStart
] = VB
->Count
;
671 VB
->Primitive
[VB
->CopyStart
] = mode
;
673 /* Transform and render.
675 gl_run_pipeline( VB
);
678 ctx
->Array
.Flag
[count
] = ctx
->Array
.Flags
;
679 ctx
->Array
.Flag
[VB_START
] = ctx
->Array
.Flags
;
685 ctx
->CompileCVAFlag
= relock
;
687 else if (ctx
->Array
.Vertex
.Enabled
)
689 /* The GL_COMPILE and GL_COMPILE_AND_EXECUTE cases. These
690 * could be handled by the above code, but it gets a little
691 * complex. The generated list is still of good quality
694 gl_Begin( ctx
, mode
);
695 for (i
=0;i
<count
;i
++) {
696 gl_ArrayElement( ctx
, start
+i
);
702 /* The degenerate case where vertices are not enabled - only
703 * need to process the very final array element, as all of the
704 * preceding ones would be overwritten anyway.
706 gl_Begin( ctx
, mode
);
707 gl_ArrayElement( ctx
, start
+count
);
714 /* KW: Exactly fakes the effects of calling glArrayElement multiple times.
715 * Compilation is handled via. the IM->maybe_transform_vb() callback.
718 #define DRAW_ELT(FUNC, TYPE) \
719 static void FUNC( GLcontext *ctx, GLenum mode, \
720 TYPE *indices, GLuint count ) \
724 gl_Begin( ctx, mode ); \
726 for (j = 0 ; j < count ; ) { \
727 struct immediate *IM = ctx->input; \
728 GLuint start = IM->Start; \
729 GLuint nr = MIN2( VB_MAX, count - j + start ); \
730 GLuint sf = IM->Flag[start]; \
731 IM->FlushElt |= IM->ArrayEltFlush; \
733 for (i = start ; i < nr ; i++) { \
734 IM->Elt[i] = (GLuint) *indices++; \
735 IM->Flag[i] = VERT_ELT; \
738 if (j == 0) IM->Flag[start] |= sf; \
743 if (j == count) gl_End( ctx ); \
744 IM->maybe_transform_vb( IM ); \
748 #define DRAW_ELT(FUNC, TYPE) \
749 static void FUNC( GLcontext *ctx, GLenum mode, \
750 TYPE *indices, GLuint count ) \
754 for (i = 0 ; i < count ; i++) \
755 glArrayElement( indices[i] ); \
761 DRAW_ELT( draw_elt_ubyte
, GLubyte
)
762 DRAW_ELT( draw_elt_ushort
, GLushort
)
763 DRAW_ELT( draw_elt_uint
, GLuint
)
766 static GLuint natural_stride
[0x10] =
768 sizeof(GLbyte
), /* 0 */
769 sizeof(GLubyte
), /* 1 */
770 sizeof(GLshort
), /* 2 */
771 sizeof(GLushort
), /* 3 */
772 sizeof(GLint
), /* 4 */
773 sizeof(GLuint
), /* 5 */
774 sizeof(GLfloat
), /* 6 */
775 2 * sizeof(GLbyte
), /* 7 */
776 3 * sizeof(GLbyte
), /* 8 */
777 4 * sizeof(GLbyte
), /* 9 */
778 sizeof(GLdouble
), /* a */
788 _mesa_DrawElements(GLenum mode
, GLsizei count
, GLenum type
, const GLvoid
*indices
)
790 GET_CURRENT_CONTEXT(ctx
);
794 ASSERT_OUTSIDE_BEGIN_END_AND_FLUSH(ctx
, "glDrawElements");
798 gl_error( ctx
, GL_INVALID_VALUE
, "glDrawElements(count)" );
802 if (mode
< 0 || mode
> GL_POLYGON
) {
803 gl_error( ctx
, GL_INVALID_ENUM
, "glDrawArrays(mode)" );
807 if (type
!= GL_UNSIGNED_INT
&& type
!= GL_UNSIGNED_BYTE
&& type
!= GL_UNSIGNED_SHORT
)
809 gl_error( ctx
, GL_INVALID_ENUM
, "glDrawElements(type)" );
814 gl_update_state(ctx
);
816 if (ctx
->CompileCVAFlag
)
818 #if defined(MESA_CVA_PROF)
822 /* Treat VERT_ELT like a special client array.
824 ctx
->Array
.NewArrayState
|= VERT_ELT
;
825 ctx
->Array
.Summary
|= VERT_ELT
;
826 ctx
->Array
.Flags
|= VERT_ELT
;
828 cva
->elt_mode
= mode
;
829 cva
->elt_count
= count
;
830 cva
->Elt
.Type
= type
;
831 cva
->Elt
.Ptr
= (void *) indices
;
832 cva
->Elt
.StrideB
= natural_stride
[TYPE_IDX(type
)];
833 cva
->EltFunc
= gl_trans_1ui_tab
[TYPE_IDX(type
)];
835 if (!cva
->pre
.pipeline_valid
)
836 gl_build_precalc_pipeline( ctx
);
837 else if (MESA_VERBOSE
& VERBOSE_PIPELINE
)
838 fprintf(stderr
, ": dont rebuild\n");
840 gl_cva_force_precalc( ctx
);
842 /* Did we 'precalculate' the render op?
844 if (ctx
->CVA
.pre
.ops
& PIPE_OP_RENDER
) {
845 ctx
->Array
.NewArrayState
|= VERT_ELT
;
846 ctx
->Array
.Summary
&= ~VERT_ELT
;
847 ctx
->Array
.Flags
&= ~VERT_ELT
;
851 if ( (MESA_VERBOSE
&VERBOSE_VARRAY
) )
852 printf("using immediate\n");
856 /* Otherwise, have to use the immediate path to render.
859 case GL_UNSIGNED_BYTE
:
861 GLubyte
*ub_indices
= (GLubyte
*) indices
;
862 if (ctx
->Array
.Summary
& VERT_OBJ_ANY
) {
863 draw_elt_ubyte( ctx
, mode
, ub_indices
, count
);
865 gl_ArrayElement( ctx
, (GLuint
) ub_indices
[count
-1] );
869 case GL_UNSIGNED_SHORT
:
871 GLushort
*us_indices
= (GLushort
*) indices
;
872 if (ctx
->Array
.Summary
& VERT_OBJ_ANY
) {
873 draw_elt_ushort( ctx
, mode
, us_indices
, count
);
875 gl_ArrayElement( ctx
, (GLuint
) us_indices
[count
-1] );
879 case GL_UNSIGNED_INT
:
881 GLuint
*ui_indices
= (GLuint
*) indices
;
882 if (ctx
->Array
.Summary
& VERT_OBJ_ANY
) {
883 draw_elt_uint( ctx
, mode
, ui_indices
, count
);
885 gl_ArrayElement( ctx
, ui_indices
[count
-1] );
890 gl_error( ctx
, GL_INVALID_ENUM
, "glDrawElements(type)" );
894 if (ctx
->CompileCVAFlag
) {
895 ctx
->Array
.NewArrayState
|= VERT_ELT
;
896 ctx
->Array
.Summary
&= ~VERT_ELT
;
903 _mesa_InterleavedArrays(GLenum format
, GLsizei stride
, const GLvoid
*pointer
)
905 GET_CURRENT_CONTEXT(ctx
);
906 GLboolean tflag
, cflag
, nflag
; /* enable/disable flags */
907 GLint tcomps
, ccomps
, vcomps
; /* components per texcoord, color, vertex */
909 GLenum ctype
; /* color type */
910 GLint coffset
, noffset
, voffset
;/* color, normal, vertex offsets */
911 GLint defstride
; /* default stride */
916 c
= f
* ((4*sizeof(GLubyte
) + (f
-1)) / f
);
919 gl_error( ctx
, GL_INVALID_VALUE
, "glInterleavedArrays(stride)" );
925 tflag
= GL_FALSE
; cflag
= GL_FALSE
; nflag
= GL_FALSE
;
926 tcomps
= 0; ccomps
= 0; vcomps
= 2;
931 tflag
= GL_FALSE
; cflag
= GL_FALSE
; nflag
= GL_FALSE
;
932 tcomps
= 0; ccomps
= 0; vcomps
= 3;
937 tflag
= GL_FALSE
; cflag
= GL_TRUE
; nflag
= GL_FALSE
;
938 tcomps
= 0; ccomps
= 4; vcomps
= 2;
939 ctype
= GL_UNSIGNED_BYTE
;
945 tflag
= GL_FALSE
; cflag
= GL_TRUE
; nflag
= GL_FALSE
;
946 tcomps
= 0; ccomps
= 4; vcomps
= 3;
947 ctype
= GL_UNSIGNED_BYTE
;
953 tflag
= GL_FALSE
; cflag
= GL_TRUE
; nflag
= GL_FALSE
;
954 tcomps
= 0; ccomps
= 3; vcomps
= 3;
961 tflag
= GL_FALSE
; cflag
= GL_FALSE
; nflag
= GL_TRUE
;
962 tcomps
= 0; ccomps
= 0; vcomps
= 3;
968 tflag
= GL_FALSE
; cflag
= GL_TRUE
; nflag
= GL_TRUE
;
969 tcomps
= 0; ccomps
= 4; vcomps
= 3;
977 tflag
= GL_TRUE
; cflag
= GL_FALSE
; nflag
= GL_FALSE
;
978 tcomps
= 2; ccomps
= 0; vcomps
= 3;
983 tflag
= GL_TRUE
; cflag
= GL_FALSE
; nflag
= GL_FALSE
;
984 tcomps
= 4; ccomps
= 0; vcomps
= 4;
988 case GL_T2F_C4UB_V3F
:
989 tflag
= GL_TRUE
; cflag
= GL_TRUE
; nflag
= GL_FALSE
;
990 tcomps
= 2; ccomps
= 4; vcomps
= 3;
991 ctype
= GL_UNSIGNED_BYTE
;
997 tflag
= GL_TRUE
; cflag
= GL_TRUE
; nflag
= GL_FALSE
;
998 tcomps
= 2; ccomps
= 3; vcomps
= 3;
1004 case GL_T2F_N3F_V3F
:
1005 tflag
= GL_TRUE
; cflag
= GL_FALSE
; nflag
= GL_TRUE
;
1006 tcomps
= 2; ccomps
= 0; vcomps
= 3;
1011 case GL_T2F_C4F_N3F_V3F
:
1012 tflag
= GL_TRUE
; cflag
= GL_TRUE
; nflag
= GL_TRUE
;
1013 tcomps
= 2; ccomps
= 4; vcomps
= 3;
1020 case GL_T4F_C4F_N3F_V4F
:
1021 tflag
= GL_TRUE
; cflag
= GL_TRUE
; nflag
= GL_TRUE
;
1022 tcomps
= 4; ccomps
= 4; vcomps
= 4;
1030 gl_error( ctx
, GL_INVALID_ENUM
, "glInterleavedArrays(format)" );
1038 _mesa_DisableClientState( GL_EDGE_FLAG_ARRAY
);
1039 _mesa_DisableClientState( GL_INDEX_ARRAY
);
1042 coordUnitSave
= ctx
->Array
.ActiveTexture
;
1045 GLint factor
= ctx
->Array
.TexCoordInterleaveFactor
;
1046 for (i
= 0; i
< factor
; i
++) {
1047 _mesa_ClientActiveTextureARB( (GLenum
) (GL_TEXTURE0_ARB
+ i
) );
1048 _mesa_EnableClientState( GL_TEXTURE_COORD_ARRAY
);
1049 glTexCoordPointer( tcomps
, GL_FLOAT
, stride
,
1050 (GLubyte
*) pointer
+ i
* coffset
);
1052 for (i
= factor
; i
< ctx
->Const
.MaxTextureUnits
; i
++) {
1053 _mesa_ClientActiveTextureARB( (GLenum
) (GL_TEXTURE0_ARB
+ i
) );
1054 _mesa_DisableClientState( GL_TEXTURE_COORD_ARRAY
);
1059 for (i
= 0; i
< ctx
->Const
.MaxTextureUnits
; i
++) {
1060 _mesa_ClientActiveTextureARB( (GLenum
) (GL_TEXTURE0_ARB
+ i
) );
1061 _mesa_DisableClientState( GL_TEXTURE_COORD_ARRAY
);
1064 /* Restore texture coordinate unit index */
1065 _mesa_ClientActiveTextureARB( (GLenum
) (GL_TEXTURE0_ARB
+ coordUnitSave
) );
1070 _mesa_EnableClientState( GL_COLOR_ARRAY
);
1071 glColorPointer( ccomps
, ctype
, stride
,
1072 (GLubyte
*) pointer
+ coffset
);
1075 _mesa_DisableClientState( GL_COLOR_ARRAY
);
1081 _mesa_EnableClientState( GL_NORMAL_ARRAY
);
1082 glNormalPointer( GL_FLOAT
, stride
,
1083 (GLubyte
*) pointer
+ noffset
);
1086 _mesa_DisableClientState( GL_NORMAL_ARRAY
);
1089 _mesa_EnableClientState( GL_VERTEX_ARRAY
);
1090 glVertexPointer( vcomps
, GL_FLOAT
, stride
,
1091 (GLubyte
*) pointer
+ voffset
);
1097 _mesa_DrawRangeElements(GLenum mode
, GLuint start
,
1098 GLuint end
, GLsizei count
,
1099 GLenum type
, const GLvoid
*indices
)
1101 GET_CURRENT_CONTEXT(ctx
);
1104 gl_error(ctx
, GL_INVALID_VALUE
, "glDrawRangeElements( end < start )");
1108 if (!ctx
->Array
.LockCount
&& 2*count
> (GLint
) 3*(end
-start
)) {
1109 glLockArraysEXT( start
, end
);
1110 glDrawElements( mode
, count
, type
, indices
);
1111 glUnlockArraysEXT();
1113 glDrawElements( mode
, count
, type
, indices
);
1119 void gl_update_client_state( GLcontext
*ctx
)
1121 static GLuint sz_flags
[5] = { 0,
1127 static GLuint tc_flags
[5] = { 0,
1133 ctx
->Array
.Flags
= 0;
1134 ctx
->Array
.Summary
= 0;
1135 ctx
->input
->ArrayIncr
= 0;
1137 if (ctx
->Array
.Normal
.Enabled
) ctx
->Array
.Flags
|= VERT_NORM
;
1138 if (ctx
->Array
.Color
.Enabled
) ctx
->Array
.Flags
|= VERT_RGBA
;
1139 if (ctx
->Array
.Index
.Enabled
) ctx
->Array
.Flags
|= VERT_INDEX
;
1140 if (ctx
->Array
.EdgeFlag
.Enabled
) ctx
->Array
.Flags
|= VERT_EDGE
;
1141 if (ctx
->Array
.Vertex
.Enabled
) {
1142 ctx
->Array
.Flags
|= sz_flags
[ctx
->Array
.Vertex
.Size
];
1143 ctx
->input
->ArrayIncr
= 1;
1145 if (ctx
->Array
.TexCoord
[0].Enabled
) {
1146 ctx
->Array
.Flags
|= tc_flags
[ctx
->Array
.TexCoord
[0].Size
];
1148 if (ctx
->Array
.TexCoord
[1].Enabled
) {
1149 ctx
->Array
.Flags
|= (tc_flags
[ctx
->Array
.TexCoord
[1].Size
] << NR_TEXSIZE_BITS
);
1152 /* Not really important any more:
1154 ctx
->Array
.Summary
= ctx
->Array
.Flags
& VERT_DATA
;
1155 ctx
->input
->ArrayAndFlags
= ~ctx
->Array
.Flags
;
1156 ctx
->input
->ArrayEltFlush
= !(ctx
->CompileCVAFlag
);