From 19932f9e497bf74cbca897bac449b57ed5dd4ff6 Mon Sep 17 00:00:00 2001 From: BZLZHH Date: Tue, 4 Aug 2026 23:41:28 -0400 Subject: [PATCH] [Feat] (MG_Impl, MG_Backend): implement the integer direct state access framebuffer clears glClearNamedFramebufferiv and glClearNamedFramebufferuiv were stubs, so a clear through them was silently dropped and the attachment kept whatever it held. Their float siblings were already implemented, which is what made the gap look like a rendering bug rather than a missing entry point. Which buffers they accept is narrower than glClearNamedFramebufferfv and differs between the two: signed values clear COLOR or STENCIL, unsigned only COLOR (GL 4.6 core 17.4.3.1). Only the colour buffer is indexed, so a stencil clear naming any drawbuffer other than 0 is INVALID_VALUE rather than merely ignored, and anything else is INVALID_ENUM. Resolving the framebuffer by name goes through the same helper the float forms use, which is what reports INVALID_OPERATION for a name that is neither zero nor an existing framebuffer. Both backends express them the way they already express the float forms: DirectGLES binds the named framebuffer and forwards to glClearBuffer*, Magma queues the payload against the named framebuffer rather than the bound one. direct_state_access.framebuffers_clear_errors passes on both backends, and framebuffers_clear passes on Espryt. Magma still fails that one, for a separate reason on the materialization side rather than in these entry points. --- MobileGL/MG_Backend/BackendObject.h | 4 + .../DirectGLES/BackendObject_DirectGLES.cpp | 2 + MobileGL/MG_Backend/DirectGLES/DirectGLES.cpp | 34 +++++++ MobileGL/MG_Backend/DirectGLES/DirectGLES.h | 4 + .../BackendObject_DirectVulkan.cpp | 2 + .../MG_Backend/DirectVulkan/DirectVulkan.cpp | 14 +++ .../MG_Backend/DirectVulkan/DirectVulkan.h | 4 + .../DirectVulkan/Renderer/VulkanRenderer.cpp | 40 +++++++++ .../DirectVulkan/Renderer/VulkanRenderer.h | 4 + .../MG_Impl/GLImpl/Exporting/Definitions.cpp | 4 +- .../GLImpl/Framebuffer/GL_Framebuffer.cpp | 88 +++++++++++++++++++ .../GLImpl/Framebuffer/GL_Framebuffer.h | 2 + 12 files changed, 200 insertions(+), 2 deletions(-) diff --git a/MobileGL/MG_Backend/BackendObject.h b/MobileGL/MG_Backend/BackendObject.h index 5285cd3c..dcab60f3 100644 --- a/MobileGL/MG_Backend/BackendObject.h +++ b/MobileGL/MG_Backend/BackendObject.h @@ -145,6 +145,10 @@ namespace MobileGL { GLenum buffer, GLint drawbuffer, const GLfloat* value); void (*ClearNamedFramebufferfi)(const SharedPtr& framebuffer, GLenum buffer, GLint drawbuffer, GLfloat depth, GLint stencil); + void (*ClearNamedFramebufferiv)(const SharedPtr& framebuffer, + GLenum buffer, GLint drawbuffer, const GLint* value); + void (*ClearNamedFramebufferuiv)(const SharedPtr& framebuffer, + GLenum buffer, GLint drawbuffer, const GLuint* value); void (*BlitFramebuffer)(GLint srcX0, GLint srcY0, GLint srcX1, GLint srcY1, GLint dstX0, GLint dstY0, GLint dstX1, GLint dstY1, GLbitfield mask, GLenum filter); void (*BlitNamedFramebuffer)(const SharedPtr& readFramebuffer, diff --git a/MobileGL/MG_Backend/DirectGLES/BackendObject_DirectGLES.cpp b/MobileGL/MG_Backend/DirectGLES/BackendObject_DirectGLES.cpp index 90cd66fd..831ecf53 100644 --- a/MobileGL/MG_Backend/DirectGLES/BackendObject_DirectGLES.cpp +++ b/MobileGL/MG_Backend/DirectGLES/BackendObject_DirectGLES.cpp @@ -988,6 +988,8 @@ namespace MobileGL::MG_Backend::DirectGLES { funcsTable.GL.ClearBufferuiv = ClearBufferuiv; funcsTable.GL.ClearBufferiv = ClearBufferiv; funcsTable.GL.ClearNamedFramebufferfv = ClearNamedFramebufferfv; + funcsTable.GL.ClearNamedFramebufferiv = ClearNamedFramebufferiv; + funcsTable.GL.ClearNamedFramebufferuiv = ClearNamedFramebufferuiv; funcsTable.GL.ClearNamedFramebufferfi = ClearNamedFramebufferfi; funcsTable.GL.BlitFramebuffer = BlitFramebuffer; funcsTable.GL.BlitNamedFramebuffer = BlitNamedFramebuffer; diff --git a/MobileGL/MG_Backend/DirectGLES/DirectGLES.cpp b/MobileGL/MG_Backend/DirectGLES/DirectGLES.cpp index 00fb641f..53f378ea 100644 --- a/MobileGL/MG_Backend/DirectGLES/DirectGLES.cpp +++ b/MobileGL/MG_Backend/DirectGLES/DirectGLES.cpp @@ -4431,6 +4431,40 @@ namespace MobileGL::MG_Backend::DirectGLES { ForceBindCurrentFBO(FramebufferTarget::Draw); } + void ClearNamedFramebufferiv(const SharedPtr& framebuffer, + GLenum buffer, GLint drawbuffer, const GLint* value) { +#if MOBILEGL_LOG_ACTIVE_LEVEL <= MOBILEGL_LOG_LEVEL_DEBUG && MOBILEGL_ENABLE_SCOPE_MARKER + DebugImpl::OpenGLScopeMarker marker(__func__); +#endif + TextureImpl::SyncNeccessaryTextures(); + RenderStateImpl::SyncRenderState(); + + SyncAndBindFramebufferObject(framebuffer, FramebufferTarget::Draw, true); + g_GLESFuncs.glClearBufferiv(buffer, drawbuffer, value); + DebugImpl::ErrorLopper::Loop([file = __FILE__, line = __LINE__](auto err) { + MGLOG_D("ES error (%s:%d): %s", file, line, MG_Util::ConvertGLEnumToString(err).c_str()); + }); + + ForceBindCurrentFBO(FramebufferTarget::Draw); + } + + void ClearNamedFramebufferuiv(const SharedPtr& framebuffer, + GLenum buffer, GLint drawbuffer, const GLuint* value) { +#if MOBILEGL_LOG_ACTIVE_LEVEL <= MOBILEGL_LOG_LEVEL_DEBUG && MOBILEGL_ENABLE_SCOPE_MARKER + DebugImpl::OpenGLScopeMarker marker(__func__); +#endif + TextureImpl::SyncNeccessaryTextures(); + RenderStateImpl::SyncRenderState(); + + SyncAndBindFramebufferObject(framebuffer, FramebufferTarget::Draw, true); + g_GLESFuncs.glClearBufferuiv(buffer, drawbuffer, value); + DebugImpl::ErrorLopper::Loop([file = __FILE__, line = __LINE__](auto err) { + MGLOG_D("ES error (%s:%d): %s", file, line, MG_Util::ConvertGLEnumToString(err).c_str()); + }); + + ForceBindCurrentFBO(FramebufferTarget::Draw); + } + static SizeT AlignPixelRow(SizeT rowBytes, Int alignment) { const SizeT resolvedAlignment = static_cast(std::max(alignment, 1)); return (rowBytes + resolvedAlignment - 1) & ~(resolvedAlignment - 1); diff --git a/MobileGL/MG_Backend/DirectGLES/DirectGLES.h b/MobileGL/MG_Backend/DirectGLES/DirectGLES.h index 9a11cfc6..bc732f6c 100644 --- a/MobileGL/MG_Backend/DirectGLES/DirectGLES.h +++ b/MobileGL/MG_Backend/DirectGLES/DirectGLES.h @@ -59,6 +59,10 @@ namespace MobileGL::MG_Backend::DirectGLES { GLenum buffer, GLint drawbuffer, const GLfloat* value); void ClearNamedFramebufferfi(const SharedPtr& framebuffer, GLenum buffer, GLint drawbuffer, GLfloat depth, GLint stencil); + void ClearNamedFramebufferiv(const SharedPtr& framebuffer, + GLenum buffer, GLint drawbuffer, const GLint* value); + void ClearNamedFramebufferuiv(const SharedPtr& framebuffer, + GLenum buffer, GLint drawbuffer, const GLuint* value); void BlitFramebuffer(GLint srcX0, GLint srcY0, GLint srcX1, GLint srcY1, GLint dstX0, GLint dstY0, GLint dstX1, GLint dstY1, GLbitfield mask, GLenum filter); void BlitNamedFramebuffer(const SharedPtr& readFramebuffer, diff --git a/MobileGL/MG_Backend/DirectVulkan/BackendObject_DirectVulkan.cpp b/MobileGL/MG_Backend/DirectVulkan/BackendObject_DirectVulkan.cpp index 97cf6949..34fc3a2d 100644 --- a/MobileGL/MG_Backend/DirectVulkan/BackendObject_DirectVulkan.cpp +++ b/MobileGL/MG_Backend/DirectVulkan/BackendObject_DirectVulkan.cpp @@ -597,6 +597,8 @@ namespace MobileGL::MG_Backend::DirectVulkan { funcsTable.GL.ClearBufferiv = ClearBufferiv; funcsTable.GL.ClearNamedFramebufferfv = ClearNamedFramebufferfv; funcsTable.GL.ClearNamedFramebufferfi = ClearNamedFramebufferfi; + funcsTable.GL.ClearNamedFramebufferiv = ClearNamedFramebufferiv; + funcsTable.GL.ClearNamedFramebufferuiv = ClearNamedFramebufferuiv; funcsTable.GL.BlitFramebuffer = BlitFramebuffer; funcsTable.GL.BlitNamedFramebuffer = BlitNamedFramebuffer; funcsTable.GL.CopyTexImage2D = CopyTexImage2D; diff --git a/MobileGL/MG_Backend/DirectVulkan/DirectVulkan.cpp b/MobileGL/MG_Backend/DirectVulkan/DirectVulkan.cpp index 575469c4..5c1b99e3 100644 --- a/MobileGL/MG_Backend/DirectVulkan/DirectVulkan.cpp +++ b/MobileGL/MG_Backend/DirectVulkan/DirectVulkan.cpp @@ -440,6 +440,20 @@ namespace MobileGL::MG_Backend::DirectVulkan { pVulkanRenderer->ClearNamedFramebufferfv(framebuffer, buffer, drawbuffer, value); } + void ClearNamedFramebufferiv(const SharedPtr& framebuffer, GLenum buffer, + GLint drawbuffer, const GLint* value) { + MOBILEGL_ASSERT(pVulkanRenderer, "DirectVulkan::ClearNamedFramebufferiv called with null VulkanRenderer"); + MOBILEGL_ASSERT(MG_State::pGLContext, "DirectVulkan::ClearNamedFramebufferiv called with null GL context"); + pVulkanRenderer->ClearNamedFramebufferiv(framebuffer, buffer, drawbuffer, value); + } + + void ClearNamedFramebufferuiv(const SharedPtr& framebuffer, GLenum buffer, + GLint drawbuffer, const GLuint* value) { + MOBILEGL_ASSERT(pVulkanRenderer, "DirectVulkan::ClearNamedFramebufferuiv called with null VulkanRenderer"); + MOBILEGL_ASSERT(MG_State::pGLContext, "DirectVulkan::ClearNamedFramebufferuiv called with null GL context"); + pVulkanRenderer->ClearNamedFramebufferuiv(framebuffer, buffer, drawbuffer, value); + } + void ClearNamedFramebufferfi(const SharedPtr& framebuffer, GLenum buffer, GLint drawbuffer, GLfloat depth, GLint stencil) { MOBILEGL_ASSERT(pVulkanRenderer, "DirectVulkan::ClearNamedFramebufferfi called with null VulkanRenderer"); diff --git a/MobileGL/MG_Backend/DirectVulkan/DirectVulkan.h b/MobileGL/MG_Backend/DirectVulkan/DirectVulkan.h index 06ad546a..9ccc7eaa 100644 --- a/MobileGL/MG_Backend/DirectVulkan/DirectVulkan.h +++ b/MobileGL/MG_Backend/DirectVulkan/DirectVulkan.h @@ -35,6 +35,10 @@ namespace MobileGL::MG_Backend::DirectVulkan { void ClearBufferiv(GLenum buffer, GLint drawbuffer, const GLint* value); void ClearNamedFramebufferfv(const SharedPtr& framebuffer, GLenum buffer, GLint drawbuffer, const GLfloat* value); + void ClearNamedFramebufferiv(const SharedPtr& framebuffer, GLenum buffer, + GLint drawbuffer, const GLint* value); + void ClearNamedFramebufferuiv(const SharedPtr& framebuffer, GLenum buffer, + GLint drawbuffer, const GLuint* value); void ClearNamedFramebufferfi(const SharedPtr& framebuffer, GLenum buffer, GLint drawbuffer, GLfloat depth, GLint stencil); void Clear(GLbitfield mask); diff --git a/MobileGL/MG_Backend/DirectVulkan/Renderer/VulkanRenderer.cpp b/MobileGL/MG_Backend/DirectVulkan/Renderer/VulkanRenderer.cpp index 093ce43d..af7207fd 100644 --- a/MobileGL/MG_Backend/DirectVulkan/Renderer/VulkanRenderer.cpp +++ b/MobileGL/MG_Backend/DirectVulkan/Renderer/VulkanRenderer.cpp @@ -5771,6 +5771,46 @@ void main() { QueueClearBufferPayloadForFramebuffer(*framebuffer, buffer, drawbuffer, payload); } + // The integer clears carry the same payload as their target-based siblings; only the + // destination differs, so they queue against the named framebuffer rather than the bound one. + void VulkanRenderer::ClearNamedFramebufferiv( + const SharedPtr& framebuffer, GLenum buffer, GLint drawbuffer, + const GLint* value) { + if (!framebuffer || value == nullptr) { + return; + } + ClearAttachmentPayload payload{}; + switch (buffer) { + case GL_COLOR: + payload.mask = GL_COLOR_BUFFER_BIT; + payload.color = FloatVec4(static_cast(value[0]), static_cast(value[1]), + static_cast(value[2]), static_cast(value[3])); + break; + case GL_STENCIL: + payload.mask = GL_STENCIL_BUFFER_BIT; + payload.stencil = static_cast(std::max(value[0], 0)); + break; + default: + break; + } + QueueClearBufferPayloadForFramebuffer(*framebuffer, buffer, drawbuffer, payload); + } + + void VulkanRenderer::ClearNamedFramebufferuiv( + const SharedPtr& framebuffer, GLenum buffer, GLint drawbuffer, + const GLuint* value) { + if (!framebuffer || value == nullptr) { + return; + } + ClearAttachmentPayload payload{}; + if (buffer == GL_COLOR) { + payload.mask = GL_COLOR_BUFFER_BIT; + payload.color = FloatVec4(static_cast(value[0]), static_cast(value[1]), + static_cast(value[2]), static_cast(value[3])); + } + QueueClearBufferPayloadForFramebuffer(*framebuffer, buffer, drawbuffer, payload); + } + void VulkanRenderer::ClearNamedFramebufferfi( const SharedPtr& framebuffer, GLenum buffer, GLint drawbuffer, GLfloat depth, GLint stencil) { diff --git a/MobileGL/MG_Backend/DirectVulkan/Renderer/VulkanRenderer.h b/MobileGL/MG_Backend/DirectVulkan/Renderer/VulkanRenderer.h index 7de35679..04c5c17e 100644 --- a/MobileGL/MG_Backend/DirectVulkan/Renderer/VulkanRenderer.h +++ b/MobileGL/MG_Backend/DirectVulkan/Renderer/VulkanRenderer.h @@ -181,6 +181,10 @@ namespace MobileGL::MG_Backend::DirectVulkan { void ClearBufferiv(GLenum buffer, GLint drawbuffer, const GLint* value); void ClearNamedFramebufferfv(const SharedPtr& framebuffer, GLenum buffer, GLint drawbuffer, const GLfloat* value); + void ClearNamedFramebufferiv(const SharedPtr& framebuffer, + GLenum buffer, GLint drawbuffer, const GLint* value); + void ClearNamedFramebufferuiv(const SharedPtr& framebuffer, + GLenum buffer, GLint drawbuffer, const GLuint* value); void ClearNamedFramebufferfi(const SharedPtr& framebuffer, GLenum buffer, GLint drawbuffer, GLfloat depth, GLint stencil); void BlitFramebuffer(GLint srcX0, GLint srcY0, GLint srcX1, GLint srcY1, diff --git a/MobileGL/MG_Impl/GLImpl/Exporting/Definitions.cpp b/MobileGL/MG_Impl/GLImpl/Exporting/Definitions.cpp index 5a688d77..f8c36028 100644 --- a/MobileGL/MG_Impl/GLImpl/Exporting/Definitions.cpp +++ b/MobileGL/MG_Impl/GLImpl/Exporting/Definitions.cpp @@ -1036,8 +1036,8 @@ DECLARE_GL_FUNCTION_HEAD(void, NamedFramebufferDrawBuffers, GLuint framebuffer, DECLARE_GL_FUNCTION_HEAD(void, NamedFramebufferReadBuffer, GLuint framebuffer, GLenum src) DECLARE_GL_FUNCTION_END_NO_RETURN(void, NamedFramebufferReadBuffer, framebuffer, src) DECLARE_GL_FUNCTION_STUB_HEAD(void, InvalidateNamedFramebufferData, GLuint framebuffer, GLsizei numAttachments, const GLenum* attachments) DECLARE_GL_FUNCTION_STUB_END_NO_RETURN(void, InvalidateNamedFramebufferData, framebuffer, numAttachments, attachments) DECLARE_GL_FUNCTION_STUB_HEAD(void, InvalidateNamedFramebufferSubData, GLuint framebuffer, GLsizei numAttachments, const GLenum* attachments, GLint x, GLint y, GLsizei width, GLsizei height) DECLARE_GL_FUNCTION_STUB_END_NO_RETURN(void, InvalidateNamedFramebufferSubData, framebuffer, numAttachments, attachments, x, y, width, height) -DECLARE_GL_FUNCTION_STUB_HEAD(void, ClearNamedFramebufferiv, GLuint framebuffer, GLenum buffer, GLint drawbuffer, const GLint* value) DECLARE_GL_FUNCTION_STUB_END_NO_RETURN(void, ClearNamedFramebufferiv, framebuffer, buffer, drawbuffer, value) -DECLARE_GL_FUNCTION_STUB_HEAD(void, ClearNamedFramebufferuiv, GLuint framebuffer, GLenum buffer, GLint drawbuffer, const GLuint* value) DECLARE_GL_FUNCTION_STUB_END_NO_RETURN(void, ClearNamedFramebufferuiv, framebuffer, buffer, drawbuffer, value) +DECLARE_GL_FUNCTION_HEAD(void, ClearNamedFramebufferiv, GLuint framebuffer, GLenum buffer, GLint drawbuffer, const GLint* value) DECLARE_GL_FUNCTION_END_NO_RETURN(void, ClearNamedFramebufferiv, framebuffer, buffer, drawbuffer, value) +DECLARE_GL_FUNCTION_HEAD(void, ClearNamedFramebufferuiv, GLuint framebuffer, GLenum buffer, GLint drawbuffer, const GLuint* value) DECLARE_GL_FUNCTION_END_NO_RETURN(void, ClearNamedFramebufferuiv, framebuffer, buffer, drawbuffer, value) DECLARE_GL_FUNCTION_HEAD(void, ClearNamedFramebufferfv, GLuint framebuffer, GLenum buffer, GLint drawbuffer, const GLfloat* value) DECLARE_GL_FUNCTION_END_NO_RETURN(void, ClearNamedFramebufferfv, framebuffer, buffer, drawbuffer, value) DECLARE_GL_FUNCTION_HEAD(void, ClearNamedFramebufferfi, GLuint framebuffer, GLenum buffer, GLint drawbuffer, GLfloat depth, GLint stencil) DECLARE_GL_FUNCTION_END_NO_RETURN(void, ClearNamedFramebufferfi, framebuffer, buffer, drawbuffer, depth, stencil) DECLARE_GL_FUNCTION_HEAD(void, BlitNamedFramebuffer, GLuint readFramebuffer, GLuint drawFramebuffer, GLint srcX0, GLint srcY0, GLint srcX1, GLint srcY1, GLint dstX0, GLint dstY0, GLint dstX1, GLint dstY1, GLbitfield mask, GLenum filter) DECLARE_GL_FUNCTION_END_NO_RETURN(void, BlitNamedFramebuffer, readFramebuffer, drawFramebuffer, srcX0, srcY0, srcX1, srcY1, dstX0, dstY0, dstX1, dstY1, mask, filter) diff --git a/MobileGL/MG_Impl/GLImpl/Framebuffer/GL_Framebuffer.cpp b/MobileGL/MG_Impl/GLImpl/Framebuffer/GL_Framebuffer.cpp index 3d2a52a1..ae6083a3 100644 --- a/MobileGL/MG_Impl/GLImpl/Framebuffer/GL_Framebuffer.cpp +++ b/MobileGL/MG_Impl/GLImpl/Framebuffer/GL_Framebuffer.cpp @@ -467,6 +467,26 @@ namespace MobileGL::MG_Impl::GLImpl { clearNamedFramebufferfi(framebuffer, buffer, drawbuffer, depth, stencil); } + void ClearNamedFramebufferiv_Backend(const SharedPtr& framebuffer, + GLenum buffer, GLint drawbuffer, const GLint* value) { + auto clearNamedFramebufferiv = MG_Backend::gBackendFunctionsTable.GL.ClearNamedFramebufferiv; + if (!clearNamedFramebufferiv) { + MGLOG_E("glClearNamedFramebufferiv skipped: backend does not implement explicit framebuffer clear."); + return; + } + clearNamedFramebufferiv(framebuffer, buffer, drawbuffer, value); + } + + void ClearNamedFramebufferuiv_Backend(const SharedPtr& framebuffer, + GLenum buffer, GLint drawbuffer, const GLuint* value) { + auto clearNamedFramebufferuiv = MG_Backend::gBackendFunctionsTable.GL.ClearNamedFramebufferuiv; + if (!clearNamedFramebufferuiv) { + MGLOG_E("glClearNamedFramebufferuiv skipped: backend does not implement explicit framebuffer clear."); + return; + } + clearNamedFramebufferuiv(framebuffer, buffer, drawbuffer, value); + } + void SampleMaski_State(GLuint maskNumber, GLbitfield mask) { if (maskNumber != 0) { MG_State::pGLContext->RecordError( @@ -1586,6 +1606,66 @@ namespace MobileGL::MG_Impl::GLImpl { ClearNamedFramebufferfi_Backend(framebufferObject, buffer, drawbuffer, depth, stencil); } + // Which buffers the integer clears accept is narrower than the float one, and differs between + // them: signed values can clear COLOR or STENCIL, unsigned only COLOR (GL 4.6 core 17.4.3.1). + // Only the colour buffer is indexed; a stencil clear names the single stencil buffer, so any + // drawbuffer other than 0 is out of range rather than merely unused. + Bool ValidateNamedClearIntegerv_State(GLenum buffer, GLint drawbuffer, const void* value, Bool allowStencil, + const char* caller) { + if (!value) { + MG_State::pGLContext->RecordError( + ErrorCode::InvalidValue, + MakeUnique("MG_Impl/GLImpl", caller, "value pointer cannot be null.")); + return false; + } + + if (buffer == GL_COLOR) { + if (drawbuffer < 0 || + drawbuffer >= static_cast(MG_State::GLState::FramebufferObject::MAX_DRAW_BUFFERS)) { + MG_State::pGLContext->RecordError( + ErrorCode::InvalidValue, + MakeUnique("MG_Impl/GLImpl", caller, "color drawbuffer index is out of range.")); + return false; + } + return true; + } + + if (buffer == GL_STENCIL && allowStencil) { + if (drawbuffer != 0) { + MG_State::pGLContext->RecordError( + ErrorCode::InvalidValue, + MakeUnique("MG_Impl/GLImpl", caller, "stencil clear requires drawbuffer 0.")); + return false; + } + return true; + } + + MG_State::pGLContext->RecordError( + ErrorCode::InvalidEnum, + MakeUnique( + "MG_Impl/GLImpl", caller, + std::format("buffer {} is not accepted for this clear.", MG_Util::ConvertGLEnumToString(buffer)))); + return false; + } + + void ClearNamedFramebufferiv_State(GLuint framebuffer, GLenum buffer, GLint drawbuffer, const GLint* value) { + auto framebufferObject = GetFramebufferObjectForNamedClear(framebuffer, "ClearNamedFramebufferiv_State"); + if (!framebufferObject) return; + if (!ValidateNamedClearIntegerv_State(buffer, drawbuffer, value, true, "ClearNamedFramebufferiv_State")) { + return; + } + ClearNamedFramebufferiv_Backend(framebufferObject, buffer, drawbuffer, value); + } + + void ClearNamedFramebufferuiv_State(GLuint framebuffer, GLenum buffer, GLint drawbuffer, const GLuint* value) { + auto framebufferObject = GetFramebufferObjectForNamedClear(framebuffer, "ClearNamedFramebufferuiv_State"); + if (!framebufferObject) return; + if (!ValidateNamedClearIntegerv_State(buffer, drawbuffer, value, false, "ClearNamedFramebufferuiv_State")) { + return; + } + ClearNamedFramebufferuiv_Backend(framebufferObject, buffer, drawbuffer, value); + } + void DeleteRenderbuffers_State(GLsizei n, const GLuint* renderbuffers) { if (n < 0) { MG_State::pGLContext->RecordError( @@ -2273,6 +2353,14 @@ namespace MobileGL::MG_Impl::GLImpl { ClearBufferiv_Backend(buffer, drawbuffer, value); } + void ClearNamedFramebufferiv(GLuint framebuffer, GLenum buffer, GLint drawbuffer, const GLint* value) { + ClearNamedFramebufferiv_State(framebuffer, buffer, drawbuffer, value); + } + + void ClearNamedFramebufferuiv(GLuint framebuffer, GLenum buffer, GLint drawbuffer, const GLuint* value) { + ClearNamedFramebufferuiv_State(framebuffer, buffer, drawbuffer, value); + } + void SampleMaski(GLuint maskNumber, GLbitfield mask) { SampleMaski_State(maskNumber, mask); } diff --git a/MobileGL/MG_Impl/GLImpl/Framebuffer/GL_Framebuffer.h b/MobileGL/MG_Impl/GLImpl/Framebuffer/GL_Framebuffer.h index 33b58f26..4b3d90cc 100644 --- a/MobileGL/MG_Impl/GLImpl/Framebuffer/GL_Framebuffer.h +++ b/MobileGL/MG_Impl/GLImpl/Framebuffer/GL_Framebuffer.h @@ -58,6 +58,8 @@ namespace MobileGL::MG_Impl::GLImpl { void NamedFramebufferReadBuffer(GLuint framebuffer, GLenum src); void ClearNamedFramebufferfv(GLuint framebuffer, GLenum buffer, GLint drawbuffer, const GLfloat* value); void ClearNamedFramebufferfi(GLuint framebuffer, GLenum buffer, GLint drawbuffer, GLfloat depth, GLint stencil); + void ClearNamedFramebufferiv(GLuint framebuffer, GLenum buffer, GLint drawbuffer, const GLint* value); + void ClearNamedFramebufferuiv(GLuint framebuffer, GLenum buffer, GLint drawbuffer, const GLuint* value); GLenum CheckNamedFramebufferStatus(GLuint framebuffer, GLenum target); void GetNamedFramebufferAttachmentParameteriv(GLuint framebuffer, GLenum attachment, GLenum pname, GLint* params); void BlitNamedFramebuffer(GLuint readFramebuffer, GLuint drawFramebuffer, GLint srcX0, GLint srcY0, GLint srcX1,