Jelajahi Sumber

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

bkaradzic 12 tahun lalu
induk
melakukan
488483a945
13 mengubah file dengan 680 tambahan dan 1010 penghapusan
  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
 			PTC24,  // PVRTC2 RGBA 4BPP
 			Unknown,
 			Unknown,
 			L8,
 			L8,
-			BGRX8,
 			BGRA8,
 			BGRA8,
 			RGBA16,
 			RGBA16,
 			RGBA16F,
 			RGBA16F,
@@ -749,12 +748,37 @@ namespace bgfx
 	TextureHandle createTexture(const Memory* _mem, uint32_t _flags = BGFX_TEXTURE_NONE, TextureInfo* _info = NULL);
 	TextureHandle createTexture(const Memory* _mem, uint32_t _flags = BGFX_TEXTURE_NONE, TextureInfo* _info = NULL);
 
 
 	/// Create 2D texture.
 	/// 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);
 	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.
 	/// 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);
 	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.
 	/// 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);
 	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.
 	/// Update 2D texture.

+ 18 - 13
src/bgfx_p.h

@@ -16,20 +16,9 @@
 #include <string.h>
 #include <string.h>
 #include <alloca.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
 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, ...);
 	void dbgPrintf(const char* _format, ...);
 }
 }
 
 
@@ -2156,7 +2145,7 @@ namespace bgfx
 						, (uint16_t)imageContainer.m_height
 						, (uint16_t)imageContainer.m_height
 						, (uint16_t)imageContainer.m_depth
 						, (uint16_t)imageContainer.m_depth
 						, imageContainer.m_numMips
 						, imageContainer.m_numMips
-						, imageContainer.m_type
+						, TextureFormat::Enum(imageContainer.m_format)
 						);
 						);
 				}
 				}
 				else
 				else
@@ -2949,6 +2938,22 @@ namespace bgfx
 
 
 						rendererCreateTexture(handle, mem, flags);
 						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);
 						release(mem);
 					}
 					}
 					break;
 					break;

+ 4 - 0
src/config.h

@@ -91,6 +91,10 @@
 #	define BGFX_CONFIG_DEBUG_PERFHUD 0
 #	define BGFX_CONFIG_DEBUG_PERFHUD 0
 #endif // BGFX_CONFIG_DEBUG_NVPERFHUD
 #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
 /// DX9 PIX markers
 #ifndef BGFX_CONFIG_DEBUG_PIX
 #ifndef BGFX_CONFIG_DEBUG_PIX
 #	define BGFX_CONFIG_DEBUG_PIX BGFX_CONFIG_DEBUG
 #	define BGFX_CONFIG_DEBUG_PIX BGFX_CONFIG_DEBUG

+ 210 - 202
src/image.cpp

@@ -30,7 +30,6 @@ namespace bgfx
 		4,  // PTC24
 		4,  // PTC24
 		0,  // Unknown
 		0,  // Unknown
 		8,  // L8
 		8,  // L8
-		32, // BGRX8
 		32, // BGRA8
 		32, // BGRA8
 		64, // RGBA16
 		64, // RGBA16
 		64, // RGBA16F
 		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
 // DDS
 #define DDS_MAGIC             BX_MAKEFOURCC('D', 'D', 'S', ' ')
 #define DDS_MAGIC             BX_MAKEFOURCC('D', 'D', 'S', ' ')
 #define DDS_HEADER_SIZE       124
 #define DDS_HEADER_SIZE       124
@@ -803,7 +634,6 @@ namespace bgfx
 		{ DDS_BC5U,                  TextureFormat::BC5     },
 		{ DDS_BC5U,                  TextureFormat::BC5     },
 		{ D3DFMT_A16B16G16R16,       TextureFormat::RGBA16  },
 		{ D3DFMT_A16B16G16R16,       TextureFormat::RGBA16  },
 		{ D3DFMT_A16B16G16R16F,      TextureFormat::RGBA16F },
 		{ D3DFMT_A16B16G16R16F,      TextureFormat::RGBA16F },
