mirror of
https://github.com/MobileGL-Dev/MobileGL
synced 2026-09-07 19:58:32 +09:00
[Feat] (MG_Impl, MG_State): implement the framebuffer parameter getters and setters
glFramebufferParameteri, glGetFramebufferParameteriv and their two by-name siblings were all export stubs - the GL_ARB_framebuffer_no_attachments entry points. The stub raises no error and writes nothing, so direct_state_access.framebuffers_get_parameter_errors saw GL_NO_ERROR for all three conditions it checks. FramebufferObject gains the five DEFAULT_* parameters as real state, initialised to GL 4.6 core table 23.24 and bumping the object version on a write like the read buffer does. The getter answers those plus the six derived names - GL_SAMPLES and GL_SAMPLE_BUFFERS from the attachments' sample counts, GL_IMPLEMENTATION_COLOR_READ_FORMAT/_TYPE from the read buffer's internal format, GL_DOUBLEBUFFER true only for the window-system framebuffer, GL_STEREO false because stereo surfaces are not exposed - which is what glGetIntegerv already reports for the bound framebuffer. The pname rules live in ValidateFramebufferParameterPname, and their ORDER is load-bearing: a name outside the table is INVALID_ENUM, and only a name that IS in the table but that the default framebuffer cannot answer is INVALID_OPERATION. Testing the framebuffer kind first would answer INVALID_ENUM for GL_FRAMEBUFFER_DEFAULT_WIDTH on framebuffer zero, which is exactly the third thing the case checks. The by-name forms take zero as the default framebuffer, like the other DSA framebuffer entry points. Rendering to a framebuffer with no attachments is deliberately NOT enabled by this: CheckCompleteness still reports INCOMPLETE_MISSING_ATTACHMENT, because no backend can rasterize one. The state is real and the queries are honest; the draw path is a separate piece of work. Takes framebuffers_get_parameter_errors from failing to passing on both backends, with framebuffers_get_parameters - which passed only because both getters were stubs leaving the CTS's zero-initialised comparands untouched - still passing.
This commit is contained in:
@@ -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)
|
||||
|
||||
@@ -8,6 +8,7 @@
|
||||
|
||||
#include "GL_Framebuffer.h"
|
||||
#include "Validators.h"
|
||||
#include <MG_Util/Texture/TextureFormatProcessor.h>
|
||||
#include "Config.h"
|
||||
#include <MG_Backend/BackendObjects.h>
|
||||
#include <MG_Util/Metrics/TextureMetrics.h>
|
||||
@@ -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<MG_State::GLState::FramebufferObject>& 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<GLint>(attachment.GetRenderbuffer()->GetSamples()));
|
||||
} else if (attachment.IsTexture() && attachment.GetTexture()) {
|
||||
maxSamples = std::max(maxSamples, static_cast<GLint>(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<GLint>(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<MG_State::GLState::FramebufferObject>& 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<GenericErrorInfo>("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<MG_State::GLState::FramebufferObject>& 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<GenericErrorInfo>("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<GenericErrorInfo>("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);
|
||||
}
|
||||
|
||||
@@ -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,
|
||||
|
||||
@@ -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<GenericErrorInfo>(
|
||||
"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<GenericErrorInfo>(
|
||||
"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<GenericErrorInfo>(
|
||||
"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();
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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<SizeT>(type)];
|
||||
++m_objectVersion;
|
||||
|
||||
@@ -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;
|
||||
};
|
||||
|
||||
Reference in New Issue
Block a user