Browse Source

Support for Cube and Volume textures.

bkaradzic 13 years ago
parent
commit
fe1252d260
10 changed files with 681 additions and 283 deletions
  1. 15 7
      include/bgfx.h
  2. 8 5
      src/bgfx_p.h
  3. 83 43
      src/dds.cpp
  4. 20 2
      src/dds.h
  5. 31 0
      src/glimports.h
  6. 227 95
      src/renderer_d3d9.cpp
  7. 17 1
      src/renderer_d3d9.h
  8. 203 94
      src/renderer_gl.cpp
  9. 38 0
      src/renderer_gl.h
  10. 39 36
      tools/ddsdump.cpp

+ 15 - 7
include/bgfx.h

@@ -74,6 +74,8 @@ namespace bgfx
 #define BGFX_STATE_SRGBWRITE            UINT64_C(0x0010000000000000)
 #define BGFX_STATE_MSAA                 UINT64_C(0x0020000000000000)
 
+#define BGFX_STATE_RESERVED             UINT64_C(0xff00000000000000)
+
 #define BGFX_STATE_NONE                 UINT64_C(0x0000000000000000)
 #define BGFX_STATE_MASK                 UINT64_C(0xffffffffffffffff)
 #define BGFX_STATE_DEFAULT (0 \
@@ -107,16 +109,21 @@ namespace bgfx
 #define BGFX_TEXTURE_V_CLAMP            UINT32_C(0x00000020)
 #define BGFX_TEXTURE_V_SHIFT            4
 #define BGFX_TEXTURE_V_MASK             UINT32_C(0x00000030)
-#define BGFX_TEXTURE_MIN_POINT          UINT32_C(0x00000100)
+#define BGFX_TEXTURE_W_REPEAT           UINT32_C(0x00000000)
+#define BGFX_TEXTURE_W_MIRROR           UINT32_C(0x00000100)
+#define BGFX_TEXTURE_W_CLAMP            UINT32_C(0x00000200)
+#define BGFX_TEXTURE_W_SHIFT            4
+#define BGFX_TEXTURE_W_MASK             UINT32_C(0x00000300)
+#define BGFX_TEXTURE_MIN_POINT          UINT32_C(0x00001000)
 #define BGFX_TEXTURE_MIN_SHIFT          8
-#define BGFX_TEXTURE_MIN_MASK           UINT32_C(0x00000100)
-#define BGFX_TEXTURE_MAG_POINT          UINT32_C(0x00001000)
+#define BGFX_TEXTURE_MIN_MASK           UINT32_C(0x00001000)
+#define BGFX_TEXTURE_MAG_POINT          UINT32_C(0x00010000)
 #define BGFX_TEXTURE_MAG_SHIFT          12
-#define BGFX_TEXTURE_MAG_MASK           UINT32_C(0x00001000)
-#define BGFX_TEXTURE_MIP_POINT          UINT32_C(0x00010000)
+#define BGFX_TEXTURE_MAG_MASK           UINT32_C(0x00010000)
+#define BGFX_TEXTURE_MIP_POINT          UINT32_C(0x00100000)
 #define BGFX_TEXTURE_MIP_SHIFT          16
-#define BGFX_TEXTURE_MIP_MASK           UINT32_C(0x00010000)
-#define BGFX_TEXTURE_SRGB               UINT32_C(0x00020000)
+#define BGFX_TEXTURE_MIP_MASK           UINT32_C(0x00100000)
+#define BGFX_TEXTURE_SRGB               UINT32_C(0x00200000)
 
 #define BGFX_RENDER_TARGET_NONE         UINT32_C(0x00000000)
 #define BGFX_RENDER_TARGET_COLOR_RGBA   UINT32_C(0x00000001)
@@ -157,6 +164,7 @@ namespace bgfx
 			D3D9_UnableToCreateInterface,
 			D3D9_UnableToCreateDevice,
 			D3D9_UnableToCreateRenderTarget,
+			D3D9_UnableToCreateTexture,
 			OPENGL_UnableToCreateContext,
 		};
 	};

+ 8 - 5
src/bgfx_p.h

@@ -98,10 +98,13 @@ namespace std { namespace tr1 {} using namespace tr1; } // namespace std
 #define BGFX_STATE_TEX2      UINT64_C(0x0400000000000000)
 #define BGFX_STATE_TEX3      UINT64_C(0x0800000000000000)
 #define BGFX_STATE_TEX4      UINT64_C(0x1000000000000000)
-#define BGFX_STATE_TEX_MASK  UINT64_C(0x1f00000000000000)
-#define BGFX_STATE_TEX_COUNT 5
+#define BGFX_STATE_TEX5      UINT64_C(0x2000000000000000)
+#define BGFX_STATE_TEX6      UINT64_C(0x4000000000000000)
+#define BGFX_STATE_TEX7      UINT64_C(0x8000000000000000)
+#define BGFX_STATE_TEX_MASK  UINT64_C(0xff00000000000000)
+#define BGFX_STATE_TEX_COUNT 8
 
-#define BGFX_SAMPLER_NONE               UINT16_C(0x0000)
+#define BGFX_SAMPLER_TEXTURE            UINT16_C(0x0000)
 #define BGFX_SAMPLER_RENDERTARGET_COLOR UINT16_C(0x0001)
 #define BGFX_SAMPLER_RENDERTARGET_DEPTH UINT16_C(0x0002)
 #define BGFX_SAMPLER_TYPE_MASK          UINT16_C(0x0003)
@@ -843,7 +846,7 @@ namespace bgfx
 			for (uint32_t ii = 0; ii < BGFX_STATE_TEX_COUNT; ++ii)
 			{
 				m_sampler[ii].m_idx = bgfx::invalidHandle;
-				m_sampler[ii].m_flags = BGFX_SAMPLER_NONE;
+				m_sampler[ii].m_flags = BGFX_SAMPLER_TEXTURE;
 			}
 		}
 
@@ -1037,7 +1040,7 @@ namespace bgfx
 			m_flags |= BGFX_STATE_TEX0<<_stage;
 			Sampler& sampler = m_state.m_sampler[_stage];
 			sampler.m_idx = _handle.idx;
-			sampler.m_flags = BGFX_SAMPLER_NONE;
+			sampler.m_flags = BGFX_SAMPLER_TEXTURE;
 
 			if (bgfx::invalidHandle != _sampler.idx)
 			{

+ 83 - 43
src/dds.cpp

@@ -19,6 +19,8 @@ namespace bgfx
 #define DDS_DXT4 MAKEFOURCC('D', 'X', 'T', '4')
 #define DDS_DXT5 MAKEFOURCC('D', 'X', 'T', '5')
 
+#define D3DFMT_A16B16G16R16F 113
+
 #define DDSD_CAPS                   0x00000001
 #define DDSD_HEIGHT                 0x00000002
 #define DDSD_WIDTH                  0x00000004
@@ -47,6 +49,11 @@ namespace bgfx
 #define DDSCAPS2_CUBEMAP_NEGATIVEY  0x00002000
 #define DDSCAPS2_CUBEMAP_POSITIVEZ  0x00004000
 #define DDSCAPS2_CUBEMAP_NEGATIVEZ  0x00008000
+
+#define DDS_CUBEMAP_ALLFACES (DDSCAPS2_CUBEMAP_POSITIVEX|DDSCAPS2_CUBEMAP_NEGATIVEX \
+							 |DDSCAPS2_CUBEMAP_POSITIVEY|DDSCAPS2_CUBEMAP_NEGATIVEY \
+							 |DDSCAPS2_CUBEMAP_POSITIVEZ|DDSCAPS2_CUBEMAP_NEGATIVEZ)
+
 #define DDSCAPS2_VOLUME             0x00200000
 
 bool isDds(const Memory* _mem)
