s/MAX_TEXTURE_LEVELS/SIS_MAX_TEXTURE_LEVELS/ and add assertion (bug 11806)
[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 static GLint doFPtoFixedNoRound( GLfloat dwInValue, int nFraction );
43
44 void
45 sisDDFogfv( GLcontext *ctx, GLenum pname, const GLfloat *params )
46 {
47 sisContextPtr smesa = SIS_CONTEXT(ctx);
48 __GLSiSHardware *prev = &smesa->prev;
49 __GLSiSHardware *current = &smesa->current;
50
51 float fArg;
52 GLint fogColor;
53
54 switch (pname)
55 {
56 case GL_FOG_COORDINATE_SOURCE_EXT:
57 current->hwFog &= ~MASK_FogMode;
58 switch (ctx->Fog.FogCoordinateSource)
59 {
60 case GL_FOG_COORDINATE_EXT:
61 current->hwFog &= ~MASK_FogZLookup;
62 break;
63 case GL_FRAGMENT_DEPTH_EXT:
64 current->hwFog |= MASK_FogZLookup;
65 break;
66 }
67 if (current->hwFog != prev->hwFog) {
68 prev->hwFog = current->hwFog;
69 smesa->GlobalFlag |= GFLAG_FOGSETTING;
70 }
71 break;
72 case GL_FOG_MODE:
73 current->hwFog &= ~MASK_FogMode;
74 switch (ctx->Fog.Mode)
75 {
76 case GL_LINEAR:
77 current->hwFog |= FOGMODE_LINEAR;
78 break;
79 case GL_EXP:
80 current->hwFog |= FOGMODE_EXP;
81 break;
82 case GL_EXP2:
83 current->hwFog |= FOGMODE_EXP2;
84 break;
85 }
86 if (current->hwFog != prev->hwFog) {
87 prev->hwFog = current->hwFog;
88 smesa->GlobalFlag |= GFLAG_FOGSETTING;
89 }
90 break;
91 case GL_FOG_DENSITY:
92 current->hwFogDensity = convertFtToFogFt( ctx->Fog.Density );
93 if (current->hwFogDensity != prev->hwFogDensity) {
94 prev->hwFogDensity = current->hwFogDensity;
95 smesa->GlobalFlag |= GFLAG_FOGSETTING;
96 }
97 break;
98 case GL_FOG_START:
99 case GL_FOG_END:
100 fArg = 1.0 / (ctx->Fog.End - ctx->Fog.Start);
101 current->hwFogInverse = doFPtoFixedNoRound( fArg, 10 );
102 if (pname == GL_FOG_END)
103 {
104 if (smesa->Chipset == PCI_CHIP_SIS300)
105 current->hwFogFar = doFPtoFixedNoRound( ctx->Fog.End, 10 );
106 else
107 current->hwFogFar = doFPtoFixedNoRound( ctx->Fog.End, 6 );
108 }
109 if (current->hwFogFar != prev->hwFogFar ||
110 current->hwFogInverse != prev->hwFogInverse)
111 {
112 prev->hwFogFar = current->hwFogFar;
113 prev->hwFogInverse = current->hwFogInverse;
114 smesa->GlobalFlag |= GFLAG_FOGSETTING;
115 }
116 break;
117 case GL_FOG_INDEX:
118 /* TODO */
119 break;
120 case GL_FOG_COLOR:
121 fogColor = FLOAT_TO_UBYTE( ctx->Fog.Color[0] ) << 16;
122 fogColor |= FLOAT_TO_UBYTE( ctx->Fog.Color[1] ) << 8;
123 fogColor |= FLOAT_TO_UBYTE( ctx->Fog.Color[2] );
124 current->hwFog &= 0xff000000;
125 current->hwFog |= fogColor;
126 if (current->hwFog != prev->hwFog) {
127 prev->hwFog = current->hwFog;
128 smesa->GlobalFlag |= GFLAG_FOGSETTING;
129 }
130 break;
131 }
132 }
133
134 static GLint
135 doFPtoFixedNoRound( GLfloat dwInValue, int nFraction )
136 {
137 GLint dwMantissa;
138 int nTemp;
139 union { int i; float f; } u;
140 GLint val;
141
142 u.f = dwInValue;
143 val = u.i;
144
145 if (val == 0)
146 return 0;
147 nTemp = (int) (val & 0x7F800000) >> 23;
148 nTemp = nTemp - 127 + nFraction - 23;
149 dwMantissa = (val & 0x007FFFFF) | 0x00800000;
150
151 if (nTemp < -25)
152 return 0;
153 if (nTemp > 0)
154 dwMantissa <<= nTemp;
155 else {
156 nTemp = -nTemp;
157 dwMantissa >>= nTemp;
158 }
159 if (val & 0x80000000)
160 dwMantissa = ~dwMantissa + 1;
161 return dwMantissa;
162 }
163
164 /* s[8].23->s[7].10 */
165 static GLint
166 convertFtToFogFt( GLfloat dwInValue )
167 {
168 GLint dwMantissa, dwExp;
169 GLint dwRet;
170 union { int i; float f; } u;
171 GLint val;
172
173 u.f = dwInValue;
174 val = u.i;
175
176 if (val == 0)
177 return 0;
178
179 /* ----- Standard float Format: s[8].23 -----
180 * ----- = (-1)^S * 2^(E - 127) * (1 + M / 2^23) -----
181 * ----- = (-1)^S * 2^((E-63) - 64) * (1 + (M/2^13) / 2^10) -----
182 * ----- Density float Format: s[7].10 -----
183 * ----- New Exponential = E - 63 -----
184 * ----- New Mantissa = M / 2^13 -----
185 * ----- -----
186 */
187
188 dwExp = (val & 0x7F800000) >> 23;
189 dwExp -= 63;
190
191 if (dwExp < 0)
192 return 0;
193
194 if (dwExp <= 0x7F)
195 dwMantissa = (val & 0x007FFFFF) >> (23 - 10);
196 else {
197 /* ----- To Return +Max(or -Max) ----- */
198 dwExp = 0x7F;
199 dwMantissa = 0x3FF;
200 }
201
202 dwRet = (val & 0x80000000) >> (31 - 17); /* Shift Sign Bit */
203
204 dwRet |= (dwExp << 10) | dwMantissa;
205
206 return dwRet;
207 }