diff --git a/MobileGL/MG_Impl/GLImpl/Framebuffer/GL_Framebuffer.cpp b/MobileGL/MG_Impl/GLImpl/Framebuffer/GL_Framebuffer.cpp index e547acb9..1224a586 100644 --- a/MobileGL/MG_Impl/GLImpl/Framebuffer/GL_Framebuffer.cpp +++ b/MobileGL/MG_Impl/GLImpl/Framebuffer/GL_Framebuffer.cpp @@ -1,6 +1,7 @@ #include "GL_Framebuffer.h" #include "Validators.h" #include "Config.h" +#include "MG_Util/Converters/GLToStr/GLEnumConverter.h" #include #include #include @@ -133,7 +134,76 @@ namespace MobileGL { } void DrawBuffers_State(GLsizei n, const GLenum* bufs) { - // TODO: implement + if (n < 0) { + MG_State::pGLContext->RecordError( + ErrorCode::InvalidValue, MakeShared("MG_Impl/GLImpl", __func__, + "`n` is less than 0.")); + return; + } else if (n > MG_State::GLState::FramebufferObject::MAX_DRAW_BUFFERS) { + MG_State::pGLContext->RecordError( + ErrorCode::InvalidValue, MakeShared("MG_Impl/GLImpl", __func__, + "`n` is greater than `GL_MAX_DRAW_BUFFERS`.")); + return; + } + + // Get bound framebuffer + auto& bindingSlot = MG_State::pGLContext->GetFramebufferBindingSlot(FramebufferTarget::Draw); + auto fbo = bindingSlot.GetBoundObject(); + bool isDefaultFBO = (fbo == FramebufferImpl::pDefaultFramebufferInfo->defaultFBO); + + static int existenceMap[(SizeT)FramebufferAttachmentType::FramebufferAttachmentTypeCount] = { + -1 + }; + std::fill(existenceMap, existenceMap + (SizeT)FramebufferAttachmentType::FramebufferAttachmentTypeCount, -1); + + for (GLsizei i = 0; i < n; ++i) { + auto attType = MG_Util::ConvertGLEnumToFramebufferAttachmentType(bufs[i]); + + // ------------------- Check validity begin ------------------------ + if (attType == FramebufferAttachmentType::Unknown) { + MG_State::pGLContext->RecordError( + ErrorCode::InvalidEnum, MakeShared("MG_Impl/GLImpl", __func__, + std::format("bufs[{}] = %s is not an accepted value.", i, MG_Util::ConvertGLEnumToString(bufs[i])))); + return; + } + + if (isDefaultFBO && + attType >= FramebufferAttachmentType::Color0 && attType <= FramebufferAttachmentType::Color31) { + MG_State::pGLContext->RecordError( + ErrorCode::InvalidEnum, MakeShared("MG_Impl/GLImpl", __func__, + std::format("FBO is default FBO, but bufs[{}] = {} is one of the `GL_COLOR_ATTACHMENTn` tokens.", i, MG_Util::ConvertGLEnumToString(bufs[i])))); + return; + } + + if (!isDefaultFBO && + attType >= FramebufferAttachmentType::FrontLeft && attType <= FramebufferAttachmentType::BackRight) { + MG_State::pGLContext->RecordError( + ErrorCode::InvalidEnum, MakeShared("MG_Impl/GLImpl", __func__, + std::format("FBO is not default FBO, but bufs[{}] = {} is anything other than `GL_NONE` or one of the `GL_COLOR_ATTACHMENTn` tokens.", i, MG_Util::ConvertGLEnumToString(bufs[i])))); + return; + } + + if (attType != FramebufferAttachmentType::None && existenceMap[(SizeT)attType] >= 0) { + MG_State::pGLContext->RecordError( + ErrorCode::InvalidOperation, MakeShared("MG_Impl/GLImpl", __func__, + std::format("a symbolic constant other than `GL_NONE` appears more than once in bufs. bufs[{}] == bufs[{}] == {}.", i, existenceMap[(SizeT)attType], MG_Util::ConvertGLEnumToString(bufs[i])))); + return; + } + + existenceMap[(SizeT)attType] = i; + + if ((SizeT)attType > (SizeT)FramebufferAttachmentType::Color0 + MG_State::GLState::FramebufferObject::MAX_DRAW_BUFFERS) { + MG_State::pGLContext->RecordError( + ErrorCode::InvalidOperation, MakeShared("MG_Impl/GLImpl", __func__, + std::format("bufs[{}] == {} indicates a color buffer that does not exist in the current GL context.", i, MG_Util::ConvertGLEnumToString(bufs[i])))); + return; + } + // ------------------------- Check validity end ---------------------------------- + fbo->SetDrawBuffer(i, attType); + } + for (GLsizei i = n; i < MG_State::GLState::FramebufferObject::MAX_DRAW_BUFFERS; ++i) { + fbo->SetDrawBuffer(i, FramebufferAttachmentType::None); + } } void DeleteRenderbuffers_State(GLsizei n, const GLuint* renderbuffers) { diff --git a/MobileGL/MG_State/GLState/FramebufferState/FramebufferObject.cpp b/MobileGL/MG_State/GLState/FramebufferState/FramebufferObject.cpp index c0fe683f..127eb719 100644 --- a/MobileGL/MG_State/GLState/FramebufferState/FramebufferObject.cpp +++ b/MobileGL/MG_State/GLState/FramebufferState/FramebufferObject.cpp @@ -63,8 +63,10 @@ namespace MobileGL { } // FramebufferObject - FramebufferObject::FramebufferObject(Uint externalIndex) : m_externalIndex(externalIndex) { + FramebufferObject::FramebufferObject(Uint externalIndex) : + m_externalIndex(externalIndex) { m_attachments.fill(FramebufferAttachment(false)); + m_drawBuffers.fill(FramebufferAttachmentType::None); } void FramebufferObject::AttachTexture(FramebufferAttachmentType type, SharedPtr texture, @@ -126,12 +128,22 @@ namespace MobileGL { return true; } - void FramebufferObject::SetDrawBuffers(const std::vector& buffers) { - m_drawBuffers = buffers; + void FramebufferObject::SetDrawBuffer(Uint index, FramebufferAttachmentType buffer) { + if (m_drawBuffers[index] == buffer) + return; m_drawBuffersDirty = true; + m_drawBuffers[index] = buffer; } - const Vector& FramebufferObject::GetDrawBuffers() const { +// void FramebufferObject::SetDrawBuffers(const Vector& buffers) { +// m_drawBuffers = buffers; +// m_drawBuffersDirty = true; +// } +// void SetDrawBuffer(Uint index, FramebufferAttachmentType buffer) { +// +// } + + const auto& FramebufferObject::GetDrawBuffers() const { return m_drawBuffers; } diff --git a/MobileGL/MG_State/GLState/FramebufferState/FramebufferObject.h b/MobileGL/MG_State/GLState/FramebufferState/FramebufferObject.h index e0e0d088..7f4f85a5 100644 --- a/MobileGL/MG_State/GLState/FramebufferState/FramebufferObject.h +++ b/MobileGL/MG_State/GLState/FramebufferState/FramebufferObject.h @@ -12,6 +12,16 @@ namespace MobileGL { }; enum class FramebufferAttachmentType { + None, + + FrontLeft, + FrontRight, + BackLeft, + BackRight, + + Depth, + Stencil, + Color0, Color1, Color2, @@ -44,8 +54,7 @@ namespace MobileGL { Color29, Color30, Color31, - Depth, - Stencil, + FramebufferAttachmentTypeCount, Unknown = -1 }; @@ -81,6 +90,7 @@ namespace MobileGL { class FramebufferObject { public: using TargetEnum = FramebufferTarget; + static constexpr uint MAX_DRAW_BUFFERS = 8; FramebufferObject(Uint externalIndex); @@ -93,8 +103,9 @@ namespace MobileGL { static_cast(FramebufferAttachmentType::FramebufferAttachmentTypeCount)>& GetAllAttachments() const; Bool CheckCompleteness() const; - void SetDrawBuffers(const std::vector& buffers); - const Vector& GetDrawBuffers() const; +// void SetDrawBuffers(const Vector& buffers); + void SetDrawBuffer(Uint index, FramebufferAttachmentType buffer); + const auto& GetDrawBuffers() const; Uint GetExternalIndex() const; private: @@ -103,7 +114,7 @@ namespace MobileGL { static_cast(FramebufferAttachmentType::FramebufferAttachmentTypeCount)> m_attachments; Bool m_drawBuffersDirty = true; - Vector m_drawBuffers; + Array m_drawBuffers; }; } // namespace GLState