Reorganized combiners. Added optimized span functions.
[mesa.git] / src / mesa / drivers / glide / fxvb.c
1 /* $Id: fxvb.c,v 1.20 2003/10/09 15:12:21 dborca Exp $ */
2
3 /*
4 * Mesa 3-D graphics library
5 * Version: 5.1
6 *
7 * Copyright (C) 1999-2003 Brian Paul All Rights Reserved.
8 *
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:
15 *
16 * The above copyright notice and this permission notice shall be included
17 * in all copies or substantial portions of the Software.
18 *
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 * KEITH WHITWELL, OR ANY OTHER CONTRIBUTORS BE LIABLE FOR ANY CLAIM,
23 * DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR
24 * OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE
25 * OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
26 */
27
28 /* Authors:
29 * Keith Whitwell
30 */
31
32 #ifdef HAVE_CONFIG_H
33 #include "conf.h"
34 #endif
35
36 #ifdef FX
37
38 #include "glheader.h"
39 #include "mtypes.h"
40 #include "imports.h"
41 #include "macros.h"
42 #include "colormac.h"
43
44 #include "math/m_translate.h"
45 #include "swrast_setup/swrast_setup.h"
46
47 #include "tnl/tnl.h"
48 #include "tnl/t_context.h"
49
50 #include "fxdrv.h"
51
52
53 static void copy_pv( GLcontext *ctx, GLuint edst, GLuint esrc )
54 {
55 fxMesaContext fxMesa = FX_CONTEXT( ctx );
56 GrVertex *dst = fxMesa->verts + edst;
57 GrVertex *src = fxMesa->verts + esrc;
58
59 *(GLuint *)&dst->pargb = *(GLuint *)&src->pargb;
60 }
61
62 typedef void (*emit_func)( GLcontext *, GLuint, GLuint, void * );
63
64 static struct {
65 emit_func emit;
66 interp_func interp;
67 GLboolean (*check_tex_sizes)( GLcontext *ctx );
68 GLuint vertex_format;
69 } setup_tab[MAX_SETUP];
70
71
72 static void import_float_colors( GLcontext *ctx )
73 {
74 struct vertex_buffer *VB = &TNL_CONTEXT(ctx)->vb;
75 struct gl_client_array *from = VB->ColorPtr[0];
76 struct gl_client_array *to = &FX_CONTEXT(ctx)->UbyteColor;
77 GLuint count = VB->Count;
78
79 if (!to->Ptr) {
80 to->Ptr = ALIGN_MALLOC( VB->Size * 4 * sizeof(GLubyte), 32 );
81 to->Type = GL_UNSIGNED_BYTE;
82 }
83
84 /* No need to transform the same value 3000 times.
85 */
86 if (!from->StrideB) {
87 to->StrideB = 0;
88 count = 1;
89 }
90 else
91 to->StrideB = 4 * sizeof(GLubyte);
92
93 _math_trans_4ub( (GLubyte (*)[4]) to->Ptr,
94 from->Ptr,
95 from->StrideB,
96 from->Type,
97 from->Size,
98 0,
99 count);
100
101 VB->ColorPtr[0] = to;
102 }
103
104
105 /* Hack alert: assume chan is 8 bits */
106 #define GET_COLOR(ptr, idx) (((GLchan (*)[4])((ptr)->Ptr))[idx])
107
108
109 static void interp_extras( GLcontext *ctx,
110 GLfloat t,
111 GLuint dst, GLuint out, GLuint in,
112 GLboolean force_boundary )
113 {
114 struct vertex_buffer *VB = &TNL_CONTEXT(ctx)->vb;
115
116 if (VB->ColorPtr[1]) {
117 INTERP_4CHAN( t,
118 GET_COLOR(VB->ColorPtr[1], dst),
119 GET_COLOR(VB->ColorPtr[1], out),
120 GET_COLOR(VB->ColorPtr[1], in) );
121 #if 1 /* [dBorca] GL_EXT_separate_specular_color */
122 if (VB->SecondaryColorPtr[1]) {
123 INTERP_3CHAN( t,
124 GET_COLOR(VB->SecondaryColorPtr[1], dst),
125 GET_COLOR(VB->SecondaryColorPtr[1], out),
126 GET_COLOR(VB->SecondaryColorPtr[1], in) );
127 }
128 #endif
129 }
130
131 if (VB->EdgeFlag) {
132 VB->EdgeFlag[dst] = VB->EdgeFlag[out] || force_boundary;
133 }
134
135 setup_tab[FX_CONTEXT(ctx)->SetupIndex].interp(ctx, t, dst, out, in,
136 force_boundary);
137 }
138
139 static void copy_pv_extras( GLcontext *ctx, GLuint dst, GLuint src )
140 {
141 struct vertex_buffer *VB = &TNL_CONTEXT(ctx)->vb;
142
143 if (VB->ColorPtr[1]) {
144 COPY_CHAN4( GET_COLOR(VB->ColorPtr[1], dst),
145 GET_COLOR(VB->ColorPtr[1], src) );
146 #if 1 /* [dBorca] GL_EXT_separate_specular_color */
147 if (VB->SecondaryColorPtr[1]) {
148 COPY_CHAN4( GET_COLOR(VB->SecondaryColorPtr[1], dst),
149 GET_COLOR(VB->SecondaryColorPtr[1], src) );
150 }
151 #endif
152 }
153
154 copy_pv(ctx, dst, src);
155 }
156
157
158 #define IND (SETUP_XYZW|SETUP_RGBA)
159 #define TAG(x) x##_wg
160 #include "fxvbtmp.h"
161
162 #define IND (SETUP_XYZW|SETUP_RGBA|SETUP_TMU0)
163 #define TAG(x) x##_wgt0
164 #include "fxvbtmp.h"
165
166 #define IND (SETUP_XYZW|SETUP_RGBA|SETUP_TMU0|SETUP_TMU1)
167 #define TAG(x) x##_wgt0t1
168 #include "fxvbtmp.h"
169
170 #define IND (SETUP_XYZW|SETUP_RGBA|SETUP_TMU0|SETUP_PTEX)
171 #define TAG(x) x##_wgpt0
172 #include "fxvbtmp.h"
173
174 #define IND (SETUP_XYZW|SETUP_RGBA|SETUP_TMU0|SETUP_TMU1|\
175 SETUP_PTEX)
176 #define TAG(x) x##_wgpt0t1
177 #include "fxvbtmp.h"
178
179
180 /* Snapping for voodoo-1
181 */
182 #define IND (SETUP_XYZW|SETUP_SNAP|SETUP_RGBA)
183 #define TAG(x) x##_wsg
184 #include "fxvbtmp.h"
185
186 #define IND (SETUP_XYZW|SETUP_SNAP|SETUP_RGBA|SETUP_TMU0)
187 #define TAG(x) x##_wsgt0
188 #include "fxvbtmp.h"
189
190 #define IND (SETUP_XYZW|SETUP_SNAP|SETUP_RGBA|SETUP_TMU0|\
191 SETUP_TMU1)
192 #define TAG(x) x##_wsgt0t1
193 #include "fxvbtmp.h"
194
195 #define IND (SETUP_XYZW|SETUP_SNAP|SETUP_RGBA|SETUP_TMU0|\
196 SETUP_PTEX)
197 #define TAG(x) x##_wsgpt0
198 #include "fxvbtmp.h"
199
200 #define IND (SETUP_XYZW|SETUP_SNAP|SETUP_RGBA|SETUP_TMU0|\
201 SETUP_TMU1|SETUP_PTEX)
202 #define TAG(x) x##_wsgpt0t1
203 #include "fxvbtmp.h"
204
205
206 /* Vertex repair (multipass rendering)
207 */
208 #define IND (SETUP_RGBA)
209 #define TAG(x) x##_g
210 #include "fxvbtmp.h"
211
212 #define IND (SETUP_TMU0)
213 #define TAG(x) x##_t0
214 #include "fxvbtmp.h"
215
216 #define IND (SETUP_TMU0|SETUP_TMU1)
217 #define TAG(x) x##_t0t1
218 #include "fxvbtmp.h"
219
220 #define IND (SETUP_RGBA|SETUP_TMU0)
221 #define TAG(x) x##_gt0
222 #include "fxvbtmp.h"
223
224 #define IND (SETUP_RGBA|SETUP_TMU0|SETUP_TMU1)
225 #define TAG(x) x##_gt0t1
226 #include "fxvbtmp.h"
227
228
229
230 static void init_setup_tab( void )
231 {
232 init_wg();
233 init_wgt0();
234 init_wgt0t1();
235 init_wgpt0();
236 init_wgpt0t1();
237
238 init_wsg();
239 init_wsgt0();
240 init_wsgt0t1();
241 init_wsgpt0();
242 init_wsgpt0t1();
243
244 init_g();
245 init_t0();
246 init_t0t1();
247 init_gt0();
248 init_gt0t1();
249 }
250
251
252 void fxPrintSetupFlags(char *msg, GLuint flags )
253 {
254 fprintf(stderr, "%s(%x): %s%s%s%s%s\n",
255 msg,
256 (int)flags,
257 (flags & SETUP_XYZW) ? " xyzw," : "",
258 (flags & SETUP_SNAP) ? " snap," : "",
259 (flags & SETUP_RGBA) ? " rgba," : "",
260 (flags & SETUP_TMU0) ? " tex-0," : "",
261 (flags & SETUP_TMU1) ? " tex-1," : "");
262 }
263
264
265
266 void fxCheckTexSizes( GLcontext *ctx )
267 {
268 TNLcontext *tnl = TNL_CONTEXT(ctx);
269 fxMesaContext fxMesa = FX_CONTEXT( ctx );
270
271 if (!setup_tab[fxMesa->SetupIndex].check_tex_sizes(ctx)) {
272 GLuint ind = fxMesa->SetupIndex |= (SETUP_PTEX|SETUP_RGBA);
273
274 /* Tdfx handles projective textures nicely; just have to change
275 * up to the new vertex format.
276 */
277 if (setup_tab[ind].vertex_format != fxMesa->stw_hint_state) {
278
279 fxMesa->stw_hint_state = setup_tab[ind].vertex_format;
280 FX_grHints(GR_HINT_STWHINT, fxMesa->stw_hint_state);
281
282 /* This is required as we have just changed the vertex
283 * format, so the interp routines must also change.
284 * In the unfilled and twosided cases we are using the
285 * Extras ones anyway, so leave them in place.
286 */
287 if (!(ctx->_TriangleCaps & (DD_TRI_LIGHT_TWOSIDE|DD_TRI_UNFILLED))) {
288 tnl->Driver.Render.Interp = setup_tab[fxMesa->SetupIndex].interp;
289 }
290 }
291 }
292 }
293
294
295 void fxBuildVertices( GLcontext *ctx, GLuint start, GLuint count,
296 GLuint newinputs )
297 {
298 fxMesaContext fxMesa = FX_CONTEXT( ctx );
299 GrVertex *v = (fxMesa->verts + start);
300
301 if (!newinputs)
302 return;
303
304 if (newinputs & VERT_BIT_CLIP) {
305 setup_tab[fxMesa->SetupIndex].emit( ctx, start, count, v );
306 } else {
307 GLuint ind = 0;
308
309 if (newinputs & VERT_BIT_COLOR0)
310 ind |= SETUP_RGBA;
311
312 if (newinputs & VERT_BIT_TEX0)
313 ind |= SETUP_TMU0;
314
315 if (newinputs & VERT_BIT_TEX1)
316 ind |= SETUP_TMU0|SETUP_TMU1;
317
318 if (fxMesa->SetupIndex & SETUP_PTEX)
319 ind = ~0;
320
321 ind &= fxMesa->SetupIndex;
322
323 if (ind) {
324 setup_tab[ind].emit( ctx, start, count, v );
325 }
326 }
327 }
328
329
330 void fxChooseVertexState( GLcontext *ctx )
331 {
332 TNLcontext *tnl = TNL_CONTEXT(ctx);
333 fxMesaContext fxMesa = FX_CONTEXT( ctx );
334 GLuint ind = SETUP_XYZW|SETUP_RGBA;
335
336 if (fxMesa->snapVertices)
337 ind |= SETUP_SNAP;
338
339 fxMesa->tmu_source[0] = 0;
340 fxMesa->tmu_source[1] = 1;
341
342 if (ctx->Texture._EnabledUnits & 0x2) {
343 if (ctx->Texture._EnabledUnits & 0x1) {
344 ind |= SETUP_TMU1|SETUP_TMU0;
345 }
346 else {
347 fxMesa->tmu_source[0] = 1;
348 fxMesa->tmu_source[1] = 0;
349 ind |= SETUP_TMU0;
350 }
351 }
352 else if (ctx->Texture._EnabledUnits & 0x1) {
353 ind |= SETUP_TMU0;
354 }
355
356 fxMesa->SetupIndex = ind;
357
358 if (ctx->_TriangleCaps & (DD_TRI_LIGHT_TWOSIDE|DD_TRI_UNFILLED)) {
359 tnl->Driver.Render.Interp = interp_extras;
360 tnl->Driver.Render.CopyPV = copy_pv_extras;
361 } else {
362 tnl->Driver.Render.Interp = setup_tab[ind].interp;
363 tnl->Driver.Render.CopyPV = copy_pv;
364 }
365
366 if (setup_tab[ind].vertex_format != fxMesa->stw_hint_state) {
367 fxMesa->stw_hint_state = setup_tab[ind].vertex_format;
368 FX_grHints(GR_HINT_STWHINT, fxMesa->stw_hint_state);
369 }
370 }
371
372
373
374 void fxAllocVB( GLcontext *ctx )
375 {
376 fxMesaContext fxMesa = FX_CONTEXT(ctx);
377 GLuint size = TNL_CONTEXT(ctx)->vb.Size;
378 static int firsttime = 1;
379 if (firsttime) {
380 init_setup_tab();
381 firsttime = 0;
382 }
383
384 fxMesa->verts = (GrVertex *)ALIGN_MALLOC(size * sizeof(GrVertex), 32);
385 fxMesa->SetupIndex = SETUP_XYZW|SETUP_RGBA;
386 }
387
388
389 void fxFreeVB( GLcontext *ctx )
390 {
391 fxMesaContext fxMesa = FX_CONTEXT(ctx);
392 if (fxMesa->verts) {
393 ALIGN_FREE(fxMesa->verts);
394 fxMesa->verts = 0;
395 }
396
397 if (fxMesa->UbyteColor.Ptr) {
398 ALIGN_FREE(fxMesa->UbyteColor.Ptr);
399 fxMesa->UbyteColor.Ptr = 0;
400 }
401 }
402 #else
403
404
405 /*
406 * Need this to provide at least one external definition.
407 */
408
409 extern int gl_fx_dummy_function_vb(void);
410 int
411 gl_fx_dummy_function_vb(void)
412 {
413 return 0;
414 }
415
416 #endif /* FX */