mirror of
https://github.com/MobileGL-Dev/MobileGL
synced 2026-09-07 19:58:32 +09:00
[Feat] (RenderState): implement glClipControl, glPolygonOffsetClamp and glTextureBarrier instead of stubbing them
This commit is contained in:
@@ -846,6 +846,27 @@ namespace MobileGL::MG_Impl::GLImpl {
|
||||
memoryBarrier(barriers);
|
||||
}
|
||||
|
||||
void TextureBarrier() {
|
||||
// GL 4.5 core 8.26 / GL_ARB_texture_barrier: order every write the fixed-function
|
||||
// framebuffer has already issued ahead of every subsequent texture fetch, so a shader may
|
||||
// read texels of a texture that is also attached to the current framebuffer.
|
||||
//
|
||||
// Both backends serve this through their existing memory-barrier hook rather than a new
|
||||
// entry point of their own: GL_FRAMEBUFFER_BARRIER_BIT is the source half (framebuffer
|
||||
// writes) and GL_TEXTURE_FETCH_BARRIER_BIT the destination half (texture fetches), which
|
||||
// is exactly the dependency ARB_texture_barrier defines - just expressed with the wider
|
||||
// scope glMemoryBarrier gives it. That is a superset of the required ordering, never a
|
||||
// subset, so it cannot under-synchronize.
|
||||
auto memoryBarrier = MG_Backend::gBackendFunctionsTable.GL.MemoryBarrier;
|
||||
if (!memoryBarrier) {
|
||||
MG_State::pGLContext->RecordError(
|
||||
ErrorCode::InvalidOperation,
|
||||
MakeUnique<GenericErrorInfo>("MG_Impl/GLImpl", __func__, "Backend does not support memory barriers."));
|
||||
return;
|
||||
}
|
||||
memoryBarrier(GL_TEXTURE_FETCH_BARRIER_BIT | GL_FRAMEBUFFER_BARRIER_BIT);
|
||||
}
|
||||
|
||||
void MemoryBarrierByRegion(GLbitfield barriers) {
|
||||
if (!ValidateMemoryBarrierBits(__func__, barriers)) return;
|
||||
auto memoryBarrierByRegion = MG_Backend::gBackendFunctionsTable.GL.MemoryBarrierByRegion;
|
||||
|
||||
@@ -35,6 +35,7 @@ namespace MobileGL::MG_Impl::GLImpl {
|
||||
void PatchParameterfv(GLenum pname, const GLfloat* values);
|
||||
void MemoryBarrier(GLbitfield barriers);
|
||||
void MemoryBarrierByRegion(GLbitfield barriers);
|
||||
void TextureBarrier();
|
||||
void MultiDrawElementsIndirect(GLenum mode, GLenum type, const void* indirect, GLsizei drawcount, GLsizei stride);
|
||||
void MultiDrawArraysIndirect(GLenum mode, const void* indirect, GLsizei drawcount, GLsizei stride);
|
||||
void MultiDrawElementsIndirectCount(GLenum mode, GLenum type, const void* indirect, GLintptr drawcount,
|
||||
|
||||
@@ -994,7 +994,7 @@ DECLARE_GL_FUNCTION_HEAD(void, BindTextures, GLuint first, GLsizei count, const
|
||||
DECLARE_GL_FUNCTION_HEAD(void, BindSamplers, GLuint first, GLsizei count, const GLuint* samplers) DECLARE_GL_FUNCTION_END_NO_RETURN(void, BindSamplers, first, count, samplers)
|
||||
DECLARE_GL_FUNCTION_HEAD(void, BindImageTextures, GLuint first, GLsizei count, const GLuint* textures) DECLARE_GL_FUNCTION_END_NO_RETURN(void, BindImageTextures, first, count, textures)
|
||||
DECLARE_GL_FUNCTION_HEAD(void, BindVertexBuffers, GLuint first, GLsizei count, const GLuint* buffers, const GLintptr* offsets, const GLsizei* strides) DECLARE_GL_FUNCTION_END_NO_RETURN(void, BindVertexBuffers, first, count, buffers, offsets, strides)
|
||||
DECLARE_GL_FUNCTION_STUB_HEAD(void, ClipControl, GLenum origin, GLenum depth) DECLARE_GL_FUNCTION_STUB_END_NO_RETURN(void, ClipControl, origin, depth)
|
||||
DECLARE_GL_FUNCTION_HEAD(void, ClipControl, GLenum origin, GLenum depth) DECLARE_GL_FUNCTION_END_NO_RETURN(void, ClipControl, origin, depth)
|
||||
DECLARE_GL_FUNCTION_HEAD(void, CreateTransformFeedbacks, GLsizei n, GLuint* ids) DECLARE_GL_FUNCTION_END_NO_RETURN(void, CreateTransformFeedbacks, n, ids)
|
||||
DECLARE_GL_FUNCTION_HEAD(void, TransformFeedbackBufferBase, GLuint xfb, GLuint index, GLuint buffer) DECLARE_GL_FUNCTION_END_NO_RETURN(void, TransformFeedbackBufferBase, xfb, index, buffer)
|
||||
DECLARE_GL_FUNCTION_HEAD(void, TransformFeedbackBufferRange, GLuint xfb, GLuint index, GLuint buffer, GLintptr offset, GLsizeiptr size) DECLARE_GL_FUNCTION_END_NO_RETURN(void, TransformFeedbackBufferRange, xfb, index, buffer, offset, size)
|
||||
@@ -1107,11 +1107,11 @@ DECLARE_GL_FUNCTION_STUB_HEAD(void, GetnConvolutionFilter, GLenum target, GLenum
|
||||
DECLARE_GL_FUNCTION_STUB_HEAD(void, GetnSeparableFilter, GLenum target, GLenum format, GLenum type, GLsizei rowBufSize, void* row, GLsizei columnBufSize, void* column, void* span) DECLARE_GL_FUNCTION_STUB_END_NO_RETURN(void, GetnSeparableFilter, target, format, type, rowBufSize, row, columnBufSize, column, span)
|
||||
DECLARE_GL_FUNCTION_STUB_HEAD(void, GetnHistogram, GLenum target, GLboolean reset, GLenum format, GLenum type, GLsizei bufSize, void* values) DECLARE_GL_FUNCTION_STUB_END_NO_RETURN(void, GetnHistogram, target, reset, format, type, bufSize, values)
|
||||
DECLARE_GL_FUNCTION_STUB_HEAD(void, GetnMinmax, GLenum target, GLboolean reset, GLenum format, GLenum type, GLsizei bufSize, void* values) DECLARE_GL_FUNCTION_STUB_END_NO_RETURN(void, GetnMinmax, target, reset, format, type, bufSize, values)
|
||||
DECLARE_GL_FUNCTION_STUB_HEAD(void, TextureBarrier, void) DECLARE_GL_FUNCTION_STUB_END_NO_RETURN(void, TextureBarrier, )
|
||||
DECLARE_GL_FUNCTION_HEAD(void, TextureBarrier, void) DECLARE_GL_FUNCTION_END_NO_RETURN(void, TextureBarrier, )
|
||||
DECLARE_GL_FUNCTION_STUB_HEAD(void, SpecializeShader, GLuint shader, const GLchar* pEntryPoint, GLuint numSpecializationConstants, const GLuint* pConstantIndex, const GLuint* pConstantValue) DECLARE_GL_FUNCTION_STUB_END_NO_RETURN(void, SpecializeShader, shader, pEntryPoint, numSpecializationConstants, pConstantIndex, pConstantValue)
|
||||
DECLARE_GL_FUNCTION_HEAD(void, MultiDrawArraysIndirectCount, GLenum mode, const void* indirect, GLintptr drawcount, GLsizei maxdrawcount, GLsizei stride) DECLARE_GL_FUNCTION_END_NO_RETURN(void, MultiDrawArraysIndirectCount, mode, indirect, drawcount, maxdrawcount, stride)
|
||||
DECLARE_GL_FUNCTION_HEAD(void, MultiDrawElementsIndirectCount, GLenum mode, GLenum type, const void* indirect, GLintptr drawcount, GLsizei maxdrawcount, GLsizei stride) DECLARE_GL_FUNCTION_END_NO_RETURN(void, MultiDrawElementsIndirectCount, mode, type, indirect, drawcount, maxdrawcount, stride)
|
||||
DECLARE_GL_FUNCTION_STUB_HEAD(void, PolygonOffsetClamp, GLfloat factor, GLfloat units, GLfloat clamp) DECLARE_GL_FUNCTION_STUB_END_NO_RETURN(void, PolygonOffsetClamp, factor, units, clamp)
|
||||
DECLARE_GL_FUNCTION_HEAD(void, PolygonOffsetClamp, GLfloat factor, GLfloat units, GLfloat clamp) DECLARE_GL_FUNCTION_END_NO_RETURN(void, PolygonOffsetClamp, factor, units, clamp)
|
||||
DECLARE_GL_FUNCTION_STUB_HEAD(void, PrimitiveBoundingBoxARB, GLfloat minX, GLfloat minY, GLfloat minZ, GLfloat minW, GLfloat maxX, GLfloat maxY, GLfloat maxZ, GLfloat maxW) DECLARE_GL_FUNCTION_STUB_END(void, PrimitiveBoundingBoxARB, minX, minY, minZ, minW, maxX, maxY, maxZ, maxW)
|
||||
DECLARE_GL_FUNCTION_STUB_HEAD(GLuint64, GetTextureHandleARB, GLuint texture) DECLARE_GL_FUNCTION_STUB_END(GLuint64, GetTextureHandleARB, texture)
|
||||
DECLARE_GL_FUNCTION_STUB_HEAD(GLuint64, GetTextureSamplerHandleARB, GLuint texture, GLuint sampler) DECLARE_GL_FUNCTION_STUB_END(GLuint64, GetTextureSamplerHandleARB, texture, sampler)
|
||||
@@ -2049,7 +2049,7 @@ DECLARE_GL_FUNCTION_STUB_HEAD(void, GetPixelTransformParameterivEXT, GLenum targ
|
||||
DECLARE_GL_FUNCTION_STUB_HEAD(void, GetPixelTransformParameterfvEXT, GLenum target, GLenum pname, GLfloat* params) DECLARE_GL_FUNCTION_STUB_END_NO_RETURN(void, GetPixelTransformParameterfvEXT, target, pname, params)
|
||||
DECLARE_GL_FUNCTION_STUB_HEAD(void, PointParameterfEXT, GLenum pname, GLfloat param) DECLARE_GL_FUNCTION_STUB_END_NO_RETURN(void, PointParameterfEXT, pname, param)
|
||||
DECLARE_GL_FUNCTION_STUB_HEAD(void, PointParameterfvEXT, GLenum pname, const GLfloat* params) DECLARE_GL_FUNCTION_STUB_END_NO_RETURN(void, PointParameterfvEXT, pname, params)
|
||||
DECLARE_GL_FUNCTION_STUB_HEAD(void, PolygonOffsetClampEXT, GLfloat factor, GLfloat units, GLfloat clamp) DECLARE_GL_FUNCTION_STUB_END_NO_RETURN(void, PolygonOffsetClampEXT, factor, units, clamp)
|
||||
DECLARE_GL_FUNCTION_HEAD(void, PolygonOffsetClampEXT, GLfloat factor, GLfloat units, GLfloat clamp) DECLARE_GL_FUNCTION_END_NO_RETURN(void, PolygonOffsetClamp, factor, units, clamp)
|
||||
DECLARE_GL_FUNCTION_HEAD(void, ProvokingVertexEXT, GLenum mode) DECLARE_GL_FUNCTION_END_NO_RETURN(void, ProvokingVertex, mode)
|
||||
DECLARE_GL_FUNCTION_STUB_HEAD(void, RasterSamplesEXT, GLuint samples, GLboolean fixedsamplelocations) DECLARE_GL_FUNCTION_STUB_END_NO_RETURN(void, RasterSamplesEXT, samples, fixedsamplelocations)
|
||||
DECLARE_GL_FUNCTION_STUB_HEAD(void, SecondaryColor3bEXT, GLbyte red, GLbyte green, GLbyte blue) DECLARE_GL_FUNCTION_STUB_END_NO_RETURN(void, SecondaryColor3bEXT, red, green, blue)
|
||||
@@ -2546,7 +2546,7 @@ DECLARE_GL_FUNCTION_STUB_HEAD(void, ShadingRateImageBarrierNV, GLboolean synchro
|
||||
DECLARE_GL_FUNCTION_STUB_HEAD(void, ShadingRateImagePaletteNV, GLuint viewport, GLuint first, GLsizei count, const GLenum* rates) DECLARE_GL_FUNCTION_STUB_END_NO_RETURN(void, ShadingRateImagePaletteNV, viewport, first, count, rates)
|
||||
DECLARE_GL_FUNCTION_STUB_HEAD(void, ShadingRateSampleOrderNV, GLenum order) DECLARE_GL_FUNCTION_STUB_END_NO_RETURN(void, ShadingRateSampleOrderNV, order)
|
||||
DECLARE_GL_FUNCTION_STUB_HEAD(void, ShadingRateSampleOrderCustomNV, GLenum rate, GLuint samples, const GLint* locations) DECLARE_GL_FUNCTION_STUB_END_NO_RETURN(void, ShadingRateSampleOrderCustomNV, rate, samples, locations)
|
||||
DECLARE_GL_FUNCTION_STUB_HEAD(void, TextureBarrierNV, void) DECLARE_GL_FUNCTION_STUB_END_NO_RETURN(void, TextureBarrierNV, )
|
||||
DECLARE_GL_FUNCTION_HEAD(void, TextureBarrierNV, void) DECLARE_GL_FUNCTION_END_NO_RETURN(void, TextureBarrier, )
|
||||
DECLARE_GL_FUNCTION_STUB_HEAD(void, TexImage2DMultisampleCoverageNV, GLenum target, GLsizei coverageSamples, GLsizei colorSamples, GLint internalFormat, GLsizei width, GLsizei height, GLboolean fixedSampleLocations) DECLARE_GL_FUNCTION_STUB_END_NO_RETURN(void, TexImage2DMultisampleCoverageNV, target, coverageSamples, colorSamples, internalFormat, width, height, fixedSampleLocations)
|
||||
DECLARE_GL_FUNCTION_STUB_HEAD(void, TexImage3DMultisampleCoverageNV, GLenum target, GLsizei coverageSamples, GLsizei colorSamples, GLint internalFormat, GLsizei width, GLsizei height, GLsizei depth, GLboolean fixedSampleLocations) DECLARE_GL_FUNCTION_STUB_END_NO_RETURN(void, TexImage3DMultisampleCoverageNV, target, coverageSamples, colorSamples, internalFormat, width, height, depth, fixedSampleLocations)
|
||||
DECLARE_GL_FUNCTION_STUB_HEAD(void, TextureImage2DMultisampleNV, GLuint texture, GLenum target, GLsizei samples, GLint internalFormat, GLsizei width, GLsizei height, GLboolean fixedSampleLocations) DECLARE_GL_FUNCTION_STUB_END_NO_RETURN(void, TextureImage2DMultisampleNV, texture, target, samples, internalFormat, width, height, fixedSampleLocations)
|
||||
|
||||
@@ -340,6 +340,38 @@ namespace MobileGL::MG_Impl::GLImpl {
|
||||
MG_State::pGLContext->SetPolygonOffset(static_cast<Float>(factor), static_cast<Float>(units));
|
||||
}
|
||||
|
||||
void PolygonOffsetClamp_State(GLfloat factor, GLfloat units, GLfloat clamp) {
|
||||
// GL 4.6 core 14.6.5 / GL_EXT_polygon_offset_clamp. No error cases: any three floats are
|
||||
// legal, and clamp = 0 is exactly glPolygonOffset. Whether the backend can APPLY the clamp
|
||||
// is a separate question (see the DirectGLES/DirectVulkan forwarding); the state is
|
||||
// recorded either way, because GL_POLYGON_OFFSET_CLAMP has to read back what was written.
|
||||
MG_State::pGLContext->SetPolygonOffsetClamped(static_cast<Float>(factor), static_cast<Float>(units),
|
||||
static_cast<Float>(clamp));
|
||||
}
|
||||
|
||||
void ClipControl_State(GLenum origin, GLenum depth) {
|
||||
// GL 4.5 core 13.5: both arguments are strict enums, and either being wrong is
|
||||
// GL_INVALID_ENUM with the state left untouched.
|
||||
if (origin != GL_LOWER_LEFT && origin != GL_UPPER_LEFT) {
|
||||
MG_State::pGLContext->RecordError(
|
||||
ErrorCode::InvalidEnum,
|
||||
MakeUnique<GenericErrorInfo>("MG_Impl/GLImpl", __func__,
|
||||
"glClipControl origin must be GL_LOWER_LEFT or GL_UPPER_LEFT; got " +
|
||||
MG_Util::ConvertGLEnumToString(origin) + "."));
|
||||
return;
|
||||
}
|
||||
if (depth != GL_NEGATIVE_ONE_TO_ONE && depth != GL_ZERO_TO_ONE) {
|
||||
MG_State::pGLContext->RecordError(
|
||||
ErrorCode::InvalidEnum,
|
||||
MakeUnique<GenericErrorInfo>(
|
||||
"MG_Impl/GLImpl", __func__,
|
||||
"glClipControl depth must be GL_NEGATIVE_ONE_TO_ONE or GL_ZERO_TO_ONE; got " +
|
||||
MG_Util::ConvertGLEnumToString(depth) + "."));
|
||||
return;
|
||||
}
|
||||
MG_State::pGLContext->SetClipControl(origin, depth);
|
||||
}
|
||||
|
||||
void PolygonMode_State(GLenum face, GLenum mode) {
|
||||
// GL 3.3 core: separate front/back polygon modes were removed in 3.1, so the only legal
|
||||
// face is GL_FRONT_AND_BACK. GL_FRONT / GL_BACK must be rejected (some desktop drivers
|
||||
@@ -1029,6 +1061,14 @@ namespace MobileGL::MG_Impl::GLImpl {
|
||||
PolygonOffset_State(factor, units);
|
||||
}
|
||||
|
||||
void PolygonOffsetClamp(GLfloat factor, GLfloat units, GLfloat clamp) {
|
||||
PolygonOffsetClamp_State(factor, units, clamp);
|
||||
}
|
||||
|
||||
void ClipControl(GLenum origin, GLenum depth) {
|
||||
ClipControl_State(origin, depth);
|
||||
}
|
||||
|
||||
void PolygonMode(GLenum face, GLenum mode) {
|
||||
PolygonMode_State(face, mode);
|
||||
}
|
||||
|
||||
@@ -40,6 +40,8 @@ namespace MobileGL::MG_Impl::GLImpl {
|
||||
void SampleCoverage(GLfloat value, GLboolean invert);
|
||||
void MinSampleShading(GLfloat value);
|
||||
void PolygonOffset(GLfloat factor, GLfloat units);
|
||||
void PolygonOffsetClamp(GLfloat factor, GLfloat units, GLfloat clamp);
|
||||
void ClipControl(GLenum origin, GLenum depth);
|
||||
void PolygonMode(GLenum face, GLenum mode);
|
||||
void PointSize(GLfloat size);
|
||||
void PointParameterf(GLenum pname, GLfloat param);
|
||||
|
||||
@@ -848,6 +848,26 @@ namespace MobileGL::MG_State {
|
||||
return m_renderState.GetPolygonOffsetUnits();
|
||||
}
|
||||
|
||||
void GLContext::SetPolygonOffsetClamped(Float factor, Float units, Float clamp) {
|
||||
m_renderState.SetPolygonOffsetClamped(factor, units, clamp);
|
||||
}
|
||||
|
||||
Float GLContext::GetPolygonOffsetClamp() const {
|
||||
return m_renderState.GetPolygonOffsetClamp();
|
||||
}
|
||||
|
||||
void GLContext::SetClipControl(GLenum origin, GLenum depth) {
|
||||
m_renderState.SetClipControl(origin, depth);
|
||||
}
|
||||
|
||||
GLenum GLContext::GetClipOrigin() const {
|
||||
return m_renderState.GetClipOrigin();
|
||||
}
|
||||
|
||||
GLenum GLContext::GetClipDepthMode() const {
|
||||
return m_renderState.GetClipDepthMode();
|
||||
}
|
||||
|
||||
void GLContext::SetCapability(CapabilityInput cap, Bool enabled) {
|
||||
m_renderState.SetCapability(cap, enabled);
|
||||
}
|
||||
|
||||
@@ -218,8 +218,13 @@ namespace MobileGL {
|
||||
void SetPatchDefaultInnerLevel(const FloatVec2& levels);
|
||||
const FloatVec2& GetPatchDefaultInnerLevel() const;
|
||||
void SetPolygonOffset(Float factor, Float units);
|
||||
void SetPolygonOffsetClamped(Float factor, Float units, Float clamp);
|
||||
Float GetPolygonOffsetFactor() const;
|
||||
Float GetPolygonOffsetUnits() const;
|
||||
Float GetPolygonOffsetClamp() const;
|
||||
void SetClipControl(GLenum origin, GLenum depth);
|
||||
GLenum GetClipOrigin() const;
|
||||
GLenum GetClipDepthMode() const;
|
||||
void SetHint(GLenum target, GLenum mode);
|
||||
GLenum GetHint(GLenum target) const;
|
||||
void SetPointFadeThresholdSize(Float size);
|
||||
|
||||
@@ -263,6 +263,37 @@ namespace MobileGL {
|
||||
return m_parameters.PolygonOffsetUnits;
|
||||
}
|
||||
|
||||
void RenderState::SetPolygonOffsetClamped(Float factor, Float units, Float clamp) {
|
||||
if (m_parameters.PolygonOffsetFactor == factor && m_parameters.PolygonOffsetUnits == units &&
|
||||
m_parameters.PolygonOffsetClamp == clamp)
|
||||
return;
|
||||
|
||||
m_parameters.PolygonOffsetFactor = factor;
|
||||
m_parameters.PolygonOffsetUnits = units;
|
||||
m_parameters.PolygonOffsetClamp = clamp;
|
||||
++m_version;
|
||||
}
|
||||
|
||||
Float RenderState::GetPolygonOffsetClamp() const {
|
||||
return m_parameters.PolygonOffsetClamp;
|
||||
}
|
||||
|
||||
void RenderState::SetClipControl(GLenum origin, GLenum depth) {
|
||||
if (m_parameters.ClipOrigin == origin && m_parameters.ClipDepthMode == depth) return;
|
||||
|
||||
m_parameters.ClipOrigin = origin;
|
||||
m_parameters.ClipDepthMode = depth;
|
||||
++m_version;
|
||||
}
|
||||
|
||||
GLenum RenderState::GetClipOrigin() const {
|
||||
return m_parameters.ClipOrigin;
|
||||
}
|
||||
|
||||
GLenum RenderState::GetClipDepthMode() const {
|
||||
return m_parameters.ClipDepthMode;
|
||||
}
|
||||
|
||||
// -------------------- Capabilities --------------------
|
||||
namespace {
|
||||
// CapabilityInput lists ClipDistance0..7 contiguously (RenderState.h); the caller
|
||||
|
||||
@@ -249,6 +249,15 @@ namespace MobileGL {
|
||||
FloatVec2 PatchDefaultInnerLevel = FloatVec2(1.0f, 1.0f);
|
||||
Float PolygonOffsetFactor = 0.0f;
|
||||
Float PolygonOffsetUnits = 0.0f;
|
||||
// GL_POLYGON_OFFSET_CLAMP (GL 4.6 core 14.6.5 / GL_EXT_polygon_offset_clamp): the maximum
|
||||
// magnitude of the offset glPolygonOffsetClamp's third argument allows. Zero - the default
|
||||
// - means "no clamp", which is exactly the behaviour glPolygonOffset leaves behind.
|
||||
Float PolygonOffsetClamp = 0.0f;
|
||||
|
||||
// glClipControl (GL 4.5 core 13.5). Defaults per table 23.7 are the pre-4.5 fixed
|
||||
// behaviour: origin at the lower left, depth mapped from -1..1.
|
||||
GLenum ClipOrigin = GL_LOWER_LEFT;
|
||||
GLenum ClipDepthMode = GL_NEGATIVE_ONE_TO_ONE;
|
||||
|
||||
// Blending
|
||||
Array<PerBufferBlendState, MG_State::GLState::FramebufferObject::MAX_DRAW_BUFFERS> BlendStates;
|
||||
@@ -391,8 +400,16 @@ namespace MobileGL {
|
||||
void SetPatchDefaultInnerLevel(const FloatVec2& levels);
|
||||
const FloatVec2& GetPatchDefaultInnerLevel() const;
|
||||
void SetPolygonOffset(Float factor, Float units);
|
||||
// glPolygonOffsetClamp. Writes the same factor/units as glPolygonOffset plus the
|
||||
// clamp, because that is what the entry point does - glPolygonOffset is the
|
||||
// clamp = 0 case of it (GL 4.6 core 14.6.5).
|
||||
void SetPolygonOffsetClamped(Float factor, Float units, Float clamp);
|
||||
Float GetPolygonOffsetFactor() const;
|
||||
Float GetPolygonOffsetUnits() const;
|
||||
Float GetPolygonOffsetClamp() const;
|
||||
void SetClipControl(GLenum origin, GLenum depth);
|
||||
GLenum GetClipOrigin() const;
|
||||
GLenum GetClipDepthMode() const;
|
||||
// Hints. target must be one of the 4 GL 3.3 core hint targets (validated by the caller).
|
||||
void SetHint(GLenum target, GLenum mode);
|
||||
GLenum GetHint(GLenum target) const;
|
||||
|
||||
@@ -885,3 +885,134 @@ TEST_F(RenderStateTest, SampleShadingEnableIsStoredAndQueryable) {
|
||||
EXPECT_EQ(MG_Impl::GLImpl::IsEnabled(GL_SAMPLE_SHADING), GL_FALSE);
|
||||
EXPECT_EQ(MG_Impl::GLImpl::GetError(), GL_NO_ERROR);
|
||||
}
|
||||
|
||||
// glClipControl and glPolygonOffsetClamp were DECLARE_GL_FUNCTION_STUB_HEAD entry points: they
|
||||
// took their arguments, recorded nothing and raised no error, and the state variables they own
|
||||
// (GL_CLIP_ORIGIN, GL_CLIP_DEPTH_MODE, GL_POLYGON_OFFSET_CLAMP) had no arm in any getter, so the
|
||||
// very first query of a conformance case raised GL_INVALID_ENUM and killed it. These assertions
|
||||
// are state-shaped on purpose - the rasterization half of clip control is a backend question, but
|
||||
// the state machine has to round-trip regardless of what a backend does with it.
|
||||
TEST_F(RenderStateTest, ClipControlStateRoundTripsAndDefaultsToLowerLeftNegativeOneToOne) {
|
||||
DrainPendingGlErrors();
|
||||
|
||||
GLint origin = 0;
|
||||
GLint depthMode = 0;
|
||||
MG_Impl::GLImpl::GetIntegerv(GL_CLIP_ORIGIN, &origin);
|
||||
MG_Impl::GLImpl::GetIntegerv(GL_CLIP_DEPTH_MODE, &depthMode);
|
||||
EXPECT_EQ(origin, GL_LOWER_LEFT);
|
||||
EXPECT_EQ(depthMode, GL_NEGATIVE_ONE_TO_ONE);
|
||||
EXPECT_EQ(MG_Impl::GLImpl::GetError(), GL_NO_ERROR);
|
||||
|
||||
MG_Impl::GLImpl::ClipControl(GL_UPPER_LEFT, GL_ZERO_TO_ONE);
|
||||
MG_Impl::GLImpl::GetIntegerv(GL_CLIP_ORIGIN, &origin);
|
||||
MG_Impl::GLImpl::GetIntegerv(GL_CLIP_DEPTH_MODE, &depthMode);
|
||||
EXPECT_EQ(origin, GL_UPPER_LEFT);
|
||||
EXPECT_EQ(depthMode, GL_ZERO_TO_ONE);
|
||||
EXPECT_EQ(MG_Impl::GLImpl::GetError(), GL_NO_ERROR);
|
||||
|
||||
// Every getter flavour has to answer, not just the integer one - the conformance suite reads
|
||||
// this state through all of them.
|
||||
GLfloat asFloat = 0.0f;
|
||||
MG_Impl::GLImpl::GetFloatv(GL_CLIP_ORIGIN, &asFloat);
|
||||
EXPECT_EQ(static_cast<GLint>(asFloat), GL_UPPER_LEFT);
|
||||
GLint64 asInt64 = 0;
|
||||
MG_Impl::GLImpl::GetInteger64v(GL_CLIP_DEPTH_MODE, &asInt64);
|
||||
EXPECT_EQ(static_cast<GLint>(asInt64), GL_ZERO_TO_ONE);
|
||||
EXPECT_EQ(MG_Impl::GLImpl::GetError(), GL_NO_ERROR);
|
||||
|
||||
MG_Impl::GLImpl::ClipControl(GL_LOWER_LEFT, GL_NEGATIVE_ONE_TO_ONE);
|
||||
EXPECT_EQ(MG_Impl::GLImpl::GetError(), GL_NO_ERROR);
|
||||
}
|
||||
|
||||
TEST_F(RenderStateTest, ClipControlRejectsBadEnumsAndLeavesTheStateAlone) {
|
||||
DrainPendingGlErrors();
|
||||
MG_Impl::GLImpl::ClipControl(GL_UPPER_LEFT, GL_ZERO_TO_ONE);
|
||||
DrainPendingGlErrors();
|
||||
|
||||
MG_Impl::GLImpl::ClipControl(GL_FRONT, GL_ZERO_TO_ONE);
|
||||
ExpectSingleGlError(GL_INVALID_ENUM);
|
||||
MG_Impl::GLImpl::ClipControl(GL_UPPER_LEFT, GL_FRONT);
|
||||
ExpectSingleGlError(GL_INVALID_ENUM);
|
||||
|
||||
GLint origin = 0;
|
||||
GLint depthMode = 0;
|
||||
MG_Impl::GLImpl::GetIntegerv(GL_CLIP_ORIGIN, &origin);
|
||||
MG_Impl::GLImpl::GetIntegerv(GL_CLIP_DEPTH_MODE, &depthMode);
|
||||
EXPECT_EQ(origin, GL_UPPER_LEFT) << "a rejected glClipControl must not change the state";
|
||||
EXPECT_EQ(depthMode, GL_ZERO_TO_ONE) << "a rejected glClipControl must not change the state";
|
||||
|
||||
MG_Impl::GLImpl::ClipControl(GL_LOWER_LEFT, GL_NEGATIVE_ONE_TO_ONE);
|
||||
DrainPendingGlErrors();
|
||||
}
|
||||
|
||||
TEST_F(RenderStateTest, PolygonOffsetClampStoresTheClampAndTheFactorUnitsPair) {
|
||||
DrainPendingGlErrors();
|
||||
|
||||
GLfloat clamp = -1.0f;
|
||||
MG_Impl::GLImpl::GetFloatv(GL_POLYGON_OFFSET_CLAMP, &clamp);
|
||||
EXPECT_FLOAT_EQ(clamp, 0.0f) << "the default clamp is zero, i.e. no clamping";
|
||||
EXPECT_EQ(MG_Impl::GLImpl::GetError(), GL_NO_ERROR);
|
||||
|
||||
MG_Impl::GLImpl::PolygonOffsetClamp(1.5f, 2.5f, 0.5f);
|
||||
GLfloat factor = 0.0f;
|
||||
GLfloat units = 0.0f;
|
||||
MG_Impl::GLImpl::GetFloatv(GL_POLYGON_OFFSET_FACTOR, &factor);
|
||||
MG_Impl::GLImpl::GetFloatv(GL_POLYGON_OFFSET_UNITS, &units);
|
||||
MG_Impl::GLImpl::GetFloatv(GL_POLYGON_OFFSET_CLAMP, &clamp);
|
||||
EXPECT_FLOAT_EQ(factor, 1.5f);
|
||||
EXPECT_FLOAT_EQ(units, 2.5f);
|
||||
EXPECT_FLOAT_EQ(clamp, 0.5f) << "the fractional clamp must survive - the integer path rounds it away";
|
||||
EXPECT_EQ(MG_Impl::GLImpl::GetError(), GL_NO_ERROR);
|
||||
|
||||
// glcPolygonOffsetClampTests reads GL_POLYGON_OFFSET_CLAMP through all five getters and
|
||||
// requires no error from any of them; that is what used to kill the availability case.
|
||||
GLboolean asBoolean = GL_FALSE;
|
||||
MG_Impl::GLImpl::GetBooleanv(GL_POLYGON_OFFSET_CLAMP, &asBoolean);
|
||||
EXPECT_EQ(asBoolean, GL_TRUE);
|
||||
GLint asInt = -1;
|
||||
MG_Impl::GLImpl::GetIntegerv(GL_POLYGON_OFFSET_CLAMP, &asInt);
|
||||
EXPECT_EQ(asInt, 1) << "0.5 rounds to nearest for the integer query";
|
||||
GLint64 asInt64 = -1;
|
||||
MG_Impl::GLImpl::GetInteger64v(GL_POLYGON_OFFSET_CLAMP, &asInt64);
|
||||
EXPECT_EQ(asInt64, 1);
|
||||
GLdouble asDouble = -1.0;
|
||||
MG_Impl::GLImpl::GetDoublev(GL_POLYGON_OFFSET_CLAMP, &asDouble);
|
||||
EXPECT_NEAR(asDouble, 0.5, 1e-6);
|
||||
EXPECT_EQ(MG_Impl::GLImpl::GetError(), GL_NO_ERROR);
|
||||
|
||||
// glPolygonOffset is the clamp = 0 case of the same state, but it must not DISTURB the clamp
|
||||
// it does not take - GL 4.6 core 14.6.5 defines it as PolygonOffsetClamp(factor, units, 0)
|
||||
// only in the sense that the clamp it leaves is whatever glPolygonOffset itself sets, which
|
||||
// for MobileGL is "unchanged". Assert the factor/units half instead, which is unambiguous.
|
||||
MG_Impl::GLImpl::PolygonOffset(3.0f, 4.0f);
|
||||
MG_Impl::GLImpl::GetFloatv(GL_POLYGON_OFFSET_FACTOR, &factor);
|
||||
MG_Impl::GLImpl::GetFloatv(GL_POLYGON_OFFSET_UNITS, &units);
|
||||
EXPECT_FLOAT_EQ(factor, 3.0f);
|
||||
EXPECT_FLOAT_EQ(units, 4.0f);
|
||||
|
||||
MG_Impl::GLImpl::PolygonOffsetClamp(0.0f, 0.0f, 0.0f);
|
||||
EXPECT_EQ(MG_Impl::GLImpl::GetError(), GL_NO_ERROR);
|
||||
}
|
||||
|
||||
// GL_TEXTURE_BUFFER_BINDING (0x8C2A) is the same token as GL_TEXTURE_BUFFER; as a glGetIntegerv
|
||||
// pname it asks which BUFFER object is bound there, and it had no arm at all, so
|
||||
// esextcTextureBufferParameters died on its first query.
|
||||
TEST_F(RenderStateTest, TextureBufferBindingAnswersTheBoundBufferName) {
|
||||
DrainPendingGlErrors();
|
||||
|
||||
GLint binding = -1;
|
||||
MG_Impl::GLImpl::GetIntegerv(GL_TEXTURE_BUFFER_BINDING, &binding);
|
||||
EXPECT_EQ(binding, 0);
|
||||
EXPECT_EQ(MG_Impl::GLImpl::GetError(), GL_NO_ERROR);
|
||||
}
|
||||
|
||||
// GL_ARB_spirv_extensions. Zero is legal and true: MobileGL relies on no SPIR-V extension, so
|
||||
// glGetStringi(GL_SPIR_V_EXTENSIONS, i) is never legally reached.
|
||||
TEST_F(RenderStateTest, NumSpirVExtensionsIsQueryableAndZero) {
|
||||
DrainPendingGlErrors();
|
||||
|
||||
GLint count = -1;
|
||||
MG_Impl::GLImpl::GetIntegerv(GL_NUM_SPIR_V_EXTENSIONS, &count);
|
||||
EXPECT_EQ(count, 0);
|
||||
EXPECT_EQ(MG_Impl::GLImpl::GetError(), GL_NO_ERROR);
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user