Procházet zdrojové kódy

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

bkaradzic před 12 roky
rodič
revize
488483a945
13 změnil soubory, kde provedl 680 přidání a 1010 odebrání
  1. 25 1
      include/bgfx.h
  2. 18 13
      src/bgfx_p.h
  3. 4 0
      src/config.h
  4. 210 202
      src/image.cpp
  5. 10 7
      src/image.h
  6. 74 234
      src/renderer_d3d11.cpp
  7. 3 1
      src/renderer_d3d11.h
  8. 111 173
      src/renderer_d3d9.cpp
  9. 3 2
      src/renderer_d3d9.h
  10. 213 353
      src/renderer_gl.cpp
  11. 3 3
      src/renderer_gl.h
  12. 1 16
      src/renderer_null.cpp
  13. 5 5
      tools/texturec/texturec.cpp

+ 25 - 1
include/bgfx.h

@@ -319,7 +319,6 @@ namespace bgfx
 			PTC24,  // PVRTC2 RGBA 4BPP
 			Unknown,
 			L8,
-			BGRX8,
 			BGRA8,
 			RGBA16,
 			RGBA16F,
@@ -749,12 +748,37 @@ namespace bgfx
 	TextureHandle createTexture(const Memory* _mem, uint32_t _flags = BGFX_TEXTURE_NONE, TextureInfo* _info = NULL);
 
 	/// Create 2D texture.
+	///
+	/// @param _width
+	/// @param _height
+	/// @param _numMips
+	/// @param _format
+	/// @param _flags
+	/// @param _mem
+	///
 	TextureHandle createTexture2D(uint16_t _width, uint16_t _height, uint8_t _numMips, TextureFormat::Enum _format, uint32_t _flags = BGFX_TEXTURE_NONE, const Memory* _mem = NULL);
 
 	/// Create 3D texture.
+	///
+	/// @param _width
+	/// @param _height
+	/// @param _depth
+	/// @param _numMips
+	/// @param _format
+	/// @param _flags
+	/// @param _mem
+	///
 	TextureHandle createTexture3D(uint16_t _width, uint16_t _height, uint16_t _depth, uint8_t _numMips, TextureFormat::Enum _format, uint32_t _flags = BGFX_TEXTURE_NONE, const Memory* _mem = NULL);
 
 	/// Create Cube texture.
+	///
+	/// @param _sides
+	/// @param _width
+	/// @param _numMips
+	/// @param _format
+	/// @param _flags
+	/// @param _mem
+	///
 	TextureHandle createTextureCube(uint16_t _sides, uint16_t _width, uint8_t _numMips, TextureFormat::Enum _format, uint32_t _flags = BGFX_TEXTURE_NONE, const Memory* _mem = NULL);
 
 	/// Update 2D texture.

+ 18 - 13
src/bgfx_p.h

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

+ 4 - 0
src/config.h

@@ -91,6 +91,10 @@
 #	define BGFX_CONFIG_DEBUG_PERFHUD 0
 #endif // BGFX_CONFIG_DEBUG_NVPERFHUD
 
+#ifndef BGFX_CONFIG_RENDERER_USE_EXTENSIONS
+#	define BGFX_CONFIG_RENDERER_USE_EXTENSIONS 1
+#endif // BGFX_CONFIG_RENDERER_USE_EXTENSIONS
+
 /// DX9 PIX markers
 #ifndef BGFX_CONFIG_DEBUG_PIX
 #	define BGFX_CONFIG_DEBUG_PIX BGFX_CONFIG_DEBUG

+ 210 - 202
src/image.cpp

@@ -30,7 +30,6 @@ namespace bgfx
 		4,  // PTC24
 		0,  // Unknown
 		8,  // L8
-		32, // BGRX8
 		32, // BGRA8
 		64, // RGBA16
 		64, // RGBA16F
@@ -564,174 +563,6 @@ namespace bgfx
 		}
 	}
 
-	void Mip::decode(uint8_t* _dst)
-	{
-		const uint8_t* src = m_data;
-
-		if (TextureFormat::Unknown > m_type)
-		{
-			uint32_t width = m_width/4;
-			uint32_t height = m_height/4;
-			uint32_t pitch = m_width*4;
-
-			uint8_t temp[16*4];
-
-			switch (m_type)
-			{
-			case TextureFormat::BC1:
-				for (uint32_t yy = 0; yy < height; ++yy)
-				{
-					for (uint32_t xx = 0; xx < width; ++xx)
-					{
-						decodeBlockDxt1(temp, src);
-						src += 8;
-
-						uint8_t* dst = &_dst[(yy*pitch+xx*4)*4];
-						memcpy(&dst[0*pitch], &temp[ 0], 16);
-						memcpy(&dst[1*pitch], &temp[16], 16);
-						memcpy(&dst[2*pitch], &temp[32], 16);
-						memcpy(&dst[3*pitch], &temp[48], 16);
-					}
-				}
-				break;
-
-			case TextureFormat::BC2:
-				for (uint32_t yy = 0; yy < height; ++yy)
-				{
-					for (uint32_t xx = 0; xx < width; ++xx)
-					{
-						decodeBlockDxt23A(temp+3, src);
-						src += 8;
-						decodeBlockDxt(temp, src);
-						src += 8;
-
-						uint8_t* dst = &_dst[(yy*pitch+xx*4)*4];
-						memcpy(&dst[0*pitch], &temp[ 0], 16);
-						memcpy(&dst[1*pitch], &temp[16], 16);
-						memcpy(&dst[2*pitch], &temp[32], 16);
-						memcpy(&dst[3*pitch], &temp[48], 16);
-					}
-				}
-				break;
-
-			case TextureFormat::BC3:
-				for (uint32_t yy = 0; yy < height; ++yy)
-				{
-					for (uint32_t xx = 0; xx < width; ++xx)
-					{
-						decodeBlockDxt45A(temp+3, src);
-						src += 8;
-						decodeBlockDxt(temp, src);
-						src += 8;
-
-						uint8_t* dst = &_dst[(yy*pitch+xx*4)*4];
-						memcpy(&dst[0*pitch], &temp[ 0], 16);
-						memcpy(&dst[1*pitch], &temp[16], 16);
-						memcpy(&dst[2*pitch], &temp[32], 16);
-						memcpy(&dst[3*pitch], &temp[48], 16);
-					}
-				}
-				break;
-
-			case TextureFormat::BC4:
-				for (uint32_t yy = 0; yy < height; ++yy)
-				{
-					for (uint32_t xx = 0; xx < width; ++xx)
-					{
-						decodeBlockDxt45A(temp, src);
-						src += 8;
-
-						uint8_t* dst = &_dst[(yy*pitch+xx*4)*4];
-						memcpy(&dst[0*pitch], &temp[ 0], 16);
-						memcpy(&dst[1*pitch], &temp[16], 16);
-						memcpy(&dst[2*pitch], &temp[32], 16);
-						memcpy(&dst[3*pitch], &temp[48], 16);
-					}
-				}
-				break;
-
-			case TextureFormat::BC5:
-				for (uint32_t yy = 0; yy < height; ++yy)
-				{
-					for (uint32_t xx = 0; xx < width; ++xx)
-					{
-						decodeBlockDxt45A(temp+1, src);
-						src += 8;
-						decodeBlockDxt45A(temp+2, src);
-						src += 8;
-
-						for (uint32_t ii = 0; ii < 16; ++ii)
-						{
-							float nx = temp[ii*4+2]*2.0f/255.0f - 1.0f;
-							float ny = temp[ii*4+1]*2.0f/255.0f - 1.0f;
-							float nz = sqrtf(1.0f - nx*nx - ny*ny);
-							temp[ii*4+0] = uint8_t( (nz + 1.0f)*255.0f/2.0f);
-							temp[ii*4+3] = 0;
-						}
-
-						uint8_t* dst = &_dst[(yy*pitch+xx*4)*4];
-						memcpy(&dst[0*pitch], &temp[ 0], 16);
-						memcpy(&dst[1*pitch], &temp[16], 16);
-						memcpy(&dst[2*pitch], &temp[32], 16);
-						memcpy(&dst[3*pitch], &temp[48], 16);
-					}
-				}
-				break;
-
-			case TextureFormat::ETC1:
-				for (uint32_t yy = 0; yy < height; ++yy)
-				{
-					for (uint32_t xx = 0; xx < width; ++xx)
-					{
-						decodeBlockEtc1(temp, src);
-						src += 8;
-
-						uint8_t* dst = &_dst[(yy*pitch+xx*4)*4];
-						memcpy(&dst[0*pitch], &temp[ 0], 16);
-						memcpy(&dst[1*pitch], &temp[16], 16);
-						memcpy(&dst[2*pitch], &temp[32], 16);
-						memcpy(&dst[3*pitch], &temp[48], 16);
-					}
-				}
-				break;
-
-			default:
-				// Decompression not implemented... Make ugly red-yellow checkerboard texture.
-				imageCheckerboard(m_width, m_height, 16, UINT32_C(0xffff0000), UINT32_C(0xffffff00), _dst);
-				break;
-			}
-		}
-		else
-		{
-			uint32_t width = m_width;
-			uint32_t height = m_height;
-
-			if (m_bpp == 8
-			||  m_bpp == 32
-			||  m_bpp == 64)
-			{
-				uint32_t pitch = m_width*m_bpp/8;
-				memcpy(_dst, src, pitch*height);
-			}
-			else
-			{
-				uint32_t pitch = m_width*4;
-				for (uint32_t yy = 0; yy < height; ++yy)
-				{
-					uint8_t* dst = &_dst[yy*pitch];
-
-					for (uint32_t xx = 0; xx < width; ++xx)
-					{
-						memcpy(dst, src, 3);
-						dst[3] = 255;
-						dst += 4;
-						src += 3;
-					}
-				}
-			}
-		}
-	}
-
 // DDS
 #define DDS_MAGIC             BX_MAKEFOURCC('D', 'D', 'S', ' ')
 #define DDS_HEADER_SIZE       124
