mirror of
https://github.com/MobileGL-Dev/MobileGL
synced 2026-09-08 20:28:32 +09:00
[Feat] (Diligent, MG_Impl): wire GetTexImage/GetTextureImage RGBA8 readback
- Copy texture to staging and map rows for GL_RGBA/GL_UNSIGNED_BYTE - Wire both GLFunctionsTable entries; 13 Diligent tests pass
This commit is contained in:
+5
-2
@@ -152,6 +152,7 @@ Verified locally on Turnip Adreno 750:
|
||||
- `ClearBufferfv` / `ClearBufferiv` / `ClearBufferuiv`
|
||||
- `BlitFramebuffer` (same-size color copy between current read/draw FBOs)
|
||||
- `CopyTexImage2D` / `CopyTexSubImage2D` (whole-color copy fallback)
|
||||
- `GetTexImage` / `GetTextureImage` (RGBA8 readback)
|
||||
- `ReadPixels` from default and user color attachments
|
||||
- Primitive expansion:
|
||||
- `GL_TRIANGLE_FAN` expanded to triangle list
|
||||
@@ -211,7 +212,7 @@ Notes:
|
||||
- Global UBO (default-block `glUniform*`) and named application UBO blocks (through `glBindBufferBase`/`glUniformBlockBinding`) now upload and bind; SSBOs are still not fed from frontend buffer bindings.
|
||||
- No swapchain / EGL window surface presentation yet; `Present()` only flushes.
|
||||
- No transform feedback / queries / sync / readback of non-color resources.
|
||||
- Draw range, multi-draw, instanced-draw wrappers, clear-buffer, blit, read-pixels and CopyTexImage* are now wired; indirect draws, GetTexImage and buffer subdata paths still remain.
|
||||
- Draw range, multi-draw, instanced-draw wrappers, clear-buffer, blit, read-pixels, CopyTexImage* and GetTexImage/GetTextureImage are now wired; indirect draws and buffer subdata paths still remain.
|
||||
- A last-PSO cache now avoids recreating the pipeline when program/render-state/topology/VAO layout is unchanged; texture/UBO resources are still rebound dynamically per draw.
|
||||
- The `GLFunctionsTable` is only partially populated.
|
||||
|
||||
@@ -243,7 +244,9 @@ Notes:
|
||||
- [x] `MultiDraw*`
|
||||
- [x] `BlitFramebuffer` (same-size color copy)
|
||||
- [x] `ReadPixels` from non-default framebuffer
|
||||
- [~] `CopyTexImage*` wired as whole-color copy; `GetTexImage` / indirect draws remain
|
||||
- [x] `CopyTexImage*` wired as whole-color copy
|
||||
- [x] `GetTexImage` / `GetTextureImage` (RGBA8)
|
||||
- [ ] Indirect draws
|
||||
|
||||
6. **Expand local test suite**
|
||||
- [x] Scissor test
|
||||
|
||||
@@ -278,6 +278,32 @@ namespace MobileGL::MG_Backend::DiligentBackend {
|
||||
}
|
||||
}
|
||||
|
||||
void GetTexImage(GLenum target, GLint level, GLenum format, GLenum type, GLvoid* pixels) {
|
||||
auto* renderer = GetActiveRenderer();
|
||||
if (renderer == nullptr || MG_State::pGLContext == nullptr || target != GL_TEXTURE_2D ||
|
||||
format != GL_RGBA || type != GL_UNSIGNED_BYTE || pixels == nullptr) {
|
||||
return;
|
||||
}
|
||||
auto& unit = MG_State::pGLContext->GetTextureUnitObject(MG_State::pGLContext->GetActiveTextureUnit());
|
||||
auto texture = unit.GetBindingSlot(TextureTarget::Texture2D).GetBoundObject();
|
||||
if (texture) {
|
||||
renderer->ReadTextureImage(*texture, static_cast<Uint32>(level), pixels);
|
||||
}
|
||||
}
|
||||
|
||||
void GetTextureImage(const SharedPtr<MG_State::GLState::ITextureObject>& texture,
|
||||
TextureUploadTarget uploadTarget, GLint level, GLenum format, GLenum type,
|
||||
GLsizei bufSize, GLvoid* pixels) {
|
||||
(void)uploadTarget;
|
||||
(void)bufSize;
|
||||
auto* renderer = GetActiveRenderer();
|
||||
if (renderer == nullptr || !texture || format != GL_RGBA || type != GL_UNSIGNED_BYTE ||
|
||||
pixels == nullptr) {
|
||||
return;
|
||||
}
|
||||
renderer->ReadTextureImage(*texture, static_cast<Uint32>(level), pixels);
|
||||
}
|
||||
|
||||
void Present() {
|
||||
auto* renderer = GetActiveRenderer();
|
||||
if (renderer != nullptr) {
|
||||
@@ -384,6 +410,8 @@ namespace MobileGL::MG_Backend::DiligentBackend {
|
||||
m_functions.GL.BlitFramebuffer = BlitFramebuffer;
|
||||
m_functions.GL.CopyTexImage2D = CopyTexImage2D;
|
||||
m_functions.GL.CopyTexSubImage2D = CopyTexSubImage2D;
|
||||
m_functions.GL.GetTexImage = GetTexImage;
|
||||
m_functions.GL.GetTextureImage = GetTextureImage;
|
||||
m_functions.GL.ReadPixels = ReadPixels;
|
||||
m_functions.Present = Present;
|
||||
|
||||
|
||||
@@ -1741,6 +1741,68 @@ void main()
|
||||
m_pContext->CopyTexture(copyAttribs);
|
||||
}
|
||||
|
||||
Bool DiligentRenderer::ReadTextureImage(MG_State::GLState::ITextureObject& texture, Uint32 level,
|
||||
void* pixels) {
|
||||
if (!m_initialized || !m_pContext || pixels == nullptr) {
|
||||
return false;
|
||||
}
|
||||
if (SyncTexture(texture) == nullptr) {
|
||||
return false;
|
||||
}
|
||||
auto it = m_textureCache.find(texture.GetLifetimeId());
|
||||
if (it == m_textureCache.end() || !it->second.Texture) {
|
||||
return false;
|
||||
}
|
||||
auto& resource = it->second;
|
||||
const auto& srcDesc = resource.Texture->GetDesc();
|
||||
if (srcDesc.Format != ::Diligent::TEX_FORMAT_RGBA8_UNORM &&
|
||||
srcDesc.Format != ::Diligent::TEX_FORMAT_RGBA8_UNORM_SRGB) {
|
||||
return false;
|
||||
}
|
||||
|
||||
::Diligent::TextureDesc stagingDesc;
|
||||
stagingDesc.Name = "MobileGL Diligent texture image staging";
|
||||
stagingDesc.Type = ::Diligent::RESOURCE_DIM_TEX_2D;
|
||||
stagingDesc.Format = srcDesc.Format;
|
||||
stagingDesc.Width = srcDesc.Width;
|
||||
stagingDesc.Height = srcDesc.Height;
|
||||
stagingDesc.MipLevels = 1;
|
||||
stagingDesc.Usage = ::Diligent::USAGE_STAGING;
|
||||
stagingDesc.CPUAccessFlags = ::Diligent::CPU_ACCESS_READ;
|
||||
|
||||
::Diligent::RefCntAutoPtr<::Diligent::ITexture> pStaging;
|
||||
m_pDevice->CreateTexture(stagingDesc, nullptr, &pStaging);
|
||||
if (!pStaging) {
|
||||
return false;
|
||||
}
|
||||
|
||||
::Diligent::CopyTextureAttribs copyAttribs(
|
||||
resource.Texture, ::Diligent::RESOURCE_STATE_TRANSITION_MODE_TRANSITION,
|
||||
pStaging, ::Diligent::RESOURCE_STATE_TRANSITION_MODE_TRANSITION);
|
||||
copyAttribs.SrcMipLevel = level;
|
||||
copyAttribs.DstMipLevel = 0;
|
||||
m_pContext->CopyTexture(copyAttribs);
|
||||
m_pContext->WaitForIdle();
|
||||
|
||||
::Diligent::MappedTextureSubresource mapped;
|
||||
m_pContext->MapTextureSubresource(pStaging, 0, 0, ::Diligent::MAP_READ,
|
||||
::Diligent::MAP_FLAG_DO_NOT_WAIT, nullptr, mapped);
|
||||
if (mapped.pData == nullptr) {
|
||||
return false;
|
||||
}
|
||||
|
||||
const Uint32 width = srcDesc.Width >> level;
|
||||
const Uint32 height = srcDesc.Height >> level;
|
||||
Uint8* dst = static_cast<Uint8*>(pixels);
|
||||
for (Uint32 row = 0; row < height; ++row) {
|
||||
std::memcpy(dst + row * width * 4,
|
||||
static_cast<const Uint8*>(mapped.pData) + row * mapped.Stride,
|
||||
width * 4);
|
||||
}
|
||||
m_pContext->UnmapTextureSubresource(pStaging, 0, 0);
|
||||
return true;
|
||||
}
|
||||
|
||||
void DiligentRenderer::Present() {
|
||||
// Offscreen renderer: nothing to present yet.
|
||||
if (m_pContext) {
|
||||
|
||||
@@ -65,6 +65,7 @@ namespace MobileGL::MG_Backend::DiligentBackend {
|
||||
GLint dstX0, GLint dstY0, GLint dstX1, GLint dstY1,
|
||||
GLbitfield mask, GLenum filter);
|
||||
void CopyReadFramebufferToTexture(MG_State::GLState::ITextureObject& dst);
|
||||
Bool ReadTextureImage(MG_State::GLState::ITextureObject& texture, Uint32 level, void* pixels);
|
||||
void Present();
|
||||
|
||||
::Diligent::IRenderDevice* GetDevice() const { return m_pDevice; }
|
||||
|
||||
Reference in New Issue
Block a user