CrystalSpace

Public API Reference

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