From 488483a9450389fee3b8cbab22cc0edf43ea10ec Mon Sep 17 00:00:00 2001 From: bkaradzic Date: Sun, 8 Sep 2013 21:03:03 -0700 Subject: [PATCH] Fixed texture update when requested texture format doesn't match internal texture format, and simplified texture creation. --- include/bgfx.h | 26 +- src/bgfx_p.h | 31 +- src/config.h | 4 + src/image.cpp | 412 ++++++++++++------------ src/image.h | 17 +- src/renderer_d3d11.cpp | 308 +++++------------- src/renderer_d3d11.h | 4 +- src/renderer_d3d9.cpp | 280 +++++++---------- src/renderer_d3d9.h | 5 +- src/renderer_gl.cpp | 604 ++++++++++++++---------------------- src/renderer_gl.h | 6 +- src/renderer_null.cpp | 17 +- tools/texturec/texturec.cpp | 10 +- 13 files changed, 697 insertions(+), 1027 deletions(-) diff --git a/include/bgfx.h b/include/bgfx.h index 1969bdda4..fa9f1637e 100644 --- a/include/bgfx.h +++ b/include/bgfx.h @@ -319,7 +319,6 @@ namespace bgfx PTC24, // PVRTC2 RGBA 4BPP Unknown, L8, - BGRX8, BGRA8, RGBA16, RGBA16F, @@ -749,12 +748,37 @@ namespace bgfx TextureHandle createTexture(const Memory* _mem, uint32_t _flags = BGFX_TEXTURE_NONE, TextureInfo* _info = NULL); /// Create 2D texture. + /// + /// @param _width + /// @param _height + /// @param _numMips + /// @param _format + /// @param _flags + /// @param _mem + /// TextureHandle createTexture2D(uint16_t _width, uint16_t _height, uint8_t _numMips, TextureFormat::Enum _format, uint32_t _flags = BGFX_TEXTURE_NONE, const Memory* _mem = NULL); /// Create 3D texture. + /// + /// @param _width + /// @param _height + /// @param _depth + /// @param _numMips + /// @param _format + /// @param _flags + /// @param _mem + /// TextureHandle createTexture3D(uint16_t _width, uint16_t _height, uint16_t _depth, uint8_t _numMips, TextureFormat::Enum _format, uint32_t _flags = BGFX_TEXTURE_NONE, const Memory* _mem = NULL); /// Create Cube texture. + /// + /// @param _sides + /// @param _width + /// @param _numMips + /// @param _format + /// @param _flags + /// @param _mem + /// TextureHandle createTextureCube(uint16_t _sides, uint16_t _width, uint8_t _numMips, TextureFormat::Enum _format, uint32_t _flags = BGFX_TEXTURE_NONE, const Memory* _mem = NULL); /// Update 2D texture. diff --git a/src/bgfx_p.h b/src/bgfx_p.h index 84c2627a8..11edeb564 100755 --- a/src/bgfx_p.h +++ b/src/bgfx_p.h @@ -16,20 +16,9 @@ #include #include -// clang analyzer annotation -#if !defined(__has_feature) -# define __has_feature(_a) 0 -#endif // !defined(__has_feature) - -#if __has_feature(attribute_analyzer_noreturn) -# define CLANG_ANALYZER_NO_RETURN __attribute__( (analyzer_noreturn) ) -#else -# define CLANG_ANALYZER_NO_RETURN -#endif // __has_feature(attribute_analyzer_noreturn) - namespace bgfx { - void fatal(Fatal::Enum _code, const char* _format, ...) CLANG_ANALYZER_NO_RETURN; + void fatal(Fatal::Enum _code, const char* _format, ...); void dbgPrintf(const char* _format, ...); } @@ -2156,7 +2145,7 @@ namespace bgfx , (uint16_t)imageContainer.m_height , (uint16_t)imageContainer.m_depth , imageContainer.m_numMips - , imageContainer.m_type + , TextureFormat::Enum(imageContainer.m_format) ); } else @@ -2949,6 +2938,22 @@ namespace bgfx rendererCreateTexture(handle, mem, flags); + bx::MemoryReader reader(mem->data, mem->size); + + uint32_t magic; + bx::read(&reader, magic); + + if (BGFX_CHUNK_MAGIC_TEX == magic) + { + TextureCreate tc; + bx::read(&reader, tc); + + if (NULL != tc.m_mem) + { + release(tc.m_mem); + } + } + release(mem); } break; diff --git a/src/config.h b/src/config.h index 4035348a2..c6a88433d 100644 --- a/src/config.h +++ b/src/config.h @@ -91,6 +91,10 @@ # define BGFX_CONFIG_DEBUG_PERFHUD 0 #endif // BGFX_CONFIG_DEBUG_NVPERFHUD +#ifndef BGFX_CONFIG_RENDERER_USE_EXTENSIONS +# define BGFX_CONFIG_RENDERER_USE_EXTENSIONS 1 +#endif // BGFX_CONFIG_RENDERER_USE_EXTENSIONS + /// DX9 PIX markers #ifndef BGFX_CONFIG_DEBUG_PIX # define BGFX_CONFIG_DEBUG_PIX BGFX_CONFIG_DEBUG diff --git a/src/image.cpp b/src/image.cpp index 92a161c4f..777e52d88 100644 --- a/src/image.cpp +++ b/src/image.cpp @@ -30,7 +30,6 @@ namespace bgfx 4, // PTC24 0, // Unknown 8, // L8 - 32, // BGRX8 32, // BGRA8 64, // RGBA16 64, // RGBA16F @@ -564,174 +563,6 @@ namespace bgfx } } - void Mip::decode(uint8_t* _dst) - { - const uint8_t* src = m_data; - - if (TextureFormat::Unknown > m_type) - { - uint32_t width = m_width/4; - uint32_t height = m_height/4; - uint32_t pitch = m_width*4; - - uint8_t temp[16*4]; - - switch (m_type) - { - case TextureFormat::BC1: - for (uint32_t yy = 0; yy < height; ++yy) - { - for (uint32_t xx = 0; xx < width; ++xx) - { - decodeBlockDxt1(temp, src); - src += 8; - - uint8_t* dst = &_dst[(yy*pitch+xx*4)*4]; - memcpy(&dst[0*pitch], &temp[ 0], 16); - memcpy(&dst[1*pitch], &temp[16], 16); - memcpy(&dst[2*pitch], &temp[32], 16); - memcpy(&dst[3*pitch], &temp[48], 16); - } - } - break; - - case TextureFormat::BC2: - for (uint32_t yy = 0; yy < height; ++yy) - { - for (uint32_t xx = 0; xx < width; ++xx) - { - decodeBlockDxt23A(temp+3, src); - src += 8; - decodeBlockDxt(temp, src); - src += 8; - - uint8_t* dst = &_dst[(yy*pitch+xx*4)*4]; - memcpy(&dst[0*pitch], &temp[ 0], 16); - memcpy(&dst[1*pitch], &temp[16], 16); - memcpy(&dst[2*pitch], &temp[32], 16); - memcpy(&dst[3*pitch], &temp[48], 16); - } - } - break; - - case TextureFormat::BC3: - for (uint32_t yy = 0; yy < height; ++yy) - { - for (uint32_t xx = 0; xx < width; ++xx) - { - decodeBlockDxt45A(temp+3, src); - src += 8; - decodeBlockDxt(temp, src); - src += 8; - - uint8_t* dst = &_dst[(yy*pitch+xx*4)*4]; - memcpy(&dst[0*pitch], &temp[ 0], 16); - memcpy(&dst[1*pitch], &temp[16], 16); - memcpy(&dst[2*pitch], &temp[32], 16); - memcpy(&dst[3*pitch], &temp[48], 16); - } - } - break; - - case TextureFormat::BC4: - for (uint32_t yy = 0; yy < height; ++yy) - { - for (uint32_t xx = 0; xx < width; ++xx) - { - decodeBlockDxt45A(temp, src); - src += 8; - - uint8_t* dst = &_dst[(yy*pitch+xx*4)*4]; - memcpy(&dst[0*pitch], &temp[ 0], 16); - memcpy(&dst[1*pitch], &temp[16], 16); - memcpy(&dst[2*pitch], &temp[32], 16); - memcpy(&dst[3*pitch], &temp[48], 16); - } - } - break; - - case TextureFormat::BC5: - for (uint32_t yy = 0; yy < height; ++yy) - { - for (uint32_t xx = 0; xx < width; ++xx) - { - decodeBlockDxt45A(temp+1, src); - src += 8; - decodeBlockDxt45A(temp+2, src); - src += 8; - - for (uint32_t ii = 0; ii < 16; ++ii) - { - float nx = temp[ii*4+2]*2.0f/255.0f - 1.0f; - float ny = temp[ii*4+1]*2.0f/255.0f - 1.0f; - float nz = sqrtf(1.0f - nx*nx - ny*ny); - temp[ii*4+0] = uint8_t( (nz + 1.0f)*255.0f/2.0f); - temp[ii*4+3] = 0; - } - - uint8_t* dst = &_dst[(yy*pitch+xx*4)*4]; - memcpy(&dst[0*pitch], &temp[ 0], 16); - memcpy(&dst[1*pitch], &temp[16], 16); - memcpy(&dst[2*pitch], &temp[32], 16); - memcpy(&dst[3*pitch], &temp[48], 16); - } - } - break; - - case TextureFormat::ETC1: - for (uint32_t yy = 0; yy < height; ++yy) - { - for (uint32_t xx = 0; xx < width; ++xx) - { - decodeBlockEtc1(temp, src); - src += 8; - - uint8_t* dst = &_dst[(yy*pitch+xx*4)*4]; - memcpy(&dst[0*pitch], &temp[ 0], 16); - memcpy(&dst[1*pitch], &temp[16], 16); - memcpy(&dst[2*pitch], &temp[32], 16); - memcpy(&dst[3*pitch], &temp[48], 16); - } - } - break; - - default: - // Decompression not implemented... Make ugly red-yellow checkerboard texture. - imageCheckerboard(m_width, m_height, 16, UINT32_C(0xffff0000), UINT32_C(0xffffff00), _dst); - break; - } - } - else - { - uint32_t width = m_width; - uint32_t height = m_height; - - if (m_bpp == 8 - || m_bpp == 32 - || m_bpp == 64) - { - uint32_t pitch = m_width*m_bpp/8; - memcpy(_dst, src, pitch*height); - } - else - { - uint32_t pitch = m_width*4; - for (uint32_t yy = 0; yy < height; ++yy) - { - uint8_t* dst = &_dst[yy*pitch]; - - for (uint32_t xx = 0; xx < width; ++xx) - { - memcpy(dst, src, 3); - dst[3] = 255; - dst += 4; - src += 3; - } - } - } - } - } - // DDS #define DDS_MAGIC BX_MAKEFOURCC('D', 'D', 'S', ' ') #define DDS_HEADER_SIZE 124 @@ -803,7 +634,6 @@ namespace bgfx { DDS_BC5U, TextureFormat::BC5 }, { D3DFMT_A16B16G16R16, TextureFormat::RGBA16 }, { D3DFMT_A16B16G16R16F, TextureFormat::RGBA16F }, - { DDPF_RGB, TextureFormat::BGRX8 }, { DDPF_RGB|DDPF_ALPHAPIXELS, TextureFormat::BGRA8 }, { DDPF_INDEXED, TextureFormat::L8 }, { DDPF_LUMINANCE, TextureFormat::L8 }, @@ -889,31 +719,30 @@ namespace bgfx uint8_t bpp = 0; uint8_t blockSize = 1; - TextureFormat::Enum type = TextureFormat::Unknown; + TextureFormat::Enum format = TextureFormat::Unknown; bool hasAlpha = pixelFlags & DDPF_ALPHAPIXELS; - uint32_t format = pixelFlags & DDPF_FOURCC ? fourcc : pixelFlags; + uint32_t ddsFormat = pixelFlags & DDPF_FOURCC ? fourcc : pixelFlags; for (uint32_t ii = 0; ii < BX_COUNTOF(s_translateDdsFormat); ++ii) { - if (s_translateDdsFormat[ii].m_format == format) + if (s_translateDdsFormat[ii].m_format == ddsFormat) { - type = s_translateDdsFormat[ii].m_textureFormat; + format = s_translateDdsFormat[ii].m_textureFormat; break; } } - bpp = TextureFormat::BGRX8 == type // special case to force conversion to 32-bpp. - ? 24 - : getBitsPerPixel(type) - ; - blockSize = type < TextureFormat::Unknown ? 4*4 : 1; + bpp = getBitsPerPixel(format); + blockSize = format < TextureFormat::Unknown ? 4*4 : 1; blockSize = blockSize*bpp/8; - _imageContainer.m_type = type; + _imageContainer.m_data = NULL; + _imageContainer.m_size = 0; _imageContainer.m_offset = DDS_IMAGE_DATA_OFFSET; _imageContainer.m_width = width; _imageContainer.m_height = height; _imageContainer.m_depth = depth; + _imageContainer.m_format = format; _imageContainer.m_blockSize = blockSize; _imageContainer.m_numMips = (caps[0] & DDSCAPS_MIPMAP) ? mips : 1; _imageContainer.m_bpp = bpp; @@ -921,7 +750,7 @@ namespace bgfx _imageContainer.m_cubeMap = cubeMap; _imageContainer.m_ktx = false; - return TextureFormat::Unknown != type; + return TextureFormat::Unknown != format; } // KTX @@ -1043,30 +872,29 @@ namespace bgfx uint8_t bpp = 0; uint8_t blockSize = 1; - TextureFormat::Enum type = TextureFormat::Unknown; + TextureFormat::Enum format = TextureFormat::Unknown; bool hasAlpha = false; for (uint32_t ii = 0; ii < BX_COUNTOF(s_translateKtxFormat); ++ii) { if (s_translateKtxFormat[ii].m_format == glInternalFormat) { - type = s_translateKtxFormat[ii].m_textureFormat; + format = s_translateKtxFormat[ii].m_textureFormat; break; } } - bpp = TextureFormat::BGRX8 == type // special case to force conversion to 32-bpp. - ? 24 - : getBitsPerPixel(type) - ; - blockSize = type < TextureFormat::Unknown ? 4*4 : 1; + bpp = getBitsPerPixel(format); + blockSize = format < TextureFormat::Unknown ? 4*4 : 1; blockSize = blockSize*bpp/8; - _imageContainer.m_type = type; + _imageContainer.m_data = NULL; + _imageContainer.m_size = 0; _imageContainer.m_offset = (uint32_t)offset; _imageContainer.m_width = width; _imageContainer.m_height = height; _imageContainer.m_depth = depth; + _imageContainer.m_format = format; _imageContainer.m_blockSize = blockSize; _imageContainer.m_numMips = numMips; _imageContainer.m_bpp = bpp; @@ -1074,7 +902,7 @@ namespace bgfx _imageContainer.m_cubeMap = numFaces > 1; _imageContainer.m_ktx = true; - return TextureFormat::Unknown != type; + return TextureFormat::Unknown != format; } // PVR3 @@ -1164,7 +992,7 @@ namespace bgfx uint8_t bpp = 0; uint8_t blockSize = 1; - TextureFormat::Enum type = TextureFormat::Unknown; + TextureFormat::Enum format = TextureFormat::Unknown; bool hasAlpha = false; for (uint32_t ii = 0; ii < BX_COUNTOF(s_translatePvr3Format); ++ii) @@ -1172,23 +1000,22 @@ namespace bgfx if (s_translatePvr3Format[ii].m_format == pixelFormat && channelType == (s_translatePvr3Format[ii].m_channelTypeMask & channelType) ) { - type = s_translatePvr3Format[ii].m_textureFormat; + format = s_translatePvr3Format[ii].m_textureFormat; break; } } - bpp = TextureFormat::BGRX8 == type // special case to force conversion to 32-bpp. - ? 24 - : getBitsPerPixel(type) - ; - blockSize = type < TextureFormat::Unknown ? 4*4 : 1; + bpp = getBitsPerPixel(format); + blockSize = format < TextureFormat::Unknown ? 4*4 : 1; blockSize = blockSize*bpp/8; - _imageContainer.m_type = type; + _imageContainer.m_data = NULL; + _imageContainer.m_size = 0; _imageContainer.m_offset = (uint32_t)offset; _imageContainer.m_width = width; _imageContainer.m_height = height; _imageContainer.m_depth = depth; + _imageContainer.m_format = format; _imageContainer.m_blockSize = blockSize; _imageContainer.m_numMips = numMips; _imageContainer.m_bpp = bpp; @@ -1196,7 +1023,7 @@ namespace bgfx _imageContainer.m_cubeMap = numFaces > 1; _imageContainer.m_ktx = false; - return TextureFormat::Unknown != type; + return TextureFormat::Unknown != format; } bool imageParse(ImageContainer& _imageContainer, bx::ReaderSeekerI* _reader) @@ -1216,6 +1043,39 @@ namespace bgfx { return imageParsePvr3(_imageContainer, _reader); } + else if (BGFX_CHUNK_MAGIC_TEX == magic) + { + TextureCreate tc; + bx::read(_reader, tc); + + uint32_t bpp = getBitsPerPixel(TextureFormat::Enum(tc.m_format) ); + uint32_t blockSize = tc.m_format < TextureFormat::Unknown ? 4*4 : 1; + blockSize = blockSize*bpp/8; + + _imageContainer.m_format = tc.m_format; + _imageContainer.m_offset = UINT32_MAX; + if (NULL == tc.m_mem) + { + _imageContainer.m_data = NULL; + _imageContainer.m_size = 0; + } + else + { + _imageContainer.m_data = tc.m_mem->data; + _imageContainer.m_size = tc.m_mem->size; + } + _imageContainer.m_width = tc.m_width; + _imageContainer.m_height = tc.m_height; + _imageContainer.m_depth = tc.m_depth; + _imageContainer.m_blockSize = blockSize; + _imageContainer.m_numMips = tc.m_numMips; + _imageContainer.m_bpp = getBitsPerPixel(TextureFormat::Enum(tc.m_format) ); + _imageContainer.m_hasAlpha = false; + _imageContainer.m_cubeMap = tc.m_cubeMap; + _imageContainer.m_ktx = false; + + return true; + } return false; } @@ -1226,14 +1086,162 @@ namespace bgfx return imageParse(_imageContainer, &reader); } - bool imageGetRawData(const ImageContainer& _imageContainer, uint8_t _side, uint8_t _lod, const void* _data, uint32_t _size, Mip& _mip) + void imageDecodeToBgra8(uint8_t* _dst, const uint8_t* _src, uint32_t _width, uint32_t _height, uint8_t _type) + { + const uint8_t* src = _src; + + uint32_t width = _width/4; + uint32_t height = _height/4; + uint32_t pitch = _width*4; + + uint8_t temp[16*4]; + + switch (_type) + { + case TextureFormat::BC1: + for (uint32_t yy = 0; yy < height; ++yy) + { + for (uint32_t xx = 0; xx < width; ++xx) + { + decodeBlockDxt1(temp, src); + src += 8; + + uint8_t* dst = &_dst[(yy*pitch+xx*4)*4]; + memcpy(&dst[0*pitch], &temp[ 0], 16); + memcpy(&dst[1*pitch], &temp[16], 16); + memcpy(&dst[2*pitch], &temp[32], 16); + memcpy(&dst[3*pitch], &temp[48], 16); + } + } + break; + + case TextureFormat::BC2: + for (uint32_t yy = 0; yy < height; ++yy) + { + for (uint32_t xx = 0; xx < width; ++xx) + { + decodeBlockDxt23A(temp+3, src); + src += 8; + decodeBlockDxt(temp, src); + src += 8; + + uint8_t* dst = &_dst[(yy*pitch+xx*4)*4]; + memcpy(&dst[0*pitch], &temp[ 0], 16); + memcpy(&dst[1*pitch], &temp[16], 16); + memcpy(&dst[2*pitch], &temp[32], 16); + memcpy(&dst[3*pitch], &temp[48], 16); + } + } + break; + + case TextureFormat::BC3: + for (uint32_t yy = 0; yy < height; ++yy) + { + for (uint32_t xx = 0; xx < width; ++xx) + { + decodeBlockDxt45A(temp+3, src); + src += 8; + decodeBlockDxt(temp, src); + src += 8; + + uint8_t* dst = &_dst[(yy*pitch+xx*4)*4]; + memcpy(&dst[0*pitch], &temp[ 0], 16); + memcpy(&dst[1*pitch], &temp[16], 16); + memcpy(&dst[2*pitch], &temp[32], 16); + memcpy(&dst[3*pitch], &temp[48], 16); + } + } + break; + + case TextureFormat::BC4: + for (uint32_t yy = 0; yy < height; ++yy) + { + for (uint32_t xx = 0; xx < width; ++xx) + { + decodeBlockDxt45A(temp, src); + src += 8; + + uint8_t* dst = &_dst[(yy*pitch+xx*4)*4]; + memcpy(&dst[0*pitch], &temp[ 0], 16); + memcpy(&dst[1*pitch], &temp[16], 16); + memcpy(&dst[2*pitch], &temp[32], 16); + memcpy(&dst[3*pitch], &temp[48], 16); + } + } + break; + + case TextureFormat::BC5: + for (uint32_t yy = 0; yy < height; ++yy) + { + for (uint32_t xx = 0; xx < width; ++xx) + { + decodeBlockDxt45A(temp+1, src); + src += 8; + decodeBlockDxt45A(temp+2, src); + src += 8; + + for (uint32_t ii = 0; ii < 16; ++ii) + { + float nx = temp[ii*4+2]*2.0f/255.0f - 1.0f; + float ny = temp[ii*4+1]*2.0f/255.0f - 1.0f; + float nz = sqrtf(1.0f - nx*nx - ny*ny); + temp[ii*4+0] = uint8_t( (nz + 1.0f)*255.0f/2.0f); + temp[ii*4+3] = 0; + } + + uint8_t* dst = &_dst[(yy*pitch+xx*4)*4]; + memcpy(&dst[0*pitch], &temp[ 0], 16); + memcpy(&dst[1*pitch], &temp[16], 16); + memcpy(&dst[2*pitch], &temp[32], 16); + memcpy(&dst[3*pitch], &temp[48], 16); + } + } + break; + + case TextureFormat::ETC1: + for (uint32_t yy = 0; yy < height; ++yy) + { + for (uint32_t xx = 0; xx < width; ++xx) + { + decodeBlockEtc1(temp, src); + src += 8; + + uint8_t* dst = &_dst[(yy*pitch+xx*4)*4]; + memcpy(&dst[0*pitch], &temp[ 0], 16); + memcpy(&dst[1*pitch], &temp[16], 16); + memcpy(&dst[2*pitch], &temp[32], 16); + memcpy(&dst[3*pitch], &temp[48], 16); + } + } + break; + + default: + // Decompression not implemented... Make ugly red-yellow checkerboard texture. + imageCheckerboard(_width, _height, 16, UINT32_C(0xffff0000), UINT32_C(0xffffff00), _dst); + break; + } + } + + bool imageGetRawData(const ImageContainer& _imageContainer, uint8_t _side, uint8_t _lod, const void* _data, uint32_t _size, ImageMip& _mip) { const uint32_t blockSize = _imageContainer.m_blockSize; uint32_t offset = _imageContainer.m_offset; const uint8_t bpp = _imageContainer.m_bpp; - TextureFormat::Enum type = _imageContainer.m_type; + TextureFormat::Enum type = TextureFormat::Enum(_imageContainer.m_format); bool hasAlpha = _imageContainer.m_hasAlpha; + if (UINT32_MAX == _imageContainer.m_offset) + { + if (NULL == _imageContainer.m_data) + { + return false; + } + + offset = 0; + _data = _imageContainer.m_data; + _size = _imageContainer.m_size; + } + for (uint8_t side = 0, numSides = _imageContainer.m_cubeMap ? 6 : 1; side < numSides; ++side) { uint32_t width = _imageContainer.m_width; @@ -1269,7 +1277,7 @@ namespace bgfx _mip.m_size = size; _mip.m_data = (const uint8_t*)_data + offset; _mip.m_bpp = bpp; - _mip.m_type = type; + _mip.m_format = type; _mip.m_hasAlpha = hasAlpha; return true; } diff --git a/src/image.h b/src/image.h index 34f8470ed..5947675e0 100644 --- a/src/image.h +++ b/src/image.h @@ -12,11 +12,13 @@ namespace bgfx { struct ImageContainer { - TextureFormat::Enum m_type; + void* m_data; + uint32_t m_size; uint32_t m_offset; uint32_t m_width; uint32_t m_height; uint32_t m_depth; + uint8_t m_format; uint8_t m_blockSize; uint8_t m_numMips; uint8_t m_bpp; @@ -25,18 +27,16 @@ namespace bgfx bool m_ktx; }; - struct Mip + struct ImageMip { uint32_t m_width; uint32_t m_height; uint32_t m_blockSize; uint32_t m_size; uint8_t m_bpp; - uint8_t m_type; + uint8_t m_format; bool m_hasAlpha; const uint8_t* m_data; - - void decode(uint8_t* _dst); }; /// @@ -61,10 +61,13 @@ namespace bgfx bool imageParse(ImageContainer& _imageContainer, bx::ReaderSeekerI* _reader); /// - bool imageParse(ImageContainer& _dds, const void* _data, uint32_t _size); + bool imageParse(ImageContainer& _imageContainer, const void* _data, uint32_t _size); /// - bool imageGetRawData(const ImageContainer& _dds, uint8_t _side, uint8_t _index, const void* _data, uint32_t _size, Mip& _mip); + void imageDecodeToBgra8(uint8_t* _dst, const uint8_t* _src, uint32_t _width, uint32_t _height, uint8_t _type); + + /// + bool imageGetRawData(const ImageContainer& _dds, uint8_t _side, uint8_t _index, const void* _data, uint32_t _size, ImageMip& _mip); } // namespace bgfx diff --git a/src/renderer_d3d11.cpp b/src/renderer_d3d11.cpp index b667921a0..af90e0dc2 100644 --- a/src/renderer_d3d11.cpp +++ b/src/renderer_d3d11.cpp @@ -200,7 +200,6 @@ namespace bgfx { DXGI_FORMAT_UNKNOWN }, // PTC24 { DXGI_FORMAT_UNKNOWN }, // Unknown { DXGI_FORMAT_R8_UNORM }, // L8 - { DXGI_FORMAT_B8G8R8A8_UNORM }, // BGRX8 { DXGI_FORMAT_B8G8R8A8_UNORM }, // BGRA8 { DXGI_FORMAT_R16G16B16A16_UNORM }, // RGBA16 { DXGI_FORMAT_R16G16B16A16_FLOAT }, // RGBA16F @@ -1643,7 +1642,20 @@ namespace bgfx if (imageParse(imageContainer, _mem->data, _mem->size) ) { - bool decompress = DXGI_FORMAT_UNKNOWN == s_textureFormat[imageContainer.m_type].m_fmt; + m_requestedFormat = (uint8_t)imageContainer.m_format; + m_textureFormat = (uint8_t)imageContainer.m_format; + + const TextureFormatInfo& tfi = s_textureFormat[m_requestedFormat]; + const bool convert = DXGI_FORMAT_UNKNOWN == tfi.m_fmt; + + uint8_t bpp = getBitsPerPixel(TextureFormat::Enum(m_textureFormat) ); + if (convert) + { + m_textureFormat = (uint8_t)TextureFormat::BGRA8; + bpp = 32; + } + + DXGI_FORMAT format = s_textureFormat[m_textureFormat].m_fmt; if (imageContainer.m_cubeMap) { @@ -1658,92 +1670,61 @@ namespace bgfx m_type = Texture2D; } - TextureFormat::Enum textureFormat = decompress ? TextureFormat::BGRA8 : imageContainer.m_type; + m_numMips = imageContainer.m_numMips; + uint32_t numSrd = imageContainer.m_numMips*(imageContainer.m_cubeMap ? 6 : 1); D3D11_SUBRESOURCE_DATA* srd = (D3D11_SUBRESOURCE_DATA*)alloca(numSrd*sizeof(D3D11_SUBRESOURCE_DATA) ); uint32_t kk = 0; - bool convert = false; - m_numMips = imageContainer.m_numMips; - - if (decompress - || TextureFormat::Unknown < imageContainer.m_type) + for (uint8_t side = 0, numSides = imageContainer.m_cubeMap ? 6 : 1; side < numSides; ++side) { - uint32_t bpp = getBitsPerPixel(textureFormat); - convert = decompress - || TextureFormat::BGRX8 == textureFormat - ; + uint32_t width = imageContainer.m_width; + uint32_t height = imageContainer.m_height; + uint32_t depth = imageContainer.m_depth; - for (uint8_t side = 0, numSides = imageContainer.m_cubeMap ? 6 : 1; side < numSides; ++side) + for (uint32_t lod = 0, num = m_numMips; lod < num; ++lod) { - uint32_t width = imageContainer.m_width; - uint32_t height = imageContainer.m_height; - uint32_t depth = imageContainer.m_depth; + width = bx::uint32_max(1, width); + height = bx::uint32_max(1, height); + depth = bx::uint32_max(1, depth); - for (uint32_t lod = 0, num = m_numMips; lod < num; ++lod) + ImageMip mip; + if (imageGetRawData(imageContainer, side, lod, _mem->data, _mem->size, mip) ) { - width = bx::uint32_max(1, width); - height = bx::uint32_max(1, height); - depth = bx::uint32_max(1, depth); + srd[kk].pSysMem = mip.m_data; - Mip mip; - if (imageGetRawData(imageContainer, side, lod, _mem->data, _mem->size, mip) ) + if (convert) { - if (convert) - { - uint8_t* temp = (uint8_t*)g_realloc(NULL, mip.m_width*mip.m_height*bpp/8); - mip.decode(temp); + uint8_t* temp = (uint8_t*)g_realloc(NULL, mip.m_width*mip.m_height*bpp/8); + imageDecodeToBgra8(temp, mip.m_data, mip.m_width, mip.m_height, mip.m_format); - srd[kk].pSysMem = temp; - srd[kk].SysMemPitch = mip.m_width*bpp/8; - } - else - { - srd[kk].pSysMem = mip.m_data; - srd[kk].SysMemPitch = mip.m_width*mip.m_bpp/8; - } - - srd[kk].SysMemSlicePitch = mip.m_height*srd[kk].SysMemPitch; - ++kk; + srd[kk].pSysMem = temp; + srd[kk].SysMemPitch = mip.m_width*bpp/8; + } + else if (TextureFormat::Unknown > m_textureFormat) + { + srd[kk].SysMemPitch = (mip.m_width/4)*mip.m_blockSize; + srd[kk].SysMemSlicePitch = (mip.m_height/4)*srd[kk].SysMemPitch; + } + else + { + srd[kk].SysMemPitch = mip.m_width*mip.m_bpp/8; } - width >>= 1; - height >>= 1; - depth >>= 1; + srd[kk].SysMemSlicePitch = mip.m_height*srd[kk].SysMemPitch; + ++kk; } - } - } - else - { - for (uint8_t side = 0, numSides = imageContainer.m_cubeMap ? 6 : 1; side < numSides; ++side) - { - for (uint32_t lod = 0, num = m_numMips; lod < num; ++lod) - { - Mip mip; - if (imageGetRawData(imageContainer, side, lod, _mem->data, _mem->size, mip) ) - { - srd[kk].pSysMem = mip.m_data; - if (TextureFormat::Unknown > imageContainer.m_type) - { - srd[kk].SysMemPitch = (mip.m_width/4)*mip.m_blockSize; - srd[kk].SysMemSlicePitch = (mip.m_height/4)*srd[kk].SysMemPitch; - } - else - { - srd[kk].SysMemPitch = mip.m_width*mip.m_bpp/8; - srd[kk].SysMemSlicePitch = mip.m_height*srd[kk].SysMemPitch; - } - ++kk; - } - } + width >>= 1; + height >>= 1; + depth >>= 1; } } D3D11_SHADER_RESOURCE_VIEW_DESC srvd; memset(&srvd, 0, sizeof(srvd) ); - srvd.Format = s_textureFormat[textureFormat].m_fmt; + srvd.Format = format; switch (m_type) { @@ -1757,7 +1738,7 @@ namespace bgfx desc.Format = srvd.Format; desc.SampleDesc.Count = 1; desc.SampleDesc.Quality = 0; - desc.Usage = D3D11_USAGE_IMMUTABLE; + desc.Usage = kk == 0 ? D3D11_USAGE_DEFAULT : D3D11_USAGE_IMMUTABLE; desc.BindFlags = D3D11_BIND_SHADER_RESOURCE; desc.CPUAccessFlags = 0; @@ -1776,7 +1757,7 @@ namespace bgfx srvd.Texture2D.MipLevels = imageContainer.m_numMips; } - DX_CHECK(s_renderCtx.m_device->CreateTexture2D(&desc, srd, &m_texture2d) ); + DX_CHECK(s_renderCtx.m_device->CreateTexture2D(&desc, kk == 0 ? NULL : srd, &m_texture2d) ); } break; @@ -1788,7 +1769,7 @@ namespace bgfx desc.Depth = imageContainer.m_depth; desc.MipLevels = imageContainer.m_numMips; desc.Format = srvd.Format; - desc.Usage = D3D11_USAGE_IMMUTABLE; + desc.Usage = kk == 0 ? D3D11_USAGE_DEFAULT : D3D11_USAGE_IMMUTABLE; desc.BindFlags = D3D11_BIND_SHADER_RESOURCE; desc.CPUAccessFlags = 0; desc.MiscFlags = 0; @@ -1796,14 +1777,15 @@ namespace bgfx srvd.ViewDimension = D3D11_SRV_DIMENSION_TEXTURE3D; srvd.Texture3D.MipLevels = imageContainer.m_numMips; - DX_CHECK(s_renderCtx.m_device->CreateTexture3D(&desc, srd, &m_texture3d) ); + DX_CHECK(s_renderCtx.m_device->CreateTexture3D(&desc, kk == 0 ? NULL : srd, &m_texture3d) ); } break; } DX_CHECK(s_renderCtx.m_device->CreateShaderResourceView(m_ptr, &srvd, &m_srv) ); - if (convert) + if (convert + && 0 != kk) { kk = 0; for (uint8_t side = 0, numSides = imageContainer.m_cubeMap ? 6 : 1; side < numSides; ++side) @@ -1816,153 +1798,6 @@ namespace bgfx } } } - else - { - bx::MemoryReader reader(_mem->data, _mem->size); - - uint32_t magic; - bx::read(&reader, magic); - - if (BGFX_CHUNK_MAGIC_TEX == magic) - { - TextureCreate tc; - bx::read(&reader, tc); - - if (tc.m_cubeMap) - { - m_type = TextureCube; - } - else if (tc.m_depth > 1) - { - m_type = Texture3D; - } - else - { - m_type = Texture2D; - } - - m_numMips = tc.m_numMips; - - D3D11_SHADER_RESOURCE_VIEW_DESC srvd; - memset(&srvd, 0, sizeof(srvd) ); - srvd.Format = s_textureFormat[tc.m_format].m_fmt; - - if (NULL != tc.m_mem) - { - D3D11_TEXTURE2D_DESC desc; - desc.Width = tc.m_width; - desc.Height = tc.m_height; - desc.MipLevels = tc.m_numMips; - desc.ArraySize = 1; - desc.Format = srvd.Format; - desc.SampleDesc.Count = 1; - desc.SampleDesc.Quality = 0; - desc.Usage = D3D11_USAGE_IMMUTABLE; - desc.BindFlags = D3D11_BIND_SHADER_RESOURCE; - desc.CPUAccessFlags = 0; - desc.MiscFlags = 0; - - srvd.ViewDimension = D3D11_SRV_DIMENSION_TEXTURE2D; - srvd.Texture2D.MipLevels = tc.m_numMips; - - D3D11_SUBRESOURCE_DATA* srd = (D3D11_SUBRESOURCE_DATA*)alloca(tc.m_numMips*sizeof(D3D11_SUBRESOURCE_DATA) ); - uint32_t bpp = getBitsPerPixel(TextureFormat::Enum(tc.m_format) ); - uint8_t* data = tc.m_mem->data; - - for (uint8_t side = 0, numSides = tc.m_cubeMap ? 6 : 1; side < numSides; ++side) - { - uint32_t width = tc.m_width; - uint32_t height = tc.m_height; - uint32_t depth = tc.m_depth; - - for (uint32_t lod = 0, num = tc.m_numMips; lod < num; ++lod) - { - width = bx::uint32_max(1, width); - height = bx::uint32_max(1, height); - depth = bx::uint32_max(1, depth); - - srd[lod].pSysMem = data; - srd[lod].SysMemPitch = width*bpp/8; - srd[lod].SysMemSlicePitch = 0; - - data += width*height*bpp/8; - - width >>= 1; - height >>= 1; - depth >>= 1; - } - } - - DX_CHECK(s_renderCtx.m_device->CreateTexture2D(&desc, srd, &m_texture2d) ); - - release(tc.m_mem); - } - else - { - switch (m_type) - { - case Texture2D: - case TextureCube: - { - D3D11_TEXTURE2D_DESC desc; - desc.Width = tc.m_width; - desc.Height = tc.m_height; - desc.MipLevels = tc.m_numMips; - desc.Format = srvd.Format; - desc.SampleDesc.Count = 1; - desc.SampleDesc.Quality = 0; - desc.Usage = D3D11_USAGE_DEFAULT; - desc.BindFlags = D3D11_BIND_SHADER_RESOURCE; - desc.CPUAccessFlags = 0; - - if (TextureCube == m_type) - { - desc.ArraySize = 6; - desc.MiscFlags = D3D11_RESOURCE_MISC_TEXTURECUBE; - srvd.ViewDimension = D3D11_SRV_DIMENSION_TEXTURECUBE; - srvd.TextureCube.MipLevels = m_numMips; - } - else - { - desc.ArraySize = 1; - desc.MiscFlags = 0; - srvd.ViewDimension = D3D11_SRV_DIMENSION_TEXTURE2D; - srvd.Texture2D.MipLevels = m_numMips; - } - - DX_CHECK(s_renderCtx.m_device->CreateTexture2D(&desc, NULL, &m_texture2d) ); - } - break; - - case Texture3D: - { - D3D11_TEXTURE3D_DESC desc; - desc.Width = tc.m_width; - desc.Height = tc.m_height; - desc.Depth = tc.m_depth; - desc.MipLevels = tc.m_numMips; - desc.Format = srvd.Format; - desc.Usage = D3D11_USAGE_DEFAULT; - desc.BindFlags = D3D11_BIND_SHADER_RESOURCE; - desc.CPUAccessFlags = 0; - desc.MiscFlags = 0; - - srvd.ViewDimension = D3D11_SRV_DIMENSION_TEXTURE3D; - srvd.Texture3D.MipLevels = m_numMips; - - DX_CHECK(s_renderCtx.m_device->CreateTexture3D(&desc, NULL, &m_texture3d) ); - } - break; - } - } - - DX_CHECK(s_renderCtx.m_device->CreateShaderResourceView(m_ptr, &srvd, &m_srv) ); - } - else - { - // - } - } } void Texture::destroy() @@ -1994,23 +1829,28 @@ namespace bgfx box.back = box.front + _depth; uint32_t subres = _mip + (_side * m_numMips); -#if 0 - D3D11_MAPPED_SUBRESOURCE mapped; - DX_CHECK(deviceCtx->Map(m_ptr, 0, D3D11_MAP_WRITE, D3D11_MAP_FLAG_DO_NOT_WAIT, &mapped) ); - memcpy( (uint8_t*)mapped.pData + subres*mapped.DepthPitch, _mem->data, _mem->size); - deviceCtx->Unmap(m_ptr, 0); - deviceCtx->CopySubresourceRegion(m_ptr - , subres - , _rect.m_x - , _rect.m_y - , _rect.m_z - , staging // D3D11_USAGE_STAGING - , ... - ); -#else - deviceCtx->UpdateSubresource(m_ptr, subres, &box, _mem->data, _rect.m_width*4, 0); -#endif // 0 + uint32_t bpp = getBitsPerPixel(TextureFormat::Enum(m_textureFormat) ); + uint32_t srcpitch = _rect.m_width*bpp/8; + + const bool convert = m_textureFormat != m_requestedFormat; + + uint8_t* data = _mem->data; + uint8_t* temp = NULL; + + if (convert) + { + uint8_t* temp = (uint8_t*)g_realloc(NULL, srcpitch*_rect.m_height); + imageDecodeToBgra8(temp, data, _rect.m_width, _rect.m_height, m_requestedFormat); + data = temp; + } + + deviceCtx->UpdateSubresource(m_ptr, subres, &box, data, srcpitch, 0); + + if (NULL != temp) + { + g_free(temp); + } } void RenderTarget::create(uint16_t _width, uint16_t _height, uint32_t _flags, uint32_t _textureFlags) diff --git a/src/renderer_d3d11.h b/src/renderer_d3d11.h index 641ccb704..6d48324a7 100644 --- a/src/renderer_d3d11.h +++ b/src/renderer_d3d11.h @@ -255,7 +255,9 @@ namespace bgfx ID3D11ShaderResourceView* m_srv; ID3D11SamplerState* m_sampler; - Enum m_type; + uint8_t m_type; + uint8_t m_requestedFormat; + uint8_t m_textureFormat; uint8_t m_numMips; }; diff --git a/src/renderer_d3d9.cpp b/src/renderer_d3d9.cpp index 77f99889d..f2ac7a7c2 100644 --- a/src/renderer_d3d9.cpp +++ b/src/renderer_d3d9.cpp @@ -183,36 +183,34 @@ namespace bgfx struct TextureFormatInfo { D3DFORMAT m_fmt; - uint8_t m_bpp; }; - static const TextureFormatInfo s_textureFormat[TextureFormat::Count] = + static TextureFormatInfo s_textureFormat[TextureFormat::Count] = { - { D3DFMT_DXT1, 4 }, // BC1 - { D3DFMT_DXT3, 8 }, // BC2 - { D3DFMT_DXT5, 8 }, // BC3 - { D3DFMT_ATI1, 4 }, // BC4 - { D3DFMT_ATI2, 8 }, // BC5 - { D3DFMT_UNKNOWN, 0 }, // ETC1 - { D3DFMT_UNKNOWN, 0 }, // ETC2 - { D3DFMT_UNKNOWN, 0 }, // ETC2A - { D3DFMT_UNKNOWN, 0 }, // ETC2A1 - { D3DFMT_UNKNOWN, 0 }, // PTC12 - { D3DFMT_UNKNOWN, 0 }, // PTC14 - { D3DFMT_UNKNOWN, 0 }, // PTC12A - { D3DFMT_UNKNOWN, 0 }, // PTC14A - { D3DFMT_UNKNOWN, 0 }, // PTC22 - { D3DFMT_UNKNOWN, 0 }, // PTC24 - { D3DFMT_UNKNOWN, 0 }, // Unknown - { D3DFMT_L8, 8 }, // L8 - { D3DFMT_X8R8G8B8, 32 }, // BGRX8 - { D3DFMT_A8R8G8B8, 32 }, // BGRA8 - { D3DFMT_A16B16G16R16, 64 }, // RGBA16 - { D3DFMT_A16B16G16R16F, 64 }, // RGBA16F - { D3DFMT_R5G6B5, 16 }, // R5G6B5 - { D3DFMT_A4R4G4B4, 16 }, // RGBA4 - { D3DFMT_A1R5G5B5, 16 }, // RGB5A1 - { D3DFMT_A2B10G10R10, 32 }, // RGB10A2 + { D3DFMT_DXT1 }, // BC1 + { D3DFMT_DXT3 }, // BC2 + { D3DFMT_DXT5 }, // BC3 + { D3DFMT_UNKNOWN }, // BC4 + { D3DFMT_UNKNOWN }, // BC5 + { D3DFMT_UNKNOWN }, // ETC1 + { D3DFMT_UNKNOWN }, // ETC2 + { D3DFMT_UNKNOWN }, // ETC2A + { D3DFMT_UNKNOWN }, // ETC2A1 + { D3DFMT_UNKNOWN }, // PTC12 + { D3DFMT_UNKNOWN }, // PTC14 + { D3DFMT_UNKNOWN }, // PTC12A + { D3DFMT_UNKNOWN }, // PTC14A + { D3DFMT_UNKNOWN }, // PTC22 + { D3DFMT_UNKNOWN }, // PTC24 + { D3DFMT_UNKNOWN }, // Unknown + { D3DFMT_L8 }, // L8 + { D3DFMT_A8R8G8B8 }, // BGRA8 + { D3DFMT_A16B16G16R16 }, // RGBA16 + { D3DFMT_A16B16G16R16F }, // RGBA16F + { D3DFMT_R5G6B5 }, // R5G6B5 + { D3DFMT_A4R4G4B4 }, // RGBA4 + { D3DFMT_A1R5G5B5 }, // RGB5A1 + { D3DFMT_A2B10G10R10 }, // RGB10A2 }; static ExtendedFormat s_extendedFormats[ExtendedFormat::Count] = @@ -404,6 +402,7 @@ namespace bgfx BX_TRACE("Max fragment shader 2.0 instr. slots: %d", m_caps.PS20Caps.NumInstructionSlots); BX_TRACE("Max fragment shader 3.0 instr. slots: %d", m_caps.MaxPixelShader30InstructionSlots); +#if BGFX_CONFIG_RENDERER_USE_EXTENSIONS BX_TRACE("Extended formats:"); for (uint32_t ii = 0; ii < ExtendedFormat::Count; ++ii) { @@ -426,6 +425,10 @@ namespace bgfx m_device->SetRenderState(D3DRS_POINTSIZE, D3DFMT_INST); } + s_textureFormat[TextureFormat::BC4].m_fmt = s_extendedFormats[ExtendedFormat::Ati1].m_supported ? D3DFMT_ATI1 : D3DFMT_UNKNOWN; + s_textureFormat[TextureFormat::BC5].m_fmt = s_extendedFormats[ExtendedFormat::Ati2].m_supported ? D3DFMT_ATI2 : D3DFMT_UNKNOWN; +#endif // BGFX_CONFIG_RENDERER_USE_EXTENSIONS + uint32_t index = 1; for (const D3DFORMAT* fmt = &s_checkColorFormats[index]; *fmt != D3DFMT_UNKNOWN; ++fmt, ++index) { @@ -1518,17 +1521,20 @@ namespace bgfx if (imageParse(imageContainer, _mem->data, _mem->size) ) { - m_format = imageContainer.m_type; - const TextureFormatInfo& tfi = s_textureFormat[imageContainer.m_type]; + m_requestedFormat = (uint8_t)imageContainer.m_format; + m_textureFormat = (uint8_t)imageContainer.m_format; - bool decompress = false - || (TextureFormat::BC4 == imageContainer.m_type && !s_extendedFormats[ExtendedFormat::Ati1].m_supported) - || (TextureFormat::BC5 == imageContainer.m_type && !s_extendedFormats[ExtendedFormat::Ati2].m_supported) - || (D3DFMT_UNKNOWN == tfi.m_fmt) - ; + const TextureFormatInfo& tfi = s_textureFormat[m_requestedFormat]; + const bool convert = D3DFMT_UNKNOWN == tfi.m_fmt; - D3DFORMAT format = decompress ? D3DFMT_A8R8G8B8 : tfi.m_fmt; - uint8_t bpp = decompress ? 32 : tfi.m_bpp; + uint8_t bpp = getBitsPerPixel(TextureFormat::Enum(m_textureFormat) ); + if (convert) + { + m_textureFormat = (uint8_t)TextureFormat::BGRA8; + bpp = 32; + } + + D3DFORMAT format = s_textureFormat[m_textureFormat].m_fmt; if (imageContainer.m_cubeMap) { @@ -1543,167 +1549,82 @@ namespace bgfx createTexture(imageContainer.m_width, imageContainer.m_height, imageContainer.m_numMips, format); } - if (decompress - || TextureFormat::Unknown < imageContainer.m_type) + // For BC4 and B5 in DX9 LockRect returns wrong number of + // bytes. If actual mip size is used it causes memory corruption. + // http://www.aras-p.info/texts/D3D9GPUHacks.html#3dc + const bool useMipSize = true + && imageContainer.m_format != TextureFormat::BC4 + && imageContainer.m_format != TextureFormat::BC5 + ; + + const bool compressed = TextureFormat::Unknown > m_requestedFormat; + const uint32_t min = compressed ? 4 : 1; + + for (uint8_t side = 0, numSides = imageContainer.m_cubeMap ? 6 : 1; side < numSides; ++side) { - for (uint8_t side = 0, numSides = imageContainer.m_cubeMap ? 6 : 1; side < numSides; ++side) + uint32_t width = imageContainer.m_width; + uint32_t height = imageContainer.m_height; + uint32_t depth = imageContainer.m_depth; + uint32_t mipWidth = imageContainer.m_width; + uint32_t mipHeight = imageContainer.m_height; + + for (uint32_t lod = 0, num = imageContainer.m_numMips; lod < num; ++lod) { - uint32_t width = imageContainer.m_width; - uint32_t height = imageContainer.m_height; - uint32_t depth = imageContainer.m_depth; + width = bx::uint32_max(1, width); + height = bx::uint32_max(1, height); + depth = bx::uint32_max(1, depth); + mipWidth = bx::uint32_max(min, mipWidth); + mipHeight = bx::uint32_max(min, mipHeight); + uint32_t mipSize = width*height*depth*bpp/8; - for (uint32_t lod = 0, num = imageContainer.m_numMips; lod < num; ++lod) + ImageMip mip; + if (imageGetRawData(imageContainer, 0, lod, _mem->data, _mem->size, mip) ) { - width = bx::uint32_max(1, width); - height = bx::uint32_max(1, height); - depth = bx::uint32_max(1, depth); + uint32_t pitch; + uint32_t slicePitch; + uint8_t* bits = lock(side, lod, pitch, slicePitch); - Mip mip; - if (imageGetRawData(imageContainer, side, lod, _mem->data, _mem->size, mip) ) + if (convert) { - uint32_t pitch; - uint32_t slicePitch; - uint8_t* bits = lock(side, lod, pitch, slicePitch); - - if (width != mip.m_width - || height != mip.m_height) + if (width != mipWidth + || height != mipHeight) { - uint32_t srcpitch = mip.m_width*bpp/8; + uint32_t srcpitch = mipWidth*bpp/8; - uint8_t* temp = (uint8_t*)g_realloc(NULL, srcpitch*mip.m_height); - mip.decode(temp); + uint8_t* temp = (uint8_t*)g_realloc(NULL, srcpitch*mipHeight); + imageDecodeToBgra8(temp, mip.m_data, mip.m_width, mip.m_height, mip.m_format); uint32_t dstpitch = pitch; for (uint32_t yy = 0; yy < height; ++yy) { uint8_t* src = &temp[yy*srcpitch]; uint8_t* dst = &bits[yy*dstpitch]; - memcpy(dst, src, srcpitch); + memcpy(dst, src, dstpitch); } g_free(temp); } else { - mip.decode(bits); + imageDecodeToBgra8(bits, mip.m_data, mip.m_width, mip.m_height, mip.m_format); } - - unlock(side, lod); } - - width >>= 1; - height >>= 1; - depth >>= 1; - } - } - } - else - { - // For BC4 and B5 in DX9 LockRect returns wrong number of - // bytes. If actual mip size is used it causes memory corruption. - // http://www.aras-p.info/texts/D3D9GPUHacks.html#3dc - bool useMipSize = true - && imageContainer.m_type != TextureFormat::BC4 - && imageContainer.m_type != TextureFormat::BC5 - ; - - for (uint8_t side = 0, numSides = imageContainer.m_cubeMap ? 6 : 1; side < numSides; ++side) - { - uint32_t width = imageContainer.m_width; - uint32_t height = imageContainer.m_height; - uint32_t depth = imageContainer.m_depth; - - for (uint32_t lod = 0, num = imageContainer.m_numMips; lod < num; ++lod) - { - width = bx::uint32_max(1, width); - height = bx::uint32_max(1, height); - depth = bx::uint32_max(1, depth); - - Mip mip; - if (imageGetRawData(imageContainer, 0, lod, _mem->data, _mem->size, mip) ) + else { - uint32_t pitch; - uint32_t slicePitch; - uint8_t* dst = lock(side, lod, pitch, slicePitch); - - uint32_t size = useMipSize ? mip.m_size : width*height*depth*bpp/8; - - memcpy(dst, mip.m_data, size); - - unlock(side, lod); + uint32_t size = useMipSize ? mip.m_size : mipSize; + memcpy(bits, mip.m_data, size); } - width >>= 1; - height >>= 1; - depth >>= 1; - } - } - } - } - else - { - bx::MemoryReader reader(_mem->data, _mem->size); - - uint32_t magic; - bx::read(&reader, magic); - - if (BGFX_CHUNK_MAGIC_TEX == magic) - { - TextureCreate tc; - bx::read(&reader, tc); - m_format = (TextureFormat::Enum)tc.m_format; - - if (tc.m_cubeMap) - { - createCubeTexture(tc.m_width, tc.m_numMips, s_textureFormat[tc.m_format].m_fmt); - } - else if (tc.m_depth > 1) - { - createVolumeTexture(tc.m_width, tc.m_height, tc.m_depth, tc.m_numMips, s_textureFormat[tc.m_format].m_fmt); - } - else - { - createTexture(tc.m_width, tc.m_height, tc.m_numMips, s_textureFormat[tc.m_format].m_fmt); - } - - if (NULL != tc.m_mem) - { - uint32_t bpp = s_textureFormat[tc.m_format].m_bpp; - uint8_t* data = tc.m_mem->data; - - for (uint8_t side = 0, numSides = tc.m_cubeMap ? 6 : 1; side < numSides; ++side) - { - uint32_t width = tc.m_width; - uint32_t height = tc.m_height; - uint32_t depth = tc.m_depth; - - for (uint32_t lod = 0, num = tc.m_numMips; lod < num; ++lod) - { - width = bx::uint32_max(1, width); - height = bx::uint32_max(1, height); - depth = bx::uint32_max(1, depth); - - uint32_t pitch; - uint32_t slicePitch; - uint8_t* dst = lock(side, lod, pitch, slicePitch); - uint32_t len = width*height*bpp/8; - memcpy(dst, data, len); - data += len; - unlock(side, lod); - - width >>= 1; - height >>= 1; - depth >>= 1; - } + unlock(side, lod); } - release(tc.m_mem); + width >>= 1; + height >>= 1; + depth >>= 1; + mipWidth >>= 1; + mipHeight >>= 1; } } - else - { - // - } } } @@ -1717,25 +1638,42 @@ namespace bgfx void Texture::update(uint8_t _side, uint8_t _mip, const Rect& _rect, uint16_t _z, uint16_t _depth, const Memory* _mem) { - uint32_t bpp = s_textureFormat[m_format].m_bpp; + uint32_t bpp = getBitsPerPixel(TextureFormat::Enum(m_textureFormat) ); uint32_t srcpitch = _rect.m_width*bpp/8; uint32_t dstpitch = s_renderCtx.m_updateTexturePitch; uint8_t* bits = s_renderCtx.m_updateTextureBits + _rect.m_y*dstpitch + _rect.m_x*bpp/8; + const bool convert = m_textureFormat != m_requestedFormat; + + uint8_t* data = _mem->data; + uint8_t* temp = NULL; + + if (convert) + { + uint8_t* temp = (uint8_t*)g_realloc(NULL, srcpitch*_rect.m_height); + imageDecodeToBgra8(temp, data, _rect.m_width, _rect.m_height, m_requestedFormat); + data = temp; + } + if (srcpitch == dstpitch) { - memcpy(bits, _mem->data, srcpitch*_rect.m_height); + memcpy(bits, data, srcpitch*_rect.m_height); } else { for (uint32_t yy = 0, height = _rect.m_height; yy < height; ++yy) { - uint8_t* src = &_mem->data[yy*srcpitch]; + uint8_t* src = &data[yy*srcpitch]; uint8_t* dst = &bits[yy*dstpitch]; memcpy(dst, src, srcpitch); } } + if (NULL != temp) + { + g_free(temp); + } + if (0 == _mip) { dirty(_side, _rect, _z, _depth); diff --git a/src/renderer_d3d9.h b/src/renderer_d3d9.h index 6e549c93a..f5cceec72 100644 --- a/src/renderer_d3d9.h +++ b/src/renderer_d3d9.h @@ -320,8 +320,9 @@ namespace bgfx }; uint32_t m_flags; - TextureFormat::Enum m_format; - Enum m_type; + uint8_t m_type; + uint8_t m_requestedFormat; + uint8_t m_textureFormat; }; struct RenderTarget diff --git a/src/renderer_gl.cpp b/src/renderer_gl.cpp index b33e8c6ab..d55019da2 100644 --- a/src/renderer_gl.cpp +++ b/src/renderer_gl.cpp @@ -194,31 +194,30 @@ namespace bgfx static TextureFormatInfo s_textureFormat[TextureFormat::Count] = { - { GL_COMPRESSED_RGBA_S3TC_DXT1_EXT, GL_COMPRESSED_RGBA_S3TC_DXT1_EXT, GL_ZERO, false }, - { GL_COMPRESSED_RGBA_S3TC_DXT3_EXT, GL_COMPRESSED_RGBA_S3TC_DXT3_EXT, GL_ZERO, false }, - { GL_COMPRESSED_RGBA_S3TC_DXT5_EXT, GL_COMPRESSED_RGBA_S3TC_DXT5_EXT, GL_ZERO, false }, - { GL_COMPRESSED_LUMINANCE_LATC1_EXT, GL_COMPRESSED_LUMINANCE_LATC1_EXT, GL_ZERO, false }, - { GL_COMPRESSED_LUMINANCE_ALPHA_LATC2_EXT, GL_COMPRESSED_LUMINANCE_ALPHA_LATC2_EXT, GL_ZERO, false }, - { GL_ETC1_RGB8_OES, GL_ETC1_RGB8_OES, GL_ZERO, false }, - { GL_COMPRESSED_RGB8_ETC2, GL_COMPRESSED_RGB8_ETC2, GL_ZERO, false }, - { GL_COMPRESSED_RGBA8_ETC2_EAC, GL_COMPRESSED_RGBA8_ETC2_EAC, GL_ZERO, false }, - { GL_COMPRESSED_RGB8_PUNCHTHROUGH_ALPHA1_ETC2, GL_COMPRESSED_RGB8_PUNCHTHROUGH_ALPHA1_ETC2, GL_ZERO, false }, - { GL_COMPRESSED_RGB_PVRTC_2BPPV1_IMG, GL_COMPRESSED_RGB_PVRTC_2BPPV1_IMG, GL_ZERO, false }, - { GL_COMPRESSED_RGB_PVRTC_4BPPV1_IMG, GL_COMPRESSED_RGB_PVRTC_4BPPV1_IMG, GL_ZERO, false }, - { GL_COMPRESSED_RGBA_PVRTC_2BPPV1_IMG, GL_COMPRESSED_RGBA_PVRTC_2BPPV1_IMG, GL_ZERO, false }, - { GL_COMPRESSED_RGBA_PVRTC_4BPPV1_IMG, GL_COMPRESSED_RGBA_PVRTC_4BPPV1_IMG, GL_ZERO, false }, - { GL_COMPRESSED_RGBA_PVRTC_2BPPV2_IMG, GL_COMPRESSED_RGBA_PVRTC_2BPPV2_IMG, GL_ZERO, false }, - { GL_COMPRESSED_RGBA_PVRTC_4BPPV2_IMG, GL_COMPRESSED_RGBA_PVRTC_4BPPV2_IMG, GL_ZERO, false }, - { GL_ZERO, GL_ZERO, GL_ZERO, true }, - { GL_LUMINANCE, GL_LUMINANCE, GL_UNSIGNED_BYTE, true }, - { GL_RGBA, GL_RGBA, GL_UNSIGNED_BYTE, true }, - { GL_RGBA, GL_RGBA, GL_UNSIGNED_BYTE, true }, - { GL_RGBA16, GL_RGBA, GL_UNSIGNED_BYTE, true }, - { GL_RGBA16F, GL_RGBA, GL_HALF_FLOAT, true }, - { GL_RGB565, GL_RGB, GL_UNSIGNED_SHORT_5_6_5, true }, - { GL_RGBA4, GL_RGBA, GL_UNSIGNED_SHORT_4_4_4_4, true }, - { GL_RGB5_A1, GL_RGBA, GL_UNSIGNED_SHORT_5_5_5_1, true }, - { GL_RGB10_A2, GL_RGBA, GL_UNSIGNED_INT_2_10_10_10_REV, true }, + { GL_COMPRESSED_RGBA_S3TC_DXT1_EXT, GL_COMPRESSED_RGBA_S3TC_DXT1_EXT, GL_ZERO, false }, // BC1 + { GL_COMPRESSED_RGBA_S3TC_DXT3_EXT, GL_COMPRESSED_RGBA_S3TC_DXT3_EXT, GL_ZERO, false }, // BC2 + { GL_COMPRESSED_RGBA_S3TC_DXT5_EXT, GL_COMPRESSED_RGBA_S3TC_DXT5_EXT, GL_ZERO, false }, // BC3 + { GL_COMPRESSED_LUMINANCE_LATC1_EXT, GL_COMPRESSED_LUMINANCE_LATC1_EXT, GL_ZERO, false }, // BC4 + { GL_COMPRESSED_LUMINANCE_ALPHA_LATC2_EXT, GL_COMPRESSED_LUMINANCE_ALPHA_LATC2_EXT, GL_ZERO, false }, // BC5 + { GL_ETC1_RGB8_OES, GL_ETC1_RGB8_OES, GL_ZERO, false }, // ETC1 + { GL_COMPRESSED_RGB8_ETC2, GL_COMPRESSED_RGB8_ETC2, GL_ZERO, false }, // ETC2 + { GL_COMPRESSED_RGBA8_ETC2_EAC, GL_COMPRESSED_RGBA8_ETC2_EAC, GL_ZERO, false }, // ETC2A + { GL_COMPRESSED_RGB8_PUNCHTHROUGH_ALPHA1_ETC2, GL_COMPRESSED_RGB8_PUNCHTHROUGH_ALPHA1_ETC2, GL_ZERO, false }, // ETC2A1 + { GL_COMPRESSED_RGB_PVRTC_2BPPV1_IMG, GL_COMPRESSED_RGB_PVRTC_2BPPV1_IMG, GL_ZERO, false }, // PTC12 + { GL_COMPRESSED_RGB_PVRTC_4BPPV1_IMG, GL_COMPRESSED_RGB_PVRTC_4BPPV1_IMG, GL_ZERO, false }, // PTC14 + { GL_COMPRESSED_RGBA_PVRTC_2BPPV1_IMG, GL_COMPRESSED_RGBA_PVRTC_2BPPV1_IMG, GL_ZERO, false }, // PTC12A + { GL_COMPRESSED_RGBA_PVRTC_4BPPV1_IMG, GL_COMPRESSED_RGBA_PVRTC_4BPPV1_IMG, GL_ZERO, false }, // PTC14A + { GL_COMPRESSED_RGBA_PVRTC_2BPPV2_IMG, GL_COMPRESSED_RGBA_PVRTC_2BPPV2_IMG, GL_ZERO, false }, // PTC22 + { GL_COMPRESSED_RGBA_PVRTC_4BPPV2_IMG, GL_COMPRESSED_RGBA_PVRTC_4BPPV2_IMG, GL_ZERO, false }, // PTC24 + { GL_ZERO, GL_ZERO, GL_ZERO, true }, // Unknown + { GL_LUMINANCE, GL_LUMINANCE, GL_UNSIGNED_BYTE, true }, // L8 + { GL_RGBA, GL_RGBA, GL_UNSIGNED_BYTE, true }, // BGRA8 + { GL_RGBA16, GL_RGBA, GL_UNSIGNED_BYTE, true }, // RGBA16 + { GL_RGBA16F, GL_RGBA, GL_HALF_FLOAT, true }, // RGBA16F + { GL_RGB565, GL_RGB, GL_UNSIGNED_SHORT_5_6_5, true }, // R5G6B5 + { GL_RGBA4, GL_RGBA, GL_UNSIGNED_SHORT_4_4_4_4, true }, // RGBA4 + { GL_RGB5_A1, GL_RGBA, GL_UNSIGNED_SHORT_5_5_5_1, true }, // RGB5A1 + { GL_RGB10_A2, GL_RGBA, GL_UNSIGNED_INT_2_10_10_10_REV, true }, // RGB10A2 }; struct Extension @@ -595,9 +594,7 @@ namespace bgfx GL_CHECK(glBindFramebuffer(GL_FRAMEBUFFER, m_msaaBackBufferFbo) ); } #else - BX_UNUSED(_width); - BX_UNUSED(_height); - BX_UNUSED(_msaa); + BX_UNUSED(_width, _height, _msaa); #endif // BGFX_CONFIG_RENDERER_OPENGL|BGFX_CONFIG_RENDERER_OPENGLES3 } @@ -1323,37 +1320,33 @@ namespace bgfx m_vcref.invalidate(s_renderCtx.m_vaoStateCache); } - static void texImage(GLenum _target, GLint _level, GLint _internalFormat, GLsizei _width, GLsizei _height, GLsizei _depth, GLint _border, GLenum _format, GLenum _type, const GLvoid* _pixels) + static void texImage(GLenum _target, GLint _level, GLint _internalFormat, GLsizei _width, GLsizei _height, GLsizei _depth, GLint _border, GLenum _format, GLenum _type, const GLvoid* _data) { #if BGFX_CONFIG_RENDERER_OPENGL|BGFX_CONFIG_RENDERER_OPENGLES3 if (_target == GL_TEXTURE_3D) { - GL_CHECK(glTexImage3D(_target - , _level - , _internalFormat - , _width - , _height - , _depth - , _border - , _format - , _type - , _pixels - ) ); + GL_CHECK(glTexImage3D(_target, _level, _internalFormat, _width, _height, _depth, _border, _format, _type, _data) ); } else #endif // BGFX_CONFIG_RENDERER_OPENGL|BGFX_CONFIG_RENDERER_OPENGLES3 { BX_UNUSED(_depth); - GL_CHECK(glTexImage2D(_target - , _level - , _internalFormat - , _width - , _height - , _border - , _format - , _type - , _pixels - ) ); + GL_CHECK(glTexImage2D(_target, _level, _internalFormat, _width, _height, _border, _format, _type, _data) ); + } + } + + static void texSubImage(GLenum _target, GLint _level, GLint _xoffset, GLint _yoffset, GLint _zoffset, GLsizei _width, GLsizei _height, GLsizei _depth, GLenum _format, GLenum _type, const GLvoid* _data) + { +#if BGFX_CONFIG_RENDERER_OPENGL|BGFX_CONFIG_RENDERER_OPENGLES3 + if (_target == GL_TEXTURE_3D) + { + GL_CHECK(glTexSubImage3D(_target, _level, _xoffset, _yoffset, _zoffset, _width, _height, _depth, _format, _type, _data) ); + } + else +#endif // BGFX_CONFIG_RENDERER_OPENGL|BGFX_CONFIG_RENDERER_OPENGLES3 + { + BX_UNUSED(_zoffset, _depth); + GL_CHECK(glTexSubImage2D(_target, _level, _xoffset, _yoffset, _width, _height, _format, _type, _data) ); } } @@ -1362,45 +1355,69 @@ namespace bgfx #if BGFX_CONFIG_RENDERER_OPENGL|BGFX_CONFIG_RENDERER_OPENGLES3 if (_target == GL_TEXTURE_3D) { - GL_CHECK(glCompressedTexImage3D(_target - , _level - , _internalformat - , _width - , _height - , _depth - , _border - , _imageSize - , _data - ) ); + GL_CHECK(glCompressedTexImage3D(_target, _level, _internalformat, _width, _height, _depth, _border, _imageSize, _data) ); } else #endif // BGFX_CONFIG_RENDERER_OPENGL|BGFX_CONFIG_RENDERER_OPENGLES3 { BX_UNUSED(_depth); - GL_CHECK(glCompressedTexImage2D(_target - , _level - , _internalformat - , _width - , _height - , _border - , _imageSize - , _data - ) ); + GL_CHECK(glCompressedTexImage2D(_target, _level, _internalformat, _width, _height, _border, _imageSize, _data) ); } } - void Texture::init(GLenum _target, uint8_t _numMips, uint32_t _flags) + static void compressedTexSubImage(GLenum _target, GLint _level, GLint _xoffset, GLint _yoffset, GLint _zoffset, GLsizei _width, GLsizei _height, GLsizei _depth, GLenum _format, GLsizei _imageSize, const GLvoid* _data) + { +#if BGFX_CONFIG_RENDERER_OPENGL|BGFX_CONFIG_RENDERER_OPENGLES3 + if (_target == GL_TEXTURE_3D) + { + GL_CHECK(glCompressedTexSubImage3D(_target, _level, _xoffset, _yoffset, _zoffset, _width, _height, _depth, _format, _imageSize, _data) ); + } + else +#endif // BGFX_CONFIG_RENDERER_OPENGL|BGFX_CONFIG_RENDERER_OPENGLES3 + { + BX_UNUSED(_zoffset, _depth); + GL_CHECK(glCompressedTexSubImage2D(_target, _level, _xoffset, _yoffset, _width, _height, _format, _imageSize, _data) ); + } + } + + void Texture::init(GLenum _target, uint8_t _format, uint8_t _numMips, uint32_t _flags) { m_target = _target; m_numMips = _numMips; m_flags = _flags; m_currentFlags = UINT32_MAX; + m_requestedFormat = _format; + m_textureFormat = _format; GL_CHECK(glGenTextures(1, &m_id) ); BX_CHECK(0 != m_id, "Failed to generate texture id."); GL_CHECK(glBindTexture(_target, m_id) ); setSamplerState(_flags); + + const TextureFormatInfo& tfi = s_textureFormat[_format]; + m_fmt = tfi.m_fmt; + m_type = tfi.m_type; + + const bool compressed = TextureFormat::Unknown > _format; + const bool decompress = !tfi.m_supported && compressed; + + if (decompress) + { + m_textureFormat = (uint8_t)TextureFormat::BGRA8; + const TextureFormatInfo& tfi = s_textureFormat[TextureFormat::BGRA8]; + m_fmt = tfi.m_fmt; + m_type = tfi.m_type; + } + +#if BGFX_CONFIG_RENDERER_OPENGL + if (GL_RGBA == m_fmt + && s_renderCtx.m_textureSwizzleSupport) + { + GLint swizzleMask[] = { GL_BLUE, GL_GREEN, GL_RED, GL_ALPHA }; + GL_CHECK(glTexParameteriv(GL_TEXTURE_2D, GL_TEXTURE_SWIZZLE_RGBA, swizzleMask) ); + } +#endif // BGFX_CONFIG_RENDERER_OPENGL } void Texture::create(const Memory* _mem, uint32_t _flags) @@ -1411,127 +1428,58 @@ namespace bgfx { uint8_t numMips = imageContainer.m_numMips; + GLenum target = GL_TEXTURE_2D; if (imageContainer.m_cubeMap) { - init(GL_TEXTURE_CUBE_MAP, numMips, _flags); + target = GL_TEXTURE_CUBE_MAP; } #if BGFX_CONFIG_RENDERER_OPENGL|BGFX_CONFIG_RENDERER_OPENGLES3 else if (imageContainer.m_depth > 1) { - init(GL_TEXTURE_3D, numMips, _flags); + target = GL_TEXTURE_3D; } #endif // BGFX_CONFIG_RENDERER_OPENGL|BGFX_CONFIG_RENDERER_OPENGLES3 - else + + init(target + , imageContainer.m_format + , numMips + , _flags + ); + + target = GL_TEXTURE_CUBE_MAP == m_target ? GL_TEXTURE_CUBE_MAP_POSITIVE_X : m_target; + + const GLenum internalFmt = s_textureFormat[m_textureFormat].m_internalFmt; + + const bool swizzle = GL_RGBA == internalFmt; + const bool convert = m_textureFormat != m_requestedFormat; + const bool compressed = TextureFormat::Unknown > m_textureFormat; + const uint32_t min = convert && compressed ? 4 : 1; + + uint8_t* temp = NULL; + if (convert || swizzle) { - init(GL_TEXTURE_2D, numMips, _flags); + temp = (uint8_t*)g_realloc(NULL, imageContainer.m_width*imageContainer.m_height*4); } - const TextureFormatInfo& tfi = s_textureFormat[imageContainer.m_type]; - GLenum internalFmt = tfi.m_internalFmt; - m_fmt = tfi.m_fmt; - m_type = tfi.m_type; - - GLenum target = m_target; - if (imageContainer.m_cubeMap) + for (uint8_t side = 0, numSides = imageContainer.m_cubeMap ? 6 : 1; side < numSides; ++side) { - target = GL_TEXTURE_CUBE_MAP_POSITIVE_X; - } + uint32_t width = imageContainer.m_width; + uint32_t height = imageContainer.m_height; + uint32_t depth = imageContainer.m_depth; - if (!tfi.m_supported - || TextureFormat::Unknown < imageContainer.m_type) - { - TextureFormat::Enum textureFormat = imageContainer.m_type; - bool decompress = TextureFormat::Unknown > textureFormat; - uint32_t bpp = getBitsPerPixel(imageContainer.m_type); - - if (decompress) + for (uint32_t lod = 0, num = numMips; lod < num; ++lod) { - textureFormat = TextureFormat::BGRA8; - const TextureFormatInfo& tfi = s_textureFormat[textureFormat]; - internalFmt = tfi.m_internalFmt; - m_fmt = tfi.m_fmt; - m_type = tfi.m_type; - bpp = getBitsPerPixel(textureFormat); - } + width = bx::uint32_max(min, width); + height = bx::uint32_max(min, height); + depth = bx::uint32_max(1, depth); - bool swizzle = GL_RGBA == m_fmt; - -#if BGFX_CONFIG_RENDERER_OPENGL - if (swizzle - && s_renderCtx.m_textureSwizzleSupport) - { - swizzle = false; - GLint swizzleMask[] = { GL_BLUE, GL_GREEN, GL_RED, GL_ALPHA }; - GL_CHECK(glTexParameteriv(GL_TEXTURE_2D, GL_TEXTURE_SWIZZLE_RGBA, swizzleMask) ); - } -#endif // BGFX_CONFIG_RENDERER_OPENGL - - uint8_t* bits = (uint8_t*)g_realloc(NULL, imageContainer.m_width*imageContainer.m_height*bpp/8); - - for (uint8_t side = 0, numSides = imageContainer.m_cubeMap ? 6 : 1; side < numSides; ++side) - { - uint32_t width = imageContainer.m_width; - uint32_t height = imageContainer.m_height; - uint32_t depth = imageContainer.m_depth; - - for (uint32_t lod = 0, num = numMips; lod < num; ++lod) + ImageMip mip; + if (imageGetRawData(imageContainer, side, lod, _mem->data, _mem->size, mip) ) { - width = bx::uint32_max(1, width); - height = bx::uint32_max(1, height); - depth = bx::uint32_max(1, depth); - - Mip mip; - if (imageGetRawData(imageContainer, side, lod, _mem->data, _mem->size, mip) ) - { - mip.decode(bits); - - if (swizzle) - { - imageSwizzleBgra8(width, height, bits, bits); - } - - texImage(target+side - , lod - , internalFmt - , width - , height - , depth - , 0 - , m_fmt - , m_type - , bits - ); - } - - width >>= 1; - height >>= 1; - depth >>= 1; - } - } - - g_free(bits); - } - else - { - m_compressed = true; - - for (uint8_t side = 0, numSides = imageContainer.m_cubeMap ? 6 : 1; side < numSides; ++side) - { - uint32_t width = imageContainer.m_width; - uint32_t height = imageContainer.m_height; - uint32_t depth = imageContainer.m_depth; - - for (uint32_t ii = 0, num = numMips; ii < num; ++ii) - { - width = bx::uint32_max(1, width); - height = bx::uint32_max(1, height); - depth = bx::uint32_max(1, depth); - - Mip mip; - if (imageGetRawData(imageContainer, side, ii, _mem->data, _mem->size, mip) ) + if (compressed) { compressedTexImage(target+side - , ii + , lod , internalFmt , width , height @@ -1541,102 +1489,20 @@ namespace bgfx , mip.m_data ); } - - width >>= 1; - height >>= 1; - depth >>= 1; - } - } - } - } - else - { - bx::MemoryReader reader(_mem->data, _mem->size); - - uint32_t magic; - bx::read(&reader, magic); - - if (BGFX_CHUNK_MAGIC_TEX == magic) - { - TextureCreate tc; - bx::read(&reader, tc); - - uint8_t numMips = tc.m_numMips; - - if (tc.m_cubeMap) - { - init(GL_TEXTURE_CUBE_MAP, numMips, _flags); - } -#if BGFX_CONFIG_RENDERER_OPENGL|BGFX_CONFIG_RENDERER_OPENGLES3 - else if (tc.m_depth > 1) - { - init(GL_TEXTURE_3D, numMips, _flags); - } -#endif // BGFX_CONFIG_RENDERER_OPENGL|BGFX_CONFIG_RENDERER_OPENGLES3 - else - { - init(GL_TEXTURE_2D, numMips, _flags); - } - - const TextureFormatInfo& tfi = s_textureFormat[tc.m_format]; - GLenum internalFmt = tfi.m_internalFmt; - m_fmt = tfi.m_fmt; - m_type = tfi.m_type; - m_compressed = tc.m_format < TextureFormat::Unknown; - - GLenum target = m_target; - if (tc.m_cubeMap) - { - target = GL_TEXTURE_CUBE_MAP_POSITIVE_X; - } - - uint32_t bpp = getBitsPerPixel(TextureFormat::Enum(tc.m_format) ); - uint8_t* data = NULL != tc.m_mem ? tc.m_mem->data : NULL; - uint32_t min = m_compressed ? 4 : 1; - bool swizzle = GL_RGBA == m_fmt; - -#if BGFX_CONFIG_RENDERER_OPENGL - if (swizzle - && s_renderCtx.m_textureSwizzleSupport) - { - swizzle = false; - GLint swizzleMask[] = { GL_BLUE, GL_GREEN, GL_RED, GL_ALPHA }; - GL_CHECK(glTexParameteriv(GL_TEXTURE_2D, GL_TEXTURE_SWIZZLE_RGBA, swizzleMask) ); - } -#endif // BGFX_CONFIG_RENDERER_OPENGL - - for (uint8_t side = 0, numSides = tc.m_cubeMap ? 6 : 1; side < numSides; ++side) - { - uint32_t width = tc.m_width; - uint32_t height = tc.m_height; - uint32_t depth = tc.m_depth; - - for (uint32_t lod = 0, num = numMips; lod < num; ++lod) - { - width = bx::uint32_max(width, min); - height = bx::uint32_max(height, min); - depth = bx::uint32_max(1, depth); - uint32_t size = width*height*bpp/8; - - if (m_compressed) - { - compressedTexImage(target+side - , lod - , internalFmt - , width - , height - , depth - , 0 - , size - , data - ); - } else { - if (NULL != data - && swizzle) + const uint8_t* data = mip.m_data; + + if (convert) { - imageSwizzleBgra8(width, height, data, data); + imageDecodeToBgra8(temp, mip.m_data, mip.m_width, mip.m_height, mip.m_format); + data = temp; + } + + if (swizzle) + { + imageSwizzleBgra8(width, height, data, temp); + data = temp; } texImage(target+side @@ -1651,26 +1517,52 @@ namespace bgfx , data ); } - - if (NULL != data) - { - data += size; - } - - width >>= 1; - height >>= 1; - depth >>= 1; } - } + else + { + if (compressed) + { + uint32_t size = bx::uint32_max(1, (width + 3)>>2) + * bx::uint32_max(1, (height + 3)>>2) + * 4*4*getBitsPerPixel(TextureFormat::Enum(m_textureFormat) )/8 + ; - if (NULL != tc.m_mem) - { - release(tc.m_mem); + compressedTexImage(target+side + , lod + , internalFmt + , width + , height + , depth + , 0 + , size + , NULL + ); + } + else + { + texImage(target+side + , lod + , internalFmt + , width + , height + , depth + , 0 + , m_fmt + , m_type + , NULL + ); + } + } + + width >>= 1; + height >>= 1; + depth >>= 1; } } - else + + if (NULL != temp) { - // + g_free(temp); } } @@ -1761,106 +1653,74 @@ namespace bgfx void Texture::update(uint8_t _side, uint8_t _mip, const Rect& _rect, uint16_t _z, uint16_t _depth, const Memory* _mem) { - BX_UNUSED(_z); - BX_UNUSED(_depth); + BX_UNUSED(_z, _depth); GL_CHECK(glBindTexture(m_target, m_id) ); GL_CHECK(glPixelStorei(GL_UNPACK_ALIGNMENT, 1) ); - switch (m_target) + GLenum target = GL_TEXTURE_CUBE_MAP == m_target ? GL_TEXTURE_CUBE_MAP_POSITIVE_X : m_target; + + const bool swizzle = GL_RGBA == m_fmt; + const bool convert = m_textureFormat != m_requestedFormat; + const bool compressed = TextureFormat::Unknown > m_textureFormat; + + uint32_t width = _rect.m_width; + uint32_t height = _rect.m_height; + + uint8_t* temp = NULL; + if (convert || swizzle) { - case GL_TEXTURE_2D: - if (m_compressed) - { - GL_CHECK(glCompressedTexSubImage2D(m_target - , _mip - , _rect.m_x - , _rect.m_y - , _rect.m_width - , _rect.m_height - , m_fmt - , _mem->size - , _mem->data - ) ); - } - else - { - GL_CHECK(glTexSubImage2D(m_target - , _mip - , _rect.m_x - , _rect.m_y - , _rect.m_width - , _rect.m_height - , m_fmt - , m_type - , _mem->data - ) ); - } - break; + temp = (uint8_t*)g_realloc(NULL, width*height*4); + } - case GL_TEXTURE_CUBE_MAP: - if (m_compressed) - { - GL_CHECK(glCompressedTexSubImage2D(GL_TEXTURE_CUBE_MAP_POSITIVE_X+_side - , _mip - , _rect.m_x - , _rect.m_y - , _rect.m_width - , _rect.m_height - , m_fmt - , _mem->size - , _mem->data - ) ); - } - else - { - GL_CHECK(glTexSubImage2D(GL_TEXTURE_CUBE_MAP_POSITIVE_X+_side - , _mip - , _rect.m_x - , _rect.m_y - , _rect.m_width - , _rect.m_height - , m_fmt - , m_type - , _mem->data - ) ); - } - break; + if (compressed) + { + GL_CHECK(compressedTexSubImage(target+_side + , _mip + , _rect.m_x + , _rect.m_y + , _z + , _rect.m_width + , _rect.m_height + , _depth + , m_fmt + , _mem->size + , _mem->data + ) ); + } + else + { + const uint8_t* data = _mem->data; -#if BGFX_CONFIG_RENDERER_OPENGL|BGFX_CONFIG_RENDERER_OPENGLES3 - case GL_TEXTURE_3D: - if (m_compressed) + if (convert) { - GL_CHECK(glCompressedTexSubImage3D(m_target - , _mip - , _rect.m_x - , _rect.m_y - , _z - , _rect.m_width - , _rect.m_height - , _depth - , m_fmt - , _mem->size - , _mem->data - ) ); + imageDecodeToBgra8(temp, data, width, height, m_requestedFormat); + data = temp; } - else + + if (swizzle) { - GL_CHECK(glTexSubImage3D(m_target - , _mip - , _rect.m_x - , _rect.m_y - , _z - , _rect.m_width - , _rect.m_height - , _depth - , m_fmt - , m_type - , _mem->data - ) ); + imageSwizzleBgra8(width, height, data, temp); + data = temp; } - break; -#endif // BGFX_CONFIG_RENDERER_OPENGL|BGFX_CONFIG_RENDERER_OPENGLES3 + + GL_CHECK(texSubImage(target+_side + , _mip + , _rect.m_x + , _rect.m_y + , _z + , _rect.m_width + , _rect.m_height + , _depth + , m_fmt + , m_type + , data + ) ); + } + + if (NULL != temp) + { + g_free(temp); } } @@ -2458,6 +2318,7 @@ namespace bgfx ^ (uint64_t(getGLStringHash(GL_VERSION ) )<<16) ; +#if BGFX_CONFIG_RENDERER_USE_EXTENSIONS const char* extensions = (const char*)glGetString(GL_EXTENSIONS); glGetError(); // ignore error if glGetString returns NULL. if (NULL != extensions) @@ -2514,6 +2375,7 @@ namespace bgfx } } } +#endif // BGFX_CONFIG_RENDERER_OPENGL_USE_EXTENSIONS bool bc123Supported = s_extension[Extension::EXT_texture_compression_s3tc].m_supported; s_textureFormat[TextureFormat::BC1].m_supported = bc123Supported || s_extension[Extension::EXT_texture_compression_dxt1].m_supported; @@ -2596,7 +2458,6 @@ namespace bgfx s_renderCtx.m_readPixelsFmt = GL_BGRA_EXT; #endif // BGFX_CONFIG_RENDERER_OPENGL - s_textureFormat[TextureFormat::BGRX8].m_fmt = GL_BGRA_EXT; s_textureFormat[TextureFormat::BGRA8].m_fmt = GL_BGRA_EXT; // Mixing GLES and GL extensions here. OpenGL EXT_bgra wants @@ -2609,7 +2470,6 @@ namespace bgfx // https://www.opengl.org/registry/specs/EXT/bgra.txt if (!s_extension[Extension::EXT_bgra].m_supported) { - s_textureFormat[TextureFormat::BGRX8].m_internalFmt = GL_BGRA_EXT; s_textureFormat[TextureFormat::BGRA8].m_internalFmt = GL_BGRA_EXT; } } diff --git a/src/renderer_gl.h b/src/renderer_gl.h index 378f07e95..2d09f1f6f 100755 --- a/src/renderer_gl.h +++ b/src/renderer_gl.h @@ -558,11 +558,10 @@ namespace bgfx , m_flags(0) , m_currentFlags(UINT32_MAX) , m_numMips(0) - , m_compressed(false) { } - void init(GLenum _target, uint8_t _numMips, uint32_t _flags); + void init(GLenum _target, uint8_t _format, uint8_t _numMips, uint32_t _flags); void create(const Memory* _mem, uint32_t _flags); void createColor(uint32_t _colorFormat, uint32_t _width, uint32_t _height, GLenum _min, GLenum _mag); void createDepth(uint32_t _width, uint32_t _height); @@ -578,7 +577,8 @@ namespace bgfx uint32_t m_flags; uint32_t m_currentFlags; uint8_t m_numMips; - bool m_compressed; + uint8_t m_requestedFormat; + uint8_t m_textureFormat; }; struct Shader diff --git a/src/renderer_null.cpp b/src/renderer_null.cpp index 2e28a1fe1..36951d441 100644 --- a/src/renderer_null.cpp +++ b/src/renderer_null.cpp @@ -105,23 +105,8 @@ namespace bgfx { } - void Context::rendererCreateTexture(TextureHandle /*_handle*/, Memory* _mem, uint32_t /*_flags*/) + void Context::rendererCreateTexture(TextureHandle /*_handle*/, Memory* /*_mem*/, uint32_t /*_flags*/) { - bx::MemoryReader reader(_mem->data, _mem->size); - - uint32_t magic; - bx::read(&reader, magic); - - if (BGFX_CHUNK_MAGIC_TEX == magic) - { - TextureCreate tc; - bx::read(&reader, tc); - - if (NULL != tc.m_mem) - { - release(tc.m_mem); - } - } } void Context::rendererUpdateTextureBegin(TextureHandle /*_handle*/, uint8_t /*_side*/, uint8_t /*_mip*/) diff --git a/tools/texturec/texturec.cpp b/tools/texturec/texturec.cpp index f5e861dbe..c2fff6130 100644 --- a/tools/texturec/texturec.cpp +++ b/tools/texturec/texturec.cpp @@ -108,7 +108,7 @@ int main(int _argc, const char* _argv[]) bool decompress = cmdLine.hasArg('d'); if (decompress - || 0 == imageContainer.m_type) + || 0 == imageContainer.m_format) { for (uint8_t side = 0, numSides = imageContainer.m_cubeMap ? 6 : 1; side < numSides; ++side) { @@ -120,7 +120,7 @@ int main(int _argc, const char* _argv[]) width = bx::uint32_max(1, width); height = bx::uint32_max(1, height); - Mip mip; + ImageMip mip; if (imageGetRawData(imageContainer, side, lod, mem->data, mem->size, mip) ) { uint32_t dstpitch = width*4; @@ -130,7 +130,7 @@ int main(int _argc, const char* _argv[]) || height != mip.m_height) { uint8_t* temp = (uint8_t*)realloc(NULL, mip.m_width*mip.m_height*4); - mip.decode(temp); + imageDecodeToBgra8(temp, mip.m_data, mip.m_width, mip.m_height, mip.m_format); uint32_t srcpitch = mip.m_width*4; for (uint32_t yy = 0; yy < height; ++yy) @@ -150,7 +150,7 @@ int main(int _argc, const char* _argv[]) } else { - mip.decode(bits); + imageDecodeToBgra8(bits, mip.m_data, mip.m_width, mip.m_height, mip.m_format); } char filePath[256]; @@ -169,7 +169,7 @@ int main(int _argc, const char* _argv[]) { for (uint32_t lod = 0, num = imageContainer.m_numMips; lod < num; ++lod) { - Mip mip; + ImageMip mip; if (imageGetRawData(imageContainer, 0, lod, mem->data, mem->size, mip) ) { char filePath[256];