@@ -803,7 +634,6 @@ namespace bgfx
 		{ DDS_BC5U,                  TextureFormat::BC5     },
 		{ D3DFMT_A16B16G16R16,       TextureFormat::RGBA16  },
 		{ D3DFMT_A16B16G16R16F,      TextureFormat::RGBA16F },
-		{ DDPF_RGB,                  TextureFormat::BGRX8   },
 		{ DDPF_RGB|DDPF_ALPHAPIXELS, TextureFormat::BGRA8   },
 		{ DDPF_INDEXED,              TextureFormat::L8      },
 		{ DDPF_LUMINANCE,            TextureFormat::L8      },
@@ -889,31 +719,30 @@ namespace bgfx
 
 		uint8_t bpp = 0;
 		uint8_t blockSize = 1;
-		TextureFormat::Enum type = TextureFormat::Unknown;
+		TextureFormat::Enum format = TextureFormat::Unknown;
 		bool hasAlpha = pixelFlags & DDPF_ALPHAPIXELS;
 
-		uint32_t format = pixelFlags & DDPF_FOURCC ? fourcc : pixelFlags;
+		uint32_t ddsFormat = pixelFlags & DDPF_FOURCC ? fourcc : pixelFlags;
 		for (uint32_t ii = 0; ii < BX_COUNTOF(s_translateDdsFormat); ++ii)
 		{
-			if (s_translateDdsFormat[ii].m_format == format)
+			if (s_translateDdsFormat[ii].m_format == ddsFormat)
 			{
-				type = s_translateDdsFormat[ii].m_textureFormat;
+				format = s_translateDdsFormat[ii].m_textureFormat;
 				break;
 			}
 		}
 
-		bpp = TextureFormat::BGRX8 == type // special case to force conversion to 32-bpp.
-			? 24
-			: getBitsPerPixel(type)
-			;
-		blockSize = type < TextureFormat::Unknown ? 4*4 : 1;
+		bpp = getBitsPerPixel(format);
+		blockSize = format < TextureFormat::Unknown ? 4*4 : 1;
 		blockSize = blockSize*bpp/8;
 
-		_imageContainer.m_type = type;
+		_imageContainer.m_data = NULL;
+		_imageContainer.m_size = 0;
 		_imageContainer.m_offset = DDS_IMAGE_DATA_OFFSET;
 		_imageContainer.m_width = width;
 		_imageContainer.m_height = height;
 		_imageContainer.m_depth = depth;
+		_imageContainer.m_format = format;
 		_imageContainer.m_blockSize = blockSize;
 		_imageContainer.m_numMips = (caps[0] & DDSCAPS_MIPMAP) ? mips : 1;
 		_imageContainer.m_bpp = bpp;
@@ -921,7 +750,7 @@ namespace bgfx
 		_imageContainer.m_cubeMap = cubeMap;
 		_imageContainer.m_ktx = false;
 
-		return TextureFormat::Unknown != type;
+		return TextureFormat::Unknown != format;
 	}
 
 // KTX
@@ -1043,30 +872,29 @@ namespace bgfx
 
 		uint8_t bpp = 0;
 		uint8_t blockSize = 1;
-		TextureFormat::Enum type = TextureFormat::Unknown;
+		TextureFormat::Enum format = TextureFormat::Unknown;
 		bool hasAlpha = false;
 
 		for (uint32_t ii = 0; ii < BX_COUNTOF(s_translateKtxFormat); ++ii)
 		{
 			if (s_translateKtxFormat[ii].m_format == glInternalFormat)
 			{
-				type = s_translateKtxFormat[ii].m_textureFormat;
+				format = s_translateKtxFormat[ii].m_textureFormat;
 				break;
 			}
 		}
 
-		bpp = TextureFormat::BGRX8 == type // special case to force conversion to 32-bpp.
-			? 24
-			: getBitsPerPixel(type)
-			;
-		blockSize = type < TextureFormat::Unknown ? 4*4 : 1;
+		bpp = getBitsPerPixel(format);
+		blockSize = format < TextureFormat::Unknown ? 4*4 : 1;
 		blockSize = blockSize*bpp/8;
 
-		_imageContainer.m_type = type;
+		_imageContainer.m_data = NULL;
+		_imageContainer.m_size = 0;
 		_imageContainer.m_offset = (uint32_t)offset;
 		_imageContainer.m_width = width;
 		_imageContainer.m_height = height;
 		_imageContainer.m_depth = depth;
