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