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