Ver Fonte

Added texture update.

bkaradzic há 13 anos atrás
pai
commit
b86fb4cb56
12 ficheiros alterados com 422 adições e 162 exclusões
  1. 29 0
      include/bgfx.h
  2. 85 13
      src/bgfx.cpp
  3. 60 0
      src/bgfx_p.h
  4. 0 17
      src/dds.h
  5. 2 0
      src/glimports.h
  6. 61 44
      src/renderer_d3d11.cpp
  7. 6 3
      src/renderer_d3d11.h
  8. 91 46
      src/renderer_d3d9.cpp
  9. 10 2
      src/renderer_d3d9.h
  10. 69 37
      src/renderer_gl.cpp
  11. 5 0
      src/renderer_gl.h
  12. 4 0
      src/renderer_null.cpp

+ 29 - 0
include/bgfx.h

@@ -217,6 +217,23 @@ namespace bgfx
 		};
 	};
 
+	struct TextureFormat
+	{
+		enum Enum
+		{
+			Dxt1,
+			Dxt3,
+			Dxt5,
+			Unknown,
+			L8,
+			XRGB8,
+			ARGB8,
+			ABGR16,
+
+			Count
+		};
+	};
+
 	static const uint16_t invalidHandle = 0xffff;
 
 	typedef struct { uint16_t idx; } DynamicIndexBufferHandle;
@@ -405,9 +422,21 @@ namespace bgfx
 	///
 	TextureHandle createTexture(const Memory* _mem, uint32_t _flags = BGFX_TEXTURE_NONE, uint16_t* _width = NULL, uint16_t* _height = 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);
+
+	///
+	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 createTextureCube(uint16_t _sides, uint16_t _width, uint8_t _numMips, TextureFormat::Enum _format, uint32_t _flags = BGFX_TEXTURE_NONE, const Memory* _mem = NULL);
+
 	///
 	void destroyTexture(TextureHandle _handle);
 
+	///
+	void updateTexture(TextureHandle _handle, uint8_t _mip, uint16_t _x, uint16_t _y, uint16_t _width, uint16_t _height, const Memory* _mem);
+
 	///
 	RenderTargetHandle createRenderTarget(uint16_t _width, uint16_t _height, uint32_t _flags = BGFX_RENDER_TARGET_COLOR_RGBA, uint32_t _textureFlags = BGFX_TEXTURE_U_CLAMP|BGFX_TEXTURE_V_CLAMP);
 

+ 85 - 13
src/bgfx.cpp

@@ -211,21 +211,11 @@ namespace bgfx
 
 		const Memory* mem;
 
-		mem = alloc(pitch*height+16);
-
-		StreamWrite stream(mem->data, mem->size);
-		uint32_t magic = BGFX_MAGIC;
-		stream.write(magic);
-		stream.write(width);
-		stream.write(height);
-		stream.write(bpp);
-		uint8_t numMips = 1;
-		stream.write(numMips);
-		stream.align(16);
-		uint8_t* rgba = stream.getDataPtr();
+		mem = alloc(pitch*height);
+		uint8_t* rgba = mem->data;
 		charsetFillTexture(vga8x8, rgba, 8, pitch, bpp);
 		charsetFillTexture(vga8x16, &rgba[8*pitch], 16, pitch, bpp);
-		m_texture = s_ctx.createTexture(mem, BGFX_TEXTURE_MIN_POINT|BGFX_TEXTURE_MAG_POINT|BGFX_TEXTURE_MIP_POINT, NULL, NULL);
+		m_texture = createTexture2D(2048, 24, 1, TextureFormat::L8, BGFX_TEXTURE_MIN_POINT|BGFX_TEXTURE_MAG_POINT|BGFX_TEXTURE_MIP_POINT, mem);
 
 #if BGFX_CONFIG_RENDERER_DIRECT3D9
 		mem = alloc(sizeof(vs_debugfont_dx9)+1);
@@ -943,11 +933,93 @@ namespace bgfx
 		return s_ctx.createTexture(_mem, _flags, _width, _height);
 	}
 
