diff --git a/include/bgfx/bgfx.h b/include/bgfx/bgfx.h index c2c7cc8aa..6a7cb04d8 100644 --- a/include/bgfx/bgfx.h +++ b/include/bgfx/bgfx.h @@ -1822,7 +1822,7 @@ namespace bgfx /// @attention Availability depends on: `BGFX_CAPS_TEXTURE_READ_BACK`. /// @attention C99 equivalent is `bgfx_read_texture`. /// - uint32_t readTexture(TextureHandle _handle, void* _data); + uint32_t readTexture(TextureHandle _handle, void* _data, uint8_t _mip = 0); /// Read back texture content. /// diff --git a/src/bgfx.cpp b/src/bgfx.cpp index 812380c42..7b94a3520 100644 --- a/src/bgfx.cpp +++ b/src/bgfx.cpp @@ -2234,7 +2234,10 @@ namespace bgfx void* data; _cmdbuf.read(data); - m_renderCtx->readTexture(handle, data); + uint8_t mip; + _cmdbuf.read(mip); + + m_renderCtx->readTexture(handle, data,mip); } break; @@ -3203,12 +3206,12 @@ error: } } - uint32_t readTexture(TextureHandle _handle, void* _data) + uint32_t readTexture(TextureHandle _handle, void* _data, uint8_t _mip) { BGFX_CHECK_MAIN_THREAD(); BX_CHECK(NULL != _data, "_data can't be NULL"); BGFX_CHECK_CAPS(BGFX_CAPS_TEXTURE_READ_BACK, "Texture read-back is not supported!"); - return s_ctx->readTexture(_handle, _data); + return s_ctx->readTexture(_handle, _data, _mip); } uint32_t readTexture(FrameBufferHandle _handle, uint8_t _attachment, void* _data) diff --git a/src/bgfx_p.h b/src/bgfx_p.h index a5f918f67..4295b1add 100644 --- a/src/bgfx_p.h +++ b/src/bgfx_p.h @@ -2110,7 +2110,7 @@ namespace bgfx virtual void updateTextureBegin(TextureHandle _handle, uint8_t _side, uint8_t _mip) = 0; virtual void updateTexture(TextureHandle _handle, uint8_t _side, uint8_t _mip, const Rect& _rect, uint16_t _z, uint16_t _depth, uint16_t _pitch, const Memory* _mem) = 0; virtual void updateTextureEnd() = 0; - virtual void readTexture(TextureHandle _handle, void* _data) = 0; + virtual void readTexture(TextureHandle _handle, void* _data, uint8_t _mip) = 0; virtual void resizeTexture(TextureHandle _handle, uint16_t _width, uint16_t _height, uint8_t _numMips) = 0; virtual void overrideInternal(TextureHandle _handle, uintptr_t _ptr) = 0; virtual uintptr_t getInternal(TextureHandle _handle) = 0; @@ -3197,11 +3197,12 @@ namespace bgfx textureDecRef(_handle); } - BGFX_API_FUNC(uint32_t readTexture(TextureHandle _handle, void* _data) ) + BGFX_API_FUNC(uint32_t readTexture(TextureHandle _handle, void* _data, uint8_t _mip) ) { CommandBuffer& cmdbuf = getCommandBuffer(CommandBuffer::ReadTexture); cmdbuf.write(_handle); cmdbuf.write(_data); + cmdbuf.write(_mip); return m_frames + 2; } @@ -3211,7 +3212,7 @@ namespace bgfx BX_CHECK(!ref.m_window, "Can't sample window frame buffer."); TextureHandle textureHandle = ref.un.m_th[_attachment]; BX_CHECK(isValid(textureHandle), "Frame buffer texture %d is invalid.", _attachment); - return readTexture(textureHandle, _data); + return readTexture(textureHandle, _data,0); } void resizeTexture(TextureHandle _handle, uint16_t _width, uint16_t _height, uint8_t _numMips) diff --git a/src/renderer_d3d11.cpp b/src/renderer_d3d11.cpp index c76fdda2c..98e7a9caa 100644 --- a/src/renderer_d3d11.cpp +++ b/src/renderer_d3d11.cpp @@ -1840,22 +1840,25 @@ BX_PRAGMA_DIAGNOSTIC_POP(); { } - void readTexture(TextureHandle _handle, void* _data) BX_OVERRIDE + void readTexture(TextureHandle _handle, void* _data, uint8_t _mip) BX_OVERRIDE { const TextureD3D11& texture = m_textures[_handle.idx]; D3D11_MAPPED_SUBRESOURCE mapped; - DX_CHECK(m_deviceCtx->Map(texture.m_ptr, 0, D3D11_MAP_READ, 0, &mapped) ); + BX_CHECK(_mipMap(texture.m_ptr, _mip, D3D11_MAP_READ, 0, &mapped) ); - uint8_t* src = (uint8_t*)mapped.pData; - uint32_t srcPitch = mapped.RowPitch; + uint32_t srcWidth = texture.m_width>>_mip; + uint32_t srcHeight = texture.m_height>>_mip; + uint8_t* src = (uint8_t*)mapped.pData; + uint32_t srcPitch = mapped.RowPitch; const uint8_t bpp = getBitsPerPixel(TextureFormat::Enum(texture.m_textureFormat) ); uint8_t* dst = (uint8_t*)_data; - uint32_t dstPitch = texture.m_width*bpp/8; + uint32_t dstPitch = srcWidth*bpp/8; uint32_t pitch = bx::uint32_min(srcPitch, dstPitch); - for (uint32_t yy = 0, height = texture.m_height; yy < height; ++yy) + for (uint32_t yy = 0, height = srcHeight; yy < height; ++yy) { memcpy(dst, src, pitch); diff --git a/src/renderer_d3d12.cpp b/src/renderer_d3d12.cpp index e1cc17e13..01d86879f 100644 --- a/src/renderer_d3d12.cpp +++ b/src/renderer_d3d12.cpp @@ -1401,7 +1401,7 @@ namespace bgfx { namespace d3d12 { } - void readTexture(TextureHandle _handle, void* _data, uint8_t _mip) BX_OVERRIDE + void readTexture(TextureHandle _handle, void* _data, uint8_t _mip ) BX_OVERRIDE { _mip; const TextureD3D12& texture = m_textures[_handle.idx]; diff --git a/src/renderer_d3d9.cpp b/src/renderer_d3d9.cpp index 529f9a6b0..abe7847f6 100644 --- a/src/renderer_d3d9.cpp +++ b/src/renderer_d3d9.cpp @@ -987,27 +987,30 @@ namespace bgfx { namespace d3d9 m_updateTexture = NULL; } - void readTexture(TextureHandle _handle, void* _data) BX_OVERRIDE + void readTexture(TextureHandle _handle, void* _data, uint8_t _mip) BX_OVERRIDE { TextureD3D9& texture = m_textures[_handle.idx]; + BX_CHECK( _mipLockRect(0 + DX_CHECK(texture.m_texture2d->LockRect(_mip , &lockedRect , NULL , D3DLOCK_NO_DIRTY_UPDATE|D3DLOCK_NOSYSLOCK|D3DLOCK_READONLY ) ); - uint32_t srcPitch = lockedRect.Pitch; - uint8_t* src = (uint8_t*)lockedRect.pBits; + uint32_t srcWidth = texture.m_width>>_mip; + uint32_t srcHeight = texture.m_height>>_mip; + uint32_t srcPitch = lockedRect.Pitch; + uint8_t* src = (uint8_t*)lockedRect.pBits; const uint8_t bpp = getBitsPerPixel(TextureFormat::Enum(texture.m_textureFormat) ); uint8_t* dst = (uint8_t*)_data; - uint32_t dstPitch = texture.m_width*bpp/8; + uint32_t dstPitch = srcWidth*bpp/8; uint32_t pitch = bx::uint32_min(srcPitch, dstPitch); - for (uint32_t yy = 0, height = texture.m_height; yy < height; ++yy) + for (uint32_t yy = 0, height = srcHeight; yy < height; ++yy) { memcpy(dst, src, pitch); diff --git a/src/renderer_gl.cpp b/src/renderer_gl.cpp index b13398941..1b4b6e09e 100644 --- a/src/renderer_gl.cpp +++ b/src/renderer_gl.cpp @@ -2370,10 +2370,11 @@ namespace bgfx { namespace gl { } - void readTexture(TextureHandle _handle, void* _data) BX_OVERRIDE + void readTexture(TextureHandle _handle, void* _data, uint8_t _mip) BX_OVERRIDE { if (m_readBackSupported) { + _mip; const TextureGL& texture = m_textures[_handle.idx]; const bool compressed = isCompressed(TextureFormat::Enum(texture.m_textureFormat) );