+		_imageContainer.m_format = format;
 		_imageContainer.m_blockSize = blockSize;
 		_imageContainer.m_numMips = numMips;
 		_imageContainer.m_bpp = bpp;
@@ -1074,7 +902,7 @@ namespace bgfx
 		_imageContainer.m_cubeMap = numFaces > 1;
 		_imageContainer.m_ktx = true;
 
-		return TextureFormat::Unknown != type;
+		return TextureFormat::Unknown != format;
 	}
 
 // PVR3
@@ -1164,7 +992,7 @@ namespace bgfx
 
 		uint8_t bpp = 0;
 		uint8_t blockSize = 1;
-		TextureFormat::Enum type = TextureFormat::Unknown;
+		TextureFormat::Enum format = TextureFormat::Unknown;
 		bool hasAlpha = false;
 
 		for (uint32_t ii = 0; ii < BX_COUNTOF(s_translatePvr3Format); ++ii)
@@ -1172,23 +1000,22 @@ namespace bgfx
 			if (s_translatePvr3Format[ii].m_format == pixelFormat
 			&&  channelType == (s_translatePvr3Format[ii].m_channelTypeMask & channelType) )
 			{
-				type = s_translatePvr3Format[ii].m_textureFormat;
+				format = s_translatePvr3Format[ii].m_textureFormat;
 				break;
 			}
 		}
 
-		bpp = TextureFormat::BGRX8 == type // special case to force conversion to 32-bpp.
-			? 24
-			: getBitsPerPixel(type)
-			;
-		blockSize = type < TextureFormat::Unknown ? 4*4 : 1;
+		bpp = getBitsPerPixel(format);
+		blockSize = format < TextureFormat::Unknown ? 4*4 : 1;
 		blockSize = blockSize*bpp/8;
 
-		_imageContainer.m_type = type;
+		_imageContainer.m_data = NULL;
+		_imageContainer.m_size = 0;
 		_imageContainer.m_offset = (uint32_t)offset;
 		_imageContainer.m_width = width;
 		_imageContainer.m_height = height;
 		_imageContainer.m_depth = depth;
+		_imageContainer.m_format = format;
 		_imageContainer.m_blockSize = blockSize;
 		_imageContainer.m_numMips = numMips;
 		_imageContainer.m_bpp = bpp;
@@ -1196,7 +1023,7 @@ namespace bgfx
 		_imageContainer.m_cubeMap = numFaces > 1;
 		_imageContainer.m_ktx = false;
 
-		return TextureFormat::Unknown != type;
+		return TextureFormat::Unknown != format;
 	}
 
 	bool imageParse(ImageContainer& _imageContainer, bx::ReaderSeekerI* _reader)
@@ -1216,6 +1043,39 @@ namespace bgfx
 		{
 			return imageParsePvr3(_imageContainer, _reader);
 		}
+		else if (BGFX_CHUNK_MAGIC_TEX == magic)
+		{
+			TextureCreate tc;
+			bx::read(_reader, tc);
+
+			uint32_t bpp = getBitsPerPixel(TextureFormat::Enum(tc.m_format) );
+			uint32_t blockSize = tc.m_format < TextureFormat::Unknown ? 4*4 : 1;
+			blockSize = blockSize*bpp/8;
+
+			_imageContainer.m_format = tc.m_format;
+			_imageContainer.m_offset = UINT32_MAX;
+			if (NULL == tc.m_mem)
+			{
+				_imageContainer.m_data = NULL;
+				_imageContainer.m_size = 0;
+			}
+			else
+			{
+				_imageContainer.m_data = tc.m_mem->data;
+				_imageContainer.m_size = tc.m_mem->size;
+			}
+			_imageContainer.m_width = tc.m_width;
+			_imageContainer.m_height = tc.m_height;
+			_imageContainer.m_depth = tc.m_depth;
+			_imageContainer.m_blockSize = blockSize;
+			_imageContainer.m_numMips = tc.m_numMips;
+			_imageContainer.m_bpp = getBitsPerPixel(TextureFormat::Enum(tc.m_format) );
+			_imageContainer.m_hasAlpha = false;
+			_imageContainer.m_cubeMap = tc.m_cubeMap;
+			_imageContainer.m_ktx = false;
+
+			return true;
+		}
 
 		return false;
 	}
@@ -1226,14 +1086,162 @@ namespace bgfx
 		return imageParse(_imageContainer, &reader);
 	}
 
