[Fix] (MG_Impl, MG_State, MG_Backend, MG_Util): Do source audit by Codex.

This commit is contained in:
BZLZHH
2026-06-09 15:34:19 +08:00
parent be3c3eb9bb
commit 727939af5b
93 changed files with 6019 additions and 731 deletions
@@ -15,10 +15,144 @@
#include <MG_State/GLState/ErrorState/Error.h>
#include <MG_Util/Converters/GLToStr/GLEnumConverter.h>
#include <MG_Util/Converters/GLToMG/TextureEnumConverter.h>
#include <MG_Util/Converters/MGToMG/TextureEnumConverter.h>
#include <MG_Util/Converters/MGToGL/TextureEnumConverter.h>
#include <MG_Util/Converters/MGToStr/TextureEnumConverter.h>
#include <MG_Util/Converters/GLToMG/FramebufferEnumConverter.h>
namespace MobileGL::MG_Impl::GLImpl {
namespace {
Bool IsActiveBackendDirectVulkan() {
auto* activeBackend = MG_Backend::pActiveBackendObject.get();
return activeBackend != nullptr && activeBackend->GetBackendType() == BackendType::DirectVulkan;
}
Bool HasDistinctCompleteDepthStencilTextureAttachments(
const MG_State::GLState::FramebufferObject& framebufferObject) {
if (framebufferObject.GetExternalIndex() == 0) {
return false;
}
const auto& depthAttachment = framebufferObject.GetAttachment(FramebufferAttachmentType::Depth);
const auto& stencilAttachment = framebufferObject.GetAttachment(FramebufferAttachmentType::Stencil);
if (!depthAttachment.IsComplete() || !stencilAttachment.IsComplete() ||
!depthAttachment.IsTexture() || !stencilAttachment.IsTexture()) {
return false;
}
return depthAttachment.GetTexture().get() != stencilAttachment.GetTexture().get() ||
depthAttachment.GetTextureUploadTarget() != stencilAttachment.GetTextureUploadTarget() ||
depthAttachment.GetTextureLevel() != stencilAttachment.GetTextureLevel();
}
Bool HasCompleteRenderbufferAttachment(const MG_State::GLState::FramebufferObject& framebufferObject) {
if (framebufferObject.GetExternalIndex() == 0) {
return false;
}
for (const auto& attachment : framebufferObject.GetAllAttachmentObjects()) {
if (attachment.IsRenderbuffer() && attachment.IsComplete()) {
return true;
}
}
return false;
}
Bool IsUnsupportedFramebufferForDirectVulkan(
const MG_State::GLState::FramebufferObject& framebufferObject) {
return HasDistinctCompleteDepthStencilTextureAttachments(framebufferObject) ||
HasCompleteRenderbufferAttachment(framebufferObject);
}
void RecordUnsupportedFramebufferTextureAttachmentError(const char* functionName, const char* detail) {
MG_State::pGLContext->RecordError(
ErrorCode::InvalidOperation,
MakeUnique<GenericErrorInfo>("MG_Impl/GLImpl", functionName, detail));
}
Bool ResolveRepresentableFramebufferTextureUploadTarget(const MG_State::GLState::ITextureObject& textureObject,
TextureUploadTarget& outUploadTarget) {
switch (textureObject.GetTarget()) {
case TextureTarget::Texture1D:
outUploadTarget = TextureUploadTarget::Texture1D;
return true;
case TextureTarget::Texture2D:
outUploadTarget = TextureUploadTarget::Texture2D;
return true;
case TextureTarget::TextureRectangle:
outUploadTarget = TextureUploadTarget::TextureRectangle;
return true;
case TextureTarget::Texture2DMultisample:
outUploadTarget = TextureUploadTarget::Texture2DMultisample;
return true;
default:
outUploadTarget = TextureUploadTarget::Unknown;
return false;
}
}
void AttachFramebufferTextureWithUploadTarget(const char* functionName, GLenum target, GLenum attachment,
GLuint texture, GLint level,
TextureUploadTarget textureUploadTarget) {
if (target == GL_FRAMEBUFFER) {
target = GL_DRAW_FRAMEBUFFER;
}
if (attachment == GL_DEPTH_STENCIL_ATTACHMENT) {
AttachFramebufferTextureWithUploadTarget(functionName, target, GL_DEPTH_ATTACHMENT, texture, level,
textureUploadTarget);
AttachFramebufferTextureWithUploadTarget(functionName, target, GL_STENCIL_ATTACHMENT, texture, level,
textureUploadTarget);
return;
}
const FramebufferAttachmentType attachmentType = MG_Util::ConvertGLEnumToFramebufferAttachmentType(attachment);
const FramebufferTarget framebufferTarget = MG_Util::ConvertGLEnumToFramebufferTarget(target);
if (!FramebufferImpl::ValidateFramebufferAttachmentType(attachmentType)) return;
if (!FramebufferImpl::ValidateFramebufferTarget(framebufferTarget)) return;
if (!TextureImpl::ValidateTextureName(texture, true)) return;
auto& bindingSlot = MG_State::pGLContext->GetFramebufferBindingSlot(framebufferTarget);
auto& framebufferObject = bindingSlot.GetBoundObject();
if (!framebufferObject) {
MG_State::pGLContext->RecordError(
ErrorCode::InvalidOperation,
MakeUnique<GenericErrorInfo>("MG_Impl/GLImpl", functionName,
"Framebuffer target is bound to no framebuffer object."));
return;
}
if (texture == 0) {
framebufferObject->Detach(attachmentType);
return;
}
auto& textureObject = MG_State::pGLContext->GetTextureObject(texture);
if (!textureObject) {
MG_State::pGLContext->RecordError(
ErrorCode::InvalidOperation,
MakeUnique<GenericErrorInfo>("MG_Impl/GLImpl", functionName,
std::format("Texture object {} is not valid.", texture)));
return;
}
const auto expectedTextureTarget = MG_Util::ConvertTextureUploadTargetToTextureTarget(textureUploadTarget);
if (expectedTextureTarget == TextureTarget::Unknown ||
textureObject->GetTarget() != expectedTextureTarget) {
MG_State::pGLContext->RecordError(
ErrorCode::InvalidOperation,
MakeUnique<GenericErrorInfo>(
"MG_Impl/GLImpl", functionName,
std::format("Attachment target {} does not match texture {} target {}.",
MG_Util::ConvertTextureUploadTargetToString(textureUploadTarget), texture,
MG_Util::ConvertTextureTargetToString(textureObject->GetTarget()))));
return;
}
framebufferObject->AttachTexture(attachmentType, textureObject, textureUploadTarget, level);
}
} // namespace
void BlitFramebuffer_Backend(GLint srcX0, GLint srcY0, GLint srcX1, GLint srcY1, GLint dstX0, GLint dstY0,
GLint dstX1, GLint dstY1, GLbitfield mask, GLenum filter) {
MG_Backend::gBackendFunctionsTable.GL.BlitFramebuffer(srcX0, srcY0, srcX1, srcY1, dstX0, dstY0, dstX1, dstY1,
@@ -26,12 +160,53 @@ namespace MobileGL::MG_Impl::GLImpl {
}
void SampleMaski_State(GLuint maskNumber, GLbitfield mask) {
// TODO: implement
if (maskNumber != 0) {
MG_State::pGLContext->RecordError(
ErrorCode::InvalidValue,
MakeUnique<GenericErrorInfo>("MG_Impl/GLImpl", "SampleMaski_State",
"Only sample mask word 0 is currently supported."));
return;
}
MG_State::pGLContext->SetSampleMaskValue(static_cast<Uint32>(mask));
}
void RenderbufferStorageMultisample_State(GLenum target, GLsizei samples, GLenum internalformat, GLsizei width,
GLsizei height) {
// TODO: implement
RenderbufferTarget rbTarget = MG_Util::ConvertGLEnumToRenderbufferTarget(target);
if (!FramebufferImpl::ValidateRenderbufferTarget(rbTarget)) return;
auto& bindingSlot = MG_State::pGLContext->GetRenderbufferBindingSlot(rbTarget);
auto& renderbufferObject = bindingSlot.GetBoundObject();
if (!renderbufferObject) {
MG_State::pGLContext->RecordError(
ErrorCode::InvalidOperation,
MakeUnique<GenericErrorInfo>("MG_Impl/GLImpl", "RenderbufferStorageMultisample_State",
"Renderbuffer target is bound to no renderbuffer object."));
return;
}
TextureInternalFormat format = MG_Util::ConvertGLEnumToTextureInternalFormat(internalformat);
if (!TextureImpl::ValidateTextureInternalFormat(format)) return;
if (samples < 0) {
MG_State::pGLContext->RecordError(
ErrorCode::InvalidValue,
MakeUnique<GenericErrorInfo>("MG_Impl/GLImpl", "RenderbufferStorageMultisample_State",
"Sample count must be non-negative."));
return;
}
if (width < 0 || height < 0) {
MG_State::pGLContext->RecordError(
ErrorCode::InvalidValue,
MakeUnique<GenericErrorInfo>("MG_Impl/GLImpl", "RenderbufferStorageMultisample_State",
"Width and height must be non-negative."));
return;
}
renderbufferObject->AllocateStorage({width, height});
renderbufferObject->SetInternalFormat(format);
renderbufferObject->SetSamples(samples);
}
void RenderbufferStorage_State(GLenum target, GLenum internalformat, GLsizei width, GLsizei height) {
@@ -56,14 +231,15 @@ namespace MobileGL::MG_Impl::GLImpl {
}
renderbufferObject->AllocateStorage({width, height});
renderbufferObject->SetInternalFormat(format);
renderbufferObject->SetSamples(0);
}
GLboolean IsRenderbuffer_State(GLuint renderbuffer) {
return MG_State::pGLContext->ValidateRenderbufferName(renderbuffer);
return MG_State::pGLContext->ValidateRenderbufferObject(renderbuffer);
}
GLboolean IsFramebuffer_State(GLuint framebuffer) {
return MG_State::pGLContext->ValidateFramebufferName(framebuffer);
return MG_State::pGLContext->ValidateFramebufferObject(framebuffer);
}
void GetFramebufferAttachmentParameteriv_State(GLenum target, GLenum attachment, GLenum pname, GLint* params) {
@@ -136,6 +312,26 @@ namespace MobileGL::MG_Impl::GLImpl {
: 0;
break;
case GL_FRAMEBUFFER_ATTACHMENT_TEXTURE_CUBE_MAP_FACE:
if (attachmentObject != nullptr && attachmentObject->IsTexture() && attachmentObject->IsValid()) {
const GLenum glUploadTarget =
MG_Util::ConvertTextureUploadTargetToGLEnum(attachmentObject->GetTextureUploadTarget());
switch (glUploadTarget) {
case GL_TEXTURE_CUBE_MAP_POSITIVE_X:
case GL_TEXTURE_CUBE_MAP_NEGATIVE_X:
case GL_TEXTURE_CUBE_MAP_POSITIVE_Y:
case GL_TEXTURE_CUBE_MAP_NEGATIVE_Y:
case GL_TEXTURE_CUBE_MAP_POSITIVE_Z:
case GL_TEXTURE_CUBE_MAP_NEGATIVE_Z:
*params = static_cast<GLint>(glUploadTarget);
break;
default:
*params = 0;
break;
}
} else {
*params = 0;
}
break;
case GL_FRAMEBUFFER_ATTACHMENT_TEXTURE_LAYER:
*params = 0;
break;
@@ -174,12 +370,31 @@ namespace MobileGL::MG_Impl::GLImpl {
}
void FramebufferTextureLayer_State(GLenum target, GLenum attachment, GLuint texture, GLint level, GLint layer) {
// TODO: implement
if (texture == 0) {
const TextureUploadTarget detachTarget = TextureUploadTarget::Texture2D;
AttachFramebufferTextureWithUploadTarget(__func__, target, attachment, texture, level, detachTarget);
return;
}
static_cast<void>(layer);
RecordUnsupportedFramebufferTextureAttachmentError(
__func__,
"Layered framebuffer texture attachments are not represented by the current framebuffer attachment model.");
}
void FramebufferTexture3D_State(GLenum target, GLenum attachment, GLenum textarget, GLuint texture, GLint level,
GLint zoffset) {
// TODO: implement
if (texture == 0) {
TextureUploadTarget textureUploadTarget = MG_Util::ConvertGLEnumToTextureUploadTarget(textarget);
if (!TextureImpl::ValidateTextureUploadTarget(textureUploadTarget)) return;
AttachFramebufferTextureWithUploadTarget(__func__, target, attachment, texture, level, textureUploadTarget);
return;
}
static_cast<void>(zoffset);
RecordUnsupportedFramebufferTextureAttachmentError(
__func__,
"3D framebuffer texture slice attachments are not represented by the current framebuffer attachment model.");
}
void FramebufferTexture2D_State(GLenum target, GLenum attachment, GLenum textarget, GLuint texture, GLint level) {
@@ -199,6 +414,11 @@ namespace MobileGL::MG_Impl::GLImpl {
if (!FramebufferImpl::ValidateFramebufferAttachmentType(attachmentType)) return;
if (!FramebufferImpl::ValidateFramebufferTarget(framebufferTarget)) return;
if (!TextureImpl::ValidateTextureName(texture, true)) return;
TextureUploadTarget textureUploadTarget = TextureUploadTarget::Unknown;
if (texture != 0) {
textureUploadTarget = MG_Util::ConvertGLEnumToTextureUploadTarget(textarget);
if (!TextureImpl::ValidateTextureUploadTarget(textureUploadTarget)) return;
}
auto& bindingSlot = MG_State::pGLContext->GetFramebufferBindingSlot(framebufferTarget);
auto& framebufferObject = bindingSlot.GetBoundObject();
@@ -224,15 +444,59 @@ namespace MobileGL::MG_Impl::GLImpl {
return;
}
framebufferObject->AttachTexture(attachmentType, textureObject, textureObject ? level : 0);
const auto expectedTextureTarget = MG_Util::ConvertTextureUploadTargetToTextureTarget(textureUploadTarget);
if (expectedTextureTarget == TextureTarget::Unknown ||
textureObject->GetTarget() != expectedTextureTarget) {
MG_State::pGLContext->RecordError(
ErrorCode::InvalidOperation,
MakeUnique<GenericErrorInfo>(
"MG_Impl/GLImpl", "FramebufferTexture2D_State",
std::format("Attachment target {} does not match texture {} target {}.",
MG_Util::ConvertGLEnumToString(textarget),
texture,
MG_Util::ConvertTextureTargetToString(textureObject->GetTarget()))));
return;
}
framebufferObject->AttachTexture(attachmentType, textureObject, textureUploadTarget, textureObject ? level : 0);
}
void FramebufferTexture1D_State(GLenum target, GLenum attachment, GLenum textarget, GLuint texture, GLint level) {
// TODO: implement
TextureUploadTarget textureUploadTarget = TextureUploadTarget::Unknown;
if (texture != 0) {
textureUploadTarget = MG_Util::ConvertGLEnumToTextureUploadTarget(textarget);
if (!TextureImpl::ValidateTextureUploadTarget(textureUploadTarget)) return;
} else {
textureUploadTarget = TextureUploadTarget::Texture1D;
}
AttachFramebufferTextureWithUploadTarget(__func__, target, attachment, texture, level, textureUploadTarget);
}
void FramebufferTexture_State(GLenum target, GLenum attachment, GLuint texture, GLint level) {
// TODO: implement
if (texture == 0) {
AttachFramebufferTextureWithUploadTarget(__func__, target, attachment, texture, level,
TextureUploadTarget::Texture2D);
return;
}
auto& textureObject = MG_State::pGLContext->GetTextureObject(texture);
if (!textureObject) {
MG_State::pGLContext->RecordError(
ErrorCode::InvalidOperation,
MakeUnique<GenericErrorInfo>("MG_Impl/GLImpl", __func__,
std::format("Texture object {} is not valid.", texture)));
return;
}
TextureUploadTarget textureUploadTarget = TextureUploadTarget::Unknown;
if (!ResolveRepresentableFramebufferTextureUploadTarget(*textureObject, textureUploadTarget)) {
RecordUnsupportedFramebufferTextureAttachmentError(
__func__,
"Layered or multi-image framebuffer texture targets are not fully represented by the current framebuffer attachment model.");
return;
}
AttachFramebufferTextureWithUploadTarget(__func__, target, attachment, texture, level, textureUploadTarget);
}
void FramebufferRenderbuffer_State(GLenum target, GLenum attachment, GLenum renderbuffertarget,
@@ -246,7 +510,8 @@ namespace MobileGL::MG_Impl::GLImpl {
RenderbufferTarget rbTarget = MG_Util::ConvertGLEnumToRenderbufferTarget(renderbuffertarget);
if (!FramebufferImpl::ValidateFramebufferAttachmentType(attachmentType)) return;
if (!FramebufferImpl::ValidateFramebufferTarget(framebufferTarget)) return;
if (!FramebufferImpl::ValidateRenderbufferName(renderbuffer)) return;
if (!FramebufferImpl::ValidateRenderbufferTarget(rbTarget)) return;
if (!FramebufferImpl::ValidateRenderbufferName(renderbuffer, true)) return;
auto& bindingSlot = MG_State::pGLContext->GetFramebufferBindingSlot(framebufferTarget);
auto& framebufferObject = bindingSlot.GetBoundObject();
if (!framebufferObject) {
@@ -290,6 +555,12 @@ namespace MobileGL::MG_Impl::GLImpl {
// Get bound framebuffer
auto& bindingSlot = MG_State::pGLContext->GetFramebufferBindingSlot(FramebufferTarget::Draw);
auto& fbo = bindingSlot.GetBoundObject();
if (!fbo) {
MG_State::pGLContext->RecordError(
ErrorCode::InvalidOperation,
MakeUnique<GenericErrorInfo>("MG_Impl/GLImpl", __func__, "No framebuffer bound to draw target."));
return;
}
bool isDefaultFBO = (fbo == FramebufferImpl::pDefaultFramebufferInfo->defaultFBO);
static int existenceMap[(SizeT)FramebufferAttachmentType::FramebufferAttachmentTypeCount] = {-1};
@@ -308,20 +579,20 @@ namespace MobileGL::MG_Impl::GLImpl {
return;
}
if (isDefaultFBO && attType >= FramebufferAttachmentType::Color0 &&
attType <= FramebufferAttachmentType::Color31) {
if (isDefaultFBO && attType != FramebufferAttachmentType::None &&
(attType < FramebufferAttachmentType::FrontLeft || attType > FramebufferAttachmentType::BackRight)) {
MG_State::pGLContext->RecordError(
ErrorCode::InvalidEnum,
MakeUnique<GenericErrorInfo>(
"MG_Impl/GLImpl", __func__,
std::format(
"FBO is default FBO, but bufs[{}] = {} is one of the `GL_COLOR_ATTACHMENTn` tokens.", i,
MG_Util::ConvertGLEnumToString(bufs[i]))));
std::format("FBO is default FBO, but bufs[{}] = {} is not `GL_NONE` or one of the default "
"framebuffer color buffer tokens.",
i, MG_Util::ConvertGLEnumToString(bufs[i]))));
return;
}
if (!isDefaultFBO && attType >= FramebufferAttachmentType::FrontLeft &&
attType <= FramebufferAttachmentType::BackRight) {
if (!isDefaultFBO && attType != FramebufferAttachmentType::None &&
(attType < FramebufferAttachmentType::Color0 || attType > FramebufferAttachmentType::Color31)) {
MG_State::pGLContext->RecordError(
ErrorCode::InvalidEnum,
MakeUnique<GenericErrorInfo>(
@@ -388,6 +659,43 @@ namespace MobileGL::MG_Impl::GLImpl {
// Get bound framebuffer
auto& bindingSlot = MG_State::pGLContext->GetFramebufferBindingSlot(FramebufferTarget::Read);
auto& fbo = bindingSlot.GetBoundObject();
if (!fbo) {
MG_State::pGLContext->RecordError(
ErrorCode::InvalidOperation,
MakeUnique<GenericErrorInfo>("MG_Impl/GLImpl", __func__, "No framebuffer bound to read target."));
return;
}
const Bool isDefaultFBO = (fbo == FramebufferImpl::pDefaultFramebufferInfo->defaultFBO);
if (isDefaultFBO && attType != FramebufferAttachmentType::None &&
(attType < FramebufferAttachmentType::FrontLeft || attType > FramebufferAttachmentType::BackRight)) {
MG_State::pGLContext->RecordError(
ErrorCode::InvalidEnum,
MakeUnique<GenericErrorInfo>(
"MG_Impl/GLImpl", __func__,
std::format("Default framebuffer read buffer {} is not valid.", MG_Util::ConvertGLEnumToString(mode))));
return;
}
if (!isDefaultFBO && attType != FramebufferAttachmentType::None &&
(attType < FramebufferAttachmentType::Color0 || attType > FramebufferAttachmentType::Color31)) {
MG_State::pGLContext->RecordError(
ErrorCode::InvalidEnum,
MakeUnique<GenericErrorInfo>("MG_Impl/GLImpl", __func__,
std::format("Framebuffer object read buffer {} is not valid.",
MG_Util::ConvertGLEnumToString(mode))));
return;
}
if (!isDefaultFBO &&
static_cast<SizeT>(attType) >
static_cast<SizeT>(FramebufferAttachmentType::Color0) +
MG_State::GLState::FramebufferObject::MAX_DRAW_BUFFERS) {
MG_State::pGLContext->RecordError(
ErrorCode::InvalidOperation,
MakeUnique<GenericErrorInfo>("MG_Impl/GLImpl", __func__,
std::format("Read buffer {} indicates a color buffer that does not exist "
"in the current GL context.",
MG_Util::ConvertGLEnumToString(mode))));
return;
}
fbo->SetReadBuffer(attType);
}
@@ -453,24 +761,35 @@ namespace MobileGL::MG_Impl::GLImpl {
// TODO: distinguish GL_FRAMEBUFFER_INCOMPLETE_ATTACHMENT and GL_FRAMEBUFFER_INCOMPLETE_MISSING_ATTACHMENT
// TODO: GL_FRAMEBUFFER_INCOMPLETE_DRAW_BUFFER, GL_FRAMEBUFFER_INCOMPLETE_READ_BUFFER,
// GL_FRAMEBUFFER_UNSUPPORTED, GL_FRAMEBUFFER_INCOMPLETE_MULTISAMPLE,
// additional GL_FRAMEBUFFER_UNSUPPORTED cases, GL_FRAMEBUFFER_INCOMPLETE_MULTISAMPLE,
// GL_FRAMEBUFFER_INCOMPLETE_LAYER_TARGETS
return framebufferObject->CheckCompleteness() ? GL_FRAMEBUFFER_COMPLETE
: GL_FRAMEBUFFER_INCOMPLETE_MISSING_ATTACHMENT;
if (!framebufferObject->CheckCompleteness()) {
return GL_FRAMEBUFFER_INCOMPLETE_MISSING_ATTACHMENT;
}
if (IsActiveBackendDirectVulkan() &&
IsUnsupportedFramebufferForDirectVulkan(*framebufferObject)) {
return GL_FRAMEBUFFER_UNSUPPORTED;
}
return GL_FRAMEBUFFER_COMPLETE;
}
void BindRenderbuffer_State(GLenum target, GLuint renderbuffer) {
if (!FramebufferImpl::ValidateRenderbufferName(renderbuffer)) return;
if (!FramebufferImpl::ValidateRenderbufferName(renderbuffer, true)) return;
RenderbufferTarget renderbufferTarget = MG_Util::ConvertGLEnumToRenderbufferTarget(target);
if (!FramebufferImpl::ValidateRenderbufferTarget(renderbufferTarget)) return;
auto& bindingSlot = MG_State::pGLContext->GetRenderbufferBindingSlot(renderbufferTarget);
if (renderbuffer == 0) {
bindingSlot.Bind(nullptr);
return;
}
Bool doesRenderbufferCreated = MG_State::pGLContext->ValidateRenderbufferObject(renderbuffer);
if (!doesRenderbufferCreated) {
MG_State::pGLContext->CreateRenderbufferObject(renderbuffer);
}
auto& renderbufferObject = MG_State::pGLContext->GetRenderbufferObject(renderbuffer);
auto& bindingSlot = MG_State::pGLContext->GetRenderbufferBindingSlot(renderbufferTarget);
bindingSlot.Bind(renderbufferObject);
}
@@ -567,7 +886,7 @@ namespace MobileGL::MG_Impl::GLImpl {
MG_Backend::gBackendFunctionsTable.GL.ClearBufferiv(buffer, drawbuffer, value);
}
void ReadPixels_State(GLint x, GLint y, GLsizei width, GLsizei height, GLenum format, GLenum type, void* pixels) {
Bool ReadPixels_State(GLint x, GLint y, GLsizei width, GLsizei height, GLenum format, GLenum type, void* pixels) {
TextureInputFormat textureInputFormat = MG_Util::ConvertGLEnumToTextureInputFormat(format);
TexturePixelDataType texturePixelDataType = MG_Util::ConvertGLEnumToTexturePixelDataType(type);
@@ -576,7 +895,7 @@ namespace MobileGL::MG_Impl::GLImpl {
MG_State::pGLContext->RecordError(ErrorCode::InvalidValue,
MakeUnique<GenericErrorInfo>("MG_Impl/GLImpl", "ReadPixels_State",
"Width and height must be non-negative"));
return;
return false;
}
// Validate format
@@ -584,7 +903,7 @@ namespace MobileGL::MG_Impl::GLImpl {
MG_State::pGLContext->RecordError(
ErrorCode::InvalidEnum,
MakeUnique<GenericErrorInfo>("MG_Impl/GLImpl", "ReadPixels_State", "Invalid format"));
return;
return false;
}
// Validate type
@@ -592,7 +911,7 @@ namespace MobileGL::MG_Impl::GLImpl {
MG_State::pGLContext->RecordError(
ErrorCode::InvalidEnum,
MakeUnique<GenericErrorInfo>("MG_Impl/GLImpl", "ReadPixels_State", "Invalid pixel data type"));
return;
return false;
}
// Get bound framebuffer
@@ -603,7 +922,7 @@ namespace MobileGL::MG_Impl::GLImpl {
MG_State::pGLContext->RecordError(ErrorCode::InvalidOperation,
MakeUnique<GenericErrorInfo>("MG_Impl/GLImpl", "ReadPixels_State",
"No framebuffer bound to read target"));
return;
return false;
}
// Check framebuffer completeness
@@ -611,7 +930,7 @@ namespace MobileGL::MG_Impl::GLImpl {
MG_State::pGLContext->RecordError(
ErrorCode::InvalidFramebufferOperation,
MakeUnique<GenericErrorInfo>("MG_Impl/GLImpl", "ReadPixels_State", "Framebuffer is incomplete"));
return;
return false;
}
// Check for required buffers
@@ -621,7 +940,7 @@ namespace MobileGL::MG_Impl::GLImpl {
ErrorCode::InvalidOperation,
MakeUnique<GenericErrorInfo>("MG_Impl/GLImpl", "ReadPixels_State",
"No stencil buffer for stencil index format"));
return;
return false;
}
} else if (textureInputFormat == TextureInputFormat::DepthComponent) {
if (!framebufferObject->GetAttachment(FramebufferAttachmentType::Depth).IsValid()) {
@@ -629,7 +948,7 @@ namespace MobileGL::MG_Impl::GLImpl {
ErrorCode::InvalidOperation,
MakeUnique<GenericErrorInfo>("MG_Impl/GLImpl", "ReadPixels_State",
"No depth buffer for depth component format"));
return;
return false;
}
} else if (textureInputFormat == TextureInputFormat::DepthStencil) {
if (!framebufferObject->GetAttachment(FramebufferAttachmentType::Depth).IsValid() ||
@@ -638,7 +957,7 @@ namespace MobileGL::MG_Impl::GLImpl {
ErrorCode::InvalidOperation,
MakeUnique<GenericErrorInfo>("MG_Impl/GLImpl", "ReadPixels_State",
"No depth/stencil buffer for depth-stencil format"));
return;
return false;
}
// Validate type for depth/stencil
@@ -647,7 +966,7 @@ namespace MobileGL::MG_Impl::GLImpl {
MG_State::pGLContext->RecordError(
ErrorCode::InvalidEnum, MakeUnique<GenericErrorInfo>("MG_Impl/GLImpl", "ReadPixels_State",
"Invalid type for depth-stencil format"));
return;
return false;
}
}
@@ -661,7 +980,7 @@ namespace MobileGL::MG_Impl::GLImpl {
MG_State::pGLContext->RecordError(
ErrorCode::InvalidOperation, MakeUnique<GenericErrorInfo>("MG_Impl/GLImpl", "ReadPixels_State",
"Pixel pack buffer is currently mapped"));
return;
return false;
}
// Check alignment
@@ -671,7 +990,7 @@ namespace MobileGL::MG_Impl::GLImpl {
ErrorCode::InvalidOperation,
MakeUnique<GenericErrorInfo>("MG_Impl/GLImpl", "ReadPixels_State",
"Pixel data not aligned for pixel pack buffer"));
return;
return false;
}
}
@@ -683,9 +1002,11 @@ namespace MobileGL::MG_Impl::GLImpl {
ErrorCode::InvalidOperation,
MakeUnique<GenericErrorInfo>("MG_Impl/GLImpl", "ReadPixels_State",
"ReadPixels not supported for multisampled framebuffers"));
return;
return false;
}
}
return true;
}
void ReadPixels_Backend(GLint x, GLint y, GLsizei width, GLsizei height, GLenum format, GLenum type, void* pixels) {
@@ -694,7 +1015,7 @@ namespace MobileGL::MG_Impl::GLImpl {
/* @INSERTION_POINT:FUNCTION_IMPLEMENTATION@ */
void ReadPixels(GLint x, GLint y, GLsizei width, GLsizei height, GLenum format, GLenum type, void* pixels) {
ReadPixels_State(x, y, width, height, format, type, pixels);
if (!ReadPixels_State(x, y, width, height, format, type, pixels)) return;
ReadPixels_Backend(x, y, width, height, format, type, pixels);
}