-		{ DDPF_RGB,                  TextureFormat::BGRX8   },
 		{ DDPF_RGB|DDPF_ALPHAPIXELS, TextureFormat::BGRA8   },
 		{ DDPF_RGB|DDPF_ALPHAPIXELS, TextureFormat::BGRA8   },
 		{ DDPF_INDEXED,              TextureFormat::L8      },
 		{ DDPF_INDEXED,              TextureFormat::L8      },
 		{ DDPF_LUMINANCE,            TextureFormat::L8      },
 		{ DDPF_LUMINANCE,            TextureFormat::L8      },
@@ -889,31 +719,30 @@ namespace bgfx
 
 
 		uint8_t bpp = 0;
 		uint8_t bpp = 0;
 		uint8_t blockSize = 1;
 		uint8_t blockSize = 1;
-		TextureFormat::Enum type = TextureFormat::Unknown;
+		TextureFormat::Enum format = TextureFormat::Unknown;
 		bool hasAlpha = pixelFlags & DDPF_ALPHAPIXELS;
 		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)
 		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;
 				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;
 		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_offset = DDS_IMAGE_DATA_OFFSET;
 		_imageContainer.m_width = width;
 		_imageContainer.m_width = width;
 		_imageContainer.m_height = height;
 		_imageContainer.m_height = height;
 		_imageContainer.m_depth = depth;
 		_imageContainer.m_depth = depth;
+		_imageContainer.m_format = format;
 		_imageContainer.m_blockSize = blockSize;
 		_imageContainer.m_blockSize = blockSize;
 		_imageContainer.m_numMips = (caps[0] & DDSCAPS_MIPMAP) ? mips : 1;
 		_imageContainer.m_numMips = (caps[0] & DDSCAPS_MIPMAP) ? mips : 1;
 		_imageContainer.m_bpp = bpp;
 		_imageContainer.m_bpp = bpp;
@@ -921,7 +750,7 @@ namespace bgfx
 		_imageContainer.m_cubeMap = cubeMap;
 		_imageContainer.m_cubeMap = cubeMap;
 		_imageContainer.m_ktx = false;
 		_imageContainer.m_ktx = false;
 
 
-		return TextureFormat::Unknown != type;
+		return TextureFormat::Unknown != format;
 	}
 	}
 
 
 // KTX
 // KTX
@@ -1043,30 +872,29 @@ namespace bgfx
 
 
 		uint8_t bpp = 0;
 		uint8_t bpp = 0;
 		uint8_t blockSize = 1;
 		uint8_t blockSize = 1;