+	TextureHandle createTexture2D(uint16_t _width, uint16_t _height, uint8_t _numMips, TextureFormat::Enum _format, uint32_t _flags, const Memory* _mem)
+	{
+		uint32_t size = sizeof(uint32_t)+sizeof(TextureInfo);
+		const bgfx::Memory* mem = alloc(size);
+
+		StreamWrite stream(mem->data, mem->size);
+		uint32_t magic = BGFX_MAGIC;
+		stream.write(magic);
+
+		TextureInfo ti;
+		ti.m_flags = _flags;
+		ti.m_width = _width;
+		ti.m_height = _height;
+		ti.m_depth = 0;
+		ti.m_numMips = _numMips;
+		ti.m_type = uint8_t(_format);
+		ti.m_cubeMap = false;
+		ti.m_mem = _mem;
+		stream.write(ti);
+
+		return s_ctx.createTexture(mem, _flags, NULL, NULL);
+	}
+
+	TextureHandle createTexture3D(uint16_t _width, uint16_t _height, uint16_t _depth, uint8_t _numMips, TextureFormat::Enum _format, uint32_t _flags, const Memory* _mem)
+	{
+		uint32_t size = sizeof(uint32_t)+sizeof(TextureInfo);
+		const bgfx::Memory* mem = alloc(size);
+
+		StreamWrite stream(mem->data, mem->size);
+		uint32_t magic = BGFX_MAGIC;
+		stream.write(magic);
+
+		TextureInfo ti;
+		ti.m_flags = _flags;
+		ti.m_width = _width;
+		ti.m_height = _height;
+		ti.m_depth = _depth;
+		ti.m_numMips = _numMips;
+		ti.m_type = uint8_t(_format);
+		ti.m_cubeMap = false;
+		ti.m_mem = _mem;
+		stream.write(ti);
+
+		return s_ctx.createTexture(mem, _flags, NULL, NULL);
+	}
+
+	TextureHandle createTextureCube(uint16_t _sides, uint16_t _width, uint8_t _numMips, TextureFormat::Enum _format, uint32_t _flags, const Memory* _mem)
+	{
+		uint32_t size = sizeof(uint32_t)+sizeof(TextureInfo);
+		const bgfx::Memory* mem = alloc(size);
+
+		StreamWrite stream(mem->data, mem->size);
+		uint32_t magic = BGFX_MAGIC;
+		stream.write(magic);
+
+		TextureInfo ti;
+		ti.m_flags = _flags;
+		ti.m_width = _width;
+		ti.m_sides = _sides;
+		ti.m_depth = 0;
+		ti.m_numMips = _numMips;
+		ti.m_type = uint8_t(_format);
+		ti.m_cubeMap = true;
+		ti.m_mem = _mem;
+		stream.write(ti);
+
+		return s_ctx.createTexture(mem, _flags, NULL, NULL);
+	}
+
 	void destroyTexture(TextureHandle _handle)
 	{
 		s_ctx.destroyTexture(_handle);
 	}
 
+	void updateTexture(TextureHandle _handle, uint8_t _mip, uint16_t _x, uint16_t _y, uint16_t _width, uint16_t _height, const Memory* _mem)
+	{
+		if (_width == 0
+		||  _height == 0)
+		{
+			release(_mem);
+		}
+		else
+		{
+			s_ctx.updateTexture(_handle, _mip, _x, _y, _width, _height, _mem);
+		}
+	}
+
 	RenderTargetHandle createRenderTarget(uint16_t _width, uint16_t _height, uint32_t _flags, uint32_t _textureFlags)
 	{
 		return s_ctx.createRenderTarget(_width, _height, _flags, _textureFlags);

+ 60 - 0
src/bgfx_p.h

@@ -161,6 +161,22 @@ namespace bgfx
 		uint16_t m_height;
 	};
 
+	struct TextureInfo
+	{
+		uint32_t m_flags;
+		uint16_t m_width;
+		union
+		{
+			uint16_t m_height;
+			uint16_t m_sides;
+		};
+		uint16_t m_depth;
+		uint8_t m_numMips;
+		uint8_t m_type;
+		bool m_cubeMap;
+		const Memory* m_mem;
+	};
+
 	extern const uint32_t g_constantTypeSize[ConstantType::Count];
 	extern FatalFn g_fatal;
 	extern ReallocFn g_realloc;
@@ -272,9 +288,16 @@ namespace bgfx
 				m_small = _small;
 				m_width = (uint16_t)width;
 				m_height = (uint16_t)height;
+
+				uint32_t size = m_size;
 				m_size = m_width * m_height * 2;
 
 				m_mem = (uint8_t*)g_realloc(m_mem, m_size);
+
+				if (size < m_size)
+				{
+					memset(&m_mem[size], 0, m_size-size);
+				}
 			}
 		}
 
@@ -507,6 +530,7 @@ namespace bgfx
 			CreateFragmentShader,
 			CreateMaterial,
 			CreateTexture,
+			UpdateTexture,
 			CreateRenderTarget,
 			CreateUniform,
 			End,
@@ -2028,6 +2052,21 @@ namespace bgfx
 			m_submit->free(_handle);
 		}
 
