1*8975f5c5SAndroid Build Coastguard Worker //
2*8975f5c5SAndroid Build Coastguard Worker // Copyright 2014 The ANGLE Project Authors. All rights reserved.
3*8975f5c5SAndroid Build Coastguard Worker // Use of this source code is governed by a BSD-style license that can be
4*8975f5c5SAndroid Build Coastguard Worker // found in the LICENSE file.
5*8975f5c5SAndroid Build Coastguard Worker //
6*8975f5c5SAndroid Build Coastguard Worker
7*8975f5c5SAndroid Build Coastguard Worker // copyvertex.inc.h: Implementation of vertex buffer copying and conversion functions
8*8975f5c5SAndroid Build Coastguard Worker
9*8975f5c5SAndroid Build Coastguard Worker namespace rx
10*8975f5c5SAndroid Build Coastguard Worker {
11*8975f5c5SAndroid Build Coastguard Worker
12*8975f5c5SAndroid Build Coastguard Worker // Returns an aligned buffer to read the input from
13*8975f5c5SAndroid Build Coastguard Worker template <typename T, size_t inputComponentCount>
GetAlignedOffsetInput(const T * offsetInput,T * alignedElement)14*8975f5c5SAndroid Build Coastguard Worker inline const T *GetAlignedOffsetInput(const T *offsetInput, T *alignedElement)
15*8975f5c5SAndroid Build Coastguard Worker {
16*8975f5c5SAndroid Build Coastguard Worker if (reinterpret_cast<uintptr_t>(offsetInput) % sizeof(T) != 0)
17*8975f5c5SAndroid Build Coastguard Worker {
18*8975f5c5SAndroid Build Coastguard Worker // Applications may pass in arbitrarily aligned buffers as input.
19*8975f5c5SAndroid Build Coastguard Worker // Certain architectures have restrictions regarding unaligned reads. Specifically, we crash
20*8975f5c5SAndroid Build Coastguard Worker // on armeabi-v7a devices with a SIGBUS error when performing such operations. arm64 and
21*8975f5c5SAndroid Build Coastguard Worker // x86-64 devices do not appear to have such issues.
22*8975f5c5SAndroid Build Coastguard Worker //
23*8975f5c5SAndroid Build Coastguard Worker // The workaround is to detect if the input buffer is unaligned and if so, perform a
24*8975f5c5SAndroid Build Coastguard Worker // byte-wise copy of the unaligned portion and a memcpy of the rest of the buffer.
25*8975f5c5SAndroid Build Coastguard Worker uint8_t *alignedBuffer = reinterpret_cast<uint8_t *>(&alignedElement[0]);
26*8975f5c5SAndroid Build Coastguard Worker uintptr_t unalignedInputStartAddress = reinterpret_cast<uintptr_t>(offsetInput);
27*8975f5c5SAndroid Build Coastguard Worker constexpr size_t kAlignmentMinusOne = sizeof(T) - 1;
28*8975f5c5SAndroid Build Coastguard Worker uintptr_t alignedInputStartAddress =
29*8975f5c5SAndroid Build Coastguard Worker (reinterpret_cast<uintptr_t>(offsetInput) + kAlignmentMinusOne) & ~(kAlignmentMinusOne);
30*8975f5c5SAndroid Build Coastguard Worker ASSERT(alignedInputStartAddress >= unalignedInputStartAddress);
31*8975f5c5SAndroid Build Coastguard Worker
32*8975f5c5SAndroid Build Coastguard Worker const size_t totalBytesToCopy = sizeof(T) * inputComponentCount;
33*8975f5c5SAndroid Build Coastguard Worker const size_t unalignedBytesToCopy = alignedInputStartAddress - unalignedInputStartAddress;
34*8975f5c5SAndroid Build Coastguard Worker ASSERT(totalBytesToCopy >= unalignedBytesToCopy);
35*8975f5c5SAndroid Build Coastguard Worker
36*8975f5c5SAndroid Build Coastguard Worker // byte-wise copy of unaligned portion
37*8975f5c5SAndroid Build Coastguard Worker for (size_t i = 0; i < unalignedBytesToCopy; i++)
38*8975f5c5SAndroid Build Coastguard Worker {
39*8975f5c5SAndroid Build Coastguard Worker alignedBuffer[i] = reinterpret_cast<const uint8_t *>(&offsetInput[0])[i];
40*8975f5c5SAndroid Build Coastguard Worker }
41*8975f5c5SAndroid Build Coastguard Worker
42*8975f5c5SAndroid Build Coastguard Worker // memcpy remaining buffer
43*8975f5c5SAndroid Build Coastguard Worker memcpy(&alignedBuffer[unalignedBytesToCopy],
44*8975f5c5SAndroid Build Coastguard Worker &reinterpret_cast<const uint8_t *>(&offsetInput[0])[unalignedBytesToCopy],
45*8975f5c5SAndroid Build Coastguard Worker totalBytesToCopy - unalignedBytesToCopy);
46*8975f5c5SAndroid Build Coastguard Worker
47*8975f5c5SAndroid Build Coastguard Worker return alignedElement;
48*8975f5c5SAndroid Build Coastguard Worker }
49*8975f5c5SAndroid Build Coastguard Worker else
50*8975f5c5SAndroid Build Coastguard Worker {
51*8975f5c5SAndroid Build Coastguard Worker return offsetInput;
52*8975f5c5SAndroid Build Coastguard Worker }
53*8975f5c5SAndroid Build Coastguard Worker }
54*8975f5c5SAndroid Build Coastguard Worker
55*8975f5c5SAndroid Build Coastguard Worker template <typename T,
56*8975f5c5SAndroid Build Coastguard Worker size_t inputComponentCount,
57*8975f5c5SAndroid Build Coastguard Worker size_t outputComponentCount,
58*8975f5c5SAndroid Build Coastguard Worker uint32_t alphaDefaultValueBits>
CopyNativeVertexData(const uint8_t * input,size_t stride,size_t count,uint8_t * output)59*8975f5c5SAndroid Build Coastguard Worker inline void CopyNativeVertexData(const uint8_t *input, size_t stride, size_t count, uint8_t *output)
60*8975f5c5SAndroid Build Coastguard Worker {
61*8975f5c5SAndroid Build Coastguard Worker const size_t attribSize = sizeof(T) * inputComponentCount;
62*8975f5c5SAndroid Build Coastguard Worker
63*8975f5c5SAndroid Build Coastguard Worker if (attribSize == stride && inputComponentCount == outputComponentCount)
64*8975f5c5SAndroid Build Coastguard Worker {
65*8975f5c5SAndroid Build Coastguard Worker memcpy(output, input, count * attribSize);
66*8975f5c5SAndroid Build Coastguard Worker return;
67*8975f5c5SAndroid Build Coastguard Worker }
68*8975f5c5SAndroid Build Coastguard Worker
69*8975f5c5SAndroid Build Coastguard Worker if (inputComponentCount == outputComponentCount)
70*8975f5c5SAndroid Build Coastguard Worker {
71*8975f5c5SAndroid Build Coastguard Worker for (size_t i = 0; i < count; i++)
72*8975f5c5SAndroid Build Coastguard Worker {
73*8975f5c5SAndroid Build Coastguard Worker const T *offsetInput = reinterpret_cast<const T *>(input + (i * stride));
74*8975f5c5SAndroid Build Coastguard Worker T offsetInputAligned[inputComponentCount];
75*8975f5c5SAndroid Build Coastguard Worker offsetInput =
76*8975f5c5SAndroid Build Coastguard Worker GetAlignedOffsetInput<T, inputComponentCount>(offsetInput, &offsetInputAligned[0]);
77*8975f5c5SAndroid Build Coastguard Worker
78*8975f5c5SAndroid Build Coastguard Worker T *offsetOutput = reinterpret_cast<T *>(output) + i * outputComponentCount;
79*8975f5c5SAndroid Build Coastguard Worker
80*8975f5c5SAndroid Build Coastguard Worker memcpy(offsetOutput, offsetInput, attribSize);
81*8975f5c5SAndroid Build Coastguard Worker }
82*8975f5c5SAndroid Build Coastguard Worker return;
83*8975f5c5SAndroid Build Coastguard Worker }
84*8975f5c5SAndroid Build Coastguard Worker
85*8975f5c5SAndroid Build Coastguard Worker const T defaultAlphaValue = gl::bitCast<T>(alphaDefaultValueBits);
86*8975f5c5SAndroid Build Coastguard Worker const size_t lastNonAlphaOutputComponent = std::min<size_t>(outputComponentCount, 3);
87*8975f5c5SAndroid Build Coastguard Worker
88*8975f5c5SAndroid Build Coastguard Worker for (size_t i = 0; i < count; i++)
89*8975f5c5SAndroid Build Coastguard Worker {
90*8975f5c5SAndroid Build Coastguard Worker const T *offsetInput = reinterpret_cast<const T *>(input + (i * stride));
91*8975f5c5SAndroid Build Coastguard Worker T offsetInputAligned[inputComponentCount];
92*8975f5c5SAndroid Build Coastguard Worker ASSERT(sizeof(offsetInputAligned) == attribSize);
93*8975f5c5SAndroid Build Coastguard Worker offsetInput =
94*8975f5c5SAndroid Build Coastguard Worker GetAlignedOffsetInput<T, inputComponentCount>(offsetInput, &offsetInputAligned[0]);
95*8975f5c5SAndroid Build Coastguard Worker
96*8975f5c5SAndroid Build Coastguard Worker T *offsetOutput = reinterpret_cast<T *>(output) + i * outputComponentCount;
97*8975f5c5SAndroid Build Coastguard Worker
98*8975f5c5SAndroid Build Coastguard Worker memcpy(offsetOutput, offsetInput, attribSize);
99*8975f5c5SAndroid Build Coastguard Worker
100*8975f5c5SAndroid Build Coastguard Worker if (inputComponentCount < lastNonAlphaOutputComponent)
101*8975f5c5SAndroid Build Coastguard Worker {
102*8975f5c5SAndroid Build Coastguard Worker // Set the remaining G/B channels to 0.
103*8975f5c5SAndroid Build Coastguard Worker size_t numComponents = (lastNonAlphaOutputComponent - inputComponentCount);
104*8975f5c5SAndroid Build Coastguard Worker memset(&offsetOutput[inputComponentCount], 0, numComponents * sizeof(T));
105*8975f5c5SAndroid Build Coastguard Worker }
106*8975f5c5SAndroid Build Coastguard Worker
107*8975f5c5SAndroid Build Coastguard Worker if (inputComponentCount < outputComponentCount && outputComponentCount == 4)
108*8975f5c5SAndroid Build Coastguard Worker {
109*8975f5c5SAndroid Build Coastguard Worker // Set the remaining alpha channel to the defaultAlphaValue.
110*8975f5c5SAndroid Build Coastguard Worker offsetOutput[3] = defaultAlphaValue;
111*8975f5c5SAndroid Build Coastguard Worker }
112*8975f5c5SAndroid Build Coastguard Worker }
113*8975f5c5SAndroid Build Coastguard Worker }
114*8975f5c5SAndroid Build Coastguard Worker
115*8975f5c5SAndroid Build Coastguard Worker template <size_t inputComponentCount, size_t outputComponentCount>
Copy8SintTo16SintVertexData(const uint8_t * input,size_t stride,size_t count,uint8_t * output)116*8975f5c5SAndroid Build Coastguard Worker inline void Copy8SintTo16SintVertexData(const uint8_t *input,
117*8975f5c5SAndroid Build Coastguard Worker size_t stride,
118*8975f5c5SAndroid Build Coastguard Worker size_t count,
119*8975f5c5SAndroid Build Coastguard Worker uint8_t *output)
120*8975f5c5SAndroid Build Coastguard Worker {
121*8975f5c5SAndroid Build Coastguard Worker const size_t lastNonAlphaOutputComponent = std::min<size_t>(outputComponentCount, 3);
122*8975f5c5SAndroid Build Coastguard Worker
123*8975f5c5SAndroid Build Coastguard Worker for (size_t i = 0; i < count; i++)
124*8975f5c5SAndroid Build Coastguard Worker {
125*8975f5c5SAndroid Build Coastguard Worker const GLbyte *offsetInput = reinterpret_cast<const GLbyte *>(input + i * stride);
126*8975f5c5SAndroid Build Coastguard Worker GLshort *offsetOutput = reinterpret_cast<GLshort *>(output) + i * outputComponentCount;
127*8975f5c5SAndroid Build Coastguard Worker
128*8975f5c5SAndroid Build Coastguard Worker for (size_t j = 0; j < inputComponentCount; j++)
129*8975f5c5SAndroid Build Coastguard Worker {
130*8975f5c5SAndroid Build Coastguard Worker offsetOutput[j] = static_cast<GLshort>(offsetInput[j]);
131*8975f5c5SAndroid Build Coastguard Worker }
132*8975f5c5SAndroid Build Coastguard Worker
133*8975f5c5SAndroid Build Coastguard Worker for (size_t j = inputComponentCount; j < lastNonAlphaOutputComponent; j++)
134*8975f5c5SAndroid Build Coastguard Worker {
135*8975f5c5SAndroid Build Coastguard Worker // Set remaining G/B channels to 0.
136*8975f5c5SAndroid Build Coastguard Worker offsetOutput[j] = 0;
137*8975f5c5SAndroid Build Coastguard Worker }
138*8975f5c5SAndroid Build Coastguard Worker
139*8975f5c5SAndroid Build Coastguard Worker if (inputComponentCount < outputComponentCount && outputComponentCount == 4)
140*8975f5c5SAndroid Build Coastguard Worker {
141*8975f5c5SAndroid Build Coastguard Worker // On integer formats, we must set the Alpha channel to 1 if it's unused.
142*8975f5c5SAndroid Build Coastguard Worker offsetOutput[3] = 1;
143*8975f5c5SAndroid Build Coastguard Worker }
144*8975f5c5SAndroid Build Coastguard Worker }
145*8975f5c5SAndroid Build Coastguard Worker }
146*8975f5c5SAndroid Build Coastguard Worker
147*8975f5c5SAndroid Build Coastguard Worker template <size_t inputComponentCount, size_t outputComponentCount>
Copy8SnormTo16SnormVertexData(const uint8_t * input,size_t stride,size_t count,uint8_t * output)148*8975f5c5SAndroid Build Coastguard Worker inline void Copy8SnormTo16SnormVertexData(const uint8_t *input,
149*8975f5c5SAndroid Build Coastguard Worker size_t stride,
150*8975f5c5SAndroid Build Coastguard Worker size_t count,
151*8975f5c5SAndroid Build Coastguard Worker uint8_t *output)
152*8975f5c5SAndroid Build Coastguard Worker {
153*8975f5c5SAndroid Build Coastguard Worker for (size_t i = 0; i < count; i++)
154*8975f5c5SAndroid Build Coastguard Worker {
155*8975f5c5SAndroid Build Coastguard Worker const GLbyte *offsetInput = reinterpret_cast<const GLbyte *>(input + i * stride);
156*8975f5c5SAndroid Build Coastguard Worker GLshort *offsetOutput = reinterpret_cast<GLshort *>(output) + i * outputComponentCount;
157*8975f5c5SAndroid Build Coastguard Worker
158*8975f5c5SAndroid Build Coastguard Worker for (size_t j = 0; j < inputComponentCount; j++)
159*8975f5c5SAndroid Build Coastguard Worker {
160*8975f5c5SAndroid Build Coastguard Worker // The original GLbyte value ranges from -128 to +127 (INT8_MAX).
161*8975f5c5SAndroid Build Coastguard Worker // When converted to GLshort, the value must be scaled to between -32768 and +32767
162*8975f5c5SAndroid Build Coastguard Worker // (INT16_MAX).
163*8975f5c5SAndroid Build Coastguard Worker if (offsetInput[j] > 0)
164*8975f5c5SAndroid Build Coastguard Worker {
165*8975f5c5SAndroid Build Coastguard Worker offsetOutput[j] =
166*8975f5c5SAndroid Build Coastguard Worker offsetInput[j] << 8 | offsetInput[j] << 1 | ((offsetInput[j] & 0x40) >> 6);
167*8975f5c5SAndroid Build Coastguard Worker }
168*8975f5c5SAndroid Build Coastguard Worker else
169*8975f5c5SAndroid Build Coastguard Worker {
170*8975f5c5SAndroid Build Coastguard Worker offsetOutput[j] = offsetInput[j] << 8;
171*8975f5c5SAndroid Build Coastguard Worker }
172*8975f5c5SAndroid Build Coastguard Worker }
173*8975f5c5SAndroid Build Coastguard Worker
174*8975f5c5SAndroid Build Coastguard Worker for (size_t j = inputComponentCount; j < std::min<size_t>(outputComponentCount, 3); j++)
175*8975f5c5SAndroid Build Coastguard Worker {
176*8975f5c5SAndroid Build Coastguard Worker // Set remaining G/B channels to 0.
177*8975f5c5SAndroid Build Coastguard Worker offsetOutput[j] = 0;
178*8975f5c5SAndroid Build Coastguard Worker }
179*8975f5c5SAndroid Build Coastguard Worker
180*8975f5c5SAndroid Build Coastguard Worker if (inputComponentCount < outputComponentCount && outputComponentCount == 4)
181*8975f5c5SAndroid Build Coastguard Worker {
182*8975f5c5SAndroid Build Coastguard Worker // On normalized formats, we must set the Alpha channel to the max value if it's unused.
183*8975f5c5SAndroid Build Coastguard Worker offsetOutput[3] = INT16_MAX;
184*8975f5c5SAndroid Build Coastguard Worker }
185*8975f5c5SAndroid Build Coastguard Worker }
186*8975f5c5SAndroid Build Coastguard Worker }
187*8975f5c5SAndroid Build Coastguard Worker
188*8975f5c5SAndroid Build Coastguard Worker template <size_t inputComponentCount, size_t outputComponentCount>
Copy32FixedTo32FVertexData(const uint8_t * input,size_t stride,size_t count,uint8_t * output)189*8975f5c5SAndroid Build Coastguard Worker inline void Copy32FixedTo32FVertexData(const uint8_t *input,
190*8975f5c5SAndroid Build Coastguard Worker size_t stride,
191*8975f5c5SAndroid Build Coastguard Worker size_t count,
192*8975f5c5SAndroid Build Coastguard Worker uint8_t *output)
193*8975f5c5SAndroid Build Coastguard Worker {
194*8975f5c5SAndroid Build Coastguard Worker static const float divisor = 1.0f / (1 << 16);
195*8975f5c5SAndroid Build Coastguard Worker
196*8975f5c5SAndroid Build Coastguard Worker for (size_t i = 0; i < count; i++)
197*8975f5c5SAndroid Build Coastguard Worker {
198*8975f5c5SAndroid Build Coastguard Worker const uint8_t *offsetInput = input + i * stride;
199*8975f5c5SAndroid Build Coastguard Worker float *offsetOutput = reinterpret_cast<float *>(output) + i * outputComponentCount;
200*8975f5c5SAndroid Build Coastguard Worker
201*8975f5c5SAndroid Build Coastguard Worker // GLfixed access must be 4-byte aligned on arm32, input and stride sometimes are not
202*8975f5c5SAndroid Build Coastguard Worker if (reinterpret_cast<uintptr_t>(offsetInput) % sizeof(GLfixed) == 0)
203*8975f5c5SAndroid Build Coastguard Worker {
204*8975f5c5SAndroid Build Coastguard Worker for (size_t j = 0; j < inputComponentCount; j++)
205*8975f5c5SAndroid Build Coastguard Worker {
206*8975f5c5SAndroid Build Coastguard Worker offsetOutput[j] =
207*8975f5c5SAndroid Build Coastguard Worker static_cast<float>(reinterpret_cast<const GLfixed *>(offsetInput)[j]) * divisor;
208*8975f5c5SAndroid Build Coastguard Worker }
209*8975f5c5SAndroid Build Coastguard Worker }
210*8975f5c5SAndroid Build Coastguard Worker else
211*8975f5c5SAndroid Build Coastguard Worker {
212*8975f5c5SAndroid Build Coastguard Worker for (size_t j = 0; j < inputComponentCount; j++)
213*8975f5c5SAndroid Build Coastguard Worker {
214*8975f5c5SAndroid Build Coastguard Worker GLfixed alignedInput;
215*8975f5c5SAndroid Build Coastguard Worker memcpy(&alignedInput, offsetInput + j * sizeof(GLfixed), sizeof(GLfixed));
216*8975f5c5SAndroid Build Coastguard Worker offsetOutput[j] = static_cast<float>(alignedInput) * divisor;
217*8975f5c5SAndroid Build Coastguard Worker }
218*8975f5c5SAndroid Build Coastguard Worker }
219*8975f5c5SAndroid Build Coastguard Worker
220*8975f5c5SAndroid Build Coastguard Worker // 4-component output formats would need special padding in the alpha channel.
221*8975f5c5SAndroid Build Coastguard Worker static_assert(!(inputComponentCount < 4 && outputComponentCount == 4),
222*8975f5c5SAndroid Build Coastguard Worker "An inputComponentCount less than 4 and an outputComponentCount equal to 4 "
223*8975f5c5SAndroid Build Coastguard Worker "is not supported.");
224*8975f5c5SAndroid Build Coastguard Worker
225*8975f5c5SAndroid Build Coastguard Worker for (size_t j = inputComponentCount; j < outputComponentCount; j++)
226*8975f5c5SAndroid Build Coastguard Worker {
227*8975f5c5SAndroid Build Coastguard Worker offsetOutput[j] = 0.0f;
228*8975f5c5SAndroid Build Coastguard Worker }
229*8975f5c5SAndroid Build Coastguard Worker }
230*8975f5c5SAndroid Build Coastguard Worker }
231*8975f5c5SAndroid Build Coastguard Worker
232*8975f5c5SAndroid Build Coastguard Worker template <typename T,
233*8975f5c5SAndroid Build Coastguard Worker size_t inputComponentCount,
234*8975f5c5SAndroid Build Coastguard Worker size_t outputComponentCount,
235*8975f5c5SAndroid Build Coastguard Worker bool normalized,
236*8975f5c5SAndroid Build Coastguard Worker bool toHalf>
CopyToFloatVertexData(const uint8_t * input,size_t stride,size_t count,uint8_t * output)237*8975f5c5SAndroid Build Coastguard Worker inline void CopyToFloatVertexData(const uint8_t *input,
238*8975f5c5SAndroid Build Coastguard Worker size_t stride,
239*8975f5c5SAndroid Build Coastguard Worker size_t count,
240*8975f5c5SAndroid Build Coastguard Worker uint8_t *output)
241*8975f5c5SAndroid Build Coastguard Worker {
242*8975f5c5SAndroid Build Coastguard Worker typedef std::numeric_limits<T> NL;
243*8975f5c5SAndroid Build Coastguard Worker typedef typename std::conditional<toHalf, GLhalf, float>::type outputType;
244*8975f5c5SAndroid Build Coastguard Worker
245*8975f5c5SAndroid Build Coastguard Worker for (size_t i = 0; i < count; i++)
246*8975f5c5SAndroid Build Coastguard Worker {
247*8975f5c5SAndroid Build Coastguard Worker const T *offsetInput = reinterpret_cast<const T *>(input + (stride * i));
248*8975f5c5SAndroid Build Coastguard Worker outputType *offsetOutput =
249*8975f5c5SAndroid Build Coastguard Worker reinterpret_cast<outputType *>(output) + i * outputComponentCount;
250*8975f5c5SAndroid Build Coastguard Worker
251*8975f5c5SAndroid Build Coastguard Worker T offsetInputAligned[inputComponentCount];
252*8975f5c5SAndroid Build Coastguard Worker offsetInput =
253*8975f5c5SAndroid Build Coastguard Worker GetAlignedOffsetInput<T, inputComponentCount>(offsetInput, &offsetInputAligned[0]);
254*8975f5c5SAndroid Build Coastguard Worker
255*8975f5c5SAndroid Build Coastguard Worker for (size_t j = 0; j < inputComponentCount; j++)
256*8975f5c5SAndroid Build Coastguard Worker {
257*8975f5c5SAndroid Build Coastguard Worker float result = 0;
258*8975f5c5SAndroid Build Coastguard Worker
259*8975f5c5SAndroid Build Coastguard Worker if (normalized)
260*8975f5c5SAndroid Build Coastguard Worker {
261*8975f5c5SAndroid Build Coastguard Worker if (NL::is_signed)
262*8975f5c5SAndroid Build Coastguard Worker {
263*8975f5c5SAndroid Build Coastguard Worker result = static_cast<float>(offsetInput[j]) / static_cast<float>(NL::max());
264*8975f5c5SAndroid Build Coastguard Worker result = result >= -1.0f ? result : -1.0f;
265*8975f5c5SAndroid Build Coastguard Worker }
266*8975f5c5SAndroid Build Coastguard Worker else
267*8975f5c5SAndroid Build Coastguard Worker {
268*8975f5c5SAndroid Build Coastguard Worker result = static_cast<float>(offsetInput[j]) / static_cast<float>(NL::max());
269*8975f5c5SAndroid Build Coastguard Worker }
270*8975f5c5SAndroid Build Coastguard Worker }
271*8975f5c5SAndroid Build Coastguard Worker else
272*8975f5c5SAndroid Build Coastguard Worker {
273*8975f5c5SAndroid Build Coastguard Worker result = static_cast<float>(offsetInput[j]);
274*8975f5c5SAndroid Build Coastguard Worker }
275*8975f5c5SAndroid Build Coastguard Worker
276*8975f5c5SAndroid Build Coastguard Worker if (toHalf)
277*8975f5c5SAndroid Build Coastguard Worker {
278*8975f5c5SAndroid Build Coastguard Worker offsetOutput[j] = gl::float32ToFloat16(result);
279*8975f5c5SAndroid Build Coastguard Worker }
280*8975f5c5SAndroid Build Coastguard Worker else
281*8975f5c5SAndroid Build Coastguard Worker {
282*8975f5c5SAndroid Build Coastguard Worker offsetOutput[j] = static_cast<outputType>(result);
283*8975f5c5SAndroid Build Coastguard Worker }
284*8975f5c5SAndroid Build Coastguard Worker }
285*8975f5c5SAndroid Build Coastguard Worker
286*8975f5c5SAndroid Build Coastguard Worker for (size_t j = inputComponentCount; j < outputComponentCount; j++)
287*8975f5c5SAndroid Build Coastguard Worker {
288*8975f5c5SAndroid Build Coastguard Worker offsetOutput[j] = 0;
289*8975f5c5SAndroid Build Coastguard Worker }
290*8975f5c5SAndroid Build Coastguard Worker
291*8975f5c5SAndroid Build Coastguard Worker if (inputComponentCount < 4 && outputComponentCount == 4)
292*8975f5c5SAndroid Build Coastguard Worker {
293*8975f5c5SAndroid Build Coastguard Worker if (toHalf)
294*8975f5c5SAndroid Build Coastguard Worker {
295*8975f5c5SAndroid Build Coastguard Worker offsetOutput[3] = gl::Float16One;
296*8975f5c5SAndroid Build Coastguard Worker }
297*8975f5c5SAndroid Build Coastguard Worker else
298*8975f5c5SAndroid Build Coastguard Worker {
299*8975f5c5SAndroid Build Coastguard Worker offsetOutput[3] = static_cast<outputType>(gl::Float32One);
300*8975f5c5SAndroid Build Coastguard Worker }
301*8975f5c5SAndroid Build Coastguard Worker }
302*8975f5c5SAndroid Build Coastguard Worker }
303*8975f5c5SAndroid Build Coastguard Worker }
304*8975f5c5SAndroid Build Coastguard Worker
305*8975f5c5SAndroid Build Coastguard Worker template <size_t inputComponentCount, size_t outputComponentCount>
Copy32FTo16FVertexData(const uint8_t * input,size_t stride,size_t count,uint8_t * output)306*8975f5c5SAndroid Build Coastguard Worker void Copy32FTo16FVertexData(const uint8_t *input, size_t stride, size_t count, uint8_t *output)
307*8975f5c5SAndroid Build Coastguard Worker {
308*8975f5c5SAndroid Build Coastguard Worker const unsigned short kZero = gl::float32ToFloat16(0.0f);
309*8975f5c5SAndroid Build Coastguard Worker const unsigned short kOne = gl::float32ToFloat16(1.0f);
310*8975f5c5SAndroid Build Coastguard Worker
311*8975f5c5SAndroid Build Coastguard Worker for (size_t i = 0; i < count; i++)
312*8975f5c5SAndroid Build Coastguard Worker {
313*8975f5c5SAndroid Build Coastguard Worker const float *offsetInput = reinterpret_cast<const float *>(input + (stride * i));
314*8975f5c5SAndroid Build Coastguard Worker unsigned short *offsetOutput =
315*8975f5c5SAndroid Build Coastguard Worker reinterpret_cast<unsigned short *>(output) + i * outputComponentCount;
316*8975f5c5SAndroid Build Coastguard Worker
317*8975f5c5SAndroid Build Coastguard Worker for (size_t j = 0; j < inputComponentCount; j++)
318*8975f5c5SAndroid Build Coastguard Worker {
319*8975f5c5SAndroid Build Coastguard Worker offsetOutput[j] = gl::float32ToFloat16(offsetInput[j]);
320*8975f5c5SAndroid Build Coastguard Worker }
321*8975f5c5SAndroid Build Coastguard Worker
322*8975f5c5SAndroid Build Coastguard Worker for (size_t j = inputComponentCount; j < outputComponentCount; j++)
323*8975f5c5SAndroid Build Coastguard Worker {
324*8975f5c5SAndroid Build Coastguard Worker offsetOutput[j] = (j == 3) ? kOne : kZero;
325*8975f5c5SAndroid Build Coastguard Worker }
326*8975f5c5SAndroid Build Coastguard Worker }
327*8975f5c5SAndroid Build Coastguard Worker }
328*8975f5c5SAndroid Build Coastguard Worker
CopyXYZ32FToXYZ9E5(const uint8_t * input,size_t stride,size_t count,uint8_t * output)329*8975f5c5SAndroid Build Coastguard Worker inline void CopyXYZ32FToXYZ9E5(const uint8_t *input, size_t stride, size_t count, uint8_t *output)
330*8975f5c5SAndroid Build Coastguard Worker {
331*8975f5c5SAndroid Build Coastguard Worker for (size_t i = 0; i < count; i++)
332*8975f5c5SAndroid Build Coastguard Worker {
333*8975f5c5SAndroid Build Coastguard Worker const float *offsetInput = reinterpret_cast<const float *>(input + (stride * i));
334*8975f5c5SAndroid Build Coastguard Worker unsigned int *offsetOutput = reinterpret_cast<unsigned int *>(output) + i;
335*8975f5c5SAndroid Build Coastguard Worker
336*8975f5c5SAndroid Build Coastguard Worker *offsetOutput = gl::convertRGBFloatsTo999E5(offsetInput[0], offsetInput[1], offsetInput[2]);
337*8975f5c5SAndroid Build Coastguard Worker }
338*8975f5c5SAndroid Build Coastguard Worker }
339*8975f5c5SAndroid Build Coastguard Worker
CopyXYZ32FToX11Y11B10F(const uint8_t * input,size_t stride,size_t count,uint8_t * output)340*8975f5c5SAndroid Build Coastguard Worker inline void CopyXYZ32FToX11Y11B10F(const uint8_t *input,
341*8975f5c5SAndroid Build Coastguard Worker size_t stride,
342*8975f5c5SAndroid Build Coastguard Worker size_t count,
343*8975f5c5SAndroid Build Coastguard Worker uint8_t *output)
344*8975f5c5SAndroid Build Coastguard Worker {
345*8975f5c5SAndroid Build Coastguard Worker for (size_t i = 0; i < count; i++)
346*8975f5c5SAndroid Build Coastguard Worker {
347*8975f5c5SAndroid Build Coastguard Worker const float *offsetInput = reinterpret_cast<const float *>(input + (stride * i));
348*8975f5c5SAndroid Build Coastguard Worker unsigned int *offsetOutput = reinterpret_cast<unsigned int *>(output) + i;
349*8975f5c5SAndroid Build Coastguard Worker
350*8975f5c5SAndroid Build Coastguard Worker *offsetOutput = gl::float32ToFloat11(offsetInput[0]) << 0 |
351*8975f5c5SAndroid Build Coastguard Worker gl::float32ToFloat11(offsetInput[1]) << 11 |
352*8975f5c5SAndroid Build Coastguard Worker gl::float32ToFloat10(offsetInput[2]) << 22;
353*8975f5c5SAndroid Build Coastguard Worker }
354*8975f5c5SAndroid Build Coastguard Worker }
355*8975f5c5SAndroid Build Coastguard Worker
356*8975f5c5SAndroid Build Coastguard Worker namespace priv
357*8975f5c5SAndroid Build Coastguard Worker {
358*8975f5c5SAndroid Build Coastguard Worker
359*8975f5c5SAndroid Build Coastguard Worker template <bool isSigned, bool normalized, bool toFloat, bool toHalf>
CopyPackedRGB(uint32_t data,uint8_t * output)360*8975f5c5SAndroid Build Coastguard Worker static inline void CopyPackedRGB(uint32_t data, uint8_t *output)
361*8975f5c5SAndroid Build Coastguard Worker {
362*8975f5c5SAndroid Build Coastguard Worker const uint32_t rgbSignMask = 0x200; // 1 set at the 9 bit
363*8975f5c5SAndroid Build Coastguard Worker const uint32_t negativeMask = 0xFFFFFC00; // All bits from 10 to 31 set to 1
364*8975f5c5SAndroid Build Coastguard Worker
365*8975f5c5SAndroid Build Coastguard Worker if (toFloat || toHalf)
366*8975f5c5SAndroid Build Coastguard Worker {
367*8975f5c5SAndroid Build Coastguard Worker GLfloat finalValue = static_cast<GLfloat>(data);
368*8975f5c5SAndroid Build Coastguard Worker if (isSigned)
369*8975f5c5SAndroid Build Coastguard Worker {
370*8975f5c5SAndroid Build Coastguard Worker if (data & rgbSignMask)
371*8975f5c5SAndroid Build Coastguard Worker {
372*8975f5c5SAndroid Build Coastguard Worker int negativeNumber = data | negativeMask;
373*8975f5c5SAndroid Build Coastguard Worker finalValue = static_cast<GLfloat>(negativeNumber);
374*8975f5c5SAndroid Build Coastguard Worker }
375*8975f5c5SAndroid Build Coastguard Worker
376*8975f5c5SAndroid Build Coastguard Worker if (normalized)
377*8975f5c5SAndroid Build Coastguard Worker {
378*8975f5c5SAndroid Build Coastguard Worker const int32_t maxValue = 0x1FF; // 1 set in bits 0 through 8
379*8975f5c5SAndroid Build Coastguard Worker const int32_t minValue = 0xFFFFFE01; // Inverse of maxValue
380*8975f5c5SAndroid Build Coastguard Worker
381*8975f5c5SAndroid Build Coastguard Worker // A 10-bit two's complement number has the possibility of being minValue - 1 but
382*8975f5c5SAndroid Build Coastguard Worker // OpenGL's normalization rules dictate that it should be clamped to minValue in
383*8975f5c5SAndroid Build Coastguard Worker // this case.
384*8975f5c5SAndroid Build Coastguard Worker if (finalValue < minValue)
385*8975f5c5SAndroid Build Coastguard Worker {
386*8975f5c5SAndroid Build Coastguard Worker finalValue = minValue;
387*8975f5c5SAndroid Build Coastguard Worker }
388*8975f5c5SAndroid Build Coastguard Worker
389*8975f5c5SAndroid Build Coastguard Worker const int32_t halfRange = (maxValue - minValue) >> 1;
390*8975f5c5SAndroid Build Coastguard Worker finalValue = ((finalValue - minValue) / halfRange) - 1.0f;
391*8975f5c5SAndroid Build Coastguard Worker }
392*8975f5c5SAndroid Build Coastguard Worker }
393*8975f5c5SAndroid Build Coastguard Worker else
394*8975f5c5SAndroid Build Coastguard Worker {
395*8975f5c5SAndroid Build Coastguard Worker if (normalized)
396*8975f5c5SAndroid Build Coastguard Worker {
397*8975f5c5SAndroid Build Coastguard Worker const uint32_t maxValue = 0x3FF; // 1 set in bits 0 through 9
398*8975f5c5SAndroid Build Coastguard Worker finalValue /= static_cast<GLfloat>(maxValue);
399*8975f5c5SAndroid Build Coastguard Worker }
400*8975f5c5SAndroid Build Coastguard Worker }
401*8975f5c5SAndroid Build Coastguard Worker
402*8975f5c5SAndroid Build Coastguard Worker if (toHalf)
403*8975f5c5SAndroid Build Coastguard Worker {
404*8975f5c5SAndroid Build Coastguard Worker *reinterpret_cast<GLhalf *>(output) = gl::float32ToFloat16(finalValue);
405*8975f5c5SAndroid Build Coastguard Worker }
406*8975f5c5SAndroid Build Coastguard Worker else
407*8975f5c5SAndroid Build Coastguard Worker {
408*8975f5c5SAndroid Build Coastguard Worker *reinterpret_cast<GLfloat *>(output) = finalValue;
409*8975f5c5SAndroid Build Coastguard Worker }
410*8975f5c5SAndroid Build Coastguard Worker }
411*8975f5c5SAndroid Build Coastguard Worker else
412*8975f5c5SAndroid Build Coastguard Worker {
413*8975f5c5SAndroid Build Coastguard Worker if (isSigned)
414*8975f5c5SAndroid Build Coastguard Worker {
415*8975f5c5SAndroid Build Coastguard Worker GLshort *intOutput = reinterpret_cast<GLshort *>(output);
416*8975f5c5SAndroid Build Coastguard Worker
417*8975f5c5SAndroid Build Coastguard Worker if (data & rgbSignMask)
418*8975f5c5SAndroid Build Coastguard Worker {
419*8975f5c5SAndroid Build Coastguard Worker *intOutput = static_cast<GLshort>(data | negativeMask);
420*8975f5c5SAndroid Build Coastguard Worker }
421*8975f5c5SAndroid Build Coastguard Worker else
422*8975f5c5SAndroid Build Coastguard Worker {
423*8975f5c5SAndroid Build Coastguard Worker *intOutput = static_cast<GLshort>(data);
424*8975f5c5SAndroid Build Coastguard Worker }
425*8975f5c5SAndroid Build Coastguard Worker }
426*8975f5c5SAndroid Build Coastguard Worker else
427*8975f5c5SAndroid Build Coastguard Worker {
428*8975f5c5SAndroid Build Coastguard Worker GLushort *uintOutput = reinterpret_cast<GLushort *>(output);
429*8975f5c5SAndroid Build Coastguard Worker *uintOutput = static_cast<GLushort>(data);
430*8975f5c5SAndroid Build Coastguard Worker }
431*8975f5c5SAndroid Build Coastguard Worker }
432*8975f5c5SAndroid Build Coastguard Worker }
433*8975f5c5SAndroid Build Coastguard Worker
434*8975f5c5SAndroid Build Coastguard Worker template <bool isSigned, bool normalized, bool toFloat, bool toHalf>
CopyPackedAlpha(uint32_t data,uint8_t * output)435*8975f5c5SAndroid Build Coastguard Worker inline void CopyPackedAlpha(uint32_t data, uint8_t *output)
436*8975f5c5SAndroid Build Coastguard Worker {
437*8975f5c5SAndroid Build Coastguard Worker ASSERT(data >= 0 && data <= 3);
438*8975f5c5SAndroid Build Coastguard Worker
439*8975f5c5SAndroid Build Coastguard Worker if (toFloat || toHalf)
440*8975f5c5SAndroid Build Coastguard Worker {
441*8975f5c5SAndroid Build Coastguard Worker GLfloat finalValue = 0;
442*8975f5c5SAndroid Build Coastguard Worker if (isSigned)
443*8975f5c5SAndroid Build Coastguard Worker {
444*8975f5c5SAndroid Build Coastguard Worker if (normalized)
445*8975f5c5SAndroid Build Coastguard Worker {
446*8975f5c5SAndroid Build Coastguard Worker switch (data)
447*8975f5c5SAndroid Build Coastguard Worker {
448*8975f5c5SAndroid Build Coastguard Worker case 0x0:
449*8975f5c5SAndroid Build Coastguard Worker finalValue = 0.0f;
450*8975f5c5SAndroid Build Coastguard Worker break;
451*8975f5c5SAndroid Build Coastguard Worker case 0x1:
452*8975f5c5SAndroid Build Coastguard Worker finalValue = 1.0f;
453*8975f5c5SAndroid Build Coastguard Worker break;
454*8975f5c5SAndroid Build Coastguard Worker case 0x2:
455*8975f5c5SAndroid Build Coastguard Worker finalValue = -1.0f;
456*8975f5c5SAndroid Build Coastguard Worker break;
457*8975f5c5SAndroid Build Coastguard Worker case 0x3:
458*8975f5c5SAndroid Build Coastguard Worker finalValue = -1.0f;
459*8975f5c5SAndroid Build Coastguard Worker break;
460*8975f5c5SAndroid Build Coastguard Worker default:
461*8975f5c5SAndroid Build Coastguard Worker UNREACHABLE();
462*8975f5c5SAndroid Build Coastguard Worker }
463*8975f5c5SAndroid Build Coastguard Worker }
464*8975f5c5SAndroid Build Coastguard Worker else
465*8975f5c5SAndroid Build Coastguard Worker {
466*8975f5c5SAndroid Build Coastguard Worker switch (data)
467*8975f5c5SAndroid Build Coastguard Worker {
468*8975f5c5SAndroid Build Coastguard Worker case 0x0:
469*8975f5c5SAndroid Build Coastguard Worker finalValue = 0.0f;
470*8975f5c5SAndroid Build Coastguard Worker break;
471*8975f5c5SAndroid Build Coastguard Worker case 0x1:
472*8975f5c5SAndroid Build Coastguard Worker finalValue = 1.0f;
473*8975f5c5SAndroid Build Coastguard Worker break;
474*8975f5c5SAndroid Build Coastguard Worker case 0x2:
475*8975f5c5SAndroid Build Coastguard Worker finalValue = -2.0f;
476*8975f5c5SAndroid Build Coastguard Worker break;
477*8975f5c5SAndroid Build Coastguard Worker case 0x3:
478*8975f5c5SAndroid Build Coastguard Worker finalValue = -1.0f;
479*8975f5c5SAndroid Build Coastguard Worker break;
480*8975f5c5SAndroid Build Coastguard Worker default:
481*8975f5c5SAndroid Build Coastguard Worker UNREACHABLE();
482*8975f5c5SAndroid Build Coastguard Worker }
483*8975f5c5SAndroid Build Coastguard Worker }
484*8975f5c5SAndroid Build Coastguard Worker }
485*8975f5c5SAndroid Build Coastguard Worker else
486*8975f5c5SAndroid Build Coastguard Worker {
487*8975f5c5SAndroid Build Coastguard Worker if (normalized)
488*8975f5c5SAndroid Build Coastguard Worker {
489*8975f5c5SAndroid Build Coastguard Worker finalValue = data / 3.0f;
490*8975f5c5SAndroid Build Coastguard Worker }
491*8975f5c5SAndroid Build Coastguard Worker else
492*8975f5c5SAndroid Build Coastguard Worker {
493*8975f5c5SAndroid Build Coastguard Worker finalValue = static_cast<float>(data);
494*8975f5c5SAndroid Build Coastguard Worker }
495*8975f5c5SAndroid Build Coastguard Worker }
496*8975f5c5SAndroid Build Coastguard Worker
497*8975f5c5SAndroid Build Coastguard Worker if (toHalf)
498*8975f5c5SAndroid Build Coastguard Worker {
499*8975f5c5SAndroid Build Coastguard Worker *reinterpret_cast<GLhalf *>(output) = gl::float32ToFloat16(finalValue);
500*8975f5c5SAndroid Build Coastguard Worker }
501*8975f5c5SAndroid Build Coastguard Worker else
502*8975f5c5SAndroid Build Coastguard Worker {
503*8975f5c5SAndroid Build Coastguard Worker *reinterpret_cast<GLfloat *>(output) = finalValue;
504*8975f5c5SAndroid Build Coastguard Worker }
505*8975f5c5SAndroid Build Coastguard Worker }
506*8975f5c5SAndroid Build Coastguard Worker else
507*8975f5c5SAndroid Build Coastguard Worker {
508*8975f5c5SAndroid Build Coastguard Worker if (isSigned)
509*8975f5c5SAndroid Build Coastguard Worker {
510*8975f5c5SAndroid Build Coastguard Worker GLshort *intOutput = reinterpret_cast<GLshort *>(output);
511*8975f5c5SAndroid Build Coastguard Worker switch (data)
512*8975f5c5SAndroid Build Coastguard Worker {
513*8975f5c5SAndroid Build Coastguard Worker case 0x0:
514*8975f5c5SAndroid Build Coastguard Worker *intOutput = 0;
515*8975f5c5SAndroid Build Coastguard Worker break;
516*8975f5c5SAndroid Build Coastguard Worker case 0x1:
517*8975f5c5SAndroid Build Coastguard Worker *intOutput = 1;
518*8975f5c5SAndroid Build Coastguard Worker break;
519*8975f5c5SAndroid Build Coastguard Worker case 0x2:
520*8975f5c5SAndroid Build Coastguard Worker *intOutput = -2;
521*8975f5c5SAndroid Build Coastguard Worker break;
522*8975f5c5SAndroid Build Coastguard Worker case 0x3:
523*8975f5c5SAndroid Build Coastguard Worker *intOutput = -1;
524*8975f5c5SAndroid Build Coastguard Worker break;
525*8975f5c5SAndroid Build Coastguard Worker default:
526*8975f5c5SAndroid Build Coastguard Worker UNREACHABLE();
527*8975f5c5SAndroid Build Coastguard Worker }
528*8975f5c5SAndroid Build Coastguard Worker }
529*8975f5c5SAndroid Build Coastguard Worker else
530*8975f5c5SAndroid Build Coastguard Worker {
531*8975f5c5SAndroid Build Coastguard Worker *reinterpret_cast<GLushort *>(output) = static_cast<GLushort>(data);
532*8975f5c5SAndroid Build Coastguard Worker }
533*8975f5c5SAndroid Build Coastguard Worker }
534*8975f5c5SAndroid Build Coastguard Worker }
535*8975f5c5SAndroid Build Coastguard Worker
536*8975f5c5SAndroid Build Coastguard Worker } // namespace priv
537*8975f5c5SAndroid Build Coastguard Worker
538*8975f5c5SAndroid Build Coastguard Worker template <bool isSigned, bool normalized, bool toFloat, bool toHalf>
CopyXYZ10W2ToXYZWFloatVertexData(const uint8_t * input,size_t stride,size_t count,uint8_t * output)539*8975f5c5SAndroid Build Coastguard Worker inline void CopyXYZ10W2ToXYZWFloatVertexData(const uint8_t *input,
540*8975f5c5SAndroid Build Coastguard Worker size_t stride,
541*8975f5c5SAndroid Build Coastguard Worker size_t count,
542*8975f5c5SAndroid Build Coastguard Worker uint8_t *output)
543*8975f5c5SAndroid Build Coastguard Worker {
544*8975f5c5SAndroid Build Coastguard Worker const size_t outputComponentSize = toFloat && !toHalf ? 4 : 2;
545*8975f5c5SAndroid Build Coastguard Worker const size_t componentCount = 4;
546*8975f5c5SAndroid Build Coastguard Worker
547*8975f5c5SAndroid Build Coastguard Worker const uint32_t rgbMask = 0x3FF; // 1 set in bits 0 through 9
548*8975f5c5SAndroid Build Coastguard Worker const size_t redShift = 0; // red is bits 0 through 9
549*8975f5c5SAndroid Build Coastguard Worker const size_t greenShift = 10; // green is bits 10 through 19
550*8975f5c5SAndroid Build Coastguard Worker const size_t blueShift = 20; // blue is bits 20 through 29
551*8975f5c5SAndroid Build Coastguard Worker
552*8975f5c5SAndroid Build Coastguard Worker const uint32_t alphaMask = 0x3; // 1 set in bits 0 and 1
553*8975f5c5SAndroid Build Coastguard Worker const size_t alphaShift = 30; // Alpha is the 30 and 31 bits
554*8975f5c5SAndroid Build Coastguard Worker
555*8975f5c5SAndroid Build Coastguard Worker for (size_t i = 0; i < count; i++)
556*8975f5c5SAndroid Build Coastguard Worker {
557*8975f5c5SAndroid Build Coastguard Worker GLuint packedValue = *reinterpret_cast<const GLuint *>(input + (i * stride));
558*8975f5c5SAndroid Build Coastguard Worker uint8_t *offsetOutput = output + (i * outputComponentSize * componentCount);
559*8975f5c5SAndroid Build Coastguard Worker
560*8975f5c5SAndroid Build Coastguard Worker priv::CopyPackedRGB<isSigned, normalized, toFloat, toHalf>(
561*8975f5c5SAndroid Build Coastguard Worker (packedValue >> redShift) & rgbMask, offsetOutput + (0 * outputComponentSize));
562*8975f5c5SAndroid Build Coastguard Worker priv::CopyPackedRGB<isSigned, normalized, toFloat, toHalf>(
563*8975f5c5SAndroid Build Coastguard Worker (packedValue >> greenShift) & rgbMask, offsetOutput + (1 * outputComponentSize));
564*8975f5c5SAndroid Build Coastguard Worker priv::CopyPackedRGB<isSigned, normalized, toFloat, toHalf>(
565*8975f5c5SAndroid Build Coastguard Worker (packedValue >> blueShift) & rgbMask, offsetOutput + (2 * outputComponentSize));
566*8975f5c5SAndroid Build Coastguard Worker priv::CopyPackedAlpha<isSigned, normalized, toFloat, toHalf>(
567*8975f5c5SAndroid Build Coastguard Worker (packedValue >> alphaShift) & alphaMask, offsetOutput + (3 * outputComponentSize));
568*8975f5c5SAndroid Build Coastguard Worker }
569*8975f5c5SAndroid Build Coastguard Worker }
570*8975f5c5SAndroid Build Coastguard Worker
571*8975f5c5SAndroid Build Coastguard Worker template <bool isSigned, bool normalized, bool toHalf>
CopyXYZ10ToXYZWFloatVertexData(const uint8_t * input,size_t stride,size_t count,uint8_t * output)572*8975f5c5SAndroid Build Coastguard Worker inline void CopyXYZ10ToXYZWFloatVertexData(const uint8_t *input,
573*8975f5c5SAndroid Build Coastguard Worker size_t stride,
574*8975f5c5SAndroid Build Coastguard Worker size_t count,
575*8975f5c5SAndroid Build Coastguard Worker uint8_t *output)
576*8975f5c5SAndroid Build Coastguard Worker {
577*8975f5c5SAndroid Build Coastguard Worker const size_t outputComponentSize = toHalf ? 2 : 4;
578*8975f5c5SAndroid Build Coastguard Worker const size_t componentCount = 4;
579*8975f5c5SAndroid Build Coastguard Worker
580*8975f5c5SAndroid Build Coastguard Worker const uint32_t rgbMask = 0x3FF; // 1 set in bits 0 through 9
581*8975f5c5SAndroid Build Coastguard Worker const size_t redShift = 22; // red is bits 22 through 31
582*8975f5c5SAndroid Build Coastguard Worker const size_t greenShift = 12; // green is bits 12 through 21
583*8975f5c5SAndroid Build Coastguard Worker const size_t blueShift = 2; // blue is bits 2 through 11
584*8975f5c5SAndroid Build Coastguard Worker
585*8975f5c5SAndroid Build Coastguard Worker const uint32_t alphaDefaultValueBits = normalized ? (isSigned ? 0x1 : 0x3) : 0x1;
586*8975f5c5SAndroid Build Coastguard Worker
587*8975f5c5SAndroid Build Coastguard Worker for (size_t i = 0; i < count; i++)
588*8975f5c5SAndroid Build Coastguard Worker {
589*8975f5c5SAndroid Build Coastguard Worker GLuint packedValue = *reinterpret_cast<const GLuint *>(input + (i * stride));
590*8975f5c5SAndroid Build Coastguard Worker uint8_t *offsetOutput = output + (i * outputComponentSize * componentCount);
591*8975f5c5SAndroid Build Coastguard Worker
592*8975f5c5SAndroid Build Coastguard Worker priv::CopyPackedRGB<isSigned, normalized, true, toHalf>(
593*8975f5c5SAndroid Build Coastguard Worker (packedValue >> redShift) & rgbMask, offsetOutput + (0 * outputComponentSize));
594*8975f5c5SAndroid Build Coastguard Worker priv::CopyPackedRGB<isSigned, normalized, true, toHalf>(
595*8975f5c5SAndroid Build Coastguard Worker (packedValue >> greenShift) & rgbMask, offsetOutput + (1 * outputComponentSize));
596*8975f5c5SAndroid Build Coastguard Worker priv::CopyPackedRGB<isSigned, normalized, true, toHalf>(
597*8975f5c5SAndroid Build Coastguard Worker (packedValue >> blueShift) & rgbMask, offsetOutput + (2 * outputComponentSize));
598*8975f5c5SAndroid Build Coastguard Worker priv::CopyPackedAlpha<isSigned, normalized, true, toHalf>(
599*8975f5c5SAndroid Build Coastguard Worker alphaDefaultValueBits, offsetOutput + (3 * outputComponentSize));
600*8975f5c5SAndroid Build Coastguard Worker }
601*8975f5c5SAndroid Build Coastguard Worker }
602*8975f5c5SAndroid Build Coastguard Worker
603*8975f5c5SAndroid Build Coastguard Worker template <bool isSigned, bool normalized, bool toHalf>
CopyW2XYZ10ToXYZWFloatVertexData(const uint8_t * input,size_t stride,size_t count,uint8_t * output)604*8975f5c5SAndroid Build Coastguard Worker inline void CopyW2XYZ10ToXYZWFloatVertexData(const uint8_t *input,
605*8975f5c5SAndroid Build Coastguard Worker size_t stride,
606*8975f5c5SAndroid Build Coastguard Worker size_t count,
607*8975f5c5SAndroid Build Coastguard Worker uint8_t *output)
608*8975f5c5SAndroid Build Coastguard Worker {
609*8975f5c5SAndroid Build Coastguard Worker const size_t outputComponentSize = toHalf ? 2 : 4;
610*8975f5c5SAndroid Build Coastguard Worker const size_t componentCount = 4;
611*8975f5c5SAndroid Build Coastguard Worker
612*8975f5c5SAndroid Build Coastguard Worker const uint32_t rgbMask = 0x3FF; // 1 set in bits 0 through 9
613*8975f5c5SAndroid Build Coastguard Worker const size_t redShift = 22; // red is bits 22 through 31
614*8975f5c5SAndroid Build Coastguard Worker const size_t greenShift = 12; // green is bits 12 through 21
615*8975f5c5SAndroid Build Coastguard Worker const size_t blueShift = 2; // blue is bits 2 through 11
616*8975f5c5SAndroid Build Coastguard Worker
617*8975f5c5SAndroid Build Coastguard Worker const uint32_t alphaMask = 0x3; // 1 set in bits 0 and 1
618*8975f5c5SAndroid Build Coastguard Worker const size_t alphaShift = 0; // Alpha is the 30 and 31 bits
619*8975f5c5SAndroid Build Coastguard Worker
620*8975f5c5SAndroid Build Coastguard Worker for (size_t i = 0; i < count; i++)
621*8975f5c5SAndroid Build Coastguard Worker {
622*8975f5c5SAndroid Build Coastguard Worker GLuint packedValue = *reinterpret_cast<const GLuint *>(input + (i * stride));
623*8975f5c5SAndroid Build Coastguard Worker uint8_t *offsetOutput = output + (i * outputComponentSize * componentCount);
624*8975f5c5SAndroid Build Coastguard Worker
625*8975f5c5SAndroid Build Coastguard Worker priv::CopyPackedRGB<isSigned, normalized, true, toHalf>(
626*8975f5c5SAndroid Build Coastguard Worker (packedValue >> redShift) & rgbMask, offsetOutput + (0 * outputComponentSize));
627*8975f5c5SAndroid Build Coastguard Worker priv::CopyPackedRGB<isSigned, normalized, true, toHalf>(
628*8975f5c5SAndroid Build Coastguard Worker (packedValue >> greenShift) & rgbMask, offsetOutput + (1 * outputComponentSize));
629*8975f5c5SAndroid Build Coastguard Worker priv::CopyPackedRGB<isSigned, normalized, true, toHalf>(
630*8975f5c5SAndroid Build Coastguard Worker (packedValue >> blueShift) & rgbMask, offsetOutput + (2 * outputComponentSize));
631*8975f5c5SAndroid Build Coastguard Worker priv::CopyPackedAlpha<isSigned, normalized, true, toHalf>(
632*8975f5c5SAndroid Build Coastguard Worker (packedValue >> alphaShift) & alphaMask, offsetOutput + (3 * outputComponentSize));
633*8975f5c5SAndroid Build Coastguard Worker }
634*8975f5c5SAndroid Build Coastguard Worker }
635*8975f5c5SAndroid Build Coastguard Worker } // namespace rx
636