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