+		void updateTexture(TextureHandle _handle, uint8_t _mip, uint16_t _x, uint16_t _y, uint16_t _width, uint16_t _height, const Memory* _mem)
+		{
+			CommandBuffer& cmdbuf = getCommandBuffer(CommandBuffer::UpdateTexture);
+			cmdbuf.write(_handle);
+			cmdbuf.write(_mip);
+
+			Rect rect;
+			rect.m_x = _x;
+			rect.m_y = _y;
+			rect.m_width = _width;
+			rect.m_height = _height;
+			cmdbuf.write(rect);
+			cmdbuf.write(_mem);
+		}
+
 		RenderTargetHandle createRenderTarget(uint16_t _width, uint16_t _height, uint32_t _flags, uint32_t _textureFlags)
 		{
 			RenderTargetHandle handle = { m_renderTargetHandle.alloc() };
@@ -2308,6 +2347,7 @@ namespace bgfx
 		void rendererCreateMaterial(MaterialHandle _handle, VertexShaderHandle _vsh, FragmentShaderHandle _fsh);
 		void rendererDestroyMaterial(FragmentShaderHandle _handle);
 		void rendererCreateTexture(TextureHandle _handle, Memory* _mem, uint32_t _flags);
+		void rendererUpdateTexture(TextureHandle _handle, uint8_t _mip, const Rect& _rect, const Memory* _mem);
 		void rendererDestroyTexture(TextureHandle _handle);
 		void rendererCreateRenderTarget(RenderTargetHandle _handle, uint16_t _width, uint16_t _height, uint32_t _flags, uint32_t _textureFlags);
 		void rendererDestroyRenderTarget(RenderTargetHandle _handle);
@@ -2608,6 +2648,26 @@ namespace bgfx
 					}
 					break;
 
+				case CommandBuffer::UpdateTexture:
+					{
+						TextureHandle handle;
+						_cmdbuf.read(handle);
+
+						uint8_t mip;
+						_cmdbuf.read(mip);
+
+						Rect rect;
+						_cmdbuf.read(rect);
+
+						Memory* mem;
+						_cmdbuf.read(mem);
+
+						rendererUpdateTexture(handle, mip, rect, mem);
+
+						release(mem);
+					}
+					break;
+
 				case CommandBuffer::DestroyTexture:
 					{
 						TextureHandle handle;

+ 0 - 17
src/dds.h

@@ -10,23 +10,6 @@
 
 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;

+ 2 - 0
src/glimports.h

@@ -15,6 +15,8 @@
 GL_IMPORT(false, PFNGLGETERRORPROC,                       glGetError);
 GL_IMPORT(false, PFNGLREADPIXELSPROC,                     glReadPixels);
 GL_IMPORT(false, PFNGLTEXIMAGE2DPROC,                     glTexImage2D);
+GL_IMPORT(false, PFNGLTEXSUBIMAGE2DPROC,                  glTexSubImage2D);
+GL_IMPORT(false, PFNGLPIXELSTOREI,                        glPixelStorei);
 GL_IMPORT(false, PFNGLTEXPARAMETERIPROC,                  glTexParameteri);
 GL_IMPORT(false, PFNGLBINDTEXTUREPROC,                    glBindTexture);
 GL_IMPORT(false, PFNGLGENTEXTURESPROC,                    glGenTextures);

+ 61 - 44
src/renderer_d3d11.cpp

@@ -989,7 +989,7 @@ namespace bgfx
 
 			uint64_t state = 0;
 			state |= _clear.m_flags & BGFX_CLEAR_COLOR_BIT ? BGFX_STATE_RGB_WRITE|BGFX_STATE_ALPHA_WRITE : 0;
-			state |= _clear.m_flags & BGFX_CLEAR_DEPTH_BIT ? BGFX_STATE_DEPTH_WRITE : 0;
+			state |= _clear.m_flags & BGFX_CLEAR_DEPTH_BIT ? BGFX_STATE_DEPTH_TEST_ALWAYS|BGFX_STATE_DEPTH_WRITE : 0;
 
 			s_renderCtx.setBlendState(state);
 			s_renderCtx.setDepthStencilState(state);
@@ -1327,17 +1327,14 @@ namespace bgfx
 				}
 			}
 
-			ID3D11Texture2D* texture;
-			DX_CHECK(s_renderCtx.m_device->CreateTexture2D(&desc, srd, &texture) );
+			DX_CHECK(s_renderCtx.m_device->CreateTexture2D(&desc, srd, &m_ptr) );
 
 			D3D11_SHADER_RESOURCE_VIEW_DESC srv;
 			memset(&srv, 0, sizeof(srv) );
 			srv.Format = s_textureFormat[dds.m_type].m_fmt;
 			srv.ViewDimension = D3D11_SRV_DIMENSION_TEXTURE2D;
 			srv.Texture2D.MipLevels = dds.m_numMips;