-	bool imageGetRawData(const ImageContainer& _imageContainer, uint8_t _side, uint8_t _lod, const void* _data, uint32_t _size, Mip& _mip)
+	void imageDecodeToBgra8(uint8_t* _dst, const uint8_t* _src, uint32_t _width, uint32_t _height, uint8_t _type)
+	{
+		const uint8_t* src = _src;
+
+		uint32_t width = _width/4;
+		uint32_t height = _height/4;
+		uint32_t pitch = _width*4;
+
+		uint8_t temp[16*4];
+
+		switch (_type)
+		{
+		case TextureFormat::BC1:
+			for (uint32_t yy = 0; yy < height; ++yy)
+			{
+				for (uint32_t xx = 0; xx < width; ++xx)
+				{
+					decodeBlockDxt1(temp, src);
+					src += 8;
+
+					uint8_t* dst = &_dst[(yy*pitch+xx*4)*4];
+					memcpy(&dst[0*pitch], &temp[ 0], 16);
+					memcpy(&dst[1*pitch], &temp[16], 16);
+					memcpy(&dst[2*pitch], &temp[32], 16);
+					memcpy(&dst[3*pitch], &temp[48], 16);
+				}
+			}
+			break;
+
+		case TextureFormat::BC2:
+			for (uint32_t yy = 0; yy < height; ++yy)
+			{
+				for (uint32_t xx = 0; xx < width; ++xx)
+				{
+					decodeBlockDxt23A(temp+3, src);
+					src += 8;
+					decodeBlockDxt(temp, src);
+					src += 8;
+
+					uint8_t* dst = &_dst[(yy*pitch+xx*4)*4];
+					memcpy(&dst[0*pitch], &temp[ 0], 16);
+					memcpy(&dst[1*pitch], &temp[16], 16);
+					memcpy(&dst[2*pitch], &temp[32], 16);
+					memcpy(&dst[3*pitch], &temp[48], 16);
+				}
+			}
+			break;
+
+		case TextureFormat::BC3:
+			for (uint32_t yy = 0; yy < height; ++yy)
+			{
+				for (uint32_t xx = 0; xx < width; ++xx)
+				{
+					decodeBlockDxt45A(temp+3, src);
+					src += 8;
+					decodeBlockDxt(temp, src);
+					src += 8;
+
+					uint8_t* dst = &_dst[(yy*pitch+xx*4)*4];
+					memcpy(&dst[0*pitch], &temp[ 0], 16);
+					memcpy(&dst[1*pitch], &temp[16], 16);
+					memcpy(&dst[2*pitch], &temp[32], 16);
+					memcpy(&dst[3*pitch], &temp[48], 16);
+				}
+			}
+			break;
+
+		case TextureFormat::BC4:
+			for (uint32_t yy = 0; yy < height; ++yy)
+			{
+				for (uint32_t xx = 0; xx < width; ++xx)
+				{
+					decodeBlockDxt45A(temp, src);
+					src += 8;
+
+					uint8_t* dst = &_dst[(yy*pitch+xx*4)*4];
+					memcpy(&dst[0*pitch], &temp[ 0], 16);
+					memcpy(&dst[1*pitch], &temp[16], 16);
+					memcpy(&dst[2*pitch], &temp[32], 16);
+					memcpy(&dst[3*pitch], &temp[48], 16);
+				}
+			}
+			break;
+
+		case TextureFormat::BC5:
+			for (uint32_t yy = 0; yy < height; ++yy)
+			{
+				for (uint32_t xx = 0; xx < width; ++xx)
+				{
+					decodeBlockDxt45A(temp+1, src);
+					src += 8;
+					decodeBlockDxt45A(temp+2, src);
+					src += 8;
+
+					for (uint32_t ii = 0; ii < 16; ++ii)
+					{
+						float nx = temp[ii*4+2]*2.0f/255.0f - 1.0f;
+						float ny = temp[ii*4+1]*2.0f/255.0f - 1.0f;
+						float nz = sqrtf(1.0f - nx*nx - ny*ny);
+						temp[ii*4+0] = uint8_t( (nz + 1.0f)*255.0f/2.0f);
+						temp[ii*4+3] = 0;
+					}
+
+					uint8_t* dst = &_dst[(yy*pitch+xx*4)*4];
+					memcpy(&dst[0*pitch], &temp[ 0], 16);
+					memcpy(&dst[1*pitch], &temp[16], 16);
+					memcpy(&dst[2*pitch], &temp[32], 16);
+					memcpy(&dst[3*pitch], &temp[48], 16);
+				}
+			}
+			break;
+
+		case TextureFormat::ETC1:
+			for (uint32_t yy = 0; yy < height; ++yy)
+			{
+				for (uint32_t xx = 0; xx < width; ++xx)
+				{
+					decodeBlockEtc1(temp, src);
+					src += 8;
+
+					uint8_t* dst = &_dst[(yy*pitch+xx*4)*4];
+					memcpy(&dst[0*pitch], &temp[ 0], 16);
+					memcpy(&dst[1*pitch], &temp[16], 16);
+					memcpy(&dst[2*pitch], &temp[32], 16);
+					memcpy(&dst[3*pitch], &temp[48], 16);
+				}
+			}
+			break;
+
+		default:
+			// Decompression not implemented... Make ugly red-yellow checkerboard texture.
+			imageCheckerboard(_width, _height, 16, UINT32_C(0xffff0000), UINT32_C(0xffffff00), _dst);
+			break;
+		}
+	}
+
+	bool imageGetRawData(const ImageContainer& _imageContainer, uint8_t _side, uint8_t _lod, const void* _data, uint32_t _size, ImageMip& _mip)
 	{
 		const uint32_t blockSize = _imageContainer.m_blockSize;
 		uint32_t offset = _imageContainer.m_offset;
 		const uint8_t bpp = _imageContainer.m_bpp;
-		TextureFormat::Enum type = _imageContainer.m_type;
+		TextureFormat::Enum type = TextureFormat::Enum(_imageContainer.m_format);
 		bool hasAlpha = _imageContainer.m_hasAlpha;
 
+		if (UINT32_MAX == _imageContainer.m_offset)
+		{
+			if (NULL == _imageContainer.m_data)
+			{
+				return false;
+			}
+
+			offset = 0;
+			_data = _imageContainer.m_data;
+			_size = _imageContainer.m_size;
+		}
+
 		for (uint8_t side = 0, numSides = _imageContainer.m_cubeMap ? 6 : 1; side < numSides; ++side)
 		{
 			uint32_t width  = _imageContainer.m_width;
@@ -1269,7 +1277,7 @@ namespace bgfx
 					_mip.m_size = size;
 					_mip.m_data = (const uint8_t*)_data + offset;
 					_mip.m_bpp = bpp;
-					_mip.m_type = type;
+					_mip.m_format = type;
 					_mip.m_hasAlpha = hasAlpha;
 					return true;
 				}

+ 10 - 7
src/image.h

@@ -12,11 +12,13 @@ namespace bgfx
 {
 	struct ImageContainer
 	{
-		TextureFormat::Enum m_type;
+		void* m_data;
+		uint32_t m_size;
 		uint32_t m_offset;
 		uint32_t m_width;
 		uint32_t m_height;
 		uint32_t m_depth;
+		uint8_t m_format;
 		uint8_t m_blockSize;
 		uint8_t m_numMips;
 		uint8_t m_bpp;
@@ -25,18 +27,16 @@ namespace bgfx
 		bool m_ktx;
 	};
 
-	struct Mip
+	struct ImageMip
 	{
 		uint32_t m_width;
 		uint32_t m_height;
 		uint32_t m_blockSize;
 		uint32_t m_size;
 		uint8_t m_bpp;
-		uint8_t m_type;
+		uint8_t m_format;
 		bool m_hasAlpha;
 		const uint8_t* m_data;
-
-		void decode(uint8_t* _dst);
 	};
 
 	///
@@ -61,10 +61,13 @@ namespace bgfx
 	bool imageParse(ImageContainer& _imageContainer, bx::ReaderSeekerI* _reader);
 
 	///
-	bool imageParse(ImageContainer& _dds, const void* _data, uint32_t _size);
+	bool imageParse(ImageContainer& _imageContainer, const void* _data, uint32_t _size);
+
+	///
+	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, Mip& _mip);
+	bool imageGetRawData(const ImageContainer& _dds, uint8_t _side, uint8_t _index, const void* _data, uint32_t _size, ImageMip& _mip);
 
 } // namespace bgfx
 

+ 74 - 234
src/renderer_d3d11.cpp

@@ -200,7 +200,6 @@ namespace bgfx
 		{ DXGI_FORMAT_UNKNOWN            }, // PTC24
 		{ DXGI_FORMAT_UNKNOWN            }, // Unknown
 		{ DXGI_FORMAT_R8_UNORM           }, // L8
-		{ DXGI_FORMAT_B8G8R8A8_UNORM     }, // BGRX8
 		{ DXGI_FORMAT_B8G8R8A8_UNORM     }, // BGRA8
 		{ DXGI_FORMAT_R16G16B16A16_UNORM }, // RGBA16
 		{ DXGI_FORMAT_R16G16B16A16_FLOAT }, // RGBA16F
