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