-			DX_CHECK(s_renderCtx.m_device->CreateShaderResourceView(texture, &srv, &m_ptr) );
-
-			DX_RELEASE(texture, 0);
+			DX_CHECK(s_renderCtx.m_device->CreateShaderResourceView(m_ptr, &srv, &m_srv) );
 
 			if (convert)
 			{
@@ -1361,28 +1358,15 @@ namespace bgfx
 
 			if (BGFX_MAGIC == magic)
 			{
-				uint16_t width;
-				stream.read(width);
-
-				uint16_t height;
-				stream.read(height);
-
-				uint8_t bpp;
-				stream.read(bpp);
-
-				uint8_t numMips;
-				stream.read(numMips);
-
-				stream.align(16);
-
-				DXGI_FORMAT fmt = 1 == bpp ? DXGI_FORMAT_R8_UNORM : DXGI_FORMAT_R8G8B8A8_UNORM;
+				TextureInfo ti;
+				stream.read(ti);
 
 				D3D11_TEXTURE2D_DESC desc;
-				desc.Width = width;
-				desc.Height = height;
-				desc.MipLevels = numMips;
+				desc.Width = ti.m_width;
+				desc.Height = ti.m_height;
+				desc.MipLevels = ti.m_numMips;
 				desc.ArraySize = 1;
-				desc.Format = fmt;
+				desc.Format = s_textureFormat[ti.m_type].m_fmt;
 				desc.SampleDesc.Count = 1;
 				desc.SampleDesc.Quality = 0;
 				desc.Usage = D3D11_USAGE_DEFAULT;
@@ -1390,33 +1374,47 @@ namespace bgfx
 				desc.CPUAccessFlags = 0;
 				desc.MiscFlags = 0;
 
-				D3D11_SUBRESOURCE_DATA* srd = (D3D11_SUBRESOURCE_DATA*)alloca(numMips*sizeof(D3D11_SUBRESOURCE_DATA) );
-
-				for (uint8_t mip = 0; mip < numMips; ++mip)
+				if (NULL != ti.m_mem)
 				{
-					width = uint32_max(width, 1);
-					height = uint32_max(height, 1);
+					D3D11_SUBRESOURCE_DATA* srd = (D3D11_SUBRESOURCE_DATA*)alloca(ti.m_numMips*sizeof(D3D11_SUBRESOURCE_DATA) );
+					uint32_t bpp = s_textureFormat[ti.m_type].m_bpp;
+					uint8_t* data = ti.m_mem->data;
 
-					srd[mip].pSysMem = stream.getDataPtr();
-					srd[mip].SysMemPitch = width*bpp;
-					srd[mip].SysMemSlicePitch = 0;
+					for (uint8_t side = 0, numSides = ti.m_cubeMap ? 6 : 1; side < numSides; ++side)
+					{
+						uint32_t width = ti.m_width;
+						uint32_t height = ti.m_height;
 
-					stream.skip(width*height*bpp);
+						for (uint32_t lod = 0, num = ti.m_numMips; lod < num; ++lod)
+						{
+							width = uint32_max(width, 1);
+							height = uint32_max(height, 1);
 
-					width >>= 1;
-					height >>= 1;
-				}
+							srd[lod].pSysMem = data;
+							srd[lod].SysMemPitch = width*bpp;
+							srd[lod].SysMemSlicePitch = 0;
+
+							data += width*height*bpp;
+
+							width >>= 1;
+							height >>= 1;
+						}
+					}
 
-				ID3D11Texture2D* texture;
-				DX_CHECK(s_renderCtx.m_device->CreateTexture2D(&desc, srd, &texture) );
+					DX_CHECK(s_renderCtx.m_device->CreateTexture2D(&desc, srd, &m_ptr) );
+
+					release(ti.m_mem);
+				}
+				else
+				{
+					DX_CHECK(s_renderCtx.m_device->CreateTexture2D(&desc, NULL, &m_ptr) );
+				}
 
 				D3D11_SHADER_RESOURCE_VIEW_DESC srv;
 				memset(&srv, 0, sizeof(srv) );
 				srv.ViewDimension = D3D11_SRV_DIMENSION_TEXTURE2D;
-				srv.Texture2D.MipLevels = numMips;
-				DX_CHECK(s_renderCtx.m_device->CreateShaderResourceView(texture, &srv, &m_ptr) );
-
-				DX_RELEASE(texture, 0);
+				srv.Texture2D.MipLevels = ti.m_numMips;
+				DX_CHECK(s_renderCtx.m_device->CreateShaderResourceView(m_ptr, &srv, &m_srv) );
 			}
 			else
 			{
@@ -1427,10 +1425,24 @@ namespace bgfx
 
 	void Texture::commit(uint8_t _stage)
 	{
-		s_renderCtx.m_textureStage.m_srv[_stage] = m_ptr;
+		s_renderCtx.m_textureStage.m_srv[_stage] = m_srv;
 		s_renderCtx.m_textureStage.m_sampler[_stage] = m_sampler;
 	}
 
+	void Texture::update(uint8_t _mip, const Rect& _rect, const Memory* _mem)
+	{
+		ID3D11DeviceContext* deviceCtx = s_renderCtx.m_deviceCtx;
+
+		D3D11_BOX box;
+		box.left = _rect.m_x;
+		box.top = _rect.m_y;
+		box.right = box.left + _rect.m_width;
+		box.bottom = box.top + _rect.m_height;
+		box.front = 0;
+		box.back = 1;
+		deviceCtx->UpdateSubresource(m_ptr, 0, &box, _mem->data, _rect.m_width, 0); 
+	}
+
 	void RenderTarget::create(uint16_t _width, uint16_t _height, uint32_t _flags, uint32_t _textureFlags)
 	{
 		m_width = _width;
@@ -1636,6 +1648,11 @@ namespace bgfx
 		s_renderCtx.m_textures[_handle.idx].create(_mem, _flags);
 	}
 
+	void Context::rendererUpdateTexture(TextureHandle _handle, uint8_t _mip, const Rect& _rect, const Memory* _mem)
+	{
+		s_renderCtx.m_textures[_handle.idx].update(_mip, _rect, _mem);
+	}
+
 	void Context::rendererDestroyTexture(TextureHandle _handle)
 	{
 		s_renderCtx.m_textures[_handle.idx].destroy();

+ 6 - 3
src/renderer_d3d11.h

@@ -214,7 +214,7 @@ namespace bgfx
 		};
 
 		Texture()
-			: m_ptr(NULL)
+			: m_srv(NULL)
 		{
 		}
 
@@ -226,12 +226,15 @@ namespace bgfx
 
 		void destroy()
 		{
-			DX_RELEASE(m_ptr, 0);
+			DX_RELEASE(m_srv, 0);
+			DX_RELEASE(m_ptr, 1);
 		}
 
 		void commit(uint8_t _stage);
+		void update(uint8_t _mip, const Rect& _rect, const Memory* _mem);
 
-		ID3D11ShaderResourceView* m_ptr;
+		ID3D11Texture2D* m_ptr;
+		ID3D11ShaderResourceView* m_srv;
 		ID3D11SamplerState* m_sampler;
 		Enum m_type;
 		bool m_srgb;

+ 91 - 46
src/renderer_d3d9.cpp

@@ -1083,11 +1083,11 @@ namespace bgfx
 			, 0
 			, _fmt
 			, D3DPOOL_MANAGED
-			, (IDirect3DTexture9**)&m_ptr
+			, &m_texture2d
 			, NULL
 			) );
 