@@ -1643,7 +1642,20 @@ namespace bgfx
 
 		if (imageParse(imageContainer, _mem->data, _mem->size) )
 		{
-			bool decompress = DXGI_FORMAT_UNKNOWN == s_textureFormat[imageContainer.m_type].m_fmt;
+			m_requestedFormat = (uint8_t)imageContainer.m_format;
+			m_textureFormat   = (uint8_t)imageContainer.m_format;
+
+			const TextureFormatInfo& tfi = s_textureFormat[m_requestedFormat];
+			const bool convert = DXGI_FORMAT_UNKNOWN == tfi.m_fmt;
+
+			uint8_t bpp = getBitsPerPixel(TextureFormat::Enum(m_textureFormat) );
+			if (convert)
+			{
+				m_textureFormat = (uint8_t)TextureFormat::BGRA8;
+				bpp = 32;
+			}
+
+			DXGI_FORMAT format = s_textureFormat[m_textureFormat].m_fmt;
 
 			if (imageContainer.m_cubeMap)
 			{
@@ -1658,92 +1670,61 @@ namespace bgfx
 				m_type = Texture2D;
 			}
 
-			TextureFormat::Enum textureFormat = decompress ? TextureFormat::BGRA8 : imageContainer.m_type;
+			m_numMips = imageContainer.m_numMips;
+
 			uint32_t numSrd = imageContainer.m_numMips*(imageContainer.m_cubeMap ? 6 : 1);
 			D3D11_SUBRESOURCE_DATA* srd = (D3D11_SUBRESOURCE_DATA*)alloca(numSrd*sizeof(D3D11_SUBRESOURCE_DATA) );
 
 			uint32_t kk = 0;
-			bool convert = false;
-
-			m_numMips = imageContainer.m_numMips;
 
-			if (decompress
-			||  TextureFormat::Unknown < imageContainer.m_type)
+			for (uint8_t side = 0, numSides = imageContainer.m_cubeMap ? 6 : 1; side < numSides; ++side)
 			{
-				uint32_t bpp = getBitsPerPixel(textureFormat);
-				convert = decompress
-					|| TextureFormat::BGRX8 == textureFormat
-					;
+				uint32_t width  = imageContainer.m_width;
+				uint32_t height = imageContainer.m_height;
+				uint32_t depth  = imageContainer.m_depth;
 
-				for (uint8_t side = 0, numSides = imageContainer.m_cubeMap ? 6 : 1; side < numSides; ++side)
+				for (uint32_t lod = 0, num = m_numMips; lod < num; ++lod)
 				{
-					uint32_t width  = imageContainer.m_width;
-					uint32_t height = imageContainer.m_height;
-					uint32_t depth  = imageContainer.m_depth;
+					width  = bx::uint32_max(1, width);
+					height = bx::uint32_max(1, height);
+					depth  = bx::uint32_max(1, depth);
 
-					for (uint32_t lod = 0, num = m_numMips; lod < num; ++lod)
+					ImageMip mip;
+					if (imageGetRawData(imageContainer, side, lod, _mem->data, _mem->size, mip) )
 					{
-						width  = bx::uint32_max(1, width);
-						height = bx::uint32_max(1, height);
-						depth  = bx::uint32_max(1, depth);
+						srd[kk].pSysMem = mip.m_data;
 
-						Mip mip;
-						if (imageGetRawData(imageContainer, side, lod, _mem->data, _mem->size, mip) )
+						if (convert)
 						{
-							if (convert)
-							{
-								uint8_t* temp = (uint8_t*)g_realloc(NULL, mip.m_width*mip.m_height*bpp/8);
-								mip.decode(temp);
-
-								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;
-							}
+							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].SysMemSlicePitch = mip.m_height*srd[kk].SysMemPitch;
-							++kk;
+							srd[kk].pSysMem = temp;
+							srd[kk].SysMemPitch = mip.m_width*bpp/8;
 						}
-
-						width  >>= 1;
-						height >>= 1;
-						depth  >>= 1;
-					}
-				}
-			}
-			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) )
+						else if (TextureFormat::Unknown > m_textureFormat)
 						{
-							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;
+							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)

+ 3 - 1
src/renderer_d3d11.h

@@ -255,7 +255,9 @@ namespace bgfx
 
 		ID3D11ShaderResourceView* m_srv;
 		ID3D11SamplerState* m_sampler;
-		Enum m_type;
+		uint8_t m_type;
+		uint8_t m_requestedFormat;
+		uint8_t m_textureFormat;
 		uint8_t m_numMips;
 	};
 

+ 111 - 173
src/renderer_d3d9.cpp

@@ -183,36 +183,34 @@ namespace bgfx
 	struct TextureFormatInfo
 	{
 		D3DFORMAT m_fmt;
-		uint8_t m_bpp;
 	};
 
-	static const TextureFormatInfo s_textureFormat[TextureFormat::Count] =
-	{
-		{ 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
+	static TextureFormatInfo s_textureFormat[TextureFormat::Count] =
+	{
+		{ 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;
+
+			uint8_t bpp = getBitsPerPixel(TextureFormat::Enum(m_textureFormat) );
+			if (convert)
+			{
+				m_textureFormat = (uint8_t)TextureFormat::BGRA8;
+				bpp = 32;
+			}
 
-			D3DFORMAT format = decompress ? D3DFMT_A8R8G8B8 : tfi.m_fmt;
-			uint8_t bpp = decompress ? 32 : tfi.m_bpp;
+			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 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)
+				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);
+					mipWidth  = bx::uint32_max(min, mipWidth);
+					mipHeight = bx::uint32_max(min, mipHeight);
+					uint32_t mipSize = width*height*depth*bpp/8;
+
+					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);

+ 3 - 2
src/renderer_d3d9.h

@@ -320,8 +320,9 @@ namespace bgfx
 		};
 
 		uint32_t m_flags;
-		TextureFormat::Enum m_format;
-		Enum m_type;
+		uint8_t m_type;
+		uint8_t m_requestedFormat;
+		uint8_t m_textureFormat;
 	};
 
 	struct RenderTarget

+ 213 - 353
src/renderer_gl.cpp

