diff options
Diffstat (limited to 'gfx/angle/checkout/src/libANGLE/renderer/copyvertex.inc.h')
-rw-r--r-- | gfx/angle/checkout/src/libANGLE/renderer/copyvertex.inc.h | 479 |
1 files changed, 479 insertions, 0 deletions
diff --git a/gfx/angle/checkout/src/libANGLE/renderer/copyvertex.inc.h b/gfx/angle/checkout/src/libANGLE/renderer/copyvertex.inc.h new file mode 100644 index 0000000000..16c82adcf2 --- /dev/null +++ b/gfx/angle/checkout/src/libANGLE/renderer/copyvertex.inc.h @@ -0,0 +1,479 @@ +// +// Copyright (c) 2014-2015 The ANGLE Project Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. +// + +// copyvertex.inc.h: Implementation of vertex buffer copying and conversion functions + +namespace rx +{ + +template <typename T, + size_t inputComponentCount, + size_t outputComponentCount, + uint32_t alphaDefaultValueBits> +inline void CopyNativeVertexData(const uint8_t *input, size_t stride, size_t count, uint8_t *output) +{ + const size_t attribSize = sizeof(T) * inputComponentCount; + + if (attribSize == stride && inputComponentCount == outputComponentCount) + { + memcpy(output, input, count * attribSize); + return; + } + + if (inputComponentCount == outputComponentCount) + { + for (size_t i = 0; i < count; i++) + { + const T *offsetInput = reinterpret_cast<const T *>(input + (i * stride)); + T *offsetOutput = reinterpret_cast<T *>(output) + i * outputComponentCount; + + memcpy(offsetOutput, offsetInput, attribSize); + } + return; + } + + const T defaultAlphaValue = gl::bitCast<T>(alphaDefaultValueBits); + const size_t lastNonAlphaOutputComponent = std::min<size_t>(outputComponentCount, 3); + + for (size_t i = 0; i < count; i++) + { + const T *offsetInput = reinterpret_cast<const T *>(input + (i * stride)); + T *offsetOutput = reinterpret_cast<T *>(output) + i * outputComponentCount; + + memcpy(offsetOutput, offsetInput, attribSize); + + if (inputComponentCount < lastNonAlphaOutputComponent) + { + // Set the remaining G/B channels to 0. + size_t numComponents = (lastNonAlphaOutputComponent - inputComponentCount); + memset(&offsetOutput[inputComponentCount], 0, numComponents * sizeof(T)); + } + + if (inputComponentCount < outputComponentCount && outputComponentCount == 4) + { + // Set the remaining alpha channel to the defaultAlphaValue. + offsetOutput[3] = defaultAlphaValue; + } + } +} + +template <size_t inputComponentCount, size_t outputComponentCount> +inline void Copy8SintTo16SintVertexData(const uint8_t *input, + size_t stride, + size_t count, + uint8_t *output) +{ + const size_t lastNonAlphaOutputComponent = std::min<size_t>(outputComponentCount, 3); + + for (size_t i = 0; i < count; i++) + { + const GLbyte *offsetInput = reinterpret_cast<const GLbyte *>(input + i * stride); + GLshort *offsetOutput = reinterpret_cast<GLshort *>(output) + i * outputComponentCount; + + for (size_t j = 0; j < inputComponentCount; j++) + { + offsetOutput[j] = static_cast<GLshort>(offsetInput[j]); + } + + for (size_t j = inputComponentCount; j < lastNonAlphaOutputComponent; j++) + { + // Set remaining G/B channels to 0. + offsetOutput[j] = 0; + } + + if (inputComponentCount < outputComponentCount && outputComponentCount == 4) + { + // On integer formats, we must set the Alpha channel to 1 if it's unused. + offsetOutput[3] = 1; + } + } +} + +template <size_t inputComponentCount, size_t outputComponentCount> +inline void Copy8SnormTo16SnormVertexData(const uint8_t *input, + size_t stride, + size_t count, + uint8_t *output) +{ + for (size_t i = 0; i < count; i++) + { + const GLbyte *offsetInput = reinterpret_cast<const GLbyte *>(input + i * stride); + GLshort *offsetOutput = reinterpret_cast<GLshort *>(output) + i * outputComponentCount; + + for (size_t j = 0; j < inputComponentCount; j++) + { + // The original GLbyte value ranges from -128 to +127 (INT8_MAX). + // When converted to GLshort, the value must be scaled to between -32768 and +32767 + // (INT16_MAX). + if (offsetInput[j] > 0) + { + offsetOutput[j] = + offsetInput[j] << 8 | offsetInput[j] << 1 | ((offsetInput[j] & 0x40) >> 6); + } + else + { + offsetOutput[j] = offsetInput[j] << 8; + } + } + + for (size_t j = inputComponentCount; j < std::min<size_t>(outputComponentCount, 3); j++) + { + // Set remaining G/B channels to 0. + offsetOutput[j] = 0; + } + + if (inputComponentCount < outputComponentCount && outputComponentCount == 4) + { + // On normalized formats, we must set the Alpha channel to the max value if it's unused. + offsetOutput[3] = INT16_MAX; + } + } +} + +template <size_t inputComponentCount, size_t outputComponentCount> +inline void Copy32FixedTo32FVertexData(const uint8_t *input, + size_t stride, + size_t count, + uint8_t *output) +{ + static const float divisor = 1.0f / (1 << 16); + + for (size_t i = 0; i < count; i++) + { + const uint8_t *offsetInput = input + i * stride; + float *offsetOutput = reinterpret_cast<float *>(output) + i * outputComponentCount; + + // GLfixed access must be 4-byte aligned on arm32, input and stride sometimes are not + if (reinterpret_cast<uintptr_t>(offsetInput) % sizeof(GLfixed) == 0) + { + for (size_t j = 0; j < inputComponentCount; j++) + { + offsetOutput[j] = + static_cast<float>(reinterpret_cast<const GLfixed *>(offsetInput)[j]) * divisor; + } + } + else + { + for (size_t j = 0; j < inputComponentCount; j++) + { + GLfixed alignedInput; + memcpy(&alignedInput, offsetInput + j * sizeof(GLfixed), sizeof(GLfixed)); + offsetOutput[j] = static_cast<float>(alignedInput) * divisor; + } + } + + // 4-component output formats would need special padding in the alpha channel. + static_assert(!(inputComponentCount < 4 && outputComponentCount == 4), + "An inputComponentCount less than 4 and an outputComponentCount equal to 4 " + "is not supported."); + + for (size_t j = inputComponentCount; j < outputComponentCount; j++) + { + offsetOutput[j] = 0.0f; + } + } +} + +template <typename T, size_t inputComponentCount, size_t outputComponentCount, bool normalized> +inline void CopyTo32FVertexData(const uint8_t *input, size_t stride, size_t count, uint8_t *output) +{ + typedef std::numeric_limits<T> NL; + + for (size_t i = 0; i < count; i++) + { + const T *offsetInput = reinterpret_cast<const T *>(input + (stride * i)); + float *offsetOutput = reinterpret_cast<float *>(output) + i * outputComponentCount; + + for (size_t j = 0; j < inputComponentCount; j++) + { + if (normalized) + { + if (NL::is_signed) + { + const float divisor = 1.0f / (2 * static_cast<float>(NL::max()) + 1); + offsetOutput[j] = (2 * static_cast<float>(offsetInput[j]) + 1) * divisor; + } + else + { + offsetOutput[j] = static_cast<float>(offsetInput[j]) / NL::max(); + } + } + else + { + offsetOutput[j] = static_cast<float>(offsetInput[j]); + } + } + + // This would require special padding. + static_assert(!(inputComponentCount < 4 && outputComponentCount == 4), + "An inputComponentCount less than 4 and an outputComponentCount equal to 4 " + "is not supported."); + + for (size_t j = inputComponentCount; j < outputComponentCount; j++) + { + offsetOutput[j] = 0.0f; + } + } +} + +namespace priv +{ + +template <bool isSigned, bool normalized, bool toFloat> +static inline void CopyPackedRGB(uint32_t data, uint8_t *output) +{ + const uint32_t rgbSignMask = 0x200; // 1 set at the 9 bit + const uint32_t negativeMask = 0xFFFFFC00; // All bits from 10 to 31 set to 1 + + if (toFloat) + { + GLfloat *floatOutput = reinterpret_cast<GLfloat *>(output); + if (isSigned) + { + GLfloat finalValue = 0; + if (data & rgbSignMask) + { + int negativeNumber = data | negativeMask; + finalValue = static_cast<GLfloat>(negativeNumber); + } + else + { + finalValue = static_cast<GLfloat>(data); + } + + if (normalized) + { + const int32_t maxValue = 0x1FF; // 1 set in bits 0 through 8 + const int32_t minValue = 0xFFFFFE01; // Inverse of maxValue + + // A 10-bit two's complement number has the possibility of being minValue - 1 but + // OpenGL's normalization rules dictate that it should be clamped to minValue in + // this case. + if (finalValue < minValue) + { + finalValue = minValue; + } + + const int32_t halfRange = (maxValue - minValue) >> 1; + *floatOutput = ((finalValue - minValue) / halfRange) - 1.0f; + } + else + { + *floatOutput = finalValue; + } + } + else + { + if (normalized) + { + const uint32_t maxValue = 0x3FF; // 1 set in bits 0 through 9 + *floatOutput = static_cast<GLfloat>(data) / static_cast<GLfloat>(maxValue); + } + else + { + *floatOutput = static_cast<GLfloat>(data); + } + } + } + else + { + if (isSigned) + { + GLshort *intOutput = reinterpret_cast<GLshort *>(output); + + if (data & rgbSignMask) + { + *intOutput = static_cast<GLshort>(data | negativeMask); + } + else + { + *intOutput = static_cast<GLshort>(data); + } + } + else + { + GLushort *uintOutput = reinterpret_cast<GLushort *>(output); + *uintOutput = static_cast<GLushort>(data); + } + } +} + +template <bool isSigned, bool normalized, bool toFloat> +inline void CopyPackedAlpha(uint32_t data, uint8_t *output) +{ + if (toFloat) + { + GLfloat *floatOutput = reinterpret_cast<GLfloat *>(output); + if (isSigned) + { + if (normalized) + { + switch (data) + { + case 0x0: + *floatOutput = 0.0f; + break; + case 0x1: + *floatOutput = 1.0f; + break; + case 0x2: + *floatOutput = -1.0f; + break; + case 0x3: + *floatOutput = -1.0f; + break; + default: + UNREACHABLE(); + } + } + else + { + switch (data) + { + case 0x0: + *floatOutput = 0.0f; + break; + case 0x1: + *floatOutput = 1.0f; + break; + case 0x2: + *floatOutput = -2.0f; + break; + case 0x3: + *floatOutput = -1.0f; + break; + default: + UNREACHABLE(); + } + } + } + else + { + if (normalized) + { + switch (data) + { + case 0x0: + *floatOutput = 0.0f / 3.0f; + break; + case 0x1: + *floatOutput = 1.0f / 3.0f; + break; + case 0x2: + *floatOutput = 2.0f / 3.0f; + break; + case 0x3: + *floatOutput = 3.0f / 3.0f; + break; + default: + UNREACHABLE(); + } + } + else + { + switch (data) + { + case 0x0: + *floatOutput = 0.0f; + break; + case 0x1: + *floatOutput = 1.0f; + break; + case 0x2: + *floatOutput = 2.0f; + break; + case 0x3: + *floatOutput = 3.0f; + break; + default: + UNREACHABLE(); + } + } + } + } + else + { + if (isSigned) + { + GLshort *intOutput = reinterpret_cast<GLshort *>(output); + switch (data) + { + case 0x0: + *intOutput = 0; + break; + case 0x1: + *intOutput = 1; + break; + case 0x2: + *intOutput = -2; + break; + case 0x3: + *intOutput = -1; + break; + default: + UNREACHABLE(); + } + } + else + { + GLushort *uintOutput = reinterpret_cast<GLushort *>(output); + switch (data) + { + case 0x0: + *uintOutput = 0; + break; + case 0x1: + *uintOutput = 1; + break; + case 0x2: + *uintOutput = 2; + break; + case 0x3: + *uintOutput = 3; + break; + default: + UNREACHABLE(); + } + } + } +} + +} // namespace priv + +template <bool isSigned, bool normalized, bool toFloat> +inline void CopyXYZ10W2ToXYZW32FVertexData(const uint8_t *input, + size_t stride, + size_t count, + uint8_t *output) +{ + const size_t outputComponentSize = toFloat ? 4 : 2; + const size_t componentCount = 4; + + const uint32_t rgbMask = 0x3FF; // 1 set in bits 0 through 9 + const size_t redShift = 0; // red is bits 0 through 9 + const size_t greenShift = 10; // green is bits 10 through 19 + const size_t blueShift = 20; // blue is bits 20 through 29 + + const uint32_t alphaMask = 0x3; // 1 set in bits 0 and 1 + const size_t alphaShift = 30; // Alpha is the 30 and 31 bits + + for (size_t i = 0; i < count; i++) + { + GLuint packedValue = *reinterpret_cast<const GLuint *>(input + (i * stride)); + uint8_t *offsetOutput = output + (i * outputComponentSize * componentCount); + + priv::CopyPackedRGB<isSigned, normalized, toFloat>( + (packedValue >> redShift) & rgbMask, offsetOutput + (0 * outputComponentSize)); + priv::CopyPackedRGB<isSigned, normalized, toFloat>( + (packedValue >> greenShift) & rgbMask, offsetOutput + (1 * outputComponentSize)); + priv::CopyPackedRGB<isSigned, normalized, toFloat>( + (packedValue >> blueShift) & rgbMask, offsetOutput + (2 * outputComponentSize)); + priv::CopyPackedAlpha<isSigned, normalized, toFloat>( + (packedValue >> alphaShift) & alphaMask, offsetOutput + (3 * outputComponentSize)); + } +} + +} // namespace rx |