From 9ab001bf755e7ebe332f4884f364fadadf1c79d2 Mon Sep 17 00:00:00 2001 From: BZLZHH Date: Sun, 14 Dec 2025 11:28:02 +0800 Subject: [PATCH] [Feat] (MG_Impl/Framebuffer): Implement renderbuffer funcs. --- .../MG_Impl/GLImpl/Exporting/Definitions.cpp | 2 +- .../GLImpl/Framebuffer/GL_Framebuffer.cpp | 172 ++++++++++++++++-- .../GLImpl/Framebuffer/GL_Framebuffer.h | 8 + .../MG_Impl/GLImpl/Framebuffer/Validators.cpp | 32 ++++ .../MG_Impl/GLImpl/Framebuffer/Validators.h | 2 + 5 files changed, 204 insertions(+), 12 deletions(-) diff --git a/MobileGL/MG_Impl/GLImpl/Exporting/Definitions.cpp b/MobileGL/MG_Impl/GLImpl/Exporting/Definitions.cpp index 16c09670..0a1d1c6a 100644 --- a/MobileGL/MG_Impl/GLImpl/Exporting/Definitions.cpp +++ b/MobileGL/MG_Impl/GLImpl/Exporting/Definitions.cpp @@ -118,7 +118,7 @@ DECLARE_GL_FUNCTION_HEAD(void, GetFramebufferAttachmentParameteriv, GLenum targe DECLARE_GL_FUNCTION_HEAD(void, GetIntegerv, GLenum pname, GLint* data) DECLARE_GL_FUNCTION_END_NO_RETURN(void, GetIntegerv, pname, data) DECLARE_GL_FUNCTION_HEAD(void, GetProgramiv, GLuint program, GLenum pname, GLint* params) DECLARE_GL_FUNCTION_END_NO_RETURN(void, GetProgramiv, program, pname, params) DECLARE_GL_FUNCTION_HEAD(void, GetProgramInfoLog, GLuint program, GLsizei bufSize, GLsizei* length, GLchar* infoLog) DECLARE_GL_FUNCTION_END_NO_RETURN(void, GetProgramInfoLog, program, bufSize, length, infoLog) -DECLARE_GL_FUNCTION_STUB_HEAD(void, GetRenderbufferParameteriv, GLenum target, GLenum pname, GLint* params) DECLARE_GL_FUNCTION_STUB_END_NO_RETURN(void, GetRenderbufferParameteriv, target, pname, params) +DECLARE_GL_FUNCTION_HEAD(void, GetRenderbufferParameteriv, GLenum target, GLenum pname, GLint* params) DECLARE_GL_FUNCTION_END_NO_RETURN(void, GetRenderbufferParameteriv, target, pname, params) DECLARE_GL_FUNCTION_HEAD(void, GetShaderiv, GLuint shader, GLenum pname, GLint* params) DECLARE_GL_FUNCTION_END_NO_RETURN(void, GetShaderiv, shader, pname, params) DECLARE_GL_FUNCTION_HEAD(void, GetShaderInfoLog, GLuint shader, GLsizei bufSize, GLsizei* length, GLchar* infoLog) DECLARE_GL_FUNCTION_END_NO_RETURN(void, GetShaderInfoLog, shader, bufSize, length, infoLog) DECLARE_GL_FUNCTION_STUB_HEAD(void, GetShaderPrecisionFormat, GLenum shadertype, GLenum precisiontype, GLint* range, GLint* precision) DECLARE_GL_FUNCTION_STUB_END_NO_RETURN(void, GetShaderPrecisionFormat, shadertype, precisiontype, range, precision) diff --git a/MobileGL/MG_Impl/GLImpl/Framebuffer/GL_Framebuffer.cpp b/MobileGL/MG_Impl/GLImpl/Framebuffer/GL_Framebuffer.cpp index d44c7358..0c7a572e 100644 --- a/MobileGL/MG_Impl/GLImpl/Framebuffer/GL_Framebuffer.cpp +++ b/MobileGL/MG_Impl/GLImpl/Framebuffer/GL_Framebuffer.cpp @@ -1,9 +1,11 @@ #include "GL_Framebuffer.h" #include "Validators.h" #include "Config.h" -#include "MG_Util/Converters/GLToStr/GLEnumConverter.h" #include #include +#include +#include +#include #include #if MOBILEGL_BACKEND == MOBILEGL_BACKEND_TYPE_DIRECT_GLES #include @@ -29,17 +31,34 @@ namespace MobileGL { } void RenderbufferStorage_State(GLenum target, GLenum internalformat, GLsizei width, GLsizei height) { - // TODO: implement + RenderbufferTarget rbTarget = MG_Util::ConvertGLEnumToRenderbufferTarget(target); + if (!FramebufferImpl::ValidateRenderbufferTarget(rbTarget)) return; + auto& bindingSlot = MG_State::pGLContext->GetRenderbufferBindingSlot(rbTarget); + auto renderbufferObject = bindingSlot.GetBoundObject(); + if (!renderbufferObject) { + MG_State::pGLContext->RecordError( + ErrorCode::InvalidOperation, + MakeShared("MG_Impl/GLImpl", "RenderbufferStorage_State", + "Renderbuffer target is bound to no renderbuffer object.")); + return; + } + TextureInternalFormat format = MG_Util::ConvertGLEnumToTextureInternalFormat(internalformat); + if (!TextureImpl::ValidateTextureInternalFormat(format)) return; + if (width < 0 || height < 0) { + MG_State::pGLContext->RecordError( + ErrorCode::InvalidValue, MakeShared("MG_Impl/GLImpl", "RenderbufferStorage_State", + "Width and height must be non-negative.")); + return; + } + renderbufferObject->AllocateStorage({width, height}); } GLboolean IsRenderbuffer_State(GLuint renderbuffer) { - // TODO: implement - return GL_FALSE; + return MG_State::pGLContext->ValidateRenderbufferName(renderbuffer); } GLboolean IsFramebuffer_State(GLuint framebuffer) { - // TODO: implement - return GL_FALSE; + return MG_State::pGLContext->ValidateFramebufferName(framebuffer); } void GetFramebufferAttachmentParameteriv_State(GLenum target, GLenum attachment, GLenum pname, GLint* params) { @@ -53,7 +72,14 @@ namespace MobileGL { } void GenRenderbuffers_State(GLsizei n, GLuint* renderbuffers) { - // TODO: implement + if (n < 0) { + MG_State::pGLContext->RecordError( + ErrorCode::InvalidValue, + MakeShared("MG_Impl/GLImpl", "GenRenderbuffers_State", "n must be non-negative")); + return; + } + auto renderbufferNames = MG_State::pGLContext->GenRenderbufferNames(n); + Memcpy(renderbuffers, renderbufferNames.data(), sizeof(GLuint) * static_cast(n)); } void GenFramebuffers_State(GLsizei n, GLuint* framebuffers) { @@ -64,7 +90,7 @@ namespace MobileGL { return; } auto framebuffersNames = MG_State::pGLContext->GenFramebufferNames(n); - Copy(framebuffersNames.data(), framebuffers, framebuffersNames.size()); + Memcpy(framebuffers, framebuffersNames.data(), sizeof(GLuint) * static_cast(n)); } void FramebufferTextureLayer_State(GLenum target, GLenum attachment, GLuint texture, GLint level, GLint layer) { @@ -132,7 +158,41 @@ namespace MobileGL { void FramebufferRenderbuffer_State(GLenum target, GLenum attachment, GLenum renderbuffertarget, GLuint renderbuffer) { - // TODO: implement + if (target == GL_FRAMEBUFFER) { + target = GL_DRAW_FRAMEBUFFER; + } + + FramebufferAttachmentType attachmentType = MG_Util::ConvertGLEnumToFramebufferAttachmentType(attachment); + FramebufferTarget framebufferTarget = MG_Util::ConvertGLEnumToFramebufferTarget(target); + RenderbufferTarget rbTarget = MG_Util::ConvertGLEnumToRenderbufferTarget(renderbuffertarget); + if (!FramebufferImpl::ValidateFramebufferAttachmentType(attachmentType)) return; + if (!FramebufferImpl::ValidateFramebufferTarget(framebufferTarget)) return; + if (!FramebufferImpl::ValidateRenderbufferName(renderbuffer)) return; + auto& bindingSlot = MG_State::pGLContext->GetFramebufferBindingSlot(framebufferTarget); + auto framebufferObject = bindingSlot.GetBoundObject(); + if (!framebufferObject) { + MG_State::pGLContext->RecordError( + ErrorCode::InvalidOperation, + MakeShared("MG_Impl/GLImpl", "FramebufferRenderbuffer_State", + "Framebuffer target is bound to no framebuffer object.")); + return; + } + + if (renderbuffer == 0) { + framebufferObject->Detach(attachmentType); + return; + } + + auto renderbufferObject = MG_State::pGLContext->GetRenderbufferObject(renderbuffer); + if (!renderbufferObject) { + MG_State::pGLContext->RecordError( + ErrorCode::InvalidOperation, + MakeShared("MG_Impl/GLImpl", "FramebufferRenderbuffer_State", + std::format("Renderbuffer object {} is not valid.", renderbuffer))); + return; + } + + framebufferObject->AttachRenderbuffer(attachmentType, renderbufferObject); } void DrawBuffers_State(GLsizei n, const GLenum* bufs) { @@ -227,7 +287,26 @@ namespace MobileGL { } void DeleteRenderbuffers_State(GLsizei n, const GLuint* renderbuffers) { - // TODO: implement + if (n < 0) { + MG_State::pGLContext->RecordError( + ErrorCode::InvalidValue, MakeShared("MG_Impl/GLImpl", "DeleteRenderbuffers_State", + "n must be non-negative.")); + return; + } + + if (!renderbuffers) { + MG_State::pGLContext->RecordError( + ErrorCode::InvalidValue, MakeShared("MG_Impl/GLImpl", "DeleteRenderbuffers_State", + "Renderbuffer names array cannot be null.")); + return; + } + + for (SizeT i = 0; i < static_cast(n); ++i) { + Uint bufferName = renderbuffers[i]; + if (bufferName == 0) continue; + if (!FramebufferImpl::ValidateRenderbufferName(bufferName)) continue; + MG_State::pGLContext->MarkRenderbufferObjectForDeletion(bufferName); + } } void DeleteFramebuffers_State(GLsizei n, const GLuint* framebuffers) { @@ -276,7 +355,18 @@ namespace MobileGL { } void BindRenderbuffer_State(GLenum target, GLuint renderbuffer) { - // TODO: implement + if (!FramebufferImpl::ValidateRenderbufferName(renderbuffer)) return; + RenderbufferTarget renderbufferTarget = MG_Util::ConvertGLEnumToRenderbufferTarget(target); + if (!FramebufferImpl::ValidateRenderbufferTarget(renderbufferTarget)) return; + + auto renderbufferObject = MG_State::pGLContext->GetRenderbufferObject(renderbuffer); + if (!renderbufferObject) { + MG_State::pGLContext->CreateRenderbufferObject(renderbuffer); + renderbufferObject = MG_State::pGLContext->GetRenderbufferObject(renderbuffer); + } + + auto& bindingSlot = MG_State::pGLContext->GetRenderbufferBindingSlot(renderbufferTarget); + bindingSlot.Bind(renderbufferObject); } void BindFramebuffer_State(GLenum target, GLuint framebuffer) { @@ -300,6 +390,62 @@ namespace MobileGL { bindingSlot.Bind(framebufferObject); } + void GetRenderbufferParameteriv_State(GLenum target, GLenum pname, GLint* params) { + if (!params) return; + + RenderbufferTarget renderbufferTarget = MG_Util::ConvertGLEnumToRenderbufferTarget(target); + if (!FramebufferImpl::ValidateRenderbufferTarget(renderbufferTarget)) return; + auto& bindingSlot = MG_State::pGLContext->GetRenderbufferBindingSlot(renderbufferTarget); + auto renderbufferObject = bindingSlot.GetBoundObject(); + if (!renderbufferObject) { + MG_State::pGLContext->RecordError( + ErrorCode::InvalidOperation, + MakeShared("MG_Impl/GLImpl", "GetRenderbufferParameteriv_State", + "Renderbuffer target is bound to no renderbuffer object.")); + return; + } + + switch (pname) { + case GL_RENDERBUFFER_WIDTH: + *params = static_cast(renderbufferObject->GetWidth()); + break; + case GL_RENDERBUFFER_HEIGHT: + *params = static_cast(renderbufferObject->GetHeight()); + break; + case GL_RENDERBUFFER_INTERNAL_FORMAT: + *params = MG_Util::ConvertTextureInternalFormatToGLEnum(renderbufferObject->GetInternalFormat()); + break; + case GL_RENDERBUFFER_RED_SIZE: + *params = static_cast(renderbufferObject->GetRedSize()); + break; + case GL_RENDERBUFFER_GREEN_SIZE: + *params = static_cast(renderbufferObject->GetGreenSize()); + break; + case GL_RENDERBUFFER_BLUE_SIZE: + *params = static_cast(renderbufferObject->GetBlueSize()); + break; + case GL_RENDERBUFFER_ALPHA_SIZE: + *params = static_cast(renderbufferObject->GetAlphaSize()); + break; + case GL_RENDERBUFFER_DEPTH_SIZE: + *params = static_cast(renderbufferObject->GetDepthSize()); + break; + case GL_RENDERBUFFER_STENCIL_SIZE: + *params = static_cast(renderbufferObject->GetStencilSize()); + break; + case GL_RENDERBUFFER_SAMPLES: + *params = static_cast(renderbufferObject->GetSamples()); + break; + default: + MG_State::pGLContext->RecordError( + ErrorCode::InvalidEnum, + MakeShared( + "MG_Impl/GLImpl", "GetRenderbufferParameteriv_State", + std::format("pname %s is not an accepted value.", MG_Util::ConvertGLEnumToString(pname)))); + return; + } + } + /* @INSERTION_POINT:FUNCTION_IMPLEMENTATION@ */ void SampleMaski(GLuint maskNumber, GLbitfield mask) { SampleMaski_State(maskNumber, mask); @@ -392,6 +538,10 @@ namespace MobileGL { BindFramebuffer_State(target, framebuffer); } + void GetRenderbufferParameteriv(GLenum target, GLenum pname, GLint* params) { + GetRenderbufferParameteriv_State(target, pname, params); + } + namespace FramebufferImpl { DefaultFramebufferInfo* pDefaultFramebufferInfo; } diff --git a/MobileGL/MG_Impl/GLImpl/Framebuffer/GL_Framebuffer.h b/MobileGL/MG_Impl/GLImpl/Framebuffer/GL_Framebuffer.h index b10cd75d..acc48f71 100644 --- a/MobileGL/MG_Impl/GLImpl/Framebuffer/GL_Framebuffer.h +++ b/MobileGL/MG_Impl/GLImpl/Framebuffer/GL_Framebuffer.h @@ -6,6 +6,14 @@ namespace MobileGL { namespace MG_Impl::GLImpl { /* @INSERTION_POINT:FUNCTION_DECLARATION@ */ + void RenderbufferStorageMultisample(GLenum target, GLsizei samples, GLenum internalformat, GLsizei width, GLsizei height); + void RenderbufferStorage(GLenum target, GLenum internalformat, GLsizei width, GLsizei height); + GLboolean IsRenderbuffer(GLuint renderbuffer); + void GetRenderbufferParameteriv(GLenum target, GLenum pname, GLint* params); + void GenRenderbuffers(GLsizei n, GLuint* renderbuffers); + void FramebufferRenderbuffer(GLenum target, GLenum attachment, GLenum renderbuffertarget, GLuint renderbuffer); + void DeleteRenderbuffers(GLsizei n, const GLuint* renderbuffers); + void BindRenderbuffer(GLenum target, GLuint renderbuffer); void SampleMaski(GLuint maskNumber, GLbitfield mask); void RenderbufferStorageMultisample(GLenum target, GLsizei samples, GLenum internalformat, GLsizei width, GLsizei height); diff --git a/MobileGL/MG_Impl/GLImpl/Framebuffer/Validators.cpp b/MobileGL/MG_Impl/GLImpl/Framebuffer/Validators.cpp index 95d71458..7e32db29 100644 --- a/MobileGL/MG_Impl/GLImpl/Framebuffer/Validators.cpp +++ b/MobileGL/MG_Impl/GLImpl/Framebuffer/Validators.cpp @@ -53,5 +53,37 @@ namespace MobileGL::MG_Impl::GLImpl { } return true; } + + Bool ValidateRenderbufferTarget(RenderbufferTarget target) { + if (target == RenderbufferTarget::Unknown) { + using namespace MG_Util; + String renderbufferTargetStr = ConvertRenderbufferTargetToString(target); + String glTargetStr = ConvertGLEnumToString(ConvertRenderbufferTargetToGLEnum(target)); + MG_State::pGLContext->RecordError( + ErrorCode::InvalidEnum, + MakeShared( + "MG_Impl/GLImpl/FramebufferImpl", "ValidateRenderbufferTarget", + std::format("Target {} ({}) is not valid.", renderbufferTargetStr, glTargetStr))); + return false; + } + return true; + } + + Bool ValidateRenderbufferName(Uint index, Bool allowZero) { + if (index == 0 && !allowZero) { + MG_State::pGLContext->RecordError( + ErrorCode::InvalidValue, + MakeShared("MG_Impl/GLImpl/FramebufferImpl", "ValidateRenderbufferName", + "Renderbuffer name 0 is not valid in this situation.")); + return false; + } + Bool isValid = MG_State::pGLContext->ValidateRenderbufferName(index); + if (isValid) return true; + MG_State::pGLContext->RecordError( + ErrorCode::InvalidOperation, + MakeShared("MG_Impl/GLImpl/FramebufferImpl", "ValidateRenderbufferName", + std::format("Renderbuffer name {} is not valid.", index))); + return false; + } } // namespace FramebufferImpl } // namespace MobileGL::MG_Impl::GLImpl \ No newline at end of file diff --git a/MobileGL/MG_Impl/GLImpl/Framebuffer/Validators.h b/MobileGL/MG_Impl/GLImpl/Framebuffer/Validators.h index c89ab58a..33adc465 100644 --- a/MobileGL/MG_Impl/GLImpl/Framebuffer/Validators.h +++ b/MobileGL/MG_Impl/GLImpl/Framebuffer/Validators.h @@ -7,5 +7,7 @@ namespace MobileGL::MG_Impl::GLImpl { Bool ValidateFramebufferTarget(FramebufferTarget target); Bool ValidateFramebufferName(Uint index, Bool allowZero = true); Bool ValidateFramebufferAttachmentType(FramebufferAttachmentType attachment); + Bool ValidateRenderbufferTarget(RenderbufferTarget target); + Bool ValidateRenderbufferName(Uint index, Bool allowZero = true); } // namespace FramebufferImpl } // namespace MobileGL::MG_Impl::GLImpl \ No newline at end of file