@@ -216,7 +223,7 @@ void Mip::decode(uint8_t* _dst)
 {
 	const uint8_t* src = m_data;
 
-	if (0 != m_type)
+	if (TextureFormat::Unknown > m_type)
 	{
 		uint32_t width = m_width/4;
 		uint32_t height = m_height/4;
@@ -226,7 +233,7 @@ void Mip::decode(uint8_t* _dst)
 
 		switch (m_type)
 		{
-		case 1:
+		case TextureFormat::Dxt1:
 			for (uint32_t yy = 0; yy < height; ++yy)
 			{
 				for (uint32_t xx = 0; xx < width; ++xx)
@@ -243,7 +250,7 @@ void Mip::decode(uint8_t* _dst)
 			}
 			break;
 
-		case 2:
+		case TextureFormat::Dxt3:
 			for (uint32_t yy = 0; yy < height; ++yy)
 			{
 				for (uint32_t xx = 0; xx < width; ++xx)
@@ -262,7 +269,7 @@ void Mip::decode(uint8_t* _dst)
 			}
 			break;
 
-		case 3:
+		case TextureFormat::Dxt5:
 			for (uint32_t yy = 0; yy < height; ++yy)
 			{
 				for (uint32_t xx = 0; xx < width; ++xx)
@@ -288,7 +295,8 @@ void Mip::decode(uint8_t* _dst)
 		uint32_t height = m_height;
 
 		if (m_bpp == 1
-		||  m_bpp == 4)
+		||  m_bpp == 4
+		||  m_bpp == 8)
 		{
 			uint32_t pitch = m_width*m_bpp;
 			memcpy(_dst, src, pitch*height);
@@ -388,11 +396,21 @@ bool parseDds(Dds& _dds, const Memory* _mem)
 		return false;
 	}
 
+	bool cubeMap = 0 != (caps[1] & DDSCAPS2_CUBEMAP);
+	if (cubeMap)
+	{
+		if ( (caps[1] & DDS_CUBEMAP_ALLFACES) != DDS_CUBEMAP_ALLFACES)
+		{
+			// parital cube map is not supported.
+			return false;
+		}
+	}
+
 	stream.skip(4); // reserved
 
 	uint8_t bpp = 1;
 	uint8_t blockSize = 1;
-	uint8_t type = 0;
+	TextureFormat::Enum type = TextureFormat::Unknown;
 	bool hasAlpha = pixelFlags & DDPF_ALPHAPIXELS;
 
 	if (pixelFlags & DDPF_FOURCC)
@@ -400,21 +418,27 @@ bool parseDds(Dds& _dds, const Memory* _mem)
 		switch (fourcc)
 		{
 		case DDS_DXT1:
-			type = 1;
+			type = TextureFormat::Dxt1;
 			blockSize = 8;
 			break;
 
 		case DDS_DXT2:
 		case DDS_DXT3:
-			type = 2;
+			type = TextureFormat::Dxt3;
 			blockSize = 16;
 			break;
 
 		case DDS_DXT4:
 		case DDS_DXT5:
-			type = 3;
+			type = TextureFormat::Dxt5;
 			blockSize = 16;
 			break;
+
+		case D3DFMT_A16B16G16R16F:
+			type = TextureFormat::ABGR16;
+			blockSize = 8;
+			bpp = 8;
+			break;
 		}
 	}
 	else
@@ -422,82 +446,98 @@ bool parseDds(Dds& _dds, const Memory* _mem)
 		switch (pixelFlags)
 		{
 		case DDPF_RGB:
-			blockSize *= 3;
+			type = TextureFormat::XRGB8;
+			blockSize = 3;
 			bpp = 3;
 			break;
 
 		case DDPF_RGB|DDPF_ALPHAPIXELS:
-			blockSize *= 4;
+			type = TextureFormat::ARGB8;
+			blockSize = 4;
 			bpp = 4;
 			break;
 
-		case DDPF_LUMINANCE:
 		case DDPF_INDEXED:
+		case DDPF_LUMINANCE:
 		case DDPF_ALPHA:
+			type = TextureFormat::L8;
 			bpp = 1;
 			break;
 
+// 			type = TextureFormat::A8;
+// 			bpp = 1;
+// 			break;
+
 		default:
 			bpp = 0;
 			break;
 		}
 	}
 
+	_dds.m_type = type;
 	_dds.m_width = width;
 	_dds.m_height = height;
 	_dds.m_depth = depth;
 	_dds.m_blockSize = blockSize;
 	_dds.m_numMips = (caps[0] & DDSCAPS_MIPMAP) ? mips : 1;
 	_dds.m_bpp = bpp;
-	_dds.m_type = type;
 	_dds.m_hasAlpha = hasAlpha;
+	_dds.m_cubeMap = cubeMap;
 
 	return true;
 }
 
-bool getRawImageData(const Dds& _dds, uint8_t _index, const Memory* _mem, Mip& _mip)
+bool getRawImageData(const Dds& _dds, uint8_t _side, uint8_t _lod, const Memory* _mem, Mip& _mip)
 {
-	uint32_t width = _dds.m_width;
-	uint32_t height = _dds.m_height;
 	uint32_t blockSize = _dds.m_blockSize;
 	uint32_t offset = DDS_IMAGE_DATA_OFFSET;
 	uint8_t bpp = _dds.m_bpp;
-	uint8_t type = _dds.m_type;
+	TextureFormat::Enum type = _dds.m_type;
 	bool hasAlpha = _dds.m_hasAlpha;
 
-	for (uint8_t ii = 0, num = _dds.m_numMips; ii < num; ++ii)
+	for (uint8_t side = 0, numSides = _dds.m_cubeMap ? 6 : 1; side < numSides; ++side)
 	{
-		width = uint32_max(1, width);
-		height = uint32_max(1, height);
+		uint32_t width = _dds.m_width;
+		uint32_t height = _dds.m_height;
+		uint32_t depth = _dds.m_depth;
 
-		uint32_t size = width*height*blockSize;
-		if (0 != type)
+		for (uint8_t lod = 0, num = _dds.m_numMips; lod < num; ++lod)
 		{
-			width = uint32_max(1, (width + 3)>>2);
-			height = uint32_max(1, (height + 3)>>2);
-			size = width*height*blockSize;
+			width = uint32_max(1, width);
+			height = uint32_max(1, height);
+			depth = uint32_max(1, depth);
 
-			width <<= 2;
-			height <<= 2;
-		}
+			uint32_t size = width*height*depth*blockSize;
+			if (TextureFormat::Unknown > type)
+			{
+				width = uint32_max(1, (width + 3)>>2);
+				height = uint32_max(1, (height + 3)>>2);
+				size = width*height*depth*blockSize;
 
-		if (ii == _index)
-		{
-			_mip.m_width = width;
-			_mip.m_height = height;
-			_mip.m_blockSize = blockSize;
-			_mip.m_size = size;
-			_mip.m_data = _mem->data + offset;
-			_mip.m_bpp = bpp;
-			_mip.m_type = type;
-			_mip.m_hasAlpha = hasAlpha;
-			return true;
-		}
+				width <<= 2;
+				height <<= 2;
+			}
+
+			if (side == _side
+			&&  lod == _lod)
+			{
+				_mip.m_width = width;
+				_mip.m_height = height;
+				_mip.m_blockSize = blockSize;
+				_mip.m_size = size;
+				_mip.m_data = _mem->data + offset;
+				_mip.m_bpp = bpp;
+				_mip.m_type = type;
+				_mip.m_hasAlpha = hasAlpha;
+				return true;
+			}
 
-		offset += size;
+			offset += size;
 
-		width >>= 1;
-		height >>= 1;
+			width >>= 1;
+			height >>= 1;
+			depth >>= 1;
+		}
 	}
 
 	return false;

+ 20 - 2
src/dds.h

@@ -10,16 +10,34 @@
 
 namespace bgfx
 {
+	struct TextureFormat
+	{
+		enum Enum
+		{
+			Dxt1,
+			Dxt3,
+			Dxt5,
+			Unknown, // compressed formats are above
+			L8,
+			XRGB8,
+			ARGB8,
+			ABGR16,
+
+			Count
+		};
+	};
+
 	struct Dds
 	{
+		TextureFormat::Enum m_type;
 		uint32_t m_width;
 		uint32_t m_height;
 		uint32_t m_depth;
 		uint8_t m_blockSize;
 		uint8_t m_numMips;
 		uint8_t m_bpp;
-		uint8_t m_type;
 		bool m_hasAlpha;
+		bool m_cubeMap;
 	};
 
 	struct Mip
@@ -39,7 +57,7 @@ namespace bgfx
 
 	bool isDds(const Memory* _mem);
 	bool parseDds(Dds& _dds, const Memory* _mem);
-	bool getRawImageData(const Dds& _dds, uint8_t _index, const Memory* _mem, Mip& _mip);
+	bool getRawImageData(const Dds& _dds, uint8_t _side, uint8_t _index, const Memory* _mem, Mip& _mip);
 
 } // namespace bgfx
 

