csplugincommon/softshader/types.h
Go to the documentation of this file.00001 /* 00002 Copyright (C) 2005 by Jorrit Tyberghein 00003 (C) 2005 by Frank Richter 00004 00005 This library is free software; you can redistribute it and/or 00006 modify it under the terms of the GNU Library General Public 00007 License as published by the Free Software Foundation; either 00008 version 2 of the License, or (at your option) any later version. 00009 00010 This library is distributed in the hope that it will be useful, 00011 but WITHOUT ANY WARRANTY; without even the implied warranty of 00012 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 00013 Library General Public License for more details. 00014 00015 You should have received a copy of the GNU Library General Public 00016 License along with this library; if not, write to the Free 00017 Software Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. 00018 */ 00019 00020 #ifndef __CS_CSPLUGINCOMMON_SOFTSHADER_TYPES_H__ 00021 #define __CS_CSPLUGINCOMMON_SOFTSHADER_TYPES_H__ 00022 00027 #include "csgeom/fixed.h" 00028 00032 namespace CS 00033 { 00034 namespace PluginCommon 00035 { 00036 namespace SoftShader 00037 { 00039 const size_t maxBuffers = 16; 00041 typedef uint BuffersMask; 00043 typedef uint TexturesMask; 00044 00046 template <typename T> 00047 static inline T Lerp (const T& a, const T& b, float f) 00048 { return a + (b-a) * f; } 00049 00051 struct InterpolateEdgePersp 00052 { 00054 float x; 00056 float dxdy; 00058 float Iz; 00060 float dIzdy; 00062 struct PerFloat 00063 { 00065 float Ic; 00067 float dIcdy; 00069 float c; 00070 } Floats[maxBuffers*4]; 00071 00073 void Setup (const csVector3* vertices, const float* floats, 00074 const size_t floatNum, size_t sv, size_t fv, int sy) 00075 { 00076 const csVector3 vsv (vertices[sv]); 00077 const csVector3 vfv (vertices[fv]); 00078 00079 float dy = vsv.y - vfv.y; 00080 if (dy) 00081 { 00082 float inv_dy = 1 / dy; 00083 x = vsv.x; 00084 dxdy = (vfv.x - x) * inv_dy; 00085 const float Isz = vsv.z; // Z coord already inverted here 00086 const float Ifz = vfv.z; 00087 dIzdy = (Ifz - Isz) * inv_dy; 00088 00089 // horizontal pixel correction 00090 float deltaX = dxdy * 00091 (vsv.y - (float (sy) - 0.5)); 00092 x += deltaX; 00093 00094 // apply sub-pixel accuracy factor 00095 float Factor; 00096 if (vfv.x != vsv.x) 00097 Factor = deltaX / (vfv.x - vsv.x); 00098 else 00099 Factor = 0; 00100 00101 Iz = Lerp (Isz, Ifz, Factor); 00102 const float z = 1.0f/Iz; 00103 00104 // Z coord already inverted here 00105 const float* Icsv = floats + sv*floatNum; 00106 const float* Icfv = floats + fv*floatNum; 00107 for (size_t f = 0; f < floatNum; f++) 00108 { 00109 const float fs = *Icsv++; 00110 const float ff = *Icfv++; 00111 Floats[f].Ic = Lerp (fs, ff, Factor); 00112 Floats[f].c = Floats[f].Ic * z; 00113 Floats[f].dIcdy = (ff - fs) * inv_dy; 00114 } 00115 } /* endif */ 00116 } 00118 void Advance (const size_t floatNum) 00119 { 00120 Iz += dIzdy; 00121 const float z = 1.0f/Iz; 00122 00123 for (size_t f = 0; f < floatNum; f++) 00124 { 00125 Floats[f].Ic += Floats[f].dIcdy; 00126 Floats[f].c = Floats[f].Ic * z; 00127 } 00128 x += dxdy; 00129 } 00130 }; 00132 struct InterpolateScanlinePerspCommon 00133 { 00135 csFixed24 Iz, dIzdx; 00137 float Iz_f, dIzdx_f, dIzdx_fLast; 00138 }; 00139 00141 struct ScanlineComp 00142 { 00144 csFixed16 c; 00146 csFixed16 dcdx; 00147 }; 00149 struct ScanlineCompDivZ 00150 { 00152 float Ic; 00154 float dIcdx; 00156 float dIcdxLast; 00157 }; 00158 00160 template<int maxFloats> 00161 struct InterpolateScanlinePersp : public InterpolateScanlinePerspCommon 00162 { 00164 ScanlineComp floats[maxFloats]; 00166 ScanlineCompDivZ floats_f[maxFloats]; 00167 00169 int InterpolStep; 00171 int InterpolShift; 00173 int ipx; 00175 int spans; 00177 float invLastSpan; 00178 00180 void Setup (const InterpolateEdgePersp& L, const InterpolateEdgePersp& R, 00181 uint len, int ipolStep, int ipolShift) 00182 { 00183 // @@@ If you notice something that can be sped up, don't hesitate! 00184 InterpolStep = ipolStep; 00185 InterpolShift = ipolShift; 00186 spans = len / ipolStep; 00187 00188 const float inv_l = 1.0f/len; 00189 const float ipf = (float)InterpolStep; 00190 ipx = InterpolStep; 00191 const float fact = inv_l * ipf; 00192 uint lastSpanSize = len % ipolStep; 00193 if (lastSpanSize == 0) lastSpanSize = ipolStep; 00194 const float lastFact = float (lastSpanSize) / ipf; 00195 invLastSpan = 1.0f / float(lastSpanSize); 00196 Iz = Iz_f = L.Iz; 00197 dIzdx = dIzdx_f = (R.Iz - L.Iz) * inv_l; 00198 dIzdx_fLast = dIzdx_f * float (lastSpanSize); 00199 dIzdx_f *= ipf; 00200 Iz_f += (spans == 0) ? dIzdx_fLast : dIzdx_f; 00201 float z2 = 1.0f / Iz_f; 00202 for (size_t f = 0; f < maxFloats; f++) 00203 { 00204 const float cL = L.Floats[f].c; 00205 const float IcL = L.Floats[f].Ic; 00206 const float IcR = R.Floats[f].Ic; 00207 floats[f].c = cL; 00208 floats_f[f].dIcdx = (IcR - IcL) * fact; 00209 floats_f[f].dIcdxLast = floats_f[f].dIcdx * lastFact; 00210 } 00211 if (spans == 0) 00212 { 00213 for (size_t f = 0; f < maxFloats; f++) 00214 { 00215 const float cL = L.Floats[f].c; 00216 const float IcL = L.Floats[f].Ic; 00217 floats_f[f].Ic = IcL + floats_f[f].dIcdxLast; 00218 floats[f].dcdx = (floats_f[f].Ic*z2 - cL) * invLastSpan; 00219 } 00220 } 00221 else 00222 { 00223 for (size_t f = 0; f < maxFloats; f++) 00224 { 00225 const float IcL = L.Floats[f].Ic; 00226 floats_f[f].Ic = IcL + floats_f[f].dIcdx; 00227 floats[f].dcdx = (floats_f[f].Ic*z2 - floats[f].c) >> InterpolShift; 00228 } 00229 } 00230 } 00232 void Advance () 00233 { 00234 if (--ipx > 0) 00235 { 00236 Iz += dIzdx; 00237 for (size_t f = 0; f < maxFloats; f++) 00238 { 00239 floats[f].c += floats[f].dcdx; 00240 } 00241 } 00242 else 00243 { 00244 if (--spans == 0) 00245 { 00246 dIzdx_f = dIzdx_fLast; 00247 } 00248 /* Note: Iz_f is "ahead" one interpolation span, ie when the 00249 * deltas are set up for the next, it has the value from the 00250 * beginning if that span. */ 00251 const float z = 1.0f / Iz_f; 00252 Iz = Iz_f; 00253 Iz_f += dIzdx_f; 00254 const float z2 = 1.0f / Iz_f; 00255 ipx = InterpolStep; 00256 for (size_t f = 0; f < maxFloats; f++) 00257 { 00258 const float c = floats_f[f].Ic * z; 00259 floats[f].c = c; 00260 if (spans == 0) 00261 { 00262 floats_f[f].Ic += floats_f[f].dIcdxLast; 00263 floats[f].dcdx = (floats_f[f].Ic*z2 - c) * invLastSpan; 00264 } 00265 else 00266 { 00267 floats_f[f].Ic += floats_f[f].dIcdx; 00268 floats[f].dcdx = (floats_f[f].Ic*z2 - floats[f].c) >> InterpolShift; 00269 } 00270 } 00271 } 00272 } 00273 00275 const ScanlineComp* GetFloat (size_t i) const { return &floats[i]; } 00276 }; 00277 00278 template<> 00279 struct InterpolateScanlinePersp<0> : public InterpolateScanlinePerspCommon 00280 { 00282 int InterpolStep; 00284 int InterpolShift; 00286 int ipx; 00288 int spans; 00289 00291 void Setup (const InterpolateEdgePersp& L, const InterpolateEdgePersp& R, 00292 uint len, int ipolStep, int ipolShift) 00293 { 00294 InterpolStep = ipolStep; 00295 InterpolShift = ipolShift; 00296 spans = len / ipolStep; 00297 00298 const float inv_l = 1.0f/len; 00299 const float ipf = (float)InterpolStep; 00300 ipx = InterpolStep; 00301 uint lastSpanSize = len % ipolStep; 00302 if (lastSpanSize == 0) lastSpanSize = ipolStep; 00303 Iz = Iz_f = L.Iz; 00304 dIzdx = dIzdx_f = (R.Iz - L.Iz) * inv_l; 00305 dIzdx_fLast = dIzdx_f * float (lastSpanSize); 00306 dIzdx_f *= ipf; 00307 Iz_f += dIzdx_f; 00308 } 00310 void Advance () 00311 { 00312 if (--ipx > 0) 00313 { 00314 Iz += dIzdx; 00315 } 00316 else 00317 { 00318 if (--spans == 0) 00319 { 00320 dIzdx_f = dIzdx_fLast; 00321 } 00322 /* Note: Iz_f is "ahead" one interpolation span, ie when the 00323 * deltas are set up for the next, it has the value from the 00324 * beginning if that span. */ 00325 Iz = Iz_f; 00326 Iz_f += dIzdx_f; 00327 ipx = InterpolStep; 00328 } 00329 } 00330 00334 const ScanlineComp* GetFloat (size_t /*i*/) const { return 0; } 00335 }; 00336 00337 struct Pixel 00338 { 00339 struct tag_c 00340 { 00341 uint8 r; 00342 uint8 g; 00343 uint8 b; 00344 uint8 a; 00345 }; 00346 union 00347 { 00348 tag_c c; 00349 uint32 ui32; 00350 }; 00351 00352 Pixel () {} 00353 Pixel (uint8 r, uint8 g, uint8 b, uint8 a) 00354 { 00355 c.r = r; c.g = g; c.b = b; c.a = a; 00356 } 00357 Pixel (uint32 ui) : ui32 (ui) { } 00358 00359 CS_FORCEINLINE 00360 Pixel operator+ (const Pixel other) 00361 { 00362 // Poor man's SIMD... add two components at once. 00363 const uint32 rb1 = (ui32 & 0xff00ff00) >> 8; 00364 const uint32 ga1 = (ui32 & 0x00ff00ff); 00365 const uint32 rb2 = (other.ui32 & 0xff00ff00) >> 8; 00366 const uint32 ga2 = (other.ui32 & 0x00ff00ff); 00367 uint32 rb = rb1 + rb2; 00368 // Clamp 00369 if (rb & 0xff000000) { rb &= 0x0000ffff; rb |= 0x00ff0000; } 00370 if (rb & 0x0000ff00) { rb &= 0xffff0000; rb |= 0x000000ff; } 00371 uint32 ga = ga1 + ga2; 00372 if (ga & 0xff000000) { ga &= 0x0000ffff; ga |= 0x00ff0000; } 00373 if (ga & 0x0000ff00) { ga &= 0xffff0000; ga |= 0x000000ff; } 00374 return Pixel ((rb << 8) | ga); 00375 } 00376 CS_FORCEINLINE 00377 Pixel& operator += (const Pixel other) 00378 { 00379 return (*this = *this + other); 00380 } 00381 CS_FORCEINLINE 00382 Pixel operator~ () const 00383 { 00384 return Pixel (~ui32); 00385 } 00386 CS_FORCEINLINE 00387 friend Pixel operator* (const Pixel p1, const Pixel p2) 00388 { 00389 uint8 nr = (p1.c.r*(p2.c.r+1)) >> 8; 00390 uint8 ng = (p1.c.g*(p2.c.g+1)) >> 8; 00391 uint8 nb = (p1.c.b*(p2.c.b+1)) >> 8; 00392 uint8 na = (p1.c.a*(p2.c.a+1)) >> 8; 00393 return Pixel (nr, ng, nb, na); 00394 } 00395 CS_FORCEINLINE 00396 friend Pixel operator* (const Pixel p, const uint8 x) 00397 { 00398 // Poor man's SIMD... 00399 const uint v = x+1; 00400 const uint32 rb = (p.ui32 & 0xff00ff00) >> 8; 00401 const uint32 ga = (p.ui32 & 0x00ff00ff); 00402 return Pixel (((rb*v) & 0xff00ff00) | (((ga*v) >> 8) & 0x00ff00ff)); 00403 } 00404 CS_FORCEINLINE 00405 Pixel& operator *= (const uint8 x) 00406 { 00407 return (*this = *this * x); 00408 } 00409 }; 00410 } // namespace SoftShader 00411 } // namespace PluginCommon 00412 } // namespace CS 00413 00418 #define CS_SOFT3D_VA_BUFINDEX(x) \ 00419 (CS_VATTRIB_ ## x - (CS_VATTRIB_ ## x >= CS_VATTRIB_GENERIC_FIRST ? \ 00420 CS_VATTRIB_GENERIC_FIRST : CS_VATTRIB_SPECIFIC_FIRST)) 00421 00425 #define CS_SOFT3D_BUFFERFLAG(x) (1 << CS_SOFT3D_VA_BUFINDEX(x)) 00426 00429 #endif // __CS_CSPLUGINCOMMON_SOFTSHADER_TYPES_H__
Generated for Crystal Space by doxygen 1.4.7