merge latest DRI sis driver changes from the DRI trunk
[mesa.git] / src / mesa / drivers / dri / sis / sis_fog.c
1 /**************************************************************************
2
3 Copyright 2000 Silicon Integrated Systems Corp, Inc., HsinChu, Taiwan.
4 Copyright 2003 Eric Anholt
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 on the rights to use, copy, modify, merge, publish, distribute, sub
11 license, and/or sell copies of the Software, and to permit persons to whom
12 the 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 NON-INFRINGEMENT. IN NO EVENT SHALL
21 ERIC ANHOLT OR SILICON INTEGRATED SYSTEMS CORP BE LIABLE FOR ANY CLAIM,
22 DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR
23 OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE
24 USE OR OTHER DEALINGS IN THE SOFTWARE.
25
26 **************************************************************************/
27 /* $XFree86: xc/lib/GL/mesa/src/drv/sis/sis_fog.c,v 1.3 2000/09/26 15:56:48 tsi Exp $ */
28
29 /*
30 * Authors:
31 * Sung-Ching Lin <sclin@sis.com.tw>
32 * Eric Anholt <anholt@FreeBSD.org>
33 */
34
35 #include "sis_context.h"
36 #include "sis_state.h"
37 #include "swrast/swrast.h"
38
39 #include "macros.h"
40
41 static GLint convertFtToFogFt( GLfloat dwInValue );
42
43 void
44 sisDDFogfv( GLcontext *ctx, GLenum pname, const GLfloat *params )
45 {
46 sisContextPtr smesa = SIS_CONTEXT(ctx);
47 __GLSiSHardware *prev = &smesa->prev;
48 __GLSiSHardware *current = &smesa->current;
49
50 float fArg;
51 GLint fogColor;
52
53 switch (pname)
54 {
55 case GL_FOG_MODE:
56 current->hwFog &= ~MASK_FogMode;
57 switch (ctx->Fog.Mode)
58 {
59 case GL_LINEAR:
60 current->hwFog |= FOGMODE_LINEAR;
61 break;
62 case GL_EXP:
63 current->hwFog |= FOGMODE_EXP;
64 break;
65 case GL_EXP2:
66 current->hwFog |= FOGMODE_EXP2;
67 break;
68 }
69 if (current->hwFog != prev->hwFog) {
70 prev->hwFog = current->hwFog;
71 smesa->GlobalFlag |= GFLAG_FOGSETTING;
72 }
73 break;
74 case GL_FOG_DENSITY:
75 current->hwFogDensity = convertFtToFogFt( ctx->Fog.Density );
76 if (current->hwFogDensity != prev->hwFogDensity) {
77 prev->hwFogDensity = current->hwFogDensity;
78 smesa->GlobalFlag |= GFLAG_FOGSETTING;
79 }
80 break;
81 case GL_FOG_START:
82 case GL_FOG_END:
83 fArg = 1.0 / (ctx->Fog.End - ctx->Fog.Start);
84 current->hwFogInverse = doFPtoFixedNoRound( fArg, 10 );
85 if (pname == GL_FOG_END)
86 {
87 if (smesa->Chipset == PCI_CHIP_SIS300)
88 current->hwFogFar = doFPtoFixedNoRound( ctx->Fog.End, 10 );
89 else
90 current->hwFogFar = doFPtoFixedNoRound( ctx->Fog.End, 6 );
91 }
92 if (current->hwFogFar != prev->hwFogFar ||
93 current->hwFogInverse != prev->hwFogInverse)
94 {
95 prev->hwFogFar = current->hwFogFar;
96 prev->hwFogInverse = current->hwFogInverse;
97 smesa->GlobalFlag |= GFLAG_FOGSETTING;
98 }
99 break;
100 case GL_FOG_INDEX:
101 /* TODO */
102 break;
103 case GL_FOG_COLOR:
104 fogColor = FLOAT_TO_UBYTE( ctx->Fog.Color[0] ) << 16;
105 fogColor |= FLOAT_TO_UBYTE( ctx->Fog.Color[1] ) << 8;
106 fogColor |= FLOAT_TO_UBYTE( ctx->Fog.Color[2] );
107 current->hwFog &= 0xff000000;
108 current->hwFog |= fogColor;
109 if (current->hwFog != prev->hwFog) {
110 prev->hwFog = current->hwFog;
111 smesa->GlobalFlag |= GFLAG_FOGSETTING;
112 }
113 break;
114 }
115 }
116
117 GLint
118 doFPtoFixedNoRound( GLfloat dwInValue, int nFraction )
119 {
120 GLint dwMantissa;
121 int nTemp;
122 union { int i; float f; } u;
123 GLint val;
124
125 u.f = dwInValue;
126 val = u.i;
127
128 if (val == 0)
129 return 0;
130 nTemp = (int) (val & 0x7F800000) >> 23;
131 nTemp = nTemp - 127 + nFraction - 23;
132 dwMantissa = (val & 0x007FFFFF) | 0x00800000;
133
134 if (nTemp < -25)
135 return 0;
136 if (nTemp > 0)
137 dwMantissa <<= nTemp;
138 else {
139 nTemp = -nTemp;
140 dwMantissa >>= nTemp;
141 }
142 if (val & 0x80000000)
143 dwMantissa = ~dwMantissa + 1;
144 return dwMantissa;
145 }
146
147 /* s[8].23->s[7].10 */
148 static GLint
149 convertFtToFogFt( GLfloat dwInValue )
150 {
151 GLint dwMantissa, dwExp;
152 GLint dwRet;
153 union { int i; float f; } u;
154 GLint val;
155
156 u.f = dwInValue;
157 val = u.i;
158
159 if (val == 0)
160 return 0;
161
162 /* ----- Standard float Format: s[8].23 -----
163 * ----- = (-1)^S * 2^(E - 127) * (1 + M / 2^23) -----
164 * ----- = (-1)^S * 2^((E-63) - 64) * (1 + (M/2^13) / 2^10) -----
165 * ----- Density float Format: s[7].10 -----
166 * ----- New Exponential = E - 63 -----
167 * ----- New Mantissa = M / 2^13 -----
168 * ----- -----
169 */
170
171 dwExp = (val & 0x7F800000) >> 23;
172 dwExp -= 63;
173
174 if (dwExp < 0)
175 return 0;
176
177 if (dwExp <= 0x7F)
178 dwMantissa = (val & 0x007FFFFF) >> (23 - 10);
179 else {
180 /* ----- To Return +Max(or -Max) ----- */
181 dwExp = 0x7F;
182 dwMantissa = 0x3FF;
183 }
184
185 dwRet = (val & 0x80000000) >> (31 - 17); /* Shift Sign Bit */
186
187 dwRet |= (dwExp << 10) | dwMantissa;
188
189 return dwRet;
190 }