mirror of
https://github.com/MobileGL-Dev/MobileGL
synced 2026-09-10 13:18:31 +09:00
[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:
@@ -7,6 +7,7 @@
|
||||
// End of Source File Header
|
||||
|
||||
#include "GL_RenderState.h"
|
||||
#include <cmath>
|
||||
#include <MG_State/GLState/Core.h>
|
||||
#include <MG_Util/Converters/GLToStr/GLEnumConverter.h>
|
||||
#include <MG_Util/Converters/GLToMG/RenderStateEnumConverter.h>
|
||||
@@ -207,12 +208,67 @@ namespace MobileGL::MG_Impl::GLImpl {
|
||||
MG_State::pGLContext->SetPointSize(static_cast<Float>(size));
|
||||
}
|
||||
|
||||
void PointParameterf_State(GLenum pname, GLfloat param) {
|
||||
// TODO: implement
|
||||
// Single funnel for all four glPointParameter forms. The two GL 3.3 core pnames both carry one
|
||||
// component, so the *v forms pass params[0], and the integer forms widen to float. The
|
||||
// GL_POINT_SPRITE_COORD_ORIGIN value is an enum passed as a float (36001.0/36002.0 are exact).
|
||||
void PointParameter_State(GLenum pname, GLfloat value) {
|
||||
switch (pname) {
|
||||
case GL_POINT_FADE_THRESHOLD_SIZE:
|
||||
if (value < 0.0f) {
|
||||
MG_State::pGLContext->RecordError(
|
||||
ErrorCode::InvalidValue,
|
||||
MakeUnique<GenericErrorInfo>("MG_Impl/GLImpl", __func__,
|
||||
"GL_POINT_FADE_THRESHOLD_SIZE must be non-negative."));
|
||||
return;
|
||||
}
|
||||
MG_State::pGLContext->SetPointFadeThresholdSize(value);
|
||||
return;
|
||||
case GL_POINT_SPRITE_COORD_ORIGIN: {
|
||||
const GLenum origin = static_cast<GLenum>(std::lround(value));
|
||||
if (origin != GL_LOWER_LEFT && origin != GL_UPPER_LEFT) {
|
||||
MG_State::pGLContext->RecordError(
|
||||
ErrorCode::InvalidEnum,
|
||||
MakeUnique<GenericErrorInfo>("MG_Impl/GLImpl", __func__,
|
||||
"GL_POINT_SPRITE_COORD_ORIGIN must be GL_LOWER_LEFT or "
|
||||
"GL_UPPER_LEFT."));
|
||||
return;
|
||||
}
|
||||
MG_State::pGLContext->SetPointSpriteCoordOrigin(origin);
|
||||
return;
|
||||
}
|
||||
default:
|
||||
MG_State::pGLContext->RecordError(
|
||||
ErrorCode::InvalidEnum,
|
||||
MakeUnique<GenericErrorInfo>("MG_Impl/GLImpl", __func__,
|
||||
"Unsupported point parameter pname: " + std::to_string(pname)));
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
void PointParameterf_State(GLenum pname, GLfloat param) { PointParameter_State(pname, param); }
|
||||
|
||||
void PointParameteri_State(GLenum pname, GLint param) {
|
||||
// TODO: implement
|
||||
PointParameter_State(pname, static_cast<GLfloat>(param));
|
||||
}
|
||||
|
||||
void PointParameterfv_State(GLenum pname, const GLfloat* params) {
|
||||
if (!params) {
|
||||
MG_State::pGLContext->RecordError(
|
||||
ErrorCode::InvalidValue,
|
||||
MakeUnique<GenericErrorInfo>("MG_Impl/GLImpl", __func__, "params pointer cannot be null."));
|
||||
return;
|
||||
}
|
||||
PointParameter_State(pname, params[0]);
|
||||
}
|
||||
|
||||
void PointParameteriv_State(GLenum pname, const GLint* params) {
|
||||
if (!params) {
|
||||
MG_State::pGLContext->RecordError(
|
||||
ErrorCode::InvalidValue,
|
||||
MakeUnique<GenericErrorInfo>("MG_Impl/GLImpl", __func__, "params pointer cannot be null."));
|
||||
return;
|
||||
}
|
||||
PointParameter_State(pname, static_cast<GLfloat>(params[0]));
|
||||
}
|
||||
|
||||
void PixelStorei_State(GLenum pname, GLint param) {
|
||||
@@ -302,7 +358,27 @@ namespace MobileGL::MG_Impl::GLImpl {
|
||||
}
|
||||
|
||||
void Hint_State(GLenum target, GLenum mode) {
|
||||
// TODO: implement
|
||||
switch (target) {
|
||||
case GL_LINE_SMOOTH_HINT:
|
||||
case GL_POLYGON_SMOOTH_HINT:
|
||||
case GL_TEXTURE_COMPRESSION_HINT:
|
||||
case GL_FRAGMENT_SHADER_DERIVATIVE_HINT:
|
||||
break;
|
||||
default:
|
||||
MG_State::pGLContext->RecordError(
|
||||
ErrorCode::InvalidEnum,
|
||||
MakeUnique<GenericErrorInfo>("MG_Impl/GLImpl", __func__,
|
||||
"Unsupported hint target: " + std::to_string(target)));
|
||||
return;
|
||||
}
|
||||
if (mode != GL_FASTEST && mode != GL_NICEST && mode != GL_DONT_CARE) {
|
||||
MG_State::pGLContext->RecordError(
|
||||
ErrorCode::InvalidEnum,
|
||||
MakeUnique<GenericErrorInfo>("MG_Impl/GLImpl", __func__,
|
||||
"Hint mode must be GL_FASTEST, GL_NICEST or GL_DONT_CARE."));
|
||||
return;
|
||||
}
|
||||
MG_State::pGLContext->SetHint(target, mode);
|
||||
}
|
||||
|
||||
void FrontFace_State(GLenum mode) {
|
||||
@@ -672,10 +748,36 @@ namespace MobileGL::MG_Impl::GLImpl {
|
||||
PointParameteri_State(pname, param);
|
||||
}
|
||||
|
||||
void PointParameterfv(GLenum pname, const GLfloat* params) {
|
||||
PointParameterfv_State(pname, params);
|
||||
}
|
||||
|
||||
void PointParameteriv(GLenum pname, const GLint* params) {
|
||||
PointParameteriv_State(pname, params);
|
||||
}
|
||||
|
||||
void PixelStorei(GLenum pname, GLint param) {
|
||||
PixelStorei_State(pname, param);
|
||||
}
|
||||
|
||||
void PixelStoref(GLenum pname, GLfloat param) {
|
||||
// Boolean pixel-store pnames convert by a zero-test (0.4 -> TRUE); integer pnames round to
|
||||
// nearest. Branch before converting so a fractional value cannot round a true flag to false.
|
||||
GLint intParam;
|
||||
switch (pname) {
|
||||
case GL_PACK_SWAP_BYTES:
|
||||
case GL_UNPACK_SWAP_BYTES:
|
||||
case GL_PACK_LSB_FIRST:
|
||||
case GL_UNPACK_LSB_FIRST:
|
||||
intParam = (param != 0.0f) ? 1 : 0;
|
||||
break;
|
||||
default:
|
||||
intParam = static_cast<GLint>(std::lround(param));
|
||||
break;
|
||||
}
|
||||
PixelStorei_State(pname, intParam);
|
||||
}
|
||||
|
||||
void LogicOp(GLenum opcode) {
|
||||
LogicOp_State(opcode);
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user