mirror of
https://github.com/MobileGL-Dev/MobileGL
synced 2026-09-12 06:08:30 +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, 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, 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_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_HEAD(void, FramebufferParameteri, GLenum target, GLenum pname, GLint param) DECLARE_GL_FUNCTION_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, 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(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(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)
|
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, 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, 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_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, 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, 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)
|
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, 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(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_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, 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, 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)
|
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 "GL_Framebuffer.h"
|
||||||
#include "Validators.h"
|
#include "Validators.h"
|
||||||
|
#include <MG_Util/Texture/TextureFormatProcessor.h>
|
||||||
#include "Config.h"
|
#include "Config.h"
|
||||||
#include <MG_Backend/BackendObjects.h>
|
#include <MG_Backend/BackendObjects.h>
|
||||||
#include <MG_Util/Metrics/TextureMetrics.h>
|
#include <MG_Util/Metrics/TextureMetrics.h>
|
||||||
@@ -2131,6 +2132,124 @@ namespace MobileGL::MG_Impl::GLImpl {
|
|||||||
return GL_FRAMEBUFFER_COMPLETE;
|
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(
|
void GetFramebufferAttachmentParameteriv_Object(
|
||||||
const SharedPtr<MG_State::GLState::FramebufferObject>& framebufferObject, GLenum attachment, GLenum pname,
|
const SharedPtr<MG_State::GLState::FramebufferObject>& framebufferObject, GLenum attachment, GLenum pname,
|
||||||
GLint* params, const char* caller) {
|
GLint* params, const char* caller) {
|
||||||
@@ -2250,6 +2369,54 @@ namespace MobileGL::MG_Impl::GLImpl {
|
|||||||
"GetNamedFramebufferAttachmentParameteriv_State");
|
"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,
|
void BlitNamedFramebuffer_State(GLuint readFramebuffer, GLuint drawFramebuffer, GLint srcX0, GLint srcY0,
|
||||||
GLint srcX1, GLint srcY1, GLint dstX0, GLint dstY0, GLint dstX1, GLint dstY1,
|
GLint srcX1, GLint srcY1, GLint dstX0, GLint dstY0, GLint dstX1, GLint dstY1,
|
||||||
GLbitfield mask, GLenum filter) {
|
GLbitfield mask, GLenum filter) {
|
||||||
@@ -2896,6 +3063,22 @@ namespace MobileGL::MG_Impl::GLImpl {
|
|||||||
return CheckNamedFramebufferStatus_State(framebuffer, target);
|
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) {
|
void GetNamedFramebufferAttachmentParameteriv(GLuint framebuffer, GLenum attachment, GLenum pname, GLint* params) {
|
||||||
GetNamedFramebufferAttachmentParameteriv_State(framebuffer, attachment, pname, 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 ClearNamedFramebufferiv(GLuint framebuffer, GLenum buffer, GLint drawbuffer, const GLint* value);
|
||||||
void ClearNamedFramebufferuiv(GLuint framebuffer, GLenum buffer, GLint drawbuffer, const GLuint* value);
|
void ClearNamedFramebufferuiv(GLuint framebuffer, GLenum buffer, GLint drawbuffer, const GLuint* value);
|
||||||
GLenum CheckNamedFramebufferStatus(GLuint framebuffer, GLenum target);
|
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 GetNamedFramebufferAttachmentParameteriv(GLuint framebuffer, GLenum attachment, GLenum pname, GLint* params);
|
||||||
void BlitNamedFramebuffer(GLuint readFramebuffer, GLuint drawFramebuffer, GLint srcX0, GLint srcY0, GLint srcX1,
|
void BlitNamedFramebuffer(GLuint readFramebuffer, GLuint drawFramebuffer, GLint srcX0, GLint srcY0, GLint srcX1,
|
||||||
GLint srcY1, GLint dstX0, GLint dstY0, GLint dstX1, GLint dstY1, GLbitfield mask,
|
GLint srcY1, GLint dstX0, GLint dstY0, GLint dstX1, GLint dstY1, GLbitfield mask,
|
||||||
|
|||||||
@@ -119,6 +119,58 @@ namespace MobileGL::MG_Impl::GLImpl::FramebufferImpl {
|
|||||||
return false;
|
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) {
|
Bool ValidateReadFramebufferForCopy(const char* caller) {
|
||||||
auto& framebufferObject =
|
auto& framebufferObject =
|
||||||
MG_State::pGLContext->GetFramebufferBindingSlot(FramebufferTarget::Read).GetBoundObject();
|
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
|
// not be multisampled. Incompleteness is INVALID_FRAMEBUFFER_OPERATION, the other two are
|
||||||
// INVALID_OPERATION.
|
// INVALID_OPERATION.
|
||||||
Bool ValidateReadFramebufferForCopy(const char* caller);
|
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
|
} // namespace MobileGL::MG_Impl::GLImpl::FramebufferImpl
|
||||||
|
|||||||
@@ -185,6 +185,20 @@ namespace MobileGL::MG_State::GLState {
|
|||||||
return m_externalIndex;
|
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) {
|
void FramebufferObject::BumpAttachmentVersion(FramebufferAttachmentType type) {
|
||||||
++m_attachmentVersions[static_cast<SizeT>(type)];
|
++m_attachmentVersions[static_cast<SizeT>(type)];
|
||||||
++m_objectVersion;
|
++m_objectVersion;
|
||||||
|
|||||||
@@ -129,6 +129,19 @@ namespace MobileGL {
|
|||||||
void SetReadBuffer(FramebufferAttachmentType buf);
|
void SetReadBuffer(FramebufferAttachmentType buf);
|
||||||
FramebufferAttachmentType GetReadBuffer() const { return m_readBuffer; }
|
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 {
|
FramebufferAttachmentVersionArray GetAllFramebufferAttachmentVersions() const {
|
||||||
return m_attachmentVersions;
|
return m_attachmentVersions;
|
||||||
}
|
}
|
||||||
@@ -148,6 +161,12 @@ namespace MobileGL {
|
|||||||
FramebufferAttachmentArray m_drawBuffers; // Probably no versioning needed for this, just check equality
|
FramebufferAttachmentArray m_drawBuffers; // Probably no versioning needed for this, just check equality
|
||||||
FramebufferAttachmentType m_readBuffer = FramebufferAttachmentType::None;
|
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`)
|
// This version will bump when draw/read buffer changes (by `glDrawBuffer(s)`/`glReadBuffer`)
|
||||||
Uint16 m_objectVersion = 0;
|
Uint16 m_objectVersion = 0;
|
||||||
};
|
};
|
||||||
|
|||||||
Reference in New Issue
Block a user