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(0, " 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
= 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
= MALLOC( tnl
->vb
.Size
);
90 for (i
= 0 ; i
< count
; i
++)
96 static 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
;
116 if (0) fprintf(stderr
, "_tnl_vb_bind_vtx(): %d verts %d vertsize\n",
117 count
, tnl
->vtx
.vertex_size
);
120 /* Setup constant data in the VB.
123 VB
->Primitive
= tnl
->vtx
.prim
;
124 VB
->PrimitiveCount
= tnl
->vtx
.prim_count
;
126 VB
->NormalLengthPtr
= NULL
;
128 for (attr
= 0; attr
<= _TNL_ATTRIB_INDEX
; attr
++) {
129 if (tnl
->vtx
.attrsz
[attr
]) {
130 tmp
->Attribs
[attr
].count
= count
;
131 tmp
->Attribs
[attr
].data
= (GLfloat (*)[4]) data
;
132 tmp
->Attribs
[attr
].start
= data
;
133 tmp
->Attribs
[attr
].size
= tnl
->vtx
.attrsz
[attr
];
134 tmp
->Attribs
[attr
].stride
= tnl
->vtx
.vertex_size
* sizeof(GLfloat
);
135 VB
->AttribPtr
[attr
] = &tmp
->Attribs
[attr
];
136 data
+= tnl
->vtx
.attrsz
[attr
];
139 /* VB->AttribPtr[attr] = &tnl->current.Attribs[attr]; */
142 tmp
->Attribs
[attr
].count
= count
;
143 tmp
->Attribs
[attr
].data
= (GLfloat (*)[4]) tnl
->vtx
.current
[attr
];
144 tmp
->Attribs
[attr
].start
= tnl
->vtx
.current
[attr
];
145 tmp
->Attribs
[attr
].size
= get_size( tnl
->vtx
.current
[attr
] );
146 tmp
->Attribs
[attr
].stride
= 0;
147 VB
->AttribPtr
[attr
] = &tmp
->Attribs
[attr
];
152 /* Copy and translate EdgeFlag to a contiguous array of GLbooleans
154 if (ctx
->Polygon
.FrontMode
!= GL_FILL
|| ctx
->Polygon
.BackMode
!= GL_FILL
) {
155 if (tnl
->vtx
.attrsz
[_TNL_ATTRIB_EDGEFLAG
]) {
156 VB
->EdgeFlag
= _tnl_translate_edgeflag( ctx
, data
, count
,
157 tnl
->vtx
.vertex_size
);
161 VB
->EdgeFlag
= _tnl_import_current_edgeflag( ctx
, count
);
164 /* Legacy pointers -- remove one day.
166 VB
->ObjPtr
= VB
->AttribPtr
[_TNL_ATTRIB_POS
];
167 VB
->NormalPtr
= VB
->AttribPtr
[_TNL_ATTRIB_NORMAL
];
168 VB
->ColorPtr
[0] = VB
->AttribPtr
[_TNL_ATTRIB_COLOR0
];
170 VB
->IndexPtr
[0] = VB
->AttribPtr
[_TNL_ATTRIB_INDEX
];
172 VB
->SecondaryColorPtr
[0] = VB
->AttribPtr
[_TNL_ATTRIB_COLOR1
];
173 VB
->SecondaryColorPtr
[1] = 0;
174 VB
->FogCoordPtr
= VB
->AttribPtr
[_TNL_ATTRIB_FOG
];
176 for (i
= 0; i
< ctx
->Const
.MaxTextureCoordUnits
; i
++) {
177 VB
->TexCoordPtr
[i
] = VB
->AttribPtr
[_TNL_ATTRIB_TEX0
+ i
];
183 * NOTE: Need to have calculated primitives by this point -- do it on the fly.
184 * NOTE: Old 'parity' issue is gone.
186 static GLuint
_tnl_copy_vertices( GLcontext
*ctx
)
188 TNLcontext
*tnl
= TNL_CONTEXT( ctx
);
189 GLuint nr
= tnl
->vtx
.prim
[tnl
->vtx
.prim_count
-1].count
;
191 GLuint sz
= tnl
->vtx
.vertex_size
;
192 GLfloat
*dst
= tnl
->vtx
.copied
.buffer
;
193 GLfloat
*src
= (tnl
->vtx
.buffer
+
194 tnl
->vtx
.prim
[tnl
->vtx
.prim_count
-1].start
*
195 tnl
->vtx
.vertex_size
);
198 switch( ctx
->Driver
.CurrentExecPrimitive
)
204 for (i
= 0 ; i
< ovf
; i
++)
205 memcpy( dst
+i
*sz
, src
+(nr
-ovf
+i
)*sz
, sz
* sizeof(GLfloat
) );
209 for (i
= 0 ; i
< ovf
; i
++)
210 memcpy( dst
+i
*sz
, src
+(nr
-ovf
+i
)*sz
, sz
* sizeof(GLfloat
) );
214 for (i
= 0 ; i
< ovf
; i
++)
215 memcpy( dst
+i
*sz
, src
+(nr
-ovf
+i
)*sz
, sz
* sizeof(GLfloat
) );
221 memcpy( dst
, src
+(nr
-1)*sz
, sz
* sizeof(GLfloat
) );
225 case GL_TRIANGLE_FAN
:
230 memcpy( dst
, src
+0, sz
* sizeof(GLfloat
) );
233 memcpy( dst
, src
+0, sz
* sizeof(GLfloat
) );
234 memcpy( dst
+sz
, src
+(nr
-1)*sz
, sz
* sizeof(GLfloat
) );
237 case GL_TRIANGLE_STRIP
:
240 case 0: ovf
= 0; break;
241 case 1: ovf
= 1; break;
242 default: ovf
= 2 + (nr
&1); break;
244 for (i
= 0 ; i
< ovf
; i
++)
245 memcpy( dst
+i
*sz
, src
+(nr
-ovf
+i
)*sz
, sz
* sizeof(GLfloat
) );
257 * Execute the buffer and save copied verts.
259 void _tnl_flush_vtx( GLcontext
*ctx
)
261 TNLcontext
*tnl
= TNL_CONTEXT(ctx
);
264 _tnl_print_vtx( ctx
);
266 if (tnl
->vtx
.prim_count
&&
267 tnl
->vtx
.counter
!= tnl
->vtx
.initial_counter
) {
269 tnl
->vtx
.copied
.nr
= _tnl_copy_vertices( ctx
);
272 _mesa_update_state( ctx
);
274 if (tnl
->pipeline
.build_state_changes
)
275 _tnl_validate_pipeline( ctx
);
277 _tnl_vb_bind_vtx( ctx
);
279 /* Invalidate all stored data before and after run:
281 tnl
->pipeline
.run_input_changes
|= tnl
->pipeline
.inputs
;
282 tnl
->Driver
.RunPipeline( ctx
);
283 tnl
->pipeline
.run_input_changes
|= tnl
->pipeline
.inputs
;
286 tnl
->vtx
.prim_count
= 0;
287 tnl
->vtx
.counter
= tnl
->vtx
.initial_counter
;
288 tnl
->vtx
.vbptr
= tnl
->vtx
.buffer
;