| /*------------------------------------------------------------------------- |
| * drawElements Quality Program Tester Core |
| * ---------------------------------------- |
| * |
| * Copyright 2014 The Android Open Source Project |
| * |
| * Licensed under the Apache License, Version 2.0 (the "License"); |
| * you may not use this file except in compliance with the License. |
| * You may obtain a copy of the License at |
| * |
| * http://www.apache.org/licenses/LICENSE-2.0 |
| * |
| * Unless required by applicable law or agreed to in writing, software |
| * distributed under the License is distributed on an "AS IS" BASIS, |
| * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. |
| * See the License for the specific language governing permissions and |
| * limitations under the License. |
| * |
| *//*! |
| * \file |
| * \brief Reference Texture Implementation. |
| *//*--------------------------------------------------------------------*/ |
| |
| #include "tcuTexture.hpp" |
| #include "deInt32.h" |
| #include "deFloat16.h" |
| #include "deMath.h" |
| #include "deMemory.h" |
| #include "tcuTestLog.hpp" |
| #include "tcuSurface.hpp" |
| #include "tcuFloat.hpp" |
| #include "tcuTextureUtil.hpp" |
| #include "deStringUtil.hpp" |
| #include "deArrayUtil.hpp" |
| #include "tcuMatrix.hpp" |
| |
| #include <limits> |
| |
| namespace tcu |
| { |
| |
| // \note No sign. Denorms are supported. |
| typedef Float<uint32_t, 5, 6, 15, FLOAT_SUPPORT_DENORM> Float11; |
| typedef Float<uint32_t, 5, 5, 15, FLOAT_SUPPORT_DENORM> Float10; |
| |
| namespace |
| { |
| |
| // Optimized getters for common formats. |
| // \todo [2012-11-14 pyry] Use intrinsics if available. |
| |
| inline Vec4 readRGBA8888Float(const uint8_t *ptr) |
| { |
| return Vec4(ptr[0] / 255.0f, ptr[1] / 255.0f, ptr[2] / 255.0f, ptr[3] / 255.0f); |
| } |
| inline Vec4 readRGB888Float(const uint8_t *ptr) |
| { |
| return Vec4(ptr[0] / 255.0f, ptr[1] / 255.0f, ptr[2] / 255.0f, 1.0f); |
| } |
| inline IVec4 readRGBA8888Int(const uint8_t *ptr) |
| { |
| return IVec4(ptr[0], ptr[1], ptr[2], ptr[3]); |
| } |
| inline IVec4 readRGB888Int(const uint8_t *ptr) |
| { |
| return IVec4(ptr[0], ptr[1], ptr[2], 1); |
| } |
| |
| // Optimized setters. |
| |
| inline void writeRGBA8888Int(uint8_t *ptr, const IVec4 &val) |
| { |
| ptr[0] = (uint8_t)de::clamp(val[0], 0, 255); |
| ptr[1] = (uint8_t)de::clamp(val[1], 0, 255); |
| ptr[2] = (uint8_t)de::clamp(val[2], 0, 255); |
| ptr[3] = (uint8_t)de::clamp(val[3], 0, 255); |
| } |
| |
| inline void writeRGB888Int(uint8_t *ptr, const IVec4 &val) |
| { |
| ptr[0] = (uint8_t)de::clamp(val[0], 0, 255); |
| ptr[1] = (uint8_t)de::clamp(val[1], 0, 255); |
| ptr[2] = (uint8_t)de::clamp(val[2], 0, 255); |
| } |
| |
| inline void writeRGBA8888Float(uint8_t *ptr, const Vec4 &val) |
| { |
| ptr[0] = floatToU8(val[0]); |
| ptr[1] = floatToU8(val[1]); |
| ptr[2] = floatToU8(val[2]); |
| ptr[3] = floatToU8(val[3]); |
| } |
| |
| inline void writeRGB888Float(uint8_t *ptr, const Vec4 &val) |
| { |
| ptr[0] = floatToU8(val[0]); |
| ptr[1] = floatToU8(val[1]); |
| ptr[2] = floatToU8(val[2]); |
| } |
| |
| inline void writeUint24(uint8_t *dst, uint32_t val) |
| { |
| #if (DE_ENDIANNESS == DE_LITTLE_ENDIAN) |
| dst[0] = (uint8_t)((val & 0x0000FFu) >> 0u); |
| dst[1] = (uint8_t)((val & 0x00FF00u) >> 8u); |
| dst[2] = (uint8_t)((val & 0xFF0000u) >> 16u); |
| #else |
| dst[0] = (uint8_t)((val & 0xFF0000u) >> 16u); |
| dst[1] = (uint8_t)((val & 0x00FF00u) >> 8u); |
| dst[2] = (uint8_t)((val & 0x0000FFu) >> 0u); |
| #endif |
| } |
| |
| inline uint32_t readUint24(const uint8_t *src) |
| { |
| #if (DE_ENDIANNESS == DE_LITTLE_ENDIAN) |
| return (((uint32_t)src[0]) << 0u) | (((uint32_t)src[1]) << 8u) | (((uint32_t)src[2]) << 16u); |
| #else |
| return (((uint32_t)src[0]) << 16u) | (((uint32_t)src[1]) << 8u) | (((uint32_t)src[2]) << 0u); |
| #endif |
| } |
| |
| inline uint8_t readUint32Low8(const uint8_t *src) |
| { |
| #if (DE_ENDIANNESS == DE_LITTLE_ENDIAN) |
| const uint32_t uint32ByteOffsetBits0To8 = 0; //!< least significant byte in the lowest address |
| #else |
| const uint32_t uint32ByteOffsetBits0To8 = 3; //!< least significant byte in the highest address |
| #endif |
| |
| return src[uint32ByteOffsetBits0To8]; |
| } |
| |
| inline uint8_t readUint32High8(const uint8_t *src) |
| { |
| #if (DE_ENDIANNESS == DE_LITTLE_ENDIAN) |
| const uint32_t uint32ByteOffsetBits24To32 = 3; |
| #else |
| const uint32_t uint32ByteOffsetBits24To32 = 0; |
| #endif |
| |
| return src[uint32ByteOffsetBits24To32]; |
| } |
| |
| inline void writeUint32Low8(uint8_t *dst, uint8_t val) |
| { |
| #if (DE_ENDIANNESS == DE_LITTLE_ENDIAN) |
| const uint32_t uint32ByteOffsetBits0To8 = 0; //!< least significant byte in the lowest address |
| #else |
| const uint32_t uint32ByteOffsetBits0To8 = 3; //!< least significant byte in the highest address |
| #endif |
| |
| dst[uint32ByteOffsetBits0To8] = val; |
| } |
| |
| inline void writeUint32High8(uint8_t *dst, uint8_t val) |
| { |
| #if (DE_ENDIANNESS == DE_LITTLE_ENDIAN) |
| const uint32_t uint32ByteOffsetBits24To32 = 3; |
| #else |
| const uint32_t uint32ByteOffsetBits24To32 = 0; |
| #endif |
| |
| dst[uint32ByteOffsetBits24To32] = val; |
| } |
| |
| inline uint32_t readUint32High16(const uint8_t *src) |
| { |
| #if (DE_ENDIANNESS == DE_LITTLE_ENDIAN) |
| const uint32_t uint32ByteOffset16To32 = 2; |
| #else |
| const uint32_t uint32ByteOffset16To32 = 0; |
| #endif |
| |
| return *(const uint16_t *)(src + uint32ByteOffset16To32); |
| } |
| |
| inline void writeUint32High16(uint8_t *dst, uint16_t val) |
| { |
| #if (DE_ENDIANNESS == DE_LITTLE_ENDIAN) |
| const uint32_t uint32ByteOffset16To32 = 2; |
| #else |
| const uint32_t uint32ByteOffset16To32 = 0; |
| #endif |
| |
| *(uint16_t *)(dst + uint32ByteOffset16To32) = val; |
| } |
| |
| inline uint32_t readUint32Low24(const uint8_t *src) |
| { |
| #if (DE_ENDIANNESS == DE_LITTLE_ENDIAN) |
| const uint32_t uint32ByteOffset0To24 = 0; |
| #else |
| const uint32_t uint32ByteOffset0To24 = 1; |
| #endif |
| |
| return readUint24(src + uint32ByteOffset0To24); |
| } |
| |
| inline uint32_t readUint32High24(const uint8_t *src) |
| { |
| #if (DE_ENDIANNESS == DE_LITTLE_ENDIAN) |
| const uint32_t uint32ByteOffset8To32 = 1; |
| #else |
| const uint32_t uint32ByteOffset8To32 = 0; |
| #endif |
| |
| return readUint24(src + uint32ByteOffset8To32); |
| } |
| |
| inline void writeUint32Low24(uint8_t *dst, uint32_t val) |
| { |
| #if (DE_ENDIANNESS == DE_LITTLE_ENDIAN) |
| const uint32_t uint32ByteOffset0To24 = 0; |
| #else |
| const uint32_t uint32ByteOffset0To24 = 1; |
| #endif |
| |
| writeUint24(dst + uint32ByteOffset0To24, val); |
| } |
| |
| inline void writeUint32High24(uint8_t *dst, uint32_t val) |
| { |
| #if (DE_ENDIANNESS == DE_LITTLE_ENDIAN) |
| const uint32_t uint32ByteOffset8To32 = 1; |
| #else |
| const uint32_t uint32ByteOffset8To32 = 0; |
| #endif |
| |
| writeUint24(dst + uint32ByteOffset8To32, val); |
| } |
| |
| // \todo [2011-09-21 pyry] Move to tcutil? |
| template <typename T> |
| inline T convertSatRte(float f) |
| { |
| // \note Doesn't work for 64-bit types |
| DE_STATIC_ASSERT(sizeof(T) < sizeof(uint64_t)); |
| DE_STATIC_ASSERT((-3 % 2 != 0) && (-4 % 2 == 0)); |
| |
| int64_t minVal = std::numeric_limits<T>::min(); |
| int64_t maxVal = std::numeric_limits<T>::max(); |
| float q = deFloatFrac(f); |
| int64_t intVal = (int64_t)(f - q); |
| |
| // Rounding. |
| if (q == 0.5f) |
| { |
| if (intVal % 2 != 0) |
| intVal++; |
| } |
| else if (q > 0.5f) |
| intVal++; |
| // else Don't add anything |
| |
| // Saturate. |
| intVal = de::max(minVal, de::min(maxVal, intVal)); |
| |
| return (T)intVal; |
| } |
| |
| inline uint32_t convertSatRteUint24(float f) |
| { |
| const uint32_t rounded = convertSatRte<uint32_t>(f); |
| const uint32_t maxUint24 = 0xFFFFFFu; |
| return de::min(rounded, maxUint24); |
| } |
| |
| inline uint16_t convertSatRteUint10(float f) |
| { |
| const uint16_t rounded = convertSatRte<uint16_t>(f); |
| const uint16_t maxUint10 = 0x3FFu; |
| return de::min(rounded, maxUint10); |
| } |
| |
| inline uint16_t convertSatRteUint12(float f) |
| { |
| const uint16_t rounded = convertSatRte<uint16_t>(f); |
| const uint16_t maxUint12 = 0xFFFu; |
| return de::min(rounded, maxUint12); |
| } |
| |
| inline float channelToFloat(const uint8_t *value, TextureFormat::ChannelType type) |
| { |
| // make sure this table is updated if format table is updated |
| DE_STATIC_ASSERT(TextureFormat::CHANNELTYPE_LAST == 48); |
| |
| switch (type) |
| { |
| case TextureFormat::SNORM_INT8: |
| return de::max(-1.0f, (float)*((const int8_t *)value) / 127.0f); |
| case TextureFormat::SNORM_INT16: |
| return de::max(-1.0f, (float)*((const int16_t *)value) / 32767.0f); |
| case TextureFormat::SNORM_INT32: |
| return de::max(-1.0f, (float)*((const int32_t *)value) / 2147483647.0f); |
| case TextureFormat::UNORM_INT8: |
| return (float)*((const uint8_t *)value) / 255.0f; |
| case TextureFormat::UNORM_INT16: |
| return (float)*((const uint16_t *)value) / 65535.0f; |
| case TextureFormat::UNORM_INT24: |
| return (float)readUint24(value) / 16777215.0f; |
| case TextureFormat::UNORM_INT32: |
| return (float)*((const uint32_t *)value) / 4294967295.0f; |
| case TextureFormat::SIGNED_INT8: |
| return (float)*((const int8_t *)value); |
| case TextureFormat::SIGNED_INT16: |
| return (float)*((const int16_t *)value); |
| case TextureFormat::SIGNED_INT32: |
| return (float)*((const int32_t *)value); |
| case TextureFormat::SIGNED_INT64: |
| return (float)*((const int64_t *)value); |
| case TextureFormat::UNSIGNED_INT8: |
| return (float)*((const uint8_t *)value); |
| case TextureFormat::UNSIGNED_INT16: |
| return (float)*((const uint16_t *)value); |
| case TextureFormat::UNSIGNED_INT24: |
| return (float)readUint24(value); |
| case TextureFormat::UNSIGNED_INT32: |
| return (float)*((const uint32_t *)value); |
| case TextureFormat::UNSIGNED_INT64: |
| return (float)*((const uint64_t *)value); |
| case TextureFormat::HALF_FLOAT: |
| return deFloat16To32(*(const deFloat16 *)value); |
| case TextureFormat::FLOAT: |
| return *((const float *)value); |
| case TextureFormat::FLOAT64: |
| return (float)*((const double *)value); |
| case TextureFormat::UNORM_SHORT_10: |
| return (float)((*((const uint16_t *)value)) >> 6u) / 1023.0f; |
| case TextureFormat::UNORM_SHORT_12: |
| return (float)((*((const uint16_t *)value)) >> 4u) / 4095.0f; |
| case TextureFormat::USCALED_INT8: |
| return (float)*((const uint8_t *)value); |
| case TextureFormat::USCALED_INT16: |
| return (float)*((const uint16_t *)value); |
| case TextureFormat::SSCALED_INT8: |
| return (float)*((const int8_t *)value); |
| case TextureFormat::SSCALED_INT16: |
| return (float)*((const int16_t *)value); |
| default: |
| DE_ASSERT(false); |
| return 0.0f; |
| } |
| } |
| |
| template <class T> |
| inline T channelToIntType(const uint8_t *value, TextureFormat::ChannelType type) |
| { |
| // make sure this table is updated if format table is updated |
| DE_STATIC_ASSERT(TextureFormat::CHANNELTYPE_LAST == 48); |
| |
| switch (type) |
| { |
| case TextureFormat::SNORM_INT8: |
| return (T) * ((const int8_t *)value); |
| case TextureFormat::SNORM_INT16: |
| return (T) * ((const int16_t *)value); |
| case TextureFormat::SNORM_INT32: |
| return (T) * ((const int32_t *)value); |
| case TextureFormat::UNORM_INT8: |
| return (T) * ((const uint8_t *)value); |
| case TextureFormat::UNORM_INT16: |
| return (T) * ((const uint16_t *)value); |
| case TextureFormat::UNORM_INT24: |
| return (T)readUint24(value); |
| case TextureFormat::UNORM_INT32: |
| return (T) * ((const uint32_t *)value); |
| case TextureFormat::SIGNED_INT8: |
| return (T) * ((const int8_t *)value); |
| case TextureFormat::SIGNED_INT16: |
| return (T) * ((const int16_t *)value); |
| case TextureFormat::SIGNED_INT32: |
| return (T) * ((const int32_t *)value); |
| case TextureFormat::SIGNED_INT64: |
| return (T) * ((const int64_t *)value); |
| case TextureFormat::UNSIGNED_INT8: |
| return (T) * ((const uint8_t *)value); |
| case TextureFormat::UNSIGNED_INT16: |
| return (T) * ((const uint16_t *)value); |
| case TextureFormat::UNSIGNED_INT24: |
| return (T)readUint24(value); |
| case TextureFormat::UNSIGNED_INT32: |
| return (T) * ((const uint32_t *)value); |
| case TextureFormat::UNSIGNED_INT64: |
| return (T) * ((const uint64_t *)value); |
| case TextureFormat::HALF_FLOAT: |
| return (T)deFloat16To32(*(const deFloat16 *)value); |
| case TextureFormat::FLOAT: |
| return (T) * ((const float *)value); |
| case TextureFormat::FLOAT64: |
| return (T) * ((const double *)value); |
| case TextureFormat::UNORM_SHORT_10: |
| return (T)((*(((const uint16_t *)value))) >> 6u); |
| case TextureFormat::UNORM_SHORT_12: |
| return (T)((*(((const uint16_t *)value))) >> 4u); |
| case TextureFormat::USCALED_INT8: |
| return (T) * ((const uint8_t *)value); |
| case TextureFormat::USCALED_INT16: |
| return (T) * ((const uint16_t *)value); |
| case TextureFormat::SSCALED_INT8: |
| return (T) * ((const int8_t *)value); |
| case TextureFormat::SSCALED_INT16: |
| return (T) * ((const int16_t *)value); |
| default: |
| DE_ASSERT(false); |
| return 0; |
| } |
| } |
| |
| inline uint64_t retrieveChannelBitsAsUint64(const uint8_t *value, TextureFormat::ChannelType type) |
| { |
| // make sure this table is updated if format table is updated |
| DE_STATIC_ASSERT(TextureFormat::CHANNELTYPE_LAST == 48); |
| |
| switch (type) |
| { |
| case TextureFormat::SNORM_INT8: |
| return (uint64_t) * ((const uint8_t *)value); |
| case TextureFormat::SNORM_INT16: |
| return (uint64_t) * ((const uint16_t *)value); |
| case TextureFormat::SNORM_INT32: |
| return (uint64_t) * ((const uint32_t *)value); |
| case TextureFormat::UNORM_INT8: |
| return (uint64_t) * ((const uint8_t *)value); |
| case TextureFormat::UNORM_INT16: |
| return (uint64_t) * ((const uint16_t *)value); |
| case TextureFormat::UNORM_INT24: |
| return (uint64_t)readUint24(value); |
| case TextureFormat::UNORM_INT32: |
| return (uint64_t) * ((const uint32_t *)value); |
| case TextureFormat::SIGNED_INT8: |
| return (uint64_t) * ((const uint8_t *)value); |
| case TextureFormat::SIGNED_INT16: |
| return (uint64_t) * ((const uint16_t *)value); |
| case TextureFormat::SIGNED_INT32: |
| return (uint64_t) * ((const uint32_t *)value); |
| case TextureFormat::SIGNED_INT64: |
| return (uint64_t) * ((const uint64_t *)value); |
| case TextureFormat::UNSIGNED_INT8: |
| return (uint64_t) * ((const uint8_t *)value); |
| case TextureFormat::UNSIGNED_INT16: |
| return (uint64_t) * ((const uint16_t *)value); |
| case TextureFormat::UNSIGNED_INT24: |
| return (uint64_t)readUint24(value); |
| case TextureFormat::UNSIGNED_INT32: |
| return (uint64_t) * ((const uint32_t *)value); |
| case TextureFormat::UNSIGNED_INT64: |
| return (uint64_t) * ((const uint64_t *)value); |
| case TextureFormat::HALF_FLOAT: |
| return (uint64_t) * ((const uint16_t *)value); |
| case TextureFormat::FLOAT: |
| return (uint64_t) * ((const uint32_t *)value); |
| case TextureFormat::FLOAT64: |
| return (uint64_t) * ((const uint64_t *)value); |
| case TextureFormat::UNORM_SHORT_10: |
| return (uint64_t)((*((const uint16_t *)value)) >> 6u); |
| case TextureFormat::UNORM_SHORT_12: |
| return (uint64_t)((*((const uint16_t *)value)) >> 4u); |
| case TextureFormat::USCALED_INT8: |
| return (uint64_t) * ((const uint8_t *)value); |
| case TextureFormat::USCALED_INT16: |
| return (uint64_t) * ((const uint16_t *)value); |
| case TextureFormat::SSCALED_INT8: |
| return (uint64_t) * ((const uint8_t *)value); |
| case TextureFormat::SSCALED_INT16: |
| return (uint64_t) * ((const uint16_t *)value); |
| default: |
| DE_ASSERT(false); |
| return 0; |
| } |
| } |
| |
| inline int channelToInt(const uint8_t *value, TextureFormat::ChannelType type) |
| { |
| return channelToIntType<int>(value, type); |
| } |
| |
| void floatToChannel(uint8_t *dst, float src, TextureFormat::ChannelType type) |
| { |
| // make sure this table is updated if format table is updated |
| DE_STATIC_ASSERT(TextureFormat::CHANNELTYPE_LAST == 48); |
| |
| switch (type) |
| { |
| case TextureFormat::SNORM_INT8: |
| *((int8_t *)dst) = convertSatRte<int8_t>(src * 127.0f); |
| break; |
| case TextureFormat::SNORM_INT16: |
| *((int16_t *)dst) = convertSatRte<int16_t>(src * 32767.0f); |
| break; |
| case TextureFormat::SNORM_INT32: |
| *((int32_t *)dst) = convertSatRte<int32_t>(src * 2147483647.0f); |
| break; |
| case TextureFormat::UNORM_INT8: |
| *((uint8_t *)dst) = convertSatRte<uint8_t>(src * 255.0f); |
| break; |
| case TextureFormat::UNORM_INT16: |
| *((uint16_t *)dst) = convertSatRte<uint16_t>(src * 65535.0f); |
| break; |
| case TextureFormat::UNORM_INT24: |
| writeUint24(dst, convertSatRteUint24(src * 16777215.0f)); |
| break; |
| case TextureFormat::UNORM_INT32: |
| *((uint32_t *)dst) = convertSatRte<uint32_t>(src * 4294967295.0f); |
| break; |
| case TextureFormat::SIGNED_INT8: |
| *((int8_t *)dst) = convertSatRte<int8_t>(src); |
| break; |
| case TextureFormat::SIGNED_INT16: |
| *((int16_t *)dst) = convertSatRte<int16_t>(src); |
| break; |
| case TextureFormat::SIGNED_INT32: |
| *((int32_t *)dst) = convertSatRte<int32_t>(src); |
| break; |
| case TextureFormat::UNSIGNED_INT8: |
| *((uint8_t *)dst) = convertSatRte<uint8_t>(src); |
| break; |
| case TextureFormat::UNSIGNED_INT16: |
| *((uint16_t *)dst) = convertSatRte<uint16_t>(src); |
| break; |
| case TextureFormat::UNSIGNED_INT24: |
| writeUint24(dst, convertSatRteUint24(src)); |
| break; |
| case TextureFormat::UNSIGNED_INT32: |
| *((uint32_t *)dst) = convertSatRte<uint32_t>(src); |
| break; |
| case TextureFormat::HALF_FLOAT: |
| *((deFloat16 *)dst) = deFloat32To16(src); |
| break; |
| case TextureFormat::FLOAT: |
| *((float *)dst) = src; |
| break; |
| case TextureFormat::FLOAT64: |
| *((double *)dst) = (double)src; |
| break; |
| case TextureFormat::UNORM_SHORT_10: |
| *((uint16_t *)dst) = (uint16_t)(convertSatRteUint10(src * 1023.0f) << 6u); |
| break; |
| case TextureFormat::UNORM_SHORT_12: |
| *((uint16_t *)dst) = (uint16_t)(convertSatRteUint12(src * 4095.0f) << 4u); |
| break; |
| case TextureFormat::USCALED_INT8: |
| *((uint8_t *)dst) = convertSatRte<uint8_t>(src); |
| break; |
| case TextureFormat::USCALED_INT16: |
| *((uint16_t *)dst) = convertSatRte<uint16_t>(src); |
| break; |
| case TextureFormat::SSCALED_INT8: |
| *((int8_t *)dst) = convertSatRte<int8_t>(src); |
| break; |
| case TextureFormat::SSCALED_INT16: |
| *((int16_t *)dst) = convertSatRte<int16_t>(src); |
| break; |
| default: |
| DE_ASSERT(false); |
| } |
| } |
| |
| template <typename T, typename S> |
| static inline T convertSat(S src) |
| { |
| S min = (S)std::numeric_limits<T>::min(); |
| S max = (S)std::numeric_limits<T>::max(); |
| |
| if (src < min) |
| return (T)min; |
| else if (src > max) |
| return (T)max; |
| else |
| return (T)src; |
| } |
| |
| template <typename S> |
| static inline uint32_t convertSatUint24(S src) |
| { |
| S min = (S)0u; |
| S max = (S)0xFFFFFFu; |
| |
| if (src < min) |
| return (uint32_t)min; |
| else if (src > max) |
| return (uint32_t)max; |
| else |
| return (uint32_t)src; |
| } |
| |
| template <typename S> |
| static inline uint16_t convertSatUint10(S src) |
| { |
| S min = (S)0u; |
| S max = (S)0x3FFu; |
| |
| if (src < min) |
| return (uint16_t)min; |
| else if (src > max) |
| return (uint16_t)max; |
| else |
| return (uint16_t)src; |
| } |
| |
| template <typename S> |
| static inline uint16_t convertSatUint12(S src) |
| { |
| S min = (S)0u; |
| S max = (S)0xFFFu; |
| |
| if (src < min) |
| return (uint16_t)min; |
| else if (src > max) |
| return (uint16_t)max; |
| else |
| return (uint16_t)src; |
| } |
| |
| void intToChannel(uint8_t *dst, int src, TextureFormat::ChannelType type) |
| { |
| // make sure this table is updated if format table is updated |
| DE_STATIC_ASSERT(TextureFormat::CHANNELTYPE_LAST == 48); |
| |
| switch (type) |
| { |
| case TextureFormat::SNORM_INT8: |
| *((int8_t *)dst) = convertSat<int8_t>(src); |
| break; |
| case TextureFormat::SNORM_INT16: |
| *((int16_t *)dst) = convertSat<int16_t>(src); |
| break; |
| case TextureFormat::UNORM_INT8: |
| *((uint8_t *)dst) = convertSat<uint8_t>(src); |
| break; |
| case TextureFormat::UNORM_INT16: |
| *((uint16_t *)dst) = convertSat<uint16_t>(src); |
| break; |
| case TextureFormat::UNORM_INT24: |
| writeUint24(dst, convertSatUint24(src)); |
| break; |
| case TextureFormat::SIGNED_INT8: |
| *((int8_t *)dst) = convertSat<int8_t>(src); |
| break; |
| case TextureFormat::SIGNED_INT16: |
| *((int16_t *)dst) = convertSat<int16_t>(src); |
| break; |
| case TextureFormat::SIGNED_INT32: |
| *((int32_t *)dst) = convertSat<int32_t>(src); |
| break; |
| case TextureFormat::SIGNED_INT64: |
| *((int64_t *)dst) = convertSat<int64_t>((int64_t)src); |
| break; |
| case TextureFormat::UNSIGNED_INT8: |
| *((uint8_t *)dst) = convertSat<uint8_t>((uint32_t)src); |
| break; |
| case TextureFormat::UNSIGNED_INT16: |
| *((uint16_t *)dst) = convertSat<uint16_t>((uint32_t)src); |
| break; |
| case TextureFormat::UNSIGNED_INT24: |
| writeUint24(dst, convertSatUint24((uint32_t)src)); |
| break; |
| case TextureFormat::UNSIGNED_INT32: |
| *((uint32_t *)dst) = convertSat<uint32_t>((uint32_t)src); |
| break; |
| case TextureFormat::UNSIGNED_INT64: |
| *((uint64_t *)dst) = convertSat<uint64_t>((uint64_t)src); |
| break; |
| case TextureFormat::HALF_FLOAT: |
| *((deFloat16 *)dst) = deFloat32To16((float)src); |
| break; |
| case TextureFormat::FLOAT: |
| *((float *)dst) = (float)src; |
| break; |
| case TextureFormat::FLOAT64: |
| *((double *)dst) = (double)src; |
| break; |
| case TextureFormat::UNORM_SHORT_10: |
| *((uint16_t *)dst) = (uint16_t)(convertSatUint10(src) << 6u); |
| break; |
| case TextureFormat::UNORM_SHORT_12: |
| *((uint16_t *)dst) = (uint16_t)(convertSatUint12(src) << 4u); |
| break; |
| case TextureFormat::USCALED_INT8: |
| *((uint8_t *)dst) = convertSat<uint8_t>((uint32_t)src); |
| break; |
| case TextureFormat::USCALED_INT16: |
| *((uint16_t *)dst) = convertSat<uint16_t>((uint32_t)src); |
| break; |
| case TextureFormat::SSCALED_INT8: |
| *((int8_t *)dst) = convertSat<int8_t>(src); |
| break; |
| case TextureFormat::SSCALED_INT16: |
| *((int16_t *)dst) = convertSat<int16_t>(src); |
| break; |
| default: |
| DE_ASSERT(false); |
| } |
| } |
| |
| inline float channelToUnormFloat(uint32_t src, int bits) |
| { |
| const uint32_t maxVal = (1u << bits) - 1; |
| |
| // \note Will lose precision if bits > 23 |
| return (float)src / (float)maxVal; |
| } |
| |
| //! Extend < 32b signed integer to 32b |
| inline int32_t signExtend(uint32_t src, int bits) |
| { |
| const uint32_t signBit = 1u << (bits - 1); |
| |
| src |= ~((src & signBit) - 1); |
| |
| return (int32_t)src; |
| } |
| |
| inline float channelToSnormFloat(uint32_t src, int bits) |
| { |
| const uint32_t range = (1u << (bits - 1)) - 1; |
| |
| // \note Will lose precision if bits > 24 |
| return de::max(-1.0f, (float)signExtend(src, bits) / (float)range); |
| } |
| |
| inline uint32_t unormFloatToChannel(float src, int bits) |
| { |
| const uint32_t maxVal = (1u << bits) - 1; |
| const uint32_t intVal = convertSatRte<uint32_t>(src * (float)maxVal); |
| |
| return de::min(intVal, maxVal); |
| } |
| |
| inline uint32_t snormFloatToChannel(float src, int bits) |
| { |
| const int32_t range = (int32_t)((1u << (bits - 1)) - 1u); |
| const uint32_t mask = (1u << bits) - 1; |
| const int32_t intVal = convertSatRte<int32_t>(src * (float)range); |
| |
| return (uint32_t)de::clamp(intVal, -range, range) & mask; |
| } |
| |
| inline uint32_t uintToChannel(uint32_t src, int bits) |
| { |
| const uint32_t maxVal = (1u << bits) - 1; |
| return de::min(src, maxVal); |
| } |
| |
| inline uint32_t intToChannel(int32_t src, int bits) |
| { |
| const int32_t minVal = -(int32_t)(1u << (bits - 1)); |
| const int32_t maxVal = (int32_t)((1u << (bits - 1)) - 1u); |
| const uint32_t mask = (1u << bits) - 1; |
| |
| return (uint32_t)de::clamp(src, minVal, maxVal) & mask; |
| } |
| |
| tcu::Vec4 unpackRGB999E5(uint32_t color) |
| { |
| const int mBits = 9; |
| const int eBias = 15; |
| |
| uint32_t exp = color >> 27; |
| uint32_t bs = (color >> 18) & ((1 << 9) - 1); |
| uint32_t gs = (color >> 9) & ((1 << 9) - 1); |
| uint32_t rs = color & ((1 << 9) - 1); |
| |
| float e = deFloatPow(2.0f, (float)((int)exp - eBias - mBits)); |
| float r = (float)rs * e; |
| float g = (float)gs * e; |
| float b = (float)bs * e; |
| |
| return tcu::Vec4(r, g, b, 1.0f); |
| } |
| |
| bool isColorOrder(TextureFormat::ChannelOrder order) |
| { |
| DE_STATIC_ASSERT(TextureFormat::CHANNELORDER_LAST == 22); |
| |
| switch (order) |
| { |
| case TextureFormat::R: |
| case TextureFormat::A: |
| case TextureFormat::I: |
| case TextureFormat::L: |
| case TextureFormat::LA: |
| case TextureFormat::RG: |
| case TextureFormat::RA: |
| case TextureFormat::RGB: |
| case TextureFormat::RGBA: |
| case TextureFormat::ARGB: |
| case TextureFormat::ABGR: |
| case TextureFormat::BGR: |
| case TextureFormat::BGRA: |
| case TextureFormat::sR: |
| case TextureFormat::sRG: |
| case TextureFormat::sRGB: |
| case TextureFormat::sRGBA: |
| case TextureFormat::sBGR: |
| case TextureFormat::sBGRA: |
| return true; |
| |
| default: |
| return false; |
| } |
| } |
| |
| float getImageViewMinLod(ImageViewMinLod &l) |
| { |
| return (l.mode == IMAGEVIEWMINLODMODE_PREFERRED) ? l.value : deFloatFloor(l.value); |
| } |
| |
| } // namespace |
| |
| bool isValid(TextureFormat format) |
| { |
| const bool isColor = isColorOrder(format.order); |
| |
| switch (format.type) |
| { |
| case TextureFormat::SNORM_INT8: |
| case TextureFormat::SNORM_INT16: |
| case TextureFormat::SNORM_INT32: |
| return isColor; |
| |
| case TextureFormat::UNORM_INT8: |
| case TextureFormat::UNORM_INT16: |
| case TextureFormat::UNORM_INT24: |
| case TextureFormat::UNORM_INT32: |
| return isColor || format.order == TextureFormat::D; |
| |
| case TextureFormat::UNORM_BYTE_44: |
| case TextureFormat::UNSIGNED_BYTE_44: |
| return format.order == TextureFormat::RG; |
| |
| case TextureFormat::UNORM_SHORT_565: |
| case TextureFormat::UNORM_SHORT_555: |
| case TextureFormat::UNSIGNED_SHORT_565: |
| return format.order == TextureFormat::RGB || format.order == TextureFormat::BGR; |
| |
| case TextureFormat::UNORM_SHORT_4444: |
| case TextureFormat::UNORM_SHORT_5551: |
| case TextureFormat::UNSIGNED_SHORT_4444: |
| case TextureFormat::UNSIGNED_SHORT_5551: |
| return format.order == TextureFormat::RGBA || format.order == TextureFormat::BGRA || |
| format.order == TextureFormat::ARGB || format.order == TextureFormat::ABGR; |
| |
| case TextureFormat::UNORM_SHORT_1555: |
| return format.order == TextureFormat::ARGB || format.order == TextureFormat::ABGR; |
| |
| case TextureFormat::UNORM_INT_101010: |
| return format.order == TextureFormat::RGB; |
| |
| case TextureFormat::SNORM_INT_1010102_REV: |
| case TextureFormat::UNORM_INT_1010102_REV: |
| case TextureFormat::SIGNED_INT_1010102_REV: |
| case TextureFormat::UNSIGNED_INT_1010102_REV: |
| case TextureFormat::USCALED_INT_1010102_REV: |
| case TextureFormat::SSCALED_INT_1010102_REV: |
| return format.order == TextureFormat::RGBA || format.order == TextureFormat::BGRA; |
| |
| case TextureFormat::UNSIGNED_INT_11F_11F_10F_REV: |
| case TextureFormat::UNSIGNED_INT_999_E5_REV: |
| return format.order == TextureFormat::RGB; |
| |
| case TextureFormat::UNSIGNED_INT_16_8_8: |
| return format.order == TextureFormat::DS; |
| |
| case TextureFormat::UNSIGNED_INT_24_8: |
| case TextureFormat::UNSIGNED_INT_24_8_REV: |
| return format.order == TextureFormat::D || format.order == TextureFormat::DS; |
| |
| case TextureFormat::SIGNED_INT8: |
| case TextureFormat::SIGNED_INT16: |
| case TextureFormat::SIGNED_INT32: |
| case TextureFormat::SSCALED_INT8: |
| case TextureFormat::SSCALED_INT16: |
| case TextureFormat::SIGNED_INT64: |
| return isColor; |
| |
| case TextureFormat::UNSIGNED_INT8: |
| case TextureFormat::UNSIGNED_INT16: |
| case TextureFormat::UNSIGNED_INT24: |
| case TextureFormat::UNSIGNED_INT32: |
| case TextureFormat::USCALED_INT8: |
| case TextureFormat::USCALED_INT16: |
| case TextureFormat::UNSIGNED_INT64: |
| return isColor || format.order == TextureFormat::S; |
| |
| case TextureFormat::HALF_FLOAT: |
| case TextureFormat::FLOAT: |
| case TextureFormat::FLOAT64: |
| return isColor || format.order == TextureFormat::D; |
| |
| case TextureFormat::FLOAT_UNSIGNED_INT_24_8_REV: |
| return format.order == TextureFormat::DS; |
| |
| case TextureFormat::UNORM_SHORT_10: |
| case TextureFormat::UNORM_SHORT_12: |
| return isColor; |
| |
| default: |
| DE_FATAL("Unknown format"); |
| return 0u; |
| } |
| |
| DE_STATIC_ASSERT(TextureFormat::CHANNELTYPE_LAST == 48); |
| } |
| |
| int getNumUsedChannels(TextureFormat::ChannelOrder order) |
| { |
| // make sure this table is updated if type table is updated |
| DE_STATIC_ASSERT(TextureFormat::CHANNELORDER_LAST == 22); |
| |
| switch (order) |
| { |
| case TextureFormat::R: |
| return 1; |
| case TextureFormat::A: |
| return 1; |
| case TextureFormat::I: |
| return 1; |
| case TextureFormat::L: |
| return 1; |
| case TextureFormat::LA: |
| return 2; |
| case TextureFormat::RG: |
| return 2; |
| case TextureFormat::RA: |
| return 2; |
| case TextureFormat::RGB: |
| return 3; |
| case TextureFormat::RGBA: |
| return 4; |
| case TextureFormat::ARGB: |
| return 4; |
| case TextureFormat::ABGR: |
| return 4; |
| case TextureFormat::BGR: |
| return 3; |
| case TextureFormat::BGRA: |
| return 4; |
| case TextureFormat::sR: |
| return 1; |
| case TextureFormat::sRG: |
| return 2; |
| case TextureFormat::sRGB: |
| return 3; |
| case TextureFormat::sRGBA: |
| return 4; |
| case TextureFormat::sBGR: |
| return 3; |
| case TextureFormat::sBGRA: |
| return 4; |
| case TextureFormat::D: |
| return 1; |
| case TextureFormat::S: |
| return 1; |
| case TextureFormat::DS: |
| return 2; |
| default: |
| DE_ASSERT(false); |
| return 0; |
| } |
| } |
| |
| bool hasAlphaChannel(TextureFormat::ChannelOrder order) |
| { |
| // make sure this table is updated if type table is updated |
| DE_STATIC_ASSERT(TextureFormat::CHANNELORDER_LAST == 22); |
| |
| switch (order) |
| { |
| case TextureFormat::A: |
| case TextureFormat::LA: |
| case TextureFormat::RG: |
| case TextureFormat::RA: |
| case TextureFormat::RGBA: |
| case TextureFormat::ARGB: |
| case TextureFormat::ABGR: |
| case TextureFormat::BGRA: |
| case TextureFormat::sRGBA: |
| case TextureFormat::sBGRA: |
| return true; |
| default: |
| return false; |
| } |
| } |
| |
| int getChannelSize(TextureFormat::ChannelType type) |
| { |
| // make sure this table is updated if format table is updated |
| DE_STATIC_ASSERT(TextureFormat::CHANNELTYPE_LAST == 48); |
| |
| switch (type) |
| { |
| case TextureFormat::SNORM_INT8: |
| return 1; |
| case TextureFormat::SNORM_INT16: |
| return 2; |
| case TextureFormat::SNORM_INT32: |
| return 4; |
| case TextureFormat::UNORM_INT8: |
| return 1; |
| case TextureFormat::UNORM_INT16: |
| return 2; |
| case TextureFormat::UNORM_INT24: |
| return 3; |
| case TextureFormat::UNORM_INT32: |
| return 4; |
| case TextureFormat::SIGNED_INT8: |
| return 1; |
| case TextureFormat::SIGNED_INT16: |
| return 2; |
| case TextureFormat::SIGNED_INT32: |
| return 4; |
| case TextureFormat::SIGNED_INT64: |
| return 8; |
| case TextureFormat::UNSIGNED_INT8: |
| return 1; |
| case TextureFormat::UNSIGNED_INT16: |
| return 2; |
| case TextureFormat::UNSIGNED_INT24: |
| return 3; |
| case TextureFormat::UNSIGNED_INT32: |
| return 4; |
| case TextureFormat::UNSIGNED_INT64: |
| return 8; |
| case TextureFormat::HALF_FLOAT: |
| return 2; |
| case TextureFormat::FLOAT: |
| return 4; |
| case TextureFormat::FLOAT64: |
| return 8; |
| case TextureFormat::UNORM_SHORT_10: |
| return 2; |
| case TextureFormat::UNORM_SHORT_12: |
| return 2; |
| case TextureFormat::USCALED_INT8: |
| return 1; |
| case TextureFormat::USCALED_INT16: |
| return 2; |
| case TextureFormat::SSCALED_INT8: |
| return 1; |
| case TextureFormat::SSCALED_INT16: |
| return 2; |
| default: |
| DE_ASSERT(false); |
| return 0; |
| } |
| } |
| |
| /** Get pixel size in bytes. */ |
| int getPixelSize(TextureFormat format) |
| { |
| const TextureFormat::ChannelOrder order = format.order; |
| const TextureFormat::ChannelType type = format.type; |
| |
| DE_ASSERT(isValid(format)); |
| |
| // make sure this table is updated if format table is updated |
| DE_STATIC_ASSERT(TextureFormat::CHANNELTYPE_LAST == 48); |
| |
| switch (type) |
| { |
| case TextureFormat::UNORM_BYTE_44: |
| case TextureFormat::UNSIGNED_BYTE_44: |
| return 1; |
| |
| case TextureFormat::UNORM_SHORT_565: |
| case TextureFormat::UNORM_SHORT_555: |
| case TextureFormat::UNORM_SHORT_4444: |
| case TextureFormat::UNORM_SHORT_5551: |
| case TextureFormat::UNORM_SHORT_1555: |
| case TextureFormat::UNSIGNED_SHORT_565: |
| case TextureFormat::UNSIGNED_SHORT_4444: |
| case TextureFormat::UNSIGNED_SHORT_5551: |
| return 2; |
| |
| case TextureFormat::UNORM_INT_101010: |
| case TextureFormat::UNSIGNED_INT_999_E5_REV: |
| case TextureFormat::UNSIGNED_INT_11F_11F_10F_REV: |
| case TextureFormat::SNORM_INT_1010102_REV: |
| case TextureFormat::UNORM_INT_1010102_REV: |
| case TextureFormat::SIGNED_INT_1010102_REV: |
| case TextureFormat::UNSIGNED_INT_1010102_REV: |
| case TextureFormat::UNSIGNED_INT_24_8: |
| case TextureFormat::UNSIGNED_INT_24_8_REV: |
| case TextureFormat::UNSIGNED_INT_16_8_8: |
| case TextureFormat::USCALED_INT_1010102_REV: |
| case TextureFormat::SSCALED_INT_1010102_REV: |
| return 4; |
| |
| case TextureFormat::FLOAT_UNSIGNED_INT_24_8_REV: |
| return 8; |
| |
| default: |
| return getNumUsedChannels(order) * getChannelSize(type); |
| } |
| } |
| |
| int TextureFormat::getPixelSize(void) const |
| { |
| return ::tcu::getPixelSize(*this); |
| } |
| |
| const TextureSwizzle &getChannelReadSwizzle(TextureFormat::ChannelOrder order) |
| { |
| // make sure to update these tables when channel orders are updated |
| DE_STATIC_ASSERT(TextureFormat::CHANNELORDER_LAST == 22); |
| |
| static const TextureSwizzle INV = {{TextureSwizzle::CHANNEL_ZERO, TextureSwizzle::CHANNEL_ZERO, |
| TextureSwizzle::CHANNEL_ZERO, TextureSwizzle::CHANNEL_ONE}}; |
| static const TextureSwizzle R = {{TextureSwizzle::CHANNEL_0, TextureSwizzle::CHANNEL_ZERO, |
| TextureSwizzle::CHANNEL_ZERO, TextureSwizzle::CHANNEL_ONE}}; |
| static const TextureSwizzle A = {{TextureSwizzle::CHANNEL_ZERO, TextureSwizzle::CHANNEL_ZERO, |
| TextureSwizzle::CHANNEL_ZERO, TextureSwizzle::CHANNEL_0}}; |
| static const TextureSwizzle I = { |
| {TextureSwizzle::CHANNEL_0, TextureSwizzle::CHANNEL_0, TextureSwizzle::CHANNEL_0, TextureSwizzle::CHANNEL_0}}; |
| static const TextureSwizzle L = { |
| {TextureSwizzle::CHANNEL_0, TextureSwizzle::CHANNEL_0, TextureSwizzle::CHANNEL_0, TextureSwizzle::CHANNEL_ONE}}; |
| static const TextureSwizzle LA = { |
| {TextureSwizzle::CHANNEL_0, TextureSwizzle::CHANNEL_0, TextureSwizzle::CHANNEL_0, TextureSwizzle::CHANNEL_1}}; |
| static const TextureSwizzle RG = {{TextureSwizzle::CHANNEL_0, TextureSwizzle::CHANNEL_1, |
| TextureSwizzle::CHANNEL_ZERO, TextureSwizzle::CHANNEL_ONE}}; |
| static const TextureSwizzle RA = {{TextureSwizzle::CHANNEL_0, TextureSwizzle::CHANNEL_ZERO, |
| TextureSwizzle::CHANNEL_ZERO, TextureSwizzle::CHANNEL_1}}; |
| static const TextureSwizzle RGB = { |
| {TextureSwizzle::CHANNEL_0, TextureSwizzle::CHANNEL_1, TextureSwizzle::CHANNEL_2, TextureSwizzle::CHANNEL_ONE}}; |
| static const TextureSwizzle RGBA = { |
| {TextureSwizzle::CHANNEL_0, TextureSwizzle::CHANNEL_1, TextureSwizzle::CHANNEL_2, TextureSwizzle::CHANNEL_3}}; |
| static const TextureSwizzle BGR = { |
| {TextureSwizzle::CHANNEL_2, TextureSwizzle::CHANNEL_1, TextureSwizzle::CHANNEL_0, TextureSwizzle::CHANNEL_ONE}}; |
| static const TextureSwizzle BGRA = { |
| {TextureSwizzle::CHANNEL_2, TextureSwizzle::CHANNEL_1, TextureSwizzle::CHANNEL_0, TextureSwizzle::CHANNEL_3}}; |
| static const TextureSwizzle ARGB = { |
| {TextureSwizzle::CHANNEL_1, TextureSwizzle::CHANNEL_2, TextureSwizzle::CHANNEL_3, TextureSwizzle::CHANNEL_0}}; |
| static const TextureSwizzle ABGR = { |
| {TextureSwizzle::CHANNEL_3, TextureSwizzle::CHANNEL_2, TextureSwizzle::CHANNEL_1, TextureSwizzle::CHANNEL_0}}; |
| static const TextureSwizzle D = {{TextureSwizzle::CHANNEL_0, TextureSwizzle::CHANNEL_ZERO, |
| TextureSwizzle::CHANNEL_ZERO, TextureSwizzle::CHANNEL_ONE}}; |
| static const TextureSwizzle S = {{TextureSwizzle::CHANNEL_0, TextureSwizzle::CHANNEL_ZERO, |
| TextureSwizzle::CHANNEL_ZERO, TextureSwizzle::CHANNEL_ONE}}; |
| static const TextureSwizzle DS = {{TextureSwizzle::CHANNEL_0, TextureSwizzle::CHANNEL_1, |
| TextureSwizzle::CHANNEL_ZERO, TextureSwizzle::CHANNEL_ONE}}; |
| |
| switch (order) |
| { |
| case TextureFormat::R: |
| return R; |
| case TextureFormat::A: |
| return A; |
| case TextureFormat::I: |
| return I; |
| case TextureFormat::L: |
| return L; |
| case TextureFormat::LA: |
| return LA; |
| case TextureFormat::RG: |
| return RG; |
| case TextureFormat::RA: |
| return RA; |
| case TextureFormat::RGB: |
| return RGB; |
| case TextureFormat::RGBA: |
| return RGBA; |
| case TextureFormat::ARGB: |
| return ARGB; |
| case TextureFormat::ABGR: |
| return ABGR; |
| case TextureFormat::BGR: |
| return BGR; |
| case TextureFormat::BGRA: |
| return BGRA; |
| case TextureFormat::sR: |
| return R; |
| case TextureFormat::sRG: |
| return RG; |
| case TextureFormat::sRGB: |
| return RGB; |
| case TextureFormat::sRGBA: |
| return RGBA; |
| case TextureFormat::sBGR: |
| return BGR; |
| case TextureFormat::sBGRA: |
| return BGRA; |
| case TextureFormat::D: |
| return D; |
| case TextureFormat::S: |
| return S; |
| case TextureFormat::DS: |
| return DS; |
| |
| default: |
| DE_ASSERT(false); |
| return INV; |
| } |
| } |
| |
| const TextureSwizzle &getChannelWriteSwizzle(TextureFormat::ChannelOrder order) |
| { |
| // make sure to update these tables when channel orders are updated |
| DE_STATIC_ASSERT(TextureFormat::CHANNELORDER_LAST == 22); |
| |
| static const TextureSwizzle INV = {{TextureSwizzle::CHANNEL_LAST, TextureSwizzle::CHANNEL_LAST, |
| TextureSwizzle::CHANNEL_LAST, TextureSwizzle::CHANNEL_LAST}}; |
| static const TextureSwizzle R = {{TextureSwizzle::CHANNEL_0, TextureSwizzle::CHANNEL_LAST, |
| TextureSwizzle::CHANNEL_LAST, TextureSwizzle::CHANNEL_LAST}}; |
| static const TextureSwizzle A = {{TextureSwizzle::CHANNEL_3, TextureSwizzle::CHANNEL_LAST, |
| TextureSwizzle::CHANNEL_LAST, TextureSwizzle::CHANNEL_LAST}}; |
| static const TextureSwizzle I = {{TextureSwizzle::CHANNEL_0, TextureSwizzle::CHANNEL_LAST, |
| TextureSwizzle::CHANNEL_LAST, TextureSwizzle::CHANNEL_LAST}}; |
| static const TextureSwizzle L = {{TextureSwizzle::CHANNEL_0, TextureSwizzle::CHANNEL_LAST, |
| TextureSwizzle::CHANNEL_LAST, TextureSwizzle::CHANNEL_LAST}}; |
| static const TextureSwizzle LA = {{TextureSwizzle::CHANNEL_0, TextureSwizzle::CHANNEL_3, |
| TextureSwizzle::CHANNEL_LAST, TextureSwizzle::CHANNEL_LAST}}; |
| static const TextureSwizzle RG = {{TextureSwizzle::CHANNEL_0, TextureSwizzle::CHANNEL_1, |
| TextureSwizzle::CHANNEL_LAST, TextureSwizzle::CHANNEL_LAST}}; |
| static const TextureSwizzle RA = {{TextureSwizzle::CHANNEL_0, TextureSwizzle::CHANNEL_3, |
| TextureSwizzle::CHANNEL_LAST, TextureSwizzle::CHANNEL_LAST}}; |
| static const TextureSwizzle RGB = {{TextureSwizzle::CHANNEL_0, TextureSwizzle::CHANNEL_1, TextureSwizzle::CHANNEL_2, |
| TextureSwizzle::CHANNEL_LAST}}; |
| static const TextureSwizzle RGBA = { |
| {TextureSwizzle::CHANNEL_0, TextureSwizzle::CHANNEL_1, TextureSwizzle::CHANNEL_2, TextureSwizzle::CHANNEL_3}}; |
| static const TextureSwizzle BGR = {{TextureSwizzle::CHANNEL_2, TextureSwizzle::CHANNEL_1, TextureSwizzle::CHANNEL_0, |
| TextureSwizzle::CHANNEL_LAST}}; |
| static const TextureSwizzle BGRA = { |
| {TextureSwizzle::CHANNEL_2, TextureSwizzle::CHANNEL_1, TextureSwizzle::CHANNEL_0, TextureSwizzle::CHANNEL_3}}; |
| static const TextureSwizzle ARGB = { |
| {TextureSwizzle::CHANNEL_3, TextureSwizzle::CHANNEL_0, TextureSwizzle::CHANNEL_1, TextureSwizzle::CHANNEL_2}}; |
| static const TextureSwizzle ABGR = { |
| {TextureSwizzle::CHANNEL_3, TextureSwizzle::CHANNEL_2, TextureSwizzle::CHANNEL_1, TextureSwizzle::CHANNEL_0}}; |
| static const TextureSwizzle D = {{TextureSwizzle::CHANNEL_0, TextureSwizzle::CHANNEL_LAST, |
| TextureSwizzle::CHANNEL_LAST, TextureSwizzle::CHANNEL_LAST}}; |
| static const TextureSwizzle S = {{TextureSwizzle::CHANNEL_0, TextureSwizzle::CHANNEL_LAST, |
| TextureSwizzle::CHANNEL_LAST, TextureSwizzle::CHANNEL_LAST}}; |
| |
| switch (order) |
| { |
| case TextureFormat::R: |
| return R; |
| case TextureFormat::A: |
| return A; |
| case TextureFormat::I: |
| return I; |
| case TextureFormat::L: |
| return L; |
| case TextureFormat::LA: |
| return LA; |
| case TextureFormat::RG: |
| return RG; |
| case TextureFormat::RA: |
| return RA; |
| case TextureFormat::RGB: |
| return RGB; |
| case TextureFormat::RGBA: |
| return RGBA; |
| case TextureFormat::ARGB: |
| return ARGB; |
| case TextureFormat::ABGR: |
| return ABGR; |
| case TextureFormat::BGR: |
| return BGR; |
| case TextureFormat::BGRA: |
| return BGRA; |
| case TextureFormat::sR: |
| return R; |
| case TextureFormat::sRG: |
| return RG; |
| case TextureFormat::sRGB: |
| return RGB; |
| case TextureFormat::sRGBA: |
| return RGBA; |
| case TextureFormat::sBGR: |
| return BGR; |
| case TextureFormat::sBGRA: |
| return BGRA; |
| case TextureFormat::D: |
| return D; |
| case TextureFormat::S: |
| return S; |
| |
| case TextureFormat::DS: |
| DE_ASSERT(false); // combined formats cannot be written to |
| return INV; |
| |
| default: |
| DE_ASSERT(false); |
| return INV; |
| } |
| } |
| |
| IVec3 calculatePackedPitch(const TextureFormat &format, const IVec3 &size) |
| { |
| const int pixelSize = format.getPixelSize(); |
| const int rowPitch = pixelSize * size.x(); |
| const int slicePitch = rowPitch * size.y(); |
| |
| return IVec3(pixelSize, rowPitch, slicePitch); |
| } |
| |
| ConstPixelBufferAccess::ConstPixelBufferAccess(void) : m_size(0), m_pitch(0), m_divider(1, 1, 1), m_data(DE_NULL) |
| { |
| } |
| |
| ConstPixelBufferAccess::ConstPixelBufferAccess(const TextureFormat &format, int width, int height, int depth, |
| const void *data) |
| : m_format(format) |
| , m_size(width, height, depth) |
| , m_pitch(calculatePackedPitch(m_format, m_size)) |
| , m_divider(1, 1, 1) |
| , m_data((void *)data) |
| { |
| DE_ASSERT(isValid(format)); |
| } |
| |
| ConstPixelBufferAccess::ConstPixelBufferAccess(const TextureFormat &format, const IVec3 &size, const void *data) |
| : m_format(format) |
| , m_size(size) |
| , m_pitch(calculatePackedPitch(m_format, m_size)) |
| , m_divider(1, 1, 1) |
| , m_data((void *)data) |
| { |
| DE_ASSERT(isValid(format)); |
| } |
| |
| ConstPixelBufferAccess::ConstPixelBufferAccess(const TextureFormat &format, int width, int height, int depth, |
| int rowPitch, int slicePitch, const void *data) |
| : m_format(format) |
| , m_size(width, height, depth) |
| , m_pitch(format.getPixelSize(), rowPitch, slicePitch) |
| , m_divider(1, 1, 1) |
| , m_data((void *)data) |
| { |
| DE_ASSERT(isValid(format)); |
| } |
| |
| ConstPixelBufferAccess::ConstPixelBufferAccess(const TextureFormat &format, const IVec3 &size, const IVec3 &pitch, |
| const void *data) |
| : m_format(format) |
| , m_size(size) |
| , m_pitch(pitch) |
| , m_divider(1, 1, 1) |
| , m_data((void *)data) |
| { |
| DE_ASSERT(isValid(format)); |
| DE_ASSERT(m_format.getPixelSize() <= m_pitch.x()); |
| } |
| |
| ConstPixelBufferAccess::ConstPixelBufferAccess(const TextureFormat &format, const IVec3 &size, const IVec3 &pitch, |
| const IVec3 &block, const void *data) |
| : m_format(format) |
| , m_size(size) |
| , m_pitch(pitch) |
| , m_divider(block) |
| , m_data((void *)data) |
| { |
| DE_ASSERT(isValid(format)); |
| DE_ASSERT(m_format.getPixelSize() <= m_pitch.x()); |
| } |
| |
| ConstPixelBufferAccess::ConstPixelBufferAccess(const TextureLevel &level) |
| : m_format(level.getFormat()) |
| , m_size(level.getSize()) |
| , m_pitch(calculatePackedPitch(m_format, m_size)) |
| , m_divider(1, 1, 1) |
| , m_data((void *)level.getPtr()) |
| { |
| } |
| |
| PixelBufferAccess::PixelBufferAccess(const TextureFormat &format, int width, int height, int depth, void *data) |
| : ConstPixelBufferAccess(format, width, height, depth, data) |
| { |
| } |
| |
| PixelBufferAccess::PixelBufferAccess(const TextureFormat &format, const IVec3 &size, void *data) |
| : ConstPixelBufferAccess(format, size, data) |
| { |
| } |
| |
| PixelBufferAccess::PixelBufferAccess(const TextureFormat &format, int width, int height, int depth, int rowPitch, |
| int slicePitch, void *data) |
| : ConstPixelBufferAccess(format, width, height, depth, rowPitch, slicePitch, data) |
| { |
| } |
| |
| PixelBufferAccess::PixelBufferAccess(const TextureFormat &format, const IVec3 &size, const IVec3 &pitch, void *data) |
| : ConstPixelBufferAccess(format, size, pitch, data) |
| { |
| } |
| |
| PixelBufferAccess::PixelBufferAccess(const TextureFormat &format, const IVec3 &size, const IVec3 &pitch, |
| const IVec3 &block, void *data) |
| : ConstPixelBufferAccess(format, size, pitch, block, data) |
| { |
| } |
| |
| PixelBufferAccess::PixelBufferAccess(TextureLevel &level) : ConstPixelBufferAccess(level) |
| { |
| } |
| |
| //! Swizzle generally based on channel order. |
| template <typename T> |
| Vector<T, 4> swizzleGe(const Vector<T, 4> &v, TextureFormat::ChannelOrder src, TextureFormat::ChannelOrder dst) |
| { |
| if (src == dst) |
| return v; |
| else |
| { |
| if ((src == TextureFormat::RGBA && dst == TextureFormat::ARGB) || |
| (src == TextureFormat::BGRA && dst == TextureFormat::ABGR)) |
| return v.swizzle(3, 0, 1, 2); |
| |
| if ((src == TextureFormat::ARGB && dst == TextureFormat::RGBA) || |
| (src == TextureFormat::ABGR && dst == TextureFormat::BGRA)) |
| return v.swizzle(1, 2, 3, 0); |
| |
| if ((src == TextureFormat::BGRA && dst == TextureFormat::ARGB) || |
| (src == TextureFormat::ABGR && dst == TextureFormat::RGBA) || |
| (src == TextureFormat::RGBA && dst == TextureFormat::ABGR) || |
| (src == TextureFormat::ARGB && dst == TextureFormat::BGRA)) |
| return v.swizzle(3, 2, 1, 0); |
| |
| if ((src == TextureFormat::RGB && dst == TextureFormat::BGR) || |
| (src == TextureFormat::BGR && dst == TextureFormat::RGB) || |
| (src == TextureFormat::RGBA && dst == TextureFormat::BGRA) || |
| (src == TextureFormat::BGRA && dst == TextureFormat::RGBA)) |
| return v.swizzle(2, 1, 0, 3); |
| |
| DE_ASSERT(false); |
| return v; |
| } |
| } |
| |
| Vec4 ConstPixelBufferAccess::getPixel(int x, int y, int z) const |
| { |
| DE_ASSERT(de::inBounds(x, 0, m_size.x())); |
| DE_ASSERT(de::inBounds(y, 0, m_size.y())); |
| DE_ASSERT(de::inBounds(z, 0, m_size.z())); |
| DE_ASSERT(!isCombinedDepthStencilType(m_format.type)); // combined types cannot be accessed directly |
| DE_ASSERT(m_format.order != TextureFormat::DS); // combined formats cannot be accessed directly |
| |
| const uint8_t *pixelPtr = (const uint8_t *)getPixelPtr(x, y, z); |
| |
| // Optimized fomats. |
| if (m_format.type == TextureFormat::UNORM_INT8) |
| { |
| if (m_format.order == TextureFormat::RGBA || m_format.order == TextureFormat::sRGBA) |
| return readRGBA8888Float(pixelPtr); |
| else if (m_format.order == TextureFormat::RGB || m_format.order == TextureFormat::sRGB) |
| return readRGB888Float(pixelPtr); |
| } |
| |
| #define UI8(OFFS, COUNT) ((*((const uint8_t *)pixelPtr) >> (OFFS)) & ((1 << (COUNT)) - 1)) |
| #define UI16(OFFS, COUNT) ((*((const uint16_t *)pixelPtr) >> (OFFS)) & ((1 << (COUNT)) - 1)) |
| #define UI32(OFFS, COUNT) ((*((const uint32_t *)pixelPtr) >> (OFFS)) & ((1 << (COUNT)) - 1)) |
| #define SI32(OFFS, COUNT) signExtend(UI32(OFFS, COUNT), (COUNT)) |
| #define UN8(OFFS, COUNT) channelToUnormFloat(UI8(OFFS, COUNT), (COUNT)) |
| #define UN16(OFFS, COUNT) channelToUnormFloat(UI16(OFFS, COUNT), (COUNT)) |
| #define UN32(OFFS, COUNT) channelToUnormFloat(UI32(OFFS, COUNT), (COUNT)) |
| #define SN32(OFFS, COUNT) channelToSnormFloat(UI32(OFFS, COUNT), (COUNT)) |
| |
| // Packed formats. |
| switch (m_format.type) |
| { |
| case TextureFormat::UNORM_BYTE_44: |
| return Vec4(UN8(4, 4), UN8(0, 4), 0.0f, 1.0f); |
| case TextureFormat::UNSIGNED_BYTE_44: |
| return UVec4(UI8(4, 4), UI8(0, 4), 0u, 1u).cast<float>(); |
| case TextureFormat::UNORM_SHORT_565: |
| return swizzleGe(Vec4(UN16(11, 5), UN16(5, 6), UN16(0, 5), 1.0f), m_format.order, TextureFormat::RGB); |
| case TextureFormat::UNSIGNED_SHORT_565: |
| return swizzleGe(UVec4(UI16(11, 5), UI16(5, 6), UI16(0, 5), 1u), m_format.order, TextureFormat::RGB) |
| .cast<float>(); |
| case TextureFormat::UNORM_SHORT_555: |
| return swizzleGe(Vec4(UN16(10, 5), UN16(5, 5), UN16(0, 5), 1.0f), m_format.order, TextureFormat::RGB); |
| case TextureFormat::UNORM_SHORT_4444: |
| return swizzleGe(Vec4(UN16(12, 4), UN16(8, 4), UN16(4, 4), UN16(0, 4)), m_format.order, TextureFormat::RGBA); |
| case TextureFormat::UNSIGNED_SHORT_4444: |
| return swizzleGe(UVec4(UI16(12, 4), UI16(8, 4), UI16(4, 4), UI16(0, 4)), m_format.order, TextureFormat::RGBA) |
| .cast<float>(); |
| case TextureFormat::UNORM_SHORT_5551: |
| return swizzleGe(Vec4(UN16(11, 5), UN16(6, 5), UN16(1, 5), UN16(0, 1)), m_format.order, TextureFormat::RGBA); |
| case TextureFormat::UNSIGNED_SHORT_5551: |
| return swizzleGe(UVec4(UI16(11, 5), UI16(6, 5), UI16(1, 5), UI16(0, 1)), m_format.order, TextureFormat::RGBA) |
| .cast<float>(); |
| case TextureFormat::UNORM_SHORT_1555: |
| return swizzleGe(Vec4(UN16(15, 1), UN16(10, 5), UN16(5, 5), UN16(0, 5)), m_format.order, TextureFormat::RGBA); |
| case TextureFormat::UNORM_INT_101010: |
| return Vec4(UN32(22, 10), UN32(12, 10), UN32(2, 10), 1.0f); |
| case TextureFormat::UNORM_INT_1010102_REV: |
| return swizzleGe(Vec4(UN32(0, 10), UN32(10, 10), UN32(20, 10), UN32(30, 2)), m_format.order, |
| TextureFormat::RGBA); |
| case TextureFormat::SNORM_INT_1010102_REV: |
| return swizzleGe(Vec4(SN32(0, 10), SN32(10, 10), SN32(20, 10), SN32(30, 2)), m_format.order, |
| TextureFormat::RGBA); |
| case TextureFormat::USCALED_INT_1010102_REV: |
| case TextureFormat::UNSIGNED_INT_1010102_REV: |
| return swizzleGe(UVec4(UI32(0, 10), UI32(10, 10), UI32(20, 10), UI32(30, 2)), m_format.order, |
| TextureFormat::RGBA) |
| .cast<float>(); |
| case TextureFormat::SSCALED_INT_1010102_REV: |
| case TextureFormat::SIGNED_INT_1010102_REV: |
| return swizzleGe(UVec4(SI32(0, 10), SI32(10, 10), SI32(20, 10), SI32(30, 2)), m_format.order, |
| TextureFormat::RGBA) |
| .cast<float>(); |
| case TextureFormat::UNSIGNED_INT_999_E5_REV: |
| return unpackRGB999E5(*((const uint32_t *)pixelPtr)); |
| |
| case TextureFormat::UNSIGNED_INT_11F_11F_10F_REV: |
| return Vec4(Float11(UI32(0, 11)).asFloat(), Float11(UI32(11, 11)).asFloat(), Float10(UI32(22, 10)).asFloat(), |
| 1.0f); |
| |
| default: |
| break; |
| } |
| |
| #undef UN8 |
| #undef UN16 |
| #undef UN32 |
| #undef SN32 |
| #undef SI32 |
| #undef UI8 |
| #undef UI16 |
| #undef UI32 |
| |
| // Generic path. |
| Vec4 result; |
| const TextureSwizzle::Channel *channelMap = getChannelReadSwizzle(m_format.order).components; |
| int channelSize = getChannelSize(m_format.type); |
| |
| for (int c = 0; c < 4; c++) |
| { |
| switch (channelMap[c]) |
| { |
| case TextureSwizzle::CHANNEL_0: |
| case TextureSwizzle::CHANNEL_1: |
| case TextureSwizzle::CHANNEL_2: |
| case TextureSwizzle::CHANNEL_3: |
| result[c] = channelToFloat(pixelPtr + channelSize * ((int)channelMap[c]), m_format.type); |
| break; |
| |
| case TextureSwizzle::CHANNEL_ZERO: |
| result[c] = 0.0f; |
| break; |
| |
| case TextureSwizzle::CHANNEL_ONE: |
| result[c] = 1.0f; |
| break; |
| |
| default: |
| DE_ASSERT(false); |
| } |
| } |
| |
| return result; |
| } |
| |
| template <typename T> |
| static tcu::Vector<T, 4> getPixelIntGeneric(const uint8_t *pixelPtr, const tcu::TextureFormat &format) |
| { |
| tcu::Vector<T, 4> result; |
| |
| // Generic path. |
| const TextureSwizzle::Channel *channelMap = getChannelReadSwizzle(format.order).components; |
| int channelSize = getChannelSize(format.type); |
| |
| for (int c = 0; c < 4; c++) |
| { |
| switch (channelMap[c]) |
| { |
| case TextureSwizzle::CHANNEL_0: |
| case TextureSwizzle::CHANNEL_1: |
| case TextureSwizzle::CHANNEL_2: |
| case TextureSwizzle::CHANNEL_3: |
| result[c] = channelToIntType<T>(pixelPtr + channelSize * ((int)channelMap[c]), format.type); |
| break; |
| |
| case TextureSwizzle::CHANNEL_ZERO: |
| result[c] = 0; |
| break; |
| |
| case TextureSwizzle::CHANNEL_ONE: |
| result[c] = 1; |
| break; |
| |
| default: |
| DE_ASSERT(false); |
| } |
| } |
| |
| return result; |
| } |
| |
| static U64Vec4 getPixelAsBitsUint64(const uint8_t *pixelPtr, const tcu::TextureFormat &format) |
| { |
| U64Vec4 result; |
| |
| // Generic path. |
| const TextureSwizzle::Channel *channelMap = getChannelReadSwizzle(format.order).components; |
| int channelSize = getChannelSize(format.type); |
| |
| for (int c = 0; c < 4; c++) |
| { |
| switch (channelMap[c]) |
| { |
| case TextureSwizzle::CHANNEL_0: |
| case TextureSwizzle::CHANNEL_1: |
| case TextureSwizzle::CHANNEL_2: |
| case TextureSwizzle::CHANNEL_3: |
| result[c] = retrieveChannelBitsAsUint64(pixelPtr + channelSize * ((int)channelMap[c]), format.type); |
| break; |
| |
| case TextureSwizzle::CHANNEL_ZERO: |
| result[c] = 0; |
| break; |
| |
| case TextureSwizzle::CHANNEL_ONE: |
| result[c] = 1; |
| break; |
| |
| default: |
| DE_ASSERT(false); |
| } |
| } |
| |
| return result; |
| } |
| |
| IVec4 ConstPixelBufferAccess::getPixelInt(int x, int y, int z) const |
| { |
| DE_ASSERT(de::inBounds(x, 0, m_size.x())); |
| DE_ASSERT(de::inBounds(y, 0, m_size.y())); |
| DE_ASSERT(de::inBounds(z, 0, m_size.z())); |
| DE_ASSERT(!isCombinedDepthStencilType(m_format.type)); // combined types cannot be accessed directly |
| DE_ASSERT(m_format.order != TextureFormat::DS); // combined formats cannot be accessed directly |
| |
| const uint8_t *const pixelPtr = (const uint8_t *)getPixelPtr(x, y, z); |
| |
| // Optimized fomats. |
| if (m_format.type == TextureFormat::UNORM_INT8) |
| { |
| if (m_format.order == TextureFormat::RGBA || m_format.order == TextureFormat::sRGBA) |
| return readRGBA8888Int(pixelPtr); |
| else if (m_format.order == TextureFormat::RGB || m_format.order == TextureFormat::sRGB) |
| return readRGB888Int(pixelPtr); |
| } |
| |
| #define U8(OFFS, COUNT) ((*((const uint8_t *)pixelPtr) >> (OFFS)) & ((1 << (COUNT)) - 1)) |
| #define U16(OFFS, COUNT) ((*((const uint16_t *)pixelPtr) >> (OFFS)) & ((1 << (COUNT)) - 1)) |
| #define U32(OFFS, COUNT) ((*((const uint32_t *)pixelPtr) >> (OFFS)) & ((1 << (COUNT)) - 1)) |
| #define S32(OFFS, COUNT) signExtend(U32(OFFS, COUNT), (COUNT)) |
| |
| switch (m_format.type) |
| { |
| case TextureFormat::UNSIGNED_BYTE_44: // Fall-through |
| case TextureFormat::UNORM_BYTE_44: |
| return UVec4(U8(4, 4), U8(0, 4), 0u, 1u).cast<int>(); |
| case TextureFormat::UNSIGNED_SHORT_565: // Fall-through |
| case TextureFormat::UNORM_SHORT_565: |
| return swizzleGe(UVec4(U16(11, 5), U16(5, 6), U16(0, 5), 1).cast<int>(), m_format.order, TextureFormat::RGB); |
| case TextureFormat::UNORM_SHORT_555: |
| return swizzleGe(UVec4(U16(10, 5), U16(5, 5), U16(0, 5), 1).cast<int>(), m_format.order, TextureFormat::RGB); |
| case TextureFormat::UNSIGNED_SHORT_4444: // Fall-through |
| case TextureFormat::UNORM_SHORT_4444: |
| return swizzleGe(UVec4(U16(12, 4), U16(8, 4), U16(4, 4), U16(0, 4)).cast<int>(), m_format.order, |
| TextureFormat::RGBA); |
| case TextureFormat::UNSIGNED_SHORT_5551: // Fall-through |
| case TextureFormat::UNORM_SHORT_5551: |
| return swizzleGe(UVec4(U16(11, 5), U16(6, 5), U16(1, 5), U16(0, 1)).cast<int>(), m_format.order, |
| TextureFormat::RGBA); |
| case TextureFormat::UNORM_SHORT_1555: |
| return swizzleGe(UVec4(U16(15, 1), U16(10, 5), U16(5, 5), U16(0, 5)).cast<int>(), m_format.order, |
| TextureFormat::RGBA); |
| case TextureFormat::UNORM_INT_101010: |
| return UVec4(U32(22, 10), U32(12, 10), U32(2, 10), 1).cast<int>(); |
| case TextureFormat::UNORM_INT_1010102_REV: // Fall-through |
| case TextureFormat::USCALED_INT_1010102_REV: // Fall-through |
| case TextureFormat::UNSIGNED_INT_1010102_REV: |
| return swizzleGe(UVec4(U32(0, 10), U32(10, 10), U32(20, 10), U32(30, 2)), m_format.order, TextureFormat::RGBA) |
| .cast<int>(); |
| case TextureFormat::SNORM_INT_1010102_REV: // Fall-through |
| case TextureFormat::SSCALED_INT_1010102_REV: // Fall-through |
| case TextureFormat::SIGNED_INT_1010102_REV: |
| return swizzleGe(IVec4(S32(0, 10), S32(10, 10), S32(20, 10), S32(30, 2)), m_format.order, TextureFormat::RGBA); |
| |
| default: |
| break; // To generic path. |
| } |
| |
| #undef U8 |
| #undef U16 |
| #undef U32 |
| #undef S32 |
| |
| // Generic path. |
| return getPixelIntGeneric<int>(pixelPtr, m_format); |
| } |
| |
| I64Vec4 ConstPixelBufferAccess::getPixelInt64(int x, int y, int z) const |
| { |
| // Rely on getPixelInt() for some formats. |
| if (m_format.type == TextureFormat::UNORM_INT8 && |
| (m_format.order == TextureFormat::RGBA || m_format.order == TextureFormat::sRGBA || |
| m_format.order == TextureFormat::RGB || m_format.order == TextureFormat::sRGB)) |
| { |
| return getPixelInt(x, y, z).cast<int64_t>(); |
| } |
| |
| switch (m_format.type) |
| { |
| case TextureFormat::UNSIGNED_BYTE_44: |
| case TextureFormat::UNORM_BYTE_44: |
| case TextureFormat::UNSIGNED_SHORT_565: |
| case TextureFormat::UNORM_SHORT_565: |
| case TextureFormat::UNORM_SHORT_555: |
| case TextureFormat::UNSIGNED_SHORT_4444: |
| case TextureFormat::UNORM_SHORT_4444: |
| case TextureFormat::UNSIGNED_SHORT_5551: |
| case TextureFormat::UNORM_SHORT_5551: |
| case TextureFormat::UNORM_INT_101010: |
| case TextureFormat::UNORM_INT_1010102_REV: |
| case TextureFormat::USCALED_INT_1010102_REV: |
| case TextureFormat::UNSIGNED_INT_1010102_REV: |
| case TextureFormat::SNORM_INT_1010102_REV: |
| case TextureFormat::SSCALED_INT_1010102_REV: |
| case TextureFormat::SIGNED_INT_1010102_REV: |
| case TextureFormat::UNORM_SHORT_1555: |
| return getPixelInt(x, y, z).cast<int64_t>(); |
| |
| default: |
| break; // To generic path. |
| } |
| |
| // Generic path. |
| auto pixelPtr = reinterpret_cast<const uint8_t *>(getPixelPtr(x, y, z)); |
| return getPixelIntGeneric<int64_t>(pixelPtr, m_format); |
| } |
| |
| U64Vec4 ConstPixelBufferAccess::getPixelBitsAsUint64(int x, int y, int z) const |
| { |
| DE_ASSERT(de::inBounds(x, 0, m_size.x())); |
| DE_ASSERT(de::inBounds(y, 0, m_size.y())); |
| DE_ASSERT(de::inBounds(z, 0, m_size.z())); |
| DE_ASSERT(!isCombinedDepthStencilType(m_format.type)); // combined types cannot be accessed directly |
| DE_ASSERT(m_format.order != TextureFormat::DS); // combined formats cannot be accessed directly |
| |
| const uint8_t *const pixelPtr = (const uint8_t *)getPixelPtr(x, y, z); |
| |
| if (m_format.type == TextureFormat::UNORM_INT8) |
| { |
| if (m_format.order == TextureFormat::RGBA || m_format.order == TextureFormat::sRGBA) |
| return U64Vec4(pixelPtr[0], pixelPtr[1], pixelPtr[2], pixelPtr[3]); |
| else if (m_format.order == TextureFormat::RGB || m_format.order == TextureFormat::sRGB) |
| return U64Vec4(pixelPtr[0], pixelPtr[1], pixelPtr[2], 1); |
| } |
| |
| #define U8(OFFS, COUNT) ((*((const uint8_t *)pixelPtr) >> (OFFS)) & ((1 << (COUNT)) - 1)) |
| #define U16(OFFS, COUNT) ((*((const uint16_t *)pixelPtr) >> (OFFS)) & ((1 << (COUNT)) - 1)) |
| #define U32(OFFS, COUNT) ((*((const uint32_t *)pixelPtr) >> (OFFS)) & ((1 << (COUNT)) - 1)) |
| |
| switch (m_format.type) |
| { |
| case TextureFormat::UNSIGNED_BYTE_44: // Fall-through |
| case TextureFormat::UNORM_BYTE_44: |
| return U64Vec4(U8(4, 4), U8(0, 4), 0u, 1u); |
| case TextureFormat::UNSIGNED_SHORT_565: // Fall-through |
| case TextureFormat::UNORM_SHORT_565: |
| return swizzleGe(U64Vec4(U16(11, 5), U16(5, 6), U16(0, 5), 1), m_format.order, TextureFormat::RGB); |
| case TextureFormat::UNORM_SHORT_555: |
| return swizzleGe(U64Vec4(U16(10, 5), U16(5, 5), U16(0, 5), 1), m_format.order, TextureFormat::RGB); |
| case TextureFormat::UNSIGNED_SHORT_4444: // Fall-through |
| case TextureFormat::UNORM_SHORT_4444: |
| return swizzleGe(U64Vec4(U16(12, 4), U16(8, 4), U16(4, 4), U16(0, 4)), m_format.order, TextureFormat::RGBA); |
| case TextureFormat::UNSIGNED_SHORT_5551: // Fall-through |
| case TextureFormat::UNORM_SHORT_5551: |
| return swizzleGe(U64Vec4(U16(11, 5), U16(6, 5), U16(1, 5), U16(0, 1)), m_format.order, TextureFormat::RGBA); |
| case TextureFormat::UNORM_INT_101010: |
| return U64Vec4(U32(22, 10), U32(12, 10), U32(2, 10), 1); |
| case TextureFormat::UNORM_INT_1010102_REV: // Fall-through |
| case TextureFormat::USCALED_INT_1010102_REV: // Fall-through |
| case TextureFormat::UNSIGNED_INT_1010102_REV: |
| return swizzleGe(U64Vec4(U32(0, 10), U32(10, 10), U32(20, 10), U32(30, 2)), m_format.order, |
| TextureFormat::RGBA); |
| case TextureFormat::SNORM_INT_1010102_REV: // Fall-through |
| case TextureFormat::SSCALED_INT_1010102_REV: // Fall-through |
| case TextureFormat::SIGNED_INT_1010102_REV: |
| return swizzleGe(U64Vec4(U32(0, 10), U32(10, 10), U32(20, 10), U32(30, 2)), m_format.order, |
| TextureFormat::RGBA); |
| case TextureFormat::UNORM_SHORT_1555: |
| return swizzleGe(U64Vec4(U16(15, 1), U16(10, 5), U16(5, 5), U16(0, 5)), m_format.order, TextureFormat::RGBA); |
| |
| default: |
| break; // To generic path. |
| } |
| |
| #undef U8 |
| #undef U16 |
| #undef U32 |
| |
| // Generic path. |
| return getPixelAsBitsUint64(pixelPtr, m_format); |
| } |
| |
| template <> |
| Vec4 ConstPixelBufferAccess::getPixelT(int x, int y, int z) const |
| { |
| return getPixel(x, y, z); |
| } |
| |
| template <> |
| IVec4 ConstPixelBufferAccess::getPixelT(int x, int y, int z) const |
| { |
| return getPixelInt(x, y, z); |
| } |
| |
| template <> |
| UVec4 ConstPixelBufferAccess::getPixelT(int x, int y, int z) const |
| { |
| return getPixelUint(x, y, z); |
| } |
| |
| template <> |
| I64Vec4 ConstPixelBufferAccess::getPixelT(int x, int y, int z) const |
| { |
| return getPixelInt64(x, y, z); |
| } |
| |
| template <> |
| U64Vec4 ConstPixelBufferAccess::getPixelT(int x, int y, int z) const |
| { |
| return getPixelUint64(x, y, z); |
| } |
| |
| float ConstPixelBufferAccess::getPixDepth(int x, int y, int z) const |
| { |
| DE_ASSERT(de::inBounds(x, 0, getWidth())); |
| DE_ASSERT(de::inBounds(y, 0, getHeight())); |
| DE_ASSERT(de::inBounds(z, 0, getDepth())); |
| |
| const uint8_t *const pixelPtr = (const uint8_t *)getPixelPtr(x, y, z); |
| |
| switch (m_format.type) |
| { |
| case TextureFormat::UNSIGNED_INT_16_8_8: |
| DE_ASSERT(m_format.order == TextureFormat::DS); |
| return (float)readUint32High16(pixelPtr) / 65535.0f; |
| |
| case TextureFormat::UNSIGNED_INT_24_8: |
| DE_ASSERT(m_format.order == TextureFormat::D || m_format.order == TextureFormat::DS); |
| return (float)readUint32High24(pixelPtr) / 16777215.0f; |
| |
| case TextureFormat::UNSIGNED_INT_24_8_REV: |
| DE_ASSERT(m_format.order == TextureFormat::D || m_format.order == TextureFormat::DS); |
| return (float)readUint32Low24(pixelPtr) / 16777215.0f; |
| |
| case TextureFormat::FLOAT_UNSIGNED_INT_24_8_REV: |
| DE_ASSERT(m_format.order == TextureFormat::DS); |
| return *((const float *)pixelPtr); |
| |
| default: |
| DE_ASSERT(m_format.order == TextureFormat::D); // no other combined depth stencil types |
| return channelToFloat(pixelPtr, m_format.type); |
| } |
| } |
| |
| int ConstPixelBufferAccess::getPixStencil(int x, int y, int z) const |
| { |
| DE_ASSERT(de::inBounds(x, 0, getWidth())); |
| DE_ASSERT(de::inBounds(y, 0, getHeight())); |
| DE_ASSERT(de::inBounds(z, 0, getDepth())); |
| |
| const uint8_t *const pixelPtr = (const uint8_t *)getPixelPtr(x, y, z); |
| |
| switch (m_format.type) |
| { |
| case TextureFormat::UNSIGNED_INT_24_8_REV: |
| DE_ASSERT(m_format.order == TextureFormat::DS); |
| return (int)readUint32High8(pixelPtr); |
| |
| case TextureFormat::UNSIGNED_INT_16_8_8: |
| case TextureFormat::UNSIGNED_INT_24_8: |
| DE_ASSERT(m_format.order == TextureFormat::DS); |
| return (int)readUint32Low8(pixelPtr); |
| |
| case TextureFormat::FLOAT_UNSIGNED_INT_24_8_REV: |
| DE_ASSERT(m_format.order == TextureFormat::DS); |
| return (int)readUint32Low8(pixelPtr + 4); |
| |
| default: |
| { |
| DE_ASSERT(m_format.order == TextureFormat::S); // no other combined depth stencil types |
| return channelToInt(pixelPtr, m_format.type); |
| } |
| } |
| } |
| |
| void PixelBufferAccess::setPixel(const Vec4 &color, int x, int y, int z) const |
| { |
| DE_ASSERT(de::inBounds(x, 0, getWidth())); |
| DE_ASSERT(de::inBounds(y, 0, getHeight())); |
| DE_ASSERT(de::inBounds(z, 0, getDepth())); |
| DE_ASSERT(!isCombinedDepthStencilType(m_format.type)); // combined types cannot be accessed directly |
| DE_ASSERT(m_format.order != TextureFormat::DS); // combined formats cannot be accessed directly |
| |
| uint8_t *const pixelPtr = (uint8_t *)getPixelPtr(x, y, z); |
| |
| // Optimized fomats. |
| if (m_format.type == TextureFormat::UNORM_INT8) |
| { |
| if (m_format.order == TextureFormat::RGBA || m_format.order == TextureFormat::sRGBA) |
| { |
| writeRGBA8888Float(pixelPtr, color); |
| return; |
| } |
| else if (m_format.order == TextureFormat::RGB || m_format.order == TextureFormat::sRGB) |
| { |
| writeRGB888Float(pixelPtr, color); |
| return; |
| } |
| } |
| |
| #define PN(VAL, OFFS, BITS) (unormFloatToChannel((VAL), (BITS)) << (OFFS)) |
| #define PS(VAL, OFFS, BITS) (snormFloatToChannel((VAL), (BITS)) << (OFFS)) |
| #define PU(VAL, OFFS, BITS) (uintToChannel((VAL), (BITS)) << (OFFS)) |
| #define PI(VAL, OFFS, BITS) (intToChannel((VAL), (BITS)) << (OFFS)) |
| |
| switch (m_format.type) |
| { |
| case TextureFormat::UNORM_BYTE_44: |
| *((uint8_t *)pixelPtr) = (uint8_t)(PN(color[0], 4, 4) | PN(color[1], 0, 4)); |
| break; |
| case TextureFormat::UNSIGNED_BYTE_44: |
| *((uint8_t *)pixelPtr) = (uint8_t)(PU((uint32_t)color[0], 4, 4) | PU((uint32_t)color[1], 0, 4)); |
| break; |
| case TextureFormat::UNORM_INT_101010: |
| *((uint32_t *)pixelPtr) = PN(color[0], 22, 10) | PN(color[1], 12, 10) | PN(color[2], 2, 10); |
| break; |
| |
| case TextureFormat::UNORM_SHORT_565: |
| { |
| const Vec4 swizzled = swizzleGe(color, TextureFormat::RGB, m_format.order); |
| *((uint16_t *)pixelPtr) = (uint16_t)(PN(swizzled[0], 11, 5) | PN(swizzled[1], 5, 6) | PN(swizzled[2], 0, 5)); |
| break; |
| } |
| |
| case TextureFormat::UNSIGNED_SHORT_565: |
| { |
| const UVec4 swizzled = swizzleGe(color.cast<uint32_t>(), TextureFormat::RGB, m_format.order); |
| *((uint16_t *)pixelPtr) = (uint16_t)(PU(swizzled[0], 11, 5) | PU(swizzled[1], 5, 6) | PU(swizzled[2], 0, 5)); |
| break; |
| } |
| |
| case TextureFormat::UNORM_SHORT_555: |
| { |
| const Vec4 swizzled = swizzleGe(color, TextureFormat::RGB, m_format.order); |
| *((uint16_t *)pixelPtr) = (uint16_t)(PN(swizzled[0], 10, 5) | PN(swizzled[1], 5, 5) | PN(swizzled[2], 0, 5)); |
| break; |
| } |
| |
| case TextureFormat::UNORM_SHORT_4444: |
| { |
| const Vec4 swizzled = swizzleGe(color, TextureFormat::RGBA, m_format.order); |
| *((uint16_t *)pixelPtr) = |
| (uint16_t)(PN(swizzled[0], 12, 4) | PN(swizzled[1], 8, 4) | PN(swizzled[2], 4, 4) | PN(swizzled[3], 0, 4)); |
| break; |
| } |
| |
| case TextureFormat::UNSIGNED_SHORT_4444: |
| { |
| const UVec4 swizzled = swizzleGe(color.cast<uint32_t>(), TextureFormat::RGBA, m_format.order); |
| *((uint16_t *)pixelPtr) = |
| (uint16_t)(PU(swizzled[0], 12, 4) | PU(swizzled[1], 8, 4) | PU(swizzled[2], 4, 4) | PU(swizzled[3], 0, 4)); |
| break; |
| } |
| |
| case TextureFormat::UNORM_SHORT_5551: |
| { |
| const Vec4 swizzled = swizzleGe(color, TextureFormat::RGBA, m_format.order); |
| *((uint16_t *)pixelPtr) = |
| (uint16_t)(PN(swizzled[0], 11, 5) | PN(swizzled[1], 6, 5) | PN(swizzled[2], 1, 5) | PN(swizzled[3], 0, 1)); |
| break; |
| } |
| |
| case TextureFormat::UNORM_SHORT_1555: |
| { |
| const Vec4 swizzled = swizzleGe(color, TextureFormat::RGBA, m_format.order); |
| *((uint16_t *)pixelPtr) = |
| (uint16_t)(PN(swizzled[0], 15, 1) | PN(swizzled[1], 10, 5) | PN(swizzled[2], 5, 5) | PN(swizzled[3], 0, 5)); |
| break; |
| } |
| |
| case TextureFormat::UNSIGNED_SHORT_5551: |
| { |
| const UVec4 swizzled = swizzleGe(color.cast<uint32_t>(), TextureFormat::RGBA, m_format.order); |
| *((uint16_t *)pixelPtr) = |
| (uint16_t)(PU(swizzled[0], 11, 5) | PU(swizzled[1], 6, 5) | PU(swizzled[2], 1, 5) | PU(swizzled[3], 0, 1)); |
| break; |
| } |
| |
| case TextureFormat::UNORM_INT_1010102_REV: |
| { |
| const Vec4 u = swizzleGe(color, TextureFormat::RGBA, m_format.order); |
| *((uint32_t *)pixelPtr) = PN(u[0], 0, 10) | PN(u[1], 10, 10) | PN(u[2], 20, 10) | PN(u[3], 30, 2); |
| break; |
| } |
| |
| case TextureFormat::SNORM_INT_1010102_REV: |
| { |
| const Vec4 u = swizzleGe(color, TextureFormat::RGBA, m_format.order); |
| *((uint32_t *)pixelPtr) = PS(u[0], 0, 10) | PS(u[1], 10, 10) | PS(u[2], 20, 10) | PS(u[3], 30, 2); |
| break; |
| } |
| |
| case TextureFormat::UNSIGNED_INT_1010102_REV: |
| case TextureFormat::USCALED_INT_1010102_REV: |
| { |
| const UVec4 u = swizzleGe(color.cast<uint32_t>(), TextureFormat::RGBA, m_format.order); |
| *((uint32_t *)pixelPtr) = PU(u[0], 0, 10) | PU(u[1], 10, 10) | PU(u[2], 20, 10) | PU(u[3], 30, 2); |
| break; |
| } |
| |
| case TextureFormat::SIGNED_INT_1010102_REV: |
| case TextureFormat::SSCALED_INT_1010102_REV: |
| { |
| const IVec4 u = swizzleGe(color.cast<int32_t>(), TextureFormat::RGBA, m_format.order); |
| *((uint32_t *)pixelPtr) = PI(u[0], 0, 10) | PI(u[1], 10, 10) | PI(u[2], 20, 10) | PI(u[3], 30, 2); |
| break; |
| } |
| |
| case TextureFormat::UNSIGNED_INT_11F_11F_10F_REV: |
| *((uint32_t *)pixelPtr) = |
| Float11(color[0]).bits() | (Float11(color[1]).bits() << 11) | (Float10(color[2]).bits() << 22); |
| break; |
| |
| case TextureFormat::UNSIGNED_INT_999_E5_REV: |
| *((uint32_t *)pixelPtr) = packRGB999E5(color); |
| break; |
| |
| default: |
| { |
| // Generic path. |
| int numChannels = getNumUsedChannels(m_format.order); |
| const TextureSwizzle::Channel *map = getChannelWriteSwizzle(m_format.order).components; |
| int channelSize = getChannelSize(m_format.type); |
| |
| for (int c = 0; c < numChannels; c++) |
| { |
| DE_ASSERT(deInRange32(map[c], TextureSwizzle::CHANNEL_0, TextureSwizzle::CHANNEL_3)); |
| floatToChannel(pixelPtr + channelSize * c, color[map[c]], m_format.type); |
| } |
| break; |
| } |
| } |
| |
| #undef PN |
| #undef PS |
| #undef PU |
| #undef PI |
| } |
| |
| void PixelBufferAccess::setPixel(const IVec4 &color, int x, int y, int z) const |
| { |
| DE_ASSERT(de::inBounds(x, 0, getWidth())); |
| DE_ASSERT(de::inBounds(y, 0, getHeight())); |
| DE_ASSERT(de::inBounds(z, 0, getDepth())); |
| DE_ASSERT(!isCombinedDepthStencilType(m_format.type)); // combined types cannot be accessed directly |
| DE_ASSERT(m_format.order != TextureFormat::DS); // combined formats cannot be accessed directly |
| |
| uint8_t *const pixelPtr = (uint8_t *)getPixelPtr(x, y, z); |
| |
| // Optimized fomats. |
| if (m_format.type == TextureFormat::UNORM_INT8) |
| { |
| if (m_format.order == TextureFormat::RGBA || m_format.order == TextureFormat::sRGBA) |
| { |
| writeRGBA8888Int(pixelPtr, color); |
| return; |
| } |
| else if (m_format.order == TextureFormat::RGB || m_format.order == TextureFormat::sRGB) |
| { |
| writeRGB888Int(pixelPtr, color); |
| return; |
| } |
| } |
| |
| #define PU(VAL, OFFS, BITS) (uintToChannel((uint32_t)(VAL), (BITS)) << (OFFS)) |
| #define PI(VAL, OFFS, BITS) (intToChannel((uint32_t)(VAL), (BITS)) << (OFFS)) |
| |
| switch (m_format.type) |
| { |
| case TextureFormat::UNSIGNED_BYTE_44: // Fall-through |
| case TextureFormat::UNORM_BYTE_44: |
| *((uint8_t *)pixelPtr) = (uint8_t)(PU(color[0], 4, 4) | PU(color[1], 0, 4)); |
| break; |
| case TextureFormat::UNORM_INT_101010: |
| *((uint32_t *)pixelPtr) = PU(color[0], 22, 10) | PU(color[1], 12, 10) | PU(color[2], 2, 10); |
| break; |
| |
| case TextureFormat::UNORM_SHORT_565: |
| case TextureFormat::UNSIGNED_SHORT_565: |
| { |
| const IVec4 swizzled = swizzleGe(color, TextureFormat::RGB, m_format.order); |
| *((uint16_t *)pixelPtr) = (uint16_t)(PU(swizzled[0], 11, 5) | PU(swizzled[1], 5, 6) | PU(swizzled[2], 0, 5)); |
| break; |
| } |
| |
| case TextureFormat::UNORM_SHORT_555: |
| { |
| const IVec4 swizzled = swizzleGe(color, TextureFormat::RGB, m_format.order); |
| *((uint16_t *)pixelPtr) = (uint16_t)(PU(swizzled[0], 10, 5) | PU(swizzled[1], 5, 5) | PU(swizzled[2], 0, 5)); |
| break; |
| } |
| |
| case TextureFormat::UNORM_SHORT_4444: |
| case TextureFormat::UNSIGNED_SHORT_4444: |
| { |
| const IVec4 swizzled = swizzleGe(color, TextureFormat::RGBA, m_format.order); |
| *((uint16_t *)pixelPtr) = |
| (uint16_t)(PU(swizzled[0], 12, 4) | PU(swizzled[1], 8, 4) | PU(swizzled[2], 4, 4) | PU(swizzled[3], 0, 4)); |
| break; |
| } |
| |
| case TextureFormat::UNORM_SHORT_5551: |
| case TextureFormat::UNSIGNED_SHORT_5551: |
| { |
| const IVec4 swizzled = swizzleGe(color, TextureFormat::RGBA, m_format.order); |
| *((uint16_t *)pixelPtr) = |
| (uint16_t)(PU(swizzled[0], 11, 5) | PU(swizzled[1], 6, 5) | PU(swizzled[2], 1, 5) | PU(swizzled[3], 0, 1)); |
| break; |
| } |
| |
| case TextureFormat::UNORM_SHORT_1555: |
| { |
| const IVec4 swizzled = swizzleGe(color, TextureFormat::RGBA, m_format.order); |
| *((uint16_t *)pixelPtr) = |
| (uint16_t)(PU(swizzled[0], 15, 1) | PU(swizzled[1], 10, 5) | PU(swizzled[2], 5, 5) | PU(swizzled[3], 0, 5)); |
| break; |
| } |
| |
| case TextureFormat::UNORM_INT_1010102_REV: |
| case TextureFormat::UNSIGNED_INT_1010102_REV: |
| case TextureFormat::USCALED_INT_1010102_REV: |
| { |
| const IVec4 swizzled = swizzleGe(color, TextureFormat::RGBA, m_format.order); |
| *((uint32_t *)pixelPtr) = |
| PU(swizzled[0], 0, 10) | PU(swizzled[1], 10, 10) | PU(swizzled[2], 20, 10) | PU(swizzled[3], 30, 2); |
| break; |
| } |
| |
| case TextureFormat::SNORM_INT_1010102_REV: |
| case TextureFormat::SIGNED_INT_1010102_REV: |
| case TextureFormat::SSCALED_INT_1010102_REV: |
| { |
| const IVec4 swizzled = swizzleGe(color, TextureFormat::RGBA, m_format.order); |
| *((uint32_t *)pixelPtr) = |
| PI(swizzled[0], 0, 10) | PI(swizzled[1], 10, 10) | PI(swizzled[2], 20, 10) | PI(swizzled[3], 30, 2); |
| break; |
| } |
| |
| default: |
| { |
| // Generic path. |
| int numChannels = getNumUsedChannels(m_format.order); |
| const TextureSwizzle::Channel *map = getChannelWriteSwizzle(m_format.order).components; |
| int channelSize = getChannelSize(m_format.type); |
| |
| for (int c = 0; c < numChannels; c++) |
| { |
| DE_ASSERT(deInRange32(map[c], TextureSwizzle::CHANNEL_0, TextureSwizzle::CHANNEL_3)); |
| intToChannel(pixelPtr + channelSize * c, color[map[c]], m_format.type); |
| } |
| break; |
| } |
| } |
| |
| #undef PU |
| #undef PI |
| } |
| |
| void PixelBufferAccess::setPixDepth(float depth, int x, int y, int z) const |
| { |
| DE_ASSERT(de::inBounds(x, 0, getWidth())); |
| DE_ASSERT(de::inBounds(y, 0, getHeight())); |
| DE_ASSERT(de::inBounds(z, 0, getDepth())); |
| |
| uint8_t *const pixelPtr = (uint8_t *)getPixelPtr(x, y, z); |
| |
| switch (m_format.type) |
| { |
| case TextureFormat::UNSIGNED_INT_16_8_8: |
| DE_ASSERT(m_format.order == TextureFormat::DS); |
| writeUint32High16(pixelPtr, convertSatRte<uint16_t>(depth * 65535.0f)); |
| break; |
| |
| case TextureFormat::UNSIGNED_INT_24_8: |
| DE_ASSERT(m_format.order == TextureFormat::D || m_format.order == TextureFormat::DS); |
| writeUint32High24(pixelPtr, convertSatRteUint24(depth * 16777215.0f)); |
| break; |
| |
| case TextureFormat::UNSIGNED_INT_24_8_REV: |
| DE_ASSERT(m_format.order == TextureFormat::D || m_format.order == TextureFormat::DS); |
| writeUint32Low24(pixelPtr, convertSatRteUint24(depth * 16777215.0f)); |
| break; |
| |
| case TextureFormat::FLOAT_UNSIGNED_INT_24_8_REV: |
| DE_ASSERT(m_format.order == TextureFormat::DS); |
| *((float *)pixelPtr) = depth; |
| break; |
| |
| default: |
| DE_ASSERT(m_format.order == TextureFormat::D); // no other combined depth stencil types |
| floatToChannel(pixelPtr, depth, m_format.type); |
| break; |
| } |
| } |
| |
| void PixelBufferAccess::setPixStencil(int stencil, int x, int y, int z) const |
| { |
| DE_ASSERT(de::inBounds(x, 0, getWidth())); |
| DE_ASSERT(de::inBounds(y, 0, getHeight())); |
| DE_ASSERT(de::inBounds(z, 0, getDepth())); |
| |
| uint8_t *const pixelPtr = (uint8_t *)getPixelPtr(x, y, z); |
| |
| switch (m_format.type) |
| { |
| case TextureFormat::UNSIGNED_INT_16_8_8: |
| case TextureFormat::UNSIGNED_INT_24_8: |
| DE_ASSERT(m_format.order == TextureFormat::DS); |
| writeUint32Low8(pixelPtr, convertSat<uint8_t>((uint32_t)stencil)); |
| break; |
| |
| case TextureFormat::UNSIGNED_INT_24_8_REV: |
| DE_ASSERT(m_format.order == TextureFormat::DS); |
| writeUint32High8(pixelPtr, convertSat<uint8_t>((uint32_t)stencil)); |
| break; |
| |
| case TextureFormat::FLOAT_UNSIGNED_INT_24_8_REV: |
| DE_ASSERT(m_format.order == TextureFormat::DS); |
| writeUint32Low8(pixelPtr + 4, convertSat<uint8_t>((uint32_t)stencil)); |
| break; |
| |
| default: |
| DE_ASSERT(m_format.order == TextureFormat::S); // no other combined depth stencil types |
| intToChannel(pixelPtr, stencil, m_format.type); |
| break; |
| } |
| } |
| |
| static inline int imod(int a, int b) |
| { |
| int m = a % b; |
| return m < 0 ? m + b : m; |
| } |
| |
| static inline int mirror(int a) |
| { |
| return a >= 0 ? a : -(1 + a); |
| } |
| |
| // Nearest-even rounding in case of tie (fractional part 0.5), otherwise ordinary rounding. |
| static inline float rint(float a) |
| { |
| DE_STATIC_ASSERT((-3 % 2 != 0) && (-4 % 2 == 0)); |
| |
| float fracVal = deFloatFrac(a); |
| |
| if (fracVal != 0.5f) |
| return deFloatRound(a); // Ordinary case. |
| |
| float floorVal = a - fracVal; |
| bool roundUp = (int64_t)floorVal % 2 != 0; |
| |
| return floorVal + (roundUp ? 1.0f : 0.0f); |
| } |
| |
| static inline int wrap(Sampler::WrapMode mode, int c, int size) |
| { |
| switch (mode) |
| { |
| case tcu::Sampler::CLAMP_TO_BORDER: |
| return deClamp32(c, -1, size); |
| |
| case tcu::Sampler::CLAMP_TO_EDGE: |
| return deClamp32(c, 0, size - 1); |
| |
| case tcu::Sampler::REPEAT_GL: |
| return imod(c, size); |
| |
| case tcu::Sampler::REPEAT_CL: |
| return imod(c, size); |
| |
| case tcu::Sampler::MIRRORED_ONCE: |
| c = deClamp32(c, -size, size); |
| // Fall-through |
| |
| case tcu::Sampler::MIRRORED_REPEAT_GL: |
| return (size - 1) - mirror(imod(c, 2 * size) - size); |
| |
| case tcu::Sampler::MIRRORED_REPEAT_CL: |
| return deClamp32(c, 0, size - 1); // \note Actual mirroring done already in unnormalization function. |
| |
| default: |
| DE_ASSERT(false); |
| return 0; |
| } |
| } |
| |
| // Special unnormalization for REPEAT_CL and MIRRORED_REPEAT_CL wrap modes; otherwise ordinary unnormalization. |
| static inline float unnormalize(Sampler::WrapMode mode, float c, int size) |
| { |
| switch (mode) |
| { |
| case tcu::Sampler::CLAMP_TO_EDGE: |
| case tcu::Sampler::CLAMP_TO_BORDER: |
| case tcu::Sampler::REPEAT_GL: |
| case tcu::Sampler::MIRRORED_REPEAT_GL: |
| case tcu::Sampler::MIRRORED_ONCE: // Fall-through (ordinary case). |
| return (float)size * c; |
| |
| case tcu::Sampler::REPEAT_CL: |
| return (float)size * (c - deFloatFloor(c)); |
| |
| case tcu::Sampler::MIRRORED_REPEAT_CL: |
| return (float)size * deFloatAbs(c - 2.0f * rint(0.5f * c)); |
| |
| default: |
| DE_ASSERT(false); |
| return 0.0f; |
| } |
| } |
| |
| static bool isFixedPointDepthTextureFormat(const tcu::TextureFormat &format) |
| { |
| DE_ASSERT(format.order == TextureFormat::D || format.order == TextureFormat::R); |
| |
| const tcu::TextureChannelClass channelClass = tcu::getTextureChannelClass(format.type); |
| if (channelClass == tcu::TEXTURECHANNELCLASS_FLOATING_POINT) |
| return false; |
| else if (channelClass == tcu::TEXTURECHANNELCLASS_UNSIGNED_FIXED_POINT) |
| return true; |
| else |
| { |
| DE_ASSERT(false); |
| return false; |
| } |
| } |
| |
| // Texel lookup with color conversion. |
| static inline Vec4 lookup(const ConstPixelBufferAccess &access, int i, int j, int k) |
| { |
| const TextureFormat &format = access.getFormat(); |
| |
| if (isSRGB(format)) |
| { |
| if (format.type == TextureFormat::UNORM_INT8 && format.order == TextureFormat::sRGB) |
| return sRGB8ToLinear(access.getPixelUint(i, j, k)); |
| else if (format.type == TextureFormat::UNORM_INT8 && format.order == TextureFormat::sRGBA) |
| return sRGBA8ToLinear(access.getPixelUint(i, j, k)); |
| else |
| return sRGBToLinear(access.getPixel(i, j, k)); |
| } |
| else |
| { |
| return access.getPixel(i, j, k); |
| } |
| } |
| |
| // Border texel lookup with color conversion. |
| static inline Vec4 lookupBorder(const tcu::TextureFormat &format, const tcu::Sampler &sampler) |
| { |
| // "lookup" for a combined format does not make sense, disallow |
| DE_ASSERT(!isCombinedDepthStencilType(format.type)); |
| |
| const tcu::TextureChannelClass channelClass = tcu::getTextureChannelClass(format.type); |
| const bool isFloat = channelClass == tcu::TEXTURECHANNELCLASS_FLOATING_POINT; |
| const bool isFixed = channelClass == tcu::TEXTURECHANNELCLASS_SIGNED_FIXED_POINT || |
| channelClass == tcu::TEXTURECHANNELCLASS_UNSIGNED_FIXED_POINT; |
| const bool isPureInteger = channelClass == tcu::TEXTURECHANNELCLASS_SIGNED_INTEGER; |
| const bool isPureUnsignedInteger = channelClass == tcu::TEXTURECHANNELCLASS_UNSIGNED_INTEGER; |
| |
| if (isFloat || isFixed) |
| return sampleTextureBorder<float>(format, sampler); |
| else if (isPureInteger) |
| return sampleTextureBorder<int32_t>(format, sampler).cast<float>(); |
| else if (isPureUnsignedInteger) |
| return sampleTextureBorder<uint32_t>(format, sampler).cast<float>(); |
| else |
| { |
| DE_ASSERT(false); |
| return Vec4(-1.0); |
| } |
| } |
| |
| static inline float execCompare(const tcu::Vec4 &color, Sampler::CompareMode compare, int chanNdx, float ref_, |
| bool isFixedPoint) |
| { |
| const bool clampValues = |
| isFixedPoint; // if comparing against a floating point texture, ref (and value) is not clamped |
| const float cmp = (clampValues) ? (de::clamp(color[chanNdx], 0.0f, 1.0f)) : (color[chanNdx]); |
| const float ref = (clampValues) ? (de::clamp(ref_, 0.0f, 1.0f)) : (ref_); |
| bool res = false; |
| |
| switch (compare) |
| { |
| case Sampler::COMPAREMODE_LESS: |
| res = ref < cmp; |
| break; |
| case Sampler::COMPAREMODE_LESS_OR_EQUAL: |
| res = ref <= cmp; |
| break; |
| case Sampler::COMPAREMODE_GREATER: |
| res = ref > cmp; |
| break; |
| case Sampler::COMPAREMODE_GREATER_OR_EQUAL: |
| res = ref >= cmp; |
| break; |
| case Sampler::COMPAREMODE_EQUAL: |
| res = ref == cmp; |
| break; |
| case Sampler::COMPAREMODE_NOT_EQUAL: |
| res = ref != cmp; |
| break; |
| case Sampler::COMPAREMODE_ALWAYS: |
| res = true; |
| break; |
| case Sampler::COMPAREMODE_NEVER: |
| res = false; |
| break; |
| default: |
| DE_ASSERT(false); |
| } |
| |
| return res ? 1.0f : 0.0f; |
| } |
| |
| static Vec4 sampleNearest1D(const ConstPixelBufferAccess &access, const Sampler &sampler, float u, const IVec2 &offset) |
| { |
| int width = access.getWidth(); |
| |
| int x = deFloorFloatToInt32(u) + offset.x(); |
| |
| // Check for CLAMP_TO_BORDER. |
| if (sampler.wrapS == Sampler::CLAMP_TO_BORDER && !deInBounds32(x, 0, width)) |
| return lookupBorder(access.getFormat(), sampler); |
| |
| int i = wrap(sampler.wrapS, x, width); |
| |
| return lookup(access, i, offset.y(), 0); |
| } |
| |
| static Vec4 sampleNearest2D(const ConstPixelBufferAccess &access, const Sampler &sampler, float u, float v, |
| const IVec3 &offset) |
| { |
| int width = access.getWidth(); |
| int height = access.getHeight(); |
| |
| int x = deFloorFloatToInt32(u) + offset.x(); |
| int y = deFloorFloatToInt32(v) + offset.y(); |
| |
| // Check for CLAMP_TO_BORDER. |
| if ((sampler.wrapS == Sampler::CLAMP_TO_BORDER && !deInBounds32(x, 0, width)) || |
| (sampler.wrapT == Sampler::CLAMP_TO_BORDER && !deInBounds32(y, 0, height))) |
| return lookupBorder(access.getFormat(), sampler); |
| |
| int
|