-		TextureFormat::Enum type = TextureFormat::Unknown;
+		TextureFormat::Enum format = TextureFormat::Unknown;
 		bool hasAlpha = false;
 		bool hasAlpha = false;
 
 
 		for (uint32_t ii = 0; ii < BX_COUNTOF(s_translateKtxFormat); ++ii)
 		for (uint32_t ii = 0; ii < BX_COUNTOF(s_translateKtxFormat); ++ii)
 		{
 		{
 			if (s_translateKtxFormat[ii].m_format == glInternalFormat)
 			if (s_translateKtxFormat[ii].m_format == glInternalFormat)
 			{
 			{
-				type = s_translateKtxFormat[ii].m_textureFormat;
+				format = s_translateKtxFormat[ii].m_textureFormat;
 				break;
 				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;
 		blockSize = blockSize*bpp/8;
 
 
-		_imageContainer.m_type = type;
+		_imageContainer.m_data = NULL;
+		_imageContainer.m_size = 0;
 		_imageContainer.m_offset = (uint32_t)offset;
 		_imageContainer.m_offset = (uint32_t)offset;
 		_imageContainer.m_width = width;
 		_imageContainer.m_width = width;
 		_imageContainer.m_height = height;
 		_imageContainer.m_height = height;
 		_imageContainer.m_depth = depth;
 		_imageContainer.m_depth = depth;
+		_imageContainer.m_format = format;
 		_imageContainer.m_blockSize = blockSize;
 		_imageContainer.m_blockSize = blockSize;
 		_imageContainer.m_numMips = numMips;
 		_imageContainer.m_numMips = numMips;
 		_imageContainer.m_bpp = bpp;
 		_imageContainer.m_bpp = bpp;
@@ -1074,7 +902,7 @@ namespace bgfx
 		_imageContainer.m_cubeMap = numFaces > 1;
 		_imageContainer.m_cubeMap = numFaces > 1;
 		_imageContainer.m_ktx = true;
 		_imageContainer.m_ktx = true;
 
 
-		return TextureFormat::Unknown != type;
+		return TextureFormat::Unknown != format;
 	}
 	}
 
 
 // PVR3
 // PVR3
@@ -1164,7 +992,7 @@ namespace bgfx
 
 
 		uint8_t bpp = 0;
 		uint8_t bpp = 0;
 		uint8_t blockSize = 1;
 		uint8_t blockSize = 1;
-		TextureFormat::Enum type = TextureFormat::Unknown;
+		TextureFormat::Enum format = TextureFormat::Unknown;
 		bool hasAlpha = false;
 		bool hasAlpha = false;
 
 
 		for (uint32_t ii = 0; ii < BX_COUNTOF(s_translatePvr3Format); ++ii)
 		for (uint32_t ii = 0; ii < BX_COUNTOF(s_translatePvr3Format); ++ii)
@@ -1172,23 +1000,22 @@ namespace bgfx
 			if (s_translatePvr3Format[ii].m_format == pixelFormat
 			if (s_translatePvr3Format[ii].m_format == pixelFormat
 			&&  channelType == (s_translatePvr3Format[ii].m_channelTypeMask & channelType) )
 			&&  channelType == (s_translatePvr3Format[ii].m_channelTypeMask & channelType) )
 			{
 			{
-				type = s_translatePvr3Format[ii].m_textureFormat;
+				format = s_translatePvr3Format[ii].m_textureFormat;
 				break;
 				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;
 		blockSize = blockSize*bpp/8;
 
 
-		_imageContainer.m_type = type;
+		_imageContainer.m_data = NULL;
+		_imageContainer.m_size = 0;
 		_imageContainer.m_offset = (uint32_t)offset;
 		_imageContainer.m_offset = (uint32_t)offset;
 		_imageContainer.m_width = width;
 		_imageContainer.m_width = width;
 		_imageContainer.m_height = height;
 		_imageContainer.m_height = height;
 		_imageContainer.m_depth = depth;
 		_imageContainer.m_depth = depth;
+		_imageContainer.m_format = format;
 		_imageContainer.m_blockSize = blockSize;
 		_imageContainer.m_blockSize = blockSize;
 		_imageContainer.m_numMips = numMips;
 		_imageContainer.m_numMips = numMips;
 		_imageContainer.m_bpp = bpp;
 		_imageContainer.m_bpp = bpp;
@@ -1196,7 +1023,7 @@ namespace bgfx
 		_imageContainer.m_cubeMap = numFaces > 1;
 		_imageContainer.m_cubeMap = numFaces > 1;
 		_imageContainer.m_ktx = false;
 		_imageContainer.m_ktx = false;
 
 
-		return TextureFormat::Unknown != type;
+		return TextureFormat::Unknown != format;
 	}
 	}
 
 
 	bool imageParse(ImageContainer& _imageContainer, bx::ReaderSeekerI* _reader)
 	bool imageParse(ImageContainer& _imageContainer, bx::ReaderSeekerI* _reader)
@@ -1216,6 +1043,39 @@ namespace bgfx
 		{
 		{
 			return imageParsePvr3(_imageContainer, _reader);
 			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;
 		return false;
 	}
 	}
@@ -1226,14 +1086,162 @@ namespace bgfx
 		return imageParse(_imageContainer, &reader);
 		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;
 		const uint32_t blockSize = _imageContainer.m_blockSize;
 		uint32_t offset = _imageContainer.m_offset;
 		uint32_t offset = _imageContainer.m_offset;
 		const uint8_t bpp = _imageContainer.m_bpp;
 		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;
 		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)
 		for (uint8_t side = 0, numSides = _imageContainer.m_cubeMap ? 6 : 1; side < numSides; ++side)
 		{
 		{
 			uint32_t width  = _imageContainer.m_width;
 			uint32_t width  = _imageContainer.m_width;
@@ -1269,7 +1277,7 @@ namespace bgfx
 					_mip.m_size = size;
 					_mip.m_size = size;
 					_mip.m_data = (const uint8_t*)_data + offset;
 					_mip.m_data = (const uint8_t*)_data + offset;
 					_mip.m_bpp = bpp;
 					_mip.m_bpp = bpp;
-					_mip.m_type = type;
+					_mip.m_format = type;
 					_mip.m_hasAlpha = hasAlpha;
 					_mip.m_hasAlpha = hasAlpha;
 					return true;
 					return true;
 				}
 				}

+ 10 - 7
src/image.h

@@ -12,11 +12,13 @@ namespace bgfx
 {
 {
 	struct ImageContainer
 	struct ImageContainer
 	{
 	{
-		TextureFormat::Enum m_type;
+		void* m_data;
+		uint32_t m_size;
 		uint32_t m_offset;
 		uint32_t m_offset;
 		uint32_t m_width;
 		uint32_t m_width;
 		uint32_t m_height;
 		uint32_t m_height;
 		uint32_t m_depth;
 		uint32_t m_depth;
+		uint8_t m_format;
 		uint8_t m_blockSize;
 		uint8_t m_blockSize;
 		uint8_t m_numMips;
 		uint8_t m_numMips;
 		uint8_t m_bpp;
 		uint8_t m_bpp;
@@ -25,18 +27,16 @@ namespace bgfx
 		bool m_ktx;
 		bool m_ktx;
 	};
 	};
 
 
-	struct Mip
+	struct ImageMip
 	{
 	{
 		uint32_t m_width;
 		uint32_t m_width;
 		uint32_t m_height;
 		uint32_t m_height;
 		uint32_t m_blockSize;
 		uint32_t m_blockSize;
 		uint32_t m_size;
 		uint32_t m_size;
 		uint8_t m_bpp;
 		uint8_t m_bpp;
-		uint8_t m_type;
+		uint8_t m_format;
 		bool m_hasAlpha;
 		bool m_hasAlpha;
 		const uint8_t* m_data;
 		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& _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
 } // namespace bgfx
 
 

+ 74 - 234
src/renderer_d3d11.cpp

@@ -200,7 +200,6 @@ namespace bgfx
 		{ DXGI_FORMAT_UNKNOWN            }, // PTC24
 		{ DXGI_FORMAT_UNKNOWN            }, // PTC24
 		{ DXGI_FORMAT_UNKNOWN            }, // Unknown
 		{ DXGI_FORMAT_UNKNOWN            }, // Unknown
 		{ DXGI_FORMAT_R8_UNORM           }, // L8
 		{ DXGI_FORMAT_R8_UNORM           }, // L8
-		{ DXGI_FORMAT_B8G8R8A8_UNORM     }, // BGRX8
 		{ DXGI_FORMAT_B8G8R8A8_UNORM     }, // BGRA8
 		{ DXGI_FORMAT_B8G8R8A8_UNORM     }, // BGRA8
 		{ DXGI_FORMAT_R16G16B16A16_UNORM }, // RGBA16
 		{ DXGI_FORMAT_R16G16B16A16_UNORM }, // RGBA16
 		{ DXGI_FORMAT_R16G16B16A16_FLOAT }, // RGBA16F
 		{ DXGI_FORMAT_R16G16B16A16_FLOAT }, // RGBA16F
@@ -1643,7 +1642,20 @@ namespace bgfx
 
 
 		if (imageParse(imageContainer, _mem->data, _mem->size) )
 		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)
 			if (imageContainer.m_cubeMap)
 			{
 			{
@@ -1658,92 +1670,61 @@ namespace bgfx
 				m_type = Texture2D;
 				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);
 			uint32_t numSrd = imageContainer.m_numMips*(imageContainer.m_cubeMap ? 6 : 1);
 			D3D11_SUBRESOURCE_DATA* srd = (D3D11_SUBRESOURCE_DATA*)alloca(numSrd*sizeof(D3D11_SUBRESOURCE_DATA) );
 			D3D11_SUBRESOURCE_DATA* srd = (D3D11_SUBRESOURCE_DATA*)alloca(numSrd*sizeof(D3D11_SUBRESOURCE_DATA) );
 
 
 			uint32_t kk = 0;
 			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;
 			D3D11_SHADER_RESOURCE_VIEW_DESC srvd;
 			memset(&srvd, 0, sizeof(srvd) );
 			memset(&srvd, 0, sizeof(srvd) );
-			srvd.Format = s_textureFormat[textureFormat].m_fmt;
+			srvd.Format = format;
 
 
 			switch (m_type)
 			switch (m_type)
 			{
 			{
@@ -1757,7 +1738,7 @@ namespace bgfx
 					desc.Format = srvd.Format;
 					desc.Format = srvd.Format;
 					desc.SampleDesc.Count = 1;
 					desc.SampleDesc.Count = 1;
 					desc.SampleDesc.Quality = 0;
 					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.BindFlags = D3D11_BIND_SHADER_RESOURCE;
 					desc.CPUAccessFlags = 0;
 					desc.CPUAccessFlags = 0;
 
 
@@ -1776,7 +1757,7 @@ namespace bgfx
 						srvd.Texture2D.MipLevels = imageContainer.m_numMips;
 						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;
 				break;
 
 
@@ -1788,7 +1769,7 @@ namespace bgfx
 					desc.Depth = imageContainer.m_depth;
 					desc.Depth = imageContainer.m_depth;
 					desc.MipLevels = imageContainer.m_numMips;
 					desc.MipLevels = imageContainer.m_numMips;
 					desc.Format = srvd.Format;
 					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.BindFlags = D3D11_BIND_SHADER_RESOURCE;
 					desc.CPUAccessFlags = 0;
 					desc.CPUAccessFlags = 0;
 					desc.MiscFlags = 0;
 					desc.MiscFlags = 0;
@@ -1796,14 +1777,15 @@ namespace bgfx
 					srvd.ViewDimension = D3D11_SRV_DIMENSION_TEXTURE3D;
 					srvd.ViewDimension = D3D11_SRV_DIMENSION_TEXTURE3D;
 					srvd.Texture3D.MipLevels = imageContainer.m_numMips;
 					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;
 				break;
 			}
 			}
 
 
 			DX_CHECK(s_renderCtx.m_device->CreateShaderResourceView(m_ptr, &srvd, &m_srv) );
 			DX_CHECK(s_renderCtx.m_device->CreateShaderResourceView(m_ptr, &srvd, &m_srv) );
 
 
-			if (convert)
+			if (convert
+			&&  0 != kk)
 			{
 			{
 				kk = 0;
 				kk = 0;
 				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)
@@ -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()
 	void Texture::destroy()
@@ -1994,23 +1829,28 @@ namespace bgfx
 		box.back = box.front + _depth;
 		box.back = box.front + _depth;
 
 
 		uint32_t subres = _mip + (_side * m_numMips);
 		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)
 	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;
 		ID3D11ShaderResourceView* m_srv;
 		ID3D11SamplerState* m_sampler;
 		ID3D11SamplerState* m_sampler;
-		Enum m_type;
+		uint8_t m_type;
+		uint8_t m_requestedFormat;
+		uint8_t m_textureFormat;
 		uint8_t m_numMips;
 		uint8_t m_numMips;
 	};
 	};
 
 

+ 111 - 173
src/renderer_d3d9.cpp

@@ -183,36 +183,34 @@ namespace bgfx
 	struct TextureFormatInfo
 	struct TextureFormatInfo
 	{
 	{
 		D3DFORMAT m_fmt;
 		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] =
 	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 2.0 instr. slots: %d", m_caps.PS20Caps.NumInstructionSlots);
 			BX_TRACE("Max fragment shader 3.0 instr. slots: %d", m_caps.MaxPixelShader30InstructionSlots);
 			BX_TRACE("Max fragment shader 3.0 instr. slots: %d", m_caps.MaxPixelShader30InstructionSlots);
 
 
+#if BGFX_CONFIG_RENDERER_USE_EXTENSIONS
 			BX_TRACE("Extended formats:");
 			BX_TRACE("Extended formats:");
 			for (uint32_t ii = 0; ii < ExtendedFormat::Count; ++ii)
 			for (uint32_t ii = 0; ii < ExtendedFormat::Count; ++ii)
 			{
 			{
@@ -426,6 +425,10 @@ namespace bgfx
 				m_device->SetRenderState(D3DRS_POINTSIZE, D3DFMT_INST);
 				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;
 			uint32_t index = 1;
 			for (const D3DFORMAT* fmt = &s_checkColorFormats[index]; *fmt != D3DFMT_UNKNOWN; ++fmt, ++index)
 			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) )
 		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)
 			if (imageContainer.m_cubeMap)
 			{
 			{
@@ -1543,167 +1549,82 @@ namespace bgfx
 				createTexture(imageContainer.m_width, imageContainer.m_height, imageContainer.m_numMips, format);
 				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;
 								uint32_t dstpitch = pitch;
 								for (uint32_t yy = 0; yy < height; ++yy)
 								for (uint32_t yy = 0; yy < height; ++yy)
 								{
 								{
 									uint8_t* src = &temp[yy*srcpitch];
 									uint8_t* src = &temp[yy*srcpitch];
 									uint8_t* dst = &bits[yy*dstpitch];
 									uint8_t* dst = &bits[yy*dstpitch];
-									memcpy(dst, src, srcpitch);
+									memcpy(dst, src, dstpitch);
 								}
 								}
 
 
 								g_free(temp);
 								g_free(temp);
 							}
 							}
 							else
 							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)
 	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 srcpitch = _rect.m_width*bpp/8;
 		uint32_t dstpitch = s_renderCtx.m_updateTexturePitch;
 		uint32_t dstpitch = s_renderCtx.m_updateTexturePitch;
 		uint8_t* bits = s_renderCtx.m_updateTextureBits + _rect.m_y*dstpitch + _rect.m_x*bpp/8;
 		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)
 		if (srcpitch == dstpitch)
 		{
 		{
-			memcpy(bits, _mem->data, srcpitch*_rect.m_height);
+			memcpy(bits, data, srcpitch*_rect.m_height);
 		}
 		}
 		else
 		else
 		{
 		{
 			for (uint32_t yy = 0, height = _rect.m_height; yy < height; ++yy)
 			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];
 				uint8_t* dst = &bits[yy*dstpitch];
 				memcpy(dst, src, srcpitch);
 				memcpy(dst, src, srcpitch);
 			}
 			}
 		}
 		}
 
 
