• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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