bb974279a2ad62544ae92f7e2ef28f11b0b772fc
[mesa.git] / src / mesa / drivers / dri / tdfx / tdfx_texstate.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_texstate.c,v 1.2 2002/02/22 21:45:04 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_state.h"
42 #include "tdfx_tex.h"
43 #include "tdfx_texman.h"
44 #include "tdfx_texstate.h"
45
46
47 /* =============================================================
48 * Texture
49 */
50
51 /*
52 * These macros are used below when handling COMBINE_EXT.
53 */
54 #define TEXENV_OPERAND_INVERTED(operand) \
55 (((operand) == GL_ONE_MINUS_SRC_ALPHA) \
56 || ((operand) == GL_ONE_MINUS_SRC_COLOR))
57 #define TEXENV_OPERAND_ALPHA(operand) \
58 (((operand) == GL_SRC_ALPHA) || ((operand) == GL_ONE_MINUS_SRC_ALPHA))
59 #define TEXENV_SETUP_ARG_A(param, source, operand, iteratedAlpha) \
60 switch (source) { \
61 case GL_TEXTURE: \
62 param = GR_CMBX_LOCAL_TEXTURE_ALPHA; \
63 break; \
64 case GL_CONSTANT_EXT: \
65 param = GR_CMBX_TMU_CALPHA; \
66 break; \
67 case GL_PRIMARY_COLOR_EXT: \
68 param = GR_CMBX_ITALPHA; \
69 break; \
70 case GL_PREVIOUS_EXT: \
71 param = iteratedAlpha; \
72 break; \
73 default: \
74 /* \
75 * This is here just to keep from getting \
76 * compiler warnings. \
77 */ \
78 param = GR_CMBX_ZERO; \
79 break; \
80 }
81
82 #define TEXENV_SETUP_ARG_RGB(param, source, operand, iteratedColor, iteratedAlpha) \
83 if (!TEXENV_OPERAND_ALPHA(operand)) { \
84 switch (source) { \
85 case GL_TEXTURE: \
86 param = GR_CMBX_LOCAL_TEXTURE_RGB; \
87 break; \
88 case GL_CONSTANT_EXT: \
89 param = GR_CMBX_TMU_CCOLOR; \
90 break; \
91 case GL_PRIMARY_COLOR_EXT: \
92 param = GR_CMBX_ITRGB; \
93 break; \
94 case GL_PREVIOUS_EXT: \
95 param = iteratedColor; \
96 break; \
97 default: \
98 /* \
99 * This is here just to keep from getting \
100 * compiler warnings. \
101 */ \
102 param = GR_CMBX_ZERO; \
103 break; \
104 } \
105 } else { \
106 switch (source) { \
107 case GL_TEXTURE: \
108 param = GR_CMBX_LOCAL_TEXTURE_ALPHA; \
109 break; \
110 case GL_CONSTANT_EXT: \
111 param = GR_CMBX_TMU_CALPHA; \
112 break; \
113 case GL_PRIMARY_COLOR_EXT: \
114 param = GR_CMBX_ITALPHA; \
115 break; \
116 case GL_PREVIOUS_EXT: \
117 param = iteratedAlpha; \
118 break; \
119 default: \
120 /* \
121 * This is here just to keep from getting \
122 * compiler warnings. \
123 */ \
124 param = GR_CMBX_ZERO; \
125 break; \
126 } \
127 }
128
129 #define TEXENV_SETUP_MODE_RGB(param, operand) \
130 switch (operand) { \
131 case GL_SRC_COLOR: \
132 case GL_SRC_ALPHA: \
133 param = GR_FUNC_MODE_X; \
134 break; \
135 case GL_ONE_MINUS_SRC_ALPHA: \
136 case GL_ONE_MINUS_SRC_COLOR: \
137 param = GR_FUNC_MODE_ONE_MINUS_X; \
138 break; \
139 default: \
140 param = GR_FUNC_MODE_ZERO; \
141 break; \
142 }
143
144 #define TEXENV_SETUP_MODE_A(param, operand) \
145 switch (operand) { \
146 case GL_SRC_ALPHA: \
147 param = GR_FUNC_MODE_X; \
148 break; \
149 case GL_ONE_MINUS_SRC_ALPHA: \
150 param = GR_FUNC_MODE_ONE_MINUS_X; \
151 break; \
152 default: \
153 param = GR_FUNC_MODE_ZERO; \
154 break; \
155 }
156
157
158
159 /*
160 * Setup a texture environment on Voodoo5.
161 * Return GL_TRUE for success, GL_FALSE for failure.
162 * If we fail, we'll have to use software rendering.
163 */
164 static GLboolean
165 SetupTexEnvNapalm(GLcontext *ctx, GLboolean useIteratedRGBA,
166 const struct gl_texture_unit *texUnit, GLenum baseFormat,
167 struct tdfx_texcombine_ext *env)
168 {
169 tdfxContextPtr fxMesa = TDFX_CONTEXT(ctx);
170 GrTCCUColor_t incomingRGB, incomingAlpha;
171 const GLenum envMode = texUnit->EnvMode;
172
173 if (useIteratedRGBA) {
174 incomingRGB = GR_CMBX_ITRGB;
175 incomingAlpha = GR_CMBX_ITALPHA;
176 }
177 else {
178 incomingRGB = GR_CMBX_OTHER_TEXTURE_RGB;
179 incomingAlpha = GR_CMBX_OTHER_TEXTURE_ALPHA;
180 }
181
182 /* invariant: */
183 env->Color.Shift = 0;
184 env->Color.Invert = FXFALSE;
185 env->Alpha.Shift = 0;
186 env->Alpha.Invert = FXFALSE;
187
188 switch (envMode) {
189 case GL_REPLACE:
190 /* -- Setup RGB combiner */
191 if (baseFormat == GL_ALPHA) {
192 /* Rv = Rf */
193 env->Color.SourceA = incomingRGB;
194 }
195 else {
196 /* Rv = Rt */
197 env->Color.SourceA = GR_CMBX_LOCAL_TEXTURE_RGB;
198 }
199 env->Color.ModeA = GR_FUNC_MODE_X;
200 env->Color.SourceB = GR_CMBX_ZERO;
201 env->Color.ModeB = GR_FUNC_MODE_ZERO;
202 env->Color.SourceC = GR_CMBX_ZERO;
203 env->Color.InvertC = FXTRUE;
204 env->Color.SourceD = GR_CMBX_ZERO;
205 env->Color.InvertD = FXFALSE;
206 /* -- Setup Alpha combiner */
207 if (baseFormat == GL_LUMINANCE || baseFormat == GL_RGB) {
208 /* Av = Af */
209 env->Alpha.SourceD = incomingAlpha;
210 }
211 else {
212 /* Av = At */
213 env->Alpha.SourceD = GR_CMBX_LOCAL_TEXTURE_ALPHA;
214 }
215 env->Alpha.SourceA = GR_CMBX_ITALPHA;
216 env->Alpha.ModeA = GR_FUNC_MODE_ZERO;
217 env->Alpha.SourceB = GR_CMBX_ITALPHA;
218 env->Alpha.ModeB = GR_FUNC_MODE_ZERO;
219 env->Alpha.SourceC = GR_CMBX_ZERO;
220 env->Alpha.InvertC = FXFALSE;
221 env->Alpha.InvertD = FXFALSE;
222 break;
223
224 case GL_MODULATE:
225 /* -- Setup RGB combiner */
226 if (baseFormat == GL_ALPHA) {
227 /* Rv = Rf */
228 env->Color.SourceC = GR_CMBX_ZERO;
229 env->Color.InvertC = FXTRUE;
230 }
231 else {
232 /* Result = Frag * Tex */
233 env->Color.SourceC = GR_CMBX_LOCAL_TEXTURE_RGB;
234 env->Color.InvertC = FXFALSE;
235 }
236 env->Color.SourceA = incomingRGB;
237 env->Color.ModeA = GR_FUNC_MODE_X;
238 env->Color.SourceB = GR_CMBX_ZERO;
239 env->Color.ModeB = GR_FUNC_MODE_ZERO;
240 env->Color.SourceD = GR_CMBX_ZERO;
241 env->Color.InvertD = FXFALSE;
242 /* -- Setup Alpha combiner */
243 if (baseFormat == GL_LUMINANCE || baseFormat == GL_RGB) {
244 /* Av = Af */
245 env->Alpha.SourceA = incomingAlpha;
246 env->Alpha.SourceC = GR_CMBX_ZERO;
247 env->Alpha.InvertC = FXTRUE;
248 }
249 else {
250 /* Av = Af * At */
251 env->Alpha.SourceA = GR_CMBX_LOCAL_TEXTURE_ALPHA;
252 env->Alpha.SourceC = incomingAlpha;
253 env->Alpha.InvertC = FXFALSE;
254 }
255 env->Alpha.ModeA = GR_FUNC_MODE_X;
256 env->Alpha.SourceB = GR_CMBX_ITALPHA;
257 env->Alpha.ModeB = GR_FUNC_MODE_ZERO;
258 env->Alpha.SourceD = GR_CMBX_ZERO;
259 env->Alpha.InvertD = FXFALSE;
260 break;
261
262 case GL_DECAL:
263 /* -- Setup RGB combiner */
264 if (baseFormat == GL_RGB) {
265 /* Rv = Rt */
266 env->Color.SourceB = GR_CMBX_ZERO;
267 env->Color.ModeB = GR_FUNC_MODE_X;
268 env->Color.SourceC = GR_CMBX_ZERO;
269 env->Color.InvertC = FXTRUE;
270 env->Color.SourceD = GR_CMBX_ZERO;
271 env->Color.InvertD = FXFALSE;
272 }
273 else {
274 /* Rv = Rf * (1 - At) + Rt * At */
275 env->Color.SourceB = incomingRGB;
276 env->Color.ModeB = GR_FUNC_MODE_NEGATIVE_X;
277 env->Color.SourceC = GR_CMBX_LOCAL_TEXTURE_ALPHA;
278 env->Color.InvertC = FXFALSE;
279 env->Color.SourceD = GR_CMBX_B;
280 env->Color.InvertD = FXFALSE;
281 }
282 env->Color.SourceA = GR_CMBX_LOCAL_TEXTURE_RGB;
283 env->Color.ModeA = GR_FUNC_MODE_X;
284 /* -- Setup Alpha combiner */
285 /* Av = Af */
286 env->Alpha.SourceA = incomingAlpha;
287 env->Alpha.ModeA = GR_FUNC_MODE_X;
288 env->Alpha.SourceB = GR_CMBX_ITALPHA;
289 env->Alpha.ModeB = GR_FUNC_MODE_ZERO;
290 env->Alpha.SourceC = GR_CMBX_ZERO;
291 env->Alpha.InvertC = FXTRUE;
292 env->Alpha.SourceD = GR_CMBX_ZERO;
293 env->Alpha.InvertD = FXFALSE;
294 break;
295
296 case GL_BLEND:
297 /* -- Setup RGB combiner */
298 if (baseFormat == GL_ALPHA) {
299 /* Rv = Rf */
300 env->Color.SourceA = incomingRGB;
301 env->Color.ModeA = GR_FUNC_MODE_X;
302 env->Color.SourceB = GR_CMBX_ZERO;
303 env->Color.ModeB = GR_FUNC_MODE_ZERO;
304 env->Color.SourceC = GR_CMBX_ZERO;
305 env->Color.InvertC = FXTRUE;
306 env->Color.SourceD = GR_CMBX_ZERO;
307 env->Color.InvertD = FXFALSE;
308 }
309 else {
310 /* Rv = Rf * (1 - Rt) + Rc * Rt */
311 env->Color.SourceA = GR_CMBX_TMU_CCOLOR;
312 env->Color.ModeA = GR_FUNC_MODE_X;
313 env->Color.SourceB = incomingRGB;
314 env->Color.ModeB = GR_FUNC_MODE_NEGATIVE_X;
315 env->Color.SourceC = GR_CMBX_LOCAL_TEXTURE_RGB;
316 env->Color.InvertC = FXFALSE;
317 env->Color.SourceD = GR_CMBX_B;
318 env->Color.InvertD = FXFALSE;
319 }
320 /* -- Setup Alpha combiner */
321 if (baseFormat == GL_LUMINANCE || baseFormat == GL_RGB) {
322 /* Av = Af */
323 env->Alpha.SourceA = incomingAlpha;
324 env->Alpha.ModeA = GR_FUNC_MODE_X;
325 env->Alpha.SourceB = GR_CMBX_ZERO;
326 env->Alpha.ModeB = GR_FUNC_MODE_ZERO;
327 env->Alpha.SourceC = GR_CMBX_ZERO;
328 env->Alpha.InvertC = FXTRUE;
329 env->Alpha.SourceD = GR_CMBX_ZERO;
330 env->Alpha.InvertD = FXFALSE;
331 }
332 else if (baseFormat == GL_INTENSITY) {
333 /* Av = Af * (1 - It) + Ac * It */
334 env->Alpha.SourceA = GR_CMBX_TMU_CALPHA;
335 env->Alpha.ModeA = GR_FUNC_MODE_X;
336 env->Alpha.SourceB = incomingAlpha;
337 env->Alpha.ModeB = GR_FUNC_MODE_NEGATIVE_X;
338 env->Alpha.SourceC = GR_CMBX_LOCAL_TEXTURE_ALPHA;
339 env->Alpha.InvertC = FXFALSE;
340 env->Alpha.SourceD = GR_CMBX_B;
341 env->Alpha.InvertD = FXFALSE;
342 }
343 else {
344 /* Av = Af * At */
345 env->Alpha.SourceA = GR_CMBX_LOCAL_TEXTURE_ALPHA;
346 env->Alpha.ModeA = GR_FUNC_MODE_X;
347 env->Alpha.SourceB = GR_CMBX_ITALPHA;
348 env->Alpha.ModeB = GR_FUNC_MODE_ZERO;
349 env->Alpha.SourceC = incomingAlpha;
350 env->Alpha.InvertC = FXFALSE;
351 env->Alpha.SourceD = GR_CMBX_ZERO;
352 env->Alpha.InvertD = FXFALSE;
353 }
354 /* Also have to set up the tex env constant color */
355 env->EnvColor = PACK_RGBA32(texUnit->EnvColor[0] * 255.0F,
356 texUnit->EnvColor[1] * 255.0F,
357 texUnit->EnvColor[2] * 255.0F,
358 texUnit->EnvColor[3] * 255.0F);
359 break;
360 case GL_ADD:
361 /* -- Setup RGB combiner */
362 if (baseFormat == GL_ALPHA) {
363 /* Rv = Rf */
364 env->Color.SourceB = GR_CMBX_ZERO;
365 env->Color.ModeB = GR_FUNC_MODE_ZERO;
366 }
367 else {
368 /* Rv = Rf + Tt */
369 env->Color.SourceB = GR_CMBX_LOCAL_TEXTURE_RGB;
370 env->Color.ModeB = GR_FUNC_MODE_X;
371 }
372 env->Color.SourceA = incomingRGB;
373 env->Color.ModeA = GR_FUNC_MODE_X;
374 env->Color.SourceC = GR_CMBX_ZERO;
375 env->Color.InvertC = FXTRUE;
376 env->Color.SourceD = GR_CMBX_ZERO;
377 env->Color.InvertD = FXFALSE;
378 /* -- Setup Alpha combiner */
379 if (baseFormat == GL_LUMINANCE || baseFormat == GL_RGB) {
380 /* Av = Af */
381 env->Alpha.SourceA = incomingAlpha;
382 env->Alpha.SourceB = GR_CMBX_ITALPHA;
383 env->Alpha.ModeB = GR_FUNC_MODE_ZERO;
384 env->Alpha.SourceC = GR_CMBX_ZERO;
385 env->Alpha.InvertC = FXTRUE;
386
387 }
388 else if (baseFormat == GL_INTENSITY) {
389 /* Av = Af + It */
390 env->Alpha.SourceA = incomingAlpha;
391 env->Alpha.SourceB = GR_CMBX_LOCAL_TEXTURE_ALPHA;
392 env->Alpha.ModeB = GR_FUNC_MODE_X;
393 env->Alpha.SourceC = GR_CMBX_ZERO;
394 env->Alpha.InvertC = FXTRUE;
395 }
396 else {
397 /* Av = Af * At */
398 env->Alpha.SourceA = GR_CMBX_LOCAL_TEXTURE_ALPHA;
399 env->Alpha.SourceB = GR_CMBX_ITALPHA;
400 env->Alpha.ModeB = GR_FUNC_MODE_ZERO;
401 env->Alpha.SourceC = incomingAlpha;
402 env->Alpha.InvertC = FXFALSE;
403 }
404 env->Alpha.ModeA = GR_FUNC_MODE_X;
405 env->Alpha.SourceD = GR_CMBX_ZERO;
406 env->Alpha.InvertD = FXFALSE;
407 break;
408
409 case GL_COMBINE_EXT:
410 {
411 FxU32 A_RGB, B_RGB, C_RGB, D_RGB;
412 FxU32 Amode_RGB, Bmode_RGB;
413 FxBool Cinv_RGB, Dinv_RGB, Ginv_RGB;
414 FxU32 Shift_RGB;
415 FxU32 A_A, B_A, C_A, D_A;
416 FxU32 Amode_A, Bmode_A;
417 FxBool Cinv_A, Dinv_A, Ginv_A;
418 FxU32 Shift_A;
419
420 /*
421 *
422 * In the formulas below, we write:
423 * o "1(x)" for the identity function applied to x,
424 * so 1(x) = x.
425 * o "0(x)" for the constant function 0, so
426 * 0(x) = 0 for all values of x.
427 *
428 * Calculate the color combination.
429 */
430 Shift_RGB = texUnit->Combine.ScaleShiftRGB;
431 Shift_A = texUnit->Combine.ScaleShiftA;
432 switch (texUnit->Combine.ModeRGB) {
433 case GL_REPLACE:
434 /*
435 * The formula is: Arg0
436 * We implement this by the formula:
437 * (Arg0 + 0(0))*(1-0) + 0
438 */
439 TEXENV_SETUP_ARG_RGB(A_RGB,
440 texUnit->Combine.SourceRGB[0],
441 texUnit->Combine.OperandRGB[0],
442 incomingRGB, incomingAlpha);
443 TEXENV_SETUP_MODE_RGB(Amode_RGB,
444 texUnit->Combine.OperandRGB[0]);
445 B_RGB = C_RGB = D_RGB = GR_CMBX_ZERO;
446 Bmode_RGB = GR_FUNC_MODE_ZERO;
447 Cinv_RGB = FXTRUE;
448 Dinv_RGB = Ginv_RGB = FXFALSE;
449 break;
450 case GL_MODULATE:
451 /*
452 * The formula is: Arg0 * Arg1
453 *
454 * We implement this by the formula
455 * (Arg0 + 0(0)) * Arg1 + 0(0)
456 */
457 TEXENV_SETUP_ARG_RGB(A_RGB,
458 texUnit->Combine.SourceRGB[0],
459 texUnit->Combine.OperandRGB[0],
460 incomingRGB, incomingAlpha);
461 TEXENV_SETUP_MODE_RGB(Amode_RGB,
462 texUnit->Combine.OperandRGB[0]);
463 B_RGB = GR_CMBX_ZERO;
464 Bmode_RGB = GR_CMBX_ZERO;
465 TEXENV_SETUP_ARG_RGB(C_RGB,
466 texUnit->Combine.SourceRGB[1],
467 texUnit->Combine.OperandRGB[1],
468 incomingRGB, incomingAlpha);
469 Cinv_RGB = TEXENV_OPERAND_INVERTED
470 (texUnit->Combine.OperandRGB[1]);
471 D_RGB = GR_CMBX_ZERO;
472 Dinv_RGB = Ginv_RGB = FXFALSE;
473 break;
474 case GL_ADD:
475 /*
476 * The formula is Arg0 + Arg1
477 */
478 TEXENV_SETUP_ARG_RGB(A_RGB,
479 texUnit->Combine.SourceRGB[0],
480 texUnit->Combine.OperandRGB[0],
481 incomingRGB, incomingAlpha);
482 TEXENV_SETUP_MODE_RGB(Amode_RGB,
483 texUnit->Combine.OperandRGB[0]);
484 TEXENV_SETUP_ARG_RGB(B_RGB,
485 texUnit->Combine.SourceRGB[1],
486 texUnit->Combine.OperandRGB[1],
487 incomingRGB, incomingAlpha);
488 TEXENV_SETUP_MODE_RGB(Bmode_RGB,
489 texUnit->Combine.OperandRGB[1]);
490 C_RGB = D_RGB = GR_CMBX_ZERO;
491 Cinv_RGB = FXTRUE;
492 Dinv_RGB = Ginv_RGB = FXFALSE;
493 break;
494 case GL_ADD_SIGNED_EXT:
495 /*
496 * The formula is: Arg0 + Arg1 - 0.5.
497 * We compute this by calculating:
498 * (Arg0 - 1/2) + Arg1 if op0 is SRC_{COLOR,ALPHA}
499 * Arg0 + (Arg1 - 1/2) if op1 is SRC_{COLOR,ALPHA}
500 * If both op0 and op1 are ONE_MINUS_SRC_{COLOR,ALPHA}
501 * we cannot implement the formula properly.
502 */
503 TEXENV_SETUP_ARG_RGB(A_RGB,
504 texUnit->Combine.SourceRGB[0],
505 texUnit->Combine.OperandRGB[0],
506 incomingRGB, incomingAlpha);
507 TEXENV_SETUP_ARG_RGB(B_RGB,
508 texUnit->Combine.SourceRGB[1],
509 texUnit->Combine.OperandRGB[1],
510 incomingRGB, incomingAlpha);
511 if (!TEXENV_OPERAND_INVERTED(texUnit->Combine.OperandRGB[0])) {
512 /*
513 * A is not inverted. So, choose it.
514 */
515 Amode_RGB = GR_FUNC_MODE_X_MINUS_HALF;
516 if (!TEXENV_OPERAND_INVERTED
517 (texUnit->Combine.OperandRGB[1])) {
518 Bmode_RGB = GR_FUNC_MODE_X;
519 }
520 else {
521 Bmode_RGB = GR_FUNC_MODE_ONE_MINUS_X;
522 }
523 }
524 else {
525 /*
526 * A is inverted, so try to subtract 1/2
527 * from B.
528 */
529 Amode_RGB = GR_FUNC_MODE_ONE_MINUS_X;
530 if (!TEXENV_OPERAND_INVERTED
531 (texUnit->Combine.OperandRGB[1])) {
532 Bmode_RGB = GR_FUNC_MODE_X_MINUS_HALF;
533 }
534 else {
535 /*
536 * Both are inverted. This is the case
537 * we cannot handle properly. We just
538 * choose to not add the - 1/2.
539 */
540 Bmode_RGB = GR_FUNC_MODE_ONE_MINUS_X;
541 return GL_FALSE;
542 }
543 }
544 C_RGB = D_RGB = GR_CMBX_ZERO;
545 Cinv_RGB = FXTRUE;
546 Dinv_RGB = Ginv_RGB = FXFALSE;
547 break;
548 case GL_INTERPOLATE_EXT:
549 /*
550 * The formula is: Arg0 * Arg2 + Arg1 * (1 - Arg2).
551 * We compute this by the formula:
552 * (Arg0 - Arg1) * Arg2 + Arg1
553 * == Arg0 * Arg2 - Arg1 * Arg2 + Arg1
554 * == Arg0 * Arg2 + Arg1 * (1 - Arg2)
555 * However, if both Arg1 is ONE_MINUS_X, the HW does
556 * not support it properly.
557 */
558 TEXENV_SETUP_ARG_RGB(A_RGB,
559 texUnit->Combine.SourceRGB[0],
560 texUnit->Combine.OperandRGB[0],
561 incomingRGB, incomingAlpha);
562 TEXENV_SETUP_MODE_RGB(Amode_RGB,
563 texUnit->Combine.OperandRGB[0]);
564 TEXENV_SETUP_ARG_RGB(B_RGB,
565 texUnit->Combine.SourceRGB[1],
566 texUnit->Combine.OperandRGB[1],
567 incomingRGB, incomingAlpha);
568 if (TEXENV_OPERAND_INVERTED(texUnit->Combine.OperandRGB[1])) {
569 /*
570 * This case is wrong.
571 */
572 Bmode_RGB = GR_FUNC_MODE_NEGATIVE_X;
573 return GL_FALSE;
574 }
575 else {
576 Bmode_RGB = GR_FUNC_MODE_NEGATIVE_X;
577 }
578 /*
579 * The Source/Operand for the C value must
580 * specify some kind of alpha value.
581 */
582 TEXENV_SETUP_ARG_A(C_RGB,
583 texUnit->Combine.SourceRGB[2],
584 texUnit->Combine.OperandRGB[2],
585 incomingAlpha);
586 Cinv_RGB = FXFALSE;
587 D_RGB = GR_CMBX_B;
588 Dinv_RGB = Ginv_RGB = FXFALSE;
589 break;
590 default:
591 /*
592 * This is here mostly to keep from getting
593 * a compiler warning about these not being set.
594 * However, this should set all the texture values
595 * to zero.
596 */
597 A_RGB = B_RGB = C_RGB = D_RGB = GR_CMBX_ZERO;
598 Amode_RGB = Bmode_RGB = GR_FUNC_MODE_X;
599 Cinv_RGB = Dinv_RGB = Ginv_RGB = FXFALSE;
600 break;
601 }
602 /*
603 * Calculate the alpha combination.
604 */
605 switch (texUnit->Combine.ModeA) {
606 case GL_REPLACE:
607 /*
608 * The formula is: Arg0
609 * We implement this by the formula:
610 * (Arg0 + 0(0))*(1-0) + 0
611 */
612 TEXENV_SETUP_ARG_A(A_A,
613 texUnit->Combine.SourceA[0],
614 texUnit->Combine.OperandA[0],
615 incomingAlpha);
616 TEXENV_SETUP_MODE_A(Amode_A,
617 texUnit->Combine.OperandA[0]);
618 B_A = GR_CMBX_ITALPHA;
619 Bmode_A = GR_FUNC_MODE_ZERO;
620 C_A = D_A = GR_CMBX_ZERO;
621 Cinv_A = FXTRUE;
622 Dinv_A = Ginv_A = FXFALSE;
623 break;
624 case GL_MODULATE:
625 /*
626 * The formula is: Arg0 * Arg1
627 *
628 * We implement this by the formula
629 * (Arg0 + 0(0)) * Arg1 + 0(0)
630 */
631 TEXENV_SETUP_ARG_A(A_A,
632 texUnit->Combine.SourceA[0],
633 texUnit->Combine.OperandA[0],
634 incomingAlpha);
635 TEXENV_SETUP_MODE_A(Amode_A,
636 texUnit->Combine.OperandA[0]);
637 B_A = GR_CMBX_ZERO;
638 Bmode_A = GR_CMBX_ZERO;
639 TEXENV_SETUP_ARG_A(C_A,
640 texUnit->Combine.SourceA[1],
641 texUnit->Combine.OperandA[1],
642 incomingAlpha);
643 Cinv_A = TEXENV_OPERAND_INVERTED
644 (texUnit->Combine.OperandA[1]);
645 D_A = GR_CMBX_ZERO;
646 Dinv_A = Ginv_A = FXFALSE;
647 break;
648 case GL_ADD:
649 /*
650 * The formula is Arg0 + Arg1
651 */
652 TEXENV_SETUP_ARG_A(A_A,
653 texUnit->Combine.SourceA[0],
654 texUnit->Combine.OperandA[0],
655 incomingAlpha);
656 TEXENV_SETUP_MODE_A(Amode_A,
657 texUnit->Combine.OperandA[0]);
658 TEXENV_SETUP_ARG_A(B_A,
659 texUnit->Combine.SourceA[1],
660 texUnit->Combine.OperandA[1],
661 incomingAlpha);
662 TEXENV_SETUP_MODE_A(Bmode_A,
663 texUnit->Combine.OperandA[1]);
664 C_A = D_A = GR_CMBX_ZERO;
665 Cinv_A = FXTRUE;
666 Dinv_A = Ginv_A = FXFALSE;
667 break;
668 case GL_ADD_SIGNED_EXT:
669 /*
670 * The formula is: Arg0 + Arg1 - 0.5.
671 * We compute this by calculating:
672 * (Arg0 - 1/2) + Arg1 if op0 is SRC_{COLOR,ALPHA}
673 * Arg0 + (Arg1 - 1/2) if op1 is SRC_{COLOR,ALPHA}
674 * If both op0 and op1 are ONE_MINUS_SRC_{COLOR,ALPHA}
675 * we cannot implement the formula properly.
676 */
677 TEXENV_SETUP_ARG_A(A_A,
678 texUnit->Combine.SourceA[0],
679 texUnit->Combine.OperandA[0],
680 incomingAlpha);
681 TEXENV_SETUP_ARG_A(B_A,
682 texUnit->Combine.SourceA[1],
683 texUnit->Combine.OperandA[1],
684 incomingAlpha);
685 if (!TEXENV_OPERAND_INVERTED(texUnit->Combine.OperandA[0])) {
686 /*
687 * A is not inverted. So, choose it.
688 */
689 Amode_A = GR_FUNC_MODE_X_MINUS_HALF;
690 if (!TEXENV_OPERAND_INVERTED
691 (texUnit->Combine.OperandA[1])) {
692 Bmode_A = GR_FUNC_MODE_X;
693 } else {
694 Bmode_A = GR_FUNC_MODE_ONE_MINUS_X;
695 }
696 } else {
697 /*
698 * A is inverted, so try to subtract 1/2
699 * from B.
700 */
701 Amode_A = GR_FUNC_MODE_ONE_MINUS_X;
702 if (!TEXENV_OPERAND_INVERTED
703 (texUnit->Combine.OperandA[1])) {
704 Bmode_A = GR_FUNC_MODE_X_MINUS_HALF;
705 } else {
706 /*
707 * Both are inverted. This is the case
708 * we cannot handle properly. We just
709 * choose to not add the - 1/2.
710 */
711 Bmode_A = GR_FUNC_MODE_ONE_MINUS_X;
712 return GL_FALSE;
713 }
714 }
715 C_A = D_A = GR_CMBX_ZERO;
716 Cinv_A = FXTRUE;
717 Dinv_A = Ginv_A = FXFALSE;
718 break;
719 case GL_INTERPOLATE_EXT:
720 /*
721 * The formula is: Arg0 * Arg2 + Arg1 * (1 - Arg2).
722 * We compute this by the formula:
723 * (Arg0 - Arg1) * Arg2 + Arg1
724 * == Arg0 * Arg2 - Arg1 * Arg2 + Arg1
725 * == Arg0 * Arg2 + Arg1 * (1 - Arg2)
726 * However, if both Arg1 is ONE_MINUS_X, the HW does
727 * not support it properly.
728 */
729 TEXENV_SETUP_ARG_A(A_A,
730 texUnit->Combine.SourceA[0],
731 texUnit->Combine.OperandA[0],
732 incomingAlpha);
733 TEXENV_SETUP_MODE_A(Amode_A,
734 texUnit->Combine.OperandA[0]);
735 TEXENV_SETUP_ARG_A(B_A,
736 texUnit->Combine.SourceA[1],
737 texUnit->Combine.OperandA[1],
738 incomingAlpha);
739 if (!TEXENV_OPERAND_INVERTED(texUnit->Combine.OperandA[1])) {
740 Bmode_A = GR_FUNC_MODE_NEGATIVE_X;
741 }
742 else {
743 /*
744 * This case is wrong.
745 */
746 Bmode_A = GR_FUNC_MODE_NEGATIVE_X;
747 return GL_FALSE;
748 }
749 /*
750 * The Source/Operand for the C value must
751 * specify some kind of alpha value.
752 */
753 TEXENV_SETUP_ARG_A(C_A,
754 texUnit->Combine.SourceA[2],
755 texUnit->Combine.OperandA[2],
756 incomingAlpha);
757 Cinv_A = FXFALSE;
758 D_A = GR_CMBX_B;
759 Dinv_A = Ginv_A = FXFALSE;
760 break;
761 default:
762 /*
763 * This is here mostly to keep from getting
764 * a compiler warning about these not being set.
765 * However, this should set all the alpha values
766 * to one.
767 */
768 A_A = B_A = C_A = D_A = GR_CMBX_ZERO;
769 Amode_A = Bmode_A = GR_FUNC_MODE_X;
770 Cinv_A = Dinv_A = FXFALSE;
771 Ginv_A = FXTRUE;
772 break;
773 }
774 /*
775 * Save the parameters.
776 */
777 env->Color.SourceA = A_RGB;
778 env->Color.ModeA = Amode_RGB;
779 env->Color.SourceB = B_RGB;
780 env->Color.ModeB = Bmode_RGB;
781 env->Color.SourceC = C_RGB;
782 env->Color.InvertC = Cinv_RGB;
783 env->Color.SourceD = D_RGB;
784 env->Color.InvertD = Dinv_RGB;
785 env->Color.Shift = Shift_RGB;
786 env->Color.Invert = Ginv_RGB;
787 env->Alpha.SourceA = A_A;
788 env->Alpha.ModeA = Amode_A;
789 env->Alpha.SourceB = B_A;
790 env->Alpha.ModeB = Bmode_A;
791 env->Alpha.SourceC = C_A;
792 env->Alpha.InvertC = Cinv_A;
793 env->Alpha.SourceD = D_A;
794 env->Alpha.InvertD = Dinv_A;
795 env->Alpha.Shift = Shift_A;
796 env->Alpha.Invert = Ginv_A;
797 env->EnvColor = PACK_RGBA32(texUnit->EnvColor[0] * 255.0F,
798 texUnit->EnvColor[1] * 255.0F,
799 texUnit->EnvColor[2] * 255.0F,
800 texUnit->EnvColor[3] * 255.0F);
801 }
802 break;
803
804 default:
805 _mesa_problem(ctx, "%s: Bad envMode", __FUNCTION__);
806 }
807
808 fxMesa->dirty |= TDFX_UPLOAD_TEXTURE_ENV;
809
810 fxMesa->ColorCombineExt.SourceA = GR_CMBX_TEXTURE_RGB;
811 fxMesa->ColorCombineExt.ModeA = GR_FUNC_MODE_X,
812 fxMesa->ColorCombineExt.SourceB = GR_CMBX_ZERO;
813 fxMesa->ColorCombineExt.ModeB = GR_FUNC_MODE_X;
814 fxMesa->ColorCombineExt.SourceC = GR_CMBX_ZERO;
815 fxMesa->ColorCombineExt.InvertC = FXTRUE;
816 fxMesa->ColorCombineExt.SourceD = GR_CMBX_ZERO;
817 fxMesa->ColorCombineExt.InvertD = FXFALSE;
818 fxMesa->ColorCombineExt.Shift = 0;
819 fxMesa->ColorCombineExt.Invert = FXFALSE;
820 fxMesa->dirty |= TDFX_UPLOAD_COLOR_COMBINE;
821 fxMesa->AlphaCombineExt.SourceA = GR_CMBX_TEXTURE_ALPHA;
822 fxMesa->AlphaCombineExt.ModeA = GR_FUNC_MODE_X;
823 fxMesa->AlphaCombineExt.SourceB = GR_CMBX_ZERO;
824 fxMesa->AlphaCombineExt.ModeB = GR_FUNC_MODE_X;
825 fxMesa->AlphaCombineExt.SourceC = GR_CMBX_ZERO;
826 fxMesa->AlphaCombineExt.InvertC = FXTRUE;
827 fxMesa->AlphaCombineExt.SourceD = GR_CMBX_ZERO;
828 fxMesa->AlphaCombineExt.InvertD = FXFALSE;
829 fxMesa->AlphaCombineExt.Shift = 0;
830 fxMesa->AlphaCombineExt.Invert = FXFALSE;
831 fxMesa->dirty |= TDFX_UPLOAD_ALPHA_COMBINE;
832 return GL_TRUE; /* success */
833 }
834
835
836
837 /*
838 * Setup the Voodoo3 texture environment for a single texture unit.
839 * Return GL_TRUE for success, GL_FALSE for failure.
840 * If failure, we'll use software rendering.
841 */
842 static GLboolean
843 SetupSingleTexEnvVoodoo3(GLcontext *ctx, int unit,
844 GLenum envMode, GLenum baseFormat)
845 {
846 tdfxContextPtr fxMesa = TDFX_CONTEXT(ctx);
847 GrCombineLocal_t localc, locala;
848 struct tdfx_combine alphaComb, colorComb;
849
850 if (1 /*iteratedRGBA*/)
851 localc = locala = GR_COMBINE_LOCAL_ITERATED;
852 else
853 localc = locala = GR_COMBINE_LOCAL_CONSTANT;
854
855 switch (envMode) {
856 case GL_DECAL:
857 alphaComb.Function = GR_COMBINE_FUNCTION_LOCAL;
858 alphaComb.Factor = GR_COMBINE_FACTOR_NONE;
859 alphaComb.Local = locala;
860 alphaComb.Other = GR_COMBINE_OTHER_NONE;
861 alphaComb.Invert = FXFALSE;
862 colorComb.Function = GR_COMBINE_FUNCTION_BLEND;
863 colorComb.Factor = GR_COMBINE_FACTOR_TEXTURE_ALPHA;
864 colorComb.Local = localc;
865 colorComb.Other = GR_COMBINE_OTHER_TEXTURE;
866 colorComb.Invert = FXFALSE;
867 break;
868 case GL_MODULATE:
869 alphaComb.Function = GR_COMBINE_FUNCTION_SCALE_OTHER;
870 alphaComb.Factor = GR_COMBINE_FACTOR_LOCAL;
871 alphaComb.Local = locala;
872 alphaComb.Other = GR_COMBINE_OTHER_TEXTURE;
873 alphaComb.Invert = FXFALSE;
874 if (baseFormat == GL_ALPHA) {
875 colorComb.Function = GR_COMBINE_FUNCTION_LOCAL;
876 colorComb.Factor = GR_COMBINE_FACTOR_NONE;
877 colorComb.Local = localc;
878 colorComb.Other = GR_COMBINE_OTHER_NONE;
879 colorComb.Invert = FXFALSE;
880 }
881 else {
882 colorComb.Function = GR_COMBINE_FUNCTION_SCALE_OTHER;
883 colorComb.Factor = GR_COMBINE_FACTOR_LOCAL;
884 colorComb.Local = localc;
885 colorComb.Other = GR_COMBINE_OTHER_TEXTURE;
886 colorComb.Invert = FXFALSE;
887 }
888 break;
889
890 case GL_BLEND:
891 /*
892 * XXX we can't do real GL_BLEND mode. These settings assume that
893 * the TexEnv color is black and incoming fragment color is white.
894 */
895 if (baseFormat == GL_LUMINANCE || baseFormat == GL_RGB) {
896 /* Av = Af */
897 alphaComb.Function = GR_COMBINE_FUNCTION_LOCAL;
898 alphaComb.Factor = GR_COMBINE_FACTOR_NONE;
899 alphaComb.Local = locala;
900 alphaComb.Other = GR_COMBINE_OTHER_NONE;
901 alphaComb.Invert = FXFALSE;
902 }
903 else if (baseFormat == GL_INTENSITY) {
904 /* Av = Af * (1 - It) + Ac * It */
905 alphaComb.Function = GR_COMBINE_FUNCTION_BLEND;
906 alphaComb.Factor = GR_COMBINE_FACTOR_TEXTURE_ALPHA;
907 alphaComb.Local = locala;
908 alphaComb.Other = GR_COMBINE_OTHER_CONSTANT;
909 alphaComb.Invert = FXFALSE;
910 }
911 else {
912 /* Av = Af * At */
913 alphaComb.Function = GR_COMBINE_FUNCTION_SCALE_OTHER;
914 alphaComb.Factor = GR_COMBINE_FACTOR_LOCAL;
915 alphaComb.Local = locala;
916 alphaComb.Other = GR_COMBINE_OTHER_TEXTURE;
917 alphaComb.Invert = FXFALSE;
918 }
919 if (baseFormat == GL_ALPHA) {
920 colorComb.Function = GR_COMBINE_FUNCTION_LOCAL;
921 colorComb.Factor = GR_COMBINE_FACTOR_NONE;
922 colorComb.Local = localc;
923 colorComb.Other = GR_COMBINE_OTHER_NONE;
924 colorComb.Invert = FXFALSE;
925 }
926 else {
927 colorComb.Function = GR_COMBINE_FUNCTION_BLEND;
928 colorComb.Factor = GR_COMBINE_FACTOR_TEXTURE_RGB;
929 colorComb.Local = localc;
930 colorComb.Other = GR_COMBINE_OTHER_CONSTANT;
931 colorComb.Invert = FXTRUE;
932 }
933 fxMesa->Color.MonoColor = PACK_RGBA32(
934 ctx->Texture.Unit[unit].EnvColor[0] * 255.0f,
935 ctx->Texture.Unit[unit].EnvColor[1] * 255.0f,
936 ctx->Texture.Unit[unit].EnvColor[2] * 255.0f,
937 ctx->Texture.Unit[unit].EnvColor[3] * 255.0f);
938 fxMesa->dirty |= TDFX_UPLOAD_CONSTANT_COLOR;
939 break;
940
941 case GL_REPLACE:
942 if ((baseFormat == GL_RGB) || (baseFormat == GL_LUMINANCE)) {
943 alphaComb.Function = GR_COMBINE_FUNCTION_LOCAL;
944 alphaComb.Factor = GR_COMBINE_FACTOR_NONE;
945 alphaComb.Local = locala;
946 alphaComb.Other = GR_COMBINE_OTHER_NONE;
947 alphaComb.Invert = FXFALSE;
948 }
949 else {
950 alphaComb.Function = GR_COMBINE_FUNCTION_SCALE_OTHER;
951 alphaComb.Factor = GR_COMBINE_FACTOR_ONE;
952 alphaComb.Local = locala;
953 alphaComb.Other = GR_COMBINE_OTHER_TEXTURE;
954 alphaComb.Invert = FXFALSE;
955 }
956 if (baseFormat == GL_ALPHA) {
957 colorComb.Function = GR_COMBINE_FUNCTION_LOCAL;
958 colorComb.Factor = GR_COMBINE_FACTOR_NONE;
959 colorComb.Local = localc;
960 colorComb.Other = GR_COMBINE_OTHER_NONE;
961 colorComb.Invert = FXFALSE;
962 }
963 else {
964 colorComb.Function = GR_COMBINE_FUNCTION_SCALE_OTHER;
965 colorComb.Factor = GR_COMBINE_FACTOR_ONE;
966 colorComb.Local = localc;
967 colorComb.Other = GR_COMBINE_OTHER_TEXTURE;
968 colorComb.Invert = FXFALSE;
969 }
970 break;
971
972 case GL_ADD:
973 if (baseFormat == GL_ALPHA ||
974 baseFormat == GL_LUMINANCE_ALPHA ||
975 baseFormat == GL_RGBA) {
976 /* product of texel and fragment alpha */
977 alphaComb.Function = GR_COMBINE_FUNCTION_SCALE_OTHER;
978 alphaComb.Factor = GR_COMBINE_FACTOR_LOCAL;
979 alphaComb.Local = locala;
980 alphaComb.Other = GR_COMBINE_OTHER_TEXTURE;
981 alphaComb.Invert = FXFALSE;
982 }
983 else if (baseFormat == GL_LUMINANCE || baseFormat == GL_RGB) {
984 /* fragment alpha is unchanged */
985 alphaComb.Function = GR_COMBINE_FUNCTION_LOCAL;
986 alphaComb.Factor = GR_COMBINE_FACTOR_NONE;
987 alphaComb.Local = locala;
988 alphaComb.Other = GR_COMBINE_OTHER_NONE;
989 alphaComb.Invert = FXFALSE;
990 }
991 else {
992 ASSERT(baseFormat == GL_INTENSITY);
993 /* sum of texel and fragment alpha */
994 alphaComb.Function = GR_COMBINE_FUNCTION_SCALE_OTHER_ADD_LOCAL,
995 alphaComb.Factor = GR_COMBINE_FACTOR_ONE;
996 alphaComb.Local = locala;
997 alphaComb.Other = GR_COMBINE_OTHER_TEXTURE;
998 alphaComb.Invert = FXFALSE;
999 }
1000 if (baseFormat == GL_ALPHA) {
1001 /* rgb unchanged */
1002 colorComb.Function = GR_COMBINE_FUNCTION_LOCAL;
1003 colorComb.Factor = GR_COMBINE_FACTOR_NONE;
1004 colorComb.Local = localc;
1005 colorComb.Other = GR_COMBINE_OTHER_NONE;
1006 colorComb.Invert = FXFALSE;
1007 }
1008 else {
1009 /* sum of texel and fragment rgb */
1010 colorComb.Function = GR_COMBINE_FUNCTION_SCALE_OTHER_ADD_LOCAL,
1011 colorComb.Factor = GR_COMBINE_FACTOR_ONE;
1012 colorComb.Local = localc;
1013 colorComb.Other = GR_COMBINE_OTHER_TEXTURE;
1014 colorComb.Invert = FXFALSE;
1015 }
1016 break;
1017
1018 default:
1019 _mesa_problem(ctx, "bad texture env mode in %s", __FUNCTION__);
1020 }
1021
1022 if (colorComb.Function != fxMesa->ColorCombine.Function ||
1023 colorComb.Factor != fxMesa->ColorCombine.Factor ||
1024 colorComb.Local != fxMesa->ColorCombine.Local ||
1025 colorComb.Other != fxMesa->ColorCombine.Other ||
1026 colorComb.Invert != fxMesa->ColorCombine.Invert) {
1027 fxMesa->ColorCombine = colorComb;
1028 fxMesa->dirty |= TDFX_UPLOAD_COLOR_COMBINE;
1029 }
1030
1031 if (alphaComb.Function != fxMesa->AlphaCombine.Function ||
1032 alphaComb.Factor != fxMesa->AlphaCombine.Factor ||
1033 alphaComb.Local != fxMesa->AlphaCombine.Local ||
1034 alphaComb.Other != fxMesa->AlphaCombine.Other ||
1035 alphaComb.Invert != fxMesa->AlphaCombine.Invert) {
1036 fxMesa->AlphaCombine = alphaComb;
1037 fxMesa->dirty |= TDFX_UPLOAD_ALPHA_COMBINE;
1038 }
1039 return GL_TRUE;
1040 }
1041
1042
1043 /*
1044 * Setup the Voodoo3 texture environment for dual texture units.
1045 * Return GL_TRUE for success, GL_FALSE for failure.
1046 * If failure, we'll use software rendering.
1047 */
1048 static GLboolean
1049 SetupDoubleTexEnvVoodoo3(GLcontext *ctx, int tmu0,
1050 GLenum envMode0, GLenum baseFormat0,
1051 GLenum envMode1, GLenum baseFormat1)
1052 {
1053 tdfxContextPtr fxMesa = TDFX_CONTEXT(ctx);
1054 const GrCombineLocal_t locala = GR_COMBINE_LOCAL_ITERATED;
1055 const GrCombineLocal_t localc = GR_COMBINE_LOCAL_ITERATED;
1056 const int tmu1 = 1 - tmu0;
1057
1058 if (envMode0 == GL_MODULATE && envMode1 == GL_MODULATE) {
1059 GLboolean isalpha[TDFX_NUM_TMU];
1060
1061 isalpha[tmu0] = (baseFormat0 == GL_ALPHA);
1062 isalpha[tmu1] = (baseFormat1 == GL_ALPHA);
1063
1064 if (isalpha[TDFX_TMU1]) {
1065 fxMesa->TexCombine[1].FunctionRGB = GR_COMBINE_FUNCTION_ZERO;
1066 fxMesa->TexCombine[1].FactorRGB = GR_COMBINE_FACTOR_NONE;
1067 fxMesa->TexCombine[1].FunctionAlpha = GR_COMBINE_FUNCTION_LOCAL;
1068 fxMesa->TexCombine[1].FactorAlpha = GR_COMBINE_FACTOR_NONE;
1069 fxMesa->TexCombine[1].InvertRGB = FXTRUE;
1070 fxMesa->TexCombine[1].InvertAlpha = FXFALSE;
1071 }
1072 else {
1073 fxMesa->TexCombine[1].FunctionRGB = GR_COMBINE_FUNCTION_LOCAL;
1074 fxMesa->TexCombine[1].FactorRGB = GR_COMBINE_FACTOR_NONE;
1075 fxMesa->TexCombine[1].FunctionAlpha = GR_COMBINE_FUNCTION_LOCAL;
1076 fxMesa->TexCombine[1].FactorAlpha = GR_COMBINE_FACTOR_NONE;
1077 fxMesa->TexCombine[1].InvertRGB = FXFALSE;
1078 fxMesa->TexCombine[1].InvertAlpha = FXFALSE;
1079 }
1080 if (isalpha[TDFX_TMU0]) {
1081 fxMesa->TexCombine[0].FunctionRGB = GR_COMBINE_FUNCTION_BLEND_OTHER;
1082 fxMesa->TexCombine[0].FactorRGB = GR_COMBINE_FACTOR_ONE;
1083 fxMesa->TexCombine[0].FunctionAlpha = GR_COMBINE_FUNCTION_BLEND_OTHER;
1084 fxMesa->TexCombine[0].FactorAlpha = GR_COMBINE_FACTOR_LOCAL;
1085 fxMesa->TexCombine[0].InvertRGB = FXFALSE;
1086 fxMesa->TexCombine[0].InvertAlpha = FXFALSE;
1087 }
1088 else {
1089 fxMesa->TexCombine[0].FunctionRGB = GR_COMBINE_FUNCTION_BLEND_OTHER;
1090 fxMesa->TexCombine[0].FactorRGB = GR_COMBINE_FACTOR_LOCAL;
1091 fxMesa->TexCombine[0].FunctionAlpha = GR_COMBINE_FUNCTION_BLEND_OTHER;
1092 fxMesa->TexCombine[0].FactorAlpha = GR_COMBINE_FACTOR_LOCAL;
1093 fxMesa->TexCombine[0].InvertRGB = FXFALSE;
1094 fxMesa->TexCombine[0].InvertAlpha = FXFALSE;
1095 }
1096 fxMesa->ColorCombine.Function = GR_COMBINE_FUNCTION_SCALE_OTHER;
1097 fxMesa->ColorCombine.Factor = GR_COMBINE_FACTOR_LOCAL;
1098 fxMesa->ColorCombine.Local = localc;
1099 fxMesa->ColorCombine.Other = GR_COMBINE_OTHER_TEXTURE;
1100 fxMesa->ColorCombine.Invert = FXFALSE;
1101 fxMesa->AlphaCombine.Function = GR_COMBINE_FUNCTION_SCALE_OTHER;
1102 fxMesa->AlphaCombine.Factor = GR_COMBINE_FACTOR_LOCAL;
1103 fxMesa->AlphaCombine.Local = locala;
1104 fxMesa->AlphaCombine.Other = GR_COMBINE_OTHER_TEXTURE;
1105 fxMesa->AlphaCombine.Invert = FXFALSE;
1106 }
1107 else if (envMode0 == GL_REPLACE && envMode1 == GL_BLEND) { /* Quake */
1108 if (tmu0 == TDFX_TMU1) {
1109 fxMesa->TexCombine[1].FunctionRGB = GR_COMBINE_FUNCTION_LOCAL;
1110 fxMesa->TexCombine[1].FactorRGB = GR_COMBINE_FACTOR_NONE;
1111 fxMesa->TexCombine[1].FunctionAlpha = GR_COMBINE_FUNCTION_LOCAL;
1112 fxMesa->TexCombine[1].FactorAlpha = GR_COMBINE_FACTOR_NONE;
1113 fxMesa->TexCombine[1].InvertRGB = FXTRUE;
1114 fxMesa->TexCombine[1].InvertAlpha = FXFALSE;
1115 fxMesa->TexCombine[0].FunctionRGB = GR_COMBINE_FUNCTION_BLEND_OTHER;
1116 fxMesa->TexCombine[0].FactorRGB = GR_COMBINE_FACTOR_LOCAL;
1117 fxMesa->TexCombine[0].FunctionAlpha = GR_COMBINE_FUNCTION_BLEND_OTHER;
1118 fxMesa->TexCombine[0].FactorAlpha = GR_COMBINE_FACTOR_LOCAL;
1119 fxMesa->TexCombine[0].InvertRGB = FXFALSE;
1120 fxMesa->TexCombine[0].InvertAlpha = FXFALSE;
1121 }
1122 else {
1123 fxMesa->TexCombine[1].FunctionRGB = GR_COMBINE_FUNCTION_LOCAL;
1124 fxMesa->TexCombine[1].FactorRGB = GR_COMBINE_FACTOR_NONE;
1125 fxMesa->TexCombine[1].FunctionAlpha = GR_COMBINE_FUNCTION_LOCAL;
1126 fxMesa->TexCombine[1].FactorAlpha = GR_COMBINE_FACTOR_NONE;
1127 fxMesa->TexCombine[1].InvertRGB = FXFALSE;
1128 fxMesa->TexCombine[1].InvertAlpha = FXFALSE;
1129 fxMesa->TexCombine[0].FunctionRGB = GR_COMBINE_FUNCTION_BLEND_OTHER;
1130 fxMesa->TexCombine[0].FactorRGB = GR_COMBINE_FACTOR_ONE_MINUS_LOCAL;
1131 fxMesa->TexCombine[0].FunctionAlpha = GR_COMBINE_FUNCTION_BLEND_OTHER;
1132 fxMesa->TexCombine[0].FactorAlpha = GR_COMBINE_FACTOR_ONE_MINUS_LOCAL;
1133 fxMesa->TexCombine[0].InvertRGB = FXFALSE;
1134 fxMesa->TexCombine[0].InvertAlpha = FXFALSE;
1135 }
1136 fxMesa->ColorCombine.Function = GR_COMBINE_FUNCTION_SCALE_OTHER;
1137 fxMesa->ColorCombine.Factor = GR_COMBINE_FACTOR_ONE;
1138 fxMesa->ColorCombine.Local = localc;
1139 fxMesa->ColorCombine.Other = GR_COMBINE_OTHER_TEXTURE;
1140 fxMesa->ColorCombine.Invert = FXFALSE;
1141 fxMesa->AlphaCombine.Function = GR_COMBINE_FUNCTION_LOCAL;
1142 fxMesa->AlphaCombine.Factor = GR_COMBINE_FACTOR_NONE;
1143 fxMesa->AlphaCombine.Local = locala;
1144 fxMesa->AlphaCombine.Other = GR_COMBINE_OTHER_NONE;
1145 fxMesa->AlphaCombine.Invert = FXFALSE;
1146 }
1147 else if (envMode0 == GL_REPLACE && envMode1 == GL_MODULATE) {
1148 /* Quake 2/3 */
1149 if (tmu1 == TDFX_TMU1) {
1150 fxMesa->TexCombine[1].FunctionRGB = GR_COMBINE_FUNCTION_LOCAL;
1151 fxMesa->TexCombine[1].FactorRGB = GR_COMBINE_FACTOR_NONE;
1152 fxMesa->TexCombine[1].FunctionAlpha = GR_COMBINE_FUNCTION_ZERO;
1153 fxMesa->TexCombine[1].FactorAlpha = GR_COMBINE_FACTOR_NONE;
1154 fxMesa->TexCombine[1].InvertRGB = FXFALSE;
1155 fxMesa->TexCombine[1].InvertAlpha = FXTRUE;
1156 fxMesa->TexCombine[0].FunctionRGB = GR_COMBINE_FUNCTION_BLEND_OTHER;
1157 fxMesa->TexCombine[0].FactorRGB = GR_COMBINE_FACTOR_LOCAL;
1158 fxMesa->TexCombine[0].FunctionAlpha = GR_COMBINE_FUNCTION_BLEND_OTHER;
1159 fxMesa->TexCombine[0].FactorAlpha = GR_COMBINE_FACTOR_LOCAL;
1160 fxMesa->TexCombine[0].InvertRGB = FXFALSE;
1161 fxMesa->TexCombine[0].InvertAlpha = FXFALSE;
1162 }
1163 else {
1164 fxMesa->TexCombine[1].FunctionRGB = GR_COMBINE_FUNCTION_LOCAL;
1165 fxMesa->TexCombine[1].FactorRGB = GR_COMBINE_FACTOR_NONE;
1166 fxMesa->TexCombine[1].FunctionAlpha = GR_COMBINE_FUNCTION_LOCAL;
1167 fxMesa->TexCombine[1].FactorAlpha = GR_COMBINE_FACTOR_NONE;
1168 fxMesa->TexCombine[1].InvertRGB = FXFALSE;
1169 fxMesa->TexCombine[1].InvertAlpha = FXFALSE;
1170 fxMesa->TexCombine[0].FunctionRGB = GR_COMBINE_FUNCTION_BLEND_OTHER;
1171 fxMesa->TexCombine[0].FactorRGB = GR_COMBINE_FACTOR_LOCAL;
1172 fxMesa->TexCombine[0].FunctionAlpha = GR_COMBINE_FUNCTION_BLEND_OTHER;
1173 fxMesa->TexCombine[0].FactorAlpha = GR_COMBINE_FACTOR_ONE;
1174 fxMesa->TexCombine[0].InvertRGB = FXFALSE;
1175 fxMesa->TexCombine[0].InvertAlpha = FXFALSE;
1176 }
1177
1178 fxMesa->ColorCombine.Function = GR_COMBINE_FUNCTION_SCALE_OTHER;
1179 fxMesa->ColorCombine.Factor = GR_COMBINE_FACTOR_ONE;
1180 fxMesa->ColorCombine.Local = localc;
1181 fxMesa->ColorCombine.Other = GR_COMBINE_OTHER_TEXTURE;
1182 fxMesa->ColorCombine.Invert = FXFALSE;
1183 if (baseFormat0 == GL_RGB) {
1184 fxMesa->AlphaCombine.Function = GR_COMBINE_FUNCTION_LOCAL;
1185 fxMesa->AlphaCombine.Factor = GR_COMBINE_FACTOR_NONE;
1186 fxMesa->AlphaCombine.Local = locala;
1187 fxMesa->AlphaCombine.Other = GR_COMBINE_OTHER_NONE;
1188 fxMesa->AlphaCombine.Invert = FXFALSE;
1189 }
1190 else {
1191 fxMesa->AlphaCombine.Function = GR_COMBINE_FUNCTION_SCALE_OTHER;
1192 fxMesa->AlphaCombine.Factor = GR_COMBINE_FACTOR_ONE;
1193 fxMesa->AlphaCombine.Local = locala;
1194 fxMesa->AlphaCombine.Other = GR_COMBINE_OTHER_NONE;
1195 fxMesa->AlphaCombine.Invert = FXFALSE;
1196 }
1197 }
1198 else if (envMode0 == GL_MODULATE && envMode1 == GL_ADD) {
1199 /* Quake 3 sky */
1200 GLboolean isalpha[TDFX_NUM_TMU];
1201
1202 isalpha[tmu0] = (baseFormat0 == GL_ALPHA);
1203 isalpha[tmu1] = (baseFormat1 == GL_ALPHA);
1204
1205 if (isalpha[TDFX_TMU1]) {
1206 fxMesa->TexCombine[1].FunctionRGB = GR_COMBINE_FUNCTION_ZERO;
1207 fxMesa->TexCombine[1].FactorRGB = GR_COMBINE_FACTOR_NONE;
1208 fxMesa->TexCombine[1].FunctionAlpha = GR_COMBINE_FUNCTION_LOCAL;
1209 fxMesa->TexCombine[1].FactorAlpha = GR_COMBINE_FACTOR_NONE;
1210 fxMesa->TexCombine[1].InvertRGB = FXTRUE;
1211 fxMesa->TexCombine[1].InvertAlpha = FXFALSE;
1212 }
1213 else {
1214 fxMesa->TexCombine[1].FunctionRGB = GR_COMBINE_FUNCTION_LOCAL;
1215 fxMesa->TexCombine[1].FactorRGB = GR_COMBINE_FACTOR_NONE;
1216 fxMesa->TexCombine[1].FunctionAlpha = GR_COMBINE_FUNCTION_LOCAL;
1217 fxMesa->TexCombine[1].FactorAlpha = GR_COMBINE_FACTOR_NONE;
1218 fxMesa->TexCombine[1].InvertRGB = FXFALSE;
1219 fxMesa->TexCombine[1].InvertAlpha = FXFALSE;
1220 }
1221 if (isalpha[TDFX_TMU0]) {
1222 fxMesa->TexCombine[0].FunctionRGB = GR_COMBINE_FUNCTION_SCALE_OTHER;
1223 fxMesa->TexCombine[0].FactorRGB = GR_COMBINE_FACTOR_ONE;
1224 fxMesa->TexCombine[0].FunctionAlpha = GR_COMBINE_FUNCTION_SCALE_OTHER_ADD_LOCAL;
1225 fxMesa->TexCombine[0].FactorAlpha = GR_COMBINE_FACTOR_ONE;
1226 fxMesa->TexCombine[0].InvertRGB = FXFALSE;
1227 fxMesa->TexCombine[0].InvertAlpha = FXFALSE;
1228 }
1229 else {
1230 fxMesa->TexCombine[0].FunctionRGB = GR_COMBINE_FUNCTION_SCALE_OTHER_ADD_LOCAL;
1231 fxMesa->TexCombine[0].FactorRGB = GR_COMBINE_FACTOR_ONE;
1232 fxMesa->TexCombine[0].FunctionAlpha = GR_COMBINE_FUNCTION_SCALE_OTHER_ADD_LOCAL;
1233 fxMesa->TexCombine[0].FactorAlpha = GR_COMBINE_FACTOR_ONE;
1234 fxMesa->TexCombine[0].InvertRGB = FXFALSE;
1235 fxMesa->TexCombine[0].InvertAlpha = FXFALSE;
1236 }
1237 fxMesa->ColorCombine.Function = GR_COMBINE_FUNCTION_SCALE_OTHER;
1238 fxMesa->ColorCombine.Factor = GR_COMBINE_FACTOR_LOCAL;
1239 fxMesa->ColorCombine.Local = localc;
1240 fxMesa->ColorCombine.Other = GR_COMBINE_OTHER_TEXTURE;
1241 fxMesa->ColorCombine.Invert = FXFALSE;
1242 fxMesa->AlphaCombine.Function = GR_COMBINE_FUNCTION_SCALE_OTHER;
1243 fxMesa->AlphaCombine.Factor = GR_COMBINE_FACTOR_LOCAL;
1244 fxMesa->AlphaCombine.Local = locala;
1245 fxMesa->AlphaCombine.Other = GR_COMBINE_OTHER_TEXTURE;
1246 fxMesa->AlphaCombine.Invert = FXFALSE;
1247 }
1248 else if (envMode0 == GL_REPLACE && envMode1 == GL_ADD) {
1249 /* Vulpine sky */
1250 GLboolean isalpha[TDFX_NUM_TMU];
1251
1252 isalpha[tmu0] = (baseFormat0 == GL_ALPHA);
1253 isalpha[tmu1] = (baseFormat1 == GL_ALPHA);
1254
1255 if (isalpha[TDFX_TMU1]) {
1256 fxMesa->TexCombine[1].FunctionRGB = GR_COMBINE_FUNCTION_ZERO;
1257 fxMesa->TexCombine[1].FactorRGB = GR_COMBINE_FACTOR_NONE;
1258 fxMesa->TexCombine[1].FunctionAlpha = GR_COMBINE_FUNCTION_LOCAL;
1259 fxMesa->TexCombine[1].FactorAlpha = GR_COMBINE_FACTOR_NONE;
1260 fxMesa->TexCombine[1].InvertRGB = FXTRUE;
1261 fxMesa->TexCombine[1].InvertAlpha = FXFALSE;
1262 } else {
1263 fxMesa->TexCombine[1].FunctionRGB = GR_COMBINE_FUNCTION_LOCAL;
1264 fxMesa->TexCombine[1].FactorRGB = GR_COMBINE_FACTOR_NONE;
1265 fxMesa->TexCombine[1].FunctionAlpha = GR_COMBINE_FUNCTION_LOCAL;
1266 fxMesa->TexCombine[1].FactorAlpha = GR_COMBINE_FACTOR_NONE;
1267 fxMesa->TexCombine[1].InvertRGB = FXFALSE;
1268 fxMesa->TexCombine[1].InvertAlpha = FXFALSE;
1269 }
1270
1271 if (isalpha[TDFX_TMU0]) {
1272 fxMesa->TexCombine[0].FunctionRGB = GR_COMBINE_FUNCTION_SCALE_OTHER;
1273 fxMesa->TexCombine[0].FactorRGB = GR_COMBINE_FACTOR_ONE;
1274 fxMesa->TexCombine[0].FunctionAlpha = GR_COMBINE_FUNCTION_SCALE_OTHER_ADD_LOCAL;
1275 fxMesa->TexCombine[0].FactorAlpha = GR_COMBINE_FACTOR_ONE;
1276 fxMesa->TexCombine[0].InvertRGB = FXFALSE;
1277 fxMesa->TexCombine[0].InvertAlpha = FXFALSE;
1278 } else {
1279 fxMesa->TexCombine[0].FunctionRGB = GR_COMBINE_FUNCTION_SCALE_OTHER_ADD_LOCAL;
1280 fxMesa->TexCombine[0].FactorRGB = GR_COMBINE_FACTOR_ONE;
1281 fxMesa->TexCombine[0].FunctionAlpha = GR_COMBINE_FUNCTION_SCALE_OTHER_ADD_LOCAL;
1282 fxMesa->TexCombine[0].FactorAlpha = GR_COMBINE_FACTOR_ONE;
1283 fxMesa->TexCombine[0].InvertRGB = FXFALSE;
1284 fxMesa->TexCombine[0].InvertAlpha = FXFALSE;
1285 }
1286
1287 fxMesa->ColorCombine.Function = GR_COMBINE_FUNCTION_SCALE_OTHER;
1288 fxMesa->ColorCombine.Factor = GR_COMBINE_FACTOR_ONE;
1289 fxMesa->ColorCombine.Local = localc;
1290 fxMesa->ColorCombine.Other = GR_COMBINE_OTHER_TEXTURE;
1291 fxMesa->ColorCombine.Invert = FXFALSE;
1292 fxMesa->AlphaCombine.Function = GR_COMBINE_FUNCTION_SCALE_OTHER;
1293 fxMesa->AlphaCombine.Factor = GR_COMBINE_FACTOR_ONE;
1294 fxMesa->AlphaCombine.Local = locala;
1295 fxMesa->AlphaCombine.Other = GR_COMBINE_OTHER_TEXTURE;
1296 fxMesa->AlphaCombine.Invert = FXFALSE;
1297 }
1298 else if (envMode1 == GL_REPLACE) {
1299 /* Homeworld2 */
1300
1301 fxMesa->TexCombine[1].FunctionRGB = GR_COMBINE_FUNCTION_ZERO;
1302 fxMesa->TexCombine[1].FactorRGB = GR_COMBINE_FACTOR_NONE;
1303 fxMesa->TexCombine[1].FunctionAlpha = GR_COMBINE_FUNCTION_ZERO;
1304 fxMesa->TexCombine[1].FactorAlpha = GR_COMBINE_FACTOR_NONE;
1305 fxMesa->TexCombine[1].InvertRGB = FXFALSE;
1306 fxMesa->TexCombine[1].InvertAlpha = FXFALSE;
1307
1308 fxMesa->TexCombine[0].FunctionRGB = GR_COMBINE_FUNCTION_LOCAL;
1309 fxMesa->TexCombine[0].FactorRGB = GR_COMBINE_FACTOR_NONE;
1310 fxMesa->TexCombine[0].FunctionAlpha = GR_COMBINE_FUNCTION_LOCAL;
1311 fxMesa->TexCombine[0].FactorAlpha = GR_COMBINE_FACTOR_NONE;
1312 fxMesa->TexCombine[0].InvertRGB = FXFALSE;
1313 fxMesa->TexCombine[0].InvertAlpha = FXFALSE;
1314
1315 if ((baseFormat0 == GL_RGB) && (baseFormat0 == GL_LUMINANCE)) {
1316 fxMesa->AlphaCombine.Function = GR_COMBINE_FUNCTION_LOCAL;
1317 fxMesa->AlphaCombine.Factor = GR_COMBINE_FACTOR_NONE;
1318 fxMesa->AlphaCombine.Local = locala;
1319 fxMesa->AlphaCombine.Other = GR_COMBINE_OTHER_NONE;
1320 fxMesa->AlphaCombine.Invert = FXFALSE;
1321 } else {
1322 fxMesa->AlphaCombine.Function = GR_COMBINE_FUNCTION_SCALE_OTHER;
1323 fxMesa->AlphaCombine.Factor = GR_COMBINE_FACTOR_ONE;
1324 fxMesa->AlphaCombine.Local = locala;
1325 fxMesa->AlphaCombine.Other = GR_COMBINE_OTHER_TEXTURE;
1326 fxMesa->AlphaCombine.Invert = FXFALSE;
1327 }
1328 if (baseFormat0 == GL_ALPHA) {
1329 fxMesa->ColorCombine.Function = GR_COMBINE_FUNCTION_LOCAL;
1330 fxMesa->ColorCombine.Factor = GR_COMBINE_FACTOR_NONE;
1331 fxMesa->ColorCombine.Local = localc;
1332 fxMesa->ColorCombine.Other = GR_COMBINE_OTHER_NONE;
1333 fxMesa->ColorCombine.Invert = FXFALSE;
1334 } else {
1335 fxMesa->ColorCombine.Function = GR_COMBINE_FUNCTION_SCALE_OTHER;
1336 fxMesa->ColorCombine.Factor = GR_COMBINE_FACTOR_ONE;
1337 fxMesa->ColorCombine.Local = localc;
1338 fxMesa->ColorCombine.Other = GR_COMBINE_OTHER_TEXTURE;
1339 fxMesa->ColorCombine.Invert = FXFALSE;
1340 }
1341 }
1342 else {
1343 _mesa_problem(ctx, "%s: Unexpected dual texture mode encountered", __FUNCTION__);
1344 return GL_FALSE;
1345 }
1346
1347 fxMesa->dirty |= TDFX_UPLOAD_TEXTURE_ENV;
1348 fxMesa->dirty |= TDFX_UPLOAD_COLOR_COMBINE;
1349 fxMesa->dirty |= TDFX_UPLOAD_ALPHA_COMBINE;
1350 return GL_TRUE;
1351 }
1352
1353
1354 /*
1355 * This function makes sure that the correct mipmap levels are loaded
1356 * in the right places in memory and then makes the Glide calls to
1357 * setup the texture source pointers.
1358 */
1359 static void
1360 setupSingleTMU(tdfxContextPtr fxMesa, struct gl_texture_object *tObj)
1361 {
1362 struct tdfxSharedState *shared = (struct tdfxSharedState *) fxMesa->glCtx->Shared->DriverData;
1363 tdfxTexInfo *ti = TDFX_TEXTURE_DATA(tObj);
1364 const GLcontext *ctx = fxMesa->glCtx;
1365
1366 /* Make sure we're not loaded incorrectly */
1367 if (ti->isInTM && !shared->umaTexMemory) {
1368 /* if doing filtering between mipmap levels, alternate mipmap levels
1369 * must be in alternate TMUs.
1370 */
1371 if (ti->LODblend) {
1372 if (ti->whichTMU != TDFX_TMU_SPLIT)
1373 tdfxTMMoveOutTM_NoLock(fxMesa, tObj);
1374 }
1375 else {
1376 if (ti->whichTMU == TDFX_TMU_SPLIT)
1377 tdfxTMMoveOutTM_NoLock(fxMesa, tObj);
1378 }
1379 }
1380
1381 /* Make sure we're loaded correctly */
1382 if (!ti->isInTM) {
1383 /* Have to download the texture */
1384 if (shared->umaTexMemory) {
1385 tdfxTMMoveInTM_NoLock(fxMesa, tObj, TDFX_TMU0);
1386 }
1387 else {
1388 /* Voodoo3 (split texture memory) */
1389 if (ti->LODblend) {
1390 tdfxTMMoveInTM_NoLock(fxMesa, tObj, TDFX_TMU_SPLIT);
1391 }
1392 else {
1393 #if 0
1394 /* XXX putting textures into the second memory bank when the
1395 * first bank is full is not working at this time.
1396 */
1397 if (fxMesa->haveTwoTMUs) {
1398 GLint memReq = fxMesa->Glide.grTexTextureMemRequired(
1399 GR_MIPMAPLEVELMASK_BOTH, &(ti->info));
1400 if (shared->freeTexMem[TDFX_TMU0] > memReq) {
1401 tdfxTMMoveInTM_NoLock(fxMesa, tObj, TDFX_TMU0);
1402 }
1403 else {
1404 tdfxTMMoveInTM_NoLock(fxMesa, tObj, TDFX_TMU1);
1405 }
1406 }
1407 else
1408 #endif
1409 {
1410 tdfxTMMoveInTM_NoLock(fxMesa, tObj, TDFX_TMU0);
1411 }
1412 }
1413 }
1414 }
1415
1416 if (ti->LODblend && ti->whichTMU == TDFX_TMU_SPLIT) {
1417 /* mipmap levels split between texture banks */
1418 GLint u;
1419
1420 if (ti->info.format == GR_TEXFMT_P_8 && !ctx->Texture.SharedPalette) {
1421 fxMesa->TexPalette.Type = ti->paltype;
1422 fxMesa->TexPalette.Data = &(ti->palette);
1423 fxMesa->dirty |= TDFX_UPLOAD_TEXTURE_PALETTE;
1424 }
1425
1426 for (u = 0; u < 2; u++) {
1427 fxMesa->TexParams[u].sClamp = ti->sClamp;
1428 fxMesa->TexParams[u].tClamp = ti->tClamp;
1429 fxMesa->TexParams[u].minFilt = ti->minFilt;
1430 fxMesa->TexParams[u].magFilt = ti->magFilt;
1431 fxMesa->TexParams[u].mmMode = ti->mmMode;
1432 fxMesa->TexParams[u].LODblend = ti->LODblend;
1433 fxMesa->TexParams[u].LodBias = ctx->Texture.Unit[u].LodBias;
1434 }
1435 fxMesa->dirty |= TDFX_UPLOAD_TEXTURE_PARAMS;
1436
1437 fxMesa->TexSource[0].StartAddress = ti->tm[TDFX_TMU0]->startAddr;
1438 fxMesa->TexSource[0].EvenOdd = GR_MIPMAPLEVELMASK_ODD;
1439 fxMesa->TexSource[0].Info = &(ti->info);
1440 fxMesa->TexSource[1].StartAddress = ti->tm[TDFX_TMU1]->startAddr;
1441 fxMesa->TexSource[1].EvenOdd = GR_MIPMAPLEVELMASK_EVEN;
1442 fxMesa->TexSource[1].Info = &(ti->info);
1443 fxMesa->dirty |= TDFX_UPLOAD_TEXTURE_SOURCE;
1444 }
1445 else {
1446 FxU32 tmu;
1447
1448 if (ti->whichTMU == TDFX_TMU_BOTH)
1449 tmu = TDFX_TMU0;
1450 else
1451 tmu = ti->whichTMU;
1452
1453 if (shared->umaTexMemory) {
1454 assert(ti->whichTMU == TDFX_TMU0);
1455 assert(tmu == TDFX_TMU0);
1456 }
1457
1458 if (ti->info.format == GR_TEXFMT_P_8 && !ctx->Texture.SharedPalette) {
1459 fxMesa->TexPalette.Type = ti->paltype;
1460 fxMesa->TexPalette.Data = &(ti->palette);
1461 fxMesa->dirty |= TDFX_UPLOAD_TEXTURE_PALETTE;
1462 }
1463
1464 /* KW: The alternative is to do the download to the other tmu. If
1465 * we get to this point, I think it means we are thrashing the
1466 * texture memory, so perhaps it's not a good idea.
1467 */
1468
1469 if (fxMesa->TexParams[tmu].sClamp != ti->sClamp ||
1470 fxMesa->TexParams[tmu].tClamp != ti->tClamp ||
1471 fxMesa->TexParams[tmu].minFilt != ti->minFilt ||
1472 fxMesa->TexParams[tmu].magFilt != ti->magFilt ||
1473 fxMesa->TexParams[tmu].mmMode != ti->mmMode ||
1474 fxMesa->TexParams[tmu].LODblend != FXFALSE ||
1475 fxMesa->TexParams[tmu].LodBias != ctx->Texture.Unit[tmu].LodBias) {
1476 fxMesa->TexParams[tmu].sClamp = ti->sClamp;
1477 fxMesa->TexParams[tmu].tClamp = ti->tClamp;
1478 fxMesa->TexParams[tmu].minFilt = ti->minFilt;
1479 fxMesa->TexParams[tmu].magFilt = ti->magFilt;
1480 fxMesa->TexParams[tmu].mmMode = ti->mmMode;
1481 fxMesa->TexParams[tmu].LODblend = FXFALSE;
1482 fxMesa->TexParams[tmu].LodBias = ctx->Texture.Unit[tmu].LodBias;
1483 fxMesa->dirty |= TDFX_UPLOAD_TEXTURE_PARAMS;
1484 }
1485
1486 /* Glide texture source info */
1487 fxMesa->TexSource[0].Info = NULL;
1488 fxMesa->TexSource[1].Info = NULL;
1489 if (ti->tm[tmu]) {
1490 fxMesa->TexSource[tmu].StartAddress = ti->tm[tmu]->startAddr;
1491 fxMesa->TexSource[tmu].EvenOdd = GR_MIPMAPLEVELMASK_BOTH;
1492 fxMesa->TexSource[tmu].Info = &(ti->info);
1493 fxMesa->dirty |= TDFX_UPLOAD_TEXTURE_SOURCE;
1494 }
1495 }
1496
1497 fxMesa->sScale0 = ti->sScale;
1498 fxMesa->tScale0 = ti->tScale;
1499 }
1500
1501 static void
1502 selectSingleTMUSrc(tdfxContextPtr fxMesa, GLint tmu, FxBool LODblend)
1503 {
1504 if (LODblend) {
1505 fxMesa->TexCombine[0].FunctionRGB = GR_COMBINE_FUNCTION_BLEND;
1506 fxMesa->TexCombine[0].FactorRGB = GR_COMBINE_FACTOR_ONE_MINUS_LOD_FRACTION;
1507 fxMesa->TexCombine[0].FunctionAlpha = GR_COMBINE_FUNCTION_BLEND;
1508 fxMesa->TexCombine[0].FactorAlpha = GR_COMBINE_FACTOR_ONE_MINUS_LOD_FRACTION;
1509 fxMesa->TexCombine[0].InvertRGB = FXFALSE;
1510 fxMesa->TexCombine[0].InvertAlpha = FXFALSE;
1511
1512 if (fxMesa->haveTwoTMUs) {
1513 const struct gl_shared_state *mesaShared = fxMesa->glCtx->Shared;
1514 const struct tdfxSharedState *shared = (struct tdfxSharedState *) mesaShared->DriverData;
1515 int tmu;
1516
1517 if (shared->umaTexMemory)
1518 tmu = GR_TMU0;
1519 else
1520 tmu = GR_TMU1;
1521
1522 fxMesa->TexCombine[tmu].FunctionRGB = GR_COMBINE_FUNCTION_LOCAL;
1523 fxMesa->TexCombine[tmu].FactorRGB = GR_COMBINE_FACTOR_NONE;
1524 fxMesa->TexCombine[tmu].FunctionAlpha = GR_COMBINE_FUNCTION_LOCAL;
1525 fxMesa->TexCombine[tmu].FactorAlpha = GR_COMBINE_FACTOR_NONE;
1526 fxMesa->TexCombine[tmu].InvertRGB = FXFALSE;
1527 fxMesa->TexCombine[tmu].InvertAlpha = FXFALSE;
1528 }
1529 fxMesa->tmuSrc = TDFX_TMU_SPLIT;
1530 }
1531 else {
1532 if (tmu != TDFX_TMU1) {
1533 fxMesa->TexCombine[0].FunctionRGB = GR_COMBINE_FUNCTION_LOCAL;
1534 fxMesa->TexCombine[0].FactorRGB = GR_COMBINE_FACTOR_NONE;
1535 fxMesa->TexCombine[0].FunctionAlpha = GR_COMBINE_FUNCTION_LOCAL;
1536 fxMesa->TexCombine[0].FactorAlpha = GR_COMBINE_FACTOR_NONE;
1537 fxMesa->TexCombine[0].InvertRGB = FXFALSE;
1538 fxMesa->TexCombine[0].InvertAlpha = FXFALSE;
1539 if (fxMesa->haveTwoTMUs) {
1540 fxMesa->TexCombine[1].FunctionRGB = GR_COMBINE_FUNCTION_ZERO;
1541 fxMesa->TexCombine[1].FactorRGB = GR_COMBINE_FACTOR_NONE;
1542 fxMesa->TexCombine[1].FunctionAlpha = GR_COMBINE_FUNCTION_ZERO;
1543 fxMesa->TexCombine[1].FactorAlpha = GR_COMBINE_FACTOR_NONE;
1544 fxMesa->TexCombine[1].InvertRGB = FXFALSE;
1545 fxMesa->TexCombine[1].InvertAlpha = FXFALSE;
1546 }
1547 fxMesa->tmuSrc = TDFX_TMU0;
1548 }
1549 else {
1550 fxMesa->TexCombine[1].FunctionRGB = GR_COMBINE_FUNCTION_LOCAL;
1551 fxMesa->TexCombine[1].FactorRGB = GR_COMBINE_FACTOR_NONE;
1552 fxMesa->TexCombine[1].FunctionAlpha = GR_COMBINE_FUNCTION_LOCAL;
1553 fxMesa->TexCombine[1].FactorAlpha = GR_COMBINE_FACTOR_NONE;
1554 fxMesa->TexCombine[1].InvertRGB = FXFALSE;
1555 fxMesa->TexCombine[1].InvertAlpha = FXFALSE;
1556 /* GR_COMBINE_FUNCTION_SCALE_OTHER doesn't work ?!? */
1557 fxMesa->TexCombine[0].FunctionRGB = GR_COMBINE_FUNCTION_BLEND;
1558 fxMesa->TexCombine[0].FactorRGB = GR_COMBINE_FACTOR_ONE;
1559 fxMesa->TexCombine[0].FunctionAlpha = GR_COMBINE_FUNCTION_BLEND;
1560 fxMesa->TexCombine[0].FactorAlpha = GR_COMBINE_FACTOR_ONE;
1561 fxMesa->TexCombine[0].InvertRGB = FXFALSE;
1562 fxMesa->TexCombine[0].InvertAlpha = FXFALSE;
1563 fxMesa->tmuSrc = TDFX_TMU1;
1564 }
1565 }
1566
1567 fxMesa->dirty |= TDFX_UPLOAD_TEXTURE_ENV;
1568 }
1569
1570 #if 0
1571 static void print_state(tdfxContextPtr fxMesa)
1572 {
1573 GLcontext *ctx = fxMesa->glCtx;
1574 struct gl_texture_object *tObj0 = ctx->Texture.Unit[0]._Current;
1575 struct gl_texture_object *tObj1 = ctx->Texture.Unit[1]._Current;
1576 GLenum base0 = tObj0->Image[0][tObj0->BaseLevel] ? tObj0->Image[0][tObj0->BaseLevel]->Format : 99;
1577 GLenum base1 = tObj1->Image[0][tObj1->BaseLevel] ? tObj1->Image[0][tObj1->BaseLevel]->Format : 99;
1578
1579 printf("Unit 0: Enabled: GL=%d Gr=%d\n", ctx->Texture.Unit[0]._ReallyEnabled,
1580 fxMesa->TexState.Enabled[0]);
1581 printf(" EnvMode: GL=0x%x Gr=0x%x\n", ctx->Texture.Unit[0].EnvMode,
1582 fxMesa->TexState.EnvMode[0]);
1583 printf(" BaseFmt: GL=0x%x Gr=0x%x\n", base0, fxMesa->TexState.TexFormat[0]);
1584
1585
1586 printf("Unit 1: Enabled: GL=%d Gr=%d\n", ctx->Texture.Unit[1]._ReallyEnabled,
1587 fxMesa->TexState.Enabled[1]);
1588 printf(" EnvMode: GL=0x%x Gr:0x%x\n", ctx->Texture.Unit[1].EnvMode,
1589 fxMesa->TexState.EnvMode[1]);
1590 printf(" BaseFmt: GL=0x%x Gr:0x%x\n", base1, fxMesa->TexState.TexFormat[1]);
1591 }
1592 #endif
1593
1594 /*
1595 * When we're only using a single texture unit, we always use the 0th
1596 * Glide/hardware unit, regardless if it's GL_TEXTURE0_ARB or GL_TEXTURE1_ARB
1597 * that's enalbed.
1598 * Input: ctx - the context
1599 * unit - the OpenGL texture unit to use.
1600 */
1601 static void setupTextureSingleTMU(GLcontext * ctx, GLuint unit)
1602 {
1603 tdfxContextPtr fxMesa = TDFX_CONTEXT(ctx);
1604 tdfxTexInfo *ti;
1605 struct gl_texture_object *tObj;
1606 int tmu;
1607 GLenum envMode, baseFormat;
1608
1609 tObj = ctx->Texture.Unit[unit]._Current;
1610 if (tObj->Image[0][tObj->BaseLevel]->Border > 0) {
1611 FALLBACK(fxMesa, TDFX_FALLBACK_TEXTURE_BORDER, GL_TRUE);
1612 return;
1613 }
1614
1615 setupSingleTMU(fxMesa, tObj);
1616
1617 ti = TDFX_TEXTURE_DATA(tObj);
1618 if (ti->whichTMU == TDFX_TMU_BOTH)
1619 tmu = TDFX_TMU0;
1620 else
1621 tmu = ti->whichTMU;
1622
1623 if (fxMesa->tmuSrc != tmu) {
1624 selectSingleTMUSrc(fxMesa, tmu, ti->LODblend);
1625 }
1626
1627 if (ti->reloadImages)
1628 fxMesa->dirty |= TDFX_UPLOAD_TEXTURE_IMAGES;
1629
1630 /* Check if we really need to update the texenv state */
1631 envMode = ctx->Texture.Unit[unit].EnvMode;
1632 baseFormat = tObj->Image[0][tObj->BaseLevel]->Format;
1633
1634 if (TDFX_IS_NAPALM(fxMesa)) {
1635 /* see if we really need to update the unit */
1636 if (1/*fxMesa->TexState.Enabled[unit] != ctx->Texture.Unit[unit]._ReallyEnabled ||
1637 envMode != fxMesa->TexState.EnvMode[0] ||
1638 envMode == GL_COMBINE_EXT ||
1639 baseFormat != fxMesa->TexState.TexFormat[0]*/) {
1640 struct tdfx_texcombine_ext *otherEnv;
1641 if (!SetupTexEnvNapalm(ctx, GL_TRUE,
1642 &ctx->Texture.Unit[unit], baseFormat,
1643 &fxMesa->TexCombineExt[0])) {
1644 /* software fallback */
1645 FALLBACK(fxMesa, TDFX_FALLBACK_TEXTURE_ENV, GL_TRUE);
1646 }
1647 /* disable other unit */
1648 otherEnv = &fxMesa->TexCombineExt[1];
1649 otherEnv->Color.SourceA = GR_CMBX_ZERO;
1650 otherEnv->Color.ModeA = GR_FUNC_MODE_ZERO;
1651 otherEnv->Color.SourceB = GR_CMBX_ZERO;
1652 otherEnv->Color.ModeB = GR_FUNC_MODE_ZERO;
1653 otherEnv->Color.SourceC = GR_CMBX_ZERO;
1654 otherEnv->Color.InvertC = FXFALSE;
1655 otherEnv->Color.SourceD = GR_CMBX_ZERO;
1656 otherEnv->Color.InvertD = FXFALSE;
1657 otherEnv->Color.Shift = 0;
1658 otherEnv->Color.Invert = FXFALSE;
1659 otherEnv->Alpha.SourceA = GR_CMBX_ITALPHA;
1660 otherEnv->Alpha.ModeA = GR_FUNC_MODE_ZERO;
1661 otherEnv->Alpha.SourceB = GR_CMBX_ITALPHA;
1662 otherEnv->Alpha.ModeB = GR_FUNC_MODE_ZERO;
1663 otherEnv->Alpha.SourceC = GR_CMBX_ZERO;
1664 otherEnv->Alpha.InvertC = FXFALSE;
1665 otherEnv->Alpha.SourceD = GR_CMBX_ZERO;
1666 otherEnv->Alpha.InvertD = FXFALSE;
1667 otherEnv->Alpha.Shift = 0;
1668 otherEnv->Alpha.Invert = FXFALSE;
1669
1670 #if 0/*JJJ*/
1671 fxMesa->TexState.Enabled[unit] = ctx->Texture.Unit[unit]._ReallyEnabled;
1672 fxMesa->TexState.EnvMode[0] = envMode;
1673 fxMesa->TexState.TexFormat[0] = baseFormat;
1674 fxMesa->TexState.EnvMode[1] = 0;
1675 fxMesa->TexState.TexFormat[1] = 0;
1676 #endif
1677 }
1678 }
1679 else {
1680 /* Voodoo3 */
1681
1682 /* see if we really need to update the unit */
1683 if (1/*fxMesa->TexState.Enabled[unit] != ctx->Texture.Unit[unit]._ReallyEnabled ||
1684 envMode != fxMesa->TexState.EnvMode[0] ||
1685 envMode == GL_COMBINE_EXT ||
1686 baseFormat != fxMesa->TexState.TexFormat[0]*/) {
1687 if (!SetupSingleTexEnvVoodoo3(ctx, unit, envMode, baseFormat)) {
1688 /* software fallback */
1689 FALLBACK(fxMesa, TDFX_FALLBACK_TEXTURE_ENV, GL_TRUE);
1690 }
1691 #if 0/*JJJ*/
1692 fxMesa->TexState.Enabled[unit] = ctx->Texture.Unit[unit]._ReallyEnabled;
1693 fxMesa->TexState.EnvMode[0] = envMode;
1694 fxMesa->TexState.TexFormat[0] = baseFormat;
1695 fxMesa->TexState.EnvMode[1] = 0;
1696 fxMesa->TexState.TexFormat[1] = 0;
1697 #endif
1698 }
1699 }
1700 }
1701
1702
1703 static void
1704 setupDoubleTMU(tdfxContextPtr fxMesa,
1705 struct gl_texture_object *tObj0,
1706 struct gl_texture_object *tObj1)
1707 {
1708 #define T0_NOT_IN_TMU 0x01
1709 #define T1_NOT_IN_TMU 0x02
1710 #define T0_IN_TMU0 0x04
1711 #define T1_IN_TMU0 0x08
1712 #define T0_IN_TMU1 0x10
1713 #define T1_IN_TMU1 0x20
1714
1715 const struct gl_shared_state *mesaShared = fxMesa->glCtx->Shared;
1716 const struct tdfxSharedState *shared = (struct tdfxSharedState *) mesaShared->DriverData;
1717 const GLcontext *ctx = fxMesa->glCtx;
1718 tdfxTexInfo *ti0 = TDFX_TEXTURE_DATA(tObj0);
1719 tdfxTexInfo *ti1 = TDFX_TEXTURE_DATA(tObj1);
1720 GLuint tstate = 0;
1721 int tmu0 = 0, tmu1 = 1;
1722
1723 if (shared->umaTexMemory) {
1724 if (!ti0->isInTM) {
1725 tdfxTMMoveInTM_NoLock(fxMesa, tObj0, TDFX_TMU0);
1726 assert(ti0->isInTM);
1727 }
1728 if (!ti1->isInTM) {
1729 tdfxTMMoveInTM_NoLock(fxMesa, tObj1, TDFX_TMU0);
1730 assert(ti1->isInTM);
1731 }
1732 }
1733 else {
1734 /* We shouldn't need to do this. There is something wrong with
1735 multitexturing when the TMUs are swapped. So, we're forcing
1736 them to always be loaded correctly. !!! */
1737 if (ti0->whichTMU == TDFX_TMU1)
1738 tdfxTMMoveOutTM_NoLock(fxMesa, tObj0);
1739 if (ti1->whichTMU == TDFX_TMU0)
1740 tdfxTMMoveOutTM_NoLock(fxMesa, tObj1);
1741
1742 if (ti0->isInTM) {
1743 switch (ti0->whichTMU) {
1744 case TDFX_TMU0:
1745 tstate |= T0_IN_TMU0;
1746 break;
1747 case TDFX_TMU1:
1748 tstate |= T0_IN_TMU1;
1749 break;
1750 case TDFX_TMU_BOTH:
1751 tstate |= T0_IN_TMU0 | T0_IN_TMU1;
1752 break;
1753 case TDFX_TMU_SPLIT:
1754 tstate |= T0_NOT_IN_TMU;
1755 break;
1756 }
1757 }
1758 else
1759 tstate |= T0_NOT_IN_TMU;
1760
1761 if (ti1->isInTM) {
1762 switch (ti1->whichTMU) {
1763 case TDFX_TMU0:
1764 tstate |= T1_IN_TMU0;
1765 break;
1766 case TDFX_TMU1:
1767 tstate |= T1_IN_TMU1;
1768 break;
1769 case TDFX_TMU_BOTH:
1770 tstate |= T1_IN_TMU0 | T1_IN_TMU1;
1771 break;
1772 case TDFX_TMU_SPLIT:
1773 tstate |= T1_NOT_IN_TMU;
1774 break;
1775 }
1776 }
1777 else
1778 tstate |= T1_NOT_IN_TMU;
1779
1780 /* Move texture maps into TMUs */
1781
1782 if (!(((tstate & T0_IN_TMU0) && (tstate & T1_IN_TMU1)) ||
1783 ((tstate & T0_IN_TMU1) && (tstate & T1_IN_TMU0)))) {
1784 if (tObj0 == tObj1) {
1785 tdfxTMMoveInTM_NoLock(fxMesa, tObj1, TDFX_TMU_BOTH);
1786 }
1787 else {
1788 /* Find the minimal way to correct the situation */
1789 if ((tstate & T0_IN_TMU0) || (tstate & T1_IN_TMU1)) {
1790 /* We have one in the standard order, setup the other */
1791 if (tstate & T0_IN_TMU0) {
1792 /* T0 is in TMU0, put T1 in TMU1 */
1793 tdfxTMMoveInTM_NoLock(fxMesa, tObj1, TDFX_TMU1);
1794 }
1795 else {
1796 tdfxTMMoveInTM_NoLock(fxMesa, tObj0, TDFX_TMU0);
1797 }
1798 /* tmu0 and tmu1 are setup */
1799 }
1800 else if ((tstate & T0_IN_TMU1) || (tstate & T1_IN_TMU0)) {
1801 /* we have one in the reverse order, setup the other */
1802 if (tstate & T1_IN_TMU0) {
1803 /* T1 is in TMU0, put T0 in TMU1 */
1804 tdfxTMMoveInTM_NoLock(fxMesa, tObj0, TDFX_TMU1);
1805 }
1806 else {
1807 tdfxTMMoveInTM_NoLock(fxMesa, tObj1, TDFX_TMU0);
1808 }
1809 tmu0 = 1;
1810 tmu1 = 0;
1811 }
1812 else { /* Nothing is loaded */
1813 tdfxTMMoveInTM_NoLock(fxMesa, tObj0, TDFX_TMU0);
1814 tdfxTMMoveInTM_NoLock(fxMesa, tObj1, TDFX_TMU1);
1815 /* tmu0 and tmu1 are setup */
1816 }
1817 }
1818 }
1819 }
1820
1821 ti0->lastTimeUsed = fxMesa->texBindNumber;
1822 ti1->lastTimeUsed = fxMesa->texBindNumber;
1823
1824
1825 if (!ctx->Texture.SharedPalette) {
1826 if (ti0->info.format == GR_TEXFMT_P_8) {
1827 fxMesa->TexPalette.Type = ti0->paltype;
1828 fxMesa->TexPalette.Data = &(ti0->palette);
1829 fxMesa->dirty |= TDFX_UPLOAD_TEXTURE_PALETTE;
1830 }
1831 else if (ti1->info.format == GR_TEXFMT_P_8) {
1832 fxMesa->TexPalette.Type = ti1->paltype;
1833 fxMesa->TexPalette.Data = &(ti1->palette);
1834 fxMesa->dirty |= TDFX_UPLOAD_TEXTURE_PALETTE;
1835 }
1836 else {
1837 fxMesa->TexPalette.Data = NULL;
1838 }
1839 }
1840
1841 /*
1842 * Setup Unit 0
1843 */
1844 assert(ti0->isInTM);
1845 assert(ti0->tm[tmu0]);
1846 fxMesa->TexSource[tmu0].StartAddress = ti0->tm[tmu0]->startAddr;
1847 fxMesa->TexSource[tmu0].EvenOdd = GR_MIPMAPLEVELMASK_BOTH;
1848 fxMesa->TexSource[tmu0].Info = &(ti0->info);
1849 fxMesa->dirty |= TDFX_UPLOAD_TEXTURE_SOURCE;
1850
1851 if (fxMesa->TexParams[tmu0].sClamp != ti0->sClamp ||
1852 fxMesa->TexParams[tmu0].tClamp != ti0->tClamp ||
1853 fxMesa->TexParams[tmu0].minFilt != ti0->minFilt ||
1854 fxMesa->TexParams[tmu0].magFilt != ti0->magFilt ||
1855 fxMesa->TexParams[tmu0].mmMode != ti0->mmMode ||
1856 fxMesa->TexParams[tmu0].LODblend != FXFALSE ||
1857 fxMesa->TexParams[tmu0].LodBias != ctx->Texture.Unit[tmu0].LodBias) {
1858 fxMesa->TexParams[tmu0].sClamp = ti0->sClamp;
1859 fxMesa->TexParams[tmu0].tClamp = ti0->tClamp;
1860 fxMesa->TexParams[tmu0].minFilt = ti0->minFilt;
1861 fxMesa->TexParams[tmu0].magFilt = ti0->magFilt;
1862 fxMesa->TexParams[tmu0].mmMode = ti0->mmMode;
1863 fxMesa->TexParams[tmu0].LODblend = FXFALSE;
1864 fxMesa->TexParams[tmu0].LodBias = ctx->Texture.Unit[tmu0].LodBias;
1865 fxMesa->dirty |= TDFX_UPLOAD_TEXTURE_PARAMS;
1866 }
1867
1868 /*
1869 * Setup Unit 1
1870 */
1871 if (shared->umaTexMemory) {
1872 ASSERT(ti1->isInTM);
1873 ASSERT(ti1->tm[0]);
1874 fxMesa->TexSource[tmu1].StartAddress = ti1->tm[0]->startAddr;
1875 fxMesa->TexSource[tmu1].EvenOdd = GR_MIPMAPLEVELMASK_BOTH;
1876 fxMesa->TexSource[tmu1].Info = &(ti1->info);
1877 }
1878 else {
1879 ASSERT(ti1->isInTM);
1880 ASSERT(ti1->tm[tmu1]);
1881 fxMesa->TexSource[tmu1].StartAddress = ti1->tm[tmu1]->startAddr;
1882 fxMesa->TexSource[tmu1].EvenOdd = GR_MIPMAPLEVELMASK_BOTH;
1883 fxMesa->TexSource[tmu1].Info = &(ti1->info);
1884 }
1885
1886 if (fxMesa->TexParams[tmu1].sClamp != ti1->sClamp ||
1887 fxMesa->TexParams[tmu1].tClamp != ti1->tClamp ||
1888 fxMesa->TexParams[tmu1].minFilt != ti1->minFilt ||
1889 fxMesa->TexParams[tmu1].magFilt != ti1->magFilt ||
1890 fxMesa->TexParams[tmu1].mmMode != ti1->mmMode ||
1891 fxMesa->TexParams[tmu1].LODblend != FXFALSE ||
1892 fxMesa->TexParams[tmu1].LodBias != ctx->Texture.Unit[tmu1].LodBias) {
1893 fxMesa->TexParams[tmu1].sClamp = ti1->sClamp;
1894 fxMesa->TexParams[tmu1].tClamp = ti1->tClamp;
1895 fxMesa->TexParams[tmu1].minFilt = ti1->minFilt;
1896 fxMesa->TexParams[tmu1].magFilt = ti1->magFilt;
1897 fxMesa->TexParams[tmu1].mmMode = ti1->mmMode;
1898 fxMesa->TexParams[tmu1].LODblend = FXFALSE;
1899 fxMesa->TexParams[tmu1].LodBias = ctx->Texture.Unit[tmu1].LodBias;
1900 fxMesa->dirty |= TDFX_UPLOAD_TEXTURE_PARAMS;
1901 }
1902
1903 fxMesa->sScale0 = ti0->sScale;
1904 fxMesa->tScale0 = ti0->tScale;
1905 fxMesa->sScale1 = ti1->sScale;
1906 fxMesa->tScale1 = ti1->tScale;
1907
1908 #undef T0_NOT_IN_TMU
1909 #undef T1_NOT_IN_TMU
1910 #undef T0_IN_TMU0
1911 #undef T1_IN_TMU0
1912 #undef T0_IN_TMU1
1913 #undef T1_IN_TMU1
1914 }
1915
1916 static void setupTextureDoubleTMU(GLcontext * ctx)
1917 {
1918 tdfxContextPtr fxMesa = TDFX_CONTEXT(ctx);
1919 struct gl_texture_object *tObj0 = ctx->Texture.Unit[1]._Current;
1920 struct gl_texture_object *tObj1 = ctx->Texture.Unit[0]._Current;
1921 tdfxTexInfo *ti0 = TDFX_TEXTURE_DATA(tObj0);
1922 tdfxTexInfo *ti1 = TDFX_TEXTURE_DATA(tObj1);
1923 struct gl_texture_image *baseImage0 = tObj0->Image[0][tObj0->BaseLevel];
1924 struct gl_texture_image *baseImage1 = tObj1->Image[0][tObj1->BaseLevel];
1925 const GLenum envMode0 = ctx->Texture.Unit[0].EnvMode;
1926 const GLenum envMode1 = ctx->Texture.Unit[1].EnvMode;
1927
1928 if (baseImage0->Border > 0 || baseImage1->Border > 0) {
1929 FALLBACK(fxMesa, TDFX_FALLBACK_TEXTURE_BORDER, GL_TRUE);
1930 return;
1931 }
1932
1933 setupDoubleTMU(fxMesa, tObj0, tObj1);
1934
1935 if (ti0->reloadImages || ti1->reloadImages)
1936 fxMesa->dirty |= TDFX_UPLOAD_TEXTURE_IMAGES;
1937
1938 fxMesa->tmuSrc = TDFX_TMU_BOTH;
1939
1940 if (TDFX_IS_NAPALM(fxMesa)) {
1941 /* Remember, Glide has its texture units numbered in backward
1942 * order compared to OpenGL.
1943 */
1944 GLboolean hw1 = GL_TRUE, hw2 = GL_TRUE;
1945
1946 /* check if we really need to update glide unit 1 */
1947 if (1/*fxMesa->TexState.Enabled[0] != ctx->Texture.Unit[0]._ReallyEnabled ||
1948 envMode0 != fxMesa->TexState.EnvMode[1] ||
1949 envMode0 == GL_COMBINE_EXT ||
1950 baseImage0->Format != fxMesa->TexState.TexFormat[1] ||
1951 (fxMesa->Fallback & TDFX_FALLBACK_TEXTURE_ENV)*/) {
1952 hw1 = SetupTexEnvNapalm(ctx, GL_TRUE, &ctx->Texture.Unit[0],
1953 baseImage0->Format, &fxMesa->TexCombineExt[1]);
1954 #if 0/*JJJ*/
1955 fxMesa->TexState.EnvMode[1] = envMode0;
1956 fxMesa->TexState.TexFormat[1] = baseImage0->Format;
1957 fxMesa->TexState.Enabled[0] = ctx->Texture.Unit[0]._ReallyEnabled;
1958 #endif
1959 }
1960
1961 /* check if we really need to update glide unit 0 */
1962 if (1/*fxMesa->TexState.Enabled[1] != ctx->Texture.Unit[1]._ReallyEnabled ||
1963 envMode1 != fxMesa->TexState.EnvMode[0] ||
1964 envMode1 == GL_COMBINE_EXT ||
1965 baseImage1->Format != fxMesa->TexState.TexFormat[0] ||
1966 (fxMesa->Fallback & TDFX_FALLBACK_TEXTURE_ENV)*/) {
1967 hw2 = SetupTexEnvNapalm(ctx, GL_FALSE, &ctx->Texture.Unit[1],
1968 baseImage1->Format, &fxMesa->TexCombineExt[0]);
1969 #if 0/*JJJ*/
1970 fxMesa->TexState.EnvMode[0] = envMode1;
1971 fxMesa->TexState.TexFormat[0] = baseImage1->Format;
1972 fxMesa->TexState.Enabled[1] = ctx->Texture.Unit[1]._ReallyEnabled;
1973 #endif
1974 }
1975
1976
1977 if (!hw1 || !hw2) {
1978 FALLBACK(fxMesa, TDFX_FALLBACK_TEXTURE_ENV, GL_TRUE);
1979 }
1980 }
1981 else {
1982 int unit0, unit1;
1983 if ((ti0->whichTMU == TDFX_TMU1) || (ti1->whichTMU == TDFX_TMU0))
1984 unit0 = 1;
1985 else
1986 unit0 = 0;
1987 unit1 = 1 - unit0;
1988
1989 if (1/*fxMesa->TexState.Enabled[0] != ctx->Texture.Unit[0]._ReallyEnabled ||
1990 fxMesa->TexState.Enabled[1] != ctx->Texture.Unit[1]._ReallyEnabled ||
1991 envMode0 != fxMesa->TexState.EnvMode[unit0] ||
1992 envMode0 == GL_COMBINE_EXT ||
1993 envMode1 != fxMesa->TexState.EnvMode[unit1] ||
1994 envMode1 == GL_COMBINE_EXT ||
1995 baseImage0->Format != fxMesa->TexState.TexFormat[unit0] ||
1996 baseImage1->Format != fxMesa->TexState.TexFormat[unit1] ||
1997 (fxMesa->Fallback & TDFX_FALLBACK_TEXTURE_ENV)*/) {
1998
1999 if (!SetupDoubleTexEnvVoodoo3(ctx, unit0,
2000 ctx->Texture.Unit[0].EnvMode, baseImage0->Format,
2001 ctx->Texture.Unit[1].EnvMode, baseImage1->Format)) {
2002 FALLBACK(fxMesa, TDFX_FALLBACK_TEXTURE_ENV, GL_TRUE);
2003 }
2004
2005 #if 0/*JJJ*/
2006 fxMesa->TexState.EnvMode[unit0] = envMode0;
2007 fxMesa->TexState.TexFormat[unit0] = baseImage0->Format;
2008 fxMesa->TexState.EnvMode[unit1] = envMode1;
2009 fxMesa->TexState.TexFormat[unit1] = baseImage1->Format;
2010 fxMesa->TexState.Enabled[0] = ctx->Texture.Unit[0]._ReallyEnabled;
2011 fxMesa->TexState.Enabled[1] = ctx->Texture.Unit[1]._ReallyEnabled;
2012 #endif
2013 }
2014 }
2015 }
2016
2017
2018 void
2019 tdfxUpdateTextureState( GLcontext *ctx )
2020 {
2021 tdfxContextPtr fxMesa = TDFX_CONTEXT(ctx);
2022
2023 FALLBACK(fxMesa, TDFX_FALLBACK_TEXTURE_BORDER, GL_FALSE);
2024 FALLBACK(fxMesa, TDFX_FALLBACK_TEXTURE_ENV, GL_FALSE);
2025
2026 if (ctx->Texture.Unit[0]._ReallyEnabled & (TEXTURE_1D_BIT|TEXTURE_2D_BIT) &&
2027 ctx->Texture.Unit[1]._ReallyEnabled == 0) {
2028 LOCK_HARDWARE( fxMesa ); /* XXX remove locking eventually */
2029 setupTextureSingleTMU(ctx, 0);
2030 UNLOCK_HARDWARE( fxMesa );
2031 }
2032 else if (ctx->Texture.Unit[0]._ReallyEnabled == 0 &&
2033 ctx->Texture.Unit[1]._ReallyEnabled & (TEXTURE_1D_BIT|TEXTURE_2D_BIT)) {
2034 LOCK_HARDWARE( fxMesa );
2035 setupTextureSingleTMU(ctx, 1);
2036 UNLOCK_HARDWARE( fxMesa );
2037 }
2038 else if (ctx->Texture.Unit[0]._ReallyEnabled & (TEXTURE_1D_BIT|TEXTURE_2D_BIT) &&
2039 ctx->Texture.Unit[1]._ReallyEnabled & (TEXTURE_1D_BIT|TEXTURE_2D_BIT)) {
2040 LOCK_HARDWARE( fxMesa );
2041 setupTextureDoubleTMU(ctx);
2042 UNLOCK_HARDWARE( fxMesa );
2043 }
2044 else {
2045 /* disable hardware texturing */
2046 if (TDFX_IS_NAPALM(fxMesa)) {
2047 fxMesa->ColorCombineExt.SourceA = GR_CMBX_ITRGB;
2048 fxMesa->ColorCombineExt.ModeA = GR_FUNC_MODE_X;
2049 fxMesa->ColorCombineExt.SourceB = GR_CMBX_ZERO;
2050 fxMesa->ColorCombineExt.ModeB = GR_FUNC_MODE_ZERO;
2051 fxMesa->ColorCombineExt.SourceC = GR_CMBX_ZERO;
2052 fxMesa->ColorCombineExt.InvertC = FXTRUE;
2053 fxMesa->ColorCombineExt.SourceD = GR_CMBX_ZERO;
2054 fxMesa->ColorCombineExt.InvertD = FXFALSE;
2055 fxMesa->ColorCombineExt.Shift = 0;
2056 fxMesa->ColorCombineExt.Invert = FXFALSE;
2057 fxMesa->AlphaCombineExt.SourceA = GR_CMBX_ITALPHA;
2058 fxMesa->AlphaCombineExt.ModeA = GR_FUNC_MODE_X;
2059 fxMesa->AlphaCombineExt.SourceB = GR_CMBX_ZERO;
2060 fxMesa->AlphaCombineExt.ModeB = GR_FUNC_MODE_ZERO;
2061 fxMesa->AlphaCombineExt.SourceC = GR_CMBX_ZERO;
2062 fxMesa->AlphaCombineExt.InvertC = FXTRUE;
2063 fxMesa->AlphaCombineExt.SourceD = GR_CMBX_ZERO;
2064 fxMesa->AlphaCombineExt.InvertD = FXFALSE;
2065 fxMesa->AlphaCombineExt.Shift = 0;
2066 fxMesa->AlphaCombineExt.Invert = FXFALSE;
2067 }
2068 else {
2069 /* Voodoo 3*/
2070 fxMesa->ColorCombine.Function = GR_COMBINE_FUNCTION_LOCAL;
2071 fxMesa->ColorCombine.Factor = GR_COMBINE_FACTOR_NONE;
2072 fxMesa->ColorCombine.Local = GR_COMBINE_LOCAL_ITERATED;
2073 fxMesa->ColorCombine.Other = GR_COMBINE_OTHER_NONE;
2074 fxMesa->ColorCombine.Invert = FXFALSE;
2075 fxMesa->AlphaCombine.Function = GR_COMBINE_FUNCTION_LOCAL;
2076 fxMesa->AlphaCombine.Factor = GR_COMBINE_FACTOR_NONE;
2077 fxMesa->AlphaCombine.Local = GR_COMBINE_LOCAL_ITERATED;
2078 fxMesa->AlphaCombine.Other = GR_COMBINE_OTHER_NONE;
2079 fxMesa->AlphaCombine.Invert = FXFALSE;
2080 }
2081
2082 fxMesa->TexState.Enabled[0] = 0;
2083 fxMesa->TexState.Enabled[1] = 0;
2084 fxMesa->TexState.EnvMode[0] = 0;
2085 fxMesa->TexState.EnvMode[1] = 0;
2086
2087 fxMesa->dirty |= TDFX_UPLOAD_COLOR_COMBINE;
2088 fxMesa->dirty |= TDFX_UPLOAD_ALPHA_COMBINE;
2089
2090 if (ctx->Texture.Unit[0]._ReallyEnabled != 0 ||
2091 ctx->Texture.Unit[1]._ReallyEnabled != 0) {
2092 /* software texture (cube map, rect tex, etc */
2093 FALLBACK(fxMesa, TDFX_FALLBACK_TEXTURE_ENV, GL_TRUE);
2094 }
2095 }
2096 }
2097
2098
2099
2100 /*
2101 * This is a special case of texture state update.
2102 * It's used when we've simply bound a new texture to a texture
2103 * unit and the new texture has the exact same attributes as the
2104 * previously bound texture.
2105 * This is very common in Quake3.
2106 */
2107 void
2108 tdfxUpdateTextureBinding( GLcontext *ctx )
2109 {
2110 tdfxContextPtr fxMesa = TDFX_CONTEXT(ctx);
2111 struct gl_texture_object *tObj0 = ctx->Texture.Unit[0]._Current;
2112 struct gl_texture_object *tObj1 = ctx->Texture.Unit[1]._Current;
2113 tdfxTexInfo *ti0 = TDFX_TEXTURE_DATA(tObj0);
2114 tdfxTexInfo *ti1 = TDFX_TEXTURE_DATA(tObj1);
2115
2116 const struct gl_shared_state *mesaShared = fxMesa->glCtx->Shared;
2117 const struct tdfxSharedState *shared = (struct tdfxSharedState *) mesaShared->DriverData;
2118
2119 if (ti0) {
2120 fxMesa->sScale0 = ti0->sScale;
2121 fxMesa->tScale0 = ti0->tScale;
2122 if (ti0->info.format == GR_TEXFMT_P_8) {
2123 fxMesa->TexPalette.Type = ti0->paltype;
2124 fxMesa->TexPalette.Data = &(ti0->palette);
2125 fxMesa->dirty |= TDFX_UPLOAD_TEXTURE_PALETTE;
2126 }
2127 else if (ti1 && ti1->info.format == GR_TEXFMT_P_8) {
2128 fxMesa->TexPalette.Type = ti1->paltype;
2129 fxMesa->TexPalette.Data = &(ti1->palette);
2130 fxMesa->dirty |= TDFX_UPLOAD_TEXTURE_PALETTE;
2131 }
2132 }
2133 if (ti1) {
2134 fxMesa->sScale1 = ti1->sScale;
2135 fxMesa->tScale1 = ti1->tScale;
2136 }
2137
2138 if (ctx->Texture.Unit[0]._ReallyEnabled & (TEXTURE_1D_BIT|TEXTURE_2D_BIT) &&
2139 ctx->Texture.Unit[0]._ReallyEnabled == 0) {
2140 /* Only unit 0 2D enabled */
2141 if (shared->umaTexMemory) {
2142 fxMesa->TexSource[0].StartAddress = ti0->tm[0]->startAddr;
2143 fxMesa->TexSource[0].EvenOdd = GR_MIPMAPLEVELMASK_BOTH;
2144 fxMesa->TexSource[0].Info = &(ti0->info);
2145 }
2146 else {
2147 if (ti0->LODblend && ti0->whichTMU == TDFX_TMU_SPLIT) {
2148 fxMesa->TexSource[0].StartAddress = ti0->tm[TDFX_TMU0]->startAddr;
2149 fxMesa->TexSource[0].EvenOdd = GR_MIPMAPLEVELMASK_ODD;
2150 fxMesa->TexSource[0].Info = &(ti0->info);
2151 fxMesa->TexSource[1].StartAddress = ti0->tm[TDFX_TMU1]->startAddr;
2152 fxMesa->TexSource[1].EvenOdd = GR_MIPMAPLEVELMASK_EVEN;
2153 fxMesa->TexSource[1].Info = &(ti0->info);
2154 }
2155 else {
2156 FxU32 tmu;
2157 if (ti0->whichTMU == TDFX_TMU_BOTH)
2158 tmu = TDFX_TMU0;
2159 else
2160 tmu = ti0->whichTMU;
2161 fxMesa->TexSource[0].Info = NULL;
2162 fxMesa->TexSource[1].Info = NULL;
2163 if (ti0->tm[tmu]) {
2164 fxMesa->TexSource[tmu].StartAddress = ti0->tm[tmu]->startAddr;
2165 fxMesa->TexSource[tmu].EvenOdd = GR_MIPMAPLEVELMASK_BOTH;
2166 fxMesa->TexSource[tmu].Info = &(ti0->info);
2167 }
2168 }
2169 }
2170 }
2171 else if (ctx->Texture.Unit[0]._ReallyEnabled == 0 &&
2172 ctx->Texture.Unit[0]._ReallyEnabled & (TEXTURE_1D_BIT|TEXTURE_2D_BIT)) {
2173 /* Only unit 1 2D enabled */
2174 if (shared->umaTexMemory) {
2175 fxMesa->TexSource[0].StartAddress = ti1->tm[0]->startAddr;
2176 fxMesa->TexSource[0].EvenOdd = GR_MIPMAPLEVELMASK_BOTH;
2177 fxMesa->TexSource[0].Info = &(ti1->info);
2178 }
2179 }
2180 else if (ctx->Texture.Unit[0]._ReallyEnabled & (TEXTURE_1D_BIT|TEXTURE_2D_BIT) &&
2181 ctx->Texture.Unit[0]._ReallyEnabled & (TEXTURE_1D_BIT|TEXTURE_2D_BIT)) {
2182 /* Both 2D enabled */
2183 if (shared->umaTexMemory) {
2184 const FxU32 tmu0 = 0, tmu1 = 1;
2185 fxMesa->TexSource[tmu0].StartAddress = ti0->tm[0]->startAddr;
2186 fxMesa->TexSource[tmu0].EvenOdd = GR_MIPMAPLEVELMASK_BOTH;
2187 fxMesa->TexSource[tmu0].Info = &(ti0->info);
2188
2189 fxMesa->TexSource[tmu1].StartAddress = ti1->tm[0]->startAddr;
2190 fxMesa->TexSource[tmu1].EvenOdd = GR_MIPMAPLEVELMASK_BOTH;
2191 fxMesa->TexSource[tmu1].Info = &(ti1->info);
2192 }
2193 else {
2194 const FxU32 tmu0 = 0, tmu1 = 1;
2195 fxMesa->TexSource[tmu0].StartAddress = ti0->tm[tmu0]->startAddr;
2196 fxMesa->TexSource[tmu0].EvenOdd = GR_MIPMAPLEVELMASK_BOTH;
2197 fxMesa->TexSource[tmu0].Info = &(ti0->info);
2198
2199 fxMesa->TexSource[tmu1].StartAddress = ti1->tm[tmu1]->startAddr;
2200 fxMesa->TexSource[tmu1].EvenOdd = GR_MIPMAPLEVELMASK_BOTH;
2201 fxMesa->TexSource[tmu1].Info = &(ti1->info);
2202 }
2203 }
2204
2205
2206 fxMesa->dirty |= TDFX_UPLOAD_TEXTURE_SOURCE;
2207 }