Fixed texture update when requested texture format doesn't match internal texture format, and simplified texture creation.

This commit is contained in:
bkaradzic 2013-09-08 21:03:03 -07:00
parent 82256fc34d
commit 488483a945
13 changed files with 697 additions and 1027 deletions

View file

@ -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.

View file

@ -16,20 +16,9 @@
#include <string.h>
#include <alloca.h>
// 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;

View file

@ -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

View file

@ -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;
}

View file

@ -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

View file

@ -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)

View file

@ -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;
};

View file

@ -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);

View file

@ -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

View file

@ -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;
}
}

View file

@ -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

View file

@ -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*/)

View file

@ -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];