Merge branch 'gallium-vertex-linear' into gallium-0.1
[mesa.git] / src / mesa / drivers / dri / tdfx / tdfx_render.c
1 /* -*- mode: c; c-basic-offset: 3 -*-
2 *
3 * Copyright 2000 VA Linux Systems Inc., Fremont, California.
4 *
5 * All Rights Reserved.
6 *
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:
13 *
14 * The above copyright notice and this permission notice (including the next
15 * paragraph) shall be included in all copies or substantial portions of the
16 * Software.
17 *
18 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
19 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
20 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
21 * VA LINUX SYSTEMS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
22 * WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF
23 * OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
24 * SOFTWARE.
25 */
26
27 /*
28 * New fixes:
29 * Daniel Borca <dborca@users.sourceforge.net>, 19 Jul 2004
30 *
31 * Original rewrite:
32 * Gareth Hughes <gareth@valinux.com>, 29 Sep - 1 Oct 2000
33 *
34 * Authors:
35 * Gareth Hughes <gareth@valinux.com>
36 * Brian Paul <brianp@valinux.com>
37 *
38 */
39
40 #include "tdfx_context.h"
41 #include "tdfx_render.h"
42 #include "tdfx_state.h"
43 #include "tdfx_texman.h"
44 #include "swrast/swrast.h"
45
46 /* Clear the color and/or depth buffers.
47 */
48 static void tdfxClear( GLcontext *ctx, GLbitfield mask )
49 {
50 tdfxContextPtr fxMesa = (tdfxContextPtr) ctx->DriverCtx;
51 GLbitfield softwareMask = mask & (BUFFER_BIT_ACCUM);
52 const GLuint stencil_size =
53 fxMesa->haveHwStencil ? fxMesa->glCtx->Visual.stencilBits : 0;
54
55 if ( TDFX_DEBUG & DEBUG_VERBOSE_API ) {
56 fprintf( stderr, "tdfxClear(0x%x)\n", mask);
57 }
58
59 /* Need this check to respond to glScissor and clipping updates */
60 if ((fxMesa->new_state & (TDFX_NEW_CLIP | TDFX_NEW_DEPTH)) ||
61 (fxMesa->dirty & TDFX_UPLOAD_COLOR_MASK)) {
62 tdfxDDUpdateHwState(ctx);
63 }
64
65 /* we can't clear accum buffers */
66 mask &= ~(BUFFER_BIT_ACCUM);
67
68 if (mask & BUFFER_BIT_STENCIL) {
69 if (!fxMesa->haveHwStencil || (ctx->Stencil.WriteMask[0] & 0xff) != 0xff) {
70 /* Napalm seems to have trouble with stencil write masks != 0xff */
71 /* do stencil clear in software */
72 mask &= ~(BUFFER_BIT_STENCIL);
73 softwareMask |= BUFFER_BIT_STENCIL;
74 }
75 }
76
77 if (fxMesa->glCtx->Visual.redBits != 8) {
78 /* can only do color masking if running in 24/32bpp on Napalm */
79 if (ctx->Color.ColorMask[RCOMP] != ctx->Color.ColorMask[GCOMP] ||
80 ctx->Color.ColorMask[GCOMP] != ctx->Color.ColorMask[BCOMP]) {
81 softwareMask |= (mask & (BUFFER_BIT_FRONT_LEFT | BUFFER_BIT_BACK_LEFT));
82 mask &= ~(BUFFER_BIT_FRONT_LEFT | BUFFER_BIT_BACK_LEFT);
83 }
84 }
85
86 if (fxMesa->haveHwStencil) {
87 /*
88 * If we want to clear stencil, it must be enabled
89 * in the HW, even if the stencil test is not enabled
90 * in the OGL state.
91 */
92 LOCK_HARDWARE(fxMesa);
93 if (mask & BUFFER_BIT_STENCIL) {
94 fxMesa->Glide.grStencilMask(/*ctx->Stencil.WriteMask*/ 0xff);
95 /* set stencil ref value = desired clear value */
96 fxMesa->Glide.grStencilFunc(GR_CMP_ALWAYS,
97 (fxMesa->Stencil.Clear & 0xff), 0xff);
98 fxMesa->Glide.grStencilOp(GR_STENCILOP_REPLACE,
99 GR_STENCILOP_REPLACE, GR_STENCILOP_REPLACE);
100 fxMesa->Glide.grEnable(GR_STENCIL_MODE_EXT);
101 }
102 else {
103 fxMesa->Glide.grDisable(GR_STENCIL_MODE_EXT);
104 }
105 UNLOCK_HARDWARE(fxMesa);
106 }
107
108 /*
109 * This may be ugly, but it's needed in order to work around a number
110 * of Glide bugs.
111 */
112 BEGIN_CLIP_LOOP(fxMesa);
113 {
114 /*
115 * This could probably be done fancier but doing each possible case
116 * explicitly is less error prone.
117 */
118 switch (mask & ~BUFFER_BIT_STENCIL) {
119 case BUFFER_BIT_BACK_LEFT | BUFFER_BIT_DEPTH:
120 /* back buffer & depth */
121 FX_grColorMaskv_NoLock(ctx, true4); /* work around Voodoo3 bug */
122 fxMesa->Glide.grDepthMask(FXTRUE);
123 fxMesa->Glide.grRenderBuffer(GR_BUFFER_BACKBUFFER);
124 if (stencil_size > 0) {
125 fxMesa->Glide.grBufferClearExt(fxMesa->Color.ClearColor,
126 fxMesa->Color.ClearAlpha,
127 fxMesa->Depth.Clear,
128 (FxU32) (ctx->Stencil.Clear & 0xff));
129 }
130 else
131 fxMesa->Glide.grBufferClear(fxMesa->Color.ClearColor,
132 fxMesa->Color.ClearAlpha,
133 fxMesa->Depth.Clear);
134 if (!ctx->Depth.Mask || !ctx->Depth.Test) {
135 fxMesa->Glide.grDepthMask(FXFALSE);
136 }
137 break;
138 case BUFFER_BIT_FRONT_LEFT | BUFFER_BIT_DEPTH:
139 /* XXX it appears that the depth buffer isn't cleared when
140 * glRenderBuffer(GR_BUFFER_FRONTBUFFER) is set.
141 * This is a work-around/
142 */
143 /* clear depth */
144 fxMesa->Glide.grDepthMask(FXTRUE);
145 fxMesa->Glide.grRenderBuffer(GR_BUFFER_BACKBUFFER);
146 FX_grColorMaskv_NoLock(ctx, false4);
147 if (stencil_size > 0)
148 fxMesa->Glide.grBufferClearExt(fxMesa->Color.ClearColor,
149 fxMesa->Color.ClearAlpha,
150 fxMesa->Depth.Clear,
151 (FxU32) (ctx->Stencil.Clear & 0xff));
152 else
153 fxMesa->Glide.grBufferClear(fxMesa->Color.ClearColor,
154 fxMesa->Color.ClearAlpha,
155 fxMesa->Depth.Clear & 0xff);
156 /* clear front */
157 FX_grColorMaskv_NoLock(ctx, true4);
158 fxMesa->Glide.grRenderBuffer(GR_BUFFER_FRONTBUFFER);
159 if (stencil_size > 0)
160 fxMesa->Glide.grBufferClearExt(fxMesa->Color.ClearColor,
161 fxMesa->Color.ClearAlpha,
162 fxMesa->Depth.Clear,
163 (FxU32) (ctx->Stencil.Clear & 0xff));
164 else
165 fxMesa->Glide.grBufferClear(fxMesa->Color.ClearColor,
166 fxMesa->Color.ClearAlpha,
167 fxMesa->Depth.Clear);
168 if (!ctx->Depth.Mask || !ctx->Depth.Test) {
169 fxMesa->Glide.grDepthMask(FXFALSE);
170 }
171 break;
172 case BUFFER_BIT_BACK_LEFT:
173 /* back buffer only */
174 fxMesa->Glide.grDepthMask(FXFALSE);
175 fxMesa->Glide.grRenderBuffer(GR_BUFFER_BACKBUFFER);
176 if (stencil_size > 0)
177 fxMesa->Glide.grBufferClearExt(fxMesa->Color.ClearColor,
178 fxMesa->Color.ClearAlpha,
179 fxMesa->Depth.Clear,
180 (FxU32) (ctx->Stencil.Clear & 0xff));
181 else
182 fxMesa->Glide.grBufferClear(fxMesa->Color.ClearColor,
183 fxMesa->Color.ClearAlpha,
184 fxMesa->Depth.Clear);
185 if (ctx->Depth.Mask && ctx->Depth.Test) {
186 fxMesa->Glide.grDepthMask(FXTRUE);
187 }
188 break;
189 case BUFFER_BIT_FRONT_LEFT:
190 /* front buffer only */
191 fxMesa->Glide.grDepthMask(FXFALSE);
192 fxMesa->Glide.grRenderBuffer(GR_BUFFER_FRONTBUFFER);
193 if (stencil_size > 0)
194 fxMesa->Glide.grBufferClearExt(fxMesa->Color.ClearColor,
195 fxMesa->Color.ClearAlpha,
196 fxMesa->Depth.Clear,
197 (FxU32) (ctx->Stencil.Clear & 0xff));
198 else
199 fxMesa->Glide.grBufferClear(fxMesa->Color.ClearColor,
200 fxMesa->Color.ClearAlpha,
201 fxMesa->Depth.Clear);
202 if (ctx->Depth.Mask && ctx->Depth.Test) {
203 fxMesa->Glide.grDepthMask(FXTRUE);
204 }
205 break;
206 case BUFFER_BIT_FRONT_LEFT | BUFFER_BIT_BACK_LEFT:
207 /* front and back */
208 fxMesa->Glide.grDepthMask(FXFALSE);
209 fxMesa->Glide.grRenderBuffer(GR_BUFFER_BACKBUFFER);
210 if (stencil_size > 0)
211 fxMesa->Glide.grBufferClearExt(fxMesa->Color.ClearColor,
212 fxMesa->Color.ClearAlpha,
213 fxMesa->Depth.Clear,
214 (FxU32) (ctx->Stencil.Clear & 0xff));
215 else
216 fxMesa->Glide.grBufferClear(fxMesa->Color.ClearColor,
217 fxMesa->Color.ClearAlpha,
218 fxMesa->Depth.Clear);
219 fxMesa->Glide.grRenderBuffer(GR_BUFFER_FRONTBUFFER);
220 if (stencil_size > 0)
221 fxMesa->Glide.grBufferClearExt(fxMesa->Color.ClearColor,
222 fxMesa->Color.ClearAlpha,
223 fxMesa->Depth.Clear,
224 (FxU32) (ctx->Stencil.Clear & 0xff));
225 else
226 fxMesa->Glide.grBufferClear(fxMesa->Color.ClearColor,
227 fxMesa->Color.ClearAlpha,
228 fxMesa->Depth.Clear);
229 if (ctx->Depth.Mask && ctx->Depth.Test) {
230 fxMesa->Glide.grDepthMask(FXTRUE);
231 }
232 break;
233 case BUFFER_BIT_FRONT_LEFT | BUFFER_BIT_BACK_LEFT | BUFFER_BIT_DEPTH:
234 /* clear front */
235 fxMesa->Glide.grDepthMask(FXFALSE);
236 fxMesa->Glide.grRenderBuffer(GR_BUFFER_FRONTBUFFER);
237 if (stencil_size > 0)
238 fxMesa->Glide.grBufferClearExt(fxMesa->Color.ClearColor,
239 fxMesa->Color.ClearAlpha,
240 fxMesa->Depth.Clear,
241 (FxU32) (ctx->Stencil.Clear & 0xff));
242 else
243 fxMesa->Glide.grBufferClear(fxMesa->Color.ClearColor,
244 fxMesa->Color.ClearAlpha,
245 fxMesa->Depth.Clear);
246 /* clear back and depth */
247 fxMesa->Glide.grDepthMask(FXTRUE);
248 fxMesa->Glide.grRenderBuffer(GR_BUFFER_BACKBUFFER);
249 if (stencil_size > 0)
250 fxMesa->Glide.grBufferClearExt(fxMesa->Color.ClearColor,
251 fxMesa->Color.ClearAlpha,
252 fxMesa->Depth.Clear,
253 (FxU32) (ctx->Stencil.Clear & 0xff));
254 else
255 fxMesa->Glide.grBufferClear(fxMesa->Color.ClearColor,
256 fxMesa->Color.ClearAlpha,
257 fxMesa->Depth.Clear);
258 if (!ctx->Depth.Mask || !ctx->Depth.Mask) {
259 fxMesa->Glide.grDepthMask(FXFALSE);
260 }
261 break;
262 case BUFFER_BIT_DEPTH:
263 /* just the depth buffer */
264 fxMesa->Glide.grRenderBuffer(GR_BUFFER_BACKBUFFER);
265 FX_grColorMaskv_NoLock(ctx, false4);
266 fxMesa->Glide.grDepthMask(FXTRUE);
267 if (stencil_size > 0)
268 fxMesa->Glide.grBufferClearExt(fxMesa->Color.ClearColor,
269 fxMesa->Color.ClearAlpha,
270 fxMesa->Depth.Clear,
271 (FxU32) (ctx->Stencil.Clear & 0xff));
272 else
273 fxMesa->Glide.grBufferClear(fxMesa->Color.ClearColor,
274 fxMesa->Color.ClearAlpha,
275 fxMesa->Depth.Clear);
276 FX_grColorMaskv_NoLock(ctx, true4);
277 if (ctx->DrawBuffer->_ColorDrawBufferMask[0] & BUFFER_BIT_FRONT_LEFT)
278 fxMesa->Glide.grRenderBuffer(GR_BUFFER_FRONTBUFFER);
279 if (!ctx->Depth.Test || !ctx->Depth.Mask)
280 fxMesa->Glide.grDepthMask(FXFALSE);
281 break;
282 default:
283 /* clear no color buffers or depth buffer but might clear stencil */
284 if (stencil_size > 0 && (mask & BUFFER_BIT_STENCIL)) {
285 /* XXX need this RenderBuffer call to work around Glide bug */
286 fxMesa->Glide.grRenderBuffer(GR_BUFFER_BACKBUFFER);
287 fxMesa->Glide.grDepthMask(FXFALSE);
288 FX_grColorMaskv_NoLock(ctx, false4);
289 fxMesa->Glide.grBufferClearExt(fxMesa->Color.ClearColor,
290 fxMesa->Color.ClearAlpha,
291 fxMesa->Depth.Clear,
292 (FxU32) (ctx->Stencil.Clear & 0xff));
293 if (ctx->Depth.Mask && ctx->Depth.Test) {
294 fxMesa->Glide.grDepthMask(FXTRUE);
295 }
296 FX_grColorMaskv_NoLock(ctx, true4);
297 if (ctx->DrawBuffer->_ColorDrawBufferMask[0] & BUFFER_BIT_FRONT_LEFT)
298 fxMesa->Glide.grRenderBuffer(GR_BUFFER_FRONTBUFFER);
299 }
300 }
301 }
302 END_CLIP_LOOP(fxMesa);
303
304 if (fxMesa->haveHwStencil && (mask & BUFFER_BIT_STENCIL)) {
305 /* We changed the stencil state above. Signal that we need to
306 * upload it again.
307 */
308 fxMesa->dirty |= TDFX_UPLOAD_STENCIL;
309 }
310
311 if (softwareMask)
312 _swrast_Clear(ctx, softwareMask);
313 }
314
315
316
317 static void tdfxFinish( GLcontext *ctx )
318 {
319 tdfxContextPtr fxMesa = TDFX_CONTEXT(ctx);
320
321 FLUSH_BATCH( fxMesa );
322
323 LOCK_HARDWARE( fxMesa );
324 fxMesa->Glide.grFinish();
325 UNLOCK_HARDWARE( fxMesa );
326 }
327
328 static void tdfxFlush( GLcontext *ctx )
329 {
330 tdfxContextPtr fxMesa = TDFX_CONTEXT(ctx);
331
332 FLUSH_BATCH( fxMesa );
333
334 LOCK_HARDWARE( fxMesa );
335 fxMesa->Glide.grFlush();
336 UNLOCK_HARDWARE( fxMesa );
337 }
338
339
340 #if 0
341 static const char *texSource(int k)
342 {
343 switch (k) {
344 case GR_CMBX_ZERO:
345 return "GR_CMBX_ZERO";
346 case GR_CMBX_TEXTURE_ALPHA:
347 return "GR_CMBX_TEXTURE_ALPHA";
348 case GR_CMBX_ALOCAL:
349 return "GR_CMBX_ALOCAL";
350 case GR_CMBX_AOTHER:
351 return "GR_CMBX_AOTHER";
352 case GR_CMBX_B:
353 return "GR_CMBX_B";
354 case GR_CMBX_CONSTANT_ALPHA:
355 return "GR_CMBX_CONSTANT_ALPHA";
356 case GR_CMBX_CONSTANT_COLOR:
357 return "GR_CMBX_CONSTANT_COLOR";
358 case GR_CMBX_DETAIL_FACTOR:
359 return "GR_CMBX_DETAIL_FACTOR";
360 case GR_CMBX_ITALPHA:
361 return "GR_CMBX_ITALPHA";
362 case GR_CMBX_ITRGB:
363 return "GR_CMBX_ITRGB";
364 case GR_CMBX_LOCAL_TEXTURE_ALPHA:
365 return "GR_CMBX_LOCAL_TEXTURE_ALPHA";
366 case GR_CMBX_LOCAL_TEXTURE_RGB:
367 return "GR_CMBX_LOCAL_TEXTURE_RGB";
368 case GR_CMBX_LOD_FRAC:
369 return "GR_CMBX_LOD_FRAC";
370 case GR_CMBX_OTHER_TEXTURE_ALPHA:
371 return "GR_CMBX_OTHER_TEXTURE_ALPHA";
372 case GR_CMBX_OTHER_TEXTURE_RGB:
373 return "GR_CMBX_OTHER_TEXTURE_RGB";
374 case GR_CMBX_TEXTURE_RGB:
375 return "GR_CMBX_TEXTURE_RGB";
376 case GR_CMBX_TMU_CALPHA:
377 return "GR_CMBX_TMU_CALPHA";
378 case GR_CMBX_TMU_CCOLOR:
379 return "GR_CMBX_TMU_CCOLOR";
380 default:
381 return "";
382 }
383 }
384 #endif
385
386 #if 0
387 static const char *texMode(int k)
388 {
389 switch (k) {
390 case GR_FUNC_MODE_ZERO:
391 return "GR_FUNC_MODE_ZERO";
392 case GR_FUNC_MODE_X:
393 return "GR_FUNC_MODE_X";
394 case GR_FUNC_MODE_ONE_MINUS_X:
395 return "GR_FUNC_MODE_ONE_MINUS_X";
396 case GR_FUNC_MODE_NEGATIVE_X:
397 return "GR_FUNC_MODE_NEGATIVE_X";
398 case GR_FUNC_MODE_X_MINUS_HALF:
399 return "GR_FUNC_MODE_X_MINUS_HALF";
400 default:
401 return "";
402 }
403 }
404 #endif
405
406 #if 0
407 static const char *texInvert(int k)
408 {
409 return k ? "FXTRUE" : "FXFALSE";
410 }
411 #endif
412
413 static void uploadTextureEnv( tdfxContextPtr fxMesa )
414 {
415 if (TDFX_IS_NAPALM(fxMesa)) {
416 int unit;
417 for (unit = 0; unit < TDFX_NUM_TMU; unit++) {
418 #if 0
419 printf("upload env %d\n", unit);
420 printf(" cSourceA = %s\t", texSource(fxMesa->TexCombineExt[unit].Color.SourceA));
421 printf(" cModeA = %s\n", texMode(fxMesa->TexCombineExt[unit].Color.ModeA));
422 printf(" cSourceB = %s\t", texSource(fxMesa->TexCombineExt[unit].Color.SourceB));
423 printf(" cModeB = %s\n", texMode(fxMesa->TexCombineExt[unit].Color.ModeB));
424 printf(" cSourceC = %s\t", texSource(fxMesa->TexCombineExt[unit].Color.SourceC));
425 printf(" cInvertC = %s\n", texInvert(fxMesa->TexCombineExt[unit].Color.InvertC));
426 printf(" cSourceD = %s\t", texSource(fxMesa->TexCombineExt[unit].Color.SourceD));
427 printf(" cInvertD = %s\n", texInvert(fxMesa->TexCombineExt[unit].Color.InvertD));
428 printf(" cShift = %d\t", fxMesa->TexCombineExt[unit].Color.Shift);
429 printf(" cInvert = %d\n", fxMesa->TexCombineExt[unit].Color.Invert);
430 printf(" aSourceA = %s\t", texSource(fxMesa->TexCombineExt[unit].Alpha.SourceA));
431 printf(" aModeA = %s\n", texMode(fxMesa->TexCombineExt[unit].Alpha.ModeA));
432 printf(" aSourceB = %s\t", texSource(fxMesa->TexCombineExt[unit].Alpha.SourceB));
433 printf(" aModeB = %s\n", texMode(fxMesa->TexCombineExt[unit].Alpha.ModeB));
434 printf(" aSourceC = %s\t", texSource(fxMesa->TexCombineExt[unit].Alpha.SourceC));
435 printf(" aInvertC = %s\n", texInvert(fxMesa->TexCombineExt[unit].Alpha.InvertC));
436 printf(" aSourceD = %s\t", texSource(fxMesa->TexCombineExt[unit].Alpha.SourceD));
437 printf(" aInvertD = %s\n", texInvert(fxMesa->TexCombineExt[unit].Alpha.InvertD));
438 printf(" aShift = %d\t", fxMesa->TexCombineExt[unit].Alpha.Shift);
439 printf(" aInvert = %d\n", fxMesa->TexCombineExt[unit].Alpha.Invert);
440 printf(" Color = 0x%08x\n", fxMesa->TexCombineExt[unit].EnvColor);
441 #endif
442 fxMesa->Glide.grTexColorCombineExt(TDFX_TMU0 + unit,
443 fxMesa->TexCombineExt[unit].Color.SourceA,
444 fxMesa->TexCombineExt[unit].Color.ModeA,
445 fxMesa->TexCombineExt[unit].Color.SourceB,
446 fxMesa->TexCombineExt[unit].Color.ModeB,
447 fxMesa->TexCombineExt[unit].Color.SourceC,
448 fxMesa->TexCombineExt[unit].Color.InvertC,
449 fxMesa->TexCombineExt[unit].Color.SourceD,
450 fxMesa->TexCombineExt[unit].Color.InvertD,
451 fxMesa->TexCombineExt[unit].Color.Shift,
452 fxMesa->TexCombineExt[unit].Color.Invert);
453 fxMesa->Glide.grTexAlphaCombineExt(TDFX_TMU0 + unit,
454 fxMesa->TexCombineExt[unit].Alpha.SourceA,
455 fxMesa->TexCombineExt[unit].Alpha.ModeA,
456 fxMesa->TexCombineExt[unit].Alpha.SourceB,
457 fxMesa->TexCombineExt[unit].Alpha.ModeB,
458 fxMesa->TexCombineExt[unit].Alpha.SourceC,
459 fxMesa->TexCombineExt[unit].Alpha.InvertC,
460 fxMesa->TexCombineExt[unit].Alpha.SourceD,
461 fxMesa->TexCombineExt[unit].Alpha.InvertD,
462 fxMesa->TexCombineExt[unit].Alpha.Shift,
463 fxMesa->TexCombineExt[unit].Alpha.Invert);
464 fxMesa->Glide.grConstantColorValueExt(TDFX_TMU0 + unit,
465 fxMesa->TexCombineExt[unit].EnvColor);
466 }
467 }
468 else {
469 /* Voodoo3 */
470 int unit;
471 for (unit = 0; unit < TDFX_NUM_TMU; unit++) {
472 struct tdfx_texcombine *comb = &fxMesa->TexCombine[unit];
473 fxMesa->Glide.grTexCombine(TDFX_TMU0 + unit,
474 comb->FunctionRGB,
475 comb->FactorRGB,
476 comb->FunctionAlpha,
477 comb->FactorAlpha,
478 comb->InvertRGB,
479 comb->InvertAlpha);
480 }
481 }
482 }
483
484
485 static void uploadTextureParams( tdfxContextPtr fxMesa )
486 {
487 int unit;
488 for (unit = 0; unit < TDFX_NUM_TMU; unit++) {
489 const struct tdfx_texparams *p = &fxMesa->TexParams[unit];
490 /*
491 printf("upload params %d\n", unit);
492 printf(" clamp %x %x\n", env->sClamp, env->tClamp);
493 printf(" filter %x %x\n", env->minFilt, env->magFilt);
494 printf(" mipmap %x %x\n", env->mmMode, env->LODblend);
495 printf(" lod bias %f\n", env->LodBias);
496 */
497 fxMesa->Glide.grTexClampMode(GR_TMU0 + unit, p->sClamp, p->tClamp);
498 fxMesa->Glide.grTexFilterMode(GR_TMU0 + unit, p->minFilt, p->magFilt);
499 fxMesa->Glide.grTexMipMapMode(GR_TMU0 + unit, p->mmMode, p->LODblend);
500 fxMesa->Glide.grTexLodBiasValue(GR_TMU0 + unit, CLAMP(p->LodBias, -8, 7.75));
501 }
502 }
503
504
505 static void uploadTextureSource( tdfxContextPtr fxMesa )
506 {
507 int unit;
508 for (unit = 0; unit < TDFX_NUM_TMU; unit++) {
509 const struct tdfx_texsource *src = &fxMesa->TexSource[unit];
510 /*
511 printf("upload source %d @ %d %p\n", unit, src->StartAddress, src->Info);
512 */
513 if (src->Info) {
514 /*
515 printf(" smallLodLog2=%d largeLodLog2=%d ar=%d format=%d data=%p\n",
516 src->Info->smallLodLog2, src->Info->largeLodLog2,
517 src->Info->aspectRatioLog2, src->Info->format,
518 src->Info->data);
519 */
520 fxMesa->Glide.grTexSource(GR_TMU0 + unit,
521 src->StartAddress,
522 src->EvenOdd,
523 src->Info);
524 }
525 }
526 }
527
528
529 static void uploadTextureImages( tdfxContextPtr fxMesa )
530 {
531 GLcontext *ctx = fxMesa->glCtx;
532 int unit;
533 for (unit = 0; unit < TDFX_NUM_TMU; unit++) {
534 if (ctx->Texture.Unit[unit]._ReallyEnabled & (TEXTURE_1D_BIT|TEXTURE_2D_BIT)) {
535 struct gl_texture_object *tObj = ctx->Texture.Unit[unit]._Current;
536 tdfxTexInfo *ti = TDFX_TEXTURE_DATA(tObj);
537 if (ti && ti->reloadImages && ti->whichTMU != TDFX_TMU_NONE) {
538 /*
539 printf("download texture image on unit %d\n", unit);
540 */
541 tdfxTMDownloadTexture(fxMesa, tObj);
542 ti->reloadImages = GL_FALSE;
543 }
544 }
545 }
546 }
547
548
549
550 /*
551 * If scissoring is enabled, compute intersection of scissor region
552 * with all X clip rects, resulting in new cliprect list.
553 * If number of cliprects is zero or one, call grClipWindow to setup
554 * the clip region. Otherwise we'll call grClipWindow inside the
555 * BEGIN_CLIP_LOOP macro.
556 */
557 void tdfxUploadClipping( tdfxContextPtr fxMesa )
558 {
559 __DRIdrawablePrivate *dPriv = fxMesa->driDrawable;
560
561 assert(dPriv);
562
563 if (fxMesa->numClipRects == 0) {
564 /* all drawing clipped away */
565 fxMesa->Glide.grClipWindow(0, 0, 0, 0);
566 }
567 else if (fxMesa->numClipRects == 1) {
568 fxMesa->Glide.grClipWindow(fxMesa->pClipRects[0].x1,
569 fxMesa->screen_height - fxMesa->pClipRects[0].y2,
570 fxMesa->pClipRects[0].x2,
571 fxMesa->screen_height - fxMesa->pClipRects[0].y1);
572 }
573 /* else, we'll do a cliprect loop around all drawing */
574
575 fxMesa->Glide.grDRIPosition( dPriv->x, dPriv->y, dPriv->w, dPriv->h,
576 fxMesa->numClipRects, fxMesa->pClipRects );
577 }
578
579
580 void tdfxEmitHwStateLocked( tdfxContextPtr fxMesa )
581 {
582 if ( !fxMesa->dirty )
583 return;
584
585 if ( fxMesa->dirty & TDFX_UPLOAD_COLOR_COMBINE ) {
586 if (TDFX_IS_NAPALM(fxMesa)) {
587 fxMesa->Glide.grColorCombineExt(fxMesa->ColorCombineExt.SourceA,
588 fxMesa->ColorCombineExt.ModeA,
589 fxMesa->ColorCombineExt.SourceB,
590 fxMesa->ColorCombineExt.ModeB,
591 fxMesa->ColorCombineExt.SourceC,
592 fxMesa->ColorCombineExt.InvertC,
593 fxMesa->ColorCombineExt.SourceD,
594 fxMesa->ColorCombineExt.InvertD,
595 fxMesa->ColorCombineExt.Shift,
596 fxMesa->ColorCombineExt.Invert);
597 }
598 else {
599 /* Voodoo 3 */
600 fxMesa->Glide.grColorCombine( fxMesa->ColorCombine.Function,
601 fxMesa->ColorCombine.Factor,
602 fxMesa->ColorCombine.Local,
603 fxMesa->ColorCombine.Other,
604 fxMesa->ColorCombine.Invert );
605 }
606 fxMesa->dirty &= ~TDFX_UPLOAD_COLOR_COMBINE;
607 }
608 if ( fxMesa->dirty & TDFX_UPLOAD_ALPHA_COMBINE ) {
609 if (TDFX_IS_NAPALM(fxMesa)) {
610 fxMesa->Glide.grAlphaCombineExt(fxMesa->AlphaCombineExt.SourceA,
611 fxMesa->AlphaCombineExt.ModeA,
612 fxMesa->AlphaCombineExt.SourceB,
613 fxMesa->AlphaCombineExt.ModeB,
614 fxMesa->AlphaCombineExt.SourceC,
615 fxMesa->AlphaCombineExt.InvertC,
616 fxMesa->AlphaCombineExt.SourceD,
617 fxMesa->AlphaCombineExt.InvertD,
618 fxMesa->AlphaCombineExt.Shift,
619 fxMesa->AlphaCombineExt.Invert);
620 }
621 else {
622 /* Voodoo 3 */
623 fxMesa->Glide.grAlphaCombine( fxMesa->AlphaCombine.Function,
624 fxMesa->AlphaCombine.Factor,
625 fxMesa->AlphaCombine.Local,
626 fxMesa->AlphaCombine.Other,
627 fxMesa->AlphaCombine.Invert );
628 }
629 fxMesa->dirty &= ~TDFX_UPLOAD_ALPHA_COMBINE;
630 }
631
632 if ( fxMesa->dirty & TDFX_UPLOAD_RENDER_BUFFER ) {
633 fxMesa->Glide.grRenderBuffer( fxMesa->DrawBuffer );
634 fxMesa->dirty &= ~TDFX_UPLOAD_RENDER_BUFFER;
635 }
636
637 if ( fxMesa->dirty & TDFX_UPLOAD_STIPPLE) {
638 fxMesa->Glide.grStipplePattern( fxMesa->Stipple.Pattern );
639 fxMesa->Glide.grStippleMode( fxMesa->Stipple.Mode );
640 fxMesa->dirty &= ~TDFX_UPLOAD_STIPPLE;
641 }
642
643 if ( fxMesa->dirty & TDFX_UPLOAD_ALPHA_TEST ) {
644 fxMesa->Glide.grAlphaTestFunction( fxMesa->Color.AlphaFunc );
645 fxMesa->dirty &= ~TDFX_UPLOAD_ALPHA_TEST;
646 }
647 if ( fxMesa->dirty & TDFX_UPLOAD_ALPHA_REF ) {
648 fxMesa->Glide.grAlphaTestReferenceValue( fxMesa->Color.AlphaRef );
649 fxMesa->dirty &= ~TDFX_UPLOAD_ALPHA_REF;
650 }
651 if ( fxMesa->dirty & TDFX_UPLOAD_BLEND_FUNC ) {
652 if (fxMesa->Glide.grAlphaBlendFunctionExt) {
653 fxMesa->Glide.grAlphaBlendFunctionExt( fxMesa->Color.BlendSrcRGB,
654 fxMesa->Color.BlendDstRGB,
655 fxMesa->Color.BlendEqRGB,
656 fxMesa->Color.BlendSrcA,
657 fxMesa->Color.BlendDstA,
658 fxMesa->Color.BlendEqA );
659 }
660 else {
661 fxMesa->Glide.grAlphaBlendFunction( fxMesa->Color.BlendSrcRGB,
662 fxMesa->Color.BlendDstRGB,
663 fxMesa->Color.BlendSrcA,
664 fxMesa->Color.BlendDstA );
665 }
666 fxMesa->dirty &= ~TDFX_UPLOAD_BLEND_FUNC;
667 }
668
669 if ( fxMesa->dirty & TDFX_UPLOAD_DEPTH_MODE ) {
670 fxMesa->Glide.grDepthBufferMode( fxMesa->Depth.Mode );
671 fxMesa->dirty &= ~TDFX_UPLOAD_DEPTH_MODE;
672 }
673 if ( fxMesa->dirty & TDFX_UPLOAD_DEPTH_BIAS ) {
674 fxMesa->Glide.grDepthBiasLevel( fxMesa->Depth.Bias );
675 fxMesa->dirty &= ~TDFX_UPLOAD_DEPTH_BIAS;
676 }
677 if ( fxMesa->dirty & TDFX_UPLOAD_DEPTH_FUNC ) {
678 fxMesa->Glide.grDepthBufferFunction( fxMesa->Depth.Func );
679 fxMesa->dirty &= ~TDFX_UPLOAD_DEPTH_FUNC;
680 }
681 if ( fxMesa->dirty & TDFX_UPLOAD_DEPTH_MASK ) {
682 fxMesa->Glide.grDepthMask( fxMesa->Depth.Mask );
683 fxMesa->dirty &= ~TDFX_UPLOAD_DEPTH_MASK;
684 }
685
686 if ( fxMesa->dirty & TDFX_UPLOAD_DITHER) {
687 fxMesa->Glide.grDitherMode( fxMesa->Color.Dither );
688 }
689
690 if ( fxMesa->dirty & TDFX_UPLOAD_FOG_MODE ) {
691 fxMesa->Glide.grFogMode( fxMesa->Fog.Mode );
692 fxMesa->dirty &= ~TDFX_UPLOAD_FOG_MODE;
693 }
694 if ( fxMesa->dirty & TDFX_UPLOAD_FOG_COLOR ) {
695 fxMesa->Glide.grFogColorValue( fxMesa->Fog.Color );
696 fxMesa->dirty &= ~TDFX_UPLOAD_FOG_COLOR;
697 }
698 if ( fxMesa->dirty & TDFX_UPLOAD_FOG_TABLE ) {
699 fxMesa->Glide.grFogTable( fxMesa->Fog.Table );
700 fxMesa->dirty &= ~TDFX_UPLOAD_FOG_TABLE;
701 }
702
703 if ( fxMesa->dirty & TDFX_UPLOAD_CULL ) {
704 fxMesa->Glide.grCullMode( fxMesa->CullMode );
705 fxMesa->dirty &= ~TDFX_UPLOAD_CULL;
706 }
707
708 if ( fxMesa->dirty & TDFX_UPLOAD_CLIP ) {
709 tdfxUploadClipping( fxMesa );
710 fxMesa->dirty &= ~TDFX_UPLOAD_CLIP;
711 }
712
713 if ( fxMesa->dirty & TDFX_UPLOAD_COLOR_MASK ) {
714 if ( fxMesa->Glide.grColorMaskExt
715 && fxMesa->glCtx->Visual.redBits == 8) {
716 fxMesa->Glide.grColorMaskExt( fxMesa->Color.ColorMask[RCOMP],
717 fxMesa->Color.ColorMask[GCOMP],
718 fxMesa->Color.ColorMask[BCOMP],
719 fxMesa->Color.ColorMask[ACOMP] );
720 } else {
721 fxMesa->Glide.grColorMask( fxMesa->Color.ColorMask[RCOMP] ||
722 fxMesa->Color.ColorMask[GCOMP] ||
723 fxMesa->Color.ColorMask[BCOMP],
724 /*fxMesa->Color.ColorMask[ACOMP]*/GL_FALSE/*[dBorca] no-no*/ );
725 }
726 fxMesa->dirty &= ~TDFX_UPLOAD_COLOR_MASK;
727 }
728
729 if ( fxMesa->dirty & TDFX_UPLOAD_CONSTANT_COLOR ) {
730 fxMesa->Glide.grConstantColorValue( fxMesa->Color.MonoColor );
731 fxMesa->dirty &= ~TDFX_UPLOAD_CONSTANT_COLOR;
732 }
733
734 if ( fxMesa->dirty & TDFX_UPLOAD_LINE ) {
735 if (fxMesa->glCtx->Line.SmoothFlag && fxMesa->glCtx->Line.Width == 1.0)
736 fxMesa->Glide.grEnable(GR_AA_ORDERED);
737 else
738 fxMesa->Glide.grDisable(GR_AA_ORDERED);
739 fxMesa->dirty &= ~TDFX_UPLOAD_LINE;
740 }
741
742 if ( fxMesa->dirty & TDFX_UPLOAD_STENCIL ) {
743 if (fxMesa->glCtx->Stencil.Enabled) {
744 fxMesa->Glide.grEnable(GR_STENCIL_MODE_EXT);
745 fxMesa->Glide.grStencilOp(fxMesa->Stencil.FailFunc,
746 fxMesa->Stencil.ZFailFunc,
747 fxMesa->Stencil.ZPassFunc);
748 fxMesa->Glide.grStencilFunc(fxMesa->Stencil.Function,
749 fxMesa->Stencil.RefValue,
750 fxMesa->Stencil.ValueMask);
751 fxMesa->Glide.grStencilMask(fxMesa->Stencil.WriteMask);
752 }
753 else {
754 fxMesa->Glide.grDisable(GR_STENCIL_MODE_EXT);
755 }
756 fxMesa->dirty &= ~TDFX_UPLOAD_STENCIL;
757 }
758
759 if ( fxMesa->dirty & TDFX_UPLOAD_VERTEX_LAYOUT ) {
760 fxMesa->Glide.grGlideSetVertexLayout( fxMesa->layout[fxMesa->vertexFormat] );
761 /* [dborca] enable fogcoord */
762 fxMesa->Glide.grVertexLayout(GR_PARAM_FOG_EXT, TDFX_FOG_OFFSET,
763 fxMesa->Fog.Mode == GR_FOG_WITH_TABLE_ON_FOGCOORD_EXT);
764 fxMesa->dirty &= ~TDFX_UPLOAD_VERTEX_LAYOUT;
765 }
766
767 if ( fxMesa->dirty & TDFX_UPLOAD_TEXTURE_ENV ) {
768 uploadTextureEnv(fxMesa);
769 fxMesa->dirty &= ~TDFX_UPLOAD_TEXTURE_ENV;
770 }
771
772 if ( fxMesa->dirty & TDFX_UPLOAD_TEXTURE_PARAMS ) {
773 uploadTextureParams(fxMesa);
774 fxMesa->dirty &= ~TDFX_UPLOAD_TEXTURE_PARAMS;
775 }
776
777 if ( fxMesa->dirty & TDFX_UPLOAD_TEXTURE_PALETTE ) {
778 if (fxMesa->TexPalette.Data) {
779 fxMesa->Glide.grTexDownloadTable(fxMesa->TexPalette.Type, fxMesa->TexPalette.Data);
780 }
781 fxMesa->dirty &= ~TDFX_UPLOAD_TEXTURE_PALETTE;
782 }
783
784 if ( fxMesa->dirty & TDFX_UPLOAD_TEXTURE_SOURCE ) {
785 uploadTextureSource(fxMesa);
786 fxMesa->dirty &= ~TDFX_UPLOAD_TEXTURE_SOURCE;
787 }
788
789 if ( fxMesa->dirty & TDFX_UPLOAD_TEXTURE_IMAGES ) {
790 uploadTextureImages(fxMesa);
791 fxMesa->dirty &= ~TDFX_UPLOAD_TEXTURE_IMAGES;
792 }
793
794 fxMesa->dirty = 0;
795 }
796
797
798
799 void tdfxInitRenderFuncs( struct dd_function_table *functions )
800 {
801 functions->Clear = tdfxClear;
802 functions->Finish = tdfxFinish;
803 functions->Flush = tdfxFlush;
804 }