-		BGFX_FATAL(NULL != m_ptr, Fatal::D3D9_UnableToCreateTexture, "Failed to create texture (size: %dx%d, mips: %d, fmt: 0x%08x)."
+		BGFX_FATAL(NULL != m_texture2d, Fatal::D3D9_UnableToCreateTexture, "Failed to create texture (size: %dx%d, mips: %d, fmt: 0x%08x)."
 			, _width
 			, _height
 			, _numMips
@@ -1106,11 +1106,11 @@ namespace bgfx
 			, 0
 			, _fmt
 			, D3DPOOL_MANAGED
-			, (IDirect3DVolumeTexture9**)&m_ptr
+			, &m_texture3d
 			, NULL
 			) );
 
-		BGFX_FATAL(NULL != m_ptr, Fatal::D3D9_UnableToCreateTexture, "Failed to create volume texture (size: %dx%dx%d, mips: %d, fmt: 0x%08x)."
+		BGFX_FATAL(NULL != m_texture3d, Fatal::D3D9_UnableToCreateTexture, "Failed to create volume texture (size: %dx%dx%d, mips: %d, fmt: 0x%08x)."
 			, _width
 			, _height
 			, _depth
@@ -1128,36 +1128,48 @@ namespace bgfx
 			, 0
 			, _fmt
 			, D3DPOOL_MANAGED
-			, (IDirect3DCubeTexture9**)&m_ptr
+			, &m_textureCube
 			, NULL
 			) );
 