+		if (NULL != temp)
+		{
+			g_free(temp);
+		}
+
 		if (0 == _mip)
 		if (0 == _mip)
 		{
 		{
 			dirty(_side, _rect, _z, _depth);
 			dirty(_side, _rect, _z, _depth);

+ 3 - 2
src/renderer_d3d9.h

@@ -320,8 +320,9 @@ namespace bgfx
 		};
 		};
 
 
 		uint32_t m_flags;
 		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
 	struct RenderTarget

+ 213 - 353
src/renderer_gl.cpp

@@ -194,31 +194,30 @@ namespace bgfx
 
 
 	static TextureFormatInfo s_textureFormat[TextureFormat::Count] =
 	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
 	struct Extension
@@ -595,9 +594,7 @@ namespace bgfx
 				GL_CHECK(glBindFramebuffer(GL_FRAMEBUFFER, m_msaaBackBufferFbo) );
 				GL_CHECK(glBindFramebuffer(GL_FRAMEBUFFER, m_msaaBackBufferFbo) );
 			}
 			}
 #else
 #else
-			BX_UNUSED(_width);
-			BX_UNUSED(_height);
-			BX_UNUSED(_msaa);
+			BX_UNUSED(_width, _height, _msaa);
 #endif // BGFX_CONFIG_RENDERER_OPENGL|BGFX_CONFIG_RENDERER_OPENGLES3
 #endif // BGFX_CONFIG_RENDERER_OPENGL|BGFX_CONFIG_RENDERER_OPENGLES3
 		}
 		}
 
 
