Merge commit 'origin/gallium-0.1'
[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 "main/glheader.h"
35 #include "main/context.h"
36 #include "main/macros.h"
37 #include "main/colormac.h"
38 #include "main/enums.h"
39
40 #include "via_context.h"
41 #include "via_state.h"
42 #include "via_tex.h"
43 #include "via_3d_reg.h"
44
45
46 #define VIA_USE_ALPHA (HC_XTC_Adif - HC_XTC_Dif)
47
48 #define INPUT_A_SHIFT 14
49 #define INPUT_B_SHIFT 7
50 #define INPUT_C_SHIFT 0
51 #define INPUT_CBias_SHIFT 14
52
53 #define CONST_ONE (HC_XTC_0 | HC_XTC_InvTOPC)
54
55 static const unsigned color_operand_modifier[4] = {
56 0,
57 HC_XTC_InvTOPC,
58 VIA_USE_ALPHA,
59 VIA_USE_ALPHA | HC_XTC_InvTOPC,
60 };
61
62 static const unsigned alpha_operand_modifier[2] = {
63 0, HC_XTA_InvTOPA
64 };
65
66 static const unsigned bias_alpha_operand_modifier[2] = {
67 0, HC_HTXnTBLAbias_Inv
68 };
69
70
71 static const unsigned c_shift_table[3] = {
72 HC_HTXnTBLCshift_No, HC_HTXnTBLCshift_1, HC_HTXnTBLCshift_2
73 };
74
75 static const unsigned a_shift_table[3] = {
76 HC_HTXnTBLAshift_No, HC_HTXnTBLAshift_1, HC_HTXnTBLAshift_2
77 };
78
79
80 /**
81 * Calculate the hardware state for the specified texture combine mode
82 *
83 * \bug
84 * All forms of DOT3 bumpmapping are completely untested, and are most
85 * likely wrong. KW: Looks like it will never be quite right as the
86 * hardware seems to experience overflow in color calculation at the
87 * 4x shift levels, which need to be programed for DOT3. Maybe newer
88 * hardware fixes these issues.
89 *
90 * \bug
91 * KW: needs attention to the case where texunit 1 is enabled but
92 * texunit 0 is not.
93 */
94 GLboolean
95 viaTexCombineState( struct via_context *vmesa,
96 const struct gl_tex_env_combine_state * combine,
97 unsigned unit )
98 {
99 unsigned color_arg[3];
100 unsigned alpha_arg[3];
101 unsigned bias_alpha_arg[3];
102 unsigned color = HC_HTXnTBLCsat_MASK;
103 unsigned alpha = HC_HTXnTBLAsat_MASK;
104 unsigned bias = 0;
105 unsigned op = 0;
106 unsigned a_shift = combine->ScaleShiftA;
107 unsigned c_shift = combine->ScaleShiftRGB;
108 unsigned i;
109 unsigned constant_color[3];
110 unsigned ordered_constant_color[4];
111 unsigned constant_alpha[3];
112 unsigned bias_alpha = 0;
113 unsigned abc_alpha = 0;
114 const struct gl_texture_unit * texUnit =
115 &vmesa->glCtx->Texture.Unit[unit];
116 unsigned env_color[4];
117
118 /* It seems that the color clamping can be overwhelmed at the 4x
119 * scale settings, necessitating this fallback:
120 */
121 if (c_shift == 2 || a_shift == 2) {
122 return GL_FALSE;
123 }
124
125 CLAMPED_FLOAT_TO_UBYTE(env_color[0], texUnit->EnvColor[0]);
126 CLAMPED_FLOAT_TO_UBYTE(env_color[1], texUnit->EnvColor[1]);
127 CLAMPED_FLOAT_TO_UBYTE(env_color[2], texUnit->EnvColor[2]);
128 CLAMPED_FLOAT_TO_UBYTE(env_color[3], texUnit->EnvColor[3]);
129
130 (void) memset( constant_color, 0, sizeof( constant_color ) );
131 (void) memset( ordered_constant_color, 0, sizeof( ordered_constant_color ) );
132 (void) memset( constant_alpha, 0, sizeof( constant_alpha ) );
133
134 for ( i = 0 ; i < combine->_NumArgsRGB ; i++ ) {
135 const GLint op = combine->OperandRGB[i] - GL_SRC_COLOR;
136
137 switch ( combine->SourceRGB[i] ) {
138 case GL_TEXTURE:
139 color_arg[i] = HC_XTC_Tex;
140 color_arg[i] += color_operand_modifier[op];
141 break;
142 case GL_CONSTANT:
143 color_arg[i] = HC_XTC_HTXnTBLRC;
144
145 switch( op ) {
146 case 0: /* GL_SRC_COLOR */
147 constant_color[i] = ((env_color[0] << 16) |
148 (env_color[1] << 8) |
149 env_color[2]);
150 break;
151 case 1: /* GL_ONE_MINUS_SRC_COLOR */
152 constant_color[i] = ~((env_color[0] << 16) |
153 (env_color[1] << 8) |
154 env_color[2]) & 0x00ffffff;
155 break;
156 case 2: /* GL_SRC_ALPHA */
157 constant_color[i] = ((env_color[3] << 16) |
158 (env_color[3] << 8) |
159 env_color[3]);
160 break;
161 case 3: /* GL_ONE_MINUS_SRC_ALPHA */
162 constant_color[i] = ~((env_color[3] << 16) |
163 (env_color[3] << 8) |
164 env_color[3]) & 0x00ffffff;
165 break;
166 }
167 break;
168 case GL_PRIMARY_COLOR:
169 color_arg[i] = HC_XTC_Dif;
170 color_arg[i] += color_operand_modifier[op];
171 break;
172 case GL_PREVIOUS:
173 color_arg[i] = (unit == 0) ? HC_XTC_Dif : HC_XTC_Cur;
174 color_arg[i] += color_operand_modifier[op];
175 break;
176 }
177 }
178
179
180 /* On the Unichrome, all combine operations take on some form of:
181 *
182 * (xA * (xB op xC) + xBias) << xShift
183 *
184 * 'op' can be selected as add, subtract, min, max, or mask. The min, max
185 * and mask modes are currently unused. With the exception of DOT3, all
186 * standard GL_COMBINE modes can be implemented simply by selecting the
187 * correct inputs for A, B, C, and Bias and the correct operation for op.
188 *
189 * NOTE: xBias (when read from the constant registers) is signed,
190 * and scaled to fit -255..255 in 8 bits, ie 0x1 == 2.
191 */
192
193 switch( combine->ModeRGB ) {
194 /* Ca = 1.0, Cb = arg0, Cc = 0, Cbias = 0
195 */
196 case GL_REPLACE:
197 color |= ((CONST_ONE << INPUT_A_SHIFT) |
198 (color_arg[0] << INPUT_B_SHIFT));
199
200 ordered_constant_color[1] = constant_color[0];
201 break;
202
203 /* Ca = arg[0], Cb = arg[1], Cc = 0, Cbias = 0
204 */
205 case GL_MODULATE:
206 color |= ((color_arg[0] << INPUT_A_SHIFT) |
207 (color_arg[1] << INPUT_B_SHIFT));
208
209 ordered_constant_color[0] = constant_color[0];
210 ordered_constant_color[1] = constant_color[1];
211 break;
212
213 /* Ca = 1.0, Cb = arg[0], Cc = arg[1], Cbias = 0
214 */
215 case GL_ADD:
216 case GL_SUBTRACT:
217 if ( combine->ModeRGB == GL_SUBTRACT ) {
218 op |= HC_HTXnTBLCop_Sub;
219 }
220
221 color |= ((CONST_ONE << INPUT_A_SHIFT) |
222 (color_arg[0] << INPUT_B_SHIFT) |
223 (color_arg[1] << INPUT_C_SHIFT));
224
225 ordered_constant_color[1] = constant_color[0];
226 ordered_constant_color[2] = constant_color[1];
227 break;
228
229 /* Ca = 1.0, Cb = arg[0], Cc = arg[1], Cbias = -0.5
230 */
231 case GL_ADD_SIGNED:
232 color |= ((CONST_ONE << INPUT_A_SHIFT) |
233 (color_arg[0] << INPUT_B_SHIFT) |
234 (color_arg[1] << INPUT_C_SHIFT));
235
236 bias |= HC_HTXnTBLCbias_HTXnTBLRC;
237
238 ordered_constant_color[1] = constant_color[0];
239 ordered_constant_color[2] = constant_color[1];
240 ordered_constant_color[3] = 0x00bfbfbf; /* -.5 */
241 break;
242
243 /* Ca = arg[2], Cb = arg[0], Cc = arg[1], Cbias = arg[1]
244 */
245 case GL_INTERPOLATE:
246 op |= HC_HTXnTBLCop_Sub;
247
248 color |= ((color_arg[2] << INPUT_A_SHIFT) |
249 (color_arg[0] << INPUT_B_SHIFT) |
250 (color_arg[1] << INPUT_C_SHIFT));
251
252 bias |= (color_arg[1] << INPUT_CBias_SHIFT);
253
254 ordered_constant_color[0] = constant_color[2];
255 ordered_constant_color[1] = constant_color[0];
256 ordered_constant_color[2] = constant_color[1];
257 ordered_constant_color[3] = (constant_color[1] >> 1) & 0x7f7f7f;
258 break;
259
260 #if 0
261 /* At this point this code is completely untested. It appears that the
262 * Unichrome has the same limitation as the Radeon R100. The only
263 * supported post-scale when doing DOT3 bumpmapping is 1x.
264 */
265 case GL_DOT3_RGB_EXT:
266 case GL_DOT3_RGBA_EXT:
267 case GL_DOT3_RGB:
268 case GL_DOT3_RGBA:
269 c_shift = 2;
270 a_shift = 2;
271 color |= ((color_arg[0] << INPUT_A_SHIFT) |
272 (color_arg[1] << INPUT_B_SHIFT));
273 op |= HC_HTXnTBLDOT4;
274 break;
275 #endif
276
277 default:
278 assert(0);
279 break;
280 }
281
282
283
284
285 /* The alpha blend stage has the annoying quirk of not having a
286 * hard-wired 0 input, like the color stage. As a result, we have
287 * to program the constant register with 0 and use that as our
288 * 0 input.
289 *
290 * (xA * (xB op xC) + xBias) << xShift
291 *
292 */
293
294 for ( i = 0 ; i < combine->_NumArgsA ; i++ ) {
295 const GLint op = combine->OperandA[i] - GL_SRC_ALPHA;
296
297 switch ( combine->SourceA[i] ) {
298 case GL_TEXTURE:
299 alpha_arg[i] = HC_XTA_Atex;
300 alpha_arg[i] += alpha_operand_modifier[op];
301 bias_alpha_arg[i] = HC_HTXnTBLAbias_Atex;
302 bias_alpha_arg[i] += bias_alpha_operand_modifier[op];
303 break;
304 case GL_CONSTANT:
305 alpha_arg[i] = HC_XTA_HTXnTBLRA;
306 bias_alpha_arg[i] = HC_HTXnTBLAbias_HTXnTBLRAbias;
307 constant_alpha[i] = (op == 0) ? env_color[3] : (~env_color[3] & 0xff);
308 break;
309 case GL_PRIMARY_COLOR:
310 alpha_arg[i] = HC_XTA_Adif;
311 alpha_arg[i] += alpha_operand_modifier[op];
312 bias_alpha_arg[i] = HC_HTXnTBLAbias_Adif;
313 bias_alpha_arg[i] += bias_alpha_operand_modifier[op];
314 break;
315 case GL_PREVIOUS:
316 alpha_arg[i] = (unit == 0) ? HC_XTA_Adif : HC_XTA_Acur;
317 alpha_arg[i] += alpha_operand_modifier[op];
318 bias_alpha_arg[i] = (unit == 0 ?
319 HC_HTXnTBLAbias_Adif :
320 HC_HTXnTBLAbias_Acur);
321 bias_alpha_arg[i] += bias_alpha_operand_modifier[op];
322 break;
323 }
324 }
325
326 switch( combine->ModeA ) {
327 /* Aa = 0, Ab = 0, Ac = 0, Abias = arg0
328 */
329 case GL_REPLACE:
330 alpha |= ((HC_XTA_HTXnTBLRA << INPUT_A_SHIFT) |
331 (HC_XTA_HTXnTBLRA << INPUT_B_SHIFT) |
332 (HC_XTA_HTXnTBLRA << INPUT_C_SHIFT));
333 abc_alpha = 0;
334
335 bias |= bias_alpha_arg[0];
336 bias_alpha = constant_alpha[0] >> 1;
337 break;
338
339 /* Aa = arg[0], Ab = arg[1], Ac = 0, Abias = 0
340 */
341 case GL_MODULATE:
342 alpha |= ((alpha_arg[1] << INPUT_A_SHIFT) |
343 (alpha_arg[0] << INPUT_B_SHIFT) |
344 (HC_XTA_HTXnTBLRA << INPUT_C_SHIFT));
345
346 abc_alpha = ((constant_alpha[1] << HC_HTXnTBLRAa_SHIFT) |
347 (constant_alpha[0] << HC_HTXnTBLRAb_SHIFT) |
348 (0 << HC_HTXnTBLRAc_SHIFT));
349
350 bias |= HC_HTXnTBLAbias_HTXnTBLRAbias;
351 bias_alpha = 0;
352 break;
353
354 /* Aa = 1.0, Ab = arg[0], Ac = arg[1], Abias = 0
355 */
356 case GL_ADD:
357 case GL_SUBTRACT:
358 if ( combine->ModeA == GL_SUBTRACT ) {
359 op |= HC_HTXnTBLAop_Sub;
360 }
361
362 alpha |= ((HC_XTA_HTXnTBLRA << INPUT_A_SHIFT) |
363 (alpha_arg[0] << INPUT_B_SHIFT) |
364 (alpha_arg[1] << INPUT_C_SHIFT));
365
366 abc_alpha = ((0xff << HC_HTXnTBLRAa_SHIFT) |
367 (constant_alpha[0] << HC_HTXnTBLRAb_SHIFT) |
368 (constant_alpha[1] << HC_HTXnTBLRAc_SHIFT));
369
370 bias |= HC_HTXnTBLAbias_HTXnTBLRAbias;
371 bias_alpha = 0;
372 break;
373
374 /* Aa = 1.0, Ab = arg[0], Ac = arg[1], Abias = -0.5
375 */
376 case GL_ADD_SIGNED:
377 alpha |= ((HC_XTA_HTXnTBLRA << INPUT_A_SHIFT) |
378 (alpha_arg[0] << INPUT_B_SHIFT) |
379 (alpha_arg[1] << INPUT_C_SHIFT));
380 abc_alpha = ((0xff << HC_HTXnTBLRAa_SHIFT) |
381 (constant_alpha[0] << HC_HTXnTBLRAb_SHIFT) |
382 (constant_alpha[1] << HC_HTXnTBLRAc_SHIFT));
383
384 bias |= HC_HTXnTBLAbias_HTXnTBLRAbias;
385 bias_alpha = 0xbf;
386 break;
387
388 /* Aa = arg[2], Ab = arg[0], Ac = arg[1], Abias = arg[1]
389 */
390 case GL_INTERPOLATE:
391 op |= HC_HTXnTBLAop_Sub;
392
393 alpha |= ((alpha_arg[2] << INPUT_A_SHIFT) |
394 (alpha_arg[0] << INPUT_B_SHIFT) |
395 (alpha_arg[1] << INPUT_C_SHIFT));
396 abc_alpha = ((constant_alpha[2] << HC_HTXnTBLRAa_SHIFT) |
397 (constant_alpha[0] << HC_HTXnTBLRAb_SHIFT) |
398 (constant_alpha[1] << HC_HTXnTBLRAc_SHIFT));
399
400 bias |= bias_alpha_arg[1];
401 bias_alpha = constant_alpha[1] >> 1;
402 break;
403 }
404
405
406 op |= c_shift_table[ c_shift ] | a_shift_table[ a_shift ];
407
408
409 vmesa->regHTXnTBLMPfog[unit] = HC_HTXnTBLMPfog_Fog;
410
411 vmesa->regHTXnTBLCsat[unit] = color;
412 vmesa->regHTXnTBLAsat[unit] = alpha;
413 vmesa->regHTXnTBLCop[unit] = op | bias;
414 vmesa->regHTXnTBLRAa[unit] = abc_alpha;
415 vmesa->regHTXnTBLRFog[unit] = bias_alpha;
416
417 vmesa->regHTXnTBLRCa[unit] = ordered_constant_color[0];
418 vmesa->regHTXnTBLRCb[unit] = ordered_constant_color[1];
419 vmesa->regHTXnTBLRCc[unit] = ordered_constant_color[2];
420 vmesa->regHTXnTBLRCbias[unit] = ordered_constant_color[3];
421
422 return GL_TRUE;
423 }
424