From 07ec47532df1ee8dd4d2b4ff0425ba523a889aea Mon Sep 17 00:00:00 2001 From: Allan Sandfeld Jensen Date: Thu, 2 May 2019 13:23:39 +0200 Subject: [Backport] Fix for CVE-2019-5817 MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Fix OOB access for dynamic attribs with offsets. We were not properly adding the offset to compute the right bounds. Bug: chromium:943709 Reviewed-on: https://chromium-review.googlesource.com/c/angle/angle/+/1548441 Reviewed-on: https://chromium-review.googlesource.com/c/angle/angle/+/1545528 Change-Id: I93e714b46dd366d5833fffa858ea3ab0322ffa92 Reviewed-by: Michael BrĂ¼ning --- .../angle/src/libANGLE/renderer/copyvertex.h | 36 +- .../angle/src/libANGLE/renderer/copyvertex.inc | 402 ----------------- .../angle/src/libANGLE/renderer/copyvertex.inc.h | 479 +++++++++++++++++++++ .../libANGLE/renderer/d3d/VertexDataManager.cpp | 26 +- chromium/third_party/angle/src/libGLESv2.gni | 2 +- 5 files changed, 517 insertions(+), 428 deletions(-) delete mode 100644 chromium/third_party/angle/src/libANGLE/renderer/copyvertex.inc create mode 100644 chromium/third_party/angle/src/libANGLE/renderer/copyvertex.inc.h (limited to 'chromium/third_party') diff --git a/chromium/third_party/angle/src/libANGLE/renderer/copyvertex.h b/chromium/third_party/angle/src/libANGLE/renderer/copyvertex.h index 7769a4f7f33..988e590f3b2 100644 --- a/chromium/third_party/angle/src/libANGLE/renderer/copyvertex.h +++ b/chromium/third_party/angle/src/libANGLE/renderer/copyvertex.h @@ -24,40 +24,34 @@ template -inline void CopyNativeVertexData(const uint8_t *input, +void CopyNativeVertexData(const uint8_t *input, size_t stride, size_t count, uint8_t *output); + +template +void Copy8SintTo16SintVertexData(const uint8_t *input, size_t stride, size_t count, uint8_t *output); -template -inline void Copy8SintTo16SintVertexData(const uint8_t *input, - size_t stride, - size_t count, - uint8_t *output); - template -inline void Copy8SnormTo16SnormVertexData(const uint8_t *input, - size_t stride, - size_t count, - uint8_t *output); +void Copy8SnormTo16SnormVertexData(const uint8_t *input, + size_t stride, + size_t count, + uint8_t *output); template -inline void Copy32FixedTo32FVertexData(const uint8_t *input, - size_t stride, - size_t count, - uint8_t *output); +void Copy32FixedTo32FVertexData(const uint8_t *input, size_t stride, size_t count, uint8_t *output); template -inline void CopyTo32FVertexData(const uint8_t *input, size_t stride, size_t count, uint8_t *output); +void CopyTo32FVertexData(const uint8_t *input, size_t stride, size_t count, uint8_t *output); template -inline void CopyXYZ10W2ToXYZW32FVertexData(const uint8_t *input, - size_t stride, - size_t count, - uint8_t *output); +void CopyXYZ10W2ToXYZW32FVertexData(const uint8_t *input, + size_t stride, + size_t count, + uint8_t *output); } // namespace rx -#include "copyvertex.inc" +#include "copyvertex.inc.h" #endif // LIBANGLE_RENDERER_COPYVERTEX_H_ diff --git a/chromium/third_party/angle/src/libANGLE/renderer/copyvertex.inc b/chromium/third_party/angle/src/libANGLE/renderer/copyvertex.inc deleted file mode 100644 index 7c3e73e59b7..00000000000 --- a/chromium/third_party/angle/src/libANGLE/renderer/copyvertex.inc +++ /dev/null @@ -1,402 +0,0 @@ -// -// 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: Implementation of vertex buffer copying and conversion functions - -namespace rx -{ - -template -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(input + (i * stride)); - T *offsetOutput = reinterpret_cast(output) + i * outputComponentCount; - - memcpy(offsetOutput, offsetInput, attribSize); - } - return; - } - - const T defaultAlphaValue = gl::bitCast(alphaDefaultValueBits); - const size_t lastNonAlphaOutputComponent = std::min(outputComponentCount, 3); - - for (size_t i = 0; i < count; i++) - { - const T *offsetInput = reinterpret_cast(input + (i * stride)); - T *offsetOutput = reinterpret_cast(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 -inline void Copy8SintTo16SintVertexData(const uint8_t *input, size_t stride, size_t count, uint8_t *output) -{ - const size_t lastNonAlphaOutputComponent = std::min(outputComponentCount, 3); - - for (size_t i = 0; i < count; i++) - { - const GLbyte *offsetInput = reinterpret_cast(input + i * stride); - GLshort *offsetOutput = reinterpret_cast(output)+i * outputComponentCount; - - for (size_t j = 0; j < inputComponentCount; j++) - { - offsetOutput[j] = static_cast(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 -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(input + i * stride); - GLshort *offsetOutput = reinterpret_cast(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(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 -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(output) + i * outputComponentCount; - - // GLfixed access must be 4-byte aligned on arm32, input and stride sometimes are not - if (reinterpret_cast(offsetInput) % sizeof(GLfixed) == 0) - { - for (size_t j = 0; j < inputComponentCount; j++) - { - offsetOutput[j] = - static_cast(reinterpret_cast(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(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 -inline void CopyTo32FVertexData(const uint8_t *input, size_t stride, size_t count, uint8_t *output) -{ - typedef std::numeric_limits NL; - - for (size_t i = 0; i < count; i++) - { - const T *offsetInput = reinterpret_cast(input + (stride * i)); - float *offsetOutput = reinterpret_cast(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(NL::max()) + 1); - offsetOutput[j] = (2 * static_cast(offsetInput[j]) + 1) * divisor; - } - else - { - offsetOutput[j] = static_cast(offsetInput[j]) / NL::max(); - } - } - else - { - offsetOutput[j] = static_cast(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 -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(output); - if (isSigned) - { - GLfloat finalValue = 0; - if (data & rgbSignMask) - { - int negativeNumber = data | negativeMask; - finalValue = static_cast(negativeNumber); - } - else - { - finalValue = static_cast(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(data) / static_cast(maxValue); - } - else - { - *floatOutput = static_cast(data); - } - } - } - else - { - if (isSigned) - { - GLshort *intOutput = reinterpret_cast(output); - - if (data & rgbSignMask) - { - *intOutput = static_cast(data | negativeMask); - } - else - { - *intOutput = static_cast(data); - } - } - else - { - GLushort *uintOutput = reinterpret_cast(output); - *uintOutput = static_cast(data); - } - } -} - -template -inline void CopyPackedAlpha(uint32_t data, uint8_t *output) -{ - if (toFloat) - { - GLfloat *floatOutput = reinterpret_cast(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(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(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(); - } - } - } -} - -} - -template -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(input + (i * stride)); - uint8_t *offsetOutput = output + (i * outputComponentSize * componentCount); - - priv::CopyPackedRGB( (packedValue >> redShift) & rgbMask, offsetOutput + (0 * outputComponentSize)); - priv::CopyPackedRGB( (packedValue >> greenShift) & rgbMask, offsetOutput + (1 * outputComponentSize)); - priv::CopyPackedRGB( (packedValue >> blueShift) & rgbMask, offsetOutput + (2 * outputComponentSize)); - priv::CopyPackedAlpha((packedValue >> alphaShift) & alphaMask, offsetOutput + (3 * outputComponentSize)); - } -} - -} diff --git a/chromium/third_party/angle/src/libANGLE/renderer/copyvertex.inc.h b/chromium/third_party/angle/src/libANGLE/renderer/copyvertex.inc.h new file mode 100644 index 00000000000..16c82adcf22 --- /dev/null +++ b/chromium/third_party/angle/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 +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(input + (i * stride)); + T *offsetOutput = reinterpret_cast(output) + i * outputComponentCount; + + memcpy(offsetOutput, offsetInput, attribSize); + } + return; + } + + const T defaultAlphaValue = gl::bitCast(alphaDefaultValueBits); + const size_t lastNonAlphaOutputComponent = std::min(outputComponentCount, 3); + + for (size_t i = 0; i < count; i++) + { + const T *offsetInput = reinterpret_cast(input + (i * stride)); + T *offsetOutput = reinterpret_cast(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 +inline void Copy8SintTo16SintVertexData(const uint8_t *input, + size_t stride, + size_t count, + uint8_t *output) +{ + const size_t lastNonAlphaOutputComponent = std::min(outputComponentCount, 3); + + for (size_t i = 0; i < count; i++) + { + const GLbyte *offsetInput = reinterpret_cast(input + i * stride); + GLshort *offsetOutput = reinterpret_cast(output) + i * outputComponentCount; + + for (size_t j = 0; j < inputComponentCount; j++) + { + offsetOutput[j] = static_cast(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 +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(input + i * stride); + GLshort *offsetOutput = reinterpret_cast(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(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 +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(output) + i * outputComponentCount; + + // GLfixed access must be 4-byte aligned on arm32, input and stride sometimes are not + if (reinterpret_cast(offsetInput) % sizeof(GLfixed) == 0) + { + for (size_t j = 0; j < inputComponentCount; j++) + { + offsetOutput[j] = + static_cast(reinterpret_cast(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(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 +inline void CopyTo32FVertexData(const uint8_t *input, size_t stride, size_t count, uint8_t *output) +{ + typedef std::numeric_limits NL; + + for (size_t i = 0; i < count; i++) + { + const T *offsetInput = reinterpret_cast(input + (stride * i)); + float *offsetOutput = reinterpret_cast(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(NL::max()) + 1); + offsetOutput[j] = (2 * static_cast(offsetInput[j]) + 1) * divisor; + } + else + { + offsetOutput[j] = static_cast(offsetInput[j]) / NL::max(); + } + } + else + { + offsetOutput[j] = static_cast(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 +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(output); + if (isSigned) + { + GLfloat finalValue = 0; + if (data & rgbSignMask) + { + int negativeNumber = data | negativeMask; + finalValue = static_cast(negativeNumber); + } + else + { + finalValue = static_cast(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(data) / static_cast(maxValue); + } + else + { + *floatOutput = static_cast(data); + } + } + } + else + { + if (isSigned) + { + GLshort *intOutput = reinterpret_cast(output); + + if (data & rgbSignMask) + { + *intOutput = static_cast(data | negativeMask); + } + else + { + *intOutput = static_cast(data); + } + } + else + { + GLushort *uintOutput = reinterpret_cast(output); + *uintOutput = static_cast(data); + } + } +} + +template +inline void CopyPackedAlpha(uint32_t data, uint8_t *output) +{ + if (toFloat) + { + GLfloat *floatOutput = reinterpret_cast(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(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(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 +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(input + (i * stride)); + uint8_t *offsetOutput = output + (i * outputComponentSize * componentCount); + + priv::CopyPackedRGB( + (packedValue >> redShift) & rgbMask, offsetOutput + (0 * outputComponentSize)); + priv::CopyPackedRGB( + (packedValue >> greenShift) & rgbMask, offsetOutput + (1 * outputComponentSize)); + priv::CopyPackedRGB( + (packedValue >> blueShift) & rgbMask, offsetOutput + (2 * outputComponentSize)); + priv::CopyPackedAlpha( + (packedValue >> alphaShift) & alphaMask, offsetOutput + (3 * outputComponentSize)); + } +} + +} // namespace rx diff --git a/chromium/third_party/angle/src/libANGLE/renderer/d3d/VertexDataManager.cpp b/chromium/third_party/angle/src/libANGLE/renderer/d3d/VertexDataManager.cpp index 527f1942859..c22d7cfdcbd 100644 --- a/chromium/third_party/angle/src/libANGLE/renderer/d3d/VertexDataManager.cpp +++ b/chromium/third_party/angle/src/libANGLE/renderer/d3d/VertexDataManager.cpp @@ -37,7 +37,23 @@ enum CONSTANT_VERTEX_BUFFER_SIZE = 4096 }; -// Warning: you should ensure binding really matches attrib.bindingIndex before using this function. +// Warning: ensure the binding matches attrib.bindingIndex before using these functions. +int64_t GetMaxAttributeByteOffsetForDraw(const gl::VertexAttribute &attrib, + const gl::VertexBinding &binding, + int64_t elementCount) +{ + CheckedNumeric stride = ComputeVertexAttributeStride(attrib, binding); + CheckedNumeric offset = ComputeVertexAttributeOffset(attrib, binding); + CheckedNumeric size = ComputeVertexAttributeTypeSize(attrib); + + ASSERT(elementCount > 0); + + CheckedNumeric result = + stride * (CheckedNumeric(elementCount) - 1) + size + offset; + return result.ValueOrDefault(std::numeric_limits::max()); +} + +// Warning: ensure the binding matches attrib.bindingIndex before using these functions. int ElementsInBuffer(const gl::VertexAttribute &attrib, const gl::VertexBinding &binding, unsigned int size) @@ -482,10 +498,12 @@ angle::Result VertexDataManager::reserveSpaceForAttrib(const gl::Context *contex GLint firstVertexIndex = binding.getDivisor() > 0 ? 0 : start; int64_t maxVertexCount = static_cast(firstVertexIndex) + static_cast(totalCount); - int elementsInBuffer = - ElementsInBuffer(attrib, binding, static_cast(bufferD3D->getSize())); - ANGLE_CHECK(GetImplAs(context), maxVertexCount <= elementsInBuffer, + int64_t maxByte = GetMaxAttributeByteOffsetForDraw(attrib, binding, maxVertexCount); + + ASSERT(bufferD3D->getSize() <= static_cast(std::numeric_limits::max())); + ANGLE_CHECK(GetImplAs(context), + maxByte <= static_cast(bufferD3D->getSize()), "Vertex buffer is not big enough for the draw call.", GL_INVALID_OPERATION); } return mStreamingBuffer.reserveVertexSpace(context, attrib, binding, totalCount, instances); diff --git a/chromium/third_party/angle/src/libGLESv2.gni b/chromium/third_party/angle/src/libGLESv2.gni index cc6676a94a9..a7170e3252c 100644 --- a/chromium/third_party/angle/src/libGLESv2.gni +++ b/chromium/third_party/angle/src/libGLESv2.gni @@ -304,7 +304,7 @@ libangle_sources = [ "src/libANGLE/renderer/TransformFeedbackImpl.h", "src/libANGLE/renderer/VertexArrayImpl.h", "src/libANGLE/renderer/copyvertex.h", - "src/libANGLE/renderer/copyvertex.inc", + "src/libANGLE/renderer/copyvertex.inc.h", "src/libANGLE/renderer/load_functions_table.h", "src/libANGLE/renderer/load_functions_table_autogen.cpp", "src/libANGLE/renderer/renderer_utils.cpp", -- cgit v1.2.1