[Feat] (MG_Impl/GLImpl, MG_State): implement glHint, glPointParameter*, glPixelStoref, glGetDoublev

Six pure-state entry points that were stubs or empty // TODO bodies, all backed by new
context state and read back through glGet*.

* glHint: Hint_State was an empty TODO. Store the 4 GL 3.3 core hint targets (LINE_SMOOTH,
  POLYGON_SMOOTH, TEXTURE_COMPRESSION, FRAGMENT_SHADER_DERIVATIVE), default GL_DONT_CARE.
  Validate target and mode (FASTEST/NICEST/DONT_CARE) -> GL_INVALID_ENUM otherwise. The
  compatibility-only targets (GL_PERSPECTIVE_CORRECTION_HINT, GL_POINT_SMOOTH_HINT, GL_FOG_HINT,
  GL_GENERATE_MIPMAP_HINT) are rejected. The glGetIntegerv hint cases, previously hardcoded to
  GL_DONT_CARE, now read the stored value; glGetBooleanv on a hint is always GL_TRUE.

* glPointParameter{f,i,fv,iv}: the scalar _State bodies were empty TODOs and the *v forms were
  stubs. Only the 2 core pnames are accepted: GL_POINT_FADE_THRESHOLD_SIZE (float, default 1.0,
  GL_INVALID_VALUE if negative) and GL_POINT_SPRITE_COORD_ORIGIN (GL_LOWER_LEFT/GL_UPPER_LEFT,
  default GL_UPPER_LEFT, GL_INVALID_ENUM on a bad value -- note the different error code from the
  fade case). The compat pnames (POINT_SIZE_MIN/MAX, POINT_DISTANCE_ATTENUATION) are rejected. All
  four forms funnel through one (pname, float) handler. glGetIntegerv(GL_POINT_FADE_THRESHOLD_SIZE)
  was hardcoded to 1; it now rounds the stored float, glGetFloatv reads the float directly (keeping
  the fractional part), and GL_POINT_SPRITE_COORD_ORIGIN gained a getter case (it had none).

* glPixelStoref: funnels into the existing glPixelStorei state, but converts per type -- boolean
  pnames (PACK/UNPACK_SWAP_BYTES/LSB_FIRST) by a zero-test so 0.4 -> TRUE, integer pnames by
  round-to-nearest. A blanket round would wrongly turn a fractional true flag into false.

* glGetDoublev: funnels through glGetFloatv and widens, writing exactly the pname's component count
  (1/2/4) so a single-component query cannot overrun the caller's buffer. MobileGL stores no native
  double state (depth range/clear are float), so widening from float matches its real resolution.

