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