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