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