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