Bring the texcombine fixes to the trunk.
[mesa.git] / src / mesa / drivers / dri / unichrome / via_texcombine.c
1 /*
2 * (C) Copyright IBM Corporation 2004
3 * All Rights Reserved.
4 *
5 * Permission is hereby granted, free of charge, to any person obtaining a
6 * copy of this software and associated documentation files (the "Software"),
7 * to deal in the Software without restriction, including without limitation
8 * on the rights to use, copy, modify, merge, publish, distribute, sub
9 * license, and/or sell copies of the Software, and to permit persons to whom
10 * the Software is furnished to do so, subject to the following conditions:
11 *
12 * The above copyright notice and this permission notice (including the next
13 * paragraph) shall be included in all copies or substantial portions of the
14 * Software.
15 *
16 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
17 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
18 * FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT. IN NO EVENT SHALL
19 * IBM AND/OR THEIR SUPPLIERS BE LIABLE FOR ANY CLAIM,
20 * DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR
21 * OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE
22 * USE OR OTHER DEALINGS IN THE SOFTWARE.
23 */
24
25 /**
26 * \file via_texcombine.c
27 * Calculate texture combine hardware state.
28 *
29 * \author Ian Romanick <idr@us.ibm.com>
30 */
31
32 #include <stdio.h>
33
34 #include "glheader.h"
35 #include "context.h"
36 #include "macros.h"
37 #include "colormac.h"
38 #include "enums.h"
39 #include "dd.h"
40
41 #include "mm.h"
42 #include "via_context.h"
43 #include "via_state.h"
44 #include "via_tex.h"
45 #include "via_tris.h"
46 #include "via_ioctl.h"
47
48 #include "swrast/swrast.h"
49 #include "array_cache/acache.h"
50 #include "tnl/tnl.h"
51 #include "swrast_setup/swrast_setup.h"
52
53 #include "tnl/t_pipeline.h"
54
55 #define VIA_USE_ALPHA (HC_XTC_Adif - HC_XTC_Dif)
56
57 #define INPUT_A_SHIFT 14
58 #define INPUT_B_SHIFT 7
59 #define INPUT_C_SHIFT 0
60 #define INPUT_CBias_SHIFT 14
61
62 #define CONST_ONE (HC_XTC_0 | HC_XTC_InvTOPC)
63
64 static const unsigned color_operand_modifier[4] = {
65 0,
66 HC_XTC_InvTOPC,
67 VIA_USE_ALPHA,
68 VIA_USE_ALPHA | HC_XTC_InvTOPC,
69 };
70
71 static const unsigned alpha_operand_modifier[2] = {
72 0, HC_XTA_InvTOPA
73 };
74
75 static const unsigned bias_alpha_operand_modifier[2] = {
76 0, HC_HTXnTBLAbias_Inv
77 };
78
79
80 static const unsigned c_shift_table[3] = {
81 HC_HTXnTBLCshift_No, HC_HTXnTBLCshift_1, HC_HTXnTBLCshift_2
82 };
83
84 static const unsigned a_shift_table[3] = {
85 HC_HTXnTBLAshift_No, HC_HTXnTBLAshift_1, HC_HTXnTBLAshift_2
86 };
87
88
89 /**
90 * Calculate the hardware state for the specified texture combine mode
91 *
92 * \bug
93 * For the alpha combine, \c GL_CONSTANT is still probably wrong.
94 *
95 * \bug
96 * All forms of DOT3 bumpmapping are completely untested, and are most
97 * likely wrong.
98 *
99 * \bug
100 * This code still fails progs/demos/texenv for all modes with \c GL_ALPHA
101 * textures. This was also the case with the code that Via supplied. It
102 * also fails for \c GL_REPLACE with \c GL_RGBA textures. Everything else
103 * that texenv tests looks good.
104 *
105 * \bug
106 * KW: needs attention to the case where texunit 1 is enabled but
107 * texunit 0 is not.
108 */
109 GLboolean
110 viaTexCombineState( viaContextPtr vmesa,
111 const struct gl_tex_env_combine_state * combine,
112 unsigned unit )
113 {
114 unsigned color_arg[3];
115 unsigned alpha_arg[3];
116 unsigned bias_alpha_arg[3];
117 unsigned color = HC_HTXnTBLCsat_MASK;
118 unsigned alpha = HC_HTXnTBLAsat_MASK;
119 unsigned bias = 0;
120 unsigned op = 0;
121 unsigned a_shift = combine->ScaleShiftA;
122 unsigned c_shift = combine->ScaleShiftRGB;
123 unsigned i;
124 unsigned constant_color[3];
125 unsigned ordered_constant_color[4];
126 unsigned constant_alpha[3];
127 unsigned bias_alpha = 0;
128 unsigned abc_alpha = 0;
129 const struct gl_texture_unit const * texUnit = & vmesa->glCtx->Texture.Unit[unit];
130 unsigned env_color[4];
131
132 /* It seems that the color clamping can be overwhelmed at the 4x
133 * scale settings, necessitating this fallback:
134 */
135 if (c_shift == 2 || a_shift == 2) {
136 return GL_FALSE;
137 }
138
139 CLAMPED_FLOAT_TO_UBYTE(env_color[0], texUnit->EnvColor[0]);
140 CLAMPED_FLOAT_TO_UBYTE(env_color[1], texUnit->EnvColor[1]);
141 CLAMPED_FLOAT_TO_UBYTE(env_color[2], texUnit->EnvColor[2]);
142 CLAMPED_FLOAT_TO_UBYTE(env_color[3], texUnit->EnvColor[3]);
143
144 (void) memset( constant_color, 0, sizeof( constant_color ) );
145 (void) memset( ordered_constant_color, 0, sizeof( ordered_constant_color ) );
146 (void) memset( constant_alpha, 0, sizeof( constant_alpha ) );
147
148 for ( i = 0 ; i < combine->_NumArgsRGB ; i++ ) {
149 const GLint op = combine->OperandRGB[i] - GL_SRC_COLOR;
150
151 switch ( combine->SourceRGB[i] ) {
152 case GL_TEXTURE:
153 color_arg[i] = HC_XTC_Tex;
154 color_arg[i] += color_operand_modifier[op];
155 break;
156 case GL_CONSTANT:
157 color_arg[i] = HC_XTC_HTXnTBLRC;
158
159 switch( op ) {
160 case 0: /* GL_SRC_COLOR */
161 constant_color[i] = ((env_color[0] << 16) |
162 (env_color[1] << 8) |
163 env_color[2]);
164 break;
165 case 1: /* GL_ONE_MINUS_SRC_COLOR */
166 constant_color[i] = ~((env_color[0] << 16) |
167 (env_color[1] << 8) |
168 env_color[2]) & 0x00ffffff;
169 break;
170 case 2: /* GL_SRC_ALPHA */
171 constant_color[i] = ((env_color[3] << 16) |
172 (env_color[3] << 8) |
173 env_color[3]);
174 break;
175 case 3: /* GL_ONE_MINUS_SRC_ALPHA */
176 constant_color[i] = ~((env_color[3] << 16) |
177 (env_color[3] << 8) |
178 env_color[3]) & 0x00ffffff;
179 break;
180 }
181 break;
182 case GL_PRIMARY_COLOR:
183 color_arg[i] = HC_XTC_Dif;
184 color_arg[i] += color_operand_modifier[op];
185 break;
186 case GL_PREVIOUS:
187 color_arg[i] = (unit == 0) ? HC_XTC_Dif : HC_XTC_Cur;
188 color_arg[i] += color_operand_modifier[op];
189 break;
190 }
191 }
192
193
194 /* On the Unichrome, all combine operations take on some form of:
195 *
196 * (xA * (xB op xC) + xBias) << xShift
197 *
198 * 'op' can be selected as add, subtract, min, max, or mask. The min, max
199 * and mask modes are currently unused. With the exception of DOT3, all
200 * standard GL_COMBINE modes can be implemented simply by selecting the
201 * correct inputs for A, B, C, and Bias and the correct operation for op.
202 *
203 * NOTE: xBias (when read from the constant registers) is signed,
204 * and scaled to fit -255..255 in 8 bits, ie 0x1 == 2.
205 */
206
207 switch( combine->ModeRGB ) {
208 /* Ca = 1.0, Cb = arg0, Cc = 0, Cbias = 0
209 */
210 case GL_REPLACE:
211 color |= ((CONST_ONE << INPUT_A_SHIFT) |
212 (color_arg[0] << INPUT_B_SHIFT));
213
214 ordered_constant_color[1] = constant_color[0];
215 break;
216
217 /* Ca = arg[0], Cb = arg[1], Cc = 0, Cbias = 0
218 */
219 case GL_MODULATE:
220 color |= ((color_arg[0] << INPUT_A_SHIFT) |
221 (color_arg[1] << INPUT_B_SHIFT));
222
223 ordered_constant_color[0] = constant_color[0];
224 ordered_constant_color[1] = constant_color[1];
225 break;
226
227 /* Ca = 1.0, Cb = arg[0], Cc = arg[1], Cbias = 0
228 */
229 case GL_ADD:
230 case GL_SUBTRACT:
231 if ( combine->ModeRGB == GL_SUBTRACT ) {
232 op |= HC_HTXnTBLCop_Sub;
233 }
234
235 color |= ((CONST_ONE << INPUT_A_SHIFT) |
236 (color_arg[0] << INPUT_B_SHIFT) |
237 (color_arg[1] << INPUT_C_SHIFT));
238
239 ordered_constant_color[1] = constant_color[0];
240 ordered_constant_color[2] = constant_color[1];
241 break;
242
243 /* Ca = 1.0, Cb = arg[0], Cc = arg[1], Cbias = -0.5
244 */
245 case GL_ADD_SIGNED:
246 color |= ((CONST_ONE << INPUT_A_SHIFT) |
247 (color_arg[0] << INPUT_B_SHIFT) |
248 (color_arg[1] << INPUT_C_SHIFT));
249
250 bias |= HC_HTXnTBLCbias_HTXnTBLRC;
251
252 ordered_constant_color[1] = constant_color[0];
253 ordered_constant_color[2] = constant_color[1];
254 ordered_constant_color[3] = 0x00bfbfbf; /* -.5 */
255 break;
256
257 /* Ca = arg[2], Cb = arg[0], Cc = arg[1], Cbias = arg[1]
258 */
259 case GL_INTERPOLATE:
260 op |= HC_HTXnTBLCop_Sub;
261
262 color |= ((color_arg[2] << INPUT_A_SHIFT) |
263 (color_arg[0] << INPUT_B_SHIFT) |
264 (color_arg[1] << INPUT_C_SHIFT));
265
266 bias |= (color_arg[1] << INPUT_CBias_SHIFT);
267
268 ordered_constant_color[0] = constant_color[2];
269 ordered_constant_color[1] = constant_color[0];
270 ordered_constant_color[2] = constant_color[1];
271 ordered_constant_color[3] = (constant_color[1] >> 1) & 0x7f7f7f;
272 break;
273
274 #if 0
275 /* At this point this code is completely untested. It appears that the
276 * Unichrome has the same limitation as the Radeon R100. The only
277 * supported post-scale when doing DOT3 bumpmapping is 1x.
278 */
279 case GL_DOT3_RGB_EXT:
280 case GL_DOT3_RGBA_EXT:
281 case GL_DOT3_RGB:
282 case GL_DOT3_RGBA:
283 c_shift = 2;
284 a_shift = 2;
285 color |= ((color_arg[0] << INPUT_A_SHIFT) |
286 (color_arg[1] << INPUT_B_SHIFT));
287 op |= HC_HTXnTBLDOT4;
288 break;
289 #endif
290
291 default:
292 assert(0);
293 break;
294 }
295
296
297
298
299 /* The alpha blend stage has the annoying quirk of not having a
300 * hard-wired 0 input, like the color stage. As a result, we have
301 * to program the constant register with 0 and use that as our
302 * 0 input.
303 *
304 * (xA * (xB op xC) + xBias) << xShift
305 *
306 */
307
308 for ( i = 0 ; i < combine->_NumArgsA ; i++ ) {
309 const GLint op = combine->OperandA[i] - GL_SRC_ALPHA;
310
311 switch ( combine->SourceA[i] ) {
312 case GL_TEXTURE:
313 alpha_arg[i] = HC_XTA_Atex;
314 alpha_arg[i] += alpha_operand_modifier[op];
315 bias_alpha_arg[i] = HC_HTXnTBLAbias_Atex;
316 bias_alpha_arg[i] += bias_alpha_operand_modifier[op];
317 break;
318 case GL_CONSTANT:
319 alpha_arg[i] = HC_XTA_HTXnTBLRA;
320 bias_alpha_arg[i] = HC_HTXnTBLAbias_HTXnTBLRAbias;
321 constant_alpha[i] = (op == 0) ? env_color[3] : (~env_color[3] & 0xff);
322 break;
323 case GL_PRIMARY_COLOR:
324 alpha_arg[i] = HC_XTA_Adif;
325 alpha_arg[i] += alpha_operand_modifier[op];
326 bias_alpha_arg[i] = HC_HTXnTBLAbias_Adif;
327 bias_alpha_arg[i] += bias_alpha_operand_modifier[op];
328 break;
329 case GL_PREVIOUS:
330 alpha_arg[i] = (unit == 0) ? HC_XTA_Adif : HC_XTA_Acur;
331 alpha_arg[i] += alpha_operand_modifier[op];
332 bias_alpha_arg[i] = (unit == 0) ? HC_HTXnTBLAbias_Adif : HC_HTXnTBLAbias_Acur;
333 bias_alpha_arg[i] += bias_alpha_operand_modifier[op];
334 break;
335 }
336 }
337
338 switch( combine->ModeA ) {
339 /* Aa = 0, Ab = 0, Ac = 0, Abias = arg0
340 */
341 case GL_REPLACE:
342 alpha |= ((HC_XTA_HTXnTBLRA << INPUT_A_SHIFT) |
343 (HC_XTA_HTXnTBLRA << INPUT_B_SHIFT) |
344 (HC_XTA_HTXnTBLRA << INPUT_C_SHIFT));
345 abc_alpha = 0;
346
347 bias |= bias_alpha_arg[0];
348 bias_alpha = constant_alpha[0] >> 1;
349 break;
350
351 /* Aa = arg[0], Ab = arg[1], Ac = 0, Abias = 0
352 */
353 case GL_MODULATE:
354 alpha |= ((alpha_arg[1] << INPUT_A_SHIFT) |
355 (alpha_arg[0] << INPUT_B_SHIFT) |
356 (HC_XTA_HTXnTBLRA << INPUT_C_SHIFT));
357
358 abc_alpha = ((constant_alpha[1] << HC_HTXnTBLRAa_SHIFT) |
359 (constant_alpha[0] << HC_HTXnTBLRAb_SHIFT) |
360 (0 << HC_HTXnTBLRAc_SHIFT));
361
362 bias |= HC_HTXnTBLAbias_HTXnTBLRAbias;
363 bias_alpha = 0;
364 break;
365
366 /* Aa = 1.0, Ab = arg[0], Ac = arg[1], Abias = 0
367 */
368 case GL_ADD:
369 case GL_SUBTRACT:
370 if ( combine->ModeA == GL_SUBTRACT ) {
371 op |= HC_HTXnTBLAop_Sub;
372 }
373
374 alpha |= ((HC_XTA_HTXnTBLRA << INPUT_A_SHIFT) |
375 (alpha_arg[0] << INPUT_B_SHIFT) |
376 (alpha_arg[1] << INPUT_C_SHIFT));
377
378 abc_alpha = ((0xff << HC_HTXnTBLRAa_SHIFT) |
379 (constant_alpha[0] << HC_HTXnTBLRAb_SHIFT) |
380 (constant_alpha[1] << HC_HTXnTBLRAc_SHIFT));
381
382 bias |= HC_HTXnTBLAbias_HTXnTBLRAbias;
383 bias_alpha = 0;
384 break;
385
386 /* Aa = 1.0, Ab = arg[0], Ac = arg[1], Abias = -0.5
387 */
388 case GL_ADD_SIGNED:
389 alpha |= ((HC_XTA_HTXnTBLRA << INPUT_A_SHIFT) |
390 (alpha_arg[0] << INPUT_B_SHIFT) |
391 (alpha_arg[1] << INPUT_C_SHIFT));
392 abc_alpha = ((0xff << HC_HTXnTBLRAa_SHIFT) |
393 (constant_alpha[0] << HC_HTXnTBLRAb_SHIFT) |
394 (constant_alpha[1] << HC_HTXnTBLRAc_SHIFT));
395
396 bias |= HC_HTXnTBLAbias_HTXnTBLRAbias;
397 bias_alpha = 0xbf;
398 break;
399
400 /* Aa = arg[2], Ab = arg[0], Ac = arg[1], Abias = arg[1]
401 */
402 case GL_INTERPOLATE:
403 op |= HC_HTXnTBLAop_Sub;
404
405 alpha |= ((alpha_arg[2] << INPUT_A_SHIFT) |
406 (alpha_arg[0] << INPUT_B_SHIFT) |
407 (alpha_arg[1] << INPUT_C_SHIFT));
408 abc_alpha = ((constant_alpha[2] << HC_HTXnTBLRAa_SHIFT) |
409 (constant_alpha[0] << HC_HTXnTBLRAb_SHIFT) |
410 (constant_alpha[1] << HC_HTXnTBLRAc_SHIFT));
411
412 bias |= bias_alpha_arg[1];
413 bias_alpha = constant_alpha[1] >> 1;
414 break;
415 }
416
417
418 op |= c_shift_table[ c_shift ] | a_shift_table[ a_shift ];
419
420
421 if ( unit == 0 ) {
422 vmesa->regHTXnTBLMPfog_0 = HC_HTXnTBLMPfog_Fog;
423
424 vmesa->regHTXnTBLCsat_0 = color;
425 vmesa->regHTXnTBLAsat_0 = alpha;
426 vmesa->regHTXnTBLCop_0 = op | bias;
427 vmesa->regHTXnTBLRAa_0 = abc_alpha;
428 vmesa->regHTXnTBLRFog_0 = bias_alpha;
429
430 vmesa->regHTXnTBLRCa_0 = ordered_constant_color[0];
431 vmesa->regHTXnTBLRCb_0 = ordered_constant_color[1];
432 vmesa->regHTXnTBLRCc_0 = ordered_constant_color[2];
433 vmesa->regHTXnTBLRCbias_0 = ordered_constant_color[3];
434 }
435 else {
436 vmesa->regHTXnTBLMPfog_1 = HC_HTXnTBLMPfog_Fog;
437
438 vmesa->regHTXnTBLCsat_1 = color;
439 vmesa->regHTXnTBLAsat_1 = alpha;
440 vmesa->regHTXnTBLCop_1 = op | bias;
441 vmesa->regHTXnTBLRAa_1 = abc_alpha;
442 vmesa->regHTXnTBLRFog_1 = bias_alpha;
443
444 vmesa->regHTXnTBLRCa_1 = ordered_constant_color[0];
445 vmesa->regHTXnTBLRCb_1 = ordered_constant_color[1];
446 vmesa->regHTXnTBLRCc_1 = ordered_constant_color[2];
447 vmesa->regHTXnTBLRCbias_1 = ordered_constant_color[3];
448 }
449
450 return GL_TRUE;
451 }
452