## Public API Reference

- Main Page
- Modules
- Namespaces
- Classes
- Files
- Related Pages

- File List
- File Members

# 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__