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>
33 #include "math/m_eval.h"
34 #include "t_vtx_api.h"
35 #include "t_pipeline.h"
37 static void _tnl_print_vtx( GLcontext
*ctx
)
39 TNLcontext
*tnl
= TNL_CONTEXT(ctx
);
40 GLuint count
= tnl
->vtx
.initial_counter
- tnl
->vtx
.counter
;
43 _mesa_debug(0, "%s: %u vertices %d primitives, %d vertsize\n",
47 tnl
->vtx
.vertex_size
);
49 for (i
= 0 ; i
< tnl
->vtx
.prim_count
; i
++) {
50 struct tnl_prim
*prim
= &tnl
->vtx
.prim
[i
];
51 _mesa_debug(0, " prim %d: %s %d..%d %s %s\n",
53 _mesa_lookup_enum_by_nr(prim
->mode
& PRIM_MODE_MASK
),
55 prim
->start
+ prim
->count
,
56 (prim
->mode
& PRIM_BEGIN
) ? "BEGIN" : "(wrap)",
57 (prim
->mode
& PRIM_END
) ? "END" : "(wrap)");
61 GLboolean
*_tnl_translate_edgeflag( GLcontext
*ctx
, const GLfloat
*data
,
62 GLuint count
, GLuint stride
)
64 TNLcontext
*tnl
= TNL_CONTEXT(ctx
);
65 GLboolean
*ef
= tnl
->vtx
.edgeflag_tmp
;
69 ef
= tnl
->vtx
.edgeflag_tmp
= MALLOC( tnl
->vb
.Size
);
71 for (i
= 0 ; i
< count
; i
++, data
+= stride
)
72 ef
[i
] = (data
[0] == 1.0);
78 GLboolean
*_tnl_import_current_edgeflag( GLcontext
*ctx
,
81 TNLcontext
*tnl
= TNL_CONTEXT(ctx
);
82 GLboolean
*ef
= tnl
->vtx
.edgeflag_tmp
;
83 GLboolean tmp
= ctx
->Current
.EdgeFlag
;
87 ef
= tnl
->vtx
.edgeflag_tmp
= MALLOC( tnl
->vb
.Size
);
89 for (i
= 0 ; i
< count
; i
++)
95 static GLint
get_size( const GLfloat
*f
)
97 if (f
[3] != 1.0) return 4;
98 if (f
[2] != 0.0) return 3;
102 /* Some nasty stuff still hanging on here.
104 * TODO - remove VB->NormalPtr, etc and just use the AttrPtr's.
106 static void _tnl_vb_bind_vtx( GLcontext
*ctx
)
108 TNLcontext
*tnl
= TNL_CONTEXT(ctx
);
109 struct vertex_buffer
*VB
= &tnl
->vb
;
110 struct tnl_vertex_arrays
*tmp
= &tnl
->vtx_inputs
;
111 GLfloat
*data
= tnl
->vtx
.buffer
;
112 GLuint count
= tnl
->vtx
.initial_counter
- tnl
->vtx
.counter
;
115 if (0) fprintf(stderr
, "%s: %d verts %d vertsize\n",
116 __FUNCTION__
, count
, tnl
->vtx
.vertex_size
);
119 /* Setup constant data in the VB.
122 VB
->Primitive
= tnl
->vtx
.prim
;
123 VB
->PrimitiveCount
= tnl
->vtx
.prim_count
;
125 VB
->NormalLengthPtr
= NULL
;
127 for (attr
= 0; attr
<= _TNL_ATTRIB_INDEX
; attr
++) {
128 if (tnl
->vtx
.attrsz
[attr
]) {
129 tmp
->Attribs
[attr
].count
= count
;
130 tmp
->Attribs
[attr
].data
= (GLfloat (*)[4]) data
;
131 tmp
->Attribs
[attr
].start
= data
;
132 tmp
->Attribs
[attr
].size
= tnl
->vtx
.attrsz
[attr
];
133 tmp
->Attribs
[attr
].stride
= tnl
->vtx
.vertex_size
* sizeof(GLfloat
);
134 VB
->AttribPtr
[attr
] = &tmp
->Attribs
[attr
];
135 data
+= tnl
->vtx
.attrsz
[attr
];
138 /* VB->AttribPtr[attr] = &tnl->current.Attribs[attr]; */
141 tmp
->Attribs
[attr
].count
= count
;
142 tmp
->Attribs
[attr
].data
= (GLfloat (*)[4]) tnl
->vtx
.current
[attr
];
143 tmp
->Attribs
[attr
].start
= tnl
->vtx
.current
[attr
];
144 tmp
->Attribs
[attr
].size
= get_size( tnl
->vtx
.current
[attr
] );
145 tmp
->Attribs
[attr
].stride
= 0;
146 VB
->AttribPtr
[attr
] = &tmp
->Attribs
[attr
];
151 /* Copy and translate EdgeFlag to a contiguous array of GLbooleans
153 if (ctx
->Polygon
.FrontMode
!= GL_FILL
|| ctx
->Polygon
.BackMode
!= GL_FILL
) {
154 if (tnl
->vtx
.attrsz
[_TNL_ATTRIB_EDGEFLAG
]) {
155 VB
->EdgeFlag
= _tnl_translate_edgeflag( ctx
, data
, count
,
156 tnl
->vtx
.vertex_size
);
160 VB
->EdgeFlag
= _tnl_import_current_edgeflag( ctx
, count
);
163 /* Legacy pointers -- remove one day.
165 VB
->ObjPtr
= VB
->AttribPtr
[_TNL_ATTRIB_POS
];
166 VB
->NormalPtr
= VB
->AttribPtr
[_TNL_ATTRIB_NORMAL
];
167 VB
->ColorPtr
[0] = VB
->AttribPtr
[_TNL_ATTRIB_COLOR0
];
169 VB
->IndexPtr
[0] = VB
->AttribPtr
[_TNL_ATTRIB_INDEX
];
171 VB
->SecondaryColorPtr
[0] = VB
->AttribPtr
[_TNL_ATTRIB_COLOR1
];
172 VB
->SecondaryColorPtr
[1] = 0;
174 for (i
= 0; i
< ctx
->Const
.MaxTextureCoordUnits
; i
++) {
175 VB
->TexCoordPtr
[i
] = VB
->AttribPtr
[_TNL_ATTRIB_TEX0
+ i
];
184 * NOTE: Need to have calculated primitives by this point -- do it on the fly.
185 * NOTE: Old 'parity' issue is gone.
187 static GLuint
_tnl_copy_vertices( GLcontext
*ctx
)
189 TNLcontext
*tnl
= TNL_CONTEXT( ctx
);
190 GLuint nr
= tnl
->vtx
.prim
[tnl
->vtx
.prim_count
-1].count
;
192 GLuint sz
= tnl
->vtx
.vertex_size
;
193 GLfloat
*dst
= tnl
->vtx
.copied
.buffer
;
194 GLfloat
*src
= (tnl
->vtx
.buffer
+
195 tnl
->vtx
.prim
[tnl
->vtx
.prim_count
-1].start
*
196 tnl
->vtx
.vertex_size
);
199 switch( ctx
->Driver
.CurrentExecPrimitive
)
205 for (i
= 0 ; i
< ovf
; i
++)
206 memcpy( dst
+i
*sz
, src
+(nr
-ovf
+i
)*sz
, sz
* sizeof(GLfloat
) );
210 for (i
= 0 ; i
< ovf
; i
++)
211 memcpy( dst
+i
*sz
, src
+(nr
-ovf
+i
)*sz
, sz
* sizeof(GLfloat
) );
215 for (i
= 0 ; i
< ovf
; i
++)
216 memcpy( dst
+i
*sz
, src
+(nr
-ovf
+i
)*sz
, sz
* sizeof(GLfloat
) );
222 memcpy( dst
, src
+(nr
-1)*sz
, sz
* sizeof(GLfloat
) );
226 case GL_TRIANGLE_FAN
:
231 memcpy( dst
, src
+0, sz
* sizeof(GLfloat
) );
234 memcpy( dst
, src
+0, sz
* sizeof(GLfloat
) );
235 memcpy( dst
+sz
, src
+(nr
-1)*sz
, sz
* sizeof(GLfloat
) );
238 case GL_TRIANGLE_STRIP
:
241 case 0: ovf
= 0; break;
242 case 1: ovf
= 1; break;
243 default: ovf
= 2 + (nr
&1); break;
245 for (i
= 0 ; i
< ovf
; i
++)
246 memcpy( dst
+i
*sz
, src
+(nr
-ovf
+i
)*sz
, sz
* sizeof(GLfloat
) );
262 * Execute the buffer and save copied verts.
264 void _tnl_flush_vtx( GLcontext
*ctx
)
266 TNLcontext
*tnl
= TNL_CONTEXT(ctx
);
269 _tnl_print_vtx( ctx
);
271 if (tnl
->vtx
.prim_count
&&
272 tnl
->vtx
.counter
!= tnl
->vtx
.initial_counter
) {
274 tnl
->vtx
.copied
.nr
= _tnl_copy_vertices( ctx
);
277 _mesa_update_state( ctx
);
279 if (tnl
->pipeline
.build_state_changes
)
280 _tnl_validate_pipeline( ctx
);
282 _tnl_vb_bind_vtx( ctx
);
284 /* Invalidate all stored data before and after run:
286 tnl
->pipeline
.run_input_changes
|= tnl
->pipeline
.inputs
;
287 tnl
->Driver
.RunPipeline( ctx
);
288 tnl
->pipeline
.run_input_changes
|= tnl
->pipeline
.inputs
;
291 tnl
->vtx
.prim_count
= 0;
292 tnl
->vtx
.counter
= tnl
->vtx
.initial_counter
;
293 tnl
->vtx
.vbptr
= tnl
->vtx
.buffer
;