[Fix] (MG_Backend/DirectGLES): direct draw buffer mapping, fix up simple case

This commit is contained in:
2026-02-04 10:27:01 +08:00
parent 77378bbf07
commit 2088009c01
+21 -106
View File
@@ -850,116 +850,31 @@ namespace MobileGL::MG_Backend::DirectGLES {
GLenum glFBOTarget = MG_Util::ConvertFramebufferTargetToGLEnum(asTarget); GLenum glFBOTarget = MG_Util::ConvertFramebufferTargetToGLEnum(asTarget);
Bind(asTarget); Bind(asTarget);
FramebufferAttachmentType* frontendAttachmentToSync = nullptr; // connect attachments (set buffers)
GLenum* backendAttachmentToSync = nullptr; // TODO: remapping
Int frontendAttachmentToSyncCount = 0; auto& stateDrawBuffers = stateFBOObject->GetDrawBuffers();
switch (asTarget) { Bool drawBufferDirty = false;
case FramebufferTarget::Draw: { for (GLint i = 0; i < MG_State::GLState::FramebufferObject::MAX_DRAW_BUFFERS; ++i) {
auto& stateDrawBuffers = stateFBOObject->GetDrawBuffers(); auto currentBuf = MG_Util::ConvertFramebufferAttachmentTypeToGLEnum(stateDrawBuffers[i]);
if (m_backendDrawBuffers[i] != currentBuf)
// Check if still clean, skip if clean drawBufferDirty = true;
if (memcmp(m_frontendDrawBuffers, stateDrawBuffers.data(), m_backendDrawBuffers[i] = currentBuf;
FramebufferObject::MAX_DRAW_BUFFERS * sizeof(FramebufferAttachmentType)) == 0) {
break;
}
// Create mappings for draw buffers
int nBuffers = 0;
std::fill(m_frontendDrawBuffers, m_frontendDrawBuffers + FramebufferObject::MAX_DRAW_BUFFERS,
FramebufferAttachmentType::None);
std::fill(m_compactedFrontendDrawBuffers,
m_compactedFrontendDrawBuffers + FramebufferObject::MAX_DRAW_BUFFERS,
FramebufferAttachmentType::None);
std::fill(m_backendDrawBuffers, m_backendDrawBuffers + FramebufferObject::MAX_DRAW_BUFFERS, GL_NONE);
for (GLint i = 0; i < FramebufferObject::MAX_DRAW_BUFFERS; ++i) {
if (stateDrawBuffers[i] == FramebufferAttachmentType::None) {
m_frontendDrawBuffers[i] = FramebufferAttachmentType::None;
continue;
}
m_frontendDrawBuffers[i] = stateDrawBuffers[i];
// Create compacted mapping
m_backendDrawBuffers[nBuffers] = GL_COLOR_ATTACHMENT0 + nBuffers;
m_compactedFrontendDrawBuffers[nBuffers] = m_frontendDrawBuffers[i];
nBuffers++;
}
MG_External::GLES::glDrawBuffers(nBuffers, m_backendDrawBuffers);
frontendAttachmentToSync = m_compactedFrontendDrawBuffers;
backendAttachmentToSync = m_backendDrawBuffers;
frontendAttachmentToSyncCount = nBuffers;
break;
} }
case FramebufferTarget::Read: { if (drawBufferDirty)
auto frontendReadBuf = stateFBOObject->GetReadBuffer(); MG_External::GLES::glDrawBuffers(MG_State::GLState::FramebufferObject::MAX_DRAW_BUFFERS, m_backendDrawBuffers);
if (frontendReadBuf == m_frontendReadBuffer) break;
m_frontendReadBuffer = frontendReadBuf;
// For consistency, we need to find the compacted attachment index of this read buffer auto currentReadBuf = MG_Util::ConvertFramebufferAttachmentTypeToGLEnum(stateFBOObject->GetReadBuffer());
auto it = std::find(m_compactedFrontendDrawBuffers, if (m_backendReadBuffer != currentReadBuf)
m_compactedFrontendDrawBuffers + FramebufferObject::MAX_DRAW_BUFFERS, frontendReadBuf); MG_External::GLES::glReadBuffer(m_backendReadBuffer);
// TODO: what if sync ReadBuffer first then DrawBuffer? // attach texture to fbo
GLenum glBackendReadBuffer = GL_NONE; // TODO: attach according to remapped
Bool notFound = (it == m_compactedFrontendDrawBuffers + FramebufferObject::MAX_DRAW_BUFFERS); const auto& attachments = stateFBOObject->GetAllAttachmentObjects();
if (notFound) { for (SizeT i = 0; i < attachments.size(); ++i) {
MGLOG_D("%s: read buffer not found in draw buffer, use as in frontend", __func__); const auto& attachmentObject = attachments[i];
glBackendReadBuffer = MG_Util::ConvertFramebufferAttachmentTypeToGLEnum(frontendReadBuf); FramebufferAttachmentType type = static_cast<FramebufferAttachmentType>(i);
} else { GLenum glBackendAttachment = MG_Util::ConvertFramebufferAttachmentTypeToGLEnum(type);
MGLOG_D("%s: read buffer found in draw buffer, keep it consistent as in read buffers", __func__);
auto index = std::distance(m_compactedFrontendDrawBuffers, it);
glBackendReadBuffer = m_backendDrawBuffers[index];
}
if (m_backendReadBuffer == glBackendReadBuffer) break;
m_backendReadBuffer = glBackendReadBuffer;
MG_External::GLES::glReadBuffer(glBackendReadBuffer);
frontendAttachmentToSync = &m_frontendReadBuffer;
backendAttachmentToSync = &m_backendReadBuffer;
frontendAttachmentToSyncCount = 1;
break;
}
default:
MOBILEGL_ASSERT(false, "%s: Unreachable!", __func__);
return;
}
// Sync texture/buffer to attachment
const auto& attachmentObjects = stateFBOObject->GetAllAttachmentObjects();
auto& attachmentVersions = stateFBOObject->GetAllFramebufferAttachmentVersions();
for (Int i = 0; i < frontendAttachmentToSyncCount; ++i) {
auto frontendAttachment = frontendAttachmentToSync[i];
if (attachmentVersions[(SizeT)frontendAttachment] ==
m_syncedAttachmentVersions[(SizeT)frontendAttachment]) {
continue;
}
m_syncedAttachmentVersions[(SizeT)frontendAttachment] = attachmentVersions[(SizeT)frontendAttachment];
const auto& attachmentObject = stateFBOObject->GetAttachment(frontendAttachment);
if (!attachmentObject.IsValid() || attachmentObject.IsEmpty()) {
continue;
}
auto glBackendAttachment = backendAttachmentToSync[i];
SyncAttachmentObject(glFBOTarget, attachmentObject, glBackendAttachment);
}
FramebufferAttachmentType auxAtt[] = {FramebufferAttachmentType::Depth, FramebufferAttachmentType::Stencil};
for (auto& att : auxAtt) {
auto frontendAttachment = att;
if (attachmentVersions[(SizeT)frontendAttachment] ==
m_syncedAttachmentVersions[(SizeT)frontendAttachment]) {
continue;
}
m_syncedAttachmentVersions[(SizeT)frontendAttachment] = attachmentVersions[(SizeT)frontendAttachment];
const auto& attachmentObject = stateFBOObject->GetAttachment(frontendAttachment);
if (!attachmentObject.IsValid() || attachmentObject.IsEmpty()) {
continue;
}
auto glBackendAttachment = MG_Util::ConvertFramebufferAttachmentTypeToGLEnum(att);
SyncAttachmentObject(glFBOTarget, attachmentObject, glBackendAttachment); SyncAttachmentObject(glFBOTarget, attachmentObject, glBackendAttachment);
} }
} }