diff --git a/include/bimg/bimg.h b/include/bimg/bimg.h index 8122b9e..620b9a5 100644 --- a/include/bimg/bimg.h +++ b/include/bimg/bimg.h @@ -404,7 +404,8 @@ namespace bimg /// bool imageConvert( - void* _dst + bx::AllocatorI* _allocator + , void* _dst , TextureFormat::Enum _dstFormat , const void* _src , TextureFormat::Enum _srcFormat @@ -575,7 +576,8 @@ namespace bimg /// void imageDecodeToBgra8( - void* _dst + bx::AllocatorI* _allocator + , void* _dst , const void* _src , uint32_t _width , uint32_t _height @@ -585,7 +587,8 @@ namespace bimg /// void imageDecodeToRgba8( - void* _dst + bx::AllocatorI* _allocator + , void* _dst , const void* _src , uint32_t _width , uint32_t _height diff --git a/include/bimg/encode.h b/include/bimg/encode.h index bab8de7..b508745 100644 --- a/include/bimg/encode.h +++ b/include/bimg/encode.h @@ -24,7 +24,8 @@ namespace bimg /// void imageEncodeFromRgba8( - void* _dst + bx::AllocatorI* _allocator + , void* _dst , const void* _src , uint32_t _width , uint32_t _height diff --git a/src/image.cpp b/src/image.cpp index c021de8..38ac966 100644 --- a/src/image.cpp +++ b/src/image.cpp @@ -969,7 +969,7 @@ namespace bimg } } - bool imageConvert(void* _dst, TextureFormat::Enum _dstFormat, const void* _src, TextureFormat::Enum _srcFormat, uint32_t _width, uint32_t _height, uint32_t _depth, uint32_t _srcPitch) + bool imageConvert(bx::AllocatorI* _allocator, void* _dst, TextureFormat::Enum _dstFormat, const void* _src, TextureFormat::Enum _srcFormat, uint32_t _width, uint32_t _height, uint32_t _depth, uint32_t _srcPitch) { UnpackFn unpack = s_packUnpack[_srcFormat].unpack; PackFn pack = s_packUnpack[_dstFormat].pack; @@ -979,18 +979,15 @@ namespace bimg switch (_dstFormat) { case TextureFormat::RGBA8: - imageDecodeToRgba8(_dst, _src, _width, _height, _width*4, _srcFormat); + imageDecodeToRgba8(_allocator, _dst, _src, _width, _height, _width*4, _srcFormat); return true; case TextureFormat::BGRA8: - imageDecodeToBgra8(_dst, _src, _width, _height, _width*4, _srcFormat); + imageDecodeToBgra8(_allocator, _dst, _src, _width, _height, _width*4, _srcFormat); return true; case TextureFormat::RGBA32F: - { - bx::DefaultAllocator allocator; - imageDecodeToRgba32f(&allocator, _dst, _src, _width, _height, 1, _width*16, _srcFormat); - } + imageDecodeToRgba32f(_allocator, _dst, _src, _width, _height, 1, _width*16, _srcFormat); return true; default: @@ -1007,7 +1004,7 @@ namespace bimg return true; } - bool imageConvert(void* _dst, TextureFormat::Enum _dstFormat, const void* _src, TextureFormat::Enum _srcFormat, uint32_t _width, uint32_t _height, uint32_t _depth) + bool imageConvert(bx::AllocatorI* _allocator, void* _dst, TextureFormat::Enum _dstFormat, const void* _src, TextureFormat::Enum _srcFormat, uint32_t _width, uint32_t _height, uint32_t _depth) { const uint32_t srcBpp = s_imageBlockInfo[_srcFormat].bitsPerPixel; @@ -1017,7 +1014,7 @@ namespace bimg return true; } - return imageConvert(_dst, _dstFormat, _src, _srcFormat, _width, _height, _depth, _width*srcBpp/8); + return imageConvert(_allocator, _dst, _dstFormat, _src, _srcFormat, _width, _height, _depth, _width*srcBpp/8); } ImageContainer* imageConvert(bx::AllocatorI* _allocator, TextureFormat::Enum _dstFormat, const ImageContainer& _input) @@ -1045,14 +1042,16 @@ namespace bimg imageGetRawData(*output, side, lod, output->m_data, output->m_size, dstMip); uint8_t* dstData = const_cast(dstMip.m_data); - bool ok = imageConvert(dstData - , _dstFormat - , mip.m_data - , mip.m_format - , mip.m_width - , mip.m_height - , mip.m_depth - ); + bool ok = imageConvert( + _allocator + , dstData + , _dstFormat + , mip.m_data + , mip.m_format + , mip.m_width + , mip.m_height + , mip.m_depth + ); BX_CHECK(ok, "Conversion from %s to %s failed!" , getName(_input.m_format) , getName(output->m_format) @@ -1447,7 +1446,579 @@ namespace bimg { 0, 4, 9, 13, 17, 21, 26, 30, 34, 38, 43, 47, 51, 55, 60, 64 }, }; - struct BptcModeInfo + struct BitReader + { + BitReader(const uint8_t* _data, uint16_t _bitPos = 0) + : m_data(_data) + , m_bitPos(_bitPos) + { + } + + uint16_t read(uint8_t _numBits) + { + const uint16_t pos = m_bitPos / 8; + const uint16_t shift = m_bitPos & 7; + uint32_t data = 0; + bx::memCopy(&data, &m_data[pos], bx::min(4, 16-pos) ); + m_bitPos += _numBits; + return uint16_t( (data >> shift) & ( (1 << _numBits)-1) ); + } + + uint16_t peek(uint16_t _offset, uint8_t _numBits) + { + const uint16_t bitPos = m_bitPos + _offset; + const uint16_t shift = bitPos & 7; + uint16_t pos = bitPos / 8; + uint32_t data = 0; + bx::memCopy(&data, &m_data[pos], bx::min(4, 16-pos) ); + return uint8_t( (data >> shift) & ( (1 << _numBits)-1) ); + } + + const uint8_t* m_data; + uint16_t m_bitPos; + }; + + uint16_t bc6hUnquantize(uint16_t _value, bool _signed, uint8_t _endpointBits) + { + const uint16_t maxValue = 1<<(_endpointBits-1); + + if (_signed) + { + if (_endpointBits >= 16) + { + return _value; + } + + const bool sign = _value & 0x8000; + _value &= 0x7fff; + + uint16_t unq; + + if (0 == _value) + { + unq = 0; + } + else if (_value >= maxValue-1) + { + unq = 0x7fff; + } + else + { + unq = ( (_value<<15) + 0x4000) >> (_endpointBits-1); + } + + return sign ? -unq : unq; + } + + if (_endpointBits >= 15) + { + return _value; + } + + if (0 == _value) + { + return 0; + } + + if (_value == maxValue) + { + return UINT16_MAX; + } + + return ( (_value<<15) + 0x4000) >> (_endpointBits-1); + } + + uint16_t bc6hUnquantizeFinal(uint16_t _value, bool _signed) + { + if (_signed) + { + const uint16_t sign = _value & 0x8000; + _value &= 0x7fff; + + return ( (_value * 31) >> 5) | sign; + } + + return (_value * 31) >> 6; + } + + uint16_t signExtend(uint16_t _value, uint8_t _numBits) + { + const uint16_t mask = 1 << (_numBits - 1); + const uint16_t result = (_value ^ mask) - mask; + + return result; + } + + struct Bc6hModeInfo + { + uint8_t transformed; + uint8_t partitionBits; + uint8_t endpointBits; + uint8_t deltaBits[3]; + }; + + static const Bc6hModeInfo s_bc6hModeInfo[] = + { // +--------------------------- transformed + // | +------------------------ partition bits + // | | +--------------------- endpoint bits + // | | | +-------------- delta bits + { 1, 5, 10, { 5, 5, 5 } }, // 00 2-bits + { 1, 5, 7, { 6, 6, 6 } }, // 01 + { 1, 5, 11, { 5, 4, 4 } }, // 00010 5-bits + { 0, 0, 10, { 10, 10, 10 } }, // 00011 + { 0, 0, 0, { 0, 0, 0 } }, // - + { 0, 0, 0, { 0, 0, 0 } }, // - + { 1, 5, 11, { 4, 5, 4 } }, // 00110 + { 1, 0, 11, { 9, 9, 9 } }, // 00010 + { 0, 0, 0, { 0, 0, 0 } }, // - + { 0, 0, 0, { 0, 0, 0 } }, // - + { 1, 5, 11, { 4, 4, 5 } }, // 00010 + { 1, 0, 12, { 8, 8, 8 } }, // 00010 + { 0, 0, 0, { 0, 0, 0 } }, // - + { 0, 0, 0, { 0, 0, 0 } }, // - + { 1, 5, 9, { 5, 5, 5 } }, // 00010 + { 1, 0, 16, { 4, 4, 4 } }, // 00010 + { 0, 0, 0, { 0, 0, 0 } }, // - + { 0, 0, 0, { 0, 0, 0 } }, // - + { 1, 5, 8, { 6, 5, 5 } }, // 00010 + { 0, 0, 0, { 0, 0, 0 } }, // - + { 0, 0, 0, { 0, 0, 0 } }, // - + { 0, 0, 0, { 0, 0, 0 } }, // - + { 1, 5, 8, { 5, 6, 5 } }, // 00010 + { 0, 0, 0, { 0, 0, 0 } }, // - + { 0, 0, 0, { 0, 0, 0 } }, // - + { 0, 0, 0, { 0, 0, 0 } }, // - + { 1, 5, 8, { 5, 5, 6 } }, // 00010 + { 0, 0, 0, { 0, 0, 0 } }, // - + { 0, 0, 0, { 0, 0, 0 } }, // - + { 0, 0, 0, { 0, 0, 0 } }, // - + { 0, 5, 6, { 6, 6, 6 } }, // 00010 + { 0, 0, 0, { 0, 0, 0 } }, // - + }; + + void decodeBlockBc6h(uint16_t _dst[16*3], const uint8_t _src[16], bool _signed) + { + BitReader bit(_src); + + uint8_t mode = uint8_t(bit.read(2) ); + if (mode & 2) + { + // 5-bit mode + mode |= bit.read(3) << 2; + } + + const Bc6hModeInfo& mi = s_bc6hModeInfo[mode]; + if (0 == mi.endpointBits) + { + bx::memSet(_dst, 0, 16*3*2); + return; + } + + uint16_t epR[4] = { /* rw, rx, ry, rz */ }; + uint16_t epG[4] = { /* gw, gx, gy, gz */ }; + uint16_t epB[4] = { /* bw, bx, by, bz */ }; + + switch (mode) + { + case 0: + epG[2] |= bit.read( 1) << 4; + epB[2] |= bit.read( 1) << 4; + epB[3] |= bit.read( 1) << 4; + epR[0] |= bit.read(10) << 0; + epG[0] |= bit.read(10) << 0; + epB[0] |= bit.read(10) << 0; + epR[1] |= bit.read( 5) << 0; + epG[3] |= bit.read( 1) << 4; + epG[2] |= bit.read( 4) << 0; + epG[1] |= bit.read( 5) << 0; + epB[3] |= bit.read( 1) << 0; + epG[3] |= bit.read( 4) << 0; + epB[1] |= bit.read( 5) << 0; + epB[3] |= bit.read( 1) << 1; + epB[2] |= bit.read( 4) << 0; + epR[2] |= bit.read( 5) << 0; + epB[3] |= bit.read( 1) << 2; + epR[3] |= bit.read( 5) << 0; + epB[3] |= bit.read( 1) << 3; + break; + + case 1: + epG[2] |= bit.read( 1) << 5; + epG[3] |= bit.read( 1) << 4; + epG[3] |= bit.read( 1) << 5; + epR[0] |= bit.read( 7) << 0; + epB[3] |= bit.read( 1) << 0; + epB[3] |= bit.read( 1) << 1; + epB[2] |= bit.read( 1) << 4; + epG[0] |= bit.read( 7) << 0; + epB[2] |= bit.read( 1) << 5; + epB[3] |= bit.read( 1) << 2; + epG[2] |= bit.read( 1) << 4; + epB[0] |= bit.read( 7) << 0; + epB[3] |= bit.read( 1) << 3; + epB[3] |= bit.read( 1) << 5; + epB[3] |= bit.read( 1) << 4; + epR[1] |= bit.read( 6) << 0; + epG[2] |= bit.read( 4) << 0; + epG[1] |= bit.read( 6) << 0; + epG[3] |= bit.read( 4) << 0; + epB[1] |= bit.read( 6) << 0; + epB[2] |= bit.read( 4) << 0; + epR[2] |= bit.read( 6) << 0; + epR[3] |= bit.read( 6) << 0; + break; + + case 2: + epR[0] |= bit.read(10) << 0; + epG[0] |= bit.read(10) << 0; + epB[0] |= bit.read(10) << 0; + epR[1] |= bit.read( 5) << 0; + epR[0] |= bit.read( 1) << 10; + epG[2] |= bit.read( 4) << 0; + epG[1] |= bit.read( 4) << 0; + epG[0] |= bit.read( 1) << 10; + epB[3] |= bit.read( 1) << 0; + epG[3] |= bit.read( 4) << 0; + epB[1] |= bit.read( 4) << 0; + epB[0] |= bit.read( 1) << 10; + epB[3] |= bit.read( 1) << 1; + epB[2] |= bit.read( 4) << 0; + epR[2] |= bit.read( 5) << 0; + epB[3] |= bit.read( 1) << 2; + epR[3] |= bit.read( 5) << 0; + epB[3] |= bit.read( 1) << 3; + break; + + case 3: + epR[0] |= bit.read(10) << 0; + epG[0] |= bit.read(10) << 0; + epB[0] |= bit.read(10) << 0; + epR[1] |= bit.read(10) << 0; + epG[1] |= bit.read(10) << 0; + epB[1] |= bit.read(10) << 0; + break; + + case 6: + epR[0] |= bit.read(10) << 0; + epG[0] |= bit.read(10) << 0; + epB[0] |= bit.read(10) << 0; + epR[1] |= bit.read( 4) << 0; + epR[0] |= bit.read( 1) << 10; + epG[3] |= bit.read( 1) << 4; + epG[2] |= bit.read( 4) << 0; + epG[1] |= bit.read( 5) << 0; + epG[0] |= bit.read( 1) << 10; + epG[3] |= bit.read( 4) << 0; + epB[1] |= bit.read( 4) << 0; + epB[0] |= bit.read( 1) << 10; + epB[3] |= bit.read( 1) << 1; + epB[2] |= bit.read( 4) << 0; + epR[2] |= bit.read( 4) << 0; + epB[3] |= bit.read( 1) << 0; + epB[3] |= bit.read( 1) << 2; + epR[3] |= bit.read( 4) << 0; + epG[2] |= bit.read( 1) << 4; + epB[3] |= bit.read( 1) << 3; + break; + + case 7: + epR[0] |= bit.read(10) << 0; + epG[0] |= bit.read(10) << 0; + epB[0] |= bit.read(10) << 0; + epR[1] |= bit.read( 9) << 0; + epR[0] |= bit.read( 1) << 10; + epG[1] |= bit.read( 9) << 0; + epG[0] |= bit.read( 1) << 10; + epB[1] |= bit.read( 9) << 0; + epB[0] |= bit.read( 1) << 10; + break; + + case 10: + epR[0] |= bit.read(10) << 0; + epG[0] |= bit.read(10) << 0; + epB[0] |= bit.read(10) << 0; + epR[1] |= bit.read( 4) << 0; + epR[0] |= bit.read( 1) << 10; + epB[2] |= bit.read( 1) << 4; + epG[2] |= bit.read( 4) << 0; + epG[1] |= bit.read( 4) << 0; + epG[0] |= bit.read( 1) << 10; + epB[3] |= bit.read( 1) << 0; + epG[3] |= bit.read( 4) << 0; + epB[1] |= bit.read( 5) << 0; + epB[0] |= bit.read( 1) << 10; + epB[2] |= bit.read( 4) << 0; + epR[2] |= bit.read( 4) << 0; + epB[3] |= bit.read( 1) << 1; + epB[3] |= bit.read( 1) << 2; + epR[3] |= bit.read( 4) << 0; + epB[3] |= bit.read( 1) << 4; + epB[3] |= bit.read( 1) << 3; + break; + + case 11: + epR[0] |= bit.read(10) << 0; + epG[0] |= bit.read(10) << 0; + epB[0] |= bit.read(10) << 0; + epR[1] |= bit.read( 8) << 0; + epR[0] |= bit.read( 1) << 11; + epR[0] |= bit.read( 1) << 10; + epG[1] |= bit.read( 8) << 0; + epG[0] |= bit.read( 1) << 11; + epG[0] |= bit.read( 1) << 10; + epB[1] |= bit.read( 8) << 0; + epB[0] |= bit.read( 1) << 11; + epB[0] |= bit.read( 1) << 10; + break; + + case 14: + epR[0] |= bit.read( 9) << 0; + epB[2] |= bit.read( 1) << 4; + epG[0] |= bit.read( 9) << 0; + epG[2] |= bit.read( 1) << 4; + epB[0] |= bit.read( 9) << 0; + epB[3] |= bit.read( 1) << 4; + epR[1] |= bit.read( 5) << 0; + epG[3] |= bit.read( 1) << 4; + epG[2] |= bit.read( 4) << 0; + epG[1] |= bit.read( 5) << 0; + epB[3] |= bit.read( 1) << 0; + epG[3] |= bit.read( 4) << 0; + epB[1] |= bit.read( 5) << 0; + epB[3] |= bit.read( 1) << 1; + epB[2] |= bit.read( 4) << 0; + epR[2] |= bit.read( 5) << 0; + epB[3] |= bit.read( 1) << 2; + epR[3] |= bit.read( 5) << 0; + epB[3] |= bit.read( 1) << 3; + break; + + case 15: + epR[0] |= bit.read(10) << 0; + epG[0] |= bit.read(10) << 0; + epB[0] |= bit.read(10) << 0; + epR[1] |= bit.read( 4) << 0; + epR[0] |= bit.read( 1) << 15; + epR[0] |= bit.read( 1) << 14; + epR[0] |= bit.read( 1) << 13; + epR[0] |= bit.read( 1) << 12; + epR[0] |= bit.read( 1) << 11; + epR[0] |= bit.read( 1) << 10; + epG[1] |= bit.read( 4) << 0; + epG[0] |= bit.read( 1) << 15; + epG[0] |= bit.read( 1) << 14; + epG[0] |= bit.read( 1) << 13; + epG[0] |= bit.read( 1) << 12; + epG[0] |= bit.read( 1) << 11; + epG[0] |= bit.read( 1) << 10; + epB[1] |= bit.read( 4) << 0; + epB[0] |= bit.read( 1) << 15; + epB[0] |= bit.read( 1) << 14; + epB[0] |= bit.read( 1) << 13; + epB[0] |= bit.read( 1) << 12; + epB[0] |= bit.read( 1) << 11; + epB[0] |= bit.read( 1) << 10; + break; + + case 18: + epR[0] |= bit.read( 8) << 0; + epG[3] |= bit.read( 1) << 4; + epB[2] |= bit.read( 1) << 4; + epG[0] |= bit.read( 8) << 0; + epB[3] |= bit.read( 1) << 2; + epG[2] |= bit.read( 1) << 4; + epB[0] |= bit.read( 8) << 0; + epB[3] |= bit.read( 1) << 3; + epB[3] |= bit.read( 1) << 4; + epR[1] |= bit.read( 6) << 0; + epG[2] |= bit.read( 4) << 0; + epG[1] |= bit.read( 5) << 0; + epB[3] |= bit.read( 1) << 0; + epG[3] |= bit.read( 4) << 0; + epB[1] |= bit.read( 5) << 0; + epB[3] |= bit.read( 1) << 1; + epB[2] |= bit.read( 4) << 0; + epR[2] |= bit.read( 6) << 0; + epR[3] |= bit.read( 6) << 0; + break; + + case 22: + epR[0] |= bit.read( 8) << 0; + epB[3] |= bit.read( 1) << 0; + epB[2] |= bit.read( 1) << 4; + epG[0] |= bit.read( 8) << 0; + epG[2] |= bit.read( 1) << 5; + epG[2] |= bit.read( 1) << 4; + epB[0] |= bit.read( 8) << 0; + epG[3] |= bit.read( 1) << 5; + epB[3] |= bit.read( 1) << 4; + epR[1] |= bit.read( 5) << 0; + epG[3] |= bit.read( 1) << 4; + epG[2] |= bit.read( 4) << 0; + epG[1] |= bit.read( 6) << 0; + epG[3] |= bit.read( 4) << 0; + epB[1] |= bit.read( 5) << 0; + epB[3] |= bit.read( 1) << 1; + epB[2] |= bit.read( 4) << 0; + epR[2] |= bit.read( 5) << 0; + epB[3] |= bit.read( 1) << 2; + epR[3] |= bit.read( 5) << 0; + epB[3] |= bit.read( 1) << 3; + break; + + case 26: + epR[0] |= bit.read( 8) << 0; + epB[3] |= bit.read( 1) << 1; + epB[2] |= bit.read( 1) << 4; + epG[0] |= bit.read( 8) << 0; + epB[2] |= bit.read( 1) << 5; + epG[2] |= bit.read( 1) << 4; + epB[0] |= bit.read( 8) << 0; + epB[3] |= bit.read( 1) << 5; + epB[3] |= bit.read( 1) << 4; + epR[1] |= bit.read( 5) << 0; + epG[3] |= bit.read( 1) << 4; + epG[2] |= bit.read( 4) << 0; + epG[1] |= bit.read( 5) << 0; + epB[3] |= bit.read( 1) << 0; + epG[3] |= bit.read( 4) << 0; + epB[1] |= bit.read( 6) << 0; + epB[2] |= bit.read( 4) << 0; + epR[2] |= bit.read( 5) << 0; + epB[3] |= bit.read( 1) << 2; + epR[3] |= bit.read( 5) << 0; + epB[3] |= bit.read( 1) << 3; + break; + + case 30: + epR[0] |= bit.read( 6) << 0; + epG[3] |= bit.read( 1) << 4; + epB[3] |= bit.read( 1) << 0; + epB[3] |= bit.read( 1) << 1; + epB[2] |= bit.read( 1) << 4; + epG[0] |= bit.read( 6) << 0; + epG[2] |= bit.read( 1) << 5; + epB[2] |= bit.read( 1) << 5; + epB[3] |= bit.read( 1) << 2; + epG[2] |= bit.read( 1) << 4; + epB[0] |= bit.read( 6) << 0; + epG[3] |= bit.read( 1) << 5; + epB[3] |= bit.read( 1) << 3; + epB[3] |= bit.read( 1) << 5; + epB[3] |= bit.read( 1) << 4; + epR[1] |= bit.read( 6) << 0; + epG[2] |= bit.read( 4) << 0; + epG[1] |= bit.read( 6) << 0; + epG[3] |= bit.read( 4) << 0; + epB[1] |= bit.read( 6) << 0; + epB[2] |= bit.read( 4) << 0; + epR[2] |= bit.read( 6) << 0; + epR[3] |= bit.read( 6) << 0; + break; + + default: + break; + } + + if (_signed) + { + epR[0] = signExtend(epR[0], mi.endpointBits); + epG[0] = signExtend(epG[0], mi.endpointBits); + epB[0] = signExtend(epB[0], mi.endpointBits); + } + + const uint8_t numSubsets = !!mi.partitionBits + 1; + + for (uint8_t ii = 1, num = numSubsets*2; ii < num; ++ii) + { + if (_signed + || mi.transformed) + { + epR[ii] = signExtend(epR[ii], mi.deltaBits[0]); + epG[ii] = signExtend(epG[ii], mi.deltaBits[1]); + epB[ii] = signExtend(epB[ii], mi.deltaBits[2]); + } + + if (mi.transformed) + { + const uint16_t mask = (1<> idx) & 1; + indexAnchor = subsetIndex ? s_bptcA2[partitionSetIdx] : 0; + } + + const uint8_t anchor = idx == indexAnchor; + const uint8_t num = indexBits - anchor; + const uint8_t index = (uint8_t)bit.read(num); + + const uint8_t fc = factors[index]; + const uint8_t fca = 64 - fc; + const uint8_t fcb = fc; + + subsetIndex *= 2; + uint16_t rr = bc6hUnquantizeFinal( (epR[subsetIndex]*fca + epR[subsetIndex + 1]*fcb + 32) >> 6, _signed); + uint16_t gg = bc6hUnquantizeFinal( (epG[subsetIndex]*fca + epG[subsetIndex + 1]*fcb + 32) >> 6, _signed); + uint16_t bb = bc6hUnquantizeFinal( (epB[subsetIndex]*fca + epB[subsetIndex + 1]*fcb + 32) >> 6, _signed); + + uint16_t* rgba = &_dst[idx*3]; + rgba[0] = rr; + rgba[1] = gg; + rgba[2] = bb; + } + } + } + + void decodeBlockBc6h(float _dst[16*4], const uint8_t _src[16]) + { + uint16_t tmp[16*3]; + + decodeBlockBc6h(tmp, _src, true); + + for (uint32_t ii = 0; ii < 16; ++ii) + { + _dst[ii*4+0] = bx::halfToFloat(tmp[ii*3+0]); + _dst[ii*4+1] = bx::halfToFloat(tmp[ii*3+1]); + _dst[ii*4+2] = bx::halfToFloat(tmp[ii*3+2]); + _dst[ii*4+3] = 1.0f; + } + } + + struct Bc7ModeInfo { uint8_t numSubsets; uint8_t partitionBits; @@ -1460,7 +2031,7 @@ namespace bimg uint8_t indexBits[2]; }; - static const BptcModeInfo s_bptcModeInfo[] = + static const Bc7ModeInfo s_bp7ModeInfo[] = { // +---------------------------- num subsets // | +------------------------- partition bits // | | +---------------------- rotation bits @@ -1480,47 +2051,6 @@ namespace bimg { 2, 6, 0, 0, 5, 5, 1, 0, { 2, 0 } }, // 7 }; - struct BitReader - { - BitReader(const uint8_t* _data, uint16_t _bitPos = 0) - : m_data(_data) - , m_bitPos(_bitPos) - { - } - - uint8_t read(uint8_t _numBits) - { - const uint16_t pos = m_bitPos / 8; - const uint16_t shift = m_bitPos & 7; - const uint16_t data = 15 > pos - ? *( (uint16_t*)&m_data[pos]) - : uint16_t(m_data[pos]) - ; - m_bitPos += _numBits; - return uint8_t( (data >> shift) & ( (1 << _numBits)-1) ); - } - - uint8_t peek(uint16_t _offset, uint8_t _numBits) - { - const uint16_t bitPos = m_bitPos + _offset; - const uint16_t pos = bitPos / 8; - const uint16_t shift = bitPos & 7; - const uint16_t data = 15 > pos - ? *( (uint16_t*)&m_data[pos]) - : uint16_t(m_data[pos]) - ; - return uint8_t( (data >> shift) & ( (1 << _numBits)-1) ); - } - - const uint8_t* m_data; - uint16_t m_bitPos; - }; - - void decodeBlockBc6(float _dst[16*4], const uint8_t _src[16]) - { - BX_UNUSED(_dst, _src); - } - void decodeBlockBc7(uint8_t _dst[16*4], const uint8_t _src[16]) { BitReader bit(_src); @@ -1536,15 +2066,15 @@ namespace bimg return; } - const BptcModeInfo& mi = s_bptcModeInfo[mode]; + const Bc7ModeInfo& mi = s_bp7ModeInfo[mode]; const uint8_t modePBits = 0 != mi.endpointPBits ? mi.endpointPBits : mi.sharedPBits ; - const uint8_t partitionSetIdx = bit.read(mi.partitionBits); - const uint8_t rotationMode = bit.read(mi.rotationBits); - const uint8_t indexSelectionMode = bit.read(mi.indexSelectionBits); + const uint8_t partitionSetIdx = uint8_t(bit.read(mi.partitionBits) ); + const uint8_t rotationMode = uint8_t(bit.read(mi.rotationBits) ); + const uint8_t indexSelectionMode = uint8_t(bit.read(mi.indexSelectionBits) ); uint8_t epR[6]; uint8_t epG[6]; @@ -1553,28 +2083,28 @@ namespace bimg for (uint8_t ii = 0; ii < mi.numSubsets; ++ii) { - epR[ii*2+0] = bit.read(mi.colorBits) << modePBits; - epR[ii*2+1] = bit.read(mi.colorBits) << modePBits; + epR[ii*2+0] = uint8_t(bit.read(mi.colorBits) << modePBits); + epR[ii*2+1] = uint8_t(bit.read(mi.colorBits) << modePBits); } for (uint8_t ii = 0; ii < mi.numSubsets; ++ii) { - epG[ii*2+0] = bit.read(mi.colorBits) << modePBits; - epG[ii*2+1] = bit.read(mi.colorBits) << modePBits; + epG[ii*2+0] = uint8_t(bit.read(mi.colorBits) << modePBits); + epG[ii*2+1] = uint8_t(bit.read(mi.colorBits) << modePBits); } for (uint8_t ii = 0; ii < mi.numSubsets; ++ii) { - epB[ii*2+0] = bit.read(mi.colorBits) << modePBits; - epB[ii*2+1] = bit.read(mi.colorBits) << modePBits; + epB[ii*2+0] = uint8_t(bit.read(mi.colorBits) << modePBits); + epB[ii*2+1] = uint8_t(bit.read(mi.colorBits) << modePBits); } if (mi.alphaBits) { for (uint8_t ii = 0; ii < mi.numSubsets; ++ii) { - epA[ii*2+0] = bit.read(mi.alphaBits) << modePBits; - epA[ii*2+1] = bit.read(mi.alphaBits) << modePBits; + epA[ii*2+0] = uint8_t(bit.read(mi.alphaBits) << modePBits); + epA[ii*2+1] = uint8_t(bit.read(mi.alphaBits) << modePBits); } } else @@ -1586,8 +2116,8 @@ namespace bimg { for (uint8_t ii = 0; ii < mi.numSubsets; ++ii) { - const uint8_t pda = bit.read(modePBits); - const uint8_t pdb = 0 == mi.sharedPBits ? bit.read(modePBits) : pda; + const uint8_t pda = uint8_t( bit.read(modePBits) ); + const uint8_t pdb = uint8_t(0 == mi.sharedPBits ? bit.read(modePBits) : pda); epR[ii*2+0] |= pda; epR[ii*2+1] |= pdb; @@ -1670,8 +2200,8 @@ namespace bimg const uint8_t index[2] = { - bit.peek(offset[0], num[0]), - hasIndexBits1 ? bit.peek(offset[1], num[1]) : index[0], + (uint8_t)bit.peek(offset[0], num[0]), + hasIndexBits1 ? (uint8_t)bit.peek(offset[1], num[1]) : index[0], }; offset[0] += num[0]; @@ -3379,18 +3909,18 @@ namespace bimg { uint32_t size = imageGetSize(NULL, uint16_t(_width), uint16_t(_height), 0, false, false, 1, TextureFormat::RGBA8); void* temp = BX_ALLOC(_allocator, size); - imageDecodeToRgba8(temp, _src, _width, _height, _width*4, _srcFormat); - imageConvert(dst, TextureFormat::R8, temp, TextureFormat::RGBA8, _width, _height, 1, _width*4); + imageDecodeToRgba8(_allocator, temp, _src, _width, _height, _width*4, _srcFormat); + imageConvert(_allocator, dst, TextureFormat::R8, temp, TextureFormat::RGBA8, _width, _height, 1, _width*4); BX_FREE(_allocator, temp); } else { - imageConvert(dst, TextureFormat::R8, src, _srcFormat, _width, _height, 1, srcPitch); + imageConvert(_allocator, dst, TextureFormat::R8, src, _srcFormat, _width, _height, 1, srcPitch); } } } - void imageDecodeToBgra8(void* _dst, const void* _src, uint32_t _width, uint32_t _height, uint32_t _dstPitch, TextureFormat::Enum _srcFormat) + void imageDecodeToBgra8(bx::AllocatorI* _allocator, void* _dst, const void* _src, uint32_t _width, uint32_t _height, uint32_t _dstPitch, TextureFormat::Enum _srcFormat) { const uint8_t* src = (const uint8_t*)_src; uint8_t* dst = (uint8_t*)_dst; @@ -3618,7 +4148,7 @@ namespace bimg { const uint32_t srcBpp = s_imageBlockInfo[_srcFormat].bitsPerPixel; const uint32_t srcPitch = _width * srcBpp / 8; - if (!imageConvert(_dst, TextureFormat::BGRA8, _src, _srcFormat, _width, _height, 1, srcPitch) ) + if (!imageConvert(_allocator, _dst, TextureFormat::BGRA8, _src, _srcFormat, _width, _height, 1, srcPitch) ) { // Failed to convert, just make ugly red-yellow checkerboard texture. imageCheckerboard(_dst, _width, _height, 16, UINT32_C(0xffff0000), UINT32_C(0xffffff00) ); @@ -3628,7 +4158,7 @@ namespace bimg } } - void imageDecodeToRgba8(void* _dst, const void* _src, uint32_t _width, uint32_t _height, uint32_t _dstPitch, TextureFormat::Enum _srcFormat) + void imageDecodeToRgba8(bx::AllocatorI* _allocator, void* _dst, const void* _src, uint32_t _width, uint32_t _height, uint32_t _dstPitch, TextureFormat::Enum _srcFormat) { switch (_srcFormat) { @@ -3650,7 +4180,7 @@ namespace bimg default: { const uint32_t srcPitch = _width * 4; - imageDecodeToBgra8(_dst, _src, _width, _height, _dstPitch, _srcFormat); + imageDecodeToBgra8(_allocator, _dst, _src, _width, _height, _dstPitch, _srcFormat); imageSwizzleBgra8(_dst, _dstPitch, _width, _height, _dst, srcPitch); } break; @@ -3781,7 +4311,7 @@ namespace bimg for (uint32_t xx = 0; xx < width; ++xx) { float tmp[16*4]; - decodeBlockBc6(tmp, srcData); + decodeBlockBc6h(tmp, srcData); srcData += 16; uint8_t* block = (uint8_t*)&dst[yy*_dstPitch*4 + xx*64]; @@ -3803,13 +4333,13 @@ namespace bimg { uint32_t size = imageGetSize(NULL, uint16_t(_width), uint16_t(_height), 0, false, false, 1, TextureFormat::RGBA8); void* temp = BX_ALLOC(_allocator, size); - imageDecodeToRgba8(temp, src, _width, _height, _width*4, _srcFormat); + imageDecodeToRgba8(_allocator, temp, src, _width, _height, _width*4, _srcFormat); imageRgba8ToRgba32f(dst, _width, _height, _width*4, temp); BX_FREE(_allocator, temp); } else { - imageConvert(dst, TextureFormat::RGBA32F, src, _srcFormat, _width, _height, 1, srcPitch); + imageConvert(_allocator, dst, TextureFormat::RGBA32F, src, _srcFormat, _width, _height, 1, srcPitch); } break; } diff --git a/src/image_encode.cpp b/src/image_encode.cpp index f7abf4c..3e29ef1 100644 --- a/src/image_encode.cpp +++ b/src/image_encode.cpp @@ -35,7 +35,7 @@ namespace bimg }; BX_STATIC_ASSERT(Quality::Count == BX_COUNTOF(s_squishQuality) ); - void imageEncodeFromRgba8(void* _dst, const void* _src, uint32_t _width, uint32_t _height, uint32_t _depth, TextureFormat::Enum _format, Quality::Enum _quality, bx::Error* _err) + void imageEncodeFromRgba8(bx::AllocatorI* _allocator, void* _dst, const void* _src, uint32_t _width, uint32_t _height, uint32_t _depth, TextureFormat::Enum _format, Quality::Enum _quality, bx::Error* _err) { const uint8_t* src = (const uint8_t*)_src; uint8_t* dst = (uint8_t*)_dst; @@ -131,7 +131,7 @@ namespace bimg break; default: - if (!imageConvert(dst, _format, src, TextureFormat::RGBA8, _width, _height, 1) ) + if (!imageConvert(_allocator, dst, _format, src, TextureFormat::RGBA8, _width, _height, 1) ) { BX_ERROR_SET(_err, BIMG_ERROR, "Unable to convert between input/output formats!"); } @@ -157,10 +157,10 @@ namespace bimg break; default: - if (!imageConvert(_dst, _dstFormat, _src, TextureFormat::RGBA32F, _width, _height, _depth) ) + if (!imageConvert(_allocator, _dst, _dstFormat, _src, TextureFormat::RGBA32F, _width, _height, _depth) ) { uint8_t* temp = (uint8_t*)BX_ALLOC(_allocator, _width*_height*_depth*4); - if (imageConvert(temp, TextureFormat::RGBA8, _src, TextureFormat::RGBA32F, _width, _height, _depth) ) + if (imageConvert(_allocator, temp, TextureFormat::RGBA8, _src, TextureFormat::RGBA32F, _width, _height, _depth) ) { for (uint32_t zz = 0; zz < _depth; ++zz) { @@ -183,7 +183,7 @@ namespace bimg } } - imageEncodeFromRgba8(_dst, temp, _width, _height, _depth, _dstFormat, _quality, _err); + imageEncodeFromRgba8(_allocator, _dst, temp, _width, _height, _depth, _dstFormat, _quality, _err); } else { @@ -211,8 +211,8 @@ namespace bimg case bimg::TextureFormat::PTC14A: { uint8_t* temp = (uint8_t*)BX_ALLOC(_allocator, _width*_height*_depth*4); - imageDecodeToRgba8(temp, _src, _width, _height, _width*4, _srcFormat); - imageEncodeFromRgba8(_dst, temp, _width, _height, _depth, _dstFormat, _quality, _err); + imageDecodeToRgba8(_allocator, temp, _src, _width, _height, _width*4, _srcFormat); + imageEncodeFromRgba8(_allocator, _dst, temp, _width, _height, _depth, _dstFormat, _quality, _err); BX_FREE(_allocator, temp); } break; diff --git a/tools/texturec/texturec.cpp b/tools/texturec/texturec.cpp index 972891c..18968ce 100644 --- a/tools/texturec/texturec.cpp +++ b/tools/texturec/texturec.cpp @@ -559,7 +559,9 @@ bimg::ImageContainer* convert(bx::AllocatorI* _allocator, const void* _inputData temp = BX_ALLOC(_allocator, size); uint8_t* rgba = (uint8_t*)temp; - bimg::imageDecodeToRgba8(rgba + bimg::imageDecodeToRgba8( + _allocator + , rgba , mip.m_data , mip.m_width , mip.m_height @@ -600,7 +602,9 @@ bimg::ImageContainer* convert(bx::AllocatorI* _allocator, const void* _inputData bimg::imageGetRawData(*output, side, 0, output->m_data, output->m_size, dstMip); dstData = const_cast(dstMip.m_data); - bimg::imageEncodeFromRgba8(dstData + bimg::imageEncodeFromRgba8( + _allocator + , dstData , rgba , dstMip.m_width , dstMip.m_height @@ -647,7 +651,9 @@ bimg::ImageContainer* convert(bx::AllocatorI* _allocator, const void* _inputData bimg::imageGetRawData(*output, side, lod, output->m_data, output->m_size, dstMip); dstData = const_cast(dstMip.m_data); - bimg::imageEncodeFromRgba8(dstData + bimg::imageEncodeFromRgba8( + _allocator + , dstData , rgba , dstMip.m_width , dstMip.m_height @@ -660,7 +666,9 @@ bimg::ImageContainer* convert(bx::AllocatorI* _allocator, const void* _inputData if (NULL != ref) { - bimg::imageDecodeToRgba8(rgba + bimg::imageDecodeToRgba8( + _allocator + , rgba , output->m_data , mip.m_width , mip.m_height