diff --git a/MobileGL/MG_Impl/GLImpl/Exporting/Definitions.cpp b/MobileGL/MG_Impl/GLImpl/Exporting/Definitions.cpp index a175509b..afe366d4 100644 --- a/MobileGL/MG_Impl/GLImpl/Exporting/Definitions.cpp +++ b/MobileGL/MG_Impl/GLImpl/Exporting/Definitions.cpp @@ -310,8 +310,8 @@ DECLARE_GL_FUNCTION_HEAD(void, DispatchCompute, GLuint num_groups_x, GLuint num_ DECLARE_GL_FUNCTION_HEAD(void, DispatchComputeIndirect, GLintptr indirect) DECLARE_GL_FUNCTION_END_NO_RETURN(void, DispatchComputeIndirect, indirect) DECLARE_GL_FUNCTION_HEAD(void, DrawArraysIndirect, GLenum mode, const void* indirect) DECLARE_GL_FUNCTION_END_NO_RETURN(void, DrawArraysIndirect, mode, indirect) DECLARE_GL_FUNCTION_HEAD(void, DrawElementsIndirect, GLenum mode, GLenum type, const void* indirect) DECLARE_GL_FUNCTION_END_NO_RETURN(void, DrawElementsIndirect, mode, type, indirect) -DECLARE_GL_FUNCTION_STUB_HEAD(void, FramebufferParameteri, GLenum target, GLenum pname, GLint param) DECLARE_GL_FUNCTION_STUB_END_NO_RETURN(void, FramebufferParameteri, target, pname, param) -DECLARE_GL_FUNCTION_STUB_HEAD(void, GetFramebufferParameteriv, GLenum target, GLenum pname, GLint* params) DECLARE_GL_FUNCTION_STUB_END_NO_RETURN(void, GetFramebufferParameteriv, target, pname, params) +DECLARE_GL_FUNCTION_HEAD(void, FramebufferParameteri, GLenum target, GLenum pname, GLint param) DECLARE_GL_FUNCTION_END_NO_RETURN(void, FramebufferParameteri, target, pname, param) +DECLARE_GL_FUNCTION_HEAD(void, GetFramebufferParameteriv, GLenum target, GLenum pname, GLint* params) DECLARE_GL_FUNCTION_END_NO_RETURN(void, GetFramebufferParameteriv, target, pname, params) DECLARE_GL_FUNCTION_HEAD(void, GetProgramInterfaceiv, GLuint program, GLenum programInterface, GLenum pname, GLint* params) DECLARE_GL_FUNCTION_END_NO_RETURN(void, GetProgramInterfaceiv, program, programInterface, pname, params) DECLARE_GL_FUNCTION_HEAD(GLuint, GetProgramResourceIndex, GLuint program, GLenum programInterface, const GLchar* name) DECLARE_GL_FUNCTION_END(GLuint, GetProgramResourceIndex, program, programInterface, name) DECLARE_GL_FUNCTION_HEAD(void, GetProgramResourceName, GLuint program, GLenum programInterface, GLuint index, GLsizei bufSize, GLsizei* length, GLchar* name) DECLARE_GL_FUNCTION_END_NO_RETURN(void, GetProgramResourceName, program, programInterface, index, bufSize, length, name) @@ -1028,7 +1028,7 @@ DECLARE_GL_FUNCTION_HEAD(void, GetNamedBufferPointerv, GLuint buffer, GLenum pna DECLARE_GL_FUNCTION_HEAD(void, GetNamedBufferSubData, GLuint buffer, GLintptr offset, GLsizeiptr size, void* data) DECLARE_GL_FUNCTION_END_NO_RETURN(void, GetNamedBufferSubData, buffer, offset, size, data) DECLARE_GL_FUNCTION_HEAD(void, CreateFramebuffers, GLsizei n, GLuint* framebuffers) DECLARE_GL_FUNCTION_END_NO_RETURN(void, CreateFramebuffers, n, framebuffers) DECLARE_GL_FUNCTION_HEAD(void, NamedFramebufferRenderbuffer, GLuint framebuffer, GLenum attachment, GLenum renderbuffertarget, GLuint renderbuffer) DECLARE_GL_FUNCTION_END_NO_RETURN(void, NamedFramebufferRenderbuffer, framebuffer, attachment, renderbuffertarget, renderbuffer) -DECLARE_GL_FUNCTION_STUB_HEAD(void, NamedFramebufferParameteri, GLuint framebuffer, GLenum pname, GLint param) DECLARE_GL_FUNCTION_STUB_END_NO_RETURN(void, NamedFramebufferParameteri, framebuffer, pname, param) +DECLARE_GL_FUNCTION_HEAD(void, NamedFramebufferParameteri, GLuint framebuffer, GLenum pname, GLint param) DECLARE_GL_FUNCTION_END_NO_RETURN(void, NamedFramebufferParameteri, framebuffer, pname, param) DECLARE_GL_FUNCTION_HEAD(void, NamedFramebufferTexture, GLuint framebuffer, GLenum attachment, GLuint texture, GLint level) DECLARE_GL_FUNCTION_END_NO_RETURN(void, NamedFramebufferTexture, framebuffer, attachment, texture, level) DECLARE_GL_FUNCTION_HEAD(void, NamedFramebufferTextureLayer, GLuint framebuffer, GLenum attachment, GLuint texture, GLint level, GLint layer) DECLARE_GL_FUNCTION_END_NO_RETURN(void, NamedFramebufferTextureLayer, framebuffer, attachment, texture, level, layer) DECLARE_GL_FUNCTION_HEAD(void, NamedFramebufferDrawBuffer, GLuint framebuffer, GLenum buf) DECLARE_GL_FUNCTION_END_NO_RETURN(void, NamedFramebufferDrawBuffer, framebuffer, buf) @@ -1042,7 +1042,7 @@ DECLARE_GL_FUNCTION_HEAD(void, ClearNamedFramebufferfv, GLuint framebuffer, GLen 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) DECLARE_GL_FUNCTION_HEAD(GLenum, CheckNamedFramebufferStatus, GLuint framebuffer, GLenum target) DECLARE_GL_FUNCTION_END(GLenum, CheckNamedFramebufferStatus, framebuffer, target) -DECLARE_GL_FUNCTION_STUB_HEAD(void, GetNamedFramebufferParameteriv, GLuint framebuffer, GLenum pname, GLint* param) DECLARE_GL_FUNCTION_STUB_END_NO_RETURN(void, GetNamedFramebufferParameteriv, framebuffer, pname, param) +DECLARE_GL_FUNCTION_HEAD(void, GetNamedFramebufferParameteriv, GLuint framebuffer, GLenum pname, GLint* param) DECLARE_GL_FUNCTION_END_NO_RETURN(void, GetNamedFramebufferParameteriv, framebuffer, pname, param) DECLARE_GL_FUNCTION_HEAD(void, GetNamedFramebufferAttachmentParameteriv, GLuint framebuffer, GLenum attachment, GLenum pname, GLint* params) DECLARE_GL_FUNCTION_END_NO_RETURN(void, GetNamedFramebufferAttachmentParameteriv, framebuffer, attachment, pname, params) DECLARE_GL_FUNCTION_HEAD(void, CreateRenderbuffers, GLsizei n, GLuint* renderbuffers) DECLARE_GL_FUNCTION_END_NO_RETURN(void, CreateRenderbuffers, n, renderbuffers) DECLARE_GL_FUNCTION_HEAD(void, NamedRenderbufferStorage, GLuint renderbuffer, GLenum internalformat, GLsizei width, GLsizei height) DECLARE_GL_FUNCTION_END_NO_RETURN(void, NamedRenderbufferStorage, renderbuffer, internalformat, width, height) diff --git a/MobileGL/MG_Impl/GLImpl/Framebuffer/GL_Framebuffer.cpp b/MobileGL/MG_Impl/GLImpl/Framebuffer/GL_Framebuffer.cpp index 95d1e1bc..7f8312b9 100644 --- a/MobileGL/MG_Impl/GLImpl/Framebuffer/GL_Framebuffer.cpp +++ b/MobileGL/MG_Impl/GLImpl/Framebuffer/GL_Framebuffer.cpp @@ -8,6 +8,7 @@ #include "GL_Framebuffer.h" #include "Validators.h" +#include #include "Config.h" #include #include @@ -2131,6 +2132,124 @@ namespace MobileGL::MG_Impl::GLImpl { return GL_FRAMEBUFFER_COMPLETE; } + // GL_ARB_framebuffer_no_attachments plus the queryable framebuffer state of GL 4.6 core 9.2.3. + // The DEFAULT_* half is real state on the framebuffer object; the rest is derived from the + // attachments, and matches what glGetIntegerv answers for the bound framebuffer. + void GetFramebufferParameteriv_Object(const SharedPtr& framebufferObject, + GLenum pname, GLint* params, const char* caller) { + if (params == nullptr) return; + if (!FramebufferImpl::ValidateFramebufferParameterPname(pname, framebufferObject->IsDefaultFramebuffer(), + /*forSetter=*/false, caller)) { + return; + } + + const auto resolveSampleCount = [&]() { + GLint maxSamples = 0; + for (const auto& attachment : framebufferObject->GetAllAttachmentObjects()) { + if (attachment.IsRenderbuffer() && attachment.GetRenderbuffer()) { + maxSamples = std::max(maxSamples, static_cast(attachment.GetRenderbuffer()->GetSamples())); + } else if (attachment.IsTexture() && attachment.GetTexture()) { + maxSamples = std::max(maxSamples, static_cast(attachment.GetTexture()->GetSamples())); + } + } + return maxSamples; + }; + + switch (pname) { + case GL_FRAMEBUFFER_DEFAULT_WIDTH: + *params = framebufferObject->GetDefaultWidth(); + break; + case GL_FRAMEBUFFER_DEFAULT_HEIGHT: + *params = framebufferObject->GetDefaultHeight(); + break; + case GL_FRAMEBUFFER_DEFAULT_LAYERS: + *params = framebufferObject->GetDefaultLayers(); + break; + case GL_FRAMEBUFFER_DEFAULT_SAMPLES: + *params = framebufferObject->GetDefaultSamples(); + break; + case GL_FRAMEBUFFER_DEFAULT_FIXED_SAMPLE_LOCATIONS: + *params = framebufferObject->GetDefaultFixedSampleLocations() ? GL_TRUE : GL_FALSE; + break; + case GL_SAMPLES: + *params = resolveSampleCount(); + break; + case GL_SAMPLE_BUFFERS: + *params = resolveSampleCount() > 0 ? 1 : 0; + break; + case GL_IMPLEMENTATION_COLOR_READ_FORMAT: + case GL_IMPLEMENTATION_COLOR_READ_TYPE: { + const auto readBuffer = framebufferObject->GetReadBuffer(); + TextureInternalFormat internalFormat = TextureInternalFormat::Unknown; + if (readBuffer != FramebufferAttachmentType::None) { + const auto& attachment = framebufferObject->GetAttachment(readBuffer); + if (attachment.IsTexture() && attachment.GetTexture()) { + internalFormat = attachment.GetTexture()->GetFormat(); + } else if (attachment.IsRenderbuffer() && attachment.GetRenderbuffer()) { + internalFormat = attachment.GetRenderbuffer()->GetInternalFormat(); + } + } + if (internalFormat == TextureInternalFormat::Unknown) { + *params = 0; + break; + } + const GLenum glInternalFormat = MG_Util::ConvertTextureInternalFormatToGLEnum(internalFormat); + GLenum normalizedInternalFormat = glInternalFormat; + GLenum format = GL_RGBA; + GLenum type = GL_UNSIGNED_BYTE; + MG_Util::TextureFormatProcessor::NormalizePixelFormat(glInternalFormat, PixelFormatNormalizeOptionBit::None, + &normalizedInternalFormat, &format, &type); + *params = static_cast(pname == GL_IMPLEMENTATION_COLOR_READ_FORMAT ? format : type); + break; + } + case GL_DOUBLEBUFFER: + // Only the window-system surface is ever double buffered; a framebuffer object never is. + *params = framebufferObject->IsDefaultFramebuffer() ? GL_TRUE : GL_FALSE; + break; + case GL_STEREO: + // Stereo surfaces are not exposed, matching what glGetIntegerv reports. + *params = GL_FALSE; + break; + default: + break; + } + } + + void FramebufferParameteri_Object(const SharedPtr& framebufferObject, + GLenum pname, GLint param, const char* caller) { + if (!FramebufferImpl::ValidateFramebufferParameterPname(pname, framebufferObject->IsDefaultFramebuffer(), + /*forSetter=*/true, caller)) { + return; + } + if (pname != GL_FRAMEBUFFER_DEFAULT_FIXED_SAMPLE_LOCATIONS && param < 0) { + MG_State::pGLContext->RecordError( + ErrorCode::InvalidValue, + MakeUnique("MG_Impl/GLImpl", caller, + "Framebuffer default parameters must be non-negative.")); + return; + } + + switch (pname) { + case GL_FRAMEBUFFER_DEFAULT_WIDTH: + framebufferObject->SetDefaultWidth(param); + break; + case GL_FRAMEBUFFER_DEFAULT_HEIGHT: + framebufferObject->SetDefaultHeight(param); + break; + case GL_FRAMEBUFFER_DEFAULT_LAYERS: + framebufferObject->SetDefaultLayers(param); + break; + case GL_FRAMEBUFFER_DEFAULT_SAMPLES: + framebufferObject->SetDefaultSamples(param); + break; + case GL_FRAMEBUFFER_DEFAULT_FIXED_SAMPLE_LOCATIONS: + framebufferObject->SetDefaultFixedSampleLocations(param != GL_FALSE); + break; + default: + break; + } + } + void GetFramebufferAttachmentParameteriv_Object( const SharedPtr& framebufferObject, GLenum attachment, GLenum pname, GLint* params, const char* caller) { @@ -2250,6 +2369,54 @@ namespace MobileGL::MG_Impl::GLImpl { "GetNamedFramebufferAttachmentParameteriv_State"); } + // The by-target forms resolve the binding; the by-name forms take zero as the default + // framebuffer, exactly as the other DSA framebuffer entry points do (GL 4.6 core 9.2.3). + void GetFramebufferParameteriv_State(GLenum target, GLenum pname, GLint* params) { + if (target == GL_FRAMEBUFFER) target = GL_DRAW_FRAMEBUFFER; + const auto framebufferTarget = MG_Util::ConvertGLEnumToFramebufferTarget(target); + if (!FramebufferImpl::ValidateFramebufferTarget(framebufferTarget)) return; + auto& framebufferObject = MG_State::pGLContext->GetFramebufferBindingSlot(framebufferTarget).GetBoundObject(); + if (!framebufferObject) { + MG_State::pGLContext->RecordError( + ErrorCode::InvalidOperation, + MakeUnique("MG_Impl/GLImpl", "GetFramebufferParameteriv_State", + "Framebuffer target is bound to no framebuffer object.")); + return; + } + GetFramebufferParameteriv_Object(framebufferObject, pname, params, "GetFramebufferParameteriv_State"); + } + + void FramebufferParameteri_State(GLenum target, GLenum pname, GLint param) { + if (target == GL_FRAMEBUFFER) target = GL_DRAW_FRAMEBUFFER; + const auto framebufferTarget = MG_Util::ConvertGLEnumToFramebufferTarget(target); + if (!FramebufferImpl::ValidateFramebufferTarget(framebufferTarget)) return; + auto& framebufferObject = MG_State::pGLContext->GetFramebufferBindingSlot(framebufferTarget).GetBoundObject(); + if (!framebufferObject) { + MG_State::pGLContext->RecordError( + ErrorCode::InvalidOperation, + MakeUnique("MG_Impl/GLImpl", "FramebufferParameteri_State", + "Framebuffer target is bound to no framebuffer object.")); + return; + } + FramebufferParameteri_Object(framebufferObject, pname, param, "FramebufferParameteri_State"); + } + + void GetNamedFramebufferParameteriv_State(GLuint framebuffer, GLenum pname, GLint* params) { + auto framebufferObject = framebuffer == 0 + ? FramebufferImpl::pDefaultFramebufferInfo->defaultFBO + : GetNamedFramebufferObject_State(framebuffer, "GetNamedFramebufferParameteriv_State"); + if (!framebufferObject) return; + GetFramebufferParameteriv_Object(framebufferObject, pname, params, "GetNamedFramebufferParameteriv_State"); + } + + void NamedFramebufferParameteri_State(GLuint framebuffer, GLenum pname, GLint param) { + auto framebufferObject = framebuffer == 0 + ? FramebufferImpl::pDefaultFramebufferInfo->defaultFBO + : GetNamedFramebufferObject_State(framebuffer, "NamedFramebufferParameteri_State"); + if (!framebufferObject) return; + FramebufferParameteri_Object(framebufferObject, pname, param, "NamedFramebufferParameteri_State"); + } + void BlitNamedFramebuffer_State(GLuint readFramebuffer, GLuint drawFramebuffer, GLint srcX0, GLint srcY0, GLint srcX1, GLint srcY1, GLint dstX0, GLint dstY0, GLint dstX1, GLint dstY1, GLbitfield mask, GLenum filter) { @@ -2896,6 +3063,22 @@ namespace MobileGL::MG_Impl::GLImpl { return CheckNamedFramebufferStatus_State(framebuffer, target); } + void GetFramebufferParameteriv(GLenum target, GLenum pname, GLint* params) { + GetFramebufferParameteriv_State(target, pname, params); + } + + void FramebufferParameteri(GLenum target, GLenum pname, GLint param) { + FramebufferParameteri_State(target, pname, param); + } + + void GetNamedFramebufferParameteriv(GLuint framebuffer, GLenum pname, GLint* params) { + GetNamedFramebufferParameteriv_State(framebuffer, pname, params); + } + + void NamedFramebufferParameteri(GLuint framebuffer, GLenum pname, GLint param) { + NamedFramebufferParameteri_State(framebuffer, pname, param); + } + void GetNamedFramebufferAttachmentParameteriv(GLuint framebuffer, GLenum attachment, GLenum pname, GLint* params) { GetNamedFramebufferAttachmentParameteriv_State(framebuffer, attachment, pname, params); } diff --git a/MobileGL/MG_Impl/GLImpl/Framebuffer/GL_Framebuffer.h b/MobileGL/MG_Impl/GLImpl/Framebuffer/GL_Framebuffer.h index 696132b2..c91a496c 100644 --- a/MobileGL/MG_Impl/GLImpl/Framebuffer/GL_Framebuffer.h +++ b/MobileGL/MG_Impl/GLImpl/Framebuffer/GL_Framebuffer.h @@ -67,6 +67,10 @@ namespace MobileGL::MG_Impl::GLImpl { 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 GetFramebufferParameteriv(GLenum target, GLenum pname, GLint* params); + void FramebufferParameteri(GLenum target, GLenum pname, GLint param); + void GetNamedFramebufferParameteriv(GLuint framebuffer, GLenum pname, GLint* params); + void NamedFramebufferParameteri(GLuint framebuffer, GLenum pname, GLint param); void GetNamedFramebufferAttachmentParameteriv(GLuint framebuffer, GLenum attachment, GLenum pname, GLint* params); void BlitNamedFramebuffer(GLuint readFramebuffer, GLuint drawFramebuffer, GLint srcX0, GLint srcY0, GLint srcX1, GLint srcY1, GLint dstX0, GLint dstY0, GLint dstX1, GLint dstY1, GLbitfield mask, diff --git a/MobileGL/MG_Impl/GLImpl/Framebuffer/Validators.cpp b/MobileGL/MG_Impl/GLImpl/Framebuffer/Validators.cpp index 84738b2a..fa05e439 100644 --- a/MobileGL/MG_Impl/GLImpl/Framebuffer/Validators.cpp +++ b/MobileGL/MG_Impl/GLImpl/Framebuffer/Validators.cpp @@ -119,6 +119,58 @@ namespace MobileGL::MG_Impl::GLImpl::FramebufferImpl { return false; } + Bool ValidateFramebufferParameterPname(GLenum pname, Bool isDefaultFramebuffer, Bool forSetter, + const char* caller) { + Bool isDefaultParameter = false; + switch (pname) { + case GL_FRAMEBUFFER_DEFAULT_WIDTH: + case GL_FRAMEBUFFER_DEFAULT_HEIGHT: + case GL_FRAMEBUFFER_DEFAULT_LAYERS: + case GL_FRAMEBUFFER_DEFAULT_SAMPLES: + case GL_FRAMEBUFFER_DEFAULT_FIXED_SAMPLE_LOCATIONS: + isDefaultParameter = true; + break; + case GL_DOUBLEBUFFER: + case GL_IMPLEMENTATION_COLOR_READ_FORMAT: + case GL_IMPLEMENTATION_COLOR_READ_TYPE: + case GL_SAMPLES: + case GL_SAMPLE_BUFFERS: + case GL_STEREO: + // Queryable only; glFramebufferParameteri sets none of these. + if (forSetter) { + MG_State::pGLContext->RecordError( + ErrorCode::InvalidEnum, + MakeUnique( + "MG_Impl/GLImpl/FramebufferImpl", caller, + std::format("pname {} is not settable on a framebuffer.", + MG_Util::ConvertGLEnumToString(pname)))); + return false; + } + break; + default: + MG_State::pGLContext->RecordError( + ErrorCode::InvalidEnum, + MakeUnique( + "MG_Impl/GLImpl/FramebufferImpl", caller, + std::format("pname {} is not a framebuffer parameter.", + MG_Util::ConvertGLEnumToString(pname)))); + return false; + } + + // The default framebuffer has no DEFAULT_* state of its own - its shape comes from the + // surface - so those names are accepted enums it simply cannot answer or accept. + if (isDefaultFramebuffer && isDefaultParameter) { + MG_State::pGLContext->RecordError( + ErrorCode::InvalidOperation, + MakeUnique( + "MG_Impl/GLImpl/FramebufferImpl", caller, + std::format("pname {} does not apply to the default framebuffer.", + MG_Util::ConvertGLEnumToString(pname)))); + return false; + } + return true; + } + Bool ValidateReadFramebufferForCopy(const char* caller) { auto& framebufferObject = MG_State::pGLContext->GetFramebufferBindingSlot(FramebufferTarget::Read).GetBoundObject(); diff --git a/MobileGL/MG_Impl/GLImpl/Framebuffer/Validators.h b/MobileGL/MG_Impl/GLImpl/Framebuffer/Validators.h index bfbd51b5..d4215c57 100644 --- a/MobileGL/MG_Impl/GLImpl/Framebuffer/Validators.h +++ b/MobileGL/MG_Impl/GLImpl/Framebuffer/Validators.h @@ -25,4 +25,10 @@ namespace MobileGL::MG_Impl::GLImpl::FramebufferImpl { // not be multisampled. Incompleteness is INVALID_FRAMEBUFFER_OPERATION, the other two are // INVALID_OPERATION. Bool ValidateReadFramebufferForCopy(const char* caller); + // The pname sets of glGet/FramebufferParameteri (GL 4.6 core 9.2.3). Order matters and is part + // of the contract: a name outside the table is INVALID_ENUM, and only then is a name that the + // DEFAULT framebuffer does not answer INVALID_OPERATION. Testing the framebuffer kind first + // would turn GL_FRAMEBUFFER_DEFAULT_WIDTH on framebuffer zero into the wrong error. + Bool ValidateFramebufferParameterPname(GLenum pname, Bool isDefaultFramebuffer, Bool forSetter, + const char* caller); } // namespace MobileGL::MG_Impl::GLImpl::FramebufferImpl diff --git a/MobileGL/MG_State/GLState/FramebufferState/FramebufferObject.cpp b/MobileGL/MG_State/GLState/FramebufferState/FramebufferObject.cpp index 1988b9e2..abedbf79 100644 --- a/MobileGL/MG_State/GLState/FramebufferState/FramebufferObject.cpp +++ b/MobileGL/MG_State/GLState/FramebufferState/FramebufferObject.cpp @@ -185,6 +185,20 @@ namespace MobileGL::MG_State::GLState { return m_externalIndex; } +#define MOBILEGL_DEFINE_FRAMEBUFFER_DEFAULT_SETTER(name, member, type) \ + void FramebufferObject::Set##name(type value) { \ + if (member == value) return; \ + member = value; \ + ++m_objectVersion; \ + } + + MOBILEGL_DEFINE_FRAMEBUFFER_DEFAULT_SETTER(DefaultWidth, m_defaultWidth, Int) + MOBILEGL_DEFINE_FRAMEBUFFER_DEFAULT_SETTER(DefaultHeight, m_defaultHeight, Int) + MOBILEGL_DEFINE_FRAMEBUFFER_DEFAULT_SETTER(DefaultLayers, m_defaultLayers, Int) + MOBILEGL_DEFINE_FRAMEBUFFER_DEFAULT_SETTER(DefaultSamples, m_defaultSamples, Int) + MOBILEGL_DEFINE_FRAMEBUFFER_DEFAULT_SETTER(DefaultFixedSampleLocations, m_defaultFixedSampleLocations, Bool) +#undef MOBILEGL_DEFINE_FRAMEBUFFER_DEFAULT_SETTER + void FramebufferObject::BumpAttachmentVersion(FramebufferAttachmentType type) { ++m_attachmentVersions[static_cast(type)]; ++m_objectVersion; diff --git a/MobileGL/MG_State/GLState/FramebufferState/FramebufferObject.h b/MobileGL/MG_State/GLState/FramebufferState/FramebufferObject.h index 3f699be4..f526891b 100644 --- a/MobileGL/MG_State/GLState/FramebufferState/FramebufferObject.h +++ b/MobileGL/MG_State/GLState/FramebufferState/FramebufferObject.h @@ -129,6 +129,19 @@ namespace MobileGL { void SetReadBuffer(FramebufferAttachmentType buf); FramebufferAttachmentType GetReadBuffer() const { return m_readBuffer; } + // GL_ARB_framebuffer_no_attachments state (GL 4.6 core table 23.24). The shape a + // framebuffer with no attachments would rasterize at; all zero / FALSE until set. + Int GetDefaultWidth() const { return m_defaultWidth; } + Int GetDefaultHeight() const { return m_defaultHeight; } + Int GetDefaultLayers() const { return m_defaultLayers; } + Int GetDefaultSamples() const { return m_defaultSamples; } + Bool GetDefaultFixedSampleLocations() const { return m_defaultFixedSampleLocations; } + void SetDefaultWidth(Int value); + void SetDefaultHeight(Int value); + void SetDefaultLayers(Int value); + void SetDefaultSamples(Int value); + void SetDefaultFixedSampleLocations(Bool value); + FramebufferAttachmentVersionArray GetAllFramebufferAttachmentVersions() const { return m_attachmentVersions; } @@ -148,6 +161,12 @@ namespace MobileGL { FramebufferAttachmentArray m_drawBuffers; // Probably no versioning needed for this, just check equality FramebufferAttachmentType m_readBuffer = FramebufferAttachmentType::None; + Int m_defaultWidth = 0; + Int m_defaultHeight = 0; + Int m_defaultLayers = 0; + Int m_defaultSamples = 0; + Bool m_defaultFixedSampleLocations = false; + // This version will bump when draw/read buffer changes (by `glDrawBuffer(s)`/`glReadBuffer`) Uint16 m_objectVersion = 0; };