-		BGFX_FATAL(NULL != m_ptr, Fatal::D3D9_UnableToCreateTexture, "Failed to create cube texture (edge: %d, mips: %d, fmt: 0x%08x)."
+		BGFX_FATAL(NULL != m_textureCube, 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)
+	uint8_t* Texture::lock(uint8_t _side, uint8_t _lod, uint32_t& _pitch, uint32_t& _slicePitch, const Rect* _rect)
 	{
 		switch (m_type)
 		{
 		case Texture2D:
 			{
-				IDirect3DTexture9* texture = (IDirect3DTexture9*)m_ptr;
-				D3DLOCKED_RECT rect;
-				DX_CHECK(texture->LockRect(_lod, &rect, NULL, 0) );
-				_pitch = rect.Pitch;
+				D3DLOCKED_RECT lockedRect;
+
+				if (NULL != _rect)
+				{
+					RECT rect;
+					rect.left = _rect->m_x;
+					rect.top = _rect->m_y;
+					rect.right = rect.left + _rect->m_width;
+					rect.bottom = rect.top + _rect->m_height;
+					DX_CHECK(m_texture2d->LockRect(_lod, &lockedRect, &rect, 0) );
+				}
+				else
+				{
+					DX_CHECK(m_texture2d->LockRect(_lod, &lockedRect, NULL, 0) );
+				}
+
+				_pitch = lockedRect.Pitch;
 				_slicePitch = 0;
-				return (uint8_t*)rect.pBits;
+				return (uint8_t*)lockedRect.pBits;
 			}
 
 		case Texture3D:
 			{
-				IDirect3DVolumeTexture9* texture = (IDirect3DVolumeTexture9*)m_ptr;
 				D3DLOCKED_BOX box;
-				DX_CHECK(texture->LockBox(_lod, &box, NULL, 0) );
+				DX_CHECK(m_texture3d->LockBox(_lod, &box, NULL, 0) );
 				_pitch = box.RowPitch;
 				_slicePitch = box.SlicePitch;
 				return (uint8_t*)box.pBits;
@@ -1165,9 +1177,8 @@ namespace bgfx
 
 		case TextureCube:
 			{
-				IDirect3DCubeTexture9* texture = (IDirect3DCubeTexture9*)m_ptr;
 				D3DLOCKED_RECT rect;
-				DX_CHECK(texture->LockRect(D3DCUBEMAP_FACES(_side), _lod, &rect, NULL, 0) );
+				DX_CHECK(m_textureCube->LockRect(D3DCUBEMAP_FACES(_side), _lod, &rect, NULL, 0) );
 				_pitch = rect.Pitch;
 				_slicePitch = 0;
 				return (uint8_t*)rect.pBits;
@@ -1184,22 +1195,19 @@ namespace bgfx
 		{
 		case Texture2D:
 			{
-				IDirect3DTexture9* texture = (IDirect3DTexture9*)m_ptr;
-				DX_CHECK(texture->UnlockRect(_lod) );
+				DX_CHECK(m_texture2d->UnlockRect(_lod) );
 			}
 			return;
 
 		case Texture3D:
 			{
-				IDirect3DVolumeTexture9* texture = (IDirect3DVolumeTexture9*)m_ptr;
-				DX_CHECK(texture->UnlockBox(_lod) );
+				DX_CHECK(m_texture3d->UnlockBox(_lod) );
 			}
 			return;
 
 		case TextureCube:
 			{
-				IDirect3DCubeTexture9* texture = (IDirect3DCubeTexture9*)m_ptr;
-				DX_CHECK(texture->UnlockRect(D3DCUBEMAP_FACES(_side), _lod) );
+				DX_CHECK(m_textureCube->UnlockRect(D3DCUBEMAP_FACES(_side), _lod) );
 			}
 			return;
 		}
@@ -1322,37 +1330,51 @@ namespace bgfx
 
 			if (BGFX_MAGIC == magic)
 			{
-				uint16_t width;
-				stream.read(width);
+				TextureInfo ti;
+				stream.read(ti);
 
-				uint16_t height;
-				stream.read(height);
-
-				uint8_t bpp;
-				stream.read(bpp);
-
-				uint8_t numMips;
-				stream.read(numMips);
+				if (ti.m_cubeMap)
+				{
+					createCubeTexture(ti.m_width, ti.m_numMips, s_textureFormat[ti.m_type].m_fmt);
+				}
+				else if (ti.m_depth > 1)
+				{
+					createVolumeTexture(ti.m_width, ti.m_height, ti.m_depth, ti.m_numMips, s_textureFormat[ti.m_type].m_fmt);
+				}
+				else
+				{
+					createTexture(ti.m_width, ti.m_height, ti.m_numMips, s_textureFormat[ti.m_type].m_fmt);
+				}
 
-				stream.align(16);
+				if (NULL != ti.m_mem)
+				{
+					uint32_t bpp = s_textureFormat[ti.m_type].m_bpp;
+					uint8_t* data = ti.m_mem->data;
 
-				D3DFORMAT fmt = 1 == bpp ? D3DFMT_L8 : D3DFMT_A8R8G8B8;
+					for (uint8_t side = 0, numSides = ti.m_cubeMap ? 6 : 1; side < numSides; ++side)
+					{
+						uint32_t width = ti.m_width;
+						uint32_t height = ti.m_height;
 
-				createTexture(width, height, numMips, fmt);
+						for (uint32_t lod = 0, num = ti.m_numMips; lod < num; ++lod)
+						{
+							width = uint32_max(width, 1);
+							height = uint32_max(height, 1);
 
-				for (uint8_t mip = 0; mip < numMips; ++mip)
-				{
-					width = uint32_max(width, 1);
-					height = uint32_max(height, 1);
+							uint32_t pitch;
+							uint32_t slicePitch;
+							uint8_t* dst = lock(side, lod, pitch, slicePitch);
+							uint32_t len = width*height*bpp;
+							memcpy(dst, data, len);
+							data += len;
+							unlock(side, lod);
 
-					uint32_t pitch;
-					uint32_t slicePitch;
-					uint8_t* dst = lock(0, mip, pitch, slicePitch);
-					stream.read(dst, width*height*bpp);
-					unlock(0, mip);
+							width >>= 1;
+							height >>= 1;
+						}
+					}
 
-					width >>= 1;
-					height >>= 1;
+					release(ti.m_mem);
 				}
 			}
 			else
@@ -1362,6 +1384,24 @@ namespace bgfx
 		}
 	}
 
+	void Texture::update(uint8_t _mip, const Rect& _rect, const Memory* _mem)
+	{
+		uint32_t pitch;
+		uint32_t slicePitch;
+		uint8_t* bits = lock(0, _mip, pitch, slicePitch, &_rect);
+
+		uint32_t srcpitch = _rect.m_width;
+		uint32_t dstpitch = pitch;
+		for (uint32_t yy = 0, height = _rect.m_height; yy < height; ++yy)
+		{
+			uint8_t* src = &_mem->data[yy*srcpitch];
+			uint8_t* dst = &bits[yy*dstpitch];
+			memcpy(dst, src, srcpitch);
+		}
+
+		unlock(0, _mip);
+	}
+
 	void Texture::commit(uint8_t _stage)
 	{
 		DX_CHECK(s_renderCtx.m_device->SetSamplerState(_stage, D3DSAMP_MINFILTER, m_minFilter) );
@@ -1783,6 +1823,11 @@ namespace bgfx
 		s_renderCtx.m_textures[_handle.idx].create(_mem, _flags);
 	}
 
+	void Context::rendererUpdateTexture(TextureHandle _handle, uint8_t _mip, const Rect& _rect, const Memory* _mem)
+	{
+		s_renderCtx.m_textures[_handle.idx].update(_mip, _rect, _mem);
+	}
+
 	void Context::rendererDestroyTexture(TextureHandle _handle)
 	{
 		s_renderCtx.m_textures[_handle.idx].destroy();

+ 10 - 2
src/renderer_d3d9.h

@@ -305,7 +305,7 @@ namespace bgfx
 		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);
+		uint8_t* lock(uint8_t _side, uint8_t _lod, uint32_t& _pitch, uint32_t& _slicePitch, const Rect* _rect = NULL);
 		void unlock(uint8_t _side, uint8_t _lod);
 
 		void create(const Memory* _mem, uint32_t _flags);
@@ -315,9 +315,17 @@ namespace bgfx
 			DX_RELEASE(m_ptr, 0);
 		}
 
+		void update(uint8_t _mip, const Rect& _rect, const Memory* _mem);
 		void commit(uint8_t _stage);
 	
-		IDirect3DBaseTexture9* m_ptr;
+		union
+		{
+			IDirect3DBaseTexture9* m_ptr;
+			IDirect3DTexture9* m_texture2d;
+			IDirect3DVolumeTexture9* m_texture3d;
+			IDirect3DCubeTexture9* m_textureCube;
+		};
+
 		D3DTEXTUREFILTERTYPE m_minFilter;
 		D3DTEXTUREFILTERTYPE m_magFilter;
 		D3DTEXTUREFILTERTYPE m_mipFilter;

+ 69 - 37
src/renderer_gl.cpp

@@ -724,7 +724,7 @@ namespace bgfx
 	struct TextureFormatInfo
 	{
 		GLenum m_internalFmt;
-		GLenum m_format;
+		GLenum m_fmt;
 		GLenum m_type;
 		uint8_t m_bpp;
 	};
@@ -1145,7 +1145,7 @@ namespace bgfx
 
 			const TextureFormatInfo& tfi = s_textureFormat[dds.m_type];
 			GLenum internalFmt = tfi.m_internalFmt;
-			GLenum fmt = tfi.m_format;
+			m_fmt = tfi.m_fmt;
 
 			GLenum target = m_target;
 			if (dds.m_cubeMap)
@@ -1162,13 +1162,13 @@ namespace bgfx
 				||  decompress)
 				{
 					internalFmt = s_extension[Extension::EXT_texture_format_BGRA8888].m_supported ? GL_BGRA_EXT : GL_RGBA;
-					fmt = internalFmt;
+					m_fmt = internalFmt;
 				}
 
-				GLenum type = tfi.m_type;
+				m_type = tfi.m_type;
 				if (decompress)
 				{
-					type = GL_UNSIGNED_BYTE;
+					m_type = GL_UNSIGNED_BYTE;
 				}
 
 				uint8_t* bits = (uint8_t*)g_realloc(NULL, dds.m_width*dds.m_height*tfi.m_bpp);
@@ -1217,8 +1217,8 @@ namespace bgfx
 									, height
 									, depth
 									, 0
-									, fmt
-									, type
+									, m_fmt
+									, m_type
 									, bits
 									) );
 							}
