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