Backends: OpenGL: Detect ES3 contexts on desktop based on version string, (#7447)
diff --git a/backends/imgui_impl_opengl3.cpp b/backends/imgui_impl_opengl3.cpp
index b3a510b..987b074 100644
--- a/backends/imgui_impl_opengl3.cpp
+++ b/backends/imgui_impl_opengl3.cpp
@@ -22,6 +22,7 @@
// CHANGELOG
// (minor and older changes stripped away, please see git history for details)
+// 2024-04-16: OpenGL: Detect ES3 contexts on desktop based on version string, to e.g. avoid calling glPolygonMode() on them. (#7447)
// 2024-01-09: OpenGL: Update GL3W based imgui_impl_opengl3_loader.h to load "libGL.so" and variants, fixing regression on distros missing a symlink.
// 2023-11-08: OpenGL: Update GL3W based imgui_impl_opengl3_loader.h to load "libGL.so" instead of "libGL.so.1", accommodating for NetBSD systems having only "libGL.so.3" available. (#6983)
// 2023-10-05: OpenGL: Rename symbols in our internal loader so that LTO compilation with another copy of gl3w is possible. (#6875, #6668, #4445)
@@ -177,9 +178,10 @@
#endif
// Desktop GL 2.0+ has extension and glPolygonMode() which GL ES and WebGL don't have..
+// A desktop ES context can technically compile fine with our loader, so we also perform a runtime checks
#if !defined(IMGUI_IMPL_OPENGL_ES2) && !defined(IMGUI_IMPL_OPENGL_ES3)
#define IMGUI_IMPL_OPENGL_HAS_EXTENSIONS // has glGetIntegerv(GL_NUM_EXTENSIONS)
-#define IMGUI_IMPL_OPENGL_HAS_POLYGON_MODE // has glPolygonMode()
+#define IMGUI_IMPL_OPENGL_MAY_HAVE_POLYGON_MODE // may have glPolygonMode()
#endif
// Desktop GL 2.1+ and GL ES 3.0+ have glBindBuffer() with GL_PIXEL_UNPACK_BUFFER target.
@@ -230,6 +232,7 @@
unsigned int VboHandle, ElementsHandle;
GLsizeiptr VertexBufferSize;
GLsizeiptr IndexBufferSize;
+ bool HasPolygonMode;
bool HasClipOrigin;
bool UseBufferSubData;
@@ -294,16 +297,13 @@
bd->GlProfileIsES2 = true;
#else
// Desktop or GLES 3
+ const char* gl_version_str = (const char*)glGetString(GL_VERSION);
GLint major = 0;
GLint minor = 0;
glGetIntegerv(GL_MAJOR_VERSION, &major);
glGetIntegerv(GL_MINOR_VERSION, &minor);
if (major == 0 && minor == 0)
- {
- // Query GL_VERSION in desktop GL 2.x, the string will start with "<major>.<minor>"
- const char* gl_version = (const char*)glGetString(GL_VERSION);
- sscanf(gl_version, "%d.%d", &major, &minor);
- }
+ sscanf(gl_version_str, "%d.%d", &major, &minor); // Query GL_VERSION in desktop GL 2.x, the string will start with "<major>.<minor>"
bd->GlVersion = (GLuint)(major * 100 + minor * 10);
#if defined(GL_CONTEXT_PROFILE_MASK)
if (bd->GlVersion >= 320)
@@ -313,6 +313,9 @@
#if defined(IMGUI_IMPL_OPENGL_ES3)
bd->GlProfileIsES3 = true;
+#else
+ if (strncmp(gl_version_str, "OpenGL ES 3", 11) == 0)
+ bd->GlProfileIsES3 = true;
#endif
bd->UseBufferSubData = false;
@@ -327,7 +330,7 @@
#endif
#ifdef IMGUI_IMPL_OPENGL_DEBUG
- printf("GlVersion = %d\nGlProfileIsCompat = %d\nGlProfileMask = 0x%X\nGlProfileIsES2 = %d, GlProfileIsES3 = %d\nGL_VENDOR = '%s'\nGL_RENDERER = '%s'\n", bd->GlVersion, bd->GlProfileIsCompat, bd->GlProfileMask, bd->GlProfileIsES2, bd->GlProfileIsES3, (const char*)glGetString(GL_VENDOR), (const char*)glGetString(GL_RENDERER)); // [DEBUG]
+ printf("GlVersion = %d, \"%s\"\nGlProfileIsCompat = %d\nGlProfileMask = 0x%X\nGlProfileIsES2 = %d, GlProfileIsES3 = %d\nGL_VENDOR = '%s'\nGL_RENDERER = '%s'\n", bd->GlVersion, gl_version_str, bd->GlProfileIsCompat, bd->GlProfileMask, bd->GlProfileIsES2, bd->GlProfileIsES3, (const char*)glGetString(GL_VENDOR), (const char*)glGetString(GL_RENDERER)); // [DEBUG]
#endif
#ifdef IMGUI_IMPL_OPENGL_MAY_HAVE_VTX_OFFSET
@@ -359,6 +362,9 @@
glGetIntegerv(GL_TEXTURE_BINDING_2D, ¤t_texture);
// Detect extensions we support
+#ifdef IMGUI_IMPL_OPENGL_MAY_HAVE_POLYGON_MODE
+ bd->HasPolygonMode = (!bd->GlProfileIsES2 && !bd->GlProfileIsES3);
+#endif
bd->HasClipOrigin = (bd->GlVersion >= 450);
#ifdef IMGUI_IMPL_OPENGL_HAS_EXTENSIONS
GLint num_extensions = 0;
@@ -412,8 +418,9 @@
if (bd->GlVersion >= 310)
glDisable(GL_PRIMITIVE_RESTART);
#endif
-#ifdef IMGUI_IMPL_OPENGL_HAS_POLYGON_MODE
- glPolygonMode(GL_FRONT_AND_BACK, GL_FILL);
+#ifdef IMGUI_IMPL_OPENGL_MAY_HAVE_POLYGON_MODE
+ if (bd->HasPolygonMode)
+ glPolygonMode(GL_FRONT_AND_BACK, GL_FILL);
#endif
// Support for GL 4.5 rarely used glClipControl(GL_UPPER_LEFT)
@@ -501,8 +508,8 @@
#ifdef IMGUI_IMPL_OPENGL_USE_VERTEX_ARRAY
GLuint last_vertex_array_object; glGetIntegerv(GL_VERTEX_ARRAY_BINDING, (GLint*)&last_vertex_array_object);
#endif
-#ifdef IMGUI_IMPL_OPENGL_HAS_POLYGON_MODE
- GLint last_polygon_mode[2]; glGetIntegerv(GL_POLYGON_MODE, last_polygon_mode);
+#ifdef IMGUI_IMPL_OPENGL_MAY_HAVE_POLYGON_MODE
+ GLint last_polygon_mode[2]; if (bd->HasPolygonMode) { glGetIntegerv(GL_POLYGON_MODE, last_polygon_mode); }
#endif
GLint last_viewport[4]; glGetIntegerv(GL_VIEWPORT, last_viewport);
GLint last_scissor_box[4]; glGetIntegerv(GL_SCISSOR_BOX, last_scissor_box);
@@ -640,18 +647,10 @@
if (bd->GlVersion >= 310) { if (last_enable_primitive_restart) glEnable(GL_PRIMITIVE_RESTART); else glDisable(GL_PRIMITIVE_RESTART); }
#endif
-#ifdef IMGUI_IMPL_OPENGL_HAS_POLYGON_MODE
+#ifdef IMGUI_IMPL_OPENGL_MAY_HAVE_POLYGON_MODE
// Desktop OpenGL 3.0 and OpenGL 3.1 had separate polygon draw modes for front-facing and back-facing faces of polygons
- if (bd->GlVersion <= 310 || bd->GlProfileIsCompat)
- {
- glPolygonMode(GL_FRONT, (GLenum)last_polygon_mode[0]);
- glPolygonMode(GL_BACK, (GLenum)last_polygon_mode[1]);
- }
- else
- {
- glPolygonMode(GL_FRONT_AND_BACK, (GLenum)last_polygon_mode[0]);
- }
-#endif // IMGUI_IMPL_OPENGL_HAS_POLYGON_MODE
+ if (bd->HasPolygonMode) { if (bd->GlVersion <= 310 || bd->GlProfileIsCompat) { glPolygonMode(GL_FRONT, (GLenum)last_polygon_mode[0]); glPolygonMode(GL_BACK, (GLenum)last_polygon_mode[1]); } else { glPolygonMode(GL_FRONT_AND_BACK, (GLenum)last_polygon_mode[0]); } }
+#endif // IMGUI_IMPL_OPENGL_MAY_HAVE_POLYGON_MODE
glViewport(last_viewport[0], last_viewport[1], (GLsizei)last_viewport[2], (GLsizei)last_viewport[3]);
glScissor(last_scissor_box[0], last_scissor_box[1], (GLsizei)last_scissor_box[2], (GLsizei)last_scissor_box[3]);
diff --git a/docs/CHANGELOG.txt b/docs/CHANGELOG.txt
index fdf2919..5f8654c 100644
--- a/docs/CHANGELOG.txt
+++ b/docs/CHANGELOG.txt
@@ -48,6 +48,8 @@
duplicate with this fix. (#7399, #7404) [@GamingMinds-DanielC]
- Text, DrawList: Improved handling of long single-line wrapped text. Faster and
mitigitate issues with reading vertex indexing limits with 16-bit indices. (#7496, #5720)
+- Backends: OpenGL: Detect ES3 contexts on desktop based on version string,
+ to e.g. avoid calling glPolygonMode() on them. (#7447) [@afraidofdark, @ocornut]
- Backends: SDL3: Fixed text inputs. Re-enable calling SDL_StartTextInput()/SDL_StopTextInput()
as SDL3 no longer enables it by default. (#7452, #6306, #6071, #1953) [@Green-Sky]
- Examples: GLFW+WebGPU: Added support for WebGPU-native/Dawn (#7435, #7132) [@eliasdaler, @Zelif]