+ 31 - 0
src/glimports.h

@@ -11,6 +11,34 @@
 // OpenGL 2.1 Reference Pages
 // http://www.opengl.org/sdk/docs/man/
 
+#if BX_PLATFORM_WINDOWS
+GL_IMPORT(false, PFNGLGETERRORPROC,                 glGetError);
+GL_IMPORT(false, PFNGLREADPIXELSPROC,               glReadPixels);
+GL_IMPORT(false, PFNGLTEXIMAGE2DPROC,               glTexImage2D);
+GL_IMPORT(false, PFNGLTEXPARAMETERIPROC,            glTexParameteri);
+GL_IMPORT(false, PFNGLBINDTEXTUREPROC,              glBindTexture);
+GL_IMPORT(false, PFNGLGENTEXTURESPROC,              glGenTextures);
+GL_IMPORT(false, PFNGLDELETETEXTURESPROC,           glDeleteTextures);
+GL_IMPORT(false, PFNGLCOLORMASKPROC,                glColorMask);
+GL_IMPORT(false, PFNGLDEPTHFUNCPROC,                glDepthFunc);
+GL_IMPORT(false, PFNGLDISABLEPROC,                  glDisable);
+GL_IMPORT(false, PFNGLVIEWPORTPROC,                 glViewport);
+GL_IMPORT(false, PFNGLDRAWELEMENTSPROC,             glDrawElements);
+GL_IMPORT(false, PFNGLGETINTEGERVPROC,              glGetIntegerv);
+GL_IMPORT(false, PFNGLGETSTRINGPROC,                glGetString);
+GL_IMPORT(false, PFNGLDRAWARRAYSPROC,               glDrawArrays);
+GL_IMPORT(false, PFNGLBLENDFUNCPROC,                glBlendFunc);
+GL_IMPORT(false, PFNGLPOINTSIZEPROC,                glPointSize);
+GL_IMPORT(false, PFNGLCULLFACEPROC,                 glCullFace);
+GL_IMPORT(false, PFNGLCLEARPROC,                    glClear);
+GL_IMPORT(false, PFNGLSCISSORPROC,                  glScissor);
+GL_IMPORT(false, PFNGLENABLEPROC,                   glEnable);
+GL_IMPORT(false, PFNGLCLEARSTENCILPROC,             glClearStencil);
+GL_IMPORT(false, PFNGLDEPTHMASKPROC,                glDepthMask);
+GL_IMPORT(false, PFNGLCLEARDEPTHPROC,               glClearDepth);
+GL_IMPORT(false, PFNGLCLEARCOLORPROC,               glClearColor);
+#endif // BX_PLATFORM_WINDOWS
+
 GL_IMPORT(false, PFNGLACTIVETEXTUREPROC,            glActiveTexture);
 GL_IMPORT(false, PFNGLCOMPRESSEDTEXIMAGE2DPROC,     glCompressedTexImage2D);
 GL_IMPORT(false, PFNGLBINDBUFFERPROC,               glBindBuffer);
@@ -61,6 +89,9 @@ GL_IMPORT(false, PFNGLUNIFORM3FVPROC,               glUniform3fv);
 GL_IMPORT(false, PFNGLUNIFORM4FVPROC,               glUniform4fv);
 GL_IMPORT(false, PFNGLUNIFORMMATRIX3FVPROC,         glUniformMatrix3fv);
 GL_IMPORT(false, PFNGLUNIFORMMATRIX4FVPROC,         glUniformMatrix4fv);
+GL_IMPORT(false, PFNGLTEXIMAGE3DPROC,               glTexImage3D);
+GL_IMPORT(false, PFNGLTEXSUBIMAGE3DPROC,            glTexSubImage3D);
+GL_IMPORT(false, PFNGLCOPYTEXSUBIMAGE3DPROC,        glCopyTexSubImage3D);
 
 GL_IMPORT(false, PFNGLGENQUERIESPROC,               glGenQueries);
 GL_IMPORT(false, PFNGLDELETEQUERIESPROC,            glDeleteQueries);

+ 227 - 95
src/renderer_d3d9.cpp

@@ -114,6 +114,24 @@ namespace bgfx
 		D3DTEXF_ANISOTROPIC,
 	};
 
+	struct TextureFormatInfo
+	{
+		D3DFORMAT m_fmt;
+		uint8_t m_bpp;
+	};
+
+	static const TextureFormatInfo s_textureFormat[TextureFormat::Count] =
+	{
+		{ D3DFMT_DXT1,         1 },
+		{ D3DFMT_DXT3,         1 },
+		{ D3DFMT_DXT5,         1 },
+		{ D3DFMT_UNKNOWN,      0 },
+		{ D3DFMT_L8,           1 },
+		{ D3DFMT_X8R8G8B8,     4 },
+		{ D3DFMT_A8R8G8B8,     4 },
+		{ D3DFMT_A16B16G16R16, 8 },
+	};
+
 	struct RendererContext
 	{
 		RendererContext()
@@ -972,11 +990,146 @@ namespace bgfx
 			DX_CHECK(s_renderCtx.m_device->CreateVertexShader(code, (IDirect3DVertexShader9**)&m_ptr) );
 		}
 	}
