xref: /aosp_15_r20/external/angle/src/libANGLE/renderer/copyvertex.inc.h (revision 8975f5c5ed3d1c378011245431ada316dfb6f244)
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