diff --git a/MobileGL/MG_Backend/DirectGLES/DirectGLES.cpp b/MobileGL/MG_Backend/DirectGLES/DirectGLES.cpp index 9693e6f8..c70ade8e 100644 --- a/MobileGL/MG_Backend/DirectGLES/DirectGLES.cpp +++ b/MobileGL/MG_Backend/DirectGLES/DirectGLES.cpp @@ -998,44 +998,26 @@ namespace MobileGL::MG_Backend::DirectGLES { RenderStateImpl::SyncRenderState(); BindCurrentFBO(FramebufferTarget::Draw); - auto backendFBOIt = FramebufferImpl::g_backendFramebufferObjects.find( - MG_State::pGLContext->GetFramebufferBindingSlot(FramebufferTarget::Draw).GetBoundObject()); - if (backendFBOIt == FramebufferImpl::g_backendFramebufferObjects.end()) { - MGLOG_E("No backend FBO found for current draw FBO, cannot clear buffer."); - return; - } - auto backendFBO = backendFBOIt->second; +// auto backendFBOIt = FramebufferImpl::g_backendFramebufferObjects.find( +// MG_State::pGLContext->GetFramebufferBindingSlot(FramebufferTarget::Draw).GetBoundObject()); +// if (backendFBOIt == FramebufferImpl::g_backendFramebufferObjects.end()) { +// MGLOG_E("No backend FBO found for current draw FBO, cannot clear buffer."); +// return; +// } +// auto backendFBO = backendFBOIt->second; GLint realDrawbuffer = drawbuffer; if (buffer == GL_COLOR) { - auto& stateDrawBuffers = backendFBOIt->first->GetDrawBuffers(); +// auto& stateDrawBuffers = backendFBOIt->first->GetDrawBuffers(); if (drawbuffer < 0 || drawbuffer >= MG_State::GLState::FramebufferObject::MAX_DRAW_BUFFERS) { MGLOG_E("Invalid drawbuffer index: %d", drawbuffer); return; } - FramebufferAttachmentType attachmentType = stateDrawBuffers[drawbuffer]; - - if (attachmentType == FramebufferAttachmentType::None) { - MGLOG_D("Drawbuffer %d has no attachment, skipping clear", drawbuffer); - return; - } - - Bool found = false; - for (int i = 0; i < MG_State::GLState::FramebufferObject::MAX_DRAW_BUFFERS; i++) { - if (backendFBO->GetCompactedAttachmentTypeAtDrawBufferIndex(i) == attachmentType) { - realDrawbuffer = i; - found = true; - break; - } - } - - if (!found) { - MGLOG_E("Failed to find backend drawbuffer for attachment type: %d", static_cast(attachmentType)); - return; - } + // since `drawbuffer` indicates an index into draw buffer array, + // using GL value directly is OK. } else if (buffer == GL_DEPTH || buffer == GL_STENCIL) { if (drawbuffer != 0) { MGLOG_W("Depth/stencil clear buffer index must be 0, got %d. Using 0.", drawbuffer); @@ -1051,44 +1033,44 @@ namespace MobileGL::MG_Backend::DirectGLES { RenderStateImpl::SyncRenderState(); BindCurrentFBO(FramebufferTarget::Draw); - auto backendFBOIt = FramebufferImpl::g_backendFramebufferObjects.find( - MG_State::pGLContext->GetFramebufferBindingSlot(FramebufferTarget::Draw).GetBoundObject()); - if (backendFBOIt == FramebufferImpl::g_backendFramebufferObjects.end()) { - MGLOG_E("No backend FBO found for current draw FBO, cannot clear buffer."); - return; - } - auto backendFBO = backendFBOIt->second; +// auto backendFBOIt = FramebufferImpl::g_backendFramebufferObjects.find( +// MG_State::pGLContext->GetFramebufferBindingSlot(FramebufferTarget::Draw).GetBoundObject()); +// if (backendFBOIt == FramebufferImpl::g_backendFramebufferObjects.end()) { +// MGLOG_E("No backend FBO found for current draw FBO, cannot clear buffer."); +// return; +// } +// auto backendFBO = backendFBOIt->second; GLint realDrawbuffer = drawbuffer; if (buffer == GL_COLOR) { - auto& stateDrawBuffers = backendFBOIt->first->GetDrawBuffers(); +// auto& stateDrawBuffers = backendFBOIt->first->GetDrawBuffers(); if (drawbuffer < 0 || drawbuffer >= MG_State::GLState::FramebufferObject::MAX_DRAW_BUFFERS) { MGLOG_E("Invalid drawbuffer index: %d", drawbuffer); return; } - FramebufferAttachmentType attachmentType = stateDrawBuffers[drawbuffer]; +// FramebufferAttachmentType attachmentType = stateDrawBuffers[drawbuffer]; - if (attachmentType == FramebufferAttachmentType::None) { - MGLOG_D("Drawbuffer %d has no attachment, skipping clear", drawbuffer); - return; - } +// if (attachmentType == FramebufferAttachmentType::None) { +// MGLOG_D("Drawbuffer %d has no attachment, skipping clear", drawbuffer); +// return; +// } - Bool found = false; - for (int i = 0; i < MG_State::GLState::FramebufferObject::MAX_DRAW_BUFFERS; i++) { - if (backendFBO->GetCompactedAttachmentTypeAtDrawBufferIndex(i) == attachmentType) { - realDrawbuffer = i; - found = true; - break; - } - } +// Bool found = false; +// for (int i = 0; i < MG_State::GLState::FramebufferObject::MAX_DRAW_BUFFERS; i++) { +// if (backendFBO->GetCompactedAttachmentTypeAtDrawBufferIndex(i) == attachmentType) { +// realDrawbuffer = i; +// found = true; +// break; +// } +// } - if (!found) { - MGLOG_E("Failed to find backend drawbuffer for attachment type: %d", static_cast(attachmentType)); - return; - } +// if (!found) { +// MGLOG_E("Failed to find backend drawbuffer for attachment type: %d", static_cast(attachmentType)); +// return; +// } } else if (buffer == GL_STENCIL) { if (drawbuffer != 0) { MGLOG_W("Stencil clear buffer index must be 0, got %d. Using 0.", drawbuffer); @@ -1105,44 +1087,44 @@ namespace MobileGL::MG_Backend::DirectGLES { RenderStateImpl::SyncRenderState(); BindCurrentFBO(FramebufferTarget::Draw); - auto backendFBOIt = FramebufferImpl::g_backendFramebufferObjects.find( - MG_State::pGLContext->GetFramebufferBindingSlot(FramebufferTarget::Draw).GetBoundObject()); - if (backendFBOIt == FramebufferImpl::g_backendFramebufferObjects.end()) { - MGLOG_E("No backend FBO found for current draw FBO, cannot clear buffer."); - return; - } - auto backendFBO = backendFBOIt->second; +// auto backendFBOIt = FramebufferImpl::g_backendFramebufferObjects.find( +// MG_State::pGLContext->GetFramebufferBindingSlot(FramebufferTarget::Draw).GetBoundObject()); +// if (backendFBOIt == FramebufferImpl::g_backendFramebufferObjects.end()) { +// MGLOG_E("No backend FBO found for current draw FBO, cannot clear buffer."); +// return; +// } +// auto backendFBO = backendFBOIt->second; GLint realDrawbuffer = drawbuffer; if (buffer == GL_COLOR) { - auto& stateDrawBuffers = backendFBOIt->first->GetDrawBuffers(); +// auto& stateDrawBuffers = backendFBOIt->first->GetDrawBuffers(); if (drawbuffer < 0 || drawbuffer >= MG_State::GLState::FramebufferObject::MAX_DRAW_BUFFERS) { MGLOG_E("Invalid drawbuffer index: %d", drawbuffer); return; } - FramebufferAttachmentType attachmentType = stateDrawBuffers[drawbuffer]; +// FramebufferAttachmentType attachmentType = stateDrawBuffers[drawbuffer]; - if (attachmentType == FramebufferAttachmentType::None) { - MGLOG_D("Drawbuffer %d has no attachment, skipping clear", drawbuffer); - return; - } +// if (attachmentType == FramebufferAttachmentType::None) { +// MGLOG_D("Drawbuffer %d has no attachment, skipping clear", drawbuffer); +// return; +// } - Bool found = false; - for (int i = 0; i < MG_State::GLState::FramebufferObject::MAX_DRAW_BUFFERS; i++) { - if (backendFBO->GetCompactedAttachmentTypeAtDrawBufferIndex(i) == attachmentType) { - realDrawbuffer = i; - found = true; - break; - } - } +// Bool found = false; +// for (int i = 0; i < MG_State::GLState::FramebufferObject::MAX_DRAW_BUFFERS; i++) { +// if (backendFBO->GetCompactedAttachmentTypeAtDrawBufferIndex(i) == attachmentType) { +// realDrawbuffer = i; +// found = true; +// break; +// } +// } - if (!found) { - MGLOG_E("Failed to find backend drawbuffer for attachment type: %d", static_cast(attachmentType)); - return; - } +// if (!found) { +// MGLOG_E("Failed to find backend drawbuffer for attachment type: %d", static_cast(attachmentType)); +// return; +// } } else { MGLOG_E("ClearBufferuiv can only be used with GL_COLOR buffer, got %s", MG_Util::ConvertGLEnumToString(buffer).c_str()); diff --git a/MobileGL/MG_Backend/DirectGLES/Managers.cpp b/MobileGL/MG_Backend/DirectGLES/Managers.cpp index db099558..a5202a91 100644 --- a/MobileGL/MG_Backend/DirectGLES/Managers.cpp +++ b/MobileGL/MG_Backend/DirectGLES/Managers.cpp @@ -850,24 +850,47 @@ namespace MobileGL::MG_Backend::DirectGLES { GLenum glFBOTarget = MG_Util::ConvertFramebufferTargetToGLEnum(asTarget); Bind(asTarget); - // connect attachments (set buffers) - // TODO: remapping + // -------------------- Connect attachments (set buffers) ----------------------- + // 1. Remap draw buffers auto& stateDrawBuffers = stateFBOObject->GetDrawBuffers(); - Bool drawBufferDirty = false; - for (GLint i = 0; i < MG_State::GLState::FramebufferObject::MAX_DRAW_BUFFERS; ++i) { - auto currentBuf = MG_Util::ConvertFramebufferAttachmentTypeToGLEnum(stateDrawBuffers[i]); - if (m_backendDrawBuffers[i] != currentBuf) - drawBufferDirty = true; - m_backendDrawBuffers[i] = currentBuf; + Bool drawBufferClean = false; + if (memcmp(m_frontendDrawBuffers, stateDrawBuffers.data(), + FramebufferObject::MAX_DRAW_BUFFERS * sizeof(FramebufferAttachmentType)) == 0) { + drawBufferClean = true; } - if (drawBufferDirty) - MG_External::GLES::glDrawBuffers(MG_State::GLState::FramebufferObject::MAX_DRAW_BUFFERS, m_backendDrawBuffers); - auto currentReadBuf = MG_Util::ConvertFramebufferAttachmentTypeToGLEnum(stateFBOObject->GetReadBuffer()); - if (m_backendReadBuffer != currentReadBuf) - MG_External::GLES::glReadBuffer(m_backendReadBuffer); + if (!drawBufferClean) { + memcpy(m_frontendDrawBuffers, stateDrawBuffers.data(), + FramebufferObject::MAX_DRAW_BUFFERS * sizeof(FramebufferAttachmentType)); + std::fill(m_backendDrawBuffers, m_backendDrawBuffers + FramebufferObject::MAX_DRAW_BUFFERS, GL_NONE); + int nEffectiveBuffers = 0; + for (GLint i = 0; i < FramebufferObject::MAX_DRAW_BUFFERS; ++i) { + if (stateDrawBuffers[i] == FramebufferAttachmentType::None) { + m_backendDrawBuffers[i] = GL_NONE; + continue; + } - // attach texture to fbo + // Create compacted mapping + m_backendDrawBuffers[i] = GL_COLOR_ATTACHMENT0 + i; + nEffectiveBuffers = i + 1; + } + MG_External::GLES::glDrawBuffers(nEffectiveBuffers, m_backendDrawBuffers); + } + + // 2. Remap read buffer + auto frontendReadBuf = stateFBOObject->GetReadBuffer(); + if (frontendReadBuf != m_frontendReadBuffer) { + m_frontendReadBuffer = frontendReadBuf; + + GLenum glBackendReadBuffer = GetBackendAttachmentType(frontendReadBuf); + + if (m_backendReadBuffer != glBackendReadBuffer) { + m_backendReadBuffer = glBackendReadBuffer; + MG_External::GLES::glReadBuffer(glBackendReadBuffer); + } + } + + // -------------------- Attach texture to backend FBO ----------------------- // TODO: attach according to remapped const auto& attachments = stateFBOObject->GetAllAttachmentObjects(); const auto& attachmentVersions = stateFBOObject->GetAllFramebufferAttachmentVersions(); @@ -885,8 +908,20 @@ namespace MobileGL::MG_Backend::DirectGLES { } } - FramebufferAttachmentType BackendFramebufferObject::GetCompactedAttachmentTypeAtDrawBufferIndex(Int index) { - return m_compactedFrontendDrawBuffers[index]; + GLenum BackendFramebufferObject::GetBackendAttachmentType(FramebufferAttachmentType frontendAtt) const { + GLenum glBackendReadBuffer = GL_NONE; + auto it = std::find(m_frontendDrawBuffers, + m_frontendDrawBuffers + FramebufferObject::MAX_DRAW_BUFFERS, frontendAtt); + Bool notFound = (it == m_frontendDrawBuffers + FramebufferObject::MAX_DRAW_BUFFERS); + if (notFound) { + MGLOG_D("%s: frontendAtt not found in draw buffer (probably not remapped), just use the same as frontend", __func__); + glBackendReadBuffer = MG_Util::ConvertFramebufferAttachmentTypeToGLEnum(frontendAtt); + } else { + MGLOG_D("%s: frontendAtt found in draw buffer, keep it consistent as in read buffers", __func__); + auto index = std::distance(m_frontendDrawBuffers, it); + glBackendReadBuffer = m_backendDrawBuffers[index]; + } + return glBackendReadBuffer; } UnorderedMap, SharedPtr> diff --git a/MobileGL/MG_Backend/DirectGLES/Managers.h b/MobileGL/MG_Backend/DirectGLES/Managers.h index b84c953b..45185474 100644 --- a/MobileGL/MG_Backend/DirectGLES/Managers.h +++ b/MobileGL/MG_Backend/DirectGLES/Managers.h @@ -133,8 +133,8 @@ namespace MobileGL::MG_Backend::DirectGLES { bool SyncAttachmentObject(GLenum glFBOTarget, const MG_State::GLState::FramebufferAttachmentObject& attachmentObject, GLenum glBackendAttachment); - FramebufferAttachmentType GetCompactedAttachmentTypeAtDrawBufferIndex(Int index); - +// FramebufferAttachmentType GetCompactedAttachmentTypeAtDrawBufferIndex(Int index); + GLenum GetBackendAttachmentType(FramebufferAttachmentType frontendAtt) const; private: Uint m_backendFBOId = 0; @@ -146,17 +146,9 @@ namespace MobileGL::MG_Backend::DirectGLES { */ FramebufferAttachmentType m_frontendDrawBuffers[MG_State::GLState::FramebufferObject::MAX_DRAW_BUFFERS] = { FramebufferAttachmentType::None}; - /* this will save buffers in its compacted GL form, - not consecutive is not allowed - i.e. it could be like [COLOR_ATTACHMENT0, COLOR_ATTACHMENT5, COLOR_ATTACHMENT4] - (no GL_NONE among those) - */ - FramebufferAttachmentType - m_compactedFrontendDrawBuffers[MG_State::GLState::FramebufferObject::MAX_DRAW_BUFFERS] = { - FramebufferAttachmentType::None}; /* this will save buffers in stricter ES rules reversion, absence or not consecutive are not allowed, according to ES spec - i.e. it could be like [COLOR_ATTACHMENT0, COLOR_ATTACHMENT1, NONE, NONE, ...] + i.e. it could be like [COLOR_ATTACHMENT0, COLOR_ATTACHMENT1, NONE, COLOR_ATTACHMENT3, ...] this array could be provided as data directly to ES `glDrawBuffers` function */ GLenum m_backendDrawBuffers[MG_State::GLState::FramebufferObject::MAX_DRAW_BUFFERS] = {GL_NONE};