@@ -194,31 +194,30 @@ namespace bgfx
 
 	static TextureFormatInfo s_textureFormat[TextureFormat::Count] =
 	{
-		{ GL_COMPRESSED_RGBA_S3TC_DXT1_EXT,            GL_COMPRESSED_RGBA_S3TC_DXT1_EXT,            GL_ZERO,                        false },
-		{ GL_COMPRESSED_RGBA_S3TC_DXT3_EXT,            GL_COMPRESSED_RGBA_S3TC_DXT3_EXT,            GL_ZERO,                        false },
-		{ GL_COMPRESSED_RGBA_S3TC_DXT5_EXT,            GL_COMPRESSED_RGBA_S3TC_DXT5_EXT,            GL_ZERO,                        false },
-		{ GL_COMPRESSED_LUMINANCE_LATC1_EXT,           GL_COMPRESSED_LUMINANCE_LATC1_EXT,           GL_ZERO,                        false },
-		{ GL_COMPRESSED_LUMINANCE_ALPHA_LATC2_EXT,     GL_COMPRESSED_LUMINANCE_ALPHA_LATC2_EXT,     GL_ZERO,                        false },
-		{ GL_ETC1_RGB8_OES,                            GL_ETC1_RGB8_OES,                            GL_ZERO,                        false },
-		{ GL_COMPRESSED_RGB8_ETC2,                     GL_COMPRESSED_RGB8_ETC2,                     GL_ZERO,                        false },
-		{ GL_COMPRESSED_RGBA8_ETC2_EAC,                GL_COMPRESSED_RGBA8_ETC2_EAC,                GL_ZERO,                        false },
-		{ GL_COMPRESSED_RGB8_PUNCHTHROUGH_ALPHA1_ETC2, GL_COMPRESSED_RGB8_PUNCHTHROUGH_ALPHA1_ETC2, GL_ZERO,                        false },
-		{ GL_COMPRESSED_RGB_PVRTC_2BPPV1_IMG,          GL_COMPRESSED_RGB_PVRTC_2BPPV1_IMG,          GL_ZERO,                        false },
-		{ GL_COMPRESSED_RGB_PVRTC_4BPPV1_IMG,          GL_COMPRESSED_RGB_PVRTC_4BPPV1_IMG,          GL_ZERO,                        false },
-		{ GL_COMPRESSED_RGBA_PVRTC_2BPPV1_IMG,         GL_COMPRESSED_RGBA_PVRTC_2BPPV1_IMG,         GL_ZERO,                        false },
-		{ GL_COMPRESSED_RGBA_PVRTC_4BPPV1_IMG,         GL_COMPRESSED_RGBA_PVRTC_4BPPV1_IMG,         GL_ZERO,                        false },
-		{ GL_COMPRESSED_RGBA_PVRTC_2BPPV2_IMG,         GL_COMPRESSED_RGBA_PVRTC_2BPPV2_IMG,         GL_ZERO,                        false },
-		{ GL_COMPRESSED_RGBA_PVRTC_4BPPV2_IMG,         GL_COMPRESSED_RGBA_PVRTC_4BPPV2_IMG,         GL_ZERO,                        false },
-		{ GL_ZERO,                                     GL_ZERO,                                     GL_ZERO,                        true  },
-		{ GL_LUMINANCE,                                GL_LUMINANCE,                                GL_UNSIGNED_BYTE,               true  },
-		{ GL_RGBA,                                     GL_RGBA,                                     GL_UNSIGNED_BYTE,               true  },
-		{ GL_RGBA,                                     GL_RGBA,                                     GL_UNSIGNED_BYTE,               true  },
-		{ GL_RGBA16,                                   GL_RGBA,                                     GL_UNSIGNED_BYTE,               true  },
-		{ GL_RGBA16F,                                  GL_RGBA,                                     GL_HALF_FLOAT,                  true  },
-		{ GL_RGB565,                                   GL_RGB,                                      GL_UNSIGNED_SHORT_5_6_5,        true  },
-		{ GL_RGBA4,                                    GL_RGBA,                                     GL_UNSIGNED_SHORT_4_4_4_4,      true  },
-		{ GL_RGB5_A1,                                  GL_RGBA,                                     GL_UNSIGNED_SHORT_5_5_5_1,      true  },
-		{ GL_RGB10_A2,                                 GL_RGBA,                                     GL_UNSIGNED_INT_2_10_10_10_REV, true  },
+		{ GL_COMPRESSED_RGBA_S3TC_DXT1_EXT,            GL_COMPRESSED_RGBA_S3TC_DXT1_EXT,            GL_ZERO,                        false }, // BC1
+		{ GL_COMPRESSED_RGBA_S3TC_DXT3_EXT,            GL_COMPRESSED_RGBA_S3TC_DXT3_EXT,            GL_ZERO,                        false }, // BC2
+		{ GL_COMPRESSED_RGBA_S3TC_DXT5_EXT,            GL_COMPRESSED_RGBA_S3TC_DXT5_EXT,            GL_ZERO,                        false }, // BC3
+		{ GL_COMPRESSED_LUMINANCE_LATC1_EXT,           GL_COMPRESSED_LUMINANCE_LATC1_EXT,           GL_ZERO,                        false }, // BC4
+		{ GL_COMPRESSED_LUMINANCE_ALPHA_LATC2_EXT,     GL_COMPRESSED_LUMINANCE_ALPHA_LATC2_EXT,     GL_ZERO,                        false }, // BC5
+		{ GL_ETC1_RGB8_OES,                            GL_ETC1_RGB8_OES,                            GL_ZERO,                        false }, // ETC1
+		{ GL_COMPRESSED_RGB8_ETC2,                     GL_COMPRESSED_RGB8_ETC2,                     GL_ZERO,                        false }, // ETC2
+		{ GL_COMPRESSED_RGBA8_ETC2_EAC,                GL_COMPRESSED_RGBA8_ETC2_EAC,                GL_ZERO,                        false }, // ETC2A
+		{ GL_COMPRESSED_RGB8_PUNCHTHROUGH_ALPHA1_ETC2, GL_COMPRESSED_RGB8_PUNCHTHROUGH_ALPHA1_ETC2, GL_ZERO,                        false }, // ETC2A1
+		{ GL_COMPRESSED_RGB_PVRTC_2BPPV1_IMG,          GL_COMPRESSED_RGB_PVRTC_2BPPV1_IMG,          GL_ZERO,                        false }, // PTC12
+		{ GL_COMPRESSED_RGB_PVRTC_4BPPV1_IMG,          GL_COMPRESSED_RGB_PVRTC_4BPPV1_IMG,          GL_ZERO,                        false }, // PTC14
+		{ GL_COMPRESSED_RGBA_PVRTC_2BPPV1_IMG,         GL_COMPRESSED_RGBA_PVRTC_2BPPV1_IMG,         GL_ZERO,                        false }, // PTC12A
+		{ GL_COMPRESSED_RGBA_PVRTC_4BPPV1_IMG,         GL_COMPRESSED_RGBA_PVRTC_4BPPV1_IMG,         GL_ZERO,                        false }, // PTC14A
+		{ GL_COMPRESSED_RGBA_PVRTC_2BPPV2_IMG,         GL_COMPRESSED_RGBA_PVRTC_2BPPV2_IMG,         GL_ZERO,                        false }, // PTC22
+		{ GL_COMPRESSED_RGBA_PVRTC_4BPPV2_IMG,         GL_COMPRESSED_RGBA_PVRTC_4BPPV2_IMG,         GL_ZERO,                        false }, // PTC24
+		{ GL_ZERO,                                     GL_ZERO,                                     GL_ZERO,                        true  }, // Unknown
+		{ GL_LUMINANCE,                                GL_LUMINANCE,                                GL_UNSIGNED_BYTE,               true  }, // L8
+		{ GL_RGBA,                                     GL_RGBA,                                     GL_UNSIGNED_BYTE,               true  }, // BGRA8
+		{ GL_RGBA16,                                   GL_RGBA,                                     GL_UNSIGNED_BYTE,               true  }, // RGBA16
+		{ GL_RGBA16F,                                  GL_RGBA,                                     GL_HALF_FLOAT,                  true  }, // RGBA16F
+		{ GL_RGB565,                                   GL_RGB,                                      GL_UNSIGNED_SHORT_5_6_5,        true  }, // R5G6B5
+		{ GL_RGBA4,                                    GL_RGBA,                                     GL_UNSIGNED_SHORT_4_4_4_4,      true  }, // RGBA4
+		{ GL_RGB5_A1,                                  GL_RGBA,                                     GL_UNSIGNED_SHORT_5_5_5_1,      true  }, // RGB5A1
+		{ GL_RGB10_A2,                                 GL_RGBA,                                     GL_UNSIGNED_INT_2_10_10_10_REV, true  }, // RGB10A2
 	};
 
 	struct Extension
@@ -595,9 +594,7 @@ namespace bgfx
 				GL_CHECK(glBindFramebuffer(GL_FRAMEBUFFER, m_msaaBackBufferFbo) );
 			}
 #else
