[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:
2026-07-11 00:03:08 -04:00
parent dc3c2cc5c7
commit 9ffcb23877
4 changed files with 50 additions and 1 deletions
+15
View File
@@ -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] = "";