Home | History | Annotate | Download | only in geometry
      1 //
      2 // Copyright (c) 2002-2010 The ANGLE Project Authors. All rights reserved.
      3 // Use of this source code is governed by a BSD-style license that can be
      4 // found in the LICENSE file.
      5 //
      6 
      7 // geometry/vertexconversion.h: A library of vertex conversion classes that can be used to build
      8 // the FormatConverter objects used by the buffer conversion system.
      9 
     10 #ifndef LIBGLESV2_GEOMETRY_VERTEXCONVERSION_H_
     11 #define LIBGLESV2_GEOMETRY_VERTEXCONVERSION_H_
     12 
     13 #include <cstddef>
     14 #include <limits>
     15 
     16 #include "libGLESv2/Context.h" // Defines Index
     17 
     18 namespace gl
     19 {
     20 
     21 // Conversion types:
     22 // static const bool identity: true if this is an identity transform, false otherwise
     23 // static U convert(T): convert a single element from the input type to the output type
     24 // typedef ... OutputType: the type produced by this conversion
     25 
     26 template <class T>
     27 struct Identity
     28 {
     29     static const bool identity = true;
     30 
     31     typedef T OutputType;
     32 
     33     static T convert(T x)
     34     {
     35         return x;
     36     }
     37 };
     38 
     39 template <class FromT, class ToT>
     40 struct Cast
     41 {
     42     static const bool identity = false;
     43 
     44     typedef ToT OutputType;
     45 
     46     static ToT convert(FromT x)
     47     {
     48         return static_cast<ToT>(x);
     49     }
     50 };
     51 
     52 template <class T>
     53 struct Cast<T, T>
     54 {
     55     static const bool identity = true;
     56 
     57     typedef T OutputType;
     58 
     59     static T convert(T x)
     60     {
     61         return static_cast<T>(x);
     62     }
     63 };
     64 
     65 template <class T>
     66 struct Normalize
     67 {
     68     static const bool identity = false;
     69 
     70     typedef float OutputType;
     71 
     72     static float convert(T x)
     73     {
     74         typedef std::numeric_limits<T> NL;
     75         float f = static_cast<float>(x);
     76 
     77         if (NL::is_signed)
     78         {
     79             // const float => VC2008 computes it at compile time
     80             // static const float => VC2008 computes it the first time we get here, stores it to memory with static guard and all that.
     81             const float divisor = 1.0f/(2*static_cast<float>(NL::max())+1);
     82             return (2*f+1)*divisor;
     83         }
     84         else
     85         {
     86             return f/NL::max();
     87         }
     88     }
     89 };
     90 
     91 template <class FromType, std::size_t ScaleBits>
     92 struct FixedToFloat
     93 {
     94     static const bool identity = false;
     95 
     96     typedef float OutputType;
     97 
     98     static float convert(FromType x)
     99     {
    100         const float divisor = 1.0f / static_cast<float>(static_cast<FromType>(1) << ScaleBits);
    101         return static_cast<float>(x) * divisor;
    102     }
    103 };
    104 
    105 // Widen types:
    106 // static const unsigned int initialWidth: number of components before conversion
    107 // static const unsigned int finalWidth: number of components after conversion
    108 
    109 // Float is supported at any size.
    110 template <std::size_t N>
    111 struct NoWiden
    112 {
    113     static const std::size_t initialWidth = N;
    114     static const std::size_t finalWidth = N;
    115 };
    116 
    117 // SHORT, norm-SHORT, norm-UNSIGNED_SHORT are supported but only with 2 or 4 components
    118 template <std::size_t N>
    119 struct WidenToEven
    120 {
    121     static const std::size_t initialWidth = N;
    122     static const std::size_t finalWidth = N+(N&1);
    123 };
    124 
    125 template <std::size_t N>
    126 struct WidenToFour
    127 {
    128     static const std::size_t initialWidth = N;
    129     static const std::size_t finalWidth = 4;
    130 };
    131 
    132 // Most types have 0 and 1 that are just that.
    133 template <class T>
    134 struct SimpleDefaultValues
    135 {
    136     static T zero() { return static_cast<T>(0); }
    137     static T one() { return static_cast<T>(1); }
    138 };
    139 
    140 // But normalised types only store [0,1] or [-1,1] so 1.0 is represented by the max value.
    141 template <class T>
    142 struct NormalizedDefaultValues
    143 {
    144     static T zero() { return static_cast<T>(0); }
    145     static T one() { return std::numeric_limits<T>::max(); }
    146 };
    147 
    148 // Converter:
    149 // static const bool identity: true if this is an identity transform (with no widening)
    150 // static const std::size_t finalSize: number of bytes per output vertex
    151 // static void convertArray(const void *in, std::size_t stride, std::size_t n, void *out): convert an array of vertices. Input may be strided, but output will be unstrided.
    152 
    153 template <class InT, class WidenRule, class Converter, class DefaultValueRule = SimpleDefaultValues<InT> >
    154 struct VertexDataConverter
    155 {
    156     typedef typename Converter::OutputType OutputType;
    157     typedef InT InputType;
    158 
    159     static const bool identity = (WidenRule::initialWidth == WidenRule::finalWidth) && Converter::identity;
    160     static const std::size_t finalSize = WidenRule::finalWidth * sizeof(OutputType);
    161 
    162     static void convertArray(const InputType *in, std::size_t stride, std::size_t n, OutputType *out)
    163     {
    164         for (std::size_t i = 0; i < n; i++)
    165         {
    166             const InputType *ein = pointerAddBytes(in, i * stride);
    167 
    168             copyComponent(out, ein, 0, static_cast<OutputType>(DefaultValueRule::zero()));
    169             copyComponent(out, ein, 1, static_cast<OutputType>(DefaultValueRule::zero()));
    170             copyComponent(out, ein, 2, static_cast<OutputType>(DefaultValueRule::zero()));
    171             copyComponent(out, ein, 3, static_cast<OutputType>(DefaultValueRule::one()));
    172 
    173             out += WidenRule::finalWidth;
    174         }
    175     }
    176 
    177     static void convertArray(const void *in, std::size_t stride, std::size_t n, void *out)
    178     {
    179         return convertArray(static_cast<const InputType*>(in), stride, n, static_cast<OutputType*>(out));
    180     }
    181 
    182   private:
    183     // Advance the given pointer by a number of bytes (not pointed-to elements).
    184     template <class T>
    185     static T *pointerAddBytes(T *basePtr, std::size_t numBytes)
    186     {
    187         return reinterpret_cast<T *>(reinterpret_cast<uintptr_t>(basePtr) + numBytes);
    188     }
    189 
    190     static void copyComponent(OutputType *out, const InputType *in, std::size_t elementindex, OutputType defaultvalue)
    191     {
    192         if (WidenRule::finalWidth > elementindex)
    193         {
    194             if (WidenRule::initialWidth > elementindex)
    195             {
    196                 out[elementindex] = Converter::convert(in[elementindex]);
    197             }
    198             else
    199             {
    200                 out[elementindex] = defaultvalue;
    201             }
    202         }
    203     }
    204 };
    205 
    206 }
    207 
    208 #endif   // LIBGLESV2_GEOMETRY_VERTEXCONVERSION_H_
    209