mirror of
https://github.com/MobileGL-Dev/MobileGL
synced 2026-09-11 21:58:31 +09:00
[Feat] (MG_Backend/DirectGLES, MG_Util/Loader): wire glPolygonMode and glColorMaski into GLES sync
Neither entry point exists in unextended OpenGL ES core, so both are gated on optional extensions detected and cached at init, with a runtime fallback when absent. Loader: - Add glPolygonModeNV/glPolygonModeANGLE and glColorMaskiEXT/glColorMaskiOES to the GLES function table, loaded via a new INIT_GLES_FUNC_OPTIONAL macro that does not log an error when the driver lacks them. - Cache GLESCapabilities.SupportsPolygonMode and SupportsIndexedColorMask from whether the entry points loaded (glColorMaski is GLES 3.2 core with no extension string, so pointer presence is the reliable signal). Sync (SyncRenderState): - Color mask: uniform masks keep using the non-indexed glColorMask (works everywhere); divergent per-draw-buffer masks use glColorMaski (core / EXT / OES, whichever loaded) when SupportsIndexedColorMask, else fall back to broadcasting draw buffer 0. Mirrors the existing indexed-blend block's all-same-vs-per-buffer structure. - Polygon mode: new sync block calls glPolygonModeNV/ANGLE(GL_FRONT_AND_BACK, mode) when SupportsPolygonMode; without the extension the mode stays FILL and non-FILL requests are dropped. Library builds clean; full SanityTest sweep green (30/30).
This commit is contained in:
@@ -702,11 +702,47 @@ namespace MobileGL::MG_Backend::DirectGLES {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
{ // Color mask. GLES core has only the non-indexed glColorMask, so sync draw buffer 0.
|
{ // Color mask. Uniform masks use the non-indexed glColorMask (works everywhere); divergent
|
||||||
if (parameters.ColorMasks[0] != g_syncedRenderStateParameters.ColorMasks[0]) {
|
// per-draw-buffer masks use the indexed glColorMaski when draw_buffers_indexed is
|
||||||
const BoolVec4& colorMask = parameters.ColorMasks[0];
|
// available, otherwise fall back to broadcasting draw buffer 0. Mirrors the blend block.
|
||||||
g_GLESFuncs.glColorMask(ToGLBoolean(colorMask.x()), ToGLBoolean(colorMask.y()),
|
using FBO = MG_State::GLState::FramebufferObject;
|
||||||
ToGLBoolean(colorMask.z()), ToGLBoolean(colorMask.w()));
|
const auto& targetMasks = parameters.ColorMasks;
|
||||||
|
const auto& syncedMasks = g_syncedRenderStateParameters.ColorMasks;
|
||||||
|
|
||||||
|
Bool anyDirty = false;
|
||||||
|
Bool allSame = true;
|
||||||
|
for (Uint i = 0; i < FBO::MAX_DRAW_BUFFERS; ++i) {
|
||||||
|
if (targetMasks[i] != syncedMasks[i]) anyDirty = true;
|
||||||
|
if (i > 0 && targetMasks[i] != targetMasks[0]) allSame = false;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (anyDirty) {
|
||||||
|
if (allSame || !g_GLESCapabilities.SupportsIndexedColorMask) {
|
||||||
|
const BoolVec4& m = targetMasks[0];
|
||||||
|
g_GLESFuncs.glColorMask(ToGLBoolean(m.x()), ToGLBoolean(m.y()), ToGLBoolean(m.z()),
|
||||||
|
ToGLBoolean(m.w()));
|
||||||
|
} else {
|
||||||
|
const auto colorMaskiFn = g_GLESFuncs.glColorMaski ? g_GLESFuncs.glColorMaski
|
||||||
|
: g_GLESFuncs.glColorMaskiEXT ? g_GLESFuncs.glColorMaskiEXT
|
||||||
|
: g_GLESFuncs.glColorMaskiOES;
|
||||||
|
for (Uint i = 0; i < FBO::MAX_DRAW_BUFFERS; ++i) {
|
||||||
|
if (targetMasks[i] != syncedMasks[i]) {
|
||||||
|
const BoolVec4& m = targetMasks[i];
|
||||||
|
colorMaskiFn(i, ToGLBoolean(m.x()), ToGLBoolean(m.y()), ToGLBoolean(m.z()),
|
||||||
|
ToGLBoolean(m.w()));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
{ // Polygon mode. GLES core has no glPolygonMode; use NV/ANGLE_polygon_mode when present.
|
||||||
|
// Without the extension the mode stays FILL and non-FILL requests are dropped.
|
||||||
|
if (parameters.PolygonModeFront != g_syncedRenderStateParameters.PolygonModeFront &&
|
||||||
|
g_GLESCapabilities.SupportsPolygonMode) {
|
||||||
|
const auto polygonModeFn =
|
||||||
|
g_GLESFuncs.glPolygonModeNV ? g_GLESFuncs.glPolygonModeNV : g_GLESFuncs.glPolygonModeANGLE;
|
||||||
|
polygonModeFn(GL_FRONT_AND_BACK, parameters.PolygonModeFront);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -82,6 +82,13 @@ namespace MobileGL::MG_Util::BackendLoader {
|
|||||||
} \
|
} \
|
||||||
} while (0);
|
} while (0);
|
||||||
|
|
||||||
|
// Optional (extension-provided) entry points: a null pointer is expected on drivers that lack the
|
||||||
|
// extension, so absence is not an error. The call site null-checks before use.
|
||||||
|
#define INIT_GLES_FUNC_OPTIONAL(name) \
|
||||||
|
do { \
|
||||||
|
funcs.name = (MG_External::GLES::name##_PTR)procAddress(#name); \
|
||||||
|
} while (0);
|
||||||
|
|
||||||
{
|
{
|
||||||
INIT_GLES_FUNC(glActiveTexture)
|
INIT_GLES_FUNC(glActiveTexture)
|
||||||
INIT_GLES_FUNC(glAttachShader)
|
INIT_GLES_FUNC(glAttachShader)
|
||||||
@@ -454,6 +461,10 @@ namespace MobileGL::MG_Util::BackendLoader {
|
|||||||
INIT_GLES_FUNC(glGetQueryObjectui64vEXT)
|
INIT_GLES_FUNC(glGetQueryObjectui64vEXT)
|
||||||
INIT_GLES_FUNC(glBindFragDataLocationEXT)
|
INIT_GLES_FUNC(glBindFragDataLocationEXT)
|
||||||
INIT_GLES_FUNC(glMapBufferOES)
|
INIT_GLES_FUNC(glMapBufferOES)
|
||||||
|
INIT_GLES_FUNC_OPTIONAL(glPolygonModeNV)
|
||||||
|
INIT_GLES_FUNC_OPTIONAL(glPolygonModeANGLE)
|
||||||
|
INIT_GLES_FUNC_OPTIONAL(glColorMaskiEXT)
|
||||||
|
INIT_GLES_FUNC_OPTIONAL(glColorMaskiOES)
|
||||||
INIT_GLES_FUNC(glMultiDrawArraysIndirectEXT)
|
INIT_GLES_FUNC(glMultiDrawArraysIndirectEXT)
|
||||||
INIT_GLES_FUNC(glMultiDrawElementsIndirectEXT)
|
INIT_GLES_FUNC(glMultiDrawElementsIndirectEXT)
|
||||||
INIT_GLES_FUNC(glMultiDrawElementsBaseVertexEXT)
|
INIT_GLES_FUNC(glMultiDrawElementsBaseVertexEXT)
|
||||||
@@ -734,6 +745,16 @@ namespace MobileGL::MG_Util::BackendLoader {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Detect optional raster/color-mask entry points by whether they loaded. glColorMaski is GLES
|
||||||
|
// 3.2 core (no extension string), so pointer presence is the reliable signal for all of these.
|
||||||
|
caps.SupportsPolygonMode =
|
||||||
|
glesFuncs.glPolygonModeNV != nullptr || glesFuncs.glPolygonModeANGLE != nullptr;
|
||||||
|
caps.SupportsIndexedColorMask = glesFuncs.glColorMaski != nullptr ||
|
||||||
|
glesFuncs.glColorMaskiEXT != nullptr ||
|
||||||
|
glesFuncs.glColorMaskiOES != nullptr;
|
||||||
|
MGLOG_I(" glPolygonMode (NV/ANGLE): %s", caps.SupportsPolygonMode ? "yes" : "no");
|
||||||
|
MGLOG_I(" indexed glColorMaski: %s", caps.SupportsIndexedColorMask ? "yes" : "no");
|
||||||
|
|
||||||
MGLOG_I("OpenGL ES capabilities:");
|
MGLOG_I("OpenGL ES capabilities:");
|
||||||
glesFuncs.glGetIntegerv(GL_UNIFORM_BUFFER_OFFSET_ALIGNMENT, &caps.UniformBufferOffsetAlignment);
|
glesFuncs.glGetIntegerv(GL_UNIFORM_BUFFER_OFFSET_ALIGNMENT, &caps.UniformBufferOffsetAlignment);
|
||||||
MGLOG_I(" GL_UNIFORM_BUFFER_OFFSET_ALIGNMENT: %d", caps.UniformBufferOffsetAlignment);
|
MGLOG_I(" GL_UNIFORM_BUFFER_OFFSET_ALIGNMENT: %d", caps.UniformBufferOffsetAlignment);
|
||||||
|
|||||||
@@ -615,6 +615,11 @@ namespace MobileGL {
|
|||||||
GL_FUNC_TYPEDEF(void, glGetQueryObjectui64vEXT, GLuint id, GLenum pname, GLuint64* params)
|
GL_FUNC_TYPEDEF(void, glGetQueryObjectui64vEXT, GLuint id, GLenum pname, GLuint64* params)
|
||||||
GL_FUNC_TYPEDEF(void, glBindFragDataLocationEXT, GLuint program, GLuint colorNumber, const GLchar* name)
|
GL_FUNC_TYPEDEF(void, glBindFragDataLocationEXT, GLuint program, GLuint colorNumber, const GLchar* name)
|
||||||
GL_FUNC_TYPEDEF(void*, glMapBufferOES, GLenum target, GLenum access)
|
GL_FUNC_TYPEDEF(void*, glMapBufferOES, GLenum target, GLenum access)
|
||||||
|
// Extension aliases for glPolygonMode (GLES core has none) and indexed glColorMaski.
|
||||||
|
GL_FUNC_TYPEDEF(void, glPolygonModeNV, GLenum face, GLenum mode)
|
||||||
|
GL_FUNC_TYPEDEF(void, glPolygonModeANGLE, GLenum face, GLenum mode)
|
||||||
|
GL_FUNC_TYPEDEF(void, glColorMaskiEXT, GLuint index, GLboolean r, GLboolean g, GLboolean b, GLboolean a)
|
||||||
|
GL_FUNC_TYPEDEF(void, glColorMaskiOES, GLuint index, GLboolean r, GLboolean g, GLboolean b, GLboolean a)
|
||||||
|
|
||||||
GL_FUNC_TYPEDEF(void, glMultiDrawArraysIndirectEXT, GLenum mode, const void* indirect, GLsizei drawcount,
|
GL_FUNC_TYPEDEF(void, glMultiDrawArraysIndirectEXT, GLenum mode, const void* indirect, GLsizei drawcount,
|
||||||
GLsizei stride)
|
GLsizei stride)
|
||||||
@@ -1006,6 +1011,10 @@ namespace MobileGL {
|
|||||||
GL_FUNC_DECL(glGetQueryObjectui64vEXT)
|
GL_FUNC_DECL(glGetQueryObjectui64vEXT)
|
||||||
GL_FUNC_DECL(glBindFragDataLocationEXT)
|
GL_FUNC_DECL(glBindFragDataLocationEXT)
|
||||||
GL_FUNC_DECL(glMapBufferOES)
|
GL_FUNC_DECL(glMapBufferOES)
|
||||||
|
GL_FUNC_DECL(glPolygonModeNV)
|
||||||
|
GL_FUNC_DECL(glPolygonModeANGLE)
|
||||||
|
GL_FUNC_DECL(glColorMaskiEXT)
|
||||||
|
GL_FUNC_DECL(glColorMaskiOES)
|
||||||
|
|
||||||
GL_FUNC_DECL(glMultiDrawArraysIndirectEXT)
|
GL_FUNC_DECL(glMultiDrawArraysIndirectEXT)
|
||||||
GL_FUNC_DECL(glMultiDrawElementsIndirectEXT)
|
GL_FUNC_DECL(glMultiDrawElementsIndirectEXT)
|
||||||
@@ -1025,6 +1034,12 @@ namespace MobileGL {
|
|||||||
Bool SupportsBaseInstance = false;
|
Bool SupportsBaseInstance = false;
|
||||||
// GL_EXT_disjoint_timer_query is present in the extension string.
|
// GL_EXT_disjoint_timer_query is present in the extension string.
|
||||||
Bool SupportsDisjointTimerQuery = false;
|
Bool SupportsDisjointTimerQuery = false;
|
||||||
|
// glPolygonModeNV/ANGLE loaded (GL_NV_polygon_mode / GL_ANGLE_polygon_mode). GLES core
|
||||||
|
// has no glPolygonMode, so without this the mode stays FILL.
|
||||||
|
Bool SupportsPolygonMode = false;
|
||||||
|
// An indexed glColorMaski entry point loaded (GLES 3.2 core, or GL_OES/EXT_draw_buffers_indexed).
|
||||||
|
// Without it, only the non-indexed glColorMask (draw buffer 0 broadcast) is available.
|
||||||
|
Bool SupportsIndexedColorMask = false;
|
||||||
// GL_RENDERER contains "ANGLE".
|
// GL_RENDERER contains "ANGLE".
|
||||||
Bool IsAngleRenderer = false;
|
Bool IsAngleRenderer = false;
|
||||||
// GL_RENDERER contains both "ANGLE" and "llvmpipe".
|
// GL_RENDERER contains both "ANGLE" and "llvmpipe".
|
||||||
|
|||||||
Reference in New Issue
Block a user