-			BX_UNUSED(_width);
-			BX_UNUSED(_height);
-			BX_UNUSED(_msaa);
+			BX_UNUSED(_width, _height, _msaa);
 #endif // BGFX_CONFIG_RENDERER_OPENGL|BGFX_CONFIG_RENDERER_OPENGLES3
 		}
 
@@ -1323,37 +1320,33 @@ namespace bgfx
 		m_vcref.invalidate(s_renderCtx.m_vaoStateCache);
 	}
 
-	static void texImage(GLenum _target, GLint _level, GLint _internalFormat, GLsizei _width, GLsizei _height, GLsizei _depth, GLint _border, GLenum _format, GLenum _type, const GLvoid* _pixels)
+	static void texImage(GLenum _target, GLint _level, GLint _internalFormat, GLsizei _width, GLsizei _height, GLsizei _depth, GLint _border, GLenum _format, GLenum _type, const GLvoid* _data)
 	{
 #if BGFX_CONFIG_RENDERER_OPENGL|BGFX_CONFIG_RENDERER_OPENGLES3
 		if (_target == GL_TEXTURE_3D)
 		{
-			GL_CHECK(glTexImage3D(_target
-				, _level
-				, _internalFormat
-				, _width
-				, _height
-				, _depth
-				, _border
-				, _format
-				, _type
-				, _pixels
-				) );
+			GL_CHECK(glTexImage3D(_target, _level, _internalFormat, _width, _height, _depth, _border, _format, _type, _data) );
 		}
 		else
 #endif // BGFX_CONFIG_RENDERER_OPENGL|BGFX_CONFIG_RENDERER_OPENGLES3
 		{
 			BX_UNUSED(_depth);
-			GL_CHECK(glTexImage2D(_target
-				, _level
-				, _internalFormat
-				, _width
-				, _height
-				, _border
-				, _format
-				, _type
-				, _pixels
-				) );
+			GL_CHECK(glTexImage2D(_target, _level, _internalFormat, _width, _height, _border, _format, _type, _data) );
+		}
+	}
+
+	static void texSubImage(GLenum _target, GLint _level, GLint _xoffset, GLint _yoffset, GLint _zoffset, GLsizei _width, GLsizei _height, GLsizei _depth, GLenum _format, GLenum _type, const GLvoid* _data)
+	{
+#if BGFX_CONFIG_RENDERER_OPENGL|BGFX_CONFIG_RENDERER_OPENGLES3
+		if (_target == GL_TEXTURE_3D)
+		{
+			GL_CHECK(glTexSubImage3D(_target, _level, _xoffset, _yoffset, _zoffset, _width, _height, _depth, _format, _type, _data) );
+		}
+		else
+#endif // BGFX_CONFIG_RENDERER_OPENGL|BGFX_CONFIG_RENDERER_OPENGLES3
+		{
+			BX_UNUSED(_zoffset, _depth);
+			GL_CHECK(glTexSubImage2D(_target, _level, _xoffset, _yoffset, _width, _height, _format, _type, _data) );
 		}
 	}
 
@@ -1362,45 +1355,69 @@ namespace bgfx
 #if BGFX_CONFIG_RENDERER_OPENGL|BGFX_CONFIG_RENDERER_OPENGLES3
 		if (_target == GL_TEXTURE_3D)
 		{
-			GL_CHECK(glCompressedTexImage3D(_target
-				, _level
-				, _internalformat
-				, _width
-				, _height
-				, _depth
-				, _border
-				, _imageSize
-				, _data
-				) );
+			GL_CHECK(glCompressedTexImage3D(_target, _level, _internalformat, _width, _height, _depth, _border, _imageSize, _data) );
 		}
 		else
 #endif // BGFX_CONFIG_RENDERER_OPENGL|BGFX_CONFIG_RENDERER_OPENGLES3
 		{
 			BX_UNUSED(_depth);
-			GL_CHECK(glCompressedTexImage2D(_target
-				, _level
-				, _internalformat
-				, _width
-				, _height
-				, _border
-				, _imageSize
-				, _data
-				) );
+			GL_CHECK(glCompressedTexImage2D(_target, _level, _internalformat, _width, _height, _border, _imageSize, _data) );
 		}
 	}
 
-	void Texture::init(GLenum _target, uint8_t _numMips, uint32_t _flags)
+	static void compressedTexSubImage(GLenum _target, GLint _level, GLint _xoffset, GLint _yoffset, GLint _zoffset, GLsizei _width, GLsizei _height, GLsizei _depth, GLenum _format, GLsizei _imageSize, const GLvoid* _data)
+	{
+#if BGFX_CONFIG_RENDERER_OPENGL|BGFX_CONFIG_RENDERER_OPENGLES3
+		if (_target == GL_TEXTURE_3D)
+		{
+			GL_CHECK(glCompressedTexSubImage3D(_target, _level, _xoffset, _yoffset, _zoffset, _width, _height, _depth, _format, _imageSize, _data) );
+		}
+		else
+#endif // BGFX_CONFIG_RENDERER_OPENGL|BGFX_CONFIG_RENDERER_OPENGLES3
+		{
+			BX_UNUSED(_zoffset, _depth);
+			GL_CHECK(glCompressedTexSubImage2D(_target, _level, _xoffset, _yoffset, _width, _height, _format, _imageSize, _data) );
+		}
+	}
+
+	void Texture::init(GLenum _target, uint8_t _format, uint8_t _numMips, uint32_t _flags)
 	{
 		m_target = _target;
 		m_numMips = _numMips;
 		m_flags = _flags;
 		m_currentFlags = UINT32_MAX;
+		m_requestedFormat = _format;
+		m_textureFormat   = _format;
 
 		GL_CHECK(glGenTextures(1, &m_id) );
 		BX_CHECK(0 != m_id, "Failed to generate texture id.");
 		GL_CHECK(glBindTexture(_target, m_id) );
 
 		setSamplerState(_flags);
+
+		const TextureFormatInfo& tfi = s_textureFormat[_format];
+		m_fmt = tfi.m_fmt;
+		m_type = tfi.m_type;
+
+		const bool compressed = TextureFormat::Unknown > _format;
+		const bool decompress = !tfi.m_supported && compressed;
+
+		if (decompress)
+		{
+			m_textureFormat = (uint8_t)TextureFormat::BGRA8;
+			const TextureFormatInfo& tfi = s_textureFormat[TextureFormat::BGRA8];
+			m_fmt = tfi.m_fmt;
+			m_type = tfi.m_type;
+		}
+
+#if BGFX_CONFIG_RENDERER_OPENGL
+		if (GL_RGBA == m_fmt
+		&&  s_renderCtx.m_textureSwizzleSupport)
+		{
+			GLint swizzleMask[] = { GL_BLUE, GL_GREEN, GL_RED, GL_ALPHA };
+			GL_CHECK(glTexParameteriv(GL_TEXTURE_2D, GL_TEXTURE_SWIZZLE_RGBA, swizzleMask) );
+		}
+#endif // BGFX_CONFIG_RENDERER_OPENGL
 	}
 
 	void Texture::create(const Memory* _mem, uint32_t _flags)
@@ -1411,215 +1428,105 @@ 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(GL_TEXTURE_2D, numMips, _flags);
-			}
 
-			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)
-			{
-				target = GL_TEXTURE_CUBE_MAP_POSITIVE_X;
-			}
+			init(target
+				, imageContainer.m_format
+				, numMips
+				, _flags
+				);
 
