Files
MobileGL/MobileGL/MG_State/GLState/Core.h
T
BZLZHH dd745d7547 [Fix] (MG_State, MG_Impl): GL-order capture for geometry triangle strips
Vulkan transform feedback captures odd strip triangles as (i, i+2, i+1)
while GL table 10.1 decomposes them as (i+1, i, i+2). When the capture
stage is a triangle-strip geometry shader whose EmitVertex/EndPrimitive
sequence is statically knowable (no emission under control flow), link
time extracts the per-invocation strip lengths from the glslang AST, and
EndTransformFeedback rotates each odd triangle's captured vertex records
into GL order in place (bounded by the binding ranges' whole-triangle
capacity; raw input primitives tracked per Begin/End).
KHR-GL33.transform_feedback.geometry passes - the family is 21/21.
2026-08-01 03:17:30 -04:00

313 lines
18 KiB
C++

// MobileGL - MobileGL/MG_State/GLState/Core.h
// Copyright (c) 2025-2026 MobileGL-Dev
// Licensed under the GNU Lesser General Public License v3.0:
// https://www.gnu.org/licenses/gpl-3.0.txt
// https://www.gnu.org/licenses/lgpl-3.0.txt
// SPDX-License-Identifier: LGPL-3.0-only
// End of Source File Header
#pragma once
#include <Includes.h>
#include "ErrorState/Error.h"
#include "BufferState/BufferState.h"
#include "MG_State/GLState/RenderbufferState/RenderbufferObject.h"
#include "MG_State/GLState/RenderbufferState/RenderbufferState.h"
#include "RenderState/RenderState.h"
#include "ProgramState/ProgramState.h"
#include "SamplerState/SamplerState.h"
#include "TextureState/TextureState.h"
#include "FramebufferState/FramebufferState.h"
#include "VertexArrayState/VertexArrayState.h"
#include "RenderbufferState/RenderbufferState.h"
namespace MobileGL {
namespace MG_State {
void Init();
namespace GLState {
struct CurrentVertexAttributeValue {
Array<Float, 4> floatValue{0.f, 0.f, 0.f, 1.f};
Array<Int32, 4> intValue{0, 0, 0, 1};
Array<Uint32, 4> uintValue{0u, 0u, 0u, 1u};
};
// Which of the three views above a shader input of a given GLSL type consumes.
enum class VertexAttribBaseType { Unsupported, Float, Int, Uint };
struct VertexAttribTypeInfo {
VertexAttribBaseType baseType = VertexAttribBaseType::Unsupported;
Uint componentCount = 0;
};
// Maps a shader vertex-input type (GL_FLOAT_VEC3, GL_INT_VEC2, ...) onto the current-value
// view that feeds it. Shared by every backend so that "a disabled array reads the current
// value" resolves identically regardless of which backend is active; each backend only
// translates the result into its own API call.
VertexAttribTypeInfo ClassifyVertexAttribType(GLenum glType);
class GLContext {
public:
GLContext() = default;
// Error
void RecordError(ErrorCode code, UniquePtr<ErrorInfo> info);
Bool HasGLError() const;
Optional<const Error*> PeekNonGLError() const;
Optional<UniquePtr<Error>> PopNonGLError();
Bool HasNonGLError() const;
Optional<const Error*> PeekGLError() const;
Optional<UniquePtr<Error>> PopGLError();
void ClearErrors();
// Buffer
void GenBufferNames(Uint number, Vector<Uint>& buffers);
const SharedPtr<BufferObject>& GetBufferObject(Uint index);
BindingSlot<BufferObject>& GetBufferBindingSlot(BufferTarget target);
BindingSlotRange1D<BufferObject>& GetBufferBindingPoint(BufferTarget target, Uint index);
constexpr SizeT GetBufferBindingPointCount(BufferTarget target) const {
return m_bufferState.GetBindingPointCount(target);
}
void TouchBufferBindingPoint(BufferTarget target, Uint index) {
m_bufferState.TouchBindPoint(target, index);
}
SizeT GetTouchedBufferBindingPointCount(BufferTarget target) const {
return m_bufferState.GetTouchedBindPointCount(target);
}
const SharedPtr<BufferObject>& CreateBufferObject(Uint index);
void MarkBufferObjectForDeletion(Uint index);
Bool ValidateBufferName(Uint index) const;
Bool ValidateBufferObject(Uint index) const;
// VertexArray
void GenVertexArrayNames(Uint number, Vector<Uint>& vertexArrays);
const SharedPtr<VertexArrayObject>& GetVertexArrayObject(Uint index);
void BindVertexArray(Uint index);
const SharedPtr<VertexArrayObject>& CreateVertexArrayObject(Uint index);
void MarkVertexArrayForDeletion(Uint index);
Bool ValidateVertexArrayName(Uint index) const;
Bool ValidateVertexArrayObject(Uint index) const;
const SharedPtr<VertexArrayObject>& GetBoundVertexArray();
void SetCurrentVertexAttributeFloat(Uint index, const Array<Float, 4>& value);
void SetCurrentVertexAttributeInt(Uint index, const Array<Int32, 4>& value);
void SetCurrentVertexAttributeUint(Uint index, const Array<Uint32, 4>& value);
const CurrentVertexAttributeValue& GetCurrentVertexAttribute(Uint index) const;
// Texture
void GenTextureNames(Uint number, Vector<Uint>& textures);
const SharedPtr<ITextureObject>& GetTextureObject(Uint index);
// Per-target default texture object (name 0); see TextureState::GetDefaultTextureObject.
const SharedPtr<ITextureObject>& GetDefaultTextureObject(TextureTarget target) const;
const SharedPtr<ITextureObject>& CreateTextureObject(Uint index, TextureTarget target);
void MarkTextureObjectForDeletion(Uint index);
TextureUnit& GetTextureUnitObject(Int unit);
ImageTextureBinding& GetImageTextureBinding(Int unit);
const ImageTextureBinding& GetImageTextureBinding(Int unit) const;
void NoteTextureUnitTouched(Int unit) { m_textureState.NoteUnitTouched(unit); }
Int GetMaxTouchedTextureUnit() const { return m_textureState.GetMaxTouchedUnit(); }
// Monotonic counter bumped whenever a texture bind/unbind/delete changes which
// texture is bound at a unit; lets a backend skip re-resolving an unchanged
// per-draw sampled-texture set.
Uint64 GetTextureBindGeneration() const { return m_textureState.GetTextureBindGeneration(); }
void BumpTextureBindGeneration() { m_textureState.BumpTextureBindGeneration(); }
Bool ValidateTextureName(Uint index) const;
Bool ValidateTextureObject(Uint index) const;
Int GetActiveTextureUnit() const;
void SetActiveTextureUnit(Int unit);
// Program
Uint CreateProgram();
Uint CreateShader(ShaderStage stage);
void MarkProgramForDeletion(Uint index);
void MarkShaderForDeletion(Uint index);
// Frees a deletion-flagged shader's name once it lost its last GL-visible
// attachment (call after glDetachShader).
void ReleaseShaderNameIfOrphaned(Uint index);
Bool ValidateProgramName(Uint index) const;
Bool ValidateShaderName(Uint index) const;
const SharedPtr<ProgramObject>& GetProgramObject(Uint index);
const SharedPtr<ShaderObject>& GetShaderObject(Uint index);
void UseProgram(Uint program);
const SharedPtr<ProgramObject>& GetCurrentProgram();
// RenderState
Uint GetRenderStateParametersVersion() const;
const RenderStateParameters& GetRenderStateParameters() const;
void SetViewport(IntVec4 viewport); // x, y, width, height
const IntVec4& GetViewport() const; // x, y, width, height
void SetLineWidth(Float width);
Float GetLineWidth() const;
void SetPointSize(Float size);
Float GetPointSize() const;
void SetPolygonOffset(Float factor, Float units);
Float GetPolygonOffsetFactor() const;
Float GetPolygonOffsetUnits() const;
void SetHint(GLenum target, GLenum mode);
GLenum GetHint(GLenum target) const;
void SetPointFadeThresholdSize(Float size);
Float GetPointFadeThresholdSize() const;
void SetPointSpriteCoordOrigin(GLenum origin);
GLenum GetPointSpriteCoordOrigin() const;
void SetClampReadColor(GLenum clamp);
GLenum GetClampReadColor() const;
void SetPolygonMode(GLenum front, GLenum back);
GLenum GetPolygonModeFront() const;
GLenum GetPolygonModeBack() const;
void SetPrimitiveRestartIndex(Uint32 index);
Uint32 GetPrimitiveRestartIndex() const;
void SetCapability(CapabilityInput cap, Bool enabled);
Bool IsCapabilityEnabled(CapabilityInput cap) const;
void SetCapabilityIndexed(CapabilityInput cap, Uint index, Bool enabled);
Bool IsCapabilityEnabledIndexed(CapabilityInput cap, Uint index) const;
void SetBlendFunc(BlendFactor srcRGB, BlendFactor dstRGB, BlendFactor srcAlpha, BlendFactor dstAlpha);
void GetBlendFunc(BlendFactor& srcRGB, BlendFactor& dstRGB, BlendFactor& srcAlpha,
BlendFactor& dstAlpha) const;
void SetBlendFuncIndexed(Uint index, BlendFactor srcRGB, BlendFactor dstRGB, BlendFactor srcAlpha,
BlendFactor dstAlpha);
void GetBlendFuncIndexed(Uint index, BlendFactor& srcRGB, BlendFactor& dstRGB, BlendFactor& srcAlpha,
BlendFactor& dstAlpha) const;
void SetBlendEquation(BlendEquation color, BlendEquation alpha);
void GetBlendEquation(BlendEquation& color, BlendEquation& alpha) const;
void SetBlendEquationIndexed(Uint index, BlendEquation color, BlendEquation alpha);
void GetBlendEquationIndexed(Uint index, BlendEquation& color, BlendEquation& alpha) const;
void SetLogicOp(LogicOperation logicOp);
LogicOperation GetLogicOp() const;
void SetDepthFunc(DepthTestFunc func);
DepthTestFunc GetDepthFunc() const;
void SetDepthMask(Bool flag);
Bool GetDepthMask() const;
void SetStencilFunc(StencilFace face, DepthTestFunc func, Int ref, Uint32 mask);
void SetStencilMask(StencilFace face, Uint32 mask);
void SetStencilOp(StencilFace face, StencilOperation fail, StencilOperation depthFail,
StencilOperation depthPass);
const StencilFaceState& GetStencilState(StencilFace face) const;
void SetColorMask(BoolVec4 mask);
BoolVec4 GetColorMask() const;
void SetColorMaskIndexed(Uint index, BoolVec4 mask);
BoolVec4 GetColorMaskIndexed(Uint index) const;
void SetClearColor(FloatVec4 color);
const FloatVec4& GetClearColor() const;
void SetClearDepth(Float depth);
Float GetClearDepth() const;
void SetClearStencil(Int stencil);
Uint32 GetClearStencil() const;
void SetBlendColor(FloatVec4 color);
const FloatVec4& GetBlendColor() const;
void SetDepthRange(FloatVec2 range);
const FloatVec2& GetDepthRange() const;
void SetSampleCoverage(Float value, Bool invert);
Float GetSampleCoverageValue() const;
Bool GetSampleCoverageInvert() const;
void SetSampleMaskValue(Uint32 mask);
Uint32 GetSampleMaskValue() const;
void SetPixelStoreParam(PixelStoreParam param, Int value);
Int GetPixelStoreParam(PixelStoreParam param) const;
PixelStoreParameters GetPixelStoreParameters(Bool isUnpack) const;
void SetCullFaceMode(CullFaceMode mode);
CullFaceMode GetCullFaceMode() const;
void SetFrontFaceMode(FrontFaceMode mode);
FrontFaceMode GetFrontFaceMode() const;
void SetProvokingVertexMode(ProvokingVertexMode mode);
ProvokingVertexMode GetProvokingVertexMode() const;
void SetScissorBox(IntVec4 box); // x, y, width, height
const IntVec4& GetScissorBox() const; // x, y, width, height
// Transform feedback (GL 3.0 core Begin/End; no feedback objects yet)
void BeginTransformFeedback(GLenum primitiveMode, const SharedPtr<ProgramObject>& program) {
m_transformFeedbackActive = true;
m_transformFeedbackPrimitiveMode = primitiveMode;
m_transformFeedbackProgram = program;
++m_transformFeedbackGeneration;
m_transformFeedbackCapturedVertices = 0;
m_transformFeedbackInputPrimitives = 0;
}
void EndTransformFeedback() {
m_transformFeedbackActive = false;
m_transformFeedbackProgram.reset();
}
Bool IsTransformFeedbackActive() const { return m_transformFeedbackActive; }
GLenum GetTransformFeedbackPrimitiveMode() const { return m_transformFeedbackPrimitiveMode; }
const SharedPtr<ProgramObject>& GetTransformFeedbackProgram() const {
return m_transformFeedbackProgram;
}
// Bumped on every BeginTransformFeedback; the backend uses it to
// distinguish "resume appending" from "fresh capture".
Uint64 GetTransformFeedbackGeneration() const { return m_transformFeedbackGeneration; }
// CPU-side primitive accounting for the transform feedback queries:
// every captured draw adds its primitive count (draws without a
// geometry stage write exactly what they generate).
void AddTransformFeedbackPrimitives(Uint64 primitives) {
m_transformFeedbackPrimitiveCounter += primitives;
}
Uint64 GetTransformFeedbackPrimitiveCounter() const { return m_transformFeedbackPrimitiveCounter; }
// Vertices already captured since BeginTransformFeedback (drives the
// buffer-capacity clamp on the primitives-written accounting).
void AddTransformFeedbackCapturedVertices(Uint64 vertices) {
m_transformFeedbackCapturedVertices += vertices;
}
Uint64 GetTransformFeedbackCapturedVertices() const { return m_transformFeedbackCapturedVertices; }
// Raw assembled input primitives fed to the capture stage since Begin
// (pre-clamp; drives the GS strip capture-order fixup at EndTF).
void AddTransformFeedbackInputPrimitives(Uint64 primitives) {
m_transformFeedbackInputPrimitives += primitives;
}
Uint64 GetTransformFeedbackInputPrimitives() const { return m_transformFeedbackInputPrimitives; }
// Framebuffer
void GenFramebufferNames(Uint number, Vector<Uint>& framebuffers);
const SharedPtr<FramebufferObject>& GetFramebufferObject(Uint index);
BindingSlot<FramebufferObject>& GetFramebufferBindingSlot(FramebufferTarget target);
const SharedPtr<FramebufferObject>& CreateFramebufferObject(Uint index);
void MarkFramebufferObjectForDeletion(Uint index);
Bool ValidateFramebufferName(Uint index) const;
Bool ValidateFramebufferObject(Uint index) const;
// Sampler
void GenSamplerNames(Uint number, Vector<Uint>& samplers);
const SharedPtr<SamplerObject>& GetSamplerObject(Uint index);
const SharedPtr<SamplerObject>& CreateSamplerObject(Uint index);
void MarkSamplerObjectForDeletion(Uint index);
Bool ValidateSamplerName(Uint index) const;
Bool ValidateSamplerObject(Uint index) const;
// Renderbuffer
void GenRenderbufferNames(Uint number, Vector<Uint>& renderbuffers);
const SharedPtr<RenderbufferObject>& GetRenderbufferObject(Uint index);
BindingSlot<RenderbufferObject>& GetRenderbufferBindingSlot(RenderbufferTarget target);
const SharedPtr<RenderbufferObject>& CreateRenderbufferObject(Uint index);
void MarkRenderbufferObjectForDeletion(Uint index);
Bool ValidateRenderbufferName(Uint index) const;
Bool ValidateRenderbufferObject(Uint index) const;
private:
// State Components
ErrorState m_errorState;
BufferState m_bufferState;
VertexArrayState m_vertexArrayState;
Array<CurrentVertexAttributeValue, VertexArrayObject::MAX_VERTEX_ATTRIBS> m_currentVertexAttributes{};
Bool m_transformFeedbackActive = false;
GLenum m_transformFeedbackPrimitiveMode = GL_POINTS;
SharedPtr<ProgramObject> m_transformFeedbackProgram;
Uint64 m_transformFeedbackGeneration = 0;
Uint64 m_transformFeedbackPrimitiveCounter = 0;
Uint64 m_transformFeedbackCapturedVertices = 0;
Uint64 m_transformFeedbackInputPrimitives = 0;
TextureState m_textureState;
ProgramState m_programState;
RenderState m_renderState;
FramebufferState m_framebufferState;
SamplerState m_samplerState;
RenderbufferState m_renderbufferState;
};
} // namespace GLState
extern UniquePtr<GLState::GLContext>& pGLContext;
// True when relaxed GL semantics apply. Strict core rules are enforced only when the
// current EGL context explicitly requested a core profile (core bit in
// EGL_CONTEXT_OPENGL_PROFILE_MASK, or a >=3.1 version request without the compatibility
// bit) and MOBILEGL_RELAXED_SEMANTICS is off; no current context, legacy version
// requests, and the compatibility bit all relax.
Bool IsRelaxedSemanticsActive();
} // namespace MG_State
} // namespace MobileGL