@@ -1323,37 +1320,33 @@ namespace bgfx
 		m_vcref.invalidate(s_renderCtx.m_vaoStateCache);
 		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 BGFX_CONFIG_RENDERER_OPENGL|BGFX_CONFIG_RENDERER_OPENGLES3
 		if (_target == GL_TEXTURE_3D)
 		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
 		else
 #endif // BGFX_CONFIG_RENDERER_OPENGL|BGFX_CONFIG_RENDERER_OPENGLES3
 #endif // BGFX_CONFIG_RENDERER_OPENGL|BGFX_CONFIG_RENDERER_OPENGLES3
 		{
 		{
 			BX_UNUSED(_depth);
 			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 BGFX_CONFIG_RENDERER_OPENGL|BGFX_CONFIG_RENDERER_OPENGLES3
 		if (_target == GL_TEXTURE_3D)
 		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
 		else
 #endif // BGFX_CONFIG_RENDERER_OPENGL|BGFX_CONFIG_RENDERER_OPENGLES3
 #endif // BGFX_CONFIG_RENDERER_OPENGL|BGFX_CONFIG_RENDERER_OPENGLES3
 		{
 		{
 			BX_UNUSED(_depth);
 			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_target = _target;
 		m_numMips = _numMips;
 		m_numMips = _numMips;
 		m_flags = _flags;
 		m_flags = _flags;
 		m_currentFlags = UINT32_MAX;
 		m_currentFlags = UINT32_MAX;
+		m_requestedFormat = _format;
+		m_textureFormat   = _format;
 
 
 		GL_CHECK(glGenTextures(1, &m_id) );
 		GL_CHECK(glGenTextures(1, &m_id) );
 		BX_CHECK(0 != m_id, "Failed to generate texture id.");
 		BX_CHECK(0 != m_id, "Failed to generate texture id.");
 		GL_CHECK(glBindTexture(_target, m_id) );
 		GL_CHECK(glBindTexture(_target, m_id) );
 
 
 		setSamplerState(_flags);
 		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)
 	void Texture::create(const Memory* _mem, uint32_t _flags)
@@ -1411,215 +1428,105 @@ namespace bgfx
 		{
 		{
 			uint8_t numMips = imageContainer.m_numMips;
 			uint8_t numMips = imageContainer.m_numMips;
 
 
+			GLenum target = GL_TEXTURE_2D;
 			if (imageContainer.m_cubeMap)
 			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
 #if BGFX_CONFIG_RENDERER_OPENGL|BGFX_CONFIG_RENDERER_OPENGLES3
 			else if (imageContainer.m_depth > 1)
 			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
 #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
 								, lod
 								, internalFmt
 								, internalFmt
 								, width
 								, width
 								, height
 								, height
 								, depth
 								, depth
 								, 0
 								, 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
 								, internalFmt
 								, width
 								, width
 								, height
 								, height
 								, depth
 								, depth
 								, 0
 								, 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
 							compressedTexImage(target+side
 								, lod
 								, lod
 								, internalFmt
 								, internalFmt
@@ -1628,17 +1535,11 @@ namespace bgfx
 								, depth
 								, depth
 								, 0
 								, 0
 								, size
 								, size
-								, data
+								, NULL
 								);
 								);
 						}
 						}
 						else
 						else
 						{
 						{
-							if (NULL != data
-							&&  swizzle)
-							{
-								imageSwizzleBgra8(width, height, data, data);
-							}
-
 							texImage(target+side
 							texImage(target+side
 								, lod
 								, lod
 								, internalFmt
 								, internalFmt
@@ -1648,29 +1549,20 @@ namespace bgfx
 								, 0
 								, 0
 								, m_fmt
 								, m_fmt
 								, m_type
 								, 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)
 	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(glBindTexture(m_target, m_id) );
 		GL_CHECK(glPixelStorei(GL_UNPACK_ALIGNMENT, 1) );
 		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)
 						^ (uint64_t(getGLStringHash(GL_VERSION ) )<<16)
 						;
 						;
 
 
+#if BGFX_CONFIG_RENDERER_USE_EXTENSIONS
 		const char* extensions = (const char*)glGetString(GL_EXTENSIONS);
 		const char* extensions = (const char*)glGetString(GL_EXTENSIONS);
 		glGetError(); // ignore error if glGetString returns NULL.
 		glGetError(); // ignore error if glGetString returns NULL.
 		if (NULL != extensions)
 		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;
 		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;
 		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;
 			s_renderCtx.m_readPixelsFmt = GL_BGRA_EXT;
 #endif // BGFX_CONFIG_RENDERER_OPENGL
 #endif // BGFX_CONFIG_RENDERER_OPENGL
 
 
-			s_textureFormat[TextureFormat::BGRX8].m_fmt = GL_BGRA_EXT;
 			s_textureFormat[TextureFormat::BGRA8].m_fmt = GL_BGRA_EXT;
 			s_textureFormat[TextureFormat::BGRA8].m_fmt = GL_BGRA_EXT;
 
 
 			// Mixing GLES and GL extensions here. OpenGL EXT_bgra wants
 			// 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
 			// https://www.opengl.org/registry/specs/EXT/bgra.txt
 			if (!s_extension[Extension::EXT_bgra].m_supported)
 			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;
 				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_flags(0)
 			, m_currentFlags(UINT32_MAX)
 			, m_currentFlags(UINT32_MAX)
 			, m_numMips(0)
 			, 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 create(const Memory* _mem, uint32_t _flags);
 		void createColor(uint32_t _colorFormat, uint32_t _width, uint32_t _height, GLenum _min, GLenum _mag);
 		void createColor(uint32_t _colorFormat, uint32_t _width, uint32_t _height, GLenum _min, GLenum _mag);
 		void createDepth(uint32_t _width, uint32_t _height);
 		void createDepth(uint32_t _width, uint32_t _height);
@@ -578,7 +577,8 @@ namespace bgfx
 		uint32_t m_flags;
 		uint32_t m_flags;
 		uint32_t m_currentFlags;
 		uint32_t m_currentFlags;
 		uint8_t m_numMips;
 		uint8_t m_numMips;
-		bool m_compressed;
+		uint8_t m_requestedFormat;
+		uint8_t m_textureFormat;
 	};
 	};
 
 
 	struct Shader
 	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*/)
 	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');
 		bool decompress = cmdLine.hasArg('d');
 
 
 		if (decompress
 		if (decompress
-		||  0 == imageContainer.m_type)
+		||  0 == imageContainer.m_format)
 		{
 		{
 			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)
 			{
 			{
@@ -120,7 +120,7 @@ int main(int _argc, const char* _argv[])
 					width = bx::uint32_max(1, width);
 					width = bx::uint32_max(1, width);
 					height = bx::uint32_max(1, height);
 					height = bx::uint32_max(1, height);
 
 
-					Mip mip;
+					ImageMip mip;
 					if (imageGetRawData(imageContainer, side, lod, mem->data, mem->size, mip) )
 					if (imageGetRawData(imageContainer, side, lod, mem->data, mem->size, mip) )
 					{
 					{
 						uint32_t dstpitch = width*4;
 						uint32_t dstpitch = width*4;
@@ -130,7 +130,7 @@ int main(int _argc, const char* _argv[])
 						||  height != mip.m_height)
 						||  height != mip.m_height)
 						{
 						{
 							uint8_t* temp = (uint8_t*)realloc(NULL, mip.m_width*mip.m_height*4);
 							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;
 							uint32_t srcpitch = mip.m_width*4;
 
 
 							for (uint32_t yy = 0; yy < height; ++yy)
 							for (uint32_t yy = 0; yy < height; ++yy)
@@ -150,7 +150,7 @@ int main(int _argc, const char* _argv[])
 						}
 						}
 						else
 						else
 						{
 						{
-							mip.decode(bits);
+							imageDecodeToBgra8(bits, mip.m_data, mip.m_width, mip.m_height, mip.m_format);
 						}
 						}
 
 
 						char filePath[256];
 						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)
 			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) )
 				if (imageGetRawData(imageContainer, 0, lod, mem->data, mem->size, mip) )
 				{
 				{
 					char filePath[256];
 					char filePath[256];