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 CrystalSpace 00033 { 00034 namespace SoftShader 00035 { 00037 const size_t maxBuffers = 16; 00039 typedef uint BuffersMask; 00041 typedef uint TexturesMask; 00042 00044 template <typename T> 00045 static inline T Lerp (const T& a, const T& b, float f) 00046 { return a + (b-a) * f; } 00047 00049 struct InterpolateEdgePersp 00050 { 00052 float x; 00054 float dxdy; 00056 float Iz; 00058 float dIzdy; 00060 struct PerFloat 00061 { 00063 float Ic; 00065 float dIcdy; 00067 float c; 00068 } Floats[maxBuffers*4]; 00069 00071 void Setup (const csVector3* vertices, const float* floats, 00072 const size_t floatNum, size_t sv, size_t fv, int sy) 00073 { 00074 const csVector3 vsv (vertices[sv]); 00075 const csVector3 vfv (vertices[fv]); 00076 00077 float dy = vsv.y - vfv.y; 00078 if (dy) 00079 { 00080 float inv_dy = 1 / dy; 00081 x = vsv.x; 00082 dxdy = (vfv.x - x) * inv_dy; 00083 const float Isz = vsv.z; // Z coord already inverted here 00084 const float Ifz = vfv.z; 00085 dIzdy = (Ifz - Isz) * inv_dy; 00086 00087 // horizontal pixel correction 00088 float deltaX = dxdy * 00089 (vsv.y - (float (sy) - 0.5)); 00090 x += deltaX; 00091 00092 // apply sub-pixel accuracy factor 00093 float Factor; 00094 if (vfv.x != vsv.x) 00095 Factor = deltaX / (vfv.x - vsv.x); 00096 else 00097 Factor = 0; 00098 00099 Iz = Lerp (Isz, Ifz, Factor); 00100 const float z = 1.0f/Iz; 00101 00102 // Z coord already inverted here 00103 const float* Icsv = floats + sv*floatNum; 00104 const float* Icfv = floats + fv*floatNum; 00105 for (size_t f = 0; f < floatNum; f++) 00106 { 00107 const float fs = *Icsv++; 00108 const float ff = *Icfv++; 00109 Floats[f].Ic = Lerp (fs, ff, Factor); 00110 Floats[f].c = Floats[f].Ic * z; 00111 Floats[f].dIcdy = (ff - fs) * inv_dy; 00112 } 00113 } /* endif */ 00114 } 00116 void Advance (const size_t floatNum) 00117 { 00118 Iz += dIzdy; 00119 const float z = 1.0f/Iz; 00120 00121 for (size_t f = 0; f < floatNum; f++) 00122 { 00123 Floats[f].Ic += Floats[f].dIcdy; 00124 Floats[f].c = Floats[f].Ic * z; 00125 } 00126 x += dxdy; 00127 } 00128 }; 00130 struct InterpolateScanlinePerspCommon 00131 { 00133 csFixed24 Iz, dIzdx; 00135 float Iz_f, dIzdx_f, dIzdx_fLast; 00136 }; 00137 00139 struct ScanlineComp 00140 { 00142 csFixed16 c; 00144 csFixed16 dcdx; 00145 }; 00147 struct ScanlineCompDivZ 00148 { 00150 float Ic; 00152 float dIcdx; 00154 float dIcdxLast; 00155 }; 00156 00158 template<int maxFloats> 00159 struct InterpolateScanlinePersp : public InterpolateScanlinePerspCommon 00160 { 00162 ScanlineComp floats[maxFloats]; 00164 ScanlineCompDivZ floats_f[maxFloats]; 00165 00167 int InterpolStep; 00169 int InterpolShift; 00171 int ipx; 00173 int spans; 00175 float invLastSpan; 00176 00178 void Setup (const InterpolateEdgePersp& L, const InterpolateEdgePersp& R, 00179 uint len, int ipolStep, int ipolShift) 00180 { 00181 // @@@ If you notice something that can be sped up, don't hesitate! 00182 InterpolStep = ipolStep; 00183 InterpolShift = ipolShift; 00184 spans = len / ipolStep; 00185 00186 const float inv_l = 1.0f/len; 00187 const float ipf = (float)InterpolStep; 00188 ipx = InterpolStep; 00189 const float fact = inv_l * ipf; 00190 uint lastSpanSize = len % ipolStep; 00191 if (lastSpanSize == 0) lastSpanSize = ipolStep; 00192 const float lastFact = float (lastSpanSize) / ipf; 00193 invLastSpan = 1.0f / float(lastSpanSize); 00194 Iz = Iz_f = L.Iz; 00195 dIzdx = dIzdx_f = (R.Iz - L.Iz) * inv_l; 00196 dIzdx_fLast = dIzdx_f * float (lastSpanSize); 00197 dIzdx_f *= ipf; 00198 Iz_f += (spans == 0) ? dIzdx_fLast : dIzdx_f; 00199 float z2 = 1.0f / Iz_f; 00200 for (size_t f = 0; f < maxFloats; f++) 00201 { 00202 const float cL = L.Floats[f].c; 00203 const float IcL = L.Floats[f].Ic; 00204 const float IcR = R.Floats[f].Ic; 00205 floats[f].c = cL; 00206 floats_f[f].dIcdx = (IcR - IcL) * fact; 00207 floats_f[f].dIcdxLast = floats_f[f].dIcdx * lastFact; 00208 } 00209 if (spans == 0) 00210 { 00211 for (size_t f = 0; f < maxFloats; f++) 00212 { 00213 const float cL = L.Floats[f].c; 00214 const float IcL = L.Floats[f].Ic; 00215 floats_f[f].Ic = IcL + floats_f[f].dIcdxLast; 00216 floats[f].dcdx = (floats_f[f].Ic*z2 - cL) * invLastSpan; 00217 } 00218 } 00219 else 00220 { 00221 for (size_t f = 0; f < maxFloats; f++) 00222 { 00223 const float IcL = L.Floats[f].Ic; 00224 floats_f[f].Ic = IcL + floats_f[f].dIcdx; 00225 floats[f].dcdx = (floats_f[f].Ic*z2 - floats[f].c) >> InterpolShift; 00226 } 00227 } 00228 } 00230 void Advance () 00231 { 00232 if (--ipx > 0) 00233 { 00234 Iz += dIzdx; 00235 for (size_t f = 0; f < maxFloats; f++) 00236 { 00237 floats[f].c += floats[f].dcdx; 00238 } 00239 } 00240 else 00241 { 00242 if (--spans == 0) 00243 { 00244 dIzdx_f = dIzdx_fLast; 00245 } 00246 /* Note: Iz_f is "ahead" one interpolation span, ie when the 00247 * deltas are set up for the next, it has the value from the 00248 * beginning if that span. */ 00249 const float z = 1.0f / Iz_f; 00250 Iz = Iz_f; 00251 Iz_f += dIzdx_f; 00252 const float z2 = 1.0f / Iz_f; 00253 ipx = InterpolStep; 00254 for (size_t f = 0; f < maxFloats; f++) 00255 { 00256 const float c = floats_f[f].Ic * z; 00257 floats[f].c = c; 00258 if (spans == 0) 00259 { 00260 floats_f[f].Ic += floats_f[f].dIcdxLast; 00261 floats[f].dcdx = (floats_f[f].Ic*z2 - c) * invLastSpan; 00262 } 00263 else 00264 { 00265 floats_f[f].Ic += floats_f[f].dIcdx; 00266 floats[f].dcdx = (floats_f[f].Ic*z2 - floats[f].c) >> InterpolShift; 00267 } 00268 } 00269 } 00270 } 00271 00273 const ScanlineComp* GetFloat (size_t i) const { return &floats[i]; } 00274 }; 00275 00276 CS_SPECIALIZE_TEMPLATE 00277 struct InterpolateScanlinePersp<0> : public InterpolateScanlinePerspCommon 00278 { 00280 int InterpolStep; 00282 int InterpolShift; 00284 int ipx; 00286 int spans; 00287 00289 void Setup (const InterpolateEdgePersp& L, const InterpolateEdgePersp& R, 00290 uint len, int ipolStep, int ipolShift) 00291 { 00292 InterpolStep = ipolStep; 00293 InterpolShift = ipolShift; 00294 spans = len / ipolStep; 00295 00296 const float inv_l = 1.0f/len; 00297 const float ipf = (float)InterpolStep; 00298 ipx = InterpolStep; 00299 uint lastSpanSize = len % ipolStep; 00300 if (lastSpanSize == 0) lastSpanSize = ipolStep; 00301 Iz = Iz_f = L.Iz; 00302 dIzdx = dIzdx_f = (R.Iz - L.Iz) * inv_l; 00303 dIzdx_fLast = dIzdx_f * float (lastSpanSize); 00304 dIzdx_f *= ipf; 00305 Iz_f += dIzdx_f; 00306 } 00308 void Advance () 00309 { 00310 if (--ipx > 0) 00311 { 00312 Iz += dIzdx; 00313 } 00314 else 00315 { 00316 if (--spans == 0) 00317 { 00318 dIzdx_f = dIzdx_fLast; 00319 } 00320 /* Note: Iz_f is "ahead" one interpolation span, ie when the 00321 * deltas are set up for the next, it has the value from the 00322 * beginning if that span. */ 00323 Iz = Iz_f; 00324 Iz_f += dIzdx_f; 00325 ipx = InterpolStep; 00326 } 00327 } 00328 00332 const ScanlineComp* GetFloat (size_t /*i*/) const { return 0; } 00333 }; 00334 00335 struct Pixel 00336 { 00337 struct tag_c 00338 { 00339 uint8 r; 00340 uint8 g; 00341 uint8 b; 00342 uint8 a; 00343 }; 00344 union 00345 { 00346 tag_c c; 00347 uint32 ui32; 00348 }; 00349 00350 Pixel () {} 00351 Pixel (uint8 r, uint8 g, uint8 b, uint8 a) 00352 { 00353 c.r = r; c.g = g; c.b = b; c.a = a; 00354 } 00355 Pixel (uint32 ui) : ui32 (ui) { } 00356 00357 CS_FORCEINLINE 00358 Pixel operator+ (const Pixel other) 00359 { 00360 // Poor man's SIMD... add two components at once. 00361 const uint32 rb1 = (ui32 & 0xff00ff00) >> 8; 00362 const uint32 ga1 = (ui32 & 0x00ff00ff); 00363 const uint32 rb2 = (other.ui32 & 0xff00ff00) >> 8; 00364 const uint32 ga2 = (other.ui32 & 0x00ff00ff); 00365 uint32 rb = rb1 + rb2; 00366 // Clamp 00367 if (rb & 0xff000000) { rb &= 0x0000ffff; rb |= 0x00ff0000; } 00368 if (rb & 0x0000ff00) { rb &= 0xffff0000; rb |= 0x000000ff; } 00369 uint32 ga = ga1 + ga2; 00370 if (ga & 0xff000000) { ga &= 0x0000ffff; ga |= 0x00ff0000; } 00371 if (ga & 0x0000ff00) { ga &= 0xffff0000; ga |= 0x000000ff; } 00372 return Pixel ((rb << 8) | ga); 00373 } 00374 CS_FORCEINLINE 00375 Pixel operator~ () const 00376 { 00377 return Pixel (~ui32); 00378 } 00379 CS_FORCEINLINE 00380 friend Pixel operator* (const Pixel p1, const Pixel p2) 00381 { 00382 uint8 nr = (p1.c.r*(p2.c.r+1)) >> 8; 00383 uint8 ng = (p1.c.g*(p2.c.g+1)) >> 8; 00384 uint8 nb = (p1.c.b*(p2.c.b+1)) >> 8; 00385 uint8 na = (p1.c.a*(p2.c.a+1)) >> 8; 00386 return Pixel (nr, ng, nb, na); 00387 } 00388 CS_FORCEINLINE 00389 friend Pixel operator* (const Pixel p, const uint8 x) 00390 { 00391 // Poor man's SIMD... 00392 const uint v = x+1; 00393 const uint32 rb = (p.ui32 & 0xff00ff00) >> 8; 00394 const uint32 ga = (p.ui32 & 0x00ff00ff); 00395 return Pixel (((rb*v) & 0xff00ff00) | (((ga*v) >> 8) & 0x00ff00ff)); 00396 } 00397 CS_FORCEINLINE 00398 Pixel& operator *= (const uint8 x) 00399 { 00400 return (*this = *this * x); 00401 } 00402 }; 00403 } // namespace SoftShader 00404 } // namespace CrystalSpace 00405 00410 #define CS_SOFT3D_VA_BUFINDEX(x) \ 00411 (CS_VATTRIB_ ## x - (CS_VATTRIB_ ## x >= CS_VATTRIB_GENERIC_FIRST ? \ 00412 CS_VATTRIB_GENERIC_FIRST : CS_VATTRIB_SPECIFIC_FIRST)) 00413 00417 #define CS_SOFT3D_BUFFERFLAG(x) (1 << CS_SOFT3D_VA_BUFINDEX(x)) 00418 00421 #endif // __CS_CSPLUGINCOMMON_SOFTSHADER_TYPES_H__
Generated for Crystal Space by doxygen 1.4.6