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