2 * Mesa 3-D graphics library
5 * Copyright (C) 1999-2003 Brian Paul All Rights Reserved.
7 * Permission is hereby granted, free of charge, to any person obtaining a
8 * copy of this software and associated documentation files (the "Software"),
9 * to deal in the Software without restriction, including without limitation
10 * the rights to use, copy, modify, merge, publish, distribute, sublicense,
11 * and/or sell copies of the Software, and to permit persons to whom the
12 * Software is furnished to do so, subject to the following conditions:
14 * The above copyright notice and this permission notice shall be included
15 * in all copies or substantial portions of the Software.
17 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
18 * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
19 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
20 * BRIAN PAUL BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN
21 * AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
22 * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
25 * Keith Whitwell <keith@tungstengraphics.com>
34 #include "math/m_eval.h"
35 #include "t_vtx_api.h"
36 #include "t_pipeline.h"
39 static void _tnl_print_vtx( GLcontext
*ctx
)
41 TNLcontext
*tnl
= TNL_CONTEXT(ctx
);
42 GLuint count
= tnl
->vtx
.initial_counter
- tnl
->vtx
.counter
;
45 _mesa_debug(ctx
, "_tnl_print_vtx: %u vertices %d primitives, %d vertsize\n",
48 tnl
->vtx
.vertex_size
);
50 for (i
= 0 ; i
< tnl
->vtx
.prim_count
; i
++) {
51 struct tnl_prim
*prim
= &tnl
->vtx
.prim
[i
];
52 _mesa_debug(NULL
, " prim %d: %s %d..%d %s %s\n",
54 _mesa_lookup_enum_by_nr(prim
->mode
& PRIM_MODE_MASK
),
56 prim
->start
+ prim
->count
,
57 (prim
->mode
& PRIM_BEGIN
) ? "BEGIN" : "(wrap)",
58 (prim
->mode
& PRIM_END
) ? "END" : "(wrap)");
62 GLboolean
*_tnl_translate_edgeflag( GLcontext
*ctx
, const GLfloat
*data
,
63 GLuint count
, GLuint stride
)
65 TNLcontext
*tnl
= TNL_CONTEXT(ctx
);
66 GLboolean
*ef
= tnl
->vtx
.edgeflag_tmp
;
70 ef
= tnl
->vtx
.edgeflag_tmp
= (GLboolean
*) MALLOC( tnl
->vb
.Size
);
72 for (i
= 0 ; i
< count
; i
++, data
+= stride
)
73 ef
[i
] = (data
[0] == 1.0);
79 GLboolean
*_tnl_import_current_edgeflag( GLcontext
*ctx
,
82 TNLcontext
*tnl
= TNL_CONTEXT(ctx
);
83 GLboolean
*ef
= tnl
->vtx
.edgeflag_tmp
;
84 GLboolean tmp
= ctx
->Current
.EdgeFlag
;
88 ef
= tnl
->vtx
.edgeflag_tmp
= (GLboolean
*) MALLOC( tnl
->vb
.Size
);
90 for (i
= 0 ; i
< count
; i
++)
96 static INLINE GLint
get_size( const GLfloat
*f
)
98 if (f
[3] != 1.0) return 4;
99 if (f
[2] != 0.0) return 3;
103 /* Some nasty stuff still hanging on here.
105 * TODO - remove VB->NormalPtr, etc and just use the AttrPtr's.
107 static void _tnl_vb_bind_vtx( GLcontext
*ctx
)
109 TNLcontext
*tnl
= TNL_CONTEXT(ctx
);
110 struct vertex_buffer
*VB
= &tnl
->vb
;
111 struct tnl_vertex_arrays
*tmp
= &tnl
->vtx_inputs
;
112 GLfloat
*data
= tnl
->vtx
.buffer
;
113 GLuint count
= tnl
->vtx
.initial_counter
- tnl
->vtx
.counter
;
119 fprintf(stderr
, "_tnl_vb_bind_vtx(): %d verts %d vertsize\n",
120 count
, tnl
->vtx
.vertex_size
);
124 /* Setup constant data in the VB.
127 VB
->Primitive
= tnl
->vtx
.prim
;
128 VB
->PrimitiveCount
= tnl
->vtx
.prim_count
;
130 VB
->NormalLengthPtr
= NULL
;
132 for (attr
= 0; attr
<= _TNL_ATTRIB_EDGEFLAG
; attr
++) {
133 if (tnl
->vtx
.attrsz
[attr
]) {
134 tmp
->Attribs
[attr
].count
= count
;
135 tmp
->Attribs
[attr
].data
= (GLfloat (*)[4]) data
;
136 tmp
->Attribs
[attr
].start
= data
;
137 tmp
->Attribs
[attr
].size
= tnl
->vtx
.attrsz
[attr
];
138 tmp
->Attribs
[attr
].stride
= tnl
->vtx
.vertex_size
* sizeof(GLfloat
);
139 VB
->AttribPtr
[attr
] = &tmp
->Attribs
[attr
];
140 data
+= tnl
->vtx
.attrsz
[attr
];
143 /* VB->AttribPtr[attr] = &tnl->current.Attribs[attr]; */
146 tmp
->Attribs
[attr
].count
= 1;
147 tmp
->Attribs
[attr
].data
= (GLfloat (*)[4]) tnl
->vtx
.current
[attr
];
148 tmp
->Attribs
[attr
].start
= tnl
->vtx
.current
[attr
];
149 tmp
->Attribs
[attr
].size
= get_size( tnl
->vtx
.current
[attr
] );
150 tmp
->Attribs
[attr
].stride
= 0;
151 VB
->AttribPtr
[attr
] = &tmp
->Attribs
[attr
];
156 /* Copy and translate EdgeFlag to a contiguous array of GLbooleans
158 if (ctx
->Polygon
.FrontMode
!= GL_FILL
|| ctx
->Polygon
.BackMode
!= GL_FILL
) {
159 if (tnl
->vtx
.attrsz
[_TNL_ATTRIB_EDGEFLAG
]) {
160 VB
->EdgeFlag
= _tnl_translate_edgeflag( ctx
, data
, count
,
161 tnl
->vtx
.vertex_size
);
165 VB
->EdgeFlag
= _tnl_import_current_edgeflag( ctx
, count
);
168 /* Legacy pointers -- remove one day.
170 VB
->ObjPtr
= VB
->AttribPtr
[_TNL_ATTRIB_POS
];
171 VB
->NormalPtr
= VB
->AttribPtr
[_TNL_ATTRIB_NORMAL
];
172 VB
->ColorPtr
[0] = VB
->AttribPtr
[_TNL_ATTRIB_COLOR0
];
173 VB
->ColorPtr
[1] = NULL
;
174 VB
->SecondaryColorPtr
[0] = VB
->AttribPtr
[_TNL_ATTRIB_COLOR1
];
175 VB
->SecondaryColorPtr
[1] = NULL
;
176 VB
->IndexPtr
[0] = VB
->AttribPtr
[_TNL_ATTRIB_COLOR_INDEX
];
177 VB
->IndexPtr
[1] = NULL
;
178 VB
->FogCoordPtr
= VB
->AttribPtr
[_TNL_ATTRIB_FOG
];
180 for (i
= 0; i
< ctx
->Const
.MaxTextureCoordUnits
; i
++) {
181 VB
->TexCoordPtr
[i
] = VB
->AttribPtr
[_TNL_ATTRIB_TEX0
+ i
];
187 * NOTE: Need to have calculated primitives by this point -- do it on the fly.
188 * NOTE: Old 'parity' issue is gone.
190 static GLuint
_tnl_copy_vertices( GLcontext
*ctx
)
192 TNLcontext
*tnl
= TNL_CONTEXT( ctx
);
193 GLuint nr
= tnl
->vtx
.prim
[tnl
->vtx
.prim_count
-1].count
;
195 GLuint sz
= tnl
->vtx
.vertex_size
;
196 GLfloat
*dst
= tnl
->vtx
.copied
.buffer
;
197 GLfloat
*src
= (tnl
->vtx
.buffer
+
198 tnl
->vtx
.prim
[tnl
->vtx
.prim_count
-1].start
*
199 tnl
->vtx
.vertex_size
);
202 switch( ctx
->Driver
.CurrentExecPrimitive
)
208 for (i
= 0 ; i
< ovf
; i
++)
209 _mesa_memcpy( dst
+i
*sz
, src
+(nr
-ovf
+i
)*sz
, sz
* sizeof(GLfloat
) );
213 for (i
= 0 ; i
< ovf
; i
++)
214 _mesa_memcpy( dst
+i
*sz
, src
+(nr
-ovf
+i
)*sz
, sz
* sizeof(GLfloat
) );
218 for (i
= 0 ; i
< ovf
; i
++)
219 _mesa_memcpy( dst
+i
*sz
, src
+(nr
-ovf
+i
)*sz
, sz
* sizeof(GLfloat
) );
225 _mesa_memcpy( dst
, src
+(nr
-1)*sz
, sz
* sizeof(GLfloat
) );
229 case GL_TRIANGLE_FAN
:
234 _mesa_memcpy( dst
, src
+0, sz
* sizeof(GLfloat
) );
237 _mesa_memcpy( dst
, src
+0, sz
* sizeof(GLfloat
) );
238 _mesa_memcpy( dst
+sz
, src
+(nr
-1)*sz
, sz
* sizeof(GLfloat
) );
241 case GL_TRIANGLE_STRIP
:
242 /* no parity issue, but need to make sure the tri is not drawn twice */
244 tnl
->vtx
.prim
[tnl
->vtx
.prim_count
-1].count
--;
249 case 0: ovf
= 0; break;
250 case 1: ovf
= 1; break;
251 default: ovf
= 2 + (nr
&1); break;
253 for (i
= 0 ; i
< ovf
; i
++)
254 _mesa_memcpy( dst
+i
*sz
, src
+(nr
-ovf
+i
)*sz
, sz
* sizeof(GLfloat
) );
256 case PRIM_OUTSIDE_BEGIN_END
:
266 * Execute the buffer and save copied verts.
268 void _tnl_flush_vtx( GLcontext
*ctx
)
270 TNLcontext
*tnl
= TNL_CONTEXT(ctx
);
271 GLuint vertex_count
= tnl
->vtx
.initial_counter
- tnl
->vtx
.counter
;
274 _tnl_print_vtx( ctx
);
276 if (tnl
->vtx
.prim_count
&& vertex_count
) {
278 tnl
->vtx
.copied
.nr
= _tnl_copy_vertices( ctx
);
280 if (tnl
->vtx
.copied
.nr
!= vertex_count
) {
282 _mesa_update_state( ctx
);
284 _tnl_vb_bind_vtx( ctx
);
286 tnl
->Driver
.RunPipeline( ctx
);
290 tnl
->vtx
.prim_count
= 0;
291 tnl
->vtx
.counter
= tnl
->vtx
.initial_counter
;
292 tnl
->vtx
.vbptr
= tnl
->vtx
.buffer
;