@@ -1231,8 +1231,8 @@ namespace bgfx
 									, width
 									, height
 									, 0
-									, fmt
-									, type
+									, m_fmt
+									, m_type
 									, bits
 									) );
 							}
@@ -1314,40 +1314,51 @@ namespace bgfx
 
 			if (BGFX_MAGIC == magic)
 			{
-				uint16_t width;
-				stream.read(width);
+				TextureInfo ti;
+				stream.read(ti);
 
-				uint16_t height;
-				stream.read(height);
+				const TextureFormatInfo& tfi = s_textureFormat[ti.m_type];
+				GLenum internalFmt = tfi.m_internalFmt;
+				m_fmt = tfi.m_fmt;
+				m_type = tfi.m_type;
 
-				uint8_t bpp;
-				stream.read(bpp);
+				uint32_t bpp = s_textureFormat[ti.m_type].m_bpp;
+				uint8_t* data = NULL != ti.m_mem ? ti.m_mem->data : NULL;
 
-				stream.read(numMips);
+				for (uint8_t side = 0, numSides = ti.m_cubeMap ? 6 : 1; side < numSides; ++side)
+				{
+					uint32_t width = ti.m_width;
+					uint32_t height = ti.m_height;
+
+					for (uint32_t lod = 0, num = ti.m_numMips; lod < num; ++lod)
+					{
+						width = uint32_max(width, 1);
+						height = uint32_max(height, 1);
+
+						GL_CHECK(glTexImage2D(m_target
+							, lod
+							, internalFmt
+							, width
+							, height
+							, 0
+							, m_fmt
+							, m_type
+							, data
+							) );
 
-				stream.align(16);
+						if (NULL != data)
+						{
+							data += width*height*bpp;
+						}
+
+						width >>= 1;
+						height >>= 1;
+					}
+				}
 
-				for (uint8_t mip = 0; mip < numMips; ++mip)
+				if (NULL != ti.m_mem)
 				{
-					width = uint32_max(width, 1);
-					height = uint32_max(height, 1);
-
-					const uint8_t* data = stream.getDataPtr();
-					stream.skip(width*height*bpp);
-
-					GL_CHECK(glTexImage2D(m_target
-						, mip
-						, 1 == bpp ? GL_LUMINANCE : GL_RGBA
-						, width
-						, height
-						, 0
-						, 1 == bpp ? GL_LUMINANCE : GL_RGBA
-						, GL_UNSIGNED_BYTE
-						, data
-						) );
-
-					width >>= 1;
-					height >>= 1;
+					release(ti.m_mem);
 				}
 			}
 			else