-			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);
+			target = GL_TEXTURE_CUBE_MAP == m_target ? GL_TEXTURE_CUBE_MAP_POSITIVE_X : m_target;
 
-				if (decompress)
-				{
-					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);
-				}
+			const GLenum internalFmt = s_textureFormat[m_textureFormat].m_internalFmt;
 
-				bool swizzle = GL_RGBA == m_fmt;
+			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;
 
-#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* temp = NULL;
+			if (convert || swizzle)
+			{
+				temp = (uint8_t*)g_realloc(NULL, imageContainer.m_width*imageContainer.m_height*4);
+			}
 
-				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 (uint8_t side = 0, numSides = imageContainer.m_cubeMap ? 6 : 1; side < numSides; ++side)
+				for (uint32_t lod = 0, num = 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(min, width);
+					height = bx::uint32_max(min, height);
+					depth  = bx::uint32_max(1, 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) )
+						if (compressed)
 						{
-							mip.decode(bits);
-
-							if (swizzle)
-							{
-								imageSwizzleBgra8(width, height, bits, bits);
-							}
-
-							texImage(target+side
+							compressedTexImage(target+side
 								, lod
 								, internalFmt
 								, width
 								, height
 								, depth
 								, 0
-								, m_fmt
-								, m_type
-								, bits
+								, mip.m_size
+								, mip.m_data
 								);
 						}
+						else
+						{
+							const uint8_t* data = mip.m_data;
 
-						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;
+							if (convert)
+							{
+								imageDecodeToBgra8(temp, mip.m_data, mip.m_width, mip.m_height, mip.m_format);
+								data = temp;
+							}
 
-					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);
+							if (swizzle)
+							{
+								imageSwizzleBgra8(width, height, data, temp);
+								data = temp;
+							}
 
-						Mip mip;
-						if (imageGetRawData(imageContainer, side, ii, _mem->data, _mem->size, mip) )
-						{
-							compressedTexImage(target+side
-								, ii
+							texImage(target+side
+								, lod
 								, internalFmt
 								, width
 								, height
 								, depth
 								, 0
-								, mip.m_size
-								, mip.m_data
+								, m_fmt
+								, m_type
+								, 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)
+					else
 					{
-						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)
+						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
+										  ;
+
 							compressedTexImage(target+side
 								, lod
 								, internalFmt
@@ -1628,17 +1535,11 @@ namespace bgfx
 								, depth
 								, 0
 								, size
-								, data
+								, NULL
 								);
 						}
 						else
 						{
-							if (NULL != data
-							&&  swizzle)
-							{
-								imageSwizzleBgra8(width, height, data, data);
-							}
-
 							texImage(target+side
 								, lod
 								, internalFmt
@@ -1648,29 +1549,20 @@ namespace bgfx
 								, 0
 								, m_fmt
 								, m_type
-								, data
+								, NULL
 								);
 						}
-
-						if (NULL != data)
-						{
-							data += size;
-						}
-
-						width  >>= 1;
-						height >>= 1;
-						depth  >>= 1;
 					}
-				}
 
-				if (NULL != tc.m_mem)
-				{
-					release(tc.m_mem);
+					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;
 			}
 		}

+ 3 - 3
src/renderer_gl.h

@@ -558,11 +558,10 @@ namespace bgfx
 			, m_flags(0)
 			, m_currentFlags(UINT32_MAX)
 			, m_numMips(0)
-			, m_compressed(false)
 		{
 		}
 
-		void init(GLenum _target, uint8_t _numMips, uint32_t _flags);
+		void init(GLenum _target, uint8_t _format, uint8_t _numMips, uint32_t _flags);
 		void create(const Memory* _mem, uint32_t _flags);
 		void createColor(uint32_t _colorFormat, uint32_t _width, uint32_t _height, GLenum _min, GLenum _mag);
 		void createDepth(uint32_t _width, uint32_t _height);
@@ -578,7 +577,8 @@ namespace bgfx
 		uint32_t m_flags;
 		uint32_t m_currentFlags;
 		uint8_t m_numMips;
-		bool m_compressed;
+		uint8_t m_requestedFormat;
+		uint8_t m_textureFormat;
 	};
 
 	struct Shader

+ 1 - 16
src/renderer_null.cpp

@@ -105,23 +105,8 @@ namespace bgfx
 	{
 	}
 
-	void Context::rendererCreateTexture(TextureHandle /*_handle*/, Memory* _mem, uint32_t /*_flags*/)
+	void Context::rendererCreateTexture(TextureHandle /*_handle*/, Memory* /*_mem*/, uint32_t /*_flags*/)
 	{
-		bx::MemoryReader reader(_mem->data, _mem->size);
-
-		uint32_t magic;
-		bx::read(&reader, magic);
-
-		if (BGFX_CHUNK_MAGIC_TEX == magic)
-		{
-			TextureCreate tc;
-			bx::read(&reader, tc);
-
-			if (NULL != tc.m_mem)
-			{
-				release(tc.m_mem);
-			}
-		}
 	}
 
 	void Context::rendererUpdateTextureBegin(TextureHandle /*_handle*/, uint8_t /*_side*/, uint8_t /*_mip*/)

+ 5 - 5
tools/texturec/texturec.cpp

@@ -108,7 +108,7 @@ int main(int _argc, const char* _argv[])
 		bool decompress = cmdLine.hasArg('d');
 
 		if (decompress
-		||  0 == imageContainer.m_type)
+		||  0 == imageContainer.m_format)
 		{
 			for (uint8_t side = 0, numSides = imageContainer.m_cubeMap ? 6 : 1; side < numSides; ++side)
 			{
@@ -120,7 +120,7 @@ int main(int _argc, const char* _argv[])
 					width = bx::uint32_max(1, width);
 					height = bx::uint32_max(1, height);
 
-					Mip mip;
+					ImageMip mip;
 					if (imageGetRawData(imageContainer, side, lod, mem->data, mem->size, mip) )
 					{
 						uint32_t dstpitch = width*4;
@@ -130,7 +130,7 @@ int main(int _argc, const char* _argv[])
 						||  height != mip.m_height)
 						{
 							uint8_t* temp = (uint8_t*)realloc(NULL, mip.m_width*mip.m_height*4);
-							mip.decode(temp);
+							imageDecodeToBgra8(temp, mip.m_data, mip.m_width, mip.m_height, mip.m_format);
 							uint32_t srcpitch = mip.m_width*4;
 
 							for (uint32_t yy = 0; yy < height; ++yy)
@@ -150,7 +150,7 @@ int main(int _argc, const char* _argv[])
 						}
 						else
 						{
-							mip.decode(bits);
+							imageDecodeToBgra8(bits, mip.m_data, mip.m_width, mip.m_height, mip.m_format);
 						}
 
 						char filePath[256];
@@ -169,7 +169,7 @@ int main(int _argc, const char* _argv[])
 		{
 			for (uint32_t lod = 0, num = imageContainer.m_numMips; lod < num; ++lod)
 			{
-				Mip mip;
+				ImageMip mip;
 				if (imageGetRawData(imageContainer, 0, lod, mem->data, mem->size, mip) )
 				{
 					char filePath[256];