-	
+
+	void Texture::createTexture(uint32_t _width, uint32_t _height, uint8_t _numMips, D3DFORMAT _fmt)
+	{
+		m_type = Texture2D;
+
+		DX_CHECK(s_renderCtx.m_device->CreateTexture(_width
+			, _height
+			, _numMips
+			, 0
+			, _fmt
+			, D3DPOOL_MANAGED
+			, (IDirect3DTexture9**)&m_ptr
+			, NULL
+			) );
+
+		BGFX_FATAL(NULL != m_ptr, Fatal::D3D9_UnableToCreateTexture, "Failed to create texture (size: %dx%d, mips: %d, fmt: 0x%08x)."
+			, _width
+			, _height
+			, _numMips
+			, _fmt
+			);
+	}
+
+	void Texture::createVolumeTexture(uint32_t _width, uint32_t _height, uint32_t _depth, uint32_t _numMips, D3DFORMAT _fmt)
+	{
+		m_type = Texture3D;
+
+		DX_CHECK(s_renderCtx.m_device->CreateVolumeTexture(_width
+			, _height
+			, _depth
+			, _numMips
+			, 0
+			, _fmt
+			, D3DPOOL_MANAGED
+			, (IDirect3DVolumeTexture9**)&m_ptr
+			, NULL
+			) );
+
+		BGFX_FATAL(NULL != m_ptr, Fatal::D3D9_UnableToCreateTexture, "Failed to create volume texture (size: %dx%dx%d, mips: %d, fmt: 0x%08x)."
+			, _width
+			, _height
+			, _depth
+			, _numMips
+			, _fmt
+			);
+	}
+
+	void Texture::createCubeTexture(uint32_t _edge, uint32_t _numMips, D3DFORMAT _fmt)
+	{
+		m_type = TextureCube;
+
+		DX_CHECK(s_renderCtx.m_device->CreateCubeTexture(_edge
+			, _numMips
+			, 0
+			, _fmt
+			, D3DPOOL_MANAGED
+			, (IDirect3DCubeTexture9**)&m_ptr
+			, NULL
+			) );
+
+		BGFX_FATAL(NULL != m_ptr, Fatal::D3D9_UnableToCreateTexture, "Failed to create cube texture (edge: %d, mips: %d, fmt: 0x%08x)."
+			, _edge
+			, _numMips
+			, _fmt
+			);
+	}
+
+	uint8_t* Texture::lock(uint8_t _side, uint8_t _lod, uint32_t& _pitch, uint32_t& _slicePitch)
+	{
+		switch (m_type)
+		{
+		case Texture2D:
+			{
+				IDirect3DTexture9* texture = (IDirect3DTexture9*)m_ptr;
+				D3DLOCKED_RECT rect;
+				DX_CHECK(texture->LockRect(_lod, &rect, NULL, 0) );
+				_pitch = rect.Pitch;
+				_slicePitch = 0;
+				return (uint8_t*)rect.pBits;
+			}
+
+		case Texture3D:
+			{
+				IDirect3DVolumeTexture9* texture = (IDirect3DVolumeTexture9*)m_ptr;
+				D3DLOCKED_BOX box;
+				DX_CHECK(texture->LockBox(_lod, &box, NULL, 0) );
+				_pitch = box.RowPitch;
+				_slicePitch = box.SlicePitch;
+				return (uint8_t*)box.pBits;
+			}
+
+		case TextureCube:
+			{
+				IDirect3DCubeTexture9* texture = (IDirect3DCubeTexture9*)m_ptr;
+				D3DLOCKED_RECT rect;
+				DX_CHECK(texture->LockRect(D3DCUBEMAP_FACES(_side), _lod, &rect, NULL, 0) );
+				_pitch = rect.Pitch;
+				_slicePitch = 0;
+				return (uint8_t*)rect.pBits;
+			}
+		}
+
+		BX_CHECK(false, "You should not be here.");
+		return NULL;
+	}
+
+	void Texture::unlock(uint8_t _side, uint8_t _lod)
+	{
+		switch (m_type)
+		{
+		case Texture2D:
+			{
+				IDirect3DTexture9* texture = (IDirect3DTexture9*)m_ptr;
+				DX_CHECK(texture->UnlockRect(_lod) );
+			}
+			return;
+
+		case Texture3D:
+			{
+				IDirect3DVolumeTexture9* texture = (IDirect3DVolumeTexture9*)m_ptr;
+				DX_CHECK(texture->UnlockBox(_lod) );
+			}
+			return;
+
+		case TextureCube:
+			{
+				IDirect3DCubeTexture9* texture = (IDirect3DCubeTexture9*)m_ptr;
+				DX_CHECK(texture->UnlockRect(D3DCUBEMAP_FACES(_side), _lod) );
+			}
+			return;
+		}
+
+		BX_CHECK(false, "You should not be here.");
+	}
+
 	void Texture::create(const Memory* _mem, uint32_t _flags)
 	{
 		m_tau = s_textureAddress[(_flags&BGFX_TEXTURE_U_MASK)>>BGFX_TEXTURE_U_SHIFT];
 		m_tav = s_textureAddress[(_flags&BGFX_TEXTURE_V_MASK)>>BGFX_TEXTURE_V_SHIFT];
+		m_taw = s_textureAddress[(_flags&BGFX_TEXTURE_W_MASK)>>BGFX_TEXTURE_W_SHIFT];
 		m_minFilter = s_textureFilter[(_flags&BGFX_TEXTURE_MIN_MASK)>>BGFX_TEXTURE_MIN_SHIFT];
 		m_magFilter = s_textureFilter[(_flags&BGFX_TEXTURE_MAG_MASK)>>BGFX_TEXTURE_MAG_SHIFT];
 		m_mipFilter = s_textureFilter[(_flags&BGFX_TEXTURE_MIP_MASK)>>BGFX_TEXTURE_MIP_SHIFT];
@@ -986,112 +1139,93 @@ namespace bgfx
 
 		if (parseDds(dds, _mem) )
 		{
-			D3DFORMAT typefmt[4] =
-			{
-				D3DFMT_X8R8G8B8,
-				D3DFMT_DXT1,
-				D3DFMT_DXT3,
-				D3DFMT_DXT5,
-			};
-
-			D3DFORMAT fmt = typefmt[dds.m_type];
+			uint8_t bpp = dds.m_bpp;
 
 			bool decompress = false;
-			uint8_t bpp = dds.m_bpp;
 
-			if (0 == dds.m_type)
+			if (dds.m_cubeMap)
 			{
-				switch (dds.m_bpp)
-				{
-				case 1:
-					fmt = D3DFMT_L8;
-					break;
-
-				case 4:
-					fmt = D3DFMT_A8R8G8B8;
-					break;
-
-				default:
-					fmt = D3DFMT_X8R8G8B8;
-					break;
-				}
+				createCubeTexture(dds.m_width, dds.m_numMips, s_textureFormat[dds.m_type].m_fmt);
 			}
-			else if (decompress)
+			else if (dds.m_depth > 1)
 			{
-				fmt = D3DFMT_A8R8G8B8;
-				bpp = 4;
+				createVolumeTexture(dds.m_width, dds.m_height, dds.m_depth, dds.m_numMips, s_textureFormat[dds.m_type].m_fmt);
+			}
+			else
+			{
+				createTexture(dds.m_width, dds.m_height, dds.m_numMips, s_textureFormat[dds.m_type].m_fmt);
 			}
-
-			DX_CHECK(s_renderCtx.m_device->CreateTexture(dds.m_width
-				, dds.m_height
-				, dds.m_numMips
-				, 0
-				, fmt
-				, D3DPOOL_MANAGED
-				, &m_ptr
-				, NULL
-				) );
 
 			if (decompress
-			||  0 == dds.m_type)
+			||  TextureFormat::Unknown < dds.m_type)
 			{
-				uint32_t width = dds.m_width;
-				uint32_t height = dds.m_height;
-
-				for (uint32_t lod = 0, num = dds.m_numMips; lod < num; ++lod)
+				for (uint8_t side = 0, numSides = dds.m_cubeMap ? 6 : 1; side < numSides; ++side)
 				{
-					width = uint32_max(1, width);
-					height = uint32_max(1, height);
+					uint32_t width = dds.m_width;
+					uint32_t height = dds.m_height;
+					uint32_t depth = dds.m_depth;
 
-					Mip mip;
-					if (getRawImageData(dds, lod, _mem, mip) )
+					for (uint32_t lod = 0, num = dds.m_numMips; lod < num; ++lod)
 					{
-						D3DLOCKED_RECT rect;
-						DX_CHECK(m_ptr->LockRect(lod, &rect, NULL, 0) );
-						uint8_t* bits = (uint8_t*)rect.pBits;
+						width = uint32_max(1, width);
+						height = uint32_max(1, height);
+						depth = uint32_max(1, depth);
 
-						if (width != mip.m_width
-						||  height != mip.m_height)
+						Mip mip;
+						if (getRawImageData(dds, side, lod, _mem, mip) )
 						{
-							uint32_t srcpitch = mip.m_width*bpp;
+							uint32_t pitch;
+							uint32_t slicePitch;
+							uint8_t* bits = lock(side, lod, pitch, slicePitch);
+
+							if (width != mip.m_width
+							||  height != mip.m_height)
+							{
+								uint32_t srcpitch = mip.m_width*bpp;
 
-							uint8_t* temp = (uint8_t*)g_realloc(NULL, srcpitch*mip.m_height);
-							mip.decode(temp);
+								uint8_t* temp = (uint8_t*)g_realloc(NULL, srcpitch*mip.m_height);
+								mip.decode(temp);
 
-							uint32_t dstpitch = rect.Pitch;
-							for (uint32_t yy = 0; yy < height; ++yy)
+								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);
+								}
+
+								g_free(temp);
+							}
+							else
 							{
-								uint8_t* src = &temp[yy*srcpitch];
-								uint8_t* dst = &bits[yy*dstpitch];
-								memcpy(dst, src, srcpitch);
+								mip.decode(bits);
 							}
 
-							g_free(temp);
-						}
-						else
-						{
-							mip.decode(bits);
+							unlock(side, lod);
 						}
-	
-						DX_CHECK(m_ptr->UnlockRect(lod) );
-					}
 
-					width >>= 1;
-					height >>= 1;
+						width >>= 1;
+						height >>= 1;
+					}
 				}
 			}
 			else
 			{
-				for (uint32_t ii = 0, num = dds.m_numMips; ii < num; ++ii)
+				for (uint8_t side = 0, numSides = dds.m_cubeMap ? 6 : 1; side < numSides; ++side)
 				{
-					Mip mip;
-					if (getRawImageData(dds, ii, _mem, mip) )
+					for (uint32_t lod = 0, num = dds.m_numMips; lod < num; ++lod)
 					{
-						D3DLOCKED_RECT rect;
-						DX_CHECK(m_ptr->LockRect(ii, &rect, NULL, 0) );
-						uint8_t* dst = (uint8_t*)rect.pBits;
-						memcpy(dst, mip.m_data, mip.m_size);
-						DX_CHECK(m_ptr->UnlockRect(ii) );
+						Mip mip;
+						if (getRawImageData(dds, 0, lod, _mem, mip) )
+						{
+							uint32_t pitch;
+							uint32_t slicePitch;
+							uint8_t* dst = lock(side, lod, pitch, slicePitch);
+
+							memcpy(dst, mip.m_data, mip.m_size);
+
+							unlock(side, lod);
+						}
 					}
 				}
 			}
