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