[Fix] (Sampler): carry GL_TEXTURE_BORDER_COLOR with its form, convert per GL 4.6 eq 2.2/2.3, and unify the name and scalar-pname error classes

This commit is contained in:
2026-08-27 08:35:00 -04:00
parent c136384f97
commit c1d89de729
7 changed files with 187 additions and 28 deletions
@@ -155,9 +155,21 @@ namespace MobileGL {
// an answer whichever form was written. Integer <-> float uses the plain value, matching
// what glTexParameterIiv/Iuiv mean: those forms are for integer texture formats, whose
// border components are the raw integers rather than a normalized fraction.
//
// Which of the three the application actually WROTE is recorded separately in
// borderColorForm, because the derived values erase it: a backend has to know whether to
// forward the colour through glSamplerParameterfv or glSamplerParameterIiv (and which
// VkBorderColor family to ask Vulkan for), and the numbers alone cannot say. That is also
// why every setter's early-out tests the form as well as the value - a float (0,0,0,1)
// followed by an integer (0,0,0,1) is a real state change even though nothing numeric
// moved, and swallowing it would leave the backend syncing the wrong entry point forever.
void SamplerObject::SetBorderColor(const FloatVec4& color) {
if (color == m_samplerParameters.borderColor) return;
if (color == m_samplerParameters.borderColor &&
m_samplerParameters.borderColorForm == BorderColorForm::Float) {
return;
}
m_samplerParameters.borderColorForm = BorderColorForm::Float;
m_samplerParameters.borderColor = color;
m_samplerParameters.borderColorI =
IntVec4(static_cast<Int32>(color.x()), static_cast<Int32>(color.y()),
@@ -169,8 +181,12 @@ namespace MobileGL {
}
void SamplerObject::SetBorderColorI(const IntVec4& color) {
if (color == m_samplerParameters.borderColorI) return;
if (color == m_samplerParameters.borderColorI &&
m_samplerParameters.borderColorForm == BorderColorForm::Int) {
return;
}
m_samplerParameters.borderColorForm = BorderColorForm::Int;
m_samplerParameters.borderColorI = color;
m_samplerParameters.borderColorUI =
UintVec4(static_cast<Uint32>(color.x()), static_cast<Uint32>(color.y()),
@@ -182,8 +198,12 @@ namespace MobileGL {
}
void SamplerObject::SetBorderColorUI(const UintVec4& color) {
if (color == m_samplerParameters.borderColorUI) return;
if (color == m_samplerParameters.borderColorUI &&
m_samplerParameters.borderColorForm == BorderColorForm::Uint) {
return;
}
m_samplerParameters.borderColorForm = BorderColorForm::Uint;
m_samplerParameters.borderColorUI = color;
m_samplerParameters.borderColorI =
IntVec4(static_cast<Int32>(color.x()), static_cast<Int32>(color.y()),
@@ -206,6 +226,10 @@ namespace MobileGL {
return m_samplerParameters.borderColorUI;
}
BorderColorForm SamplerObject::GetBorderColorForm() const {
return m_samplerParameters.borderColorForm;
}
SamplerCompareMode SamplerObject::GetCompareMode() const {
return m_samplerParameters.compareMode;
}
@@ -56,6 +56,19 @@ namespace MobileGL {
Unknown = -1
};
// Which of the three GL_TEXTURE_BORDER_COLOR entry-point families last wrote the border colour,
// and therefore which of the three stored representations is AUTHORITATIVE. GL 4.6 core 8.10:
// TexParameterIiv/Iuiv store an integer border colour "unmodified, with an internal data type of
// integer", TexParameterfv stores a floating-point one, and the derived forms are only a
// convenience for a getter of the other spelling. A backend cannot pick the right driver entry
// point (glSamplerParameterIiv vs fv) or the right VkBorderColor family without this: numerically
// the three representations are always populated, so the value alone says nothing about the form.
enum class BorderColorForm : Uint8 {
Float,
Int,
Uint
};
struct SamplerParameters {
SamplerWrapMode wrapS = SamplerWrapMode::Repeat;
SamplerWrapMode wrapT = SamplerWrapMode::Repeat;
@@ -79,6 +92,7 @@ namespace MobileGL {
FloatVec4 borderColor = {0.0f, 0.0f, 0.0f, 0.0f};
IntVec4 borderColorI = {0, 0, 0, 0};
UintVec4 borderColorUI = {0, 0, 0, 0};
BorderColorForm borderColorForm = BorderColorForm::Float;
};
namespace MG_State {
@@ -117,6 +131,7 @@ namespace MobileGL {
const FloatVec4& GetBorderColor() const;
const IntVec4& GetBorderColorI() const;
const UintVec4& GetBorderColorUI() const;
BorderColorForm GetBorderColorForm() const;
Uint GetExternalIndex() const;
Uint16 GetVersion() const;
// Globally-unique, never-reused id for this sampler object's lifetime. Lets a
@@ -113,8 +113,14 @@ namespace MobileGL {
return m_sampler->GetBorderColor();
}
// The redundancy filters test the FORM as well as the value: the derived representations
// make a float (0,0,0,1) and an integer (0,0,0,1) numerically identical, but they are
// different GL state and the DirectGLES sync memoises on m_textureParamsVersion.
void TextureObjectBase::SetBorderColor(const FloatVec4& color) {
if (color == m_sampler->GetBorderColor()) return;
if (color == m_sampler->GetBorderColor() &&
m_sampler->GetBorderColorForm() == BorderColorForm::Float) {
return;
}
m_sampler->SetBorderColor(color);
++m_textureParamsVersion;
@@ -125,7 +131,10 @@ namespace MobileGL {
}
void TextureObjectBase::SetBorderColorI(const IntVec4& color) {
if (color == m_sampler->GetBorderColorI()) return;
if (color == m_sampler->GetBorderColorI() &&
m_sampler->GetBorderColorForm() == BorderColorForm::Int) {
return;
}
m_sampler->SetBorderColorI(color);
++m_textureParamsVersion;
@@ -136,12 +145,19 @@ namespace MobileGL {
}
void TextureObjectBase::SetBorderColorUI(const UintVec4& color) {
if (color == m_sampler->GetBorderColorUI()) return;
if (color == m_sampler->GetBorderColorUI() &&
m_sampler->GetBorderColorForm() == BorderColorForm::Uint) {
return;
}
m_sampler->SetBorderColorUI(color);
++m_textureParamsVersion;
}
BorderColorForm TextureObjectBase::GetBorderColorForm() const {
return m_sampler->GetBorderColorForm();
}
TextureSwizzleParam TextureObjectBase::GetSwizzleParam(TextureSwizzleParam param) const {
switch (param) {
case TextureSwizzleParam::Red:
@@ -40,6 +40,8 @@ namespace MobileGL::MG_State::GLState {
virtual void SetBorderColorI(const IntVec4& color) = 0;
virtual const UintVec4& GetBorderColorUI() const = 0;
virtual void SetBorderColorUI(const UintVec4& color) = 0;
// Which of the three setters above last ran; see SamplerParameters::borderColorForm.
virtual BorderColorForm GetBorderColorForm() const = 0;
virtual TextureSwizzleParam GetSwizzleParam(TextureSwizzleParam param) const = 0;
virtual void SetSwizzleParam(TextureSwizzleParam param, TextureSwizzleParam value) = 0;
virtual void SetSwizzleParamRGBA(const Vec4<TextureSwizzleParam>& values) = 0;
@@ -129,6 +131,7 @@ namespace MobileGL::MG_State::GLState {
void SetBorderColorI(const IntVec4& color) override;
const UintVec4& GetBorderColorUI() const override;
void SetBorderColorUI(const UintVec4& color) override;
BorderColorForm GetBorderColorForm() const override;
TextureSwizzleParam GetSwizzleParam(TextureSwizzleParam param) const override;
const Vec4<TextureSwizzleParam>& GetAllSwizzleParams() const override;
void SetSwizzleParam(TextureSwizzleParam param, TextureSwizzleParam value) override;