State added to RenderStateParameters + RenderState Set/Get + GLContext wrappers, following the
existing LineWidth/DepthRange pattern. Covered by 4 SanityTest cases (set-then-get round trips, the
core-vs-compat enum rejections, the two different error codes, and the glPixelStoref boolean
zero-test, which was verified to fail against a blanket-round implementation).
This commit is contained in:
2026-07-10 20:35:08 -04:00
parent 561d8992bc
commit e460536119
10 changed files with 415 additions and 13 deletions
+53 -5
View File
@@ -7,6 +7,7 @@
// End of Source File Header
#include "GL_Getter.h"
#include <cmath>
#include <Config.h>
#include <MGGitHash.h>
#include <MG_Impl/GLImpl/VertexArray/Validators.h>
@@ -562,6 +563,10 @@ namespace MobileGL::MG_Impl::GLImpl {
case GL_SAMPLE_COVERAGE_VALUE:
params[0] = MG_State::pGLContext->GetSampleCoverageValue();
return;
case GL_POINT_FADE_THRESHOLD_SIZE:
// Float state: read it directly so the fractional part is not lost to the integer path.
params[0] = MG_State::pGLContext->GetPointFadeThresholdSize();
return;
default:
break;
}
@@ -837,6 +842,46 @@ namespace MobileGL::MG_Impl::GLImpl {
}
}
// glGetDoublev shares GetFloatv's accepted-pname set (and its INVALID_ENUM handling) and widens the
// result. MobileGL stores no native-double state (depth range/clear are float), so widening from
// float matches the resolution MobileGL actually holds. Only the pname's own component count is
// written, never a fixed 4, so a 1-component query cannot overrun the caller's buffer.
void GetDoublev(GLenum pname, GLdouble* params) {
if (!params) {
MG_State::pGLContext->RecordError(
ErrorCode::InvalidValue,
MakeUnique<GenericErrorInfo>("MG_Impl/GLImpl", __func__, "params pointer cannot be null"));
return;
}
GLfloat floats[4] = {};
GetFloatv(pname, floats);
GLsizei count = 1;
switch (pname) {
case GL_DEPTH_RANGE:
case GL_VIEWPORT_BOUNDS_RANGE:
case GL_ALIASED_LINE_WIDTH_RANGE:
case GL_ALIASED_POINT_SIZE_RANGE:
case GL_POINT_SIZE_RANGE:
case GL_SMOOTH_LINE_WIDTH_RANGE:
case GL_MAX_VIEWPORT_DIMS:
count = 2;
break;
case GL_BLEND_COLOR:
case GL_COLOR_CLEAR_VALUE:
case GL_VIEWPORT:
case GL_SCISSOR_BOX:
case GL_COLOR_WRITEMASK:
count = 4;
break;
default:
count = 1;
break;
}
for (GLsizei i = 0; i < count; ++i) {
params[i] = static_cast<GLdouble>(floats[i]);
}
}
void GetIntegerv(GLenum pname, GLint* params) {
MGLOG_D("glGetIntegerv, pname: %s", MG_Util::ConvertGLEnumToString(pname).c_str());
if (!params) {
@@ -1063,7 +1108,7 @@ namespace MobileGL::MG_Impl::GLImpl {
return;
}
case GL_FRAGMENT_SHADER_DERIVATIVE_HINT:
*params = GL_DONT_CARE;
*params = static_cast<GLint>(MG_State::pGLContext->GetHint(pname));
return;
case GL_IMPLEMENTATION_COLOR_READ_FORMAT: {
GLint format = 0;
@@ -1081,7 +1126,7 @@ namespace MobileGL::MG_Impl::GLImpl {
*params = MG_State::pGLContext->IsCapabilityEnabled(CapabilityInput::LineSmooth) ? GL_TRUE : GL_FALSE;
return;
case GL_LINE_SMOOTH_HINT:
*params = GL_DONT_CARE;
*params = static_cast<GLint>(MG_State::pGLContext->GetHint(pname));
return;
case GL_LINE_WIDTH:
*params = static_cast<GLint>(MG_State::pGLContext->GetLineWidth());
@@ -1290,7 +1335,10 @@ namespace MobileGL::MG_Impl::GLImpl {
return;
}
case GL_POINT_FADE_THRESHOLD_SIZE:
*params = 1;
*params = static_cast<GLint>(std::lround(MG_State::pGLContext->GetPointFadeThresholdSize()));
return;
case GL_POINT_SPRITE_COORD_ORIGIN:
*params = static_cast<GLint>(MG_State::pGLContext->GetPointSpriteCoordOrigin());
return;
case GL_PRIMITIVE_RESTART:
*params = MG_State::pGLContext->IsCapabilityEnabled(CapabilityInput::PrimitiveRestart) ? GL_TRUE
@@ -1341,7 +1389,7 @@ namespace MobileGL::MG_Impl::GLImpl {
*params = MG_State::pGLContext->IsCapabilityEnabled(CapabilityInput::PolygonSmooth) ? GL_TRUE : GL_FALSE;
return;
case GL_POLYGON_SMOOTH_HINT:
*params = GL_DONT_CARE;
*params = static_cast<GLint>(MG_State::pGLContext->GetHint(pname));
return;
case GL_READ_BUFFER:
if (const auto& fbo = MG_State::pGLContext->GetFramebufferBindingSlot(FramebufferTarget::Read)
@@ -1571,7 +1619,7 @@ namespace MobileGL::MG_Impl::GLImpl {
return;
}
case GL_TEXTURE_COMPRESSION_HINT:
*params = GL_DONT_CARE;
*params = static_cast<GLint>(MG_State::pGLContext->GetHint(pname));
return;
case GL_TEXTURE_BUFFER_OFFSET_ALIGNMENT:
*params = 0; // texture-buffer range entrypoints are stubbed