From d6b54f8e3012ca985913c1f2e45495502f084011 Mon Sep 17 00:00:00 2001 From: BZLZHH Date: Thu, 2 Oct 2025 21:27:33 +0800 Subject: [PATCH] [Feat] (MG_State/FramebufferState): Implement FramebufferAttachment, FramebufferObject and FramebufferState. --- CMakeLists.txt | 2 + MobileGL/MG_State/GLState/Core.cpp | 29 +++++ MobileGL/MG_State/GLState/Core.h | 13 ++ .../FramebufferState/FramebufferObject.cpp | 113 ++++++++++++++++++ .../FramebufferState/FramebufferObject.h | 105 ++++++++++++++++ .../FramebufferState/FramebufferState.cpp | 62 ++++++++++ .../FramebufferState/FramebufferState.h | 29 +++++ 7 files changed, 353 insertions(+) create mode 100644 MobileGL/MG_State/GLState/FramebufferState/FramebufferObject.cpp create mode 100644 MobileGL/MG_State/GLState/FramebufferState/FramebufferObject.h create mode 100644 MobileGL/MG_State/GLState/FramebufferState/FramebufferState.cpp create mode 100644 MobileGL/MG_State/GLState/FramebufferState/FramebufferState.h diff --git a/CMakeLists.txt b/CMakeLists.txt index 8fa42e53..6ddf6bc1 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -81,6 +81,8 @@ set(SOURCE_FILES MobileGL/MG_State/GLState/ProgramState/ShaderObject.cpp MobileGL/MG_State/GLState/ProgramState/ProgramState.cpp MobileGL/MG_State/GLState/RenderState/RenderState.cpp + MobileGL/MG_State/GLState/FramebufferState/FramebufferObject.cpp + MobileGL/MG_State/GLState/FramebufferState/FramebufferState.cpp ) add_library(${CMAKE_PROJECT_NAME} SHARED diff --git a/MobileGL/MG_State/GLState/Core.cpp b/MobileGL/MG_State/GLState/Core.cpp index 82f14231..3cf82ed3 100644 --- a/MobileGL/MG_State/GLState/Core.cpp +++ b/MobileGL/MG_State/GLState/Core.cpp @@ -289,6 +289,35 @@ namespace MobileGL { return m_renderState.IsCullFaceEnabled(); } + // Framebuffer + Vector GLContext::GenFramebufferNames(Uint number) { + return m_framebufferState.GenerateNames(number); + } + + SharedPtr GLContext::GetFramebufferObject(Uint index) { + return m_framebufferState.GetFramebufferObject(index); + } + + BindingSlot& GLContext::GetFramebufferBindingSlot(FramebufferTarget target) { + return m_framebufferState.GetBindingSlot(target); + } + + SharedPtr GLContext::CreateFramebufferObject(Uint index) { + return m_framebufferState.CreateFramebufferObject(index); + } + + void GLContext::MarkFramebufferObjectForDeletion(Uint index) { + m_framebufferState.MarkFramebufferObjectForDeletion(index); + } + + Bool GLContext::ValidateFramebufferName(Uint index) const { + return m_framebufferState.ValidateName(index); + } + + Bool GLContext::ValidateFramebufferObject(Uint index) const { + return m_framebufferState.ValidateFramebufferObject(index); + } + } // namespace GLState GLState::GLContext* pGLContext; diff --git a/MobileGL/MG_State/GLState/Core.h b/MobileGL/MG_State/GLState/Core.h index 3edf8163..b526686d 100644 --- a/MobileGL/MG_State/GLState/Core.h +++ b/MobileGL/MG_State/GLState/Core.h @@ -5,6 +5,7 @@ #include "BufferState/BufferState.h" #include "ProgramState/ProgramState.h" #include "TextureState/TextureState.h" +#include "FramebufferState/FramebufferState.h" #include "VertexArrayState/VertexArrayState.h" #include "MG_State/GLState/RenderState/RenderState.h" @@ -92,6 +93,15 @@ namespace MobileGL { void SetCullFaceEnabled(Bool enabled); Bool IsCullFaceEnabled() const; + // Framebuffer + Vector GenFramebufferNames(Uint number); + SharedPtr GetFramebufferObject(Uint index); + BindingSlot& GetFramebufferBindingSlot(FramebufferTarget target); + SharedPtr CreateFramebufferObject(Uint index); + void MarkFramebufferObjectForDeletion(Uint index); + Bool ValidateFramebufferName(Uint index) const; + Bool ValidateFramebufferObject(Uint index) const; + private: // Error ErrorState m_errorState; @@ -110,6 +120,9 @@ namespace MobileGL { // RenderState RenderState m_renderState; + + // Framebuffer + FramebufferState m_framebufferState; }; } // namespace GLState diff --git a/MobileGL/MG_State/GLState/FramebufferState/FramebufferObject.cpp b/MobileGL/MG_State/GLState/FramebufferState/FramebufferObject.cpp new file mode 100644 index 00000000..f1aed1ee --- /dev/null +++ b/MobileGL/MG_State/GLState/FramebufferState/FramebufferObject.cpp @@ -0,0 +1,113 @@ +#include "FramebufferObject.h" + +namespace MobileGL { + namespace MG_State { + namespace GLState { + // FramebufferAttachment + FramebufferAttachment::FramebufferAttachment(SharedPtr texture, + Int level) + : m_texture(texture), m_textureLevel(level) {} + FramebufferAttachment::FramebufferAttachment(SharedPtr renderbuffer) + : m_renderbuffer(renderbuffer) {} + FramebufferAttachment::FramebufferAttachment(std::nullptr_t) + : m_texture(nullptr), m_renderbuffer(nullptr) {} + + Bool FramebufferAttachment::IsTexture() const { + return m_texture != nullptr; + } + + Bool FramebufferAttachment::IsRenderbuffer() const { + return false; + } + + Bool FramebufferAttachment::IsEmpty() { + return m_texture == nullptr && m_renderbuffer == nullptr; + } + + SharedPtr FramebufferAttachment::GetTexture() const { + return m_texture; + } + + SharedPtr FramebufferAttachment::GetRenderbuffer() const { + return m_renderbuffer; + } + + Int FramebufferAttachment::GetTextureLevel() const { + return m_textureLevel; + } + + Bool FramebufferAttachment::IsComplete() const { + if (IsTexture()) { + return m_texture->IsComplete(); + } else if (IsRenderbuffer()) { + // TODO + } + return false; + } + + IntVec3 FramebufferAttachment::GetSize() const { + if (IsTexture()) { + return m_texture->GetMipmap(m_textureLevel).size; + } else if (IsRenderbuffer()) { + // TODO + } + return {0, 0}; + } + + // FramebufferObject + void FramebufferObject::AttachTexture(FramebufferAttachmentType type, SharedPtr texture, + int level) { + m_attachments[static_cast(type)] = FramebufferAttachment(std::move(texture), level); + m_drawBuffersDirty = true; + } + + void FramebufferObject::AttachRenderbuffer(FramebufferAttachmentType type, + std::shared_ptr renderbuffer) { + m_attachments[static_cast(type)] = FramebufferAttachment(renderbuffer); + m_drawBuffersDirty = true; + } + + void FramebufferObject::Detach(FramebufferAttachmentType type) { + m_attachments[static_cast(type)] = FramebufferAttachment(nullptr); + m_drawBuffersDirty = true; + } + + const FramebufferAttachment& FramebufferObject::GetAttachment(FramebufferAttachmentType type) const { + return m_attachments[static_cast(type)]; + } + + Bool FramebufferObject::CheckCompleteness() const { + if (m_attachments.empty()) { + return false; + } + + int width = -1, height = -1; + for (const auto& attachment : m_attachments) { + auto attachmentSize = attachment.GetSize(); + int w = attachmentSize.x(); + int h = attachmentSize.y(); + if (width == -1) { + width = w; + height = h; + } else if (width != w || height != h) { + return false; + } + if (!attachment.IsComplete()) { + return false; + } + } + return true; + } + + void FramebufferObject::SetDrawBuffers(const std::vector& buffers) { + m_drawBuffers = buffers; + m_drawBuffersDirty = true; + } + + const Vector& FramebufferObject::GetDrawBuffers() const { + return m_drawBuffers; + } + + } // namespace GLState + } // namespace MG_State +} // namespace MobileGL diff --git a/MobileGL/MG_State/GLState/FramebufferState/FramebufferObject.h b/MobileGL/MG_State/GLState/FramebufferState/FramebufferObject.h new file mode 100644 index 00000000..d2670c64 --- /dev/null +++ b/MobileGL/MG_State/GLState/FramebufferState/FramebufferObject.h @@ -0,0 +1,105 @@ +#pragma once +#include "MG_Util/Types.h" +#include +#include + +namespace MobileGL { + enum class FramebufferTarget { + Draw, + Read, + FramebufferTargetCount, + Unknown = -1 + }; + + enum class FramebufferAttachmentType { + Color0, + Color1, + Color2, + Color3, + Color4, + Color5, + Color6, + Color7, + Color8, + Color9, + Color10, + Color11, + Color12, + Color13, + Color14, + Color15, + Color16, + Color17, + Color18, + Color19, + Color20, + Color21, + Color22, + Color23, + Color24, + Color25, + Color26, + Color27, + Color28, + Color29, + Color30, + Color31, + Depth, + Stencil, + DepthStencil, + FramebufferAttachmentTypeCount, + Unknown = -1 + }; + + namespace MG_State { + namespace GLState { + class RenderbufferObjectStub {}; // TODO + + class FramebufferAttachment { + public: + // TODO: add Renderbuffer when it is implemented + explicit FramebufferAttachment(SharedPtr texture, Int level = 0); + explicit FramebufferAttachment(SharedPtr renderbuffer); + explicit FramebufferAttachment(std::nullptr_t); + + Bool IsTexture() const; + Bool IsRenderbuffer() const; + Bool IsEmpty(); + SharedPtr GetTexture() const; + SharedPtr GetRenderbuffer() const; + Int GetTextureLevel() const; + Bool IsComplete() const; + IntVec3 GetSize() const; + + private: + SharedPtr m_texture; + SharedPtr m_renderbuffer; + Int m_textureLevel = 0; + }; + + class FramebufferObject { + public: + using TargetEnum = FramebufferTarget; + + FramebufferObject(); + + void AttachTexture(FramebufferAttachmentType type, SharedPtr texture, int level = 0); + void AttachRenderbuffer(FramebufferAttachmentType type, + std::shared_ptr renderbuffer); + void Detach(FramebufferAttachmentType type); + const FramebufferAttachment& GetAttachment(FramebufferAttachmentType type) const; + Bool CheckCompleteness() const; + void SetDrawBuffers(const std::vector& buffers); + const Vector& GetDrawBuffers() const; + + private: + Array(FramebufferAttachmentType::FramebufferAttachmentTypeCount)> + m_attachments; + Bool m_drawBuffersDirty = true; + Vector m_drawBuffers; + }; + + } // namespace GLState + } // namespace MG_State +} // namespace MobileGL diff --git a/MobileGL/MG_State/GLState/FramebufferState/FramebufferState.cpp b/MobileGL/MG_State/GLState/FramebufferState/FramebufferState.cpp new file mode 100644 index 00000000..e5cac679 --- /dev/null +++ b/MobileGL/MG_State/GLState/FramebufferState/FramebufferState.cpp @@ -0,0 +1,62 @@ +#include "FramebufferState.h" + +namespace MobileGL { + namespace MG_State { + namespace GLState { + FramebufferState::FramebufferState() {} + + SharedPtr FramebufferState::GetFramebufferObject(Uint index) { + auto it = m_bufferObjects.find(index); + if (it != m_bufferObjects.end()) { + return it->second; + } + return nullptr; + } + + Vector FramebufferState::GenerateNames(Uint number) { + Vector buffers(number); + m_indexGenerator.Generate(number, buffers.data()); + return buffers; + } + + SharedPtr FramebufferState::CreateFramebufferObject(Uint index) { + auto bufferObject = MakeShared(); + m_bufferObjects[index] = bufferObject; + return bufferObject; + } + + BindingSlot& FramebufferState::GetBindingSlot(FramebufferTarget target) { + for (SizeT i = 0; i < m_bindingSlots.size(); ++i) { + if (m_bindingSlots[i].GetTarget() == target) { + return m_bindingSlots[i]; + } + } + assert(false); + return m_bindingSlots[0]; + } + + void FramebufferState::MarkFramebufferObjectForDeletion(Uint index) { + if (m_indexGenerator.IsValid(index)) { + auto it = m_bufferObjects.find(index); + if (it != m_bufferObjects.end()) { + for (SizeT i = 0; i < m_bindingSlots.size(); ++i) { + if (m_bindingSlots[i].GetBoundObject() == it->second) { + m_bindingSlots[i].Bind(nullptr); + } + } + m_bufferObjects.erase(it); + } + m_indexGenerator.Delete(index); + } + } + + Bool FramebufferState::ValidateName(Uint index) const { + return m_indexGenerator.IsValid(index); + } + + Bool FramebufferState::ValidateFramebufferObject(Uint index) const { + return m_bufferObjects.find(index) != m_bufferObjects.end(); + } + } // namespace GLState + } // namespace MG_State +} // namespace MobileGL diff --git a/MobileGL/MG_State/GLState/FramebufferState/FramebufferState.h b/MobileGL/MG_State/GLState/FramebufferState/FramebufferState.h new file mode 100644 index 00000000..8a63a5e7 --- /dev/null +++ b/MobileGL/MG_State/GLState/FramebufferState/FramebufferState.h @@ -0,0 +1,29 @@ +#pragma once +#include +#include +#include "FramebufferObject.h" + +namespace MobileGL { + namespace MG_State { + namespace GLState { + class FramebufferState { + public: + FramebufferState(); + + SharedPtr GetFramebufferObject(Uint index); + Vector GenerateNames(Uint number); + SharedPtr CreateFramebufferObject(Uint index); + BindingSlot& GetBindingSlot(FramebufferTarget target); + void MarkFramebufferObjectForDeletion(Uint index); + Bool ValidateName(Uint index) const; + Bool ValidateFramebufferObject(Uint index) const; + + private: + UnorderedMap> m_bufferObjects; + IndexGenerator m_indexGenerator; + Array, static_cast(FramebufferTarget::FramebufferTargetCount)> + m_bindingSlots; + }; + } // namespace GLState + } // namespace MG_State +} // namespace MobileGL \ No newline at end of file