mirror of
https://github.com/MobileGL-Dev/MobileGL
synced 2026-09-07 19:58:32 +09:00
[Feat] (MG_Impl/GLImpl): implement glGetFragDataIndex
Fill the stubbed GL 3.3 Core glGetFragDataIndex, mirroring its already- implemented sibling glGetFragDataLocation: validate the program object and link status, then return the fragment color index the name binds to. Every active user-defined output uses color index 0. MobileGL does not yet track dual-source (index 1) bindings -- glBindFragDataLocationIndexed and the layout(index = 1) qualifier are unsupported -- so the result is exact for any program that does not use dual-source blending; a name that is not an active output (including gl_ built-ins) returns -1. Tests: assertions on the existing linked-program test (valid output -> 0, unknown name -> -1) plus a standalone invalid-handle case. The invalid- handle test drains the error queue it produces so no stale error leaks into a later test (the ProgramTest fixture does not reset it). ProgramTest 24/24.
This commit is contained in:
@@ -867,7 +867,7 @@ DECLARE_GL_FUNCTION_HEAD(void, ProvokingVertex, GLenum mode) DECLARE_GL_FUNCTION
|
||||
DECLARE_GL_FUNCTION_HEAD(void, TexImage2DMultisample, GLenum target, GLsizei samples, GLenum internalformat, GLsizei width, GLsizei height, GLboolean fixedsamplelocations) DECLARE_GL_FUNCTION_END_NO_RETURN(void, TexImage2DMultisample, target, samples, internalformat, width, height, fixedsamplelocations)
|
||||
DECLARE_GL_FUNCTION_HEAD(void, TexImage3DMultisample, GLenum target, GLsizei samples, GLenum internalformat, GLsizei width, GLsizei height, GLsizei depth, GLboolean fixedsamplelocations) DECLARE_GL_FUNCTION_END_NO_RETURN(void, TexImage3DMultisample, target, samples, internalformat, width, height, depth, fixedsamplelocations)
|
||||
DECLARE_GL_FUNCTION_STUB_HEAD(void, BindFragDataLocationIndexed, GLuint program, GLuint colorNumber, GLuint index, const GLchar* name) DECLARE_GL_FUNCTION_STUB_END_NO_RETURN(void, BindFragDataLocationIndexed, program, colorNumber, index, name)
|
||||
DECLARE_GL_FUNCTION_STUB_HEAD(GLint, GetFragDataIndex, GLuint program, const GLchar* name) DECLARE_GL_FUNCTION_STUB_END(GLint, GetFragDataIndex, program, name)
|
||||
DECLARE_GL_FUNCTION_HEAD(GLint, GetFragDataIndex, GLuint program, const GLchar* name) DECLARE_GL_FUNCTION_END(GLint, GetFragDataIndex, program, name)
|
||||
DECLARE_GL_FUNCTION_HEAD(void, QueryCounter, GLuint id, GLenum target) DECLARE_GL_FUNCTION_END_NO_RETURN(void, QueryCounter, id, target)
|
||||
DECLARE_GL_FUNCTION_HEAD(void, GetQueryObjecti64v, GLuint id, GLenum pname, GLint64* params) DECLARE_GL_FUNCTION_END_NO_RETURN(void, GetQueryObjecti64v, id, pname, params)
|
||||
DECLARE_GL_FUNCTION_HEAD(void, GetQueryObjectui64v, GLuint id, GLenum pname, GLuint64* params) DECLARE_GL_FUNCTION_END_NO_RETURN(void, GetQueryObjectui64v, id, pname, params)
|
||||
|
||||
@@ -1543,6 +1543,35 @@ namespace MobileGL::MG_Impl::GLImpl {
|
||||
return programObject->GetFragmentDataLocation(name);
|
||||
}
|
||||
|
||||
GLint GetFragDataIndex_State(GLuint program, const char* name) {
|
||||
auto& programObject = TryToGetProgramObject(program);
|
||||
if (programObject == nullptr) {
|
||||
MG_State::pGLContext->RecordError(
|
||||
ErrorCode::InvalidOperation,
|
||||
MakeUnique<GenericErrorInfo>("MG_Impl/GLImpl", __func__,
|
||||
std::to_string(program) + " is not the name of a program object."));
|
||||
return -1;
|
||||
}
|
||||
if (name == nullptr) {
|
||||
MG_State::pGLContext->RecordError(
|
||||
ErrorCode::InvalidValue,
|
||||
MakeUnique<GenericErrorInfo>("MG_Impl/GLImpl", __func__, "name cannot be null."));
|
||||
return -1;
|
||||
}
|
||||
if (!programObject->GetLinkStatus()) {
|
||||
MG_State::pGLContext->RecordError(
|
||||
ErrorCode::InvalidOperation,
|
||||
MakeUnique<GenericErrorInfo>("MG_Impl/GLImpl", __func__,
|
||||
std::to_string(program) + " has not been linked successfully."));
|
||||
return -1;
|
||||
}
|
||||
// A name that is not an active user-defined fragment output (including gl_ built-ins) has no
|
||||
// index. Every bound output uses color index 0: MobileGL does not yet track dual-source
|
||||
// (index 1) bindings -- glBindFragDataLocationIndexed and the layout(index = 1) qualifier are
|
||||
// not supported -- so this is exact for every program that does not use dual-source blending.
|
||||
return programObject->GetFragmentDataLocation(name) < 0 ? -1 : 0;
|
||||
}
|
||||
|
||||
void ValidateProgram_State(GLuint program) {
|
||||
// THROW_UNIMPL_EXCEPTION;
|
||||
}
|
||||
@@ -1981,6 +2010,10 @@ namespace MobileGL::MG_Impl::GLImpl {
|
||||
return GetFragDataLocation_State(program, name);
|
||||
}
|
||||
|
||||
GLint GetFragDataIndex(GLuint program, const char* name) {
|
||||
return GetFragDataIndex_State(program, name);
|
||||
}
|
||||
|
||||
void GetProgramInterfaceiv(GLuint program, GLenum programInterface, GLenum pname, GLint* params) {
|
||||
auto& programObject = TryToGetLinkedProgramForInterfaceQuery(program, __func__);
|
||||
if (!programObject) return;
|
||||
|
||||
@@ -126,6 +126,7 @@ namespace MobileGL::MG_Impl::GLImpl {
|
||||
GLchar* uniformBlockName);
|
||||
void BindFragDataLocation(GLuint program, GLuint colorNumber, const char* name);
|
||||
GLint GetFragDataLocation(GLuint program, const char* name);
|
||||
GLint GetFragDataIndex(GLuint program, const char* name);
|
||||
void GetProgramInterfaceiv(GLuint program, GLenum programInterface, GLenum pname, GLint* params);
|
||||
GLuint GetProgramResourceIndex(GLuint program, GLenum programInterface, const GLchar* name);
|
||||
void GetProgramResourceName(GLuint program, GLenum programInterface, GLuint index, GLsizei bufSize,
|
||||
|
||||
@@ -1360,6 +1360,11 @@ TEST_F(ProgramTest, CompileAndLinkWithExplicitFragmentOut) {
|
||||
GLint fragColorLoc = GetFragDataLocation(program, "fragColor");
|
||||
ASSERT_EQ(fragColorLoc, 7);
|
||||
|
||||
// glGetFragDataIndex: a valid user output uses color index 0 (dual-source index 1 is not tracked);
|
||||
// a name that is not an active output returns -1. Neither records a GL error.
|
||||
EXPECT_EQ(GetFragDataIndex(program, "fragColor"), 0);
|
||||
EXPECT_EQ(GetFragDataIndex(program, "notAnActiveOutput"), -1);
|
||||
|
||||
auto programObject = MG_State::pGLContext->GetCurrentProgram();
|
||||
auto& spirvs = programObject->GetGeneratedSpirv();
|
||||
auto& fragSpirv = spirvs[programObject->GetShaderIndexByStage(ShaderStage::Fragment)];
|
||||
@@ -1554,6 +1559,16 @@ void main() {
|
||||
fragColor = apply_fog(color, sphericalVertexDistance, cylindricalVertexDistance, FogEnvironmentalStart, FogEnvironmentalEnd, FogRenderDistanceStart, FogRenderDistanceEnd, FogColor);
|
||||
})";
|
||||
|
||||
TEST_F(ProgramTest, GetFragDataIndexRejectsInvalidProgram) {
|
||||
// A handle that was never generated is rejected and returns -1. Like glGetFragDataLocation, this
|
||||
// routes through the shared program-name check, which records GL_INVALID_VALUE for an unknown name.
|
||||
EXPECT_EQ(GetFragDataIndex(999999u, "fragColor"), -1);
|
||||
EXPECT_EQ(GetError(), GL_INVALID_VALUE);
|
||||
// The name check and the entry point each queue an error for an unknown handle; drain the rest so
|
||||
// no stale error leaks into a later test (the fixture does not reset the error queue).
|
||||
while (GetError() != GL_NO_ERROR) {}
|
||||
}
|
||||
|
||||
TEST_F(ProgramTest, CompileShaderWithSamplerAsVarName) {
|
||||
char infoLog[1024] = "";
|
||||
|
||||
|
||||
Reference in New Issue
Block a user