1// 2// Copyright (c) 2014-2015 The ANGLE Project Authors. All rights reserved. 3// Use of this source code is governed by a BSD-style license that can be 4// found in the LICENSE file. 5// 6 7namespace rx 8{ 9 10template <typename T, size_t inputComponentCount, size_t outputComponentCount, uint32_t alphaDefaultValueBits> 11inline void CopyNativeVertexData(const uint8_t *input, size_t stride, size_t count, uint8_t *output) 12{ 13 const size_t attribSize = sizeof(T)* inputComponentCount; 14 15 if (attribSize == stride && inputComponentCount == outputComponentCount) 16 { 17 memcpy(output, input, count * attribSize); 18 return; 19 } 20 21 if (inputComponentCount == outputComponentCount) 22 { 23 for (size_t i = 0; i < count; i++) 24 { 25 const T *offsetInput = reinterpret_cast<const T*>(input + (i * stride)); 26 T *offsetOutput = reinterpret_cast<T*>(output) + i * outputComponentCount; 27 28 memcpy(offsetOutput, offsetInput, attribSize); 29 } 30 return; 31 } 32 33 const T defaultAlphaValue = gl::bitCast<T>(alphaDefaultValueBits); 34 const size_t lastNonAlphaOutputComponent = std::min<size_t>(outputComponentCount, 3); 35 36 for (size_t i = 0; i < count; i++) 37 { 38 const T *offsetInput = reinterpret_cast<const T*>(input + (i * stride)); 39 T *offsetOutput = reinterpret_cast<T*>(output) + i * outputComponentCount; 40 41 memcpy(offsetOutput, offsetInput, attribSize); 42 43 if (inputComponentCount < lastNonAlphaOutputComponent) 44 { 45 // Set the remaining G/B channels to 0. 46 size_t numComponents = (lastNonAlphaOutputComponent - inputComponentCount); 47 memset(&offsetOutput[inputComponentCount], 0, numComponents * sizeof(T)); 48 } 49 50 if (inputComponentCount < outputComponentCount && outputComponentCount == 4) 51 { 52 // Set the remaining alpha channel to the defaultAlphaValue. 53 offsetOutput[3] = defaultAlphaValue; 54 } 55 } 56} 57 58template <size_t inputComponentCount, size_t outputComponentCount> 59inline void Copy8SintTo16SintVertexData(const uint8_t *input, size_t stride, size_t count, uint8_t *output) 60{ 61 const size_t lastNonAlphaOutputComponent = std::min<size_t>(outputComponentCount, 3); 62 63 for (size_t i = 0; i < count; i++) 64 { 65 const GLbyte *offsetInput = reinterpret_cast<const GLbyte*>(input + i * stride); 66 GLshort *offsetOutput = reinterpret_cast<GLshort*>(output)+i * outputComponentCount; 67 68 for (size_t j = 0; j < inputComponentCount; j++) 69 { 70 offsetOutput[j] = static_cast<GLshort>(offsetInput[j]); 71 } 72 73 for (size_t j = inputComponentCount; j < lastNonAlphaOutputComponent; j++) 74 { 75 // Set remaining G/B channels to 0. 76 offsetOutput[j] = 0; 77 } 78 79 if (inputComponentCount < outputComponentCount && outputComponentCount == 4) 80 { 81 // On integer formats, we must set the Alpha channel to 1 if it's unused. 82 offsetOutput[3] = 1; 83 } 84 } 85} 86 87template <size_t inputComponentCount, size_t outputComponentCount> 88inline void Copy8SnormTo16SnormVertexData(const uint8_t *input, size_t stride, size_t count, uint8_t *output) 89{ 90 for (size_t i = 0; i < count; i++) 91 { 92 const GLbyte *offsetInput = reinterpret_cast<const GLbyte*>(input + i * stride); 93 GLshort *offsetOutput = reinterpret_cast<GLshort*>(output) + i * outputComponentCount; 94 95 for (size_t j = 0; j < inputComponentCount; j++) 96 { 97 // The original GLbyte value ranges from -128 to +127 (INT8_MAX). 98 // When converted to GLshort, the value must be scaled to between -32768 and +32767 (INT16_MAX). 99 if (offsetInput[j] > 0) 100 { 101 offsetOutput[j] = offsetInput[j] << 8 | offsetInput[j] << 1 | ((offsetInput[j] & 0x40) >> 6); 102 } 103 else 104 { 105 offsetOutput[j] = offsetInput[j] << 8; 106 } 107 } 108 109 for (size_t j = inputComponentCount; j < std::min<size_t>(outputComponentCount, 3); j++) 110 { 111 // Set remaining G/B channels to 0. 112 offsetOutput[j] = 0; 113 } 114 115 if (inputComponentCount < outputComponentCount && outputComponentCount == 4) 116 { 117 // On normalized formats, we must set the Alpha channel to the max value if it's unused. 118 offsetOutput[3] = INT16_MAX; 119 } 120 } 121} 122 123template <size_t inputComponentCount, size_t outputComponentCount> 124inline void Copy32FixedTo32FVertexData(const uint8_t *input, size_t stride, size_t count, uint8_t *output) 125{ 126 static const float divisor = 1.0f / (1 << 16); 127 128 for (size_t i = 0; i < count; i++) 129 { 130 const GLfixed* offsetInput = reinterpret_cast<const GLfixed*>(input + (stride * i)); 131 float* offsetOutput = reinterpret_cast<float*>(output) + i * outputComponentCount; 132 133 for (size_t j = 0; j < inputComponentCount; j++) 134 { 135 offsetOutput[j] = static_cast<float>(offsetInput[j]) * divisor; 136 } 137 138 // 4-component output formats would need special padding in the alpha channel. 139 static_assert(!(inputComponentCount < 4 && outputComponentCount == 4), 140 "An inputComponentCount less than 4 and an outputComponentCount equal to 4 is not supported."); 141 142 for (size_t j = inputComponentCount; j < outputComponentCount; j++) 143 { 144 offsetOutput[j] = 0.0f; 145 } 146 } 147} 148 149template <typename T, size_t inputComponentCount, size_t outputComponentCount, bool normalized> 150inline void CopyTo32FVertexData(const uint8_t *input, size_t stride, size_t count, uint8_t *output) 151{ 152 typedef std::numeric_limits<T> NL; 153 154 for (size_t i = 0; i < count; i++) 155 { 156 const T *offsetInput = reinterpret_cast<const T*>(input + (stride * i)); 157 float *offsetOutput = reinterpret_cast<float*>(output) + i * outputComponentCount; 158 159 for (size_t j = 0; j < inputComponentCount; j++) 160 { 161 if (normalized) 162 { 163 if (NL::is_signed) 164 { 165 const float divisor = 1.0f / (2 * static_cast<float>(NL::max()) + 1); 166 offsetOutput[j] = (2 * static_cast<float>(offsetInput[j]) + 1) * divisor; 167 } 168 else 169 { 170 offsetOutput[j] = static_cast<float>(offsetInput[j]) / NL::max(); 171 } 172 } 173 else 174 { 175 offsetOutput[j] = static_cast<float>(offsetInput[j]); 176 } 177 } 178 179 // This would require special padding. 180 static_assert(!(inputComponentCount < 4 && outputComponentCount == 4), 181 "An inputComponentCount less than 4 and an outputComponentCount equal to 4 is not supported."); 182 183 for (size_t j = inputComponentCount; j < outputComponentCount; j++) 184 { 185 offsetOutput[j] = 0.0f; 186 } 187 } 188} 189 190namespace priv 191{ 192 193template <bool isSigned, bool normalized, bool toFloat> 194static inline void CopyPackedRGB(uint32_t data, uint8_t *output) 195{ 196 const uint32_t rgbSignMask = 0x200; // 1 set at the 9 bit 197 const uint32_t negativeMask = 0xFFFFFC00; // All bits from 10 to 31 set to 1 198 199 if (toFloat) 200 { 201 GLfloat *floatOutput = reinterpret_cast<GLfloat*>(output); 202 if (isSigned) 203 { 204 GLfloat finalValue = 0; 205 if (data & rgbSignMask) 206 { 207 int negativeNumber = data | negativeMask; 208 finalValue = static_cast<GLfloat>(negativeNumber); 209 } 210 else 211 { 212 finalValue = static_cast<GLfloat>(data); 213 } 214 215 if (normalized) 216 { 217 const int32_t maxValue = 0x1FF; // 1 set in bits 0 through 8 218 const int32_t minValue = 0xFFFFFE01; // Inverse of maxValue 219 220 // A 10-bit two's complement number has the possibility of being minValue - 1 but 221 // OpenGL's normalization rules dictate that it should be clamped to minValue in this 222 // case. 223 if (finalValue < minValue) 224 { 225 finalValue = minValue; 226 } 227 228 const int32_t halfRange = (maxValue - minValue) >> 1; 229 *floatOutput = ((finalValue - minValue) / halfRange) - 1.0f; 230 } 231 else 232 { 233 *floatOutput = finalValue; 234 } 235 } 236 else 237 { 238 if (normalized) 239 { 240 const uint32_t maxValue = 0x3FF; // 1 set in bits 0 through 9 241 *floatOutput = static_cast<GLfloat>(data) / static_cast<GLfloat>(maxValue); 242 } 243 else 244 { 245 *floatOutput = static_cast<GLfloat>(data); 246 } 247 } 248 } 249 else 250 { 251 if (isSigned) 252 { 253 GLshort *intOutput = reinterpret_cast<GLshort*>(output); 254 255 if (data & rgbSignMask) 256 { 257 *intOutput = static_cast<GLshort>(data | negativeMask); 258 } 259 else 260 { 261 *intOutput = static_cast<GLshort>(data); 262 } 263 } 264 else 265 { 266 GLushort *uintOutput = reinterpret_cast<GLushort*>(output); 267 *uintOutput = static_cast<GLushort>(data); 268 } 269 } 270} 271 272template <bool isSigned, bool normalized, bool toFloat> 273inline void CopyPackedAlpha(uint32_t data, uint8_t *output) 274{ 275 if (toFloat) 276 { 277 GLfloat *floatOutput = reinterpret_cast<GLfloat*>(output); 278 if (isSigned) 279 { 280 if (normalized) 281 { 282 switch (data) 283 { 284 case 0x0: *floatOutput = 0.0f; break; 285 case 0x1: *floatOutput = 1.0f; break; 286 case 0x2: *floatOutput = -1.0f; break; 287 case 0x3: *floatOutput = -1.0f; break; 288 default: UNREACHABLE(); 289 } 290 } 291 else 292 { 293 switch (data) 294 { 295 case 0x0: *floatOutput = 0.0f; break; 296 case 0x1: *floatOutput = 1.0f; break; 297 case 0x2: *floatOutput = -2.0f; break; 298 case 0x3: *floatOutput = -1.0f; break; 299 default: UNREACHABLE(); 300 } 301 } 302 } 303 else 304 { 305 if (normalized) 306 { 307 switch (data) 308 { 309 case 0x0: *floatOutput = 0.0f / 3.0f; break; 310 case 0x1: *floatOutput = 1.0f / 3.0f; break; 311 case 0x2: *floatOutput = 2.0f / 3.0f; break; 312 case 0x3: *floatOutput = 3.0f / 3.0f; break; 313 default: UNREACHABLE(); 314 } 315 } 316 else 317 { 318 switch (data) 319 { 320 case 0x0: *floatOutput = 0.0f; break; 321 case 0x1: *floatOutput = 1.0f; break; 322 case 0x2: *floatOutput = 2.0f; break; 323 case 0x3: *floatOutput = 3.0f; break; 324 default: UNREACHABLE(); 325 } 326 } 327 } 328 } 329 else 330 { 331 if (isSigned) 332 { 333 GLshort *intOutput = reinterpret_cast<GLshort*>(output); 334 switch (data) 335 { 336 case 0x0: *intOutput = 0; break; 337 case 0x1: *intOutput = 1; break; 338 case 0x2: *intOutput = -2; break; 339 case 0x3: *intOutput = -1; break; 340 default: UNREACHABLE(); 341 } 342 } 343 else 344 { 345 GLushort *uintOutput = reinterpret_cast<GLushort*>(output); 346 switch (data) 347 { 348 case 0x0: *uintOutput = 0; break; 349 case 0x1: *uintOutput = 1; break; 350 case 0x2: *uintOutput = 2; break; 351 case 0x3: *uintOutput = 3; break; 352 default: UNREACHABLE(); 353 } 354 } 355 } 356} 357 358} 359 360template <bool isSigned, bool normalized, bool toFloat> 361inline void CopyXYZ10W2ToXYZW32FVertexData(const uint8_t *input, size_t stride, size_t count, uint8_t *output) 362{ 363 const size_t outputComponentSize = toFloat ? 4 : 2; 364 const size_t componentCount = 4; 365 366 const uint32_t rgbMask = 0x3FF; // 1 set in bits 0 through 9 367 const size_t redShift = 0; // red is bits 0 through 9 368 const size_t greenShift = 10; // green is bits 10 through 19 369 const size_t blueShift = 20; // blue is bits 20 through 29 370 371 const uint32_t alphaMask = 0x3; // 1 set in bits 0 and 1 372 const size_t alphaShift = 30; // Alpha is the 30 and 31 bits 373 374 for (size_t i = 0; i < count; i++) 375 { 376 GLuint packedValue = *reinterpret_cast<const GLuint*>(input + (i * stride)); 377 uint8_t *offsetOutput = output + (i * outputComponentSize * componentCount); 378 379 priv::CopyPackedRGB<isSigned, normalized, toFloat>( (packedValue >> redShift) & rgbMask, offsetOutput + (0 * outputComponentSize)); 380 priv::CopyPackedRGB<isSigned, normalized, toFloat>( (packedValue >> greenShift) & rgbMask, offsetOutput + (1 * outputComponentSize)); 381 priv::CopyPackedRGB<isSigned, normalized, toFloat>( (packedValue >> blueShift) & rgbMask, offsetOutput + (2 * outputComponentSize)); 382 priv::CopyPackedAlpha<isSigned, normalized, toFloat>((packedValue >> alphaShift) & alphaMask, offsetOutput + (3 * outputComponentSize)); 383 } 384} 385 386} 387