mirror of
https://github.com/scratchfoundation/bgfx.git
synced 2025-03-25 06:11:09 -04:00
Added ETC1 texture support. Added KTX file format support.
This commit is contained in:
parent
9537208d2f
commit
19dd4020f4
13 changed files with 1185 additions and 875 deletions
|
@ -307,6 +307,7 @@ namespace bgfx
|
|||
BC3, // DXT5
|
||||
BC4, // LATC1/ATI1
|
||||
BC5, // LATC2/ATI2
|
||||
ETC1,
|
||||
Unknown,
|
||||
L8,
|
||||
BGRX8,
|
||||
|
|
|
@ -14,7 +14,7 @@ project "texturec"
|
|||
}
|
||||
|
||||
files {
|
||||
BGFX_DIR .. "src/dds.*",
|
||||
BGFX_DIR .. "src/image.*",
|
||||
BGFX_DIR .. "tools/texturec/**.cpp",
|
||||
BGFX_DIR .. "tools/texturec/**.h",
|
||||
}
|
||||
|
|
|
@ -1000,6 +1000,7 @@ namespace bgfx
|
|||
8, // BC3
|
||||
4, // BC4
|
||||
8, // BC5
|
||||
4, // ETC1
|
||||
0, // Unknown
|
||||
8, // L8
|
||||
32, // BGRX8
|
||||
|
@ -1012,6 +1013,11 @@ namespace bgfx
|
|||
32, // RGB10A2
|
||||
};
|
||||
|
||||
uint32_t getBitsPerPixel(TextureFormat::Enum _format)
|
||||
{
|
||||
return s_bitsPerPixel[_format];
|
||||
}
|
||||
|
||||
void calcTextureSize(TextureInfo& _info, uint16_t _width, uint16_t _height, uint16_t _depth, uint8_t _numMips, TextureFormat::Enum _format)
|
||||
{
|
||||
_width = bx::uint32_max(1, _width);
|
||||
|
|
20
src/bgfx_p.h
20
src/bgfx_p.h
|
@ -72,7 +72,7 @@ namespace bgfx
|
|||
#include <bx/string.h>
|
||||
#include <bx/os.h>
|
||||
|
||||
#include "dds.h"
|
||||
#include "image.h"
|
||||
|
||||
#define BGFX_CHUNK_MAGIC_FSH BX_MAKEFOURCC('F', 'S', 'H', 0x1)
|
||||
#define BGFX_CHUNK_MAGIC_TEX BX_MAKEFOURCC('T', 'E', 'X', 0x0)
|
||||
|
@ -230,7 +230,7 @@ namespace bgfx
|
|||
extern FreeFn g_free;
|
||||
|
||||
void release(const Memory* _mem);
|
||||
void imageWriteTga(bx::WriterI* _writer, uint32_t _width, uint32_t _height, uint32_t _srcPitch, const void* _src, bool _grayscale = false, bool _yflip = false);
|
||||
uint32_t getBitsPerPixel(TextureFormat::Enum _format);
|
||||
const char* getAttribName(Attrib::Enum _attr);
|
||||
bool renderFrame();
|
||||
|
||||
|
@ -275,7 +275,7 @@ namespace bgfx
|
|||
return _offset+align-(_offset%align);
|
||||
}
|
||||
|
||||
BX_FORCE_INLINE uint32_t castfu(float _value)
|
||||
inline uint32_t castfu(float _value)
|
||||
{
|
||||
union { float fl; uint32_t ui; } un;
|
||||
un.fl = _value;
|
||||
|
@ -2138,15 +2138,15 @@ namespace bgfx
|
|||
{
|
||||
if (NULL != _info)
|
||||
{
|
||||
Dds dds;
|
||||
if (parseDds(dds, _mem) )
|
||||
ImageContainer imageContainer;
|
||||
if (imageParse(imageContainer, _mem->data, _mem->size) )
|
||||
{
|
||||
calcTextureSize(*_info
|
||||
, (uint16_t)dds.m_width
|
||||
, (uint16_t)dds.m_height
|
||||
, (uint16_t)dds.m_depth
|
||||
, dds.m_numMips
|
||||
, dds.m_type
|
||||
, (uint16_t)imageContainer.m_width
|
||||
, (uint16_t)imageContainer.m_height
|
||||
, (uint16_t)imageContainer.m_depth
|
||||
, imageContainer.m_numMips
|
||||
, imageContainer.m_type
|
||||
);
|
||||
}
|
||||
else
|
||||
|
|
619
src/dds.cpp
619
src/dds.cpp
|
@ -1,619 +0,0 @@
|
|||
/*
|
||||
* Copyright 2011-2013 Branimir Karadzic. All rights reserved.
|
||||
* License: http://www.opensource.org/licenses/BSD-2-Clause
|
||||
*/
|
||||
|
||||
#include <math.h> // sqrtf
|
||||
|
||||
#include "bgfx_p.h"
|
||||
#include "dds.h"
|
||||
|
||||
namespace bgfx
|
||||
{
|
||||
|
||||
#define DDS_MAGIC BX_MAKEFOURCC('D','D','S',' ')
|
||||
#define DDS_HEADER_SIZE 124
|
||||
#define DDS_IMAGE_DATA_OFFSET (DDS_HEADER_SIZE + 4)
|
||||
|
||||
#define DDS_DXT1 BX_MAKEFOURCC('D', 'X', 'T', '1')
|
||||
#define DDS_DXT2 BX_MAKEFOURCC('D', 'X', 'T', '2')
|
||||
#define DDS_DXT3 BX_MAKEFOURCC('D', 'X', 'T', '3')
|
||||
#define DDS_DXT4 BX_MAKEFOURCC('D', 'X', 'T', '4')
|
||||
#define DDS_DXT5 BX_MAKEFOURCC('D', 'X', 'T', '5')
|
||||
#define DDS_ATI1 BX_MAKEFOURCC('A', 'T', 'I', '1')
|
||||
#define DDS_BC4U BX_MAKEFOURCC('B', 'C', '4', 'U')
|
||||
#define DDS_ATI2 BX_MAKEFOURCC('A', 'T', 'I', '2')
|
||||
#define DDS_BC5U BX_MAKEFOURCC('B', 'C', '5', 'U')
|
||||
|
||||
#define D3DFMT_A16B16G16R16 36
|
||||
#define D3DFMT_A16B16G16R16F 113
|
||||
|
||||
#define DDSD_CAPS 0x00000001
|
||||
#define DDSD_HEIGHT 0x00000002
|
||||
#define DDSD_WIDTH 0x00000004
|
||||
#define DDSD_PITCH 0x00000008
|
||||
#define DDSD_PIXELFORMAT 0x00001000
|
||||
#define DDSD_MIPMAPCOUNT 0x00020000
|
||||
#define DDSD_LINEARSIZE 0x00080000
|
||||
#define DDSD_DEPTH 0x00800000
|
||||
|
||||
#define DDPF_ALPHAPIXELS 0x00000001
|
||||
#define DDPF_ALPHA 0x00000002
|
||||
#define DDPF_FOURCC 0x00000004
|
||||
#define DDPF_INDEXED 0x00000020
|
||||
#define DDPF_RGB 0x00000040
|
||||
#define DDPF_YUV 0x00000200
|
||||
#define DDPF_LUMINANCE 0x00020000
|
||||
|
||||
#define DDSCAPS_COMPLEX 0x00000008
|
||||
#define DDSCAPS_TEXTURE 0x00001000
|
||||
#define DDSCAPS_MIPMAP 0x00400000
|
||||
|
||||
#define DDSCAPS2_CUBEMAP 0x00000200
|
||||
#define DDSCAPS2_CUBEMAP_POSITIVEX 0x00000400
|
||||
#define DDSCAPS2_CUBEMAP_NEGATIVEX 0x00000800
|
||||
#define DDSCAPS2_CUBEMAP_POSITIVEY 0x00001000
|
||||
#define DDSCAPS2_CUBEMAP_NEGATIVEY 0x00002000
|
||||
#define DDSCAPS2_CUBEMAP_POSITIVEZ 0x00004000
|
||||
#define DDSCAPS2_CUBEMAP_NEGATIVEZ 0x00008000
|
||||
|
||||
#define DDS_CUBEMAP_ALLFACES (DDSCAPS2_CUBEMAP_POSITIVEX|DDSCAPS2_CUBEMAP_NEGATIVEX \
|
||||
|DDSCAPS2_CUBEMAP_POSITIVEY|DDSCAPS2_CUBEMAP_NEGATIVEY \
|
||||
|DDSCAPS2_CUBEMAP_POSITIVEZ|DDSCAPS2_CUBEMAP_NEGATIVEZ)
|
||||
|
||||
#define DDSCAPS2_VOLUME 0x00200000
|
||||
|
||||
bool isDds(const Memory* _mem)
|
||||
{
|
||||
bx::MemoryReader reader(_mem->data, _mem->size);
|
||||
|
||||
uint32_t magic;
|
||||
bx::read(&reader, magic);
|
||||
|
||||
return DDS_MAGIC == magic;
|
||||
}
|
||||
|
||||
uint32_t bitRangeConvert(uint32_t _in, uint32_t _from, uint32_t _to)
|
||||
{
|
||||
using namespace bx;
|
||||
uint32_t tmp0 = uint32_sll(1, _to);
|
||||
uint32_t tmp1 = uint32_sll(1, _from);
|
||||
uint32_t tmp2 = uint32_dec(tmp0);
|
||||
uint32_t tmp3 = uint32_dec(tmp1);
|
||||
uint32_t tmp4 = uint32_mul(_in, tmp2);
|
||||
uint32_t tmp5 = uint32_add(tmp3, tmp4);
|
||||
uint32_t tmp6 = uint32_srl(tmp5, _from);
|
||||
uint32_t tmp7 = uint32_add(tmp5, tmp6);
|
||||
uint32_t result = uint32_srl(tmp7, _from);
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
void decodeBlockDxt(uint8_t _dst[16*4], const uint8_t _src[8])
|
||||
{
|
||||
uint8_t colors[4*3];
|
||||
|
||||
uint32_t c0 = _src[0] | (_src[1] << 8);
|
||||
colors[0] = bitRangeConvert( (c0>> 0)&0x1f, 5, 8);
|
||||
colors[1] = bitRangeConvert( (c0>> 5)&0x3f, 6, 8);
|
||||
colors[2] = bitRangeConvert( (c0>>11)&0x1f, 5, 8);
|
||||
|
||||
uint32_t c1 = _src[2] | (_src[3] << 8);
|
||||
colors[3] = bitRangeConvert( (c1>> 0)&0x1f, 5, 8);
|
||||
colors[4] = bitRangeConvert( (c1>> 5)&0x3f, 6, 8);
|
||||
colors[5] = bitRangeConvert( (c1>>11)&0x1f, 5, 8);
|
||||
|
||||
colors[6] = (2*colors[0] + colors[3]) / 3;
|
||||
colors[7] = (2*colors[1] + colors[4]) / 3;
|
||||
colors[8] = (2*colors[2] + colors[5]) / 3;
|
||||
|
||||
colors[ 9] = (colors[0] + 2*colors[3]) / 3;
|
||||
colors[10] = (colors[1] + 2*colors[4]) / 3;
|
||||
colors[11] = (colors[2] + 2*colors[5]) / 3;
|
||||
|
||||
for (uint32_t ii = 0, next = 8*4; ii < 16*4; ii += 4, next += 2)
|
||||
{
|
||||
int idx = ( (_src[next>>3] >> (next & 7) ) & 3) * 3;
|
||||
_dst[ii+0] = colors[idx+0];
|
||||
_dst[ii+1] = colors[idx+1];
|
||||
_dst[ii+2] = colors[idx+2];
|
||||
}
|
||||
}
|
||||
|
||||
void decodeBlockDxt1(uint8_t _dst[16*4], const uint8_t _src[8])
|
||||
{
|
||||
uint8_t colors[4*4];
|
||||
|
||||
uint32_t c0 = _src[0] | (_src[1] << 8);
|
||||
colors[0] = bitRangeConvert( (c0>> 0)&0x1f, 5, 8);
|
||||
colors[1] = bitRangeConvert( (c0>> 5)&0x3f, 6, 8);
|
||||
colors[2] = bitRangeConvert( (c0>>11)&0x1f, 5, 8);
|
||||
colors[3] = 255;
|
||||
|
||||
uint32_t c1 = _src[2] | (_src[3] << 8);
|
||||
colors[4] = bitRangeConvert( (c1>> 0)&0x1f, 5, 8);
|
||||
colors[5] = bitRangeConvert( (c1>> 5)&0x3f, 6, 8);
|
||||
colors[6] = bitRangeConvert( (c1>>11)&0x1f, 5, 8);
|
||||
colors[7] = 255;
|
||||
|
||||
if (c0 > c1)
|
||||
{
|
||||
colors[ 8] = (2*colors[0] + colors[4]) / 3;
|
||||
colors[ 9] = (2*colors[1] + colors[5]) / 3;
|
||||
colors[10] = (2*colors[2] + colors[6]) / 3;
|
||||
colors[11] = 255;
|
||||
|
||||
colors[12] = (colors[0] + 2*colors[4]) / 3;
|
||||
colors[13] = (colors[1] + 2*colors[5]) / 3;
|
||||
colors[14] = (colors[2] + 2*colors[6]) / 3;
|
||||
colors[15] = 255;
|
||||
}
|
||||
else
|
||||
{
|
||||
colors[ 8] = (colors[0] + colors[4]) / 2;
|
||||
colors[ 9] = (colors[1] + colors[5]) / 2;
|
||||
colors[10] = (colors[2] + colors[6]) / 2;
|
||||
colors[11] = 255;
|
||||
|
||||
colors[12] = 0;
|
||||
colors[13] = 0;
|
||||
colors[14] = 0;
|
||||
colors[15] = 0;
|
||||
}
|
||||
|
||||
for (uint32_t ii = 0, next = 8*4; ii < 16*4; ii += 4, next += 2)
|
||||
{
|
||||
int idx = ( (_src[next>>3] >> (next & 7) ) & 3) * 4;
|
||||
_dst[ii+0] = colors[idx+0];
|
||||
_dst[ii+1] = colors[idx+1];
|
||||
_dst[ii+2] = colors[idx+2];
|
||||
_dst[ii+3] = colors[idx+3];
|
||||
}
|
||||
}
|
||||
|
||||
void decodeBlockDxt23A(uint8_t _dst[16*4], const uint8_t _src[8])
|
||||
{
|
||||
for (uint32_t ii = 0, next = 0; ii < 16*4; ii += 4, next += 4)
|
||||
{
|
||||
uint32_t c0 = (_src[next>>3] >> (next&7) ) & 0xf;
|
||||
_dst[ii] = bitRangeConvert(c0, 4, 8);
|
||||
}
|
||||
}
|
||||
|
||||
void decodeBlockDxt45A(uint8_t _dst[16*4], const uint8_t _src[8])
|
||||
{
|
||||
uint8_t alpha[8];
|
||||
alpha[0] = _src[0];
|
||||
alpha[1] = _src[1];
|
||||
|
||||
if (alpha[0] > alpha[1])
|
||||
{
|
||||
alpha[2] = (6*alpha[0] + 1*alpha[1]) / 7;
|
||||
alpha[3] = (5*alpha[0] + 2*alpha[1]) / 7;
|
||||
alpha[4] = (4*alpha[0] + 3*alpha[1]) / 7;
|
||||
alpha[5] = (3*alpha[0] + 4*alpha[1]) / 7;
|
||||
alpha[6] = (2*alpha[0] + 5*alpha[1]) / 7;
|
||||
alpha[7] = (1*alpha[0] + 6*alpha[1]) / 7;
|
||||
}
|
||||
else
|
||||
{
|
||||
alpha[2] = (4*alpha[0] + 1*alpha[1]) / 5;
|
||||
alpha[3] = (3*alpha[0] + 2*alpha[1]) / 5;
|
||||
alpha[4] = (2*alpha[0] + 3*alpha[1]) / 5;
|
||||
alpha[5] = (1*alpha[0] + 4*alpha[1]) / 5;
|
||||
alpha[6] = 0;
|
||||
alpha[7] = 255;
|
||||
}
|
||||
|
||||
uint32_t idx0 = _src[2];
|
||||
uint32_t idx1 = _src[5];
|
||||
idx0 |= uint32_t(_src[3])<<8;
|
||||
idx1 |= uint32_t(_src[6])<<8;
|
||||
idx0 |= uint32_t(_src[4])<<16;
|
||||
idx1 |= uint32_t(_src[7])<<16;
|
||||
for (uint32_t ii = 0; ii < 8*4; ii += 4)
|
||||
{
|
||||
_dst[ii] = alpha[idx0&7];
|
||||
_dst[ii+32] = alpha[idx1&7];
|
||||
idx0 >>= 3;
|
||||
idx1 >>= 3;
|
||||
}
|
||||
}
|
||||
|
||||
uint32_t Mip::getDecodedSize() const
|
||||
{
|
||||
return m_width*m_height*4;
|
||||
}
|
||||
|
||||
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;
|
||||
}
|
||||
}
|
||||
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;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
bool parseDds(Dds& _dds, const Memory* _mem)
|
||||
{
|
||||
bx::MemoryReader reader(_mem->data, _mem->size);
|
||||
|
||||
uint32_t magic;
|
||||
bx::read(&reader, magic);
|
||||
|
||||
if (DDS_MAGIC != magic)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
uint32_t headerSize;
|
||||
bx::read(&reader, headerSize);
|
||||
|
||||
if (headerSize < DDS_HEADER_SIZE)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
uint32_t flags;
|
||||
bx::read(&reader, flags);
|
||||
|
||||
if ( (flags & (DDSD_CAPS|DDSD_HEIGHT|DDSD_WIDTH|DDSD_PIXELFORMAT) ) != (DDSD_CAPS|DDSD_HEIGHT|DDSD_WIDTH|DDSD_PIXELFORMAT) )
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
uint32_t height;
|
||||
bx::read(&reader, height);
|
||||
|
||||
uint32_t width;
|
||||
bx::read(&reader, width);
|
||||
|
||||
uint32_t pitch;
|
||||
bx::read(&reader, pitch);
|
||||
|
||||
uint32_t depth;
|
||||
bx::read(&reader, depth);
|
||||
|
||||
uint32_t mips;
|
||||
bx::read(&reader, mips);
|
||||
|
||||
bx::skip(&reader, 44); // reserved
|
||||
bx::skip(&reader, 4); // pixel format size
|
||||
|
||||
uint32_t pixelFlags;
|
||||
bx::read(&reader, pixelFlags);
|
||||
|
||||
uint32_t fourcc;
|
||||
bx::read(&reader, fourcc);
|
||||
|
||||
uint32_t rgbCount;
|
||||
bx::read(&reader, rgbCount);
|
||||
|
||||
uint32_t rbitmask;
|
||||
bx::read(&reader, rbitmask);
|
||||
|
||||
uint32_t gbitmask;
|
||||
bx::read(&reader, gbitmask);
|
||||
|
||||
uint32_t bbitmask;
|
||||
bx::read(&reader, bbitmask);
|
||||
|
||||
uint32_t abitmask;
|
||||
bx::read(&reader, abitmask);
|
||||
|
||||
uint32_t caps[4];
|
||||
bx::read(&reader, caps);
|
||||
|
||||
if ( (caps[0] & DDSCAPS_TEXTURE) == 0)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
bool cubeMap = 0 != (caps[1] & DDSCAPS2_CUBEMAP);
|
||||
if (cubeMap)
|
||||
{
|
||||
if ( (caps[1] & DDS_CUBEMAP_ALLFACES) != DDS_CUBEMAP_ALLFACES)
|
||||
{
|
||||
// parital cube map is not supported.
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
bx::skip(&reader, 4); // reserved
|
||||
|
||||
uint8_t bpp = 0;
|
||||
uint8_t blockSize = 1;
|
||||
TextureFormat::Enum type = TextureFormat::Unknown;
|
||||
bool hasAlpha = pixelFlags & DDPF_ALPHAPIXELS;
|
||||
|
||||
if (pixelFlags & DDPF_FOURCC)
|
||||
{
|
||||
switch (fourcc)
|
||||
{
|
||||
case DDS_DXT1:
|
||||
type = TextureFormat::BC1;
|
||||
bpp = 4;
|
||||
blockSize = 4*4*bpp/8;
|
||||
break;
|
||||
|
||||
case DDS_DXT2:
|
||||
case DDS_DXT3:
|
||||
type = TextureFormat::BC2;
|
||||
bpp = 8;
|
||||
blockSize = 4*4*bpp/8;
|
||||
break;
|
||||
|
||||
case DDS_DXT4:
|
||||
case DDS_DXT5:
|
||||
type = TextureFormat::BC3;
|
||||
bpp = 8;
|
||||
blockSize = 4*4*bpp/8;
|
||||
break;
|
||||
|
||||
case DDS_ATI1:
|
||||
case DDS_BC4U:
|
||||
type = TextureFormat::BC4;
|
||||
bpp = 4;
|
||||
blockSize = 4*4*bpp/8;
|
||||
break;
|
||||
|
||||
case DDS_ATI2:
|
||||
case DDS_BC5U:
|
||||
type = TextureFormat::BC5;
|
||||
bpp = 8;
|
||||
blockSize = 4*4*bpp/8;
|
||||
break;
|
||||
|
||||
case D3DFMT_A16B16G16R16:
|
||||
type = TextureFormat::RGBA16;
|
||||
blockSize = 8;
|
||||
bpp = 64;
|
||||
break;
|
||||
|
||||
case D3DFMT_A16B16G16R16F:
|
||||
type = TextureFormat::RGBA16F;
|
||||
blockSize = 8;
|
||||
bpp = 64;
|
||||
break;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
switch (pixelFlags)
|
||||
{
|
||||
case DDPF_RGB:
|
||||
type = TextureFormat::BGRX8;
|
||||
blockSize = 3;
|
||||
bpp = 24;
|
||||
break;
|
||||
|
||||
case DDPF_RGB|DDPF_ALPHAPIXELS:
|
||||
type = TextureFormat::BGRA8;
|
||||
blockSize = 4;
|
||||
bpp = 32;
|
||||
break;
|
||||
|
||||
case DDPF_INDEXED:
|
||||
case DDPF_LUMINANCE:
|
||||
case DDPF_ALPHA:
|
||||
type = TextureFormat::L8;
|
||||
bpp = 8;
|
||||
break;
|
||||
|
||||
// type = TextureFormat::A8;
|
||||
// bpp = 1;
|
||||
// break;
|
||||
|
||||
default:
|
||||
bpp = 0;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
_dds.m_type = type;
|
||||
_dds.m_width = width;
|
||||
_dds.m_height = height;
|
||||
_dds.m_depth = depth;
|
||||
_dds.m_blockSize = blockSize;
|
||||
_dds.m_numMips = (caps[0] & DDSCAPS_MIPMAP) ? mips : 1;
|
||||
_dds.m_bpp = bpp;
|
||||
_dds.m_hasAlpha = hasAlpha;
|
||||
_dds.m_cubeMap = cubeMap;
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
bool getRawImageData(const Dds& _dds, uint8_t _side, uint8_t _lod, const Memory* _mem, Mip& _mip)
|
||||
{
|
||||
uint32_t blockSize = _dds.m_blockSize;
|
||||
uint32_t offset = DDS_IMAGE_DATA_OFFSET;
|
||||
uint8_t bpp = _dds.m_bpp;
|
||||
TextureFormat::Enum type = _dds.m_type;
|
||||
bool hasAlpha = _dds.m_hasAlpha;
|
||||
|
||||
for (uint8_t side = 0, numSides = _dds.m_cubeMap ? 6 : 1; side < numSides; ++side)
|
||||
{
|
||||
uint32_t width = _dds.m_width;
|
||||
uint32_t height = _dds.m_height;
|
||||
uint32_t depth = _dds.m_depth;
|
||||
|
||||
for (uint8_t lod = 0, num = _dds.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 size = width*height*depth*blockSize;
|
||||
if (TextureFormat::Unknown > type)
|
||||
{
|
||||
width = bx::uint32_max(1, (width + 3)>>2);
|
||||
height = bx::uint32_max(1, (height + 3)>>2);
|
||||
size = width*height*depth*blockSize;
|
||||
|
||||
width <<= 2;
|
||||
height <<= 2;
|
||||
}
|
||||
|
||||
if (side == _side
|
||||
&& lod == _lod)
|
||||
{
|
||||
_mip.m_width = width;
|
||||
_mip.m_height = height;
|
||||
_mip.m_blockSize = blockSize;
|
||||
_mip.m_size = size;
|
||||
_mip.m_data = _mem->data + offset;
|
||||
_mip.m_bpp = bpp;
|
||||
_mip.m_type = type;
|
||||
_mip.m_hasAlpha = hasAlpha;
|
||||
return true;
|
||||
}
|
||||
|
||||
offset += size;
|
||||
|
||||
width >>= 1;
|
||||
height >>= 1;
|
||||
depth >>= 1;
|
||||
}
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
} // namespace bgfx
|
47
src/dds.h
47
src/dds.h
|
@ -1,47 +0,0 @@
|
|||
/*
|
||||
* Copyright 2011-2013 Branimir Karadzic. All rights reserved.
|
||||
* License: http://www.opensource.org/licenses/BSD-2-Clause
|
||||
*/
|
||||
|
||||
#ifndef __DDS_H__
|
||||
#define __DDS_H__
|
||||
|
||||
#include <stdint.h>
|
||||
|
||||
namespace bgfx
|
||||
{
|
||||
struct Dds
|
||||
{
|
||||
TextureFormat::Enum m_type;
|
||||
uint32_t m_width;
|
||||
uint32_t m_height;
|
||||
uint32_t m_depth;
|
||||
uint8_t m_blockSize;
|
||||
uint8_t m_numMips;
|
||||
uint8_t m_bpp;
|
||||
bool m_hasAlpha;
|
||||
bool m_cubeMap;
|
||||
};
|
||||
|
||||
struct Mip
|
||||
{
|
||||
uint32_t m_width;
|
||||
uint32_t m_height;
|
||||
uint32_t m_blockSize;
|
||||
uint32_t m_size;
|
||||
uint8_t m_bpp;
|
||||
uint8_t m_type;
|
||||
bool m_hasAlpha;
|
||||
const uint8_t* m_data;
|
||||
|
||||
uint32_t getDecodedSize() const;
|
||||
void decode(uint8_t* _dst);
|
||||
};
|
||||
|
||||
bool isDds(const Memory* _mem);
|
||||
bool parseDds(Dds& _dds, const Memory* _mem);
|
||||
bool getRawImageData(const Dds& _dds, uint8_t _side, uint8_t _index, const Memory* _mem, Mip& _mip);
|
||||
|
||||
} // namespace bgfx
|
||||
|
||||
#endif // __DDS_H__
|
878
src/image.cpp
878
src/image.cpp
|
@ -5,7 +5,83 @@
|
|||
|
||||
#include "bgfx_p.h"
|
||||
#include <bx/float4_t.h>
|
||||
#include <math.h> // powf
|
||||
#include <math.h> // powf, sqrtf
|
||||
|
||||
#include "image.h"
|
||||
|
||||
#define DDS_MAGIC BX_MAKEFOURCC('D', 'D', 'S', ' ')
|
||||
#define DDS_HEADER_SIZE 124
|
||||
#define DDS_IMAGE_DATA_OFFSET (DDS_HEADER_SIZE + 4)
|
||||
|
||||
#define DDS_DXT1 BX_MAKEFOURCC('D', 'X', 'T', '1')
|
||||
#define DDS_DXT2 BX_MAKEFOURCC('D', 'X', 'T', '2')
|
||||
#define DDS_DXT3 BX_MAKEFOURCC('D', 'X', 'T', '3')
|
||||
#define DDS_DXT4 BX_MAKEFOURCC('D', 'X', 'T', '4')
|
||||
#define DDS_DXT5 BX_MAKEFOURCC('D', 'X', 'T', '5')
|
||||
#define DDS_ATI1 BX_MAKEFOURCC('A', 'T', 'I', '1')
|
||||
#define DDS_BC4U BX_MAKEFOURCC('B', 'C', '4', 'U')
|
||||
#define DDS_ATI2 BX_MAKEFOURCC('A', 'T', 'I', '2')
|
||||
#define DDS_BC5U BX_MAKEFOURCC('B', 'C', '5', 'U')
|
||||
|
||||
#define D3DFMT_A16B16G16R16 36
|
||||
#define D3DFMT_A16B16G16R16F 113
|
||||
|
||||
#define DDSD_CAPS 0x00000001
|
||||
#define DDSD_HEIGHT 0x00000002
|
||||
#define DDSD_WIDTH 0x00000004
|
||||
#define DDSD_PITCH 0x00000008
|
||||
#define DDSD_PIXELFORMAT 0x00001000
|
||||
#define DDSD_MIPMAPCOUNT 0x00020000
|
||||
#define DDSD_LINEARSIZE 0x00080000
|
||||
#define DDSD_DEPTH 0x00800000
|
||||
|
||||
#define DDPF_ALPHAPIXELS 0x00000001
|
||||
#define DDPF_ALPHA 0x00000002
|
||||
#define DDPF_FOURCC 0x00000004
|
||||
#define DDPF_INDEXED 0x00000020
|
||||
#define DDPF_RGB 0x00000040
|
||||
#define DDPF_YUV 0x00000200
|
||||
#define DDPF_LUMINANCE 0x00020000
|
||||
|
||||
#define DDSCAPS_COMPLEX 0x00000008
|
||||
#define DDSCAPS_TEXTURE 0x00001000
|
||||
#define DDSCAPS_MIPMAP 0x00400000
|
||||
|
||||
#define DDSCAPS2_CUBEMAP 0x00000200
|
||||
#define DDSCAPS2_CUBEMAP_POSITIVEX 0x00000400
|
||||
#define DDSCAPS2_CUBEMAP_NEGATIVEX 0x00000800
|
||||
#define DDSCAPS2_CUBEMAP_POSITIVEY 0x00001000
|
||||
#define DDSCAPS2_CUBEMAP_NEGATIVEY 0x00002000
|
||||
#define DDSCAPS2_CUBEMAP_POSITIVEZ 0x00004000
|
||||
#define DDSCAPS2_CUBEMAP_NEGATIVEZ 0x00008000
|
||||
|
||||
#define DDS_CUBEMAP_ALLFACES (DDSCAPS2_CUBEMAP_POSITIVEX|DDSCAPS2_CUBEMAP_NEGATIVEX \
|
||||
|DDSCAPS2_CUBEMAP_POSITIVEY|DDSCAPS2_CUBEMAP_NEGATIVEY \
|
||||
|DDSCAPS2_CUBEMAP_POSITIVEZ|DDSCAPS2_CUBEMAP_NEGATIVEZ)
|
||||
|
||||
#define DDSCAPS2_VOLUME 0x00200000
|
||||
|
||||
#define KTX_MAGIC BX_MAKEFOURCC(0xAB, 'K', 'T', 'X')
|
||||
#define KTX_HEADER_SIZE 64
|
||||
|
||||
#define KTX_ETC1_RGB8_OES 0x8D64
|
||||
#define KTX_COMPRESSED_R11_EAC 0x9270
|
||||
#define KTX_COMPRESSED_SIGNED_R11_EAC 0x9271
|
||||
#define KTX_COMPRESSED_RG11_EAC 0x9272
|
||||
#define KTX_COMPRESSED_SIGNED_RG11_EAC 0x9273
|
||||
#define KTX_COMPRESSED_RGB8_ETC2 0x9274
|
||||
#define KTX_COMPRESSED_SRGB8_ETC2 0x9275
|
||||
#define KTX_COMPRESSED_RGB8_PUNCHTHROUGH_ALPHA1_ETC2 0x9276
|
||||
#define KTX_COMPRESSED_SRGB8_PUNCHTHROUGH_ALPHA1_ETC2 0x9277
|
||||
#define KTX_COMPRESSED_RGBA8_ETC2_EAC 0x9278
|
||||
#define KTX_COMPRESSED_SRGB8_ALPHA8_ETC2_EAC 0x9279
|
||||
#define KTX_COMPRESSED_RGB_PVRTC_4BPPV1_IMG 0x8C00
|
||||
#define KTX_COMPRESSED_RGB_PVRTC_2BPPV1_IMG 0x8C01
|
||||
#define KTX_COMPRESSED_RGBA_PVRTC_4BPPV1_IMG 0x8C02
|
||||
#define KTX_COMPRESSED_RGBA_PVRTC_2BPPV1_IMG 0x8C03
|
||||
|
||||
#define PKM_MAGIC BX_MAKEFOURCC('P', 'K', 'M', 0)
|
||||
#define PKM_HEADER_SIZE 16
|
||||
|
||||
namespace bgfx
|
||||
{
|
||||
|
@ -163,7 +239,7 @@ namespace bgfx
|
|||
}
|
||||
}
|
||||
|
||||
static void imageSwizzleBgra8Ref(uint32_t _width, uint32_t _height, const void* _src, void* _dst)
|
||||
void imageSwizzleBgra8Ref(uint32_t _width, uint32_t _height, const void* _src, void* _dst)
|
||||
{
|
||||
const uint8_t* src = (uint8_t*) _src;
|
||||
uint8_t* dst = (uint8_t*)_dst;
|
||||
|
@ -260,4 +336,802 @@ namespace bgfx
|
|||
}
|
||||
}
|
||||
|
||||
uint32_t bitRangeConvert(uint32_t _in, uint32_t _from, uint32_t _to)
|
||||
{
|
||||
using namespace bx;
|
||||
uint32_t tmp0 = uint32_sll(1, _to);
|
||||
uint32_t tmp1 = uint32_sll(1, _from);
|
||||
uint32_t tmp2 = uint32_dec(tmp0);
|
||||
uint32_t tmp3 = uint32_dec(tmp1);
|
||||
uint32_t tmp4 = uint32_mul(_in, tmp2);
|
||||
uint32_t tmp5 = uint32_add(tmp3, tmp4);
|
||||
uint32_t tmp6 = uint32_srl(tmp5, _from);
|
||||
uint32_t tmp7 = uint32_add(tmp5, tmp6);
|
||||
uint32_t result = uint32_srl(tmp7, _from);
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
void decodeBlockDxt(uint8_t _dst[16*4], const uint8_t _src[8])
|
||||
{
|
||||
uint8_t colors[4*3];
|
||||
|
||||
uint32_t c0 = _src[0] | (_src[1] << 8);
|
||||
colors[0] = bitRangeConvert( (c0>> 0)&0x1f, 5, 8);
|
||||
colors[1] = bitRangeConvert( (c0>> 5)&0x3f, 6, 8);
|
||||
colors[2] = bitRangeConvert( (c0>>11)&0x1f, 5, 8);
|
||||
|
||||
uint32_t c1 = _src[2] | (_src[3] << 8);
|
||||
colors[3] = bitRangeConvert( (c1>> 0)&0x1f, 5, 8);
|
||||
colors[4] = bitRangeConvert( (c1>> 5)&0x3f, 6, 8);
|
||||
colors[5] = bitRangeConvert( (c1>>11)&0x1f, 5, 8);
|
||||
|
||||
colors[6] = (2*colors[0] + colors[3]) / 3;
|
||||
colors[7] = (2*colors[1] + colors[4]) / 3;
|
||||
colors[8] = (2*colors[2] + colors[5]) / 3;
|
||||
|
||||
colors[ 9] = (colors[0] + 2*colors[3]) / 3;
|
||||
colors[10] = (colors[1] + 2*colors[4]) / 3;
|
||||
colors[11] = (colors[2] + 2*colors[5]) / 3;
|
||||
|
||||
for (uint32_t ii = 0, next = 8*4; ii < 16*4; ii += 4, next += 2)
|
||||
{
|
||||
int idx = ( (_src[next>>3] >> (next & 7) ) & 3) * 3;
|
||||
_dst[ii+0] = colors[idx+0];
|
||||
_dst[ii+1] = colors[idx+1];
|
||||
_dst[ii+2] = colors[idx+2];
|
||||
}
|
||||
}
|
||||
|
||||
void decodeBlockDxt1(uint8_t _dst[16*4], const uint8_t _src[8])
|
||||
{
|
||||
uint8_t colors[4*4];
|
||||
|
||||
uint32_t c0 = _src[0] | (_src[1] << 8);
|
||||
colors[0] = bitRangeConvert( (c0>> 0)&0x1f, 5, 8);
|
||||
colors[1] = bitRangeConvert( (c0>> 5)&0x3f, 6, 8);
|
||||
colors[2] = bitRangeConvert( (c0>>11)&0x1f, 5, 8);
|
||||
colors[3] = 255;
|
||||
|
||||
uint32_t c1 = _src[2] | (_src[3] << 8);
|
||||
colors[4] = bitRangeConvert( (c1>> 0)&0x1f, 5, 8);
|
||||
colors[5] = bitRangeConvert( (c1>> 5)&0x3f, 6, 8);
|
||||
colors[6] = bitRangeConvert( (c1>>11)&0x1f, 5, 8);
|
||||
colors[7] = 255;
|
||||
|
||||
if (c0 > c1)
|
||||
{
|
||||
colors[ 8] = (2*colors[0] + colors[4]) / 3;
|
||||
colors[ 9] = (2*colors[1] + colors[5]) / 3;
|
||||
colors[10] = (2*colors[2] + colors[6]) / 3;
|
||||
colors[11] = 255;
|
||||
|
||||
colors[12] = (colors[0] + 2*colors[4]) / 3;
|
||||
colors[13] = (colors[1] + 2*colors[5]) / 3;
|
||||
colors[14] = (colors[2] + 2*colors[6]) / 3;
|
||||
colors[15] = 255;
|
||||
}
|
||||
else
|
||||
{
|
||||
colors[ 8] = (colors[0] + colors[4]) / 2;
|
||||
colors[ 9] = (colors[1] + colors[5]) / 2;
|
||||
colors[10] = (colors[2] + colors[6]) / 2;
|
||||
colors[11] = 255;
|
||||
|
||||
colors[12] = 0;
|
||||
colors[13] = 0;
|
||||
colors[14] = 0;
|
||||
colors[15] = 0;
|
||||
}
|
||||
|
||||
for (uint32_t ii = 0, next = 8*4; ii < 16*4; ii += 4, next += 2)
|
||||
{
|
||||
int idx = ( (_src[next>>3] >> (next & 7) ) & 3) * 4;
|
||||
_dst[ii+0] = colors[idx+0];
|
||||
_dst[ii+1] = colors[idx+1];
|
||||
_dst[ii+2] = colors[idx+2];
|
||||
_dst[ii+3] = colors[idx+3];
|
||||
}
|
||||
}
|
||||
|
||||
void decodeBlockDxt23A(uint8_t _dst[16*4], const uint8_t _src[8])
|
||||
{
|
||||
for (uint32_t ii = 0, next = 0; ii < 16*4; ii += 4, next += 4)
|
||||
{
|
||||
uint32_t c0 = (_src[next>>3] >> (next&7) ) & 0xf;
|
||||
_dst[ii] = bitRangeConvert(c0, 4, 8);
|
||||
}
|
||||
}
|
||||
|
||||
void decodeBlockDxt45A(uint8_t _dst[16*4], const uint8_t _src[8])
|
||||
{
|
||||
uint8_t alpha[8];
|
||||
alpha[0] = _src[0];
|
||||
alpha[1] = _src[1];
|
||||
|
||||
if (alpha[0] > alpha[1])
|
||||
{
|
||||
alpha[2] = (6*alpha[0] + 1*alpha[1]) / 7;
|
||||
alpha[3] = (5*alpha[0] + 2*alpha[1]) / 7;
|
||||
alpha[4] = (4*alpha[0] + 3*alpha[1]) / 7;
|
||||
alpha[5] = (3*alpha[0] + 4*alpha[1]) / 7;
|
||||
alpha[6] = (2*alpha[0] + 5*alpha[1]) / 7;
|
||||
alpha[7] = (1*alpha[0] + 6*alpha[1]) / 7;
|
||||
}
|
||||
else
|
||||
{
|
||||
alpha[2] = (4*alpha[0] + 1*alpha[1]) / 5;
|
||||
alpha[3] = (3*alpha[0] + 2*alpha[1]) / 5;
|
||||
alpha[4] = (2*alpha[0] + 3*alpha[1]) / 5;
|
||||
alpha[5] = (1*alpha[0] + 4*alpha[1]) / 5;
|
||||
alpha[6] = 0;
|
||||
alpha[7] = 255;
|
||||
}
|
||||
|
||||
uint32_t idx0 = _src[2];
|
||||
uint32_t idx1 = _src[5];
|
||||
idx0 |= uint32_t(_src[3])<<8;
|
||||
idx1 |= uint32_t(_src[6])<<8;
|
||||
idx0 |= uint32_t(_src[4])<<16;
|
||||
idx1 |= uint32_t(_src[7])<<16;
|
||||
for (uint32_t ii = 0; ii < 8*4; ii += 4)
|
||||
{
|
||||
_dst[ii] = alpha[idx0&7];
|
||||
_dst[ii+32] = alpha[idx1&7];
|
||||
idx0 >>= 3;
|
||||
idx1 >>= 3;
|
||||
}
|
||||
}
|
||||
|
||||
static const int32_t s_mod[8][4] =
|
||||
{
|
||||
{ 2, 8, -2, -8},
|
||||
{ 15, 17, -15, -17},
|
||||
{ 9, 29, -9, -29},
|
||||
{ 13, 42, -13, -42},
|
||||
{ 18, 60, -18, -60},
|
||||
{ 24, 80, -24, -80},
|
||||
{ 33, 106, -33, -106},
|
||||
{ 47, 183, -47, -183},
|
||||
};
|
||||
|
||||
int8_t uint8_add2c(int32_t _a, int32_t _b)
|
||||
{
|
||||
return _b & 0x4
|
||||
? _a - ( (~_b + 1) & 0x7)
|
||||
: _a + _b
|
||||
;
|
||||
}
|
||||
|
||||
int8_t uint8_satadd(int32_t _a, int32_t _b)
|
||||
{
|
||||
using namespace bx;
|
||||
const int32_t add = _a + _b;
|
||||
const uint32_t min = uint32_min(add, 255);
|
||||
const uint32_t result = uint32_max(min, 0);
|
||||
return result;
|
||||
}
|
||||
|
||||
void decodeBlockEtc1(uint8_t _dst[16*4], const uint8_t _src[8])
|
||||
{
|
||||
bool flipBit = 0 != (_src[3] & 0x1);
|
||||
bool diffBit = 0 != (_src[3] & 0x2);
|
||||
|
||||
uint8_t rgb[8];
|
||||
|
||||
if (diffBit)
|
||||
{
|
||||
rgb[0] = _src[0] >> 3;
|
||||
rgb[1] = _src[1] >> 3;
|
||||
rgb[2] = _src[2] >> 3;
|
||||
|
||||
uint8_t diff[3];
|
||||
diff[0] = _src[0] & 0x07;
|
||||
diff[1] = _src[1] & 0x07;
|
||||
diff[2] = _src[2] & 0x07;
|
||||
|
||||
rgb[4] = uint8_add2c(rgb[0], diff[0]);
|
||||
rgb[5] = uint8_add2c(rgb[1], diff[1]);
|
||||
rgb[6] = uint8_add2c(rgb[2], diff[2]);
|
||||
|
||||
rgb[0] = bitRangeConvert(rgb[0], 5, 8);
|
||||
rgb[1] = bitRangeConvert(rgb[1], 5, 8);
|
||||
rgb[2] = bitRangeConvert(rgb[2], 5, 8);
|
||||
rgb[4] = bitRangeConvert(rgb[4], 5, 8);
|
||||
rgb[5] = bitRangeConvert(rgb[5], 5, 8);
|
||||
rgb[6] = bitRangeConvert(rgb[6], 5, 8);
|
||||
}
|
||||
else
|
||||
{
|
||||
rgb[0] = _src[0] >> 4;
|
||||
rgb[1] = _src[1] >> 4;
|
||||
rgb[2] = _src[2] >> 4;
|
||||
|
||||
rgb[4] = _src[0] & 0xf;
|
||||
rgb[5] = _src[1] & 0xf;
|
||||
rgb[6] = _src[2] & 0xf;
|
||||
|
||||
rgb[0] = bitRangeConvert(rgb[0], 4, 8);
|
||||
rgb[1] = bitRangeConvert(rgb[1], 4, 8);
|
||||
rgb[2] = bitRangeConvert(rgb[2], 4, 8);
|
||||
rgb[4] = bitRangeConvert(rgb[4], 4, 8);
|
||||
rgb[5] = bitRangeConvert(rgb[5], 4, 8);
|
||||
rgb[6] = bitRangeConvert(rgb[6], 4, 8);
|
||||
}
|
||||
|
||||
uint32_t table[2];
|
||||
table[0] = (_src[3] >> 5) & 0x7;
|
||||
table[1] = (_src[3] >> 2) & 0x7;
|
||||
|
||||
uint32_t indexBits = 0
|
||||
| (_src[4]<<24)
|
||||
| (_src[5]<<16)
|
||||
| (_src[6]<< 8)
|
||||
| (_src[7] )
|
||||
;
|
||||
|
||||
if (flipBit)
|
||||
{
|
||||
for (uint32_t ii = 0; ii < 16; ++ii)
|
||||
{
|
||||
const uint32_t block = (ii>>1)&1;
|
||||
const uint32_t color = block<<2;
|
||||
const uint32_t idx = (ii&0xc) | ( (ii & 0x3)<<4);
|
||||
const uint32_t lsbi = (indexBits >> ii) & 1;
|
||||
const uint32_t msbi = (indexBits >> (16 + ii) ) & 1;
|
||||
const int32_t mod = s_mod[table[block] ][lsbi + msbi*2];
|
||||
|
||||
_dst[idx + 0] = uint8_satadd(rgb[color+2], mod);
|
||||
_dst[idx + 1] = uint8_satadd(rgb[color+1], mod);
|
||||
_dst[idx + 2] = uint8_satadd(rgb[color+0], mod);
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
for (uint32_t ii = 0; ii < 16; ++ii)
|
||||
{
|
||||
const uint32_t block = ii>>3;
|
||||
const uint32_t color = block<<2;
|
||||
const uint32_t idx = (ii&0xc) | ( (ii & 0x3)<<4);
|
||||
const uint32_t lsbi = (indexBits >> ii) & 1;
|
||||
const uint32_t msbi = (indexBits >> (16 + ii) ) & 1;
|
||||
const int32_t mod = s_mod[table[block] ][lsbi + msbi*2];
|
||||
|
||||
_dst[idx + 0] = uint8_satadd(rgb[color+2], mod);
|
||||
_dst[idx + 1] = uint8_satadd(rgb[color+1], mod);
|
||||
_dst[idx + 2] = uint8_satadd(rgb[color+0], mod);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
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;
|
||||
}
|
||||
}
|
||||
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;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
bool imageParseDds(ImageContainer& _imageContainer, bx::ReaderSeekerI* _reader)
|
||||
{
|
||||
uint32_t headerSize;
|
||||
bx::read(_reader, headerSize);
|
||||
|
||||
if (headerSize < DDS_HEADER_SIZE)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
uint32_t flags;
|
||||
bx::read(_reader, flags);
|
||||
|
||||
if ( (flags & (DDSD_CAPS|DDSD_HEIGHT|DDSD_WIDTH|DDSD_PIXELFORMAT) ) != (DDSD_CAPS|DDSD_HEIGHT|DDSD_WIDTH|DDSD_PIXELFORMAT) )
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
uint32_t height;
|
||||
bx::read(_reader, height);
|
||||
|
||||
uint32_t width;
|
||||
bx::read(_reader, width);
|
||||
|
||||
uint32_t pitch;
|
||||
bx::read(_reader, pitch);
|
||||
|
||||
uint32_t depth;
|
||||
bx::read(_reader, depth);
|
||||
|
||||
uint32_t mips;
|
||||
bx::read(_reader, mips);
|
||||
|
||||
bx::skip(_reader, 44); // reserved
|
||||
bx::skip(_reader, 4); // pixel format size
|
||||
|
||||
uint32_t pixelFlags;
|
||||
bx::read(_reader, pixelFlags);
|
||||
|
||||
uint32_t fourcc;
|
||||
bx::read(_reader, fourcc);
|
||||
|
||||
uint32_t rgbCount;
|
||||
bx::read(_reader, rgbCount);
|
||||
|
||||
uint32_t rbitmask;
|
||||
bx::read(_reader, rbitmask);
|
||||
|
||||
uint32_t gbitmask;
|
||||
bx::read(_reader, gbitmask);
|
||||
|
||||
uint32_t bbitmask;
|
||||
bx::read(_reader, bbitmask);
|
||||
|
||||
uint32_t abitmask;
|
||||
bx::read(_reader, abitmask);
|
||||
|
||||
uint32_t caps[4];
|
||||
bx::read(_reader, caps);
|
||||
|
||||
if ( (caps[0] & DDSCAPS_TEXTURE) == 0)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
bool cubeMap = 0 != (caps[1] & DDSCAPS2_CUBEMAP);
|
||||
if (cubeMap)
|
||||
{
|
||||
if ( (caps[1] & DDS_CUBEMAP_ALLFACES) != DDS_CUBEMAP_ALLFACES)
|
||||
{
|
||||
// parital cube map is not supported.
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
bx::skip(_reader, 4); // reserved
|
||||
|
||||
uint8_t bpp = 0;
|
||||
uint8_t blockSize = 1;
|
||||
TextureFormat::Enum type = TextureFormat::Unknown;
|
||||
bool hasAlpha = pixelFlags & DDPF_ALPHAPIXELS;
|
||||
|
||||
if (pixelFlags & DDPF_FOURCC)
|
||||
{
|
||||
switch (fourcc)
|
||||
{
|
||||
case DDS_DXT1:
|
||||
type = TextureFormat::BC1;
|
||||
bpp = 4;
|
||||
blockSize = 4*4*bpp/8;
|
||||
break;
|
||||
|
||||
case DDS_DXT2:
|
||||
case DDS_DXT3:
|
||||
type = TextureFormat::BC2;
|
||||
bpp = 8;
|
||||
blockSize = 4*4*bpp/8;
|
||||
break;
|
||||
|
||||
case DDS_DXT4:
|
||||
case DDS_DXT5:
|
||||
type = TextureFormat::BC3;
|
||||
bpp = 8;
|
||||
blockSize = 4*4*bpp/8;
|
||||
break;
|
||||
|
||||
case DDS_ATI1:
|
||||
case DDS_BC4U:
|
||||
type = TextureFormat::BC4;
|
||||
bpp = 4;
|
||||
blockSize = 4*4*bpp/8;
|
||||
break;
|
||||
|
||||
case DDS_ATI2:
|
||||
case DDS_BC5U:
|
||||
type = TextureFormat::BC5;
|
||||
bpp = 8;
|
||||
blockSize = 4*4*bpp/8;
|
||||
break;
|
||||
|
||||
case D3DFMT_A16B16G16R16:
|
||||
type = TextureFormat::RGBA16;
|
||||
blockSize = 8;
|
||||
bpp = 64;
|
||||
break;
|
||||
|
||||
case D3DFMT_A16B16G16R16F:
|
||||
type = TextureFormat::RGBA16F;
|
||||
blockSize = 8;
|
||||
bpp = 64;
|
||||
break;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
switch (pixelFlags)
|
||||
{
|
||||
case DDPF_RGB:
|
||||
type = TextureFormat::BGRX8;
|
||||
blockSize = 3;
|
||||
bpp = 24;
|
||||
break;
|
||||
|
||||
case DDPF_RGB|DDPF_ALPHAPIXELS:
|
||||
type = TextureFormat::BGRA8;
|
||||
blockSize = 4;
|
||||
bpp = 32;
|
||||
break;
|
||||
|
||||
case DDPF_INDEXED:
|
||||
case DDPF_LUMINANCE:
|
||||
case DDPF_ALPHA:
|
||||
type = TextureFormat::L8;
|
||||
bpp = 8;
|
||||
break;
|
||||
|
||||
// type = TextureFormat::A8;
|
||||
// bpp = 1;
|
||||
// break;
|
||||
|
||||
default:
|
||||
bpp = 0;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
_imageContainer.m_type = type;
|
||||
_imageContainer.m_offset = DDS_IMAGE_DATA_OFFSET;
|
||||
_imageContainer.m_width = width;
|
||||
_imageContainer.m_height = height;
|
||||
_imageContainer.m_depth = depth;
|
||||
_imageContainer.m_blockSize = blockSize;
|
||||
_imageContainer.m_numMips = (caps[0] & DDSCAPS_MIPMAP) ? mips : 1;
|
||||
_imageContainer.m_bpp = bpp;
|
||||
_imageContainer.m_hasAlpha = hasAlpha;
|
||||
_imageContainer.m_cubeMap = cubeMap;
|
||||
_imageContainer.m_ktx = false;
|
||||
|
||||
return TextureFormat::Unknown != type;
|
||||
}
|
||||
|
||||
bool imageParseKtx(ImageContainer& _imageContainer, bx::ReaderSeekerI* _reader)
|
||||
{
|
||||
uint8_t identifier[8];
|
||||
bx::read(_reader, identifier);
|
||||
|
||||
if (identifier[1] != '1'
|
||||
&& identifier[2] != '1')
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
uint32_t endianness;
|
||||
bx::read(_reader, endianness);
|
||||
|
||||
bool fromLittleEndian = 0x04030201 == endianness;
|
||||
|
||||
uint32_t glType;
|
||||
bx::readHE(_reader, glType, fromLittleEndian);
|
||||
|
||||
uint32_t glTypeSize;
|
||||
bx::readHE(_reader, glTypeSize, fromLittleEndian);
|
||||
|
||||
uint32_t glFormat;
|
||||
bx::readHE(_reader, glFormat, fromLittleEndian);
|
||||
|
||||
uint32_t glInternalFormat;
|
||||
bx::readHE(_reader, glInternalFormat, fromLittleEndian);
|
||||
|
||||
uint32_t glBaseInternalFormat;
|
||||
bx::readHE(_reader, glBaseInternalFormat, fromLittleEndian);
|
||||
|
||||
uint32_t pixelWidth;
|
||||
bx::readHE(_reader, pixelWidth, fromLittleEndian);
|
||||
|
||||
uint32_t pixelHeight;
|
||||
bx::readHE(_reader, pixelHeight, fromLittleEndian);
|
||||
|
||||
uint32_t pixelDepth;
|
||||
bx::readHE(_reader, pixelDepth, fromLittleEndian);
|
||||
|
||||
uint32_t numberOfArrayElements;
|
||||
bx::readHE(_reader, numberOfArrayElements, fromLittleEndian);
|
||||
|
||||
uint32_t numberOfFaces;
|
||||
bx::readHE(_reader, numberOfFaces, fromLittleEndian);
|
||||
|
||||
uint32_t numberOfMipmapLevels;
|
||||
bx::readHE(_reader, numberOfMipmapLevels, fromLittleEndian);
|
||||
|
||||
uint32_t bytesOfKeyValueData;
|
||||
bx::readHE(_reader, bytesOfKeyValueData, fromLittleEndian);
|
||||
|
||||
// skip meta garbage...
|
||||
int64_t offset = bx::skip(_reader, bytesOfKeyValueData);
|
||||
|
||||
uint8_t bpp = 0;
|
||||
uint8_t blockSize = 1;
|
||||
TextureFormat::Enum type = TextureFormat::Unknown;
|
||||
bool hasAlpha = false;
|
||||
|
||||
switch (glInternalFormat)
|
||||
{
|
||||
case KTX_ETC1_RGB8_OES:
|
||||
type = TextureFormat::ETC1;
|
||||
bpp = 4;
|
||||
blockSize = 4*4*bpp/8;
|
||||
break;
|
||||
|
||||
case KTX_COMPRESSED_R11_EAC:
|
||||
case KTX_COMPRESSED_SIGNED_R11_EAC:
|
||||
case KTX_COMPRESSED_RG11_EAC:
|
||||
case KTX_COMPRESSED_SIGNED_RG11_EAC:
|
||||
case KTX_COMPRESSED_RGB8_ETC2:
|
||||
case KTX_COMPRESSED_SRGB8_ETC2:
|
||||
case KTX_COMPRESSED_RGB8_PUNCHTHROUGH_ALPHA1_ETC2:
|
||||
case KTX_COMPRESSED_SRGB8_PUNCHTHROUGH_ALPHA1_ETC2:
|
||||
case KTX_COMPRESSED_RGBA8_ETC2_EAC:
|
||||
case KTX_COMPRESSED_SRGB8_ALPHA8_ETC2_EAC:
|
||||
case KTX_COMPRESSED_RGB_PVRTC_4BPPV1_IMG:
|
||||
case KTX_COMPRESSED_RGB_PVRTC_2BPPV1_IMG:
|
||||
case KTX_COMPRESSED_RGBA_PVRTC_4BPPV1_IMG:
|
||||
case KTX_COMPRESSED_RGBA_PVRTC_2BPPV1_IMG:
|
||||
default:
|
||||
break;
|
||||
}
|
||||
|
||||
_imageContainer.m_type = type;
|
||||
_imageContainer.m_offset = (uint32_t)offset;
|
||||
_imageContainer.m_width = pixelWidth;
|
||||
_imageContainer.m_height = pixelHeight;
|
||||
_imageContainer.m_depth = pixelDepth;
|
||||
_imageContainer.m_blockSize = blockSize;
|
||||
_imageContainer.m_numMips = numberOfMipmapLevels;
|
||||
_imageContainer.m_bpp = bpp;
|
||||
_imageContainer.m_hasAlpha = hasAlpha;
|
||||
_imageContainer.m_cubeMap = numberOfFaces > 1;
|
||||
_imageContainer.m_ktx = true;
|
||||
|
||||
return TextureFormat::Unknown != type;
|
||||
}
|
||||
|
||||
bool imageParse(ImageContainer& _imageContainer, bx::ReaderSeekerI* _reader)
|
||||
{
|
||||
uint32_t magic;
|
||||
bx::read(_reader, magic);
|
||||
|
||||
if (DDS_MAGIC == magic)
|
||||
{
|
||||
return imageParseDds(_imageContainer, _reader);
|
||||
}
|
||||
else if (KTX_MAGIC == magic)
|
||||
{
|
||||
return imageParseKtx(_imageContainer, _reader);
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
bool imageParse(ImageContainer& _imageContainer, const void* _data, uint32_t _size)
|
||||
{
|
||||
bx::MemoryReader reader(_data, _size);
|
||||
return imageParse(_imageContainer, &reader);
|
||||
}
|
||||
|
||||
bool imageGetRawData(const ImageContainer& _imageContainer, uint8_t _side, uint8_t _lod, const void* _data, uint32_t _size, Mip& _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;
|
||||
bool hasAlpha = _imageContainer.m_hasAlpha;
|
||||
|
||||
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 (uint8_t lod = 0, num = _imageContainer.m_numMips; lod < num; ++lod)
|
||||
{
|
||||
// skip imageSize in KTX format.
|
||||
offset += _imageContainer.m_ktx ? sizeof(uint32_t) : 0;
|
||||
|
||||
width = bx::uint32_max(1, width);
|
||||
height = bx::uint32_max(1, height);
|
||||
depth = bx::uint32_max(1, depth);
|
||||
|
||||
uint32_t size = width*height*depth*blockSize;
|
||||
if (TextureFormat::Unknown > type)
|
||||
{
|
||||
width = bx::uint32_max(1, (width + 3)>>2);
|
||||
height = bx::uint32_max(1, (height + 3)>>2);
|
||||
size = width*height*depth*blockSize;
|
||||
|
||||
width <<= 2;
|
||||
height <<= 2;
|
||||
}
|
||||
|
||||
if (side == _side
|
||||
&& lod == _lod)
|
||||
{
|
||||
_mip.m_width = width;
|
||||
_mip.m_height = height;
|
||||
_mip.m_blockSize = blockSize;
|
||||
_mip.m_size = size;
|
||||
_mip.m_data = (const uint8_t*)_data + offset;
|
||||
_mip.m_bpp = bpp;
|
||||
_mip.m_type = type;
|
||||
_mip.m_hasAlpha = hasAlpha;
|
||||
return true;
|
||||
}
|
||||
|
||||
offset += size;
|
||||
|
||||
BX_CHECK(offset <= _size, "Reading past size of data buffer! (offset %d, size %d)", offset, _size);
|
||||
BX_UNUSED(_size);
|
||||
|
||||
width >>= 1;
|
||||
height >>= 1;
|
||||
depth >>= 1;
|
||||
}
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
} // namespace bgfx
|
||||
|
|
68
src/image.h
Normal file
68
src/image.h
Normal file
|
@ -0,0 +1,68 @@
|
|||
/*
|
||||
* Copyright 2011-2013 Branimir Karadzic. All rights reserved.
|
||||
* License: http://www.opensource.org/licenses/BSD-2-Clause
|
||||
*/
|
||||
|
||||
#ifndef __IMAGE_H__
|
||||
#define __IMAGE_H__
|
||||
|
||||
#include <stdint.h>
|
||||
|
||||
namespace bgfx
|
||||
{
|
||||
struct ImageContainer
|
||||
{
|
||||
TextureFormat::Enum m_type;
|
||||
uint32_t m_offset;
|
||||
uint32_t m_width;
|
||||
uint32_t m_height;
|
||||
uint32_t m_depth;
|
||||
uint8_t m_blockSize;
|
||||
uint8_t m_numMips;
|
||||
uint8_t m_bpp;
|
||||
bool m_hasAlpha;
|
||||
bool m_cubeMap;
|
||||
bool m_ktx;
|
||||
};
|
||||
|
||||
struct Mip
|
||||
{
|
||||
uint32_t m_width;
|
||||
uint32_t m_height;
|
||||
uint32_t m_blockSize;
|
||||
uint32_t m_size;
|
||||
uint8_t m_bpp;
|
||||
uint8_t m_type;
|
||||
bool m_hasAlpha;
|
||||
const uint8_t* m_data;
|
||||
|
||||
void decode(uint8_t* _dst);
|
||||
};
|
||||
|
||||
///
|
||||
void imageSolid(uint32_t _width, uint32_t _height, uint32_t _solid, void* _dst);
|
||||
|
||||
///
|
||||
void imageChessboard(uint32_t _width, uint32_t _height, uint32_t _step, uint32_t _0, uint32_t _1, void* _dst);
|
||||
|
||||
///
|
||||
void imageRgba8Downsample2x2(uint32_t _width, uint32_t _height, uint32_t _pitch, const void* _src, void* _dst);
|
||||
|
||||
///
|
||||
void imageSwizzleBgra8(uint32_t _width, uint32_t _height, const void* _src, void* _dst);
|
||||
|
||||
///
|
||||
void imageWriteTga(bx::WriterI* _writer, uint32_t _width, uint32_t _height, uint32_t _srcPitch, const void* _src, bool _grayscale, bool _yflip);
|
||||
|
||||
///
|
||||
bool imageParse(ImageContainer& _imageContainer, bx::ReaderSeekerI* _reader);
|
||||
|
||||
///
|
||||
bool imageParse(ImageContainer& _dds, 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);
|
||||
|
||||
} // namespace bgfx
|
||||
|
||||
#endif // __IMAGE_H__
|
|
@ -172,7 +172,6 @@ namespace bgfx
|
|||
struct TextureFormatInfo
|
||||
{
|
||||
DXGI_FORMAT m_fmt;
|
||||
uint8_t m_bpp;
|
||||
};
|
||||
|
||||
#ifndef DXGI_FORMAT_B4G4R4A4_UNORM
|
||||
|
@ -184,21 +183,22 @@ namespace bgfx
|
|||
|
||||
static const TextureFormatInfo s_textureFormat[TextureFormat::Count] =
|
||||
{
|
||||
{ DXGI_FORMAT_BC1_UNORM, 4 },
|
||||
{ DXGI_FORMAT_BC2_UNORM, 8 },
|
||||
{ DXGI_FORMAT_BC3_UNORM, 8 },
|
||||
{ DXGI_FORMAT_BC4_UNORM, 4 },
|
||||
{ DXGI_FORMAT_BC5_UNORM, 8 },
|
||||
{ DXGI_FORMAT_UNKNOWN, 0 },
|
||||
{ DXGI_FORMAT_R8_UNORM, 8 },
|
||||
{ DXGI_FORMAT_B8G8R8A8_UNORM, 32 },
|
||||
{ DXGI_FORMAT_B8G8R8A8_UNORM, 32 },
|
||||
{ DXGI_FORMAT_R16G16B16A16_UNORM, 64 },
|
||||
{ DXGI_FORMAT_R16G16B16A16_FLOAT, 64 },
|
||||
{ DXGI_FORMAT_B5G6R5_UNORM, 16 },
|
||||
{ DXGI_FORMAT_B4G4R4A4_UNORM, 16 },
|
||||
{ DXGI_FORMAT_B5G5R5A1_UNORM, 16 },
|
||||
{ DXGI_FORMAT_R10G10B10A2_UNORM, 32 },
|
||||
{ DXGI_FORMAT_BC1_UNORM },
|
||||
{ DXGI_FORMAT_BC2_UNORM },
|
||||
{ DXGI_FORMAT_BC3_UNORM },
|
||||
{ DXGI_FORMAT_BC4_UNORM },
|
||||
{ DXGI_FORMAT_BC5_UNORM },
|
||||
{ DXGI_FORMAT_UNKNOWN },
|
||||
{ DXGI_FORMAT_UNKNOWN },
|
||||
{ DXGI_FORMAT_R8_UNORM },
|
||||
{ DXGI_FORMAT_B8G8R8A8_UNORM },
|
||||
{ DXGI_FORMAT_B8G8R8A8_UNORM },
|
||||
{ DXGI_FORMAT_R16G16B16A16_UNORM },
|
||||
{ DXGI_FORMAT_R16G16B16A16_FLOAT },
|
||||
{ DXGI_FORMAT_B5G6R5_UNORM },
|
||||
{ DXGI_FORMAT_B4G4R4A4_UNORM },
|
||||
{ DXGI_FORMAT_B5G5R5A1_UNORM },
|
||||
{ DXGI_FORMAT_R10G10B10A2_UNORM },
|
||||
};
|
||||
|
||||
static const D3D11_INPUT_ELEMENT_DESC s_attrib[Attrib::Count] =
|
||||
|
@ -1630,17 +1630,19 @@ namespace bgfx
|
|||
{
|
||||
m_sampler = s_renderCtx.getSamplerState(_flags);
|
||||
|
||||
Dds dds;
|
||||
ImageContainer imageContainer;
|
||||
|
||||
if (parseDds(dds, _mem) )
|
||||
if (imageParse(imageContainer, _mem->data, _mem->size) )
|
||||
{
|
||||
bool decompress = false;
|
||||
bool decompress = false
|
||||
|| (TextureFormat::ETC1 == imageContainer.m_type)
|
||||
;
|
||||
|
||||
if (dds.m_cubeMap)
|
||||
if (imageContainer.m_cubeMap)
|
||||
{
|
||||
m_type = TextureCube;
|
||||
}
|
||||
else if (dds.m_depth > 1)
|
||||
else if (imageContainer.m_depth > 1)
|
||||
{
|
||||
m_type = Texture3D;
|
||||
}
|
||||
|
@ -1649,25 +1651,28 @@ namespace bgfx
|
|||
m_type = Texture2D;
|
||||
}
|
||||
|
||||
uint32_t numSrd = dds.m_numMips*(dds.m_cubeMap ? 6 : 1);
|
||||
TextureFormat::Enum textureFormat = decompress ? TextureFormat::BGRA8 : imageContainer.m_type;
|
||||
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 = dds.m_numMips;
|
||||
m_numMips = imageContainer.m_numMips;
|
||||
|
||||
if (decompress
|
||||
|| TextureFormat::Unknown < dds.m_type)
|
||||
|| TextureFormat::Unknown < imageContainer.m_type)
|
||||
{
|
||||
uint32_t bpp = s_textureFormat[dds.m_type].m_bpp;
|
||||
convert = TextureFormat::BGRX8 == dds.m_type;
|
||||
uint32_t bpp = getBitsPerPixel(textureFormat);
|
||||
convert = decompress
|
||||
|| TextureFormat::BGRX8 == textureFormat
|
||||
;
|
||||
|
||||
for (uint8_t side = 0, numSides = dds.m_cubeMap ? 6 : 1; side < numSides; ++side)
|
||||
for (uint8_t side = 0, numSides = imageContainer.m_cubeMap ? 6 : 1; side < numSides; ++side)
|
||||
{
|
||||
uint32_t width = dds.m_width;
|
||||
uint32_t height = dds.m_height;
|
||||
uint32_t depth = dds.m_depth;
|
||||
uint32_t width = imageContainer.m_width;
|
||||
uint32_t height = imageContainer.m_height;
|
||||
uint32_t depth = imageContainer.m_depth;
|
||||
|
||||
for (uint32_t lod = 0, num = m_numMips; lod < num; ++lod)
|
||||
{
|
||||
|
@ -1676,7 +1681,7 @@ namespace bgfx
|
|||
depth = bx::uint32_max(1, depth);
|
||||
|
||||
Mip mip;
|
||||
if (getRawImageData(dds, side, lod, _mem, mip) )
|
||||
if (imageGetRawData(imageContainer, side, lod, _mem->data, _mem->size, mip) )
|
||||
{
|
||||
if (convert)
|
||||
{
|
||||
|
@ -1704,15 +1709,15 @@ namespace bgfx
|
|||
}
|
||||
else
|
||||
{
|
||||
for (uint8_t side = 0, numSides = dds.m_cubeMap ? 6 : 1; side < numSides; ++side)
|
||||
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 (getRawImageData(dds, side, lod, _mem, mip) )
|
||||
if (imageGetRawData(imageContainer, side, lod, _mem->data, _mem->size, mip) )
|
||||
{
|
||||
srd[kk].pSysMem = mip.m_data;
|
||||
if (TextureFormat::Unknown > dds.m_type)
|
||||
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;
|
||||
|
@ -1731,7 +1736,7 @@ namespace bgfx
|
|||
|
||||
D3D11_SHADER_RESOURCE_VIEW_DESC srvd;
|
||||
memset(&srvd, 0, sizeof(srvd) );
|
||||
srvd.Format = s_textureFormat[dds.m_type].m_fmt;
|
||||
srvd.Format = s_textureFormat[textureFormat].m_fmt;
|
||||
|
||||
switch (m_type)
|
||||
{
|
||||
|
@ -1739,29 +1744,29 @@ namespace bgfx
|
|||
case TextureCube:
|
||||
{
|
||||
D3D11_TEXTURE2D_DESC desc;
|
||||
desc.Width = dds.m_width;
|
||||
desc.Height = dds.m_height;
|
||||
desc.MipLevels = dds.m_numMips;
|
||||
desc.Format = s_textureFormat[dds.m_type].m_fmt;
|
||||
desc.Width = imageContainer.m_width;
|
||||
desc.Height = imageContainer.m_height;
|
||||
desc.MipLevels = imageContainer.m_numMips;
|
||||
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;
|
||||
|
||||
if (dds.m_cubeMap)
|
||||
if (imageContainer.m_cubeMap)
|
||||
{
|
||||
desc.ArraySize = 6;
|
||||
desc.MiscFlags = D3D11_RESOURCE_MISC_TEXTURECUBE;
|
||||
srvd.ViewDimension = D3D11_SRV_DIMENSION_TEXTURECUBE;
|
||||
srvd.TextureCube.MipLevels = dds.m_numMips;
|
||||
srvd.TextureCube.MipLevels = imageContainer.m_numMips;
|
||||
}
|
||||
else
|
||||
{
|
||||
desc.ArraySize = 1;
|
||||
desc.MiscFlags = 0;
|
||||
srvd.ViewDimension = D3D11_SRV_DIMENSION_TEXTURE2D;
|
||||
srvd.Texture2D.MipLevels = dds.m_numMips;
|
||||
srvd.Texture2D.MipLevels = imageContainer.m_numMips;
|
||||
}
|
||||
|
||||
DX_CHECK(s_renderCtx.m_device->CreateTexture2D(&desc, srd, &m_texture2d) );
|
||||
|
@ -1771,18 +1776,18 @@ namespace bgfx
|
|||
case Texture3D:
|
||||
{
|
||||
D3D11_TEXTURE3D_DESC desc;
|
||||
desc.Width = dds.m_width;
|
||||
desc.Height = dds.m_height;
|
||||
desc.Depth = dds.m_depth;
|
||||
desc.MipLevels = dds.m_numMips;
|
||||
desc.Format = s_textureFormat[dds.m_type].m_fmt;
|
||||
desc.Width = imageContainer.m_width;
|
||||
desc.Height = imageContainer.m_height;
|
||||
desc.Depth = imageContainer.m_depth;
|
||||
desc.MipLevels = imageContainer.m_numMips;
|
||||
desc.Format = srvd.Format;
|
||||
desc.Usage = D3D11_USAGE_IMMUTABLE;
|
||||
desc.BindFlags = D3D11_BIND_SHADER_RESOURCE;
|
||||
desc.CPUAccessFlags = 0;
|
||||
desc.MiscFlags = 0;
|
||||
|
||||
srvd.ViewDimension = D3D11_SRV_DIMENSION_TEXTURE3D;
|
||||
srvd.Texture3D.MipLevels = dds.m_numMips;
|
||||
srvd.Texture3D.MipLevels = imageContainer.m_numMips;
|
||||
|
||||
DX_CHECK(s_renderCtx.m_device->CreateTexture3D(&desc, srd, &m_texture3d) );
|
||||
}
|
||||
|
@ -1794,9 +1799,9 @@ namespace bgfx
|
|||
if (convert)
|
||||
{
|
||||
kk = 0;
|
||||
for (uint8_t side = 0, numSides = dds.m_cubeMap ? 6 : 1; side < numSides; ++side)
|
||||
for (uint8_t side = 0, numSides = imageContainer.m_cubeMap ? 6 : 1; side < numSides; ++side)
|
||||
{
|
||||
for (uint32_t lod = 0, num = dds.m_numMips; lod < num; ++lod)
|
||||
for (uint32_t lod = 0, num = imageContainer.m_numMips; lod < num; ++lod)
|
||||
{
|
||||
g_free(const_cast<void*>(srd[kk].pSysMem) );
|
||||
++kk;
|
||||
|
@ -1854,7 +1859,7 @@ namespace bgfx
|
|||
srvd.Texture2D.MipLevels = tc.m_numMips;
|
||||
|
||||
D3D11_SUBRESOURCE_DATA* srd = (D3D11_SUBRESOURCE_DATA*)alloca(tc.m_numMips*sizeof(D3D11_SUBRESOURCE_DATA) );
|
||||
uint32_t bpp = s_textureFormat[tc.m_format].m_bpp;
|
||||
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)
|
||||
|
|
|
@ -194,6 +194,7 @@ namespace bgfx
|
|||
{ D3DFMT_ATI1, 4 },
|
||||
{ D3DFMT_ATI2, 8 },
|
||||
{ D3DFMT_UNKNOWN, 0 },
|
||||
{ D3DFMT_UNKNOWN, 0 },
|
||||
{ D3DFMT_L8, 8 },
|
||||
{ D3DFMT_X8R8G8B8, 32 },
|
||||
{ D3DFMT_A8R8G8B8, 32 },
|
||||
|
@ -1504,51 +1505,52 @@ namespace bgfx
|
|||
{
|
||||
m_flags = _flags;
|
||||
|
||||
Dds dds;
|
||||
ImageContainer imageContainer;
|
||||
|
||||
if (parseDds(dds, _mem) )
|
||||
if (imageParse(imageContainer, _mem->data, _mem->size) )
|
||||
{
|
||||
m_format = dds.m_type;
|
||||
const TextureFormatInfo& tfi = s_textureFormat[dds.m_type];
|
||||
m_format = imageContainer.m_type;
|
||||
const TextureFormatInfo& tfi = s_textureFormat[imageContainer.m_type];
|
||||
|
||||
bool decompress = false
|
||||
|| (TextureFormat::BC4 == dds.m_type && !s_extendedFormats[ExtendedFormat::Ati1].m_supported)
|
||||
|| (TextureFormat::BC5 == dds.m_type && !s_extendedFormats[ExtendedFormat::Ati2].m_supported)
|
||||
|| (TextureFormat::BC4 == imageContainer.m_type && !s_extendedFormats[ExtendedFormat::Ati1].m_supported)
|
||||
|| (TextureFormat::BC5 == imageContainer.m_type && !s_extendedFormats[ExtendedFormat::Ati2].m_supported)
|
||||
|| (TextureFormat::ETC1 == imageContainer.m_type)
|
||||
;
|
||||
|
||||
D3DFORMAT format = decompress ? D3DFMT_A8R8G8B8 : tfi.m_fmt;
|
||||
uint8_t bpp = decompress ? 32 : tfi.m_bpp;
|
||||
|
||||
if (dds.m_cubeMap)
|
||||
if (imageContainer.m_cubeMap)
|
||||
{
|
||||
createCubeTexture(dds.m_width, dds.m_numMips, format);
|
||||
createCubeTexture(imageContainer.m_width, imageContainer.m_numMips, format);
|
||||
}
|
||||
else if (dds.m_depth > 1)
|
||||
else if (imageContainer.m_depth > 1)
|
||||
{
|
||||
createVolumeTexture(dds.m_width, dds.m_height, dds.m_depth, dds.m_numMips, format);
|
||||
createVolumeTexture(imageContainer.m_width, imageContainer.m_height, imageContainer.m_depth, imageContainer.m_numMips, format);
|
||||
}
|
||||
else
|
||||
{
|
||||
createTexture(dds.m_width, dds.m_height, dds.m_numMips, format);
|
||||
createTexture(imageContainer.m_width, imageContainer.m_height, imageContainer.m_numMips, format);
|
||||
}
|
||||
|
||||
if (decompress
|
||||
|| TextureFormat::Unknown < dds.m_type)
|
||||
|| TextureFormat::Unknown < imageContainer.m_type)
|
||||
{
|
||||
for (uint8_t side = 0, numSides = dds.m_cubeMap ? 6 : 1; side < numSides; ++side)
|
||||
for (uint8_t side = 0, numSides = imageContainer.m_cubeMap ? 6 : 1; side < numSides; ++side)
|
||||
{
|
||||
uint32_t width = dds.m_width;
|
||||
uint32_t height = dds.m_height;
|
||||
uint32_t depth = dds.m_depth;
|
||||
uint32_t width = imageContainer.m_width;
|
||||
uint32_t height = imageContainer.m_height;
|
||||
uint32_t depth = imageContainer.m_depth;
|
||||
|
||||
for (uint32_t lod = 0, num = dds.m_numMips; lod < num; ++lod)
|
||||
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 (getRawImageData(dds, side, lod, _mem, mip) )
|
||||
if (imageGetRawData(imageContainer, side, lod, _mem->data, _mem->size, mip) )
|
||||
{
|
||||
uint32_t pitch;
|
||||
uint32_t slicePitch;
|
||||
|
@ -1592,24 +1594,24 @@ namespace bgfx
|
|||
// bytes. If actual mip size is used it causes memory corruption.
|
||||
// http://www.aras-p.info/texts/D3D9GPUHacks.html#3dc
|
||||
bool useMipSize = true
|
||||
&& dds.m_type != TextureFormat::BC4
|
||||
&& dds.m_type != TextureFormat::BC5
|
||||
&& imageContainer.m_type != TextureFormat::BC4
|
||||
&& imageContainer.m_type != TextureFormat::BC5
|
||||
;
|
||||
|
||||
for (uint8_t side = 0, numSides = dds.m_cubeMap ? 6 : 1; side < numSides; ++side)
|
||||
for (uint8_t side = 0, numSides = imageContainer.m_cubeMap ? 6 : 1; side < numSides; ++side)
|
||||
{
|
||||
uint32_t width = dds.m_width;
|
||||
uint32_t height = dds.m_height;
|
||||
uint32_t depth = dds.m_depth;
|
||||
uint32_t width = imageContainer.m_width;
|
||||
uint32_t height = imageContainer.m_height;
|
||||
uint32_t depth = imageContainer.m_depth;
|
||||
|
||||
for (uint32_t lod = 0, num = dds.m_numMips; lod < num; ++lod)
|
||||
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 (getRawImageData(dds, 0, lod, _mem, mip) )
|
||||
if (imageGetRawData(imageContainer, 0, lod, _mem->data, _mem->size, mip) )
|
||||
{
|
||||
uint32_t pitch;
|
||||
uint32_t slicePitch;
|
||||
|
|
|
@ -189,27 +189,27 @@ namespace bgfx
|
|||
GLenum m_internalFmt;
|
||||
GLenum m_fmt;
|
||||
GLenum m_type;
|
||||
uint8_t m_bpp;
|
||||
bool m_supported;
|
||||
};
|
||||
|
||||
static TextureFormatInfo s_textureFormat[TextureFormat::Count] =
|
||||
{
|
||||
{ GL_COMPRESSED_RGBA_S3TC_DXT1_EXT, GL_COMPRESSED_RGBA_S3TC_DXT1_EXT, GL_ZERO, 4, false },
|
||||
{ GL_COMPRESSED_RGBA_S3TC_DXT3_EXT, GL_COMPRESSED_RGBA_S3TC_DXT3_EXT, GL_ZERO, 8, false },
|
||||
{ GL_COMPRESSED_RGBA_S3TC_DXT5_EXT, GL_COMPRESSED_RGBA_S3TC_DXT5_EXT, GL_ZERO, 8, false },
|
||||
{ GL_COMPRESSED_LUMINANCE_LATC1_EXT, GL_COMPRESSED_LUMINANCE_LATC1_EXT, GL_ZERO, 4, false },
|
||||
{ GL_COMPRESSED_LUMINANCE_ALPHA_LATC2_EXT, GL_COMPRESSED_LUMINANCE_ALPHA_LATC2_EXT, GL_ZERO, 8, false },
|
||||
{ GL_ZERO, GL_ZERO, GL_ZERO, 0, true },
|
||||
{ GL_LUMINANCE, GL_LUMINANCE, GL_UNSIGNED_BYTE, 8, true },
|
||||
{ GL_RGBA, GL_RGBA, GL_UNSIGNED_BYTE, 32, true },
|
||||
{ GL_RGBA, GL_RGBA, GL_UNSIGNED_BYTE, 32, true },
|
||||
{ GL_RGBA16, GL_RGBA, GL_UNSIGNED_BYTE, 64, true },
|
||||
{ GL_RGBA16F, GL_RGBA, GL_HALF_FLOAT, 64, true },
|
||||
{ GL_RGB565, GL_RGB, GL_UNSIGNED_SHORT_5_6_5, 16, true },
|
||||
{ GL_RGBA4, GL_RGBA, GL_UNSIGNED_SHORT_4_4_4_4, 16, true },
|
||||
{ GL_RGB5_A1, GL_RGBA, GL_UNSIGNED_SHORT_5_5_5_1, 16, true },
|
||||
{ GL_RGB10_A2, GL_RGBA, GL_UNSIGNED_INT_2_10_10_10_REV, 32, true },
|
||||
{ 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_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 },
|
||||
};
|
||||
|
||||
struct Extension
|
||||
|
@ -255,7 +255,13 @@ namespace bgfx
|
|||
EXT_texture_swizzle,
|
||||
EXT_texture_type_2_10_10_10_REV,
|
||||
EXT_timer_query,
|
||||
IMG_multisampled_render_to_texture,
|
||||
IMG_shader_binary,
|
||||
IMG_texture_compression_pvrtc,
|
||||
IMG_texture_format_BGRA8888,
|
||||
NVX_gpu_memory_info,
|
||||
OES_compressed_ETC1_RGB8_texture,
|
||||
OES_depth_texture,
|
||||
OES_get_program_binary,
|
||||
OES_rgb8_rgba8,
|
||||
OES_standard_derivatives,
|
||||
|
@ -277,56 +283,62 @@ namespace bgfx
|
|||
|
||||
static Extension s_extension[Extension::Count] =
|
||||
{
|
||||
{ "GL_ANGLE_instanced_arrays", false, true },
|
||||
{ "GL_ANGLE_translated_shader_source", false, true },
|
||||
{ "GL_ARB_debug_output", BGFX_CONFIG_RENDERER_OPENGL >= 43, true },
|
||||
{ "GL_ARB_depth_clamp", BGFX_CONFIG_RENDERER_OPENGL >= 31, true },
|
||||
{ "GL_ARB_framebuffer_sRGB", false, true },
|
||||
{ "GL_ARB_get_program_binary", BGFX_CONFIG_RENDERER_OPENGL >= 41, true },
|
||||
{ "GL_ARB_half_float_vertex", false, true },
|
||||
{ "GL_ARB_instanced_arrays", BGFX_CONFIG_RENDERER_OPENGL >= 33, true },
|
||||
{ "GL_ARB_multisample", false, true },
|
||||
{ "GL_ARB_sampler_objects", BGFX_CONFIG_RENDERER_OPENGL >= 31, true },
|
||||
{ "GL_ARB_seamless_cube_map", BGFX_CONFIG_RENDERER_OPENGL >= 31, true },
|
||||
{ "GL_ARB_texture_float", BGFX_CONFIG_RENDERER_OPENGL >= 31, true },
|
||||
{ "GL_ARB_texture_multisample", false, true },
|
||||
{ "GL_ARB_texture_swizzle", BGFX_CONFIG_RENDERER_OPENGL >= 33, true },
|
||||
{ "GL_ARB_timer_query", false, true },
|
||||
{ "GL_ARB_vertex_array_object", BGFX_CONFIG_RENDERER_OPENGL >= 31, true },
|
||||
{ "GL_ARB_vertex_type_2_10_10_10_rev", false, true },
|
||||
{ "GL_ATI_meminfo", false, true },
|
||||
{ "GL_CHROMIUM_framebuffer_multisample", false, true },
|
||||
{ "GL_CHROMIUM_texture_compression_dxt3", false, true },
|
||||
{ "GL_CHROMIUM_texture_compression_dxt5", false, true },
|
||||
{ "GL_EXT_bgra", false, true },
|
||||
{ "GL_EXT_blend_color", BGFX_CONFIG_RENDERER_OPENGL >= 31, true },
|
||||
{ "GL_EXT_blend_minmax", BGFX_CONFIG_RENDERER_OPENGL >= 31, true },
|
||||
{ "GL_EXT_blend_subtract", BGFX_CONFIG_RENDERER_OPENGL >= 31, true },
|
||||
{ "GL_EXT_framebuffer_blit", BGFX_CONFIG_RENDERER_OPENGL >= 31, true },
|
||||
{ "GL_EXT_framebuffer_sRGB", false, true },
|
||||
{ "GL_EXT_occlusion_query_boolean", false, true },
|
||||
{ "GL_EXT_texture_compression_dxt1", false, true },
|
||||
{ "GL_EXT_texture_compression_latc", false, true },
|
||||
{ "GL_EXT_texture_compression_rgtc", BGFX_CONFIG_RENDERER_OPENGL >= 31, true },
|
||||
{ "GL_EXT_texture_compression_s3tc", false, true },
|
||||
{ "GL_EXT_texture_filter_anisotropic", false, true },
|
||||
{ "GL_EXT_texture_format_BGRA8888", false, true },
|
||||
{ "GL_EXT_texture_sRGB", false, true },
|
||||
{ "GL_EXT_texture_storage", false, true },
|
||||
{ "GL_EXT_texture_swizzle", false, true },
|
||||
{ "GL_EXT_texture_type_2_10_10_10_REV", false, true },
|
||||
{ "GL_EXT_timer_query", false, true },
|
||||
{ "GL_NVX_gpu_memory_info", false, true },
|
||||
{ "GL_OES_get_program_binary", false, false },
|
||||
{ "GL_OES_rgb8_rgba8", false, true },
|
||||
{ "GL_OES_standard_derivatives", false, true },
|
||||
{ "GL_OES_texture_float", false, true },
|
||||
{ "GL_OES_texture_float_linear", false, true },
|
||||
{ "GL_OES_texture_half_float", false, true },
|
||||
{ "GL_OES_texture_half_float_linear", false, true },
|
||||
{ "GL_OES_vertex_array_object", false, !BX_PLATFORM_IOS },
|
||||
{ "GL_OES_vertex_half_float", false, true },
|
||||
{ "GL_OES_vertex_type_10_10_10_2", false, true },
|
||||
{ "GL_ANGLE_instanced_arrays", false, true },
|
||||
{ "GL_ANGLE_translated_shader_source", false, true },
|
||||
{ "GL_ARB_debug_output", BGFX_CONFIG_RENDERER_OPENGL >= 43, true },
|
||||
{ "GL_ARB_depth_clamp", BGFX_CONFIG_RENDERER_OPENGL >= 31, true },
|
||||
{ "GL_ARB_framebuffer_sRGB", false, true },
|
||||
{ "GL_ARB_get_program_binary", BGFX_CONFIG_RENDERER_OPENGL >= 41, true },
|
||||
{ "GL_ARB_half_float_vertex", false, true },
|
||||
{ "GL_ARB_instanced_arrays", BGFX_CONFIG_RENDERER_OPENGL >= 33, true },
|
||||
{ "GL_ARB_multisample", false, true },
|
||||
{ "GL_ARB_sampler_objects", BGFX_CONFIG_RENDERER_OPENGL >= 31, true },
|
||||
{ "GL_ARB_seamless_cube_map", BGFX_CONFIG_RENDERER_OPENGL >= 31, true },
|
||||
{ "GL_ARB_texture_float", BGFX_CONFIG_RENDERER_OPENGL >= 31, true },
|
||||
{ "GL_ARB_texture_multisample", false, true },
|
||||
{ "GL_ARB_texture_swizzle", BGFX_CONFIG_RENDERER_OPENGL >= 33, true },
|
||||
{ "GL_ARB_timer_query", false, true },
|
||||
{ "GL_ARB_vertex_array_object", BGFX_CONFIG_RENDERER_OPENGL >= 31, true },
|
||||
{ "GL_ARB_vertex_type_2_10_10_10_rev", false, true },
|
||||
{ "GL_ATI_meminfo", false, true },
|
||||
{ "GL_CHROMIUM_framebuffer_multisample", false, true },
|
||||
{ "GL_CHROMIUM_texture_compression_dxt3", false, true },
|
||||
{ "GL_CHROMIUM_texture_compression_dxt5", false, true },
|
||||
{ "GL_EXT_bgra", false, true },
|
||||
{ "GL_EXT_blend_color", BGFX_CONFIG_RENDERER_OPENGL >= 31, true },
|
||||
{ "GL_EXT_blend_minmax", BGFX_CONFIG_RENDERER_OPENGL >= 31, true },
|
||||
{ "GL_EXT_blend_subtract", BGFX_CONFIG_RENDERER_OPENGL >= 31, true },
|
||||
{ "GL_EXT_framebuffer_blit", BGFX_CONFIG_RENDERER_OPENGL >= 31, true },
|
||||
{ "GL_EXT_framebuffer_sRGB", false, true },
|
||||
{ "GL_EXT_occlusion_query_boolean", false, true },
|
||||
{ "GL_EXT_texture_compression_dxt1", false, true },
|
||||
{ "GL_EXT_texture_compression_latc", false, true },
|
||||
{ "GL_EXT_texture_compression_rgtc", BGFX_CONFIG_RENDERER_OPENGL >= 31, true },
|
||||
{ "GL_EXT_texture_compression_s3tc", false, true },
|
||||
{ "GL_EXT_texture_filter_anisotropic", false, true },
|
||||
{ "GL_EXT_texture_format_BGRA8888", false, true },
|
||||
{ "GL_EXT_texture_sRGB", false, true },
|
||||
{ "GL_EXT_texture_storage", false, true },
|
||||
{ "GL_EXT_texture_swizzle", false, true },
|
||||
{ "GL_EXT_texture_type_2_10_10_10_REV", false, true },
|
||||
{ "GL_EXT_timer_query", false, true },
|
||||
{ "GL_IMG_multisampled_render_to_texture", false, true },
|
||||
{ "GL_IMG_shader_binary", false, true },
|
||||
{ "GL_IMG_texture_compression_pvrtc", false, true },
|
||||
{ "GL_IMG_texture_format_BGRA8888", false, true },
|
||||
{ "GL_NVX_gpu_memory_info", false, true },
|
||||
{ "GL_OES_compressed_ETC1_RGB8_texture", false, true },
|
||||
{ "GL_OES_depth_texture", false, true },
|
||||
{ "GL_OES_get_program_binary", false, false },
|
||||
{ "GL_OES_rgb8_rgba8", false, true },
|
||||
{ "GL_OES_standard_derivatives", false, true },
|
||||
{ "GL_OES_texture_float", false, true },
|
||||
{ "GL_OES_texture_float_linear", false, true },
|
||||
{ "GL_OES_texture_half_float", false, true },
|
||||
{ "GL_OES_texture_half_float_linear", false, true },
|
||||
{ "GL_OES_vertex_array_object", false, !BX_PLATFORM_IOS },
|
||||
{ "GL_OES_vertex_half_float", false, true },
|
||||
{ "GL_OES_vertex_type_10_10_10_2", false, true },
|
||||
};
|
||||
|
||||
#if BGFX_CONFIG_RENDERER_OPENGLES3
|
||||
|
@ -665,7 +677,9 @@ namespace bgfx
|
|||
|
||||
void setSamplerState(uint32_t _stage, uint32_t _numMips, uint32_t _flags)
|
||||
{
|
||||
#if !BGFX_CONFIG_RENDERER_OPENGLES2
|
||||
#if BGFX_CONFIG_RENDERER_OPENGLES2
|
||||
BX_UNUSED(_stage, _numMips, _flags);
|
||||
#else
|
||||
if (0 == (BGFX_SAMPLER_DEFAULT_FLAGS & _flags) )
|
||||
{
|
||||
GLuint sampler = m_samplerStateCache.find(_flags);
|
||||
|
@ -697,7 +711,7 @@ namespace bgfx
|
|||
{
|
||||
GL_CHECK(glBindSampler(_stage, 0) );
|
||||
}
|
||||
#endif // !BGFX_CONFIG_RENDERER_OPENGLES2
|
||||
#endif // BGFX_CONFIG_RENDERER_OPENGLES2
|
||||
}
|
||||
|
||||
void updateCapture()
|
||||
|
@ -1373,18 +1387,18 @@ namespace bgfx
|
|||
|
||||
void Texture::create(const Memory* _mem, uint32_t _flags)
|
||||
{
|
||||
Dds dds;
|
||||
ImageContainer imageContainer;
|
||||
|
||||
if (parseDds(dds, _mem) )
|
||||
if (imageParse(imageContainer, _mem->data, _mem->size) )
|
||||
{
|
||||
uint8_t numMips = dds.m_numMips;
|
||||
uint8_t numMips = imageContainer.m_numMips;
|
||||
|
||||
if (dds.m_cubeMap)
|
||||
if (imageContainer.m_cubeMap)
|
||||
{
|
||||
init(GL_TEXTURE_CUBE_MAP, numMips, _flags);
|
||||
}
|
||||
#if BGFX_CONFIG_RENDERER_OPENGL|BGFX_CONFIG_RENDERER_OPENGLES3
|
||||
else if (dds.m_depth > 1)
|
||||
else if (imageContainer.m_depth > 1)
|
||||
{
|
||||
init(GL_TEXTURE_3D, numMips, _flags);
|
||||
}
|
||||
|
@ -1394,23 +1408,23 @@ namespace bgfx
|
|||
init(GL_TEXTURE_2D, numMips, _flags);
|
||||
}
|
||||
|
||||
const TextureFormatInfo& tfi = s_textureFormat[dds.m_type];
|
||||
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 (dds.m_cubeMap)
|
||||
if (imageContainer.m_cubeMap)
|
||||
{
|
||||
target = GL_TEXTURE_CUBE_MAP_POSITIVE_X;
|
||||
}
|
||||
|
||||
if (!tfi.m_supported
|
||||
|| TextureFormat::Unknown < dds.m_type)
|
||||
|| TextureFormat::Unknown < imageContainer.m_type)
|
||||
{
|
||||
uint8_t textureFormat = dds.m_type;
|
||||
TextureFormat::Enum textureFormat = imageContainer.m_type;
|
||||
bool decompress = TextureFormat::Unknown > textureFormat;
|
||||
uint32_t bpp = tfi.m_bpp;
|
||||
uint32_t bpp = getBitsPerPixel(imageContainer.m_type);
|
||||
|
||||
if (decompress)
|
||||
{
|
||||
|
@ -1419,7 +1433,7 @@ namespace bgfx
|
|||
internalFmt = tfi.m_internalFmt;
|
||||
m_fmt = tfi.m_fmt;
|
||||
m_type = tfi.m_type;
|
||||
bpp = tfi.m_bpp;
|
||||
bpp = getBitsPerPixel(textureFormat);
|
||||
}
|
||||
|
||||
bool swizzle = GL_RGBA == m_fmt;
|
||||
|
@ -1434,13 +1448,13 @@ namespace bgfx
|
|||
}
|
||||
#endif // BGFX_CONFIG_RENDERER_OPENGL
|
||||
|
||||
uint8_t* bits = (uint8_t*)g_realloc(NULL, dds.m_width*dds.m_height*bpp/8);
|
||||
uint8_t* bits = (uint8_t*)g_realloc(NULL, imageContainer.m_width*imageContainer.m_height*bpp/8);
|
||||
|
||||
for (uint8_t side = 0, numSides = dds.m_cubeMap ? 6 : 1; side < numSides; ++side)
|
||||
for (uint8_t side = 0, numSides = imageContainer.m_cubeMap ? 6 : 1; side < numSides; ++side)
|
||||
{
|
||||
uint32_t width = dds.m_width;
|
||||
uint32_t height = dds.m_height;
|
||||
uint32_t depth = dds.m_depth;
|
||||
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)
|
||||
{
|
||||
|
@ -1449,7 +1463,7 @@ namespace bgfx
|
|||
depth = bx::uint32_max(1, depth);
|
||||
|
||||
Mip mip;
|
||||
if (getRawImageData(dds, side, lod, _mem, mip) )
|
||||
if (imageGetRawData(imageContainer, side, lod, _mem->data, _mem->size, mip) )
|
||||
{
|
||||
mip.decode(bits);
|
||||
|
||||
|
@ -1483,11 +1497,11 @@ namespace bgfx
|
|||
{
|
||||
m_compressed = true;
|
||||
|
||||
for (uint8_t side = 0, numSides = dds.m_cubeMap ? 6 : 1; side < numSides; ++side)
|
||||
for (uint8_t side = 0, numSides = imageContainer.m_cubeMap ? 6 : 1; side < numSides; ++side)
|
||||
{
|
||||
uint32_t width = dds.m_width;
|
||||
uint32_t height = dds.m_height;
|
||||
uint32_t depth = dds.m_depth;
|
||||
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)
|
||||
{
|
||||
|
@ -1496,7 +1510,7 @@ namespace bgfx
|
|||
depth = bx::uint32_max(1, depth);
|
||||
|
||||
Mip mip;
|
||||
if (getRawImageData(dds, side, ii, _mem, mip) )
|
||||
if (imageGetRawData(imageContainer, side, ii, _mem->data, _mem->size, mip) )
|
||||
{
|
||||
compressedTexImage(target+side
|
||||
, ii
|
||||
|
@ -1558,7 +1572,7 @@ namespace bgfx
|
|||
target = GL_TEXTURE_CUBE_MAP_POSITIVE_X;
|
||||
}
|
||||
|
||||
uint32_t bpp = tfi.m_bpp;
|
||||
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;
|
||||
|
@ -2462,6 +2476,7 @@ namespace bgfx
|
|||
;
|
||||
s_textureFormat[TextureFormat::BC4].m_supported = bc45Supported;
|
||||
s_textureFormat[TextureFormat::BC5].m_supported = bc45Supported;
|
||||
s_textureFormat[TextureFormat::ETC1].m_supported = s_extension[Extension::OES_compressed_ETC1_RGB8_texture].m_supported;
|
||||
|
||||
s_renderCtx.m_vaoSupport = !!BGFX_CONFIG_RENDERER_OPENGLES3
|
||||
|| s_extension[Extension::ARB_vertex_array_object].m_supported
|
||||
|
|
|
@ -171,6 +171,10 @@ typedef void (*PFNGLGETTRANSLATEDSHADERSOURCEANGLEPROC)(GLuint shader, GLsizei b
|
|||
# define GL_COMPRESSED_RED_GREEN_RGTC2_EXT 0x8DBD
|
||||
# endif // GL_COMPRESSED_RED_GREEN_RGTC2_EXT
|
||||
|
||||
# ifndef GL_ETC1_RGB8_OES
|
||||
# define GL_ETC1_RGB8_OES 0x8D64
|
||||
# endif // GL_ETC1_RGB8_OES
|
||||
|
||||
# ifndef GL_TRANSLATED_SHADER_SOURCE_LENGTH_ANGLE
|
||||
# define GL_TRANSLATED_SHADER_SOURCE_LENGTH_ANGLE 0x93A0
|
||||
# endif // GL_TRANSLATED_SHADER_SOURCE_LENGTH_ANGLE
|
||||
|
|
|
@ -11,7 +11,7 @@
|
|||
#include "bgfx_p.h"
|
||||
using namespace bgfx;
|
||||
|
||||
#include "dds.h"
|
||||
#include "image.h"
|
||||
|
||||
#if 0
|
||||
# define BX_TRACE(_format, ...) fprintf(stderr, "" _format "\n", ##__VA_ARGS__)
|
||||
|
@ -83,47 +83,45 @@ namespace bgfx
|
|||
}
|
||||
}
|
||||
|
||||
long int fsize(FILE* _file)
|
||||
{
|
||||
long int pos = ftell(_file);
|
||||
fseek(_file, 0L, SEEK_END);
|
||||
long int size = ftell(_file);
|
||||
fseek(_file, pos, SEEK_SET);
|
||||
return size;
|
||||
}
|
||||
|
||||
int main(int _argc, const char* _argv[])
|
||||
{
|
||||
bx::CommandLine cmdLine(_argc, _argv);
|
||||
|
||||
FILE* file = fopen(_argv[1], "rb");
|
||||
uint32_t size = fsize(file);
|
||||
const char* inputFileName = cmdLine.findOption('i');
|
||||
|
||||
if (NULL == inputFileName)
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
|
||||
bx::CrtFileReader reader;
|
||||
bx::open(&reader, inputFileName);
|
||||
uint32_t size = (uint32_t)bx::getSize(&reader);
|
||||
const Memory* mem = alloc(size);
|
||||
size_t readSize = fread(mem->data, 1, size, file);
|
||||
BX_UNUSED(readSize);
|
||||
fclose(file);
|
||||
bx::read(&reader, mem->data, mem->size);
|
||||
bx::close(&reader);
|
||||
|
||||
Dds dds;
|
||||
ImageContainer imageContainer;
|
||||
|
||||
if (parseDds(dds, mem) )
|
||||
if (imageParse(imageContainer, mem->data, mem->size) )
|
||||
{
|
||||
bool decompress = cmdLine.hasArg('d');
|
||||
|
||||
if (decompress
|
||||
|| 0 == dds.m_type)
|
||||
|| 0 == imageContainer.m_type)
|
||||
{
|
||||
for (uint8_t side = 0, numSides = dds.m_cubeMap ? 6 : 1; side < numSides; ++side)
|
||||
for (uint8_t side = 0, numSides = imageContainer.m_cubeMap ? 6 : 1; side < numSides; ++side)
|
||||
{
|
||||
uint32_t width = dds.m_width;
|
||||
uint32_t height = dds.m_height;
|
||||
uint32_t width = imageContainer.m_width;
|
||||
uint32_t height = imageContainer.m_height;
|
||||
|
||||
for (uint32_t lod = 0, num = dds.m_numMips; lod < num; ++lod)
|
||||
for (uint32_t lod = 0, num = imageContainer.m_numMips; lod < num; ++lod)
|
||||
{
|
||||
width = bx::uint32_max(1, width);
|
||||
height = bx::uint32_max(1, height);
|
||||
|
||||
Mip mip;
|
||||
if (getRawImageData(dds, side, lod, mem, mip) )
|
||||
if (imageGetRawData(imageContainer, side, lod, mem->data, mem->size, mip) )
|
||||
{
|
||||
uint32_t dstpitch = width*4;
|
||||
uint8_t* bits = (uint8_t*)malloc(dstpitch*height);
|
||||
|
@ -169,16 +167,19 @@ int main(int _argc, const char* _argv[])
|
|||
}
|
||||
else
|
||||
{
|
||||
for (uint32_t lod = 0, num = dds.m_numMips; lod < num; ++lod)
|
||||
for (uint32_t lod = 0, num = imageContainer.m_numMips; lod < num; ++lod)
|
||||
{
|
||||
Mip mip;
|
||||
if (getRawImageData(dds, 0, lod, mem, mip) )
|
||||
if (imageGetRawData(imageContainer, 0, lod, mem->data, mem->size, mip) )
|
||||
{
|
||||
char filePath[256];
|
||||
bx::snprintf(filePath, sizeof(filePath), "mip%d.bin", lod);
|
||||
file = fopen(filePath, "wb");
|
||||
fwrite(mip.m_data, 1, mip.m_size, file);
|
||||
fclose(file);
|
||||
|
||||
bx::CrtFileWriter writer;
|
||||
bx::open(&writer, filePath);
|
||||
printf("mip%d, size %d\n", lod, mip.m_size);
|
||||
bx::write(&writer, mip.m_data, mip.m_size);
|
||||
bx::close(&writer);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
Loading…
Add table
Reference in a new issue