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