Upstream version 8.37.180.0
[platform/framework/web/crosswalk.git] / src / third_party / angle / src / libGLESv2 / renderer / copyvertex.h
1 //
2 // Copyright (c) 2013 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 // copyvertex.h: Defines vertex buffer copying and conversion functions
8
9 #ifndef LIBGLESV2_RENDERER_COPYVERTEX_H_
10 #define LIBGLESV2_RENDERER_COPYVERTEX_H_
11
12 #include "common/mathutil.h"
13
14 // 'widenDefaultValueBits' gives the default value for the alpha channel (4th component)
15 //  the sentinel value 0 means we do not want to widen the input or add an alpha channel
16 template <typename T, unsigned int componentCount, unsigned int widenDefaultValueBits>
17 inline void copyVertexData(const void *input, size_t stride, size_t count, void *output)
18 {
19     const unsigned int attribSize = sizeof(T) * componentCount;
20     const T defaultValue = gl::bitCast<T>(widenDefaultValueBits);
21     const bool widen = (widenDefaultValueBits != 0);
22
23     if (attribSize == stride && !widen)
24     {
25         memcpy(output, input, count * attribSize);
26     }
27     else
28     {
29         unsigned int outputStride = widen ? 4 : componentCount;
30
31         for (unsigned int i = 0; i < count; i++)
32         {
33             const T *offsetInput = reinterpret_cast<const T*>(reinterpret_cast<const char*>(input) + i * stride);
34             T *offsetOutput = reinterpret_cast<T*>(output) + i * outputStride;
35
36             for (unsigned int j = 0; j < componentCount; j++)
37             {
38                 offsetOutput[j] = offsetInput[j];
39             }
40
41             if (widen)
42             {
43                 offsetOutput[3] = defaultValue;
44             }
45         }
46     }
47 }
48
49 template <unsigned int componentCount>
50 inline void copyFixedVertexData(const void* input, size_t stride, size_t count, void* output)
51 {
52     static const float divisor = 1.0f / (1 << 16);
53
54     for (unsigned int i = 0; i < count; i++)
55     {
56         const GLfixed* offsetInput = reinterpret_cast<const GLfixed*>(reinterpret_cast<const char*>(input) + stride * i);
57         float* offsetOutput = reinterpret_cast<float*>(output) + i * componentCount;
58
59         for (unsigned int j = 0; j < componentCount; j++)
60         {
61             offsetOutput[j] = static_cast<float>(offsetInput[j]) * divisor;
62         }
63     }
64 }
65
66 template <typename T, unsigned int componentCount, bool normalized>
67 inline void copyToFloatVertexData(const void* input, size_t stride, size_t count, void* output)
68 {
69     typedef std::numeric_limits<T> NL;
70
71     for (unsigned int i = 0; i < count; i++)
72     {
73         const T *offsetInput = reinterpret_cast<const T*>(reinterpret_cast<const char*>(input) + stride * i);
74         float *offsetOutput = reinterpret_cast<float*>(output) + i * componentCount;
75
76         for (unsigned int j = 0; j < componentCount; j++)
77         {
78             if (normalized)
79             {
80                 if (NL::is_signed)
81                 {
82                     const float divisor = 1.0f / (2 * static_cast<float>(NL::max()) + 1);
83                     offsetOutput[j] = (2 * static_cast<float>(offsetInput[j]) + 1) * divisor;
84                 }
85                 else
86                 {
87                     offsetOutput[j] =  static_cast<float>(offsetInput[j]) / NL::max();
88                 }
89             }
90             else
91             {
92                 offsetOutput[j] =  static_cast<float>(offsetInput[j]);
93             }
94         }
95     }
96 }
97
98 inline void copyPackedUnsignedVertexData(const void* input, size_t stride, size_t count, void* output)
99 {
100     const unsigned int attribSize = 4;
101
102     if (attribSize == stride)
103     {
104         memcpy(output, input, count * attribSize);
105     }
106     else
107     {
108         for (unsigned int i = 0; i < count; i++)
109         {
110             const GLuint *offsetInput = reinterpret_cast<const GLuint*>(reinterpret_cast<const char*>(input) + (i * stride));
111             GLuint *offsetOutput = reinterpret_cast<GLuint*>(output) + (i * attribSize);
112
113             offsetOutput[i] = offsetInput[i];
114         }
115     }
116 }
117
118 template <bool isSigned, bool normalized, bool toFloat>
119 static inline void copyPackedRGB(unsigned int data, void *output)
120 {
121     const unsigned int rgbSignMask = 0x200;       // 1 set at the 9 bit
122     const unsigned int negativeMask = 0xFFFFFC00; // All bits from 10 to 31 set to 1
123
124     if (toFloat)
125     {
126         GLfloat *floatOutput = reinterpret_cast<GLfloat*>(output);
127         if (isSigned)
128         {
129             GLfloat finalValue = 0;
130             if (data & rgbSignMask)
131             {
132                 int negativeNumber = data | negativeMask;
133                 finalValue = static_cast<GLfloat>(negativeNumber);
134             }
135             else
136             {
137                 finalValue = static_cast<GLfloat>(data);
138             }
139
140             if (normalized)
141             {
142                 const int maxValue = 0x1FF;      // 1 set in bits 0 through 8
143                 const int minValue = 0xFFFFFE01; // Inverse of maxValue
144
145                 // A 10-bit two's complement number has the possibility of being minValue - 1 but
146                 // OpenGL's normalization rules dictate that it should be clamped to minValue in this
147                 // case.
148                 if (finalValue < minValue)
149                 {
150                     finalValue = minValue;
151                 }
152
153                 const int halfRange = (maxValue - minValue) >> 1;
154                 *floatOutput = ((finalValue - minValue) / halfRange) - 1.0f;
155             }
156             else
157             {
158                 *floatOutput = finalValue;
159             }
160         }
161         else
162         {
163             if (normalized)
164             {
165                 const unsigned int maxValue = 0x3FF; // 1 set in bits 0 through 9
166                 *floatOutput = static_cast<GLfloat>(data) / static_cast<GLfloat>(maxValue);
167             }
168             else
169             {
170                 *floatOutput = static_cast<GLfloat>(data);
171             }
172         }
173     }
174     else
175     {
176         if (isSigned)
177         {
178             GLshort *intOutput = reinterpret_cast<GLshort*>(output);
179
180             if (data & rgbSignMask)
181             {
182                 *intOutput = data | negativeMask;
183             }
184             else
185             {
186                 *intOutput = data;
187             }
188         }
189         else
190         {
191             GLushort *uintOutput = reinterpret_cast<GLushort*>(output);
192             *uintOutput = data;
193         }
194     }
195 }
196
197 template <bool isSigned, bool normalized, bool toFloat>
198 inline void copyPackedAlpha(unsigned int data, void *output)
199 {
200     if (toFloat)
201     {
202         GLfloat *floatOutput = reinterpret_cast<GLfloat*>(output);
203         if (isSigned)
204         {
205             if (normalized)
206             {
207                 switch (data)
208                 {
209                   case 0x0: *floatOutput =  0.0f; break;
210                   case 0x1: *floatOutput =  1.0f; break;
211                   case 0x2: *floatOutput = -1.0f; break;
212                   case 0x3: *floatOutput = -1.0f; break;
213                   default: UNREACHABLE();
214                 }
215             }
216             else
217             {
218                 switch (data)
219                 {
220                   case 0x0: *floatOutput =  0.0f; break;
221                   case 0x1: *floatOutput =  1.0f; break;
222                   case 0x2: *floatOutput = -2.0f; break;
223                   case 0x3: *floatOutput = -1.0f; break;
224                   default: UNREACHABLE();
225                 }
226             }
227         }
228         else
229         {
230             if (normalized)
231             {
232                 switch (data)
233                 {
234                   case 0x0: *floatOutput = 0.0f / 3.0f; break;
235                   case 0x1: *floatOutput = 1.0f / 3.0f; break;
236                   case 0x2: *floatOutput = 2.0f / 3.0f; break;
237                   case 0x3: *floatOutput = 3.0f / 3.0f; break;
238                   default: UNREACHABLE();
239                 }
240             }
241             else
242             {
243                 switch (data)
244                 {
245                   case 0x0: *floatOutput = 0.0f; break;
246                   case 0x1: *floatOutput = 1.0f; break;
247                   case 0x2: *floatOutput = 2.0f; break;
248                   case 0x3: *floatOutput = 3.0f; break;
249                   default: UNREACHABLE();
250                 }
251             }
252         }
253     }
254     else
255     {
256         if (isSigned)
257         {
258             GLshort *intOutput = reinterpret_cast<GLshort*>(output);
259             switch (data)
260             {
261               case 0x0: *intOutput =  0; break;
262               case 0x1: *intOutput =  1; break;
263               case 0x2: *intOutput = -2; break;
264               case 0x3: *intOutput = -1; break;
265               default: UNREACHABLE();
266             }
267         }
268         else
269         {
270             GLushort *uintOutput = reinterpret_cast<GLushort*>(output);
271             switch (data)
272             {
273               case 0x0: *uintOutput = 0; break;
274               case 0x1: *uintOutput = 1; break;
275               case 0x2: *uintOutput = 2; break;
276               case 0x3: *uintOutput = 3; break;
277               default: UNREACHABLE();
278             }
279         }
280     }
281 }
282
283 template <bool isSigned, bool normalized, bool toFloat>
284 inline void copyPackedVertexData(const void* input, size_t stride, size_t count, void* output)
285 {
286     const unsigned int outputComponentSize = toFloat ? 4 : 2;
287     const unsigned int componentCount = 4;
288
289     const unsigned int rgbMask = 0x3FF; // 1 set in bits 0 through 9
290     const unsigned int redShift = 0;    // red is bits 0 through 9
291     const unsigned int greenShift = 10; // green is bits 10 through 19
292     const unsigned int blueShift = 20;  // blue is bits 20 through 29
293
294     const unsigned int alphaMask = 0x3; // 1 set in bits 0 and 1
295     const unsigned int alphaShift = 30; // Alpha is the 30 and 31 bits
296
297     for (unsigned int i = 0; i < count; i++)
298     {
299         GLuint packedValue = *reinterpret_cast<const GLuint*>(reinterpret_cast<const char*>(input) + (i * stride));
300         GLbyte *offsetOutput = reinterpret_cast<GLbyte*>(output) + (i * outputComponentSize * componentCount);
301
302         copyPackedRGB<isSigned, normalized, toFloat>(  (packedValue >> redShift) & rgbMask,     offsetOutput + (0 * outputComponentSize));
303         copyPackedRGB<isSigned, normalized, toFloat>(  (packedValue >> greenShift) & rgbMask,   offsetOutput + (1 * outputComponentSize));
304         copyPackedRGB<isSigned, normalized, toFloat>(  (packedValue >> blueShift) & rgbMask,    offsetOutput + (2 * outputComponentSize));
305         copyPackedAlpha<isSigned, normalized, toFloat>((packedValue >> alphaShift) & alphaMask, offsetOutput + (3* outputComponentSize));
306     }
307 }
308
309 #endif // LIBGLESV2_RENDERER_COPYVERTEX_H_