@@ -1119,26 +1253,20 @@ namespace bgfx
 
 				stream.align(16);
 
-				DX_CHECK(s_renderCtx.m_device->CreateTexture(width
-					, height
-					, numMips
-					, 0
-					, 1 == bpp ? D3DFMT_L8 : D3DFMT_A8R8G8B8
-					, D3DPOOL_MANAGED
-					, &m_ptr
-					, NULL
-					) );
+				D3DFORMAT fmt = 1 == bpp ? D3DFMT_L8 : D3DFMT_A8R8G8B8;
+
+				createTexture(width, height, numMips, fmt);
 
 				for (uint8_t mip = 0; mip < numMips; ++mip)
 				{
 					width = uint32_max(width, 1);
 					height = uint32_max(height, 1);
 
-					D3DLOCKED_RECT rect;
-					DX_CHECK(m_ptr->LockRect(mip, &rect, NULL, 0) );
-					uint8_t* dst = (uint8_t*)rect.pBits;
+					uint32_t pitch;
+					uint32_t slicePitch;
+					uint8_t* dst = lock(0, mip, pitch, slicePitch);
 					stream.read(dst, width*height*bpp);
-					DX_CHECK(m_ptr->UnlockRect(mip) );
+					unlock(0, mip);
 
 					width >>= 1;
 					height >>= 1;
@@ -1158,6 +1286,10 @@ namespace bgfx
 		DX_CHECK(s_renderCtx.m_device->SetSamplerState(_stage, D3DSAMP_MIPFILTER, m_mipFilter) );
 		DX_CHECK(s_renderCtx.m_device->SetSamplerState(_stage, D3DSAMP_ADDRESSU, m_tau) );
 		DX_CHECK(s_renderCtx.m_device->SetSamplerState(_stage, D3DSAMP_ADDRESSV, m_tav) );
+		if (m_type == Texture3D)
+		{
+			DX_CHECK(s_renderCtx.m_device->SetSamplerState(_stage, D3DSAMP_ADDRESSW, m_taw) );
+		}
 #if BX_PLATFORM_WINDOWS
 		DX_CHECK(s_renderCtx.m_device->SetSamplerState(_stage, D3DSAMP_SRGBTEXTURE, m_srgb) );
 #endif // BX_PLATFORM_WINDOWS
@@ -1970,15 +2102,15 @@ namespace bgfx
 							{
 								switch (sampler.m_flags&BGFX_SAMPLER_TYPE_MASK)
 								{
-								case 0:
+								case BGFX_SAMPLER_TEXTURE:
 									s_renderCtx.m_textures[sampler.m_idx].commit(stage);
 									break;
 
-								case 1:
+								case BGFX_SAMPLER_RENDERTARGET_COLOR:
 									s_renderCtx.m_renderTargets[sampler.m_idx].commit(stage);
 									break;
 
-								case 2:
+								case BGFX_SAMPLER_RENDERTARGET_DEPTH:
 //									id = s_renderCtx.m_renderTargets[sampler.m_idx].m_depth.m_id;
 									break;
 								}

+ 17 - 1
src/renderer_d3d9.h

@@ -269,11 +269,25 @@ namespace bgfx
 
 	struct Texture
 	{
+		enum Enum
+		{
+			Texture2D,
+			Texture3D,
+			TextureCube,
+		};
+
 		Texture()
 			: m_ptr(NULL)
 		{
 		}
 
+		void createTexture(uint32_t _width, uint32_t _height, uint8_t _numMips, D3DFORMAT _fmt);
+		void createVolumeTexture(uint32_t _width, uint32_t _height, uint32_t _depth, uint32_t _numMips, D3DFORMAT _fmt);
+		void createCubeTexture(uint32_t _edge, uint32_t _numMips, D3DFORMAT _fmt);
+
+		uint8_t* lock(uint8_t _side, uint8_t _lod, uint32_t& _pitch, uint32_t& _slicePitch);
+		void unlock(uint8_t _side, uint8_t _lod);
+
 		void create(const Memory* _mem, uint32_t _flags);
 
 		void destroy()
@@ -283,12 +297,14 @@ namespace bgfx
 
 		void commit(uint8_t _stage);
 	
-		IDirect3DTexture9* m_ptr;
+		IDirect3DBaseTexture9* m_ptr;
 		D3DTEXTUREFILTERTYPE m_minFilter;
 		D3DTEXTUREFILTERTYPE m_magFilter;
 		D3DTEXTUREFILTERTYPE m_mipFilter;
 		D3DTEXTUREADDRESS m_tau;
 		D3DTEXTUREADDRESS m_tav;
+		D3DTEXTUREADDRESS m_taw;
+		Enum m_type;
 		bool m_srgb;
 	};
 

+ 203 - 94
src/renderer_gl.cpp

@@ -16,6 +16,12 @@
 
 namespace bgfx
 {
+#if BX_PLATFORM_WINDOWS
+	PFNWGLGETPROCADDRESSPROC wglGetProcAddress;
+	PFNWGLMAKECURRENTPROC wglMakeCurrent;
+	PFNWGLCREATECONTEXTPROC wglCreateContext;
+#endif // BX_PLATFORM_WINDOWS
+
 #define GL_IMPORT(_optional, _proto, _func) _proto _func
 #include "glimports.h"
 #undef GL_IMPORT
@@ -116,6 +122,18 @@ namespace bgfx
 #elif BX_PLATFORM_WINDOWS
 				if (NULL == m_hdc)
 				{
+					m_opengl32dll = LoadLibrary("opengl32.dll");
+					BGFX_FATAL(NULL != m_opengl32dll, bgfx::Fatal::OPENGL_UnableToCreateContext, "Failed to load opengl32.dll.");
+
+					wglGetProcAddress = (PFNWGLGETPROCADDRESSPROC)GetProcAddress(m_opengl32dll, "wglGetProcAddress");
+					BGFX_FATAL(NULL != wglGetProcAddress, bgfx::Fatal::OPENGL_UnableToCreateContext, "Failed get wglGetProcAddress.");
+
+					wglMakeCurrent = (PFNWGLMAKECURRENTPROC)GetProcAddress(m_opengl32dll, "wglMakeCurrent");
+					BGFX_FATAL(NULL != wglMakeCurrent, bgfx::Fatal::OPENGL_UnableToCreateContext, "Failed get wglMakeCurrent.");
+
+					wglCreateContext = (PFNWGLCREATECONTEXTPROC)GetProcAddress(m_opengl32dll, "wglCreateContext");
+					BGFX_FATAL(NULL != wglCreateContext, bgfx::Fatal::OPENGL_UnableToCreateContext, "Failed get wglCreateContext.");
+
 					m_hdc = GetDC(g_bgfxHwnd);
 					BGFX_FATAL(NULL != m_hdc, bgfx::Fatal::OPENGL_UnableToCreateContext, "GetDC failed!");
 
@@ -148,6 +166,10 @@ namespace bgfx
 #	define GL_IMPORT(_optional, _proto, _func) \
 				{ \
 					_func = (_proto)wglGetProcAddress(#_func); \
+					if (_func == NULL) \
+					{ \
+						_func = (_proto)GetProcAddress(m_opengl32dll, #_func); \
+					} \
 					BGFX_FATAL(_optional || NULL != _func, bgfx::Fatal::OPENGL_UnableToCreateContext, "Failed to create OpenGL context. wglGetProcAddress(\"%s\")", #_func); \
 				}
 #	include "glimports.h"
@@ -309,11 +331,6 @@ namespace bgfx
 			}
 		}
 
-		void init()
-		{
-			setRenderContextSize(BGFX_DEFAULT_WIDTH, BGFX_DEFAULT_HEIGHT);
-		}
-
 		void saveScreenShot(Memory* _mem)
 		{
 #if BGFX_CONFIG_RENDERER_OPENGL
@@ -324,6 +341,18 @@ namespace bgfx
 #endif // BGFX_CONFIG_RENDERER_OPENGL
 		}
 
+		void init()
+		{
+			setRenderContextSize(BGFX_DEFAULT_WIDTH, BGFX_DEFAULT_HEIGHT);
+		}
+
+		void shutdown()
+		{
+#if BX_PLATFORM_WINDOWS
+			FreeLibrary(m_opengl32dll);
+#endif // BX_PLATFORM_WINDOWS
+		}
+
 		IndexBuffer m_indexBuffers[BGFX_CONFIG_MAX_INDEX_BUFFERS];
 		VertexBuffer m_vertexBuffers[BGFX_CONFIG_MAX_VERTEX_BUFFERS];
 		Shader m_vertexShaders[BGFX_CONFIG_MAX_VERTEX_SHADERS];
@@ -350,6 +379,7 @@ namespace bgfx
 		const PPB_Instance* m_instInterface;
 		const PPB_Graphics3D* m_graphicsInterface;
 #elif BX_PLATFORM_WINDOWS
+		HMODULE m_opengl32dll;
 		HGLRC m_context;
 		HDC m_hdc;
 #elif BX_PLATFORM_LINUX
@@ -552,6 +582,30 @@ namespace bgfx
 		GL_NEAREST,
 	};
 
+	struct TextureFormatInfo
+	{
+		GLenum m_internalFmt;
+		GLenum m_format;
+		GLenum m_type;
+		uint8_t m_bpp;
+	};
+
+	static const TextureFormatInfo s_textureFormat[TextureFormat::Count] =
+	{
+		{ GL_COMPRESSED_RGBA_S3TC_DXT1_EXT, GL_ZERO,      GL_ZERO,           1 },
+		{ GL_COMPRESSED_RGBA_S3TC_DXT3_EXT, GL_ZERO,      GL_ZERO,           1 },
+		{ GL_COMPRESSED_RGBA_S3TC_DXT5_EXT, GL_ZERO,      GL_ZERO,           1 },
+		{ GL_ZERO,                          GL_ZERO,      GL_ZERO,           0 },
+		{ GL_LUMINANCE,                     GL_LUMINANCE, GL_UNSIGNED_BYTE,  1 },
+		{ GL_RGBA,                          GL_RGBA,      GL_UNSIGNED_BYTE,  4 },
+		{ GL_RGBA,                          GL_RGBA,      GL_UNSIGNED_BYTE,  4 },
+#if BGFX_CONFIG_RENDERER_OPENGL
+		{ GL_RGBA16,                        GL_RGBA,      GL_UNSIGNED_SHORT, 8 },
+#else
+		{ GL_RGBA,                          GL_RGBA,      GL_UNSIGNED_BYTE,  8 },
+#endif // BGFX_CONFIG_RENDERER_OPENGL
+	};
+
 	const char* glslTypeName(GLuint _type)
 	{
 #define GLSL_TYPE(_ty) case _ty: return #_ty
@@ -915,125 +969,167 @@ namespace bgfx
 
 	void Texture::create(const Memory* _mem, uint32_t _flags)
 	{
-		m_target = GL_TEXTURE_2D;
-
-		GL_CHECK(glGenTextures(1, &m_id) );
-		BX_CHECK(0 != m_id, "Failed to generate texture id.");
-		GL_CHECK(glBindTexture(m_target, m_id) );
-
-		GL_CHECK(glTexParameteri(m_target, GL_TEXTURE_WRAP_S, s_textureAddress[(_flags&BGFX_TEXTURE_U_MASK)>>BGFX_TEXTURE_U_SHIFT]) );
-		GL_CHECK(glTexParameteri(m_target, GL_TEXTURE_WRAP_T, s_textureAddress[(_flags&BGFX_TEXTURE_V_MASK)>>BGFX_TEXTURE_V_SHIFT]) );
-		GL_CHECK(glTexParameteri(m_target, GL_TEXTURE_MIN_FILTER, s_textureFilter[(_flags&BGFX_TEXTURE_MIN_MASK)>>BGFX_TEXTURE_MIN_SHIFT]) );
-		GL_CHECK(glTexParameteri(m_target, GL_TEXTURE_MAG_FILTER, s_textureFilter[(_flags&BGFX_TEXTURE_MAG_MASK)>>BGFX_TEXTURE_MAG_SHIFT]) );
-
 		Dds dds;
 
 		if (parseDds(dds, _mem) )
 		{
-			GLenum typefmt[4] =
+			if (dds.m_cubeMap)
+			{
+				m_target = GL_TEXTURE_CUBE_MAP;
+			}
+#if BGFX_CONFIG_RENDERER_OPENGL
+			else if (dds.m_depth > 1)
+			{
+				m_target = GL_TEXTURE_3D;
+			}
+#endif // BGFX_CONFIG_RENDERER_OPENGL
+			else
 			{
-				GL_RGBA,
-				GL_COMPRESSED_RGBA_S3TC_DXT1_EXT,
- 				GL_COMPRESSED_RGBA_S3TC_DXT3_EXT,
- 				GL_COMPRESSED_RGBA_S3TC_DXT5_EXT,
-			};
+				m_target = GL_TEXTURE_2D;
+			}
 
-			GL_CHECK(glTexParameteri(m_target, GL_TEXTURE_MIN_FILTER, 1 < dds.m_numMips ? GL_LINEAR_MIPMAP_LINEAR : GL_LINEAR) );
+			GL_CHECK(glGenTextures(1, &m_id) );
+			BX_CHECK(0 != m_id, "Failed to generate texture id.");
+			GL_CHECK(glBindTexture(m_target, m_id) );
 
-			GLenum fmt = typefmt[dds.m_type];
+			GL_CHECK(glTexParameteri(m_target, GL_TEXTURE_MIN_FILTER, 1 < dds.m_numMips ? GL_LINEAR_MIPMAP_LINEAR : GL_LINEAR) );
 
-			uint32_t width = dds.m_width;
-			uint32_t height = dds.m_height;
+			const TextureFormatInfo& tfi = s_textureFormat[dds.m_type];
+			GLenum internalFmt = tfi.m_internalFmt;
 
 			if (!s_renderCtx.m_dxtSupport
-			||  0 == dds.m_type)
+			||  TextureFormat::Unknown < dds.m_type)
 			{
-				fmt = s_extension[Extension::EXT_texture_format_BGRA8888].m_supported ? GL_BGRA_EXT : GL_RGBA;
-
-				uint8_t bpp = 4;
-				if (dds.m_type == 0
-				&&  dds.m_bpp == 1)
+				if (internalFmt == GL_RGBA)
 				{
-					fmt = GL_LUMINANCE;
-					bpp = 1;
+					internalFmt = s_extension[Extension::EXT_texture_format_BGRA8888].m_supported ? GL_BGRA_EXT : GL_RGBA;
 				}
 
-				uint8_t* bits = (uint8_t*)g_realloc(NULL, dds.m_width*dds.m_height*bpp);
+				uint8_t* bits = (uint8_t*)g_realloc(NULL, dds.m_width*dds.m_height*tfi.m_bpp);
+
+				GLenum target = m_target;
+				if (dds.m_cubeMap)
+				{
+					target = GL_TEXTURE_CUBE_MAP_POSITIVE_X;
+				}
 
-				for (uint32_t lod = 0, num = dds.m_numMips; lod < num; ++lod)
+				for (uint8_t side = 0, numSides = dds.m_cubeMap ? 6 : 1; side < numSides; ++side)
 				{
-					width = uint32_max(1, width);
-					height = uint32_max(1, height);
+					uint32_t width = dds.m_width;
+					uint32_t height = dds.m_height;
+					uint32_t depth = dds.m_depth;
 
-					Mip mip;
-					if (getRawImageData(dds, lod, _mem, mip) )
+					for (uint32_t lod = 0, num = dds.m_numMips; lod < num; ++lod)
 					{
-						mip.decode(bits);
+						width = uint32_max(1, width);
+						height = uint32_max(1, height);
+						depth = uint32_max(1, depth);
 
-						if (GL_RGBA == fmt)
+						Mip mip;
+						if (getRawImageData(dds, 0, lod, _mem, mip) )
 						{
-							uint32_t dstpitch = width*4;
-							for (uint32_t yy = 0; yy < height; ++yy)
-							{
-								uint8_t* dst = &bits[yy*dstpitch];
+							mip.decode(bits);
 
-								for (uint32_t xx = 0; xx < width; ++xx)
+							if (GL_RGBA == internalFmt)
+							{
+								uint32_t dstpitch = width*4;
+								for (uint32_t yy = 0; yy < height; ++yy)
 								{
-									uint8_t tmp = dst[0];
-									dst[0] = dst[2];
-									dst[2] = tmp;
-									dst += 4;
+									uint8_t* dst = &bits[yy*dstpitch];
+
+									for (uint32_t xx = 0; xx < width; ++xx)
+									{
+										uint8_t tmp = dst[0];
+										dst[0] = dst[2];
+										dst[2] = tmp;
+										dst += 4;
+									}
 								}
 							}
+
+#if BGFX_CONFIG_RENDERER_OPENGL
+							if (target == GL_TEXTURE_3D)
+							{
+								
+								GL_CHECK(glTexImage3D(target
+									, lod
+									, internalFmt
+									, width
+									, height
+									, depth
+									, 0
+									, tfi.m_format
+									, tfi.m_type
+									, bits
+									) );
+							}
+							else
+#endif // BGFX_CONFIG_RENDERER_OPENGL
+							{
+								GL_CHECK(glTexImage2D(target+side
+									, lod
+									, internalFmt
+									, width
+									, height
+									, 0
+									, tfi.m_format
+									, tfi.m_type
+									, bits
+									) );
+							}
 						}
 
-						GL_CHECK(glTexImage2D(m_target
-							, lod
-							, fmt
-							, width
-							, height
-							, 0
-							, fmt
-							, GL_UNSIGNED_BYTE
-							, bits
-						) );
+						width >>= 1;
+						height >>= 1;
+						depth >>= 1;
 					}
-
-					width >>= 1;
-					height >>= 1;
 				}
 
 				g_free(bits);
 			}
 			else
 			{
-				for (uint32_t ii = 0, num = dds.m_numMips; ii < num; ++ii)
+				for (uint8_t side = 0, numSides = dds.m_cubeMap ? 6 : 1; side < numSides; ++side)
 				{
-					width = uint32_max(1, width);
-					height = uint32_max(1, height);
+					uint32_t width = dds.m_width;
+					uint32_t height = dds.m_height;
+					uint32_t depth = dds.m_depth;
 
-					Mip mip;
-					if (getRawImageData(dds, ii, _mem, mip) )
+					for (uint32_t ii = 0, num = dds.m_numMips; ii < num; ++ii)
 					{
-						GL_CHECK(glCompressedTexImage2D(m_target
-							, ii
-							, fmt
-							, width
-							, height
-							, 0
-							, mip.m_size
-							, mip.m_data
-							) );
-					}
+						width = uint32_max(1, width);
+						height = uint32_max(1, height);
+						depth = uint32_max(1, depth);
 
-					width >>= 1;
-					height >>= 1;
+						Mip mip;
+						if (getRawImageData(dds, 0, ii, _mem, mip) )
+						{
+							GL_CHECK(glCompressedTexImage2D(m_target
+								, ii
+								, internalFmt
+								, width
+								, height
+								, 0
+								, mip.m_size
+								, mip.m_data
+								) );
+						}
+
+						width >>= 1;
+						height >>= 1;
+						depth >>= 1;
+					}
 				}
 			}
 
 		}
 		else
 		{
+			m_target = GL_TEXTURE_2D;
+			GL_CHECK(glGenTextures(1, &m_id) );
+			BX_CHECK(0 != m_id, "Failed to generate texture id.");
+			GL_CHECK(glBindTexture(m_target, m_id) );
+
 			StreamRead stream(_mem->data, _mem->size);
 
 			uint32_t magic;
@@ -1055,7 +1151,7 @@ namespace bgfx
 
 				stream.align(16);
 
-				GL_CHECK(glTexParameteri(m_target, GL_TEXTURE_MIN_FILTER, 1 < dds.m_numMips ? GL_LINEAR_MIPMAP_LINEAR : GL_LINEAR) );
+				GL_CHECK(glTexParameteri(m_target, GL_TEXTURE_MIN_FILTER, 1 < numMips ? GL_LINEAR_MIPMAP_LINEAR : GL_LINEAR) );
 
 				for (uint8_t mip = 0; mip < numMips; ++mip)
 				{
@@ -1086,6 +1182,19 @@ namespace bgfx
 			}
 		}
 
+		GL_CHECK(glTexParameteri(m_target, GL_TEXTURE_WRAP_S, s_textureAddress[(_flags&BGFX_TEXTURE_U_MASK)>>BGFX_TEXTURE_U_SHIFT]) );
+		GL_CHECK(glTexParameteri(m_target, GL_TEXTURE_WRAP_T, s_textureAddress[(_flags&BGFX_TEXTURE_V_MASK)>>BGFX_TEXTURE_V_SHIFT]) );
+
+#if BGFX_CONFIG_RENDERER_OPENGL
+		if (m_target == GL_TEXTURE_3D)
+		{
+			GL_CHECK(glTexParameteri(m_target, GL_TEXTURE_WRAP_R, s_textureAddress[(_flags&BGFX_TEXTURE_W_MASK)>>BGFX_TEXTURE_W_SHIFT]) );
+		}
+#endif // BGFX_CONFIG_RENDERER_OPENGL
+
+		GL_CHECK(glTexParameteri(m_target, GL_TEXTURE_MIN_FILTER, s_textureFilter[(_flags&BGFX_TEXTURE_MIN_MASK)>>BGFX_TEXTURE_MIN_SHIFT]) );
+		GL_CHECK(glTexParameteri(m_target, GL_TEXTURE_MAG_FILTER, s_textureFilter[(_flags&BGFX_TEXTURE_MAG_MASK)>>BGFX_TEXTURE_MAG_SHIFT]) );
+
 		GL_CHECK(glBindTexture(m_target, 0) );
 	}
 
@@ -1490,6 +1599,7 @@ namespace bgfx
 
 	void Context::rendererShutdown()
 	{
+		s_renderCtx.shutdown();
 	}
 
 	void Context::rendererCreateIndexBuffer(IndexBufferHandle _handle, Memory* _mem)
@@ -2015,30 +2125,29 @@ namespace bgfx
 								const Sampler& sampler = state.m_sampler[stage];
 								Sampler& current = currentState.m_sampler[stage];
 								if (current.m_idx != sampler.m_idx
-									||  current.m_flags != sampler.m_flags
-									||  materialChanged)
+								||  current.m_flags != sampler.m_flags
+								||  materialChanged)
 								{
 									GL_CHECK(glActiveTexture(GL_TEXTURE0+stage) );
 									if (bgfx::invalidHandle != sampler.m_idx)
 									{
-										GLuint id = 0;
 										switch (sampler.m_flags&BGFX_SAMPLER_TYPE_MASK)
 										{
-										case 0:
-											id = s_renderCtx.m_textures[sampler.m_idx].m_id;
+										case BGFX_SAMPLER_TEXTURE:
+											{
+												const Texture& texture = s_renderCtx.m_textures[sampler.m_idx];
+												GL_CHECK(glBindTexture(texture.m_target, texture.m_id) );
+											}
 											break;
 
-										case 1:
-											id = s_renderCtx.m_renderTargets[sampler.m_idx].m_color.m_id;
+										case BGFX_SAMPLER_RENDERTARGET_COLOR:
+											GL_CHECK(glBindTexture(GL_TEXTURE_2D, s_renderCtx.m_renderTargets[sampler.m_idx].m_color.m_id) );
 											break;
 
-										case 2:
-											id = s_renderCtx.m_renderTargets[sampler.m_idx].m_depth.m_id;
+										case BGFX_SAMPLER_RENDERTARGET_DEPTH:
+											GL_CHECK(glBindTexture(GL_TEXTURE_2D, s_renderCtx.m_renderTargets[sampler.m_idx].m_depth.m_id) );
 											break;
 										}
-
-										GL_CHECK(glBindTexture(GL_TEXTURE_2D, id) );
-										//								GL_CHECK(glUniform1i(material.m_sampler[stage], stage) );
 									}
 								}
 

+ 38 - 0
src/renderer_gl.h

@@ -63,6 +63,38 @@ typedef void (*PFNGLGETTRANSLATEDSHADERSOURCEANGLEPROC)(GLuint shader, GLsizei b
 #	include <gl/GRemedyGLExtensions.h>
 #endif // BGFX_CONFIG_DEBUG_GREMEDY && (BX_PLATFORM_WINDOWS || BX_PLATFORM_LINUX)
 
+#if BX_PLATFORM_WINDOWS
+typedef PROC (APIENTRYP PFNWGLGETPROCADDRESSPROC) (LPCSTR lpszProc);
+typedef BOOL (APIENTRYP PFNWGLMAKECURRENTPROC) (HDC hDc, HGLRC newContext);
+typedef HGLRC (APIENTRYP PFNWGLCREATECONTEXTPROC) (HDC hDc);
+//
+typedef GLenum (APIENTRYP PFNGLGETERRORPROC) (void);
+typedef void (APIENTRYP PFNGLREADPIXELSPROC) (GLint x, GLint y, GLsizei width, GLsizei height, GLenum format, GLenum type, GLvoid *pixels);
+typedef void (APIENTRYP PFNGLTEXIMAGE2DPROC) (GLenum target, GLint level, GLint internalformat, GLsizei width, GLsizei height, GLint border, GLenum format, GLenum type, const GLvoid *pixels);
+typedef void (APIENTRYP PFNGLTEXPARAMETERIPROC) (GLenum target, GLenum pname, GLint param);
+typedef void (APIENTRYP PFNGLBINDTEXTUREPROC) (GLenum target, GLuint texture);
+typedef void (APIENTRYP PFNGLGENTEXTURESPROC) (GLsizei n, GLuint *textures);
+typedef void (APIENTRYP PFNGLDELETETEXTURESPROC) (GLsizei n, const GLuint *textures);
+typedef void (APIENTRYP PFNGLCOLORMASKPROC) (GLboolean red, GLboolean green, GLboolean blue, GLboolean alpha);
+typedef void (APIENTRYP PFNGLDEPTHFUNCPROC) (GLenum func);
+typedef void (APIENTRYP PFNGLDISABLEPROC) (GLenum cap);
+typedef void (APIENTRYP PFNGLVIEWPORTPROC) (GLint x, GLint y, GLsizei width, GLsizei height);
+typedef void (APIENTRYP PFNGLDRAWELEMENTSPROC) (GLenum mode, GLsizei count, GLenum type, const GLvoid *indices);
+typedef void (APIENTRYP PFNGLGETINTEGERVPROC) (GLenum pname, GLint *params);
+typedef const GLubyte * (APIENTRYP PFNGLGETSTRINGPROC) (GLenum name);
+typedef void (APIENTRYP PFNGLDRAWARRAYSPROC) (GLenum mode, GLint first, GLsizei count);
+typedef void (APIENTRYP PFNGLBLENDFUNCPROC) (GLenum sfactor, GLenum dfactor);
+typedef void (APIENTRYP PFNGLPOINTSIZEPROC) (GLfloat size);
+typedef void (APIENTRYP PFNGLCULLFACEPROC) (GLenum mode);
+typedef void (APIENTRYP PFNGLCLEARPROC) (GLbitfield mask);
+typedef void (APIENTRYP PFNGLSCISSORPROC) (GLint x, GLint y, GLsizei width, GLsizei height);
+typedef void (APIENTRYP PFNGLENABLEPROC) (GLenum cap);
+typedef void (APIENTRYP PFNGLCLEARSTENCILPROC) (GLint s);
+typedef void (APIENTRYP PFNGLDEPTHMASKPROC) (GLboolean flag);
+typedef void (APIENTRYP PFNGLCLEARDEPTHPROC) (GLdouble depth);
+typedef void (APIENTRYP PFNGLCLEARCOLORPROC) (GLfloat red, GLfloat green, GLfloat blue, GLfloat alpha);
+#endif // BX_PLATFORM_WINDOWS
+
 namespace bgfx
 {
 #	define _GL_CHECK(_call) \
@@ -104,6 +136,12 @@ namespace bgfx
 #define GREMEDY_SETMARKER(_string) _GREMEDY_SETMARKER(_string)
 #define GREMEDY_FRAMETERMINATOR() _GREMEDY_FRAMETERMINATOR()
 
+#if BX_PLATFORM_WINDOWS
+	extern PFNWGLGETPROCADDRESSPROC wglGetProcAddress;
+	extern PFNWGLMAKECURRENTPROC wglMakeCurrent;
+	extern PFNWGLCREATECONTEXTPROC wglCreateContext;
+#endif // BX_PLATFORM_WINDOWS
+
 #define GL_IMPORT(_optional, _proto, _func) extern _proto _func
 #include "glimports.h"
 #undef GL_IMPORT

+ 39 - 36
tools/ddsdump.cpp

@@ -49,56 +49,59 @@ int main(int _argc, const char* _argv[])
 		if (decompress
 		||  0 == dds.m_type)
 		{
-			uint32_t width = dds.m_width;
-			uint32_t height = dds.m_height;
-
-			for (uint32_t lod = 0, num = dds.m_numMips; lod < num; ++lod)
+			for (uint8_t side = 0, numSides = dds.m_cubeMap ? 6 : 1; side < numSides; ++side)
 			{
-				width = uint32_max(1, width);
-				height = uint32_max(1, height);
+				uint32_t width = dds.m_width;
+				uint32_t height = dds.m_height;
 
-				Mip mip;
-				if (getRawImageData(dds, lod, mem, mip) )
+				for (uint32_t lod = 0, num = dds.m_numMips; lod < num; ++lod)
 				{
-					uint32_t dstpitch = width*4;
-					uint8_t* bits = (uint8_t*)malloc(dstpitch*height);
+					width = uint32_max(1, width);
+					height = uint32_max(1, height);
 
-					if (width != mip.m_width
-					||  height != mip.m_height)
+					Mip mip;
+					if (getRawImageData(dds, side, lod, mem, mip) )
 					{
-						uint8_t* temp = (uint8_t*)realloc(NULL, mip.m_width*mip.m_height*4);
-						mip.decode(temp);
-						uint32_t srcpitch = mip.m_width*4;
+						uint32_t dstpitch = width*4;
+						uint8_t* bits = (uint8_t*)malloc(dstpitch*height);
 
-						for (uint32_t yy = 0; yy < height; ++yy)
+						if (width != mip.m_width
+						||  height != mip.m_height)
 						{
-							uint8_t* src = &temp[yy*srcpitch];
-							uint8_t* dst = &bits[yy*dstpitch];
+							uint8_t* temp = (uint8_t*)realloc(NULL, mip.m_width*mip.m_height*4);
+							mip.decode(temp);
+							uint32_t srcpitch = mip.m_width*4;
 
-							for (uint32_t xx = 0; xx < width; ++xx)
+							for (uint32_t yy = 0; yy < height; ++yy)
 							{
-								memcpy(dst, src, 4);
-								dst += 4;
-								src += 4;
+								uint8_t* src = &temp[yy*srcpitch];
+								uint8_t* dst = &bits[yy*dstpitch];
+
+								for (uint32_t xx = 0; xx < width; ++xx)
+								{
+									memcpy(dst, src, 4);
+									dst += 4;
+									src += 4;
+								}
 							}
+
+							free(temp);
+						}
+						else
+						{
+							mip.decode(bits);
 						}
 
-						free(temp);
-					}
-					else
-					{
-						mip.decode(bits);
-					}
+						char filePath[256];
+						_snprintf(filePath, sizeof(filePath), "mip%d_%d.tga", side, lod);
 
-					char filePath[256];
-					_snprintf(filePath, sizeof(filePath), "mip%d.tga", lod);
+						bgfx::saveTga(filePath, width, height, dstpitch, bits);
+						free(bits);
+					}
 
-					bgfx::saveTga(filePath, width, height, dstpitch, bits);
-					free(bits);
+					width >>= 1;
+					height >>= 1;
 				}
-
-				width >>= 1;
-				height >>= 1;
 			}
 		}
 		else
@@ -106,7 +109,7 @@ int main(int _argc, const char* _argv[])
 			for (uint32_t lod = 0, num = dds.m_numMips; lod < num; ++lod)
 			{
 				Mip mip;
-				if (getRawImageData(dds, lod, mem, mip) )
+				if (getRawImageData(dds, 0, lod, mem, mip) )
 				{
 					char filePath[256];
 					_snprintf(filePath, sizeof(filePath), "mip%d.bin", lod);