diff --git a/include/bgfx.h b/include/bgfx.h index 63f70f96..d5e206c0 100644 --- a/include/bgfx.h +++ b/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); diff --git a/src/bgfx.cpp b/src/bgfx.cpp index 5d8c6804..580e024b 100644 --- a/src/bgfx.cpp +++ b/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); diff --git a/src/bgfx_p.h b/src/bgfx_p.h index 9e6236ad..a8ad2948 100644 --- a/src/bgfx_p.h +++ b/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; diff --git a/src/dds.h b/src/dds.h index adc9748f..9a47a386 100644 --- a/src/dds.h +++ b/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; diff --git a/src/glimports.h b/src/glimports.h index d1ca30c4..a2fd2912 100644 --- a/src/glimports.h +++ b/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); diff --git a/src/renderer_d3d11.cpp b/src/renderer_d3d11.cpp index 1354c7ee..d415968a 100644 --- a/src/renderer_d3d11.cpp +++ b/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; + } + } + + 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) ); } - - ID3D11Texture2D* texture; - DX_CHECK(s_renderCtx.m_device->CreateTexture2D(&desc, srd, &texture) ); 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(); diff --git a/src/renderer_d3d11.h b/src/renderer_d3d11.h index c85b4d56..8ff07f15 100644 --- a/src/renderer_d3d11.h +++ b/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; diff --git a/src/renderer_d3d9.cpp b/src/renderer_d3d9.cpp index 79fcf972..3657d254 100644 --- a/src/renderer_d3d9.cpp +++ b/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); - - stream.align(16); - - D3DFORMAT fmt = 1 == bpp ? D3DFMT_L8 : D3DFMT_A8R8G8B8; - - createTexture(width, height, numMips, fmt); - - for (uint8_t mip = 0; mip < numMips; ++mip) + if (ti.m_cubeMap) { - width = uint32_max(width, 1); - height = uint32_max(height, 1); + 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); + } - uint32_t pitch; - uint32_t slicePitch; - uint8_t* dst = lock(0, mip, pitch, slicePitch); - stream.read(dst, width*height*bpp); - unlock(0, mip); + if (NULL != ti.m_mem) + { + uint32_t bpp = s_textureFormat[ti.m_type].m_bpp; + uint8_t* data = ti.m_mem->data; - width >>= 1; - height >>= 1; + 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); + + 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); + + 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(); diff --git a/src/renderer_d3d9.h b/src/renderer_d3d9.h index 48b15f3c..7904fb5a 100644 --- a/src/renderer_d3d9.h +++ b/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; diff --git a/src/renderer_gl.cpp b/src/renderer_gl.cpp index 555bc7b3..e739b0af 100644 --- a/src/renderer_gl.cpp +++ b/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); - - stream.align(16); - - for (uint8_t mip = 0; mip < numMips; ++mip) + for (uint8_t side = 0, numSides = ti.m_cubeMap ? 6 : 1; side < numSides; ++side) { - width = uint32_max(width, 1); - height = uint32_max(height, 1); + uint32_t width = ti.m_width; + uint32_t height = ti.m_height; - const uint8_t* data = stream.getDataPtr(); - 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); - 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 - ) ); + GL_CHECK(glTexImage2D(m_target + , lod + , internalFmt + , width + , height + , 0 + , m_fmt + , m_type + , data + ) ); - width >>= 1; - height >>= 1; + if (NULL != data) + { + data += width*height*bpp; + } + + width >>= 1; + height >>= 1; + } + } + + if (NULL != ti.m_mem) + { + 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(); diff --git a/src/renderer_gl.h b/src/renderer_gl.h index ec740b93..d93e62b0 100644 --- a/src/renderer_gl.h +++ b/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 diff --git a/src/renderer_null.cpp b/src/renderer_null.cpp index 5ff6c0d3..9b3042a9 100644 --- a/src/renderer_null.cpp +++ b/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*/) { }