draw: corrections to allow for different cliptest cases
[mesa.git] / src / mesa / drivers / dri / tdfx / tdfx_vb.c
1 /*
2 * GLX Hardware Device Driver for Intel i810
3 * Copyright (C) 1999 Keith Whitwell
4 *
5 * Permission is hereby granted, free of charge, to any person obtaining a
6 * copy of this software and associated documentation files (the "Software"),
7 * to deal in the Software without restriction, including without limitation
8 * the rights to use, copy, modify, merge, publish, distribute, sublicense,
9 * and/or sell copies of the Software, and to permit persons to whom the
10 * Software is furnished to do so, subject to the following conditions:
11 *
12 * The above copyright notice and this permission notice shall be included
13 * in all copies or substantial portions of the Software.
14 *
15 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
16 * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
18 * KEITH WHITWELL, OR ANY OTHER CONTRIBUTORS BE LIABLE FOR ANY CLAIM,
19 * DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR
20 * OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE
21 * OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
22 *
23 *
24 */
25
26 #include "main/glheader.h"
27 #include "main/mtypes.h"
28 #include "main/imports.h"
29 #include "main/macros.h"
30 #include "main/colormac.h"
31
32 #include "tdfx_context.h"
33 #include "tdfx_vb.h"
34 #include "tdfx_render.h"
35
36 static void copy_pv( GLcontext *ctx, GLuint edst, GLuint esrc )
37 {
38 tdfxContextPtr fxMesa = TDFX_CONTEXT( ctx );
39 tdfxVertex *dst = fxMesa->verts + edst;
40 tdfxVertex *src = fxMesa->verts + esrc;
41 *(GLuint *)&dst->color = *(GLuint *)&src->color;
42 }
43
44 static struct {
45 void (*emit)( GLcontext *, GLuint, GLuint, void * );
46 tnl_interp_func interp;
47 tnl_copy_pv_func copy_pv;
48 GLboolean (*check_tex_sizes)( GLcontext *ctx );
49 GLuint vertex_format;
50 } setup_tab[TDFX_MAX_SETUP];
51
52
53
54
55 #define GET_COLOR(ptr, idx) ((ptr)->data[idx])
56
57
58 static void interp_extras( GLcontext *ctx,
59 GLfloat t,
60 GLuint dst, GLuint out, GLuint in,
61 GLboolean force_boundary )
62 {
63 struct vertex_buffer *VB = &TNL_CONTEXT(ctx)->vb;
64
65 /*fprintf(stderr, "%s\n", __FUNCTION__);*/
66
67 if (VB->BackfaceColorPtr) {
68 INTERP_4F( t,
69 GET_COLOR(VB->BackfaceColorPtr, dst),
70 GET_COLOR(VB->BackfaceColorPtr, out),
71 GET_COLOR(VB->BackfaceColorPtr, in) );
72 }
73
74 if (VB->EdgeFlag) {
75 VB->EdgeFlag[dst] = VB->EdgeFlag[out] || force_boundary;
76 }
77
78 setup_tab[TDFX_CONTEXT(ctx)->SetupIndex].interp(ctx, t, dst, out, in,
79 force_boundary);
80 }
81
82 static void copy_pv_extras( GLcontext *ctx, GLuint dst, GLuint src )
83 {
84 struct vertex_buffer *VB = &TNL_CONTEXT(ctx)->vb;
85
86 if (VB->BackfaceColorPtr) {
87 COPY_4FV( GET_COLOR(VB->BackfaceColorPtr, dst),
88 GET_COLOR(VB->BackfaceColorPtr, src) );
89 }
90
91 setup_tab[TDFX_CONTEXT(ctx)->SetupIndex].copy_pv(ctx, dst, src);
92 }
93
94
95
96 #define IND (TDFX_XYZ_BIT|TDFX_RGBA_BIT)
97 #define TAG(x) x##_wg
98 #include "tdfx_vbtmp.h"
99
100 /* Special for tdfx: fog requires w
101 */
102 #define IND (TDFX_XYZ_BIT|TDFX_RGBA_BIT|TDFX_W_BIT)
103 #define TAG(x) x##_wg_fog
104 #include "tdfx_vbtmp.h"
105
106 #define IND (TDFX_XYZ_BIT|TDFX_RGBA_BIT|TDFX_W_BIT|TDFX_TEX0_BIT)
107 #define TAG(x) x##_wgt0
108 #include "tdfx_vbtmp.h"
109
110 #define IND (TDFX_XYZ_BIT|TDFX_RGBA_BIT|TDFX_W_BIT|TDFX_TEX0_BIT|TDFX_TEX1_BIT)
111 #define TAG(x) x##_wgt0t1
112 #include "tdfx_vbtmp.h"
113
114 #define IND (TDFX_XYZ_BIT|TDFX_RGBA_BIT|TDFX_W_BIT|TDFX_TEX0_BIT|TDFX_PTEX_BIT)
115 #define TAG(x) x##_wgpt0
116 #include "tdfx_vbtmp.h"
117
118 #define IND (TDFX_XYZ_BIT|TDFX_RGBA_BIT|TDFX_W_BIT|TDFX_TEX0_BIT|TDFX_TEX1_BIT|\
119 TDFX_PTEX_BIT)
120 #define TAG(x) x##_wgpt0t1
121 #include "tdfx_vbtmp.h"
122
123 #define IND (TDFX_RGBA_BIT)
124 #define TAG(x) x##_g
125 #include "tdfx_vbtmp.h"
126
127 #define IND (TDFX_TEX0_BIT)
128 #define TAG(x) x##_t0
129 #include "tdfx_vbtmp.h"
130
131 #define IND (TDFX_TEX0_BIT|TDFX_TEX1_BIT)
132 #define TAG(x) x##_t0t1
133 #include "tdfx_vbtmp.h"
134
135 #define IND (TDFX_RGBA_BIT|TDFX_TEX0_BIT)
136 #define TAG(x) x##_gt0
137 #include "tdfx_vbtmp.h"
138
139 #define IND (TDFX_RGBA_BIT|TDFX_TEX0_BIT|TDFX_TEX1_BIT)
140 #define TAG(x) x##_gt0t1
141 #include "tdfx_vbtmp.h"
142
143
144 /* fogc { */
145 #define IND (TDFX_XYZ_BIT|TDFX_RGBA_BIT|TDFX_W_BIT|TDFX_FOGC_BIT)
146 #define TAG(x) x##_wgf
147 #include "tdfx_vbtmp.h"
148
149 #define IND (TDFX_XYZ_BIT|TDFX_RGBA_BIT|TDFX_W_BIT|TDFX_TEX0_BIT|TDFX_FOGC_BIT)
150 #define TAG(x) x##_wgt0f
151 #include "tdfx_vbtmp.h"
152
153 #define IND (TDFX_XYZ_BIT|TDFX_RGBA_BIT|TDFX_W_BIT|TDFX_TEX0_BIT|TDFX_TEX1_BIT|TDFX_FOGC_BIT)
154 #define TAG(x) x##_wgt0t1f
155 #include "tdfx_vbtmp.h"
156
157 #define IND (TDFX_XYZ_BIT|TDFX_RGBA_BIT|TDFX_W_BIT|TDFX_TEX0_BIT|TDFX_PTEX_BIT|TDFX_FOGC_BIT)
158 #define TAG(x) x##_wgpt0f
159 #include "tdfx_vbtmp.h"
160
161 #define IND (TDFX_XYZ_BIT|TDFX_RGBA_BIT|TDFX_W_BIT|TDFX_TEX0_BIT|TDFX_TEX1_BIT|\
162 TDFX_PTEX_BIT|TDFX_FOGC_BIT)
163 #define TAG(x) x##_wgpt0t1f
164 #include "tdfx_vbtmp.h"
165 /* fogc } */
166
167
168 static void init_setup_tab( void )
169 {
170 init_wg();
171 init_wg_fog();
172 init_wgt0();
173 init_wgt0t1();
174 init_wgpt0();
175 init_wgpt0t1();
176
177 init_g();
178 init_t0();
179 init_t0t1();
180 init_gt0();
181 init_gt0t1();
182
183 /* fogcoord */
184 init_wgf();
185 init_wgt0f();
186 init_wgt0t1f();
187 init_wgpt0f();
188 init_wgpt0t1f();
189 }
190
191
192 void tdfxPrintSetupFlags(char *msg, GLuint flags )
193 {
194 fprintf(stderr, "%s(%x): %s%s%s%s%s%s\n",
195 msg,
196 (int)flags,
197 (flags & TDFX_XYZ_BIT) ? " xyz," : "",
198 (flags & TDFX_W_BIT) ? " w," : "",
199 (flags & TDFX_RGBA_BIT) ? " rgba," : "",
200 (flags & TDFX_TEX0_BIT) ? " tex-0," : "",
201 (flags & TDFX_TEX1_BIT) ? " tex-1," : "",
202 (flags & TDFX_FOGC_BIT) ? " fogc," : "");
203 }
204
205
206
207 void tdfxCheckTexSizes( GLcontext *ctx )
208 {
209 TNLcontext *tnl = TNL_CONTEXT(ctx);
210 tdfxContextPtr fxMesa = TDFX_CONTEXT( ctx );
211
212 if (!setup_tab[fxMesa->SetupIndex].check_tex_sizes(ctx)) {
213 GLuint ind = fxMesa->SetupIndex |= (TDFX_PTEX_BIT|TDFX_RGBA_BIT);
214
215 /* Tdfx handles projective textures nicely; just have to change
216 * up to the new vertex format.
217 */
218 if (setup_tab[ind].vertex_format != fxMesa->vertexFormat) {
219 FLUSH_BATCH(fxMesa);
220 fxMesa->dirty |= TDFX_UPLOAD_VERTEX_LAYOUT;
221 fxMesa->vertexFormat = setup_tab[ind].vertex_format;
222
223 /* This is required as we have just changed the vertex
224 * format, so the interp and copy routines must also change.
225 * In the unfilled and twosided cases we are using the
226 * swrast_setup ones anyway, so leave them in place.
227 */
228 if (!(ctx->_TriangleCaps & (DD_TRI_LIGHT_TWOSIDE|DD_TRI_UNFILLED))) {
229 tnl->Driver.Render.Interp = setup_tab[fxMesa->SetupIndex].interp;
230 tnl->Driver.Render.CopyPV = setup_tab[fxMesa->SetupIndex].copy_pv;
231 }
232 }
233 }
234 }
235
236
237 void tdfxBuildVertices( GLcontext *ctx, GLuint start, GLuint end,
238 GLuint newinputs )
239 {
240 tdfxContextPtr fxMesa = TDFX_CONTEXT( ctx );
241 tdfxVertex *v = fxMesa->verts + start;
242
243 newinputs |= fxMesa->SetupNewInputs;
244 fxMesa->SetupNewInputs = 0;
245
246 if (!newinputs)
247 return;
248
249 if (newinputs & VERT_BIT_POS) {
250 setup_tab[fxMesa->SetupIndex].emit( ctx, start, end, v );
251 } else {
252 GLuint ind = 0;
253
254 if (newinputs & VERT_BIT_COLOR0)
255 ind |= TDFX_RGBA_BIT;
256
257 if (newinputs & VERT_BIT_FOG)
258 ind |= TDFX_FOGC_BIT;
259
260 if (newinputs & VERT_BIT_TEX0)
261 ind |= TDFX_TEX0_BIT;
262
263 if (newinputs & VERT_BIT_TEX1)
264 ind |= TDFX_TEX0_BIT|TDFX_TEX1_BIT;
265
266 if (fxMesa->SetupIndex & TDFX_PTEX_BIT)
267 ind = ~0;
268
269 ind &= fxMesa->SetupIndex;
270
271 if (ind) {
272 setup_tab[ind].emit( ctx, start, end, v );
273 }
274 }
275 }
276
277
278 void tdfxChooseVertexState( GLcontext *ctx )
279 {
280 TNLcontext *tnl = TNL_CONTEXT(ctx);
281 tdfxContextPtr fxMesa = TDFX_CONTEXT( ctx );
282 GLuint ind = TDFX_XYZ_BIT|TDFX_RGBA_BIT;
283
284 fxMesa->tmu_source[0] = 0;
285 fxMesa->tmu_source[1] = 1;
286
287 if (ctx->Texture._EnabledUnits & 0x2) {
288 if (ctx->Texture._EnabledUnits & 0x1) {
289 ind |= TDFX_TEX1_BIT;
290 }
291 ind |= TDFX_W_BIT|TDFX_TEX0_BIT;
292 fxMesa->tmu_source[0] = 1;
293 fxMesa->tmu_source[1] = 0;
294 } else if (ctx->Texture._EnabledUnits & 0x1) {
295 /* unit 0 enabled */
296 ind |= TDFX_W_BIT|TDFX_TEX0_BIT;
297 } else if (fxMesa->Fog.Mode != GR_FOG_DISABLE) {
298 ind |= TDFX_W_BIT;
299 }
300
301 if (fxMesa->Fog.Mode == GR_FOG_WITH_TABLE_ON_FOGCOORD_EXT) {
302 ind |= TDFX_FOGC_BIT;
303 }
304
305 fxMesa->SetupIndex = ind;
306
307 if (ctx->_TriangleCaps & (DD_TRI_LIGHT_TWOSIDE|DD_TRI_UNFILLED)) {
308 tnl->Driver.Render.Interp = interp_extras;
309 tnl->Driver.Render.CopyPV = copy_pv_extras;
310 } else {
311 tnl->Driver.Render.Interp = setup_tab[ind].interp;
312 tnl->Driver.Render.CopyPV = setup_tab[ind].copy_pv;
313 }
314
315 if (setup_tab[ind].vertex_format != fxMesa->vertexFormat) {
316 FLUSH_BATCH(fxMesa);
317 fxMesa->dirty |= TDFX_UPLOAD_VERTEX_LAYOUT;
318 fxMesa->vertexFormat = setup_tab[ind].vertex_format;
319 }
320 }
321
322
323
324 void tdfxInitVB( GLcontext *ctx )
325 {
326 tdfxContextPtr fxMesa = TDFX_CONTEXT(ctx);
327 GLuint size = TNL_CONTEXT(ctx)->vb.Size;
328 static int firsttime = 1;
329 if (firsttime) {
330 init_setup_tab();
331 firsttime = 0;
332 }
333
334 fxMesa->verts = _mesa_align_malloc(size * sizeof(tdfxVertex), 32);
335 fxMesa->vertexFormat = TDFX_LAYOUT_TINY;
336 fxMesa->SetupIndex = TDFX_XYZ_BIT|TDFX_RGBA_BIT;
337 }
338
339
340 void tdfxFreeVB( GLcontext *ctx )
341 {
342 tdfxContextPtr fxMesa = TDFX_CONTEXT(ctx);
343 if (fxMesa->verts) {
344 _mesa_align_free(fxMesa->verts);
345 fxMesa->verts = 0;
346 }
347 }