From 6ef7724d4065bccaa6505822b2cc6b5a863c6d47 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Branimir=20Karad=C5=BEi=C4=87?= Date: Tue, 23 Feb 2016 18:50:33 -0800 Subject: [PATCH] D3D9: Fixed 16-bit texture formats. --- src/image.cpp | 97 +++++++++++++++++----- src/image.h | 189 ++++++++++++++++++++++++++++++++++++++++++ src/renderer_d3d9.cpp | 30 ++++++- 3 files changed, 294 insertions(+), 22 deletions(-) diff --git a/src/image.cpp b/src/image.cpp index a9da90ea..6e167551 100644 --- a/src/image.cpp +++ b/src/image.cpp @@ -1252,6 +1252,26 @@ namespace bgfx _dst[3] = float( ( (packed>>12) & 0xf) ) / 15.0f; } + // RGBA4 + void packBgra4(void* _dst, const float* _src) + { + *( (uint16_t*)_dst) = 0 + | uint16_t(toUnorm(_src[0], 15.0f)<< 8) + | uint16_t(toUnorm(_src[1], 15.0f)<< 4) + | uint16_t(toUnorm(_src[2], 15.0f) ) + | uint16_t(toUnorm(_src[3], 15.0f)<<12) + ; + } + + void unpackBgra4(float* _dst, const void* _src) + { + uint16_t packed = *( (const uint16_t*)_src); + _dst[0] = float( ( (packed>> 8) & 0xf) ) / 15.0f; + _dst[1] = float( ( (packed>> 4) & 0xf) ) / 15.0f; + _dst[2] = float( ( (packed ) & 0xf) ) / 15.0f; + _dst[3] = float( ( (packed>>12) & 0xf) ) / 15.0f; + } + // RGB5A1 void packRgb5a1(void* _dst, const float* _src) { @@ -1272,6 +1292,26 @@ namespace bgfx _dst[3] = float( ( (packed>>14) & 0x1) ); } + // BGR5A1 + void packBgr5a1(void* _dst, const float* _src) + { + *( (uint16_t*)_dst) = 0 + | uint16_t(toUnorm(_src[0], 31.0f)<<10) + | uint16_t(toUnorm(_src[1], 31.0f)<< 5) + | uint16_t(toUnorm(_src[2], 31.0f) ) + | uint16_t(toUnorm(_src[3], 1.0f)<<15) + ; + } + + void unpackBgr5a1(float* _dst, const void* _src) + { + uint16_t packed = *( (const uint16_t*)_src); + _dst[0] = float( ( (packed>>10) & 0x1f) ) / 31.0f; + _dst[1] = float( ( (packed>> 5) & 0x1f) ) / 31.0f; + _dst[2] = float( ( (packed ) & 0x1f) ) / 31.0f; + _dst[3] = float( ( (packed>>14) & 0x1) ); + } + // RGB10A2 void packRgb10A2(void* _dst, const float* _src) { @@ -1310,9 +1350,6 @@ namespace bgfx _dst[2] = bx::halfToFloat( (packed>>17) & 0x7fe0); } - typedef void (*PackFn)(void*, const float*); - typedef void (*UnpackFn)(float*, const void*); - struct PackUnpack { PackFn pack; @@ -1405,6 +1442,40 @@ namespace bgfx ; } + void imageConvert(void* _dst, uint32_t _bpp, PackFn _pack, const void* _src, UnpackFn _unpack, uint32_t _size) + { + const uint8_t* src = (uint8_t*)_src; + uint8_t* dst = (uint8_t*)_dst; + + const uint32_t size = _size * 8 / _bpp; + + for (uint32_t ii = 0; ii < size; ++ii) + { + float rgba[4]; + _unpack(rgba, &src[ii*_bpp/8]); + _pack(&dst[ii*_bpp/8], rgba); + } + } + + void imageConvert(void* _dst, uint32_t _dstBpp, PackFn _pack, const void* _src, uint32_t _srcBpp, UnpackFn _unpack, uint32_t _width, uint32_t _height) + { + const uint8_t* src = (uint8_t*)_src; + uint8_t* dst = (uint8_t*)_dst; + + const uint32_t srcPitch = _width * _srcBpp / 8; + const uint32_t dstPitch = _width * _dstBpp / 8; + + for (uint32_t yy = 0; yy < _height; ++yy, src += srcPitch, dst += dstPitch) + { + for (uint32_t xx = 0; xx < _width; ++xx) + { + float rgba[4]; + _unpack(rgba, &src[xx*_srcBpp/8]); + _pack(&dst[xx*_dstBpp/8], rgba); + } + } + } + bool imageConvert(void* _dst, TextureFormat::Enum _dstFormat, const void* _src, TextureFormat::Enum _srcFormat, uint32_t _width, uint32_t _height) { UnpackFn unpack = s_packUnpack[_srcFormat].unpack; @@ -1415,23 +1486,9 @@ namespace bgfx return false; } - const uint8_t* src = (uint8_t*)_src; - uint8_t* dst = (uint8_t*)_dst; - - const uint32_t srcBpp = s_imageBlockInfo[_srcFormat].bitsPerPixel; - const uint32_t dstBpp = s_imageBlockInfo[_dstFormat].bitsPerPixel; - const uint32_t srcPitch = _width * srcBpp / 8; - const uint32_t dstPitch = _width * dstBpp / 8; - - for (uint32_t yy = 0; yy < _height; ++yy, src += srcPitch, dst += dstPitch) - { - for (uint32_t xx = 0; xx < _width; ++xx) - { - float rgba[4]; - unpack(rgba, &src[xx*srcBpp/8]); - pack(&dst[xx*dstBpp/8], rgba); - } - } + const uint32_t srcBpp = s_imageBlockInfo[_srcFormat].bitsPerPixel; + const uint32_t dstBpp = s_imageBlockInfo[_dstFormat].bitsPerPixel; + imageConvert(_dst, dstBpp, pack, _src, srcBpp, unpack, _width, _height); return true; } diff --git a/src/image.h b/src/image.h index 1df4d63a..bb2dde8e 100644 --- a/src/image.h +++ b/src/image.h @@ -66,6 +66,189 @@ namespace bgfx uint8_t encoding; }; + typedef void (*PackFn)(void*, const float*); + typedef void (*UnpackFn)(float*, const void*); + + // R8 + void packR8(void* _dst, const float* _src); + void unpackR8(float* _dst, const void* _src); + + // R8S + void packR8S(void* _dst, const float* _src); + void unpackR8S(float* _dst, const void* _src); + + // R8I + void packR8I(void* _dst, const float* _src); + void unpackR8I(float* _dst, const void* _src); + + // R8U + void packR8U(void* _dst, const float* _src); + void unpackR8U(float* _dst, const void* _src); + + // RG8 + void packRg8(void* _dst, const float* _src); + void unpackRg8(float* _dst, const void* _src); + + // RG8S + void packRg8S(void* _dst, const float* _src); + void unpackRg8S(float* _dst, const void* _src); + + // RG8I + void packRg8I(void* _dst, const float* _src); + void unpackRg8I(float* _dst, const void* _src); + + // RG8U + void packRg8U(void* _dst, const float* _src); + void unpackRg8U(float* _dst, const void* _src); + + // RGBA8 + void packRgba8(void* _dst, const float* _src); + void unpackRgba8(float* _dst, const void* _src); + + // BGRA8 + void packBgra8(void* _dst, const float* _src); + void unpackBgra8(float* _dst, const void* _src); + + // RGBA8S + void packRgba8S(void* _dst, const float* _src); + void unpackRgba8S(float* _dst, const void* _src); + + // RGBA8I + void packRgba8I(void* _dst, const float* _src); + void unpackRgba8I(float* _dst, const void* _src); + + // RGBA8U + void packRgba8U(void* _dst, const float* _src); + void unpackRgba8U(float* _dst, const void* _src); + + // R16 + void packR16(void* _dst, const float* _src); + void unpackR16(float* _dst, const void* _src); + + // R16S + void packR16S(void* _dst, const float* _src); + void unpackR16S(float* _dst, const void* _src); + + // R16I + void packR16I(void* _dst, const float* _src); + void unpackR16I(float* _dst, const void* _src); + + // R16U + void packR16U(void* _dst, const float* _src); + void unpackR16U(float* _dst, const void* _src); + + // R16F + void packR16F(void* _dst, const float* _src); + void unpackR16F(float* _dst, const void* _src); + + // RG16 + void packRg16(void* _dst, const float* _src); + void unpackRg16(float* _dst, const void* _src); + + // RG16S + void packRg16S(void* _dst, const float* _src); + void unpackRg16S(float* _dst, const void* _src); + + // RG16I + void packRg16I(void* _dst, const float* _src); + void unpackRg16I(float* _dst, const void* _src); + + // RG16U + void packRg16U(void* _dst, const float* _src); + void unpackRg16U(float* _dst, const void* _src); + + // RG16F + void packRg16F(void* _dst, const float* _src); + void unpackRg16F(float* _dst, const void* _src); + + // RGBA16 + void packRgba16(void* _dst, const float* _src); + void unpackRgba16(float* _dst, const void* _src); + + // RGBA16S + void packRgba16S(void* _dst, const float* _src); + void unpackRgba16S(float* _dst, const void* _src); + + // RGBA16I + void packRgba16I(void* _dst, const float* _src); + void unpackRgba16I(float* _dst, const void* _src); + + // RGBA16U + void packRgba16U(void* _dst, const float* _src); + void unpackRgba16U(float* _dst, const void* _src); + + // RGBA16F + void packRgba16F(void* _dst, const float* _src); + void unpackRgba16F(float* _dst, const void* _src); + + // R32I + void packR32I(void* _dst, const float* _src); + void unpackR32I(float* _dst, const void* _src); + + // R32U + void packR32U(void* _dst, const float* _src); + void unpackR32U(float* _dst, const void* _src); + + // R32F + void packR32F(void* _dst, const float* _src); + void unpackR32F(float* _dst, const void* _src); + + // RG32I + void packRg32I(void* _dst, const float* _src); + void unpackRg32I(float* _dst, const void* _src); + + // RG32U + void packRg32U(void* _dst, const float* _src); + void unpackRg32U(float* _dst, const void* _src); + + // RGB9E5F + void packRgb9E5F(void* _dst, const float* _src); + void unpackRgb9E5F(float* _dst, const void* _src); + + // RGBA32I + void packRgba32I(void* _dst, const float* _src); + void unpackRgba32I(float* _dst, const void* _src); + + // RGBA32U + void packRgba32U(void* _dst, const float* _src); + void unpackRgba32U(float* _dst, const void* _src); + + // RGBA32F + void packRgba32F(void* _dst, const float* _src); + void unpackRgba32F(float* _dst, const void* _src); + + // R5G6B5 + void packR5G6B5(void* _dst, const float* _src); + void unpackR5G6B5(float* _dst, const void* _src); + + // RGBA4 + void packRgba4(void* _dst, const float* _src); + void unpackRgba4(float* _dst, const void* _src); + + // RGBA4 + void packBgra4(void* _dst, const float* _src); + void unpackBgra4(float* _dst, const void* _src); + + // RGB5A1 + void packRgb5a1(void* _dst, const float* _src); + void unpackRgb5a1(float* _dst, const void* _src); + + // BGR5A1 + void packBgr5a1(void* _dst, const float* _src); + void unpackBgr5a1(float* _dst, const void* _src); + + // RGB10A2 + void packRgb10A2(void* _dst, const float* _src); + void unpackRgb10A2(float* _dst, const void* _src); + + // R11G11B10F + void packR11G11B10F(void* _dst, const float* _src); + void unpackR11G11B10F(float* _dst, const void* _src); + + // RG32F + void packRg32F(void* _dst, const float* _src); + void unpackRg32F(float* _dst, const void* _src); + /// Returns true if texture format is compressed. bool isCompressed(TextureFormat::Enum _format); @@ -120,6 +303,12 @@ namespace bgfx /// bool imageConvert(TextureFormat::Enum _dstFormat, TextureFormat::Enum _srcFormat); + /// + void imageConvert(void* _dst, uint32_t _bpp, PackFn _pack, const void* _src, UnpackFn _unpack, uint32_t _size); + + /// + void imageConvert(void* _dst, uint32_t _dstBpp, PackFn _pack, const void* _src, uint32_t _srcBpp, UnpackFn _unpack, uint32_t _width, uint32_t _height); + /// bool imageConvert(void* _dst, TextureFormat::Enum _dstFormat, const void* _src, TextureFormat::Enum _srcFormat, uint32_t _width, uint32_t _height); diff --git a/src/renderer_d3d9.cpp b/src/renderer_d3d9.cpp index c934deda..9b826251 100644 --- a/src/renderer_d3d9.cpp +++ b/src/renderer_d3d9.cpp @@ -2927,7 +2927,20 @@ namespace bgfx { namespace d3d9 else { uint32_t size = useMipSize ? mip.m_size : mipSize; - memcpy(bits, mip.m_data, size); + switch (m_textureFormat) + { + case TextureFormat::RGB5A1: + imageConvert(bits, 16, packBgr5a1, mip.m_data, unpackRgb5a1, size); + break; + + case TextureFormat::RGBA4: + imageConvert(bits, 16, packBgra4, mip.m_data, unpackRgba4, size); + break; + + default: + memcpy(bits, mip.m_data, size); + break; + } } unlock(side, lod); @@ -2976,7 +2989,20 @@ namespace bgfx { namespace d3d9 uint8_t* dst = bits; for (uint32_t yy = 0, height = _rect.m_height; yy < height; ++yy) { - memcpy(dst, src, rectpitch); + switch (m_textureFormat) + { + case TextureFormat::RGB5A1: + imageConvert(dst, 16, packBgr5a1, src, unpackRgb5a1, rectpitch); + break; + + case TextureFormat::RGBA4: + imageConvert(dst, 16, packBgra4, src, unpackRgba4, rectpitch); + break; + + default: + memcpy(dst, src, rectpitch); + break; + } src += srcpitch; dst += dstpitch; }