@@ -1440,6 +1451,22 @@ namespace bgfx
 		}
 	}
 
+	void Texture::update(uint8_t _mip, const Rect& _rect, const Memory* _mem)
+	{
+		GL_CHECK(glBindTexture(m_target, m_id) );
+		GL_CHECK(glPixelStorei(GL_UNPACK_ALIGNMENT, 1) );
+		GL_CHECK(glTexSubImage2D(m_target
+			, _mip
+			, _rect.m_x
+			, _rect.m_y
+			, _rect.m_width
+			, _rect.m_height
+			, m_fmt
+			, m_type
+			, _mem->data
+			) );
+	}
+
 	void RenderTarget::create(uint16_t _width, uint16_t _height, uint32_t _flags, uint32_t _textureFlags)
 	{
 		BX_TRACE("Create render target %dx%d 0x%02x", _width, _height, _flags);
@@ -1877,6 +1904,11 @@ namespace bgfx
 		s_renderCtx.m_textures[_handle.idx].create(_mem, _flags);
 	}
 
+	void Context::rendererUpdateTexture(TextureHandle _handle, uint8_t _mip, const Rect& _rect, const Memory* _mem)
+	{
+		s_renderCtx.m_textures[_handle.idx].update(_mip, _rect, _mem);
+	}
+
 	void Context::rendererDestroyTexture(TextureHandle _handle)
 	{
 		s_renderCtx.m_textures[_handle.idx].destroy();

+ 5 - 0
src/renderer_gl.h

@@ -129,7 +129,9 @@ typedef BOOL (APIENTRYP PFNWGLDELETECONTEXTPROC) (HGLRC hglrc);
 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 PFNGLTEXSUBIMAGE2DPROC) (GLenum target, GLint level, GLint xoffset, GLint yoffset, GLsizei width, GLsizei height, GLenum format, GLenum type, const GLvoid *pixels);
 typedef void (APIENTRYP PFNGLTEXPARAMETERIPROC) (GLenum target, GLenum pname, GLint param);
+typedef void (APIENTRYP PFNGLPIXELSTOREI) (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);
@@ -308,9 +310,12 @@ namespace bgfx
 		void createColor(uint32_t _width, uint32_t _height, GLenum _min, GLenum _mag);
 		void createDepth(uint32_t _width, uint32_t _height);
 		void destroy();
+		void update(uint8_t _mip, const Rect& _rect, const Memory* _mem);
 
 		GLuint m_id;
 		GLenum m_target;
+		GLenum m_fmt;
+		GLenum m_type;
 	};
 
 	struct Shader

+ 4 - 0
src/renderer_null.cpp

@@ -109,6 +109,10 @@ namespace bgfx
 	{
 	}
 
+	void Context::rendererUpdateTexture(TextureHandle /*_handle*/, uint8_t /*_mip*/, const Rect& /*_rect*/, const Memory* /*_mem*/)
+	{
+	}
+
 	void Context::rendererDestroyTexture(TextureHandle /*_handle*/)
 	{
 	}