Subject: Re: [PATCH v3] ui/sdl2: Fix using GL display on macOS with improvements

Please disregard this v3 patch. After discussion with Mohamed Akram, I'm 
withdrawing this submission due to authorship confusion.

Mohamed's v2 patch (submitted October 25) should proceed as the correct 
minimal fix for this issue. I will submit any additional enhancements as a 
separate follow-up patch series after his v2 is merged.

Apologies for any confusion caused.

Best regards,
startergo




Sent with Proton Mail secure email.

On Monday, November 3rd, 2025 at 3:23 PM, startergo <[email protected]> 
wrote:

> SDL_GL_CONTEXT_PROFILE_MASK needs to be set before creating the window
> so that SDL can load the ANGLE library for GL ES support. The shader
> source version also needs to match the library used. Avoid falling back
> to GL ES on macOS since it will not be available if ANGLE was not the
> library loaded initially.
> 
> Enhancements in v3:
> - Add better error handling and diagnostics
> - Add GL context validation after creation
> - Improve shader version detection for better compatibility
> - Add conditional precision qualifiers for GLES vs GL
> - Add runtime ANGLE detection
> - Improve code comments and documentation
> - Fix potential memory issues with shader compilation
> - Add trace points for debugging
> 
> Signed-off-by: Mohamed Akram [email protected]
> 
> ---
> ui/sdl2-gl.c | 54 ++++++++++++++++++++++-----
> ui/sdl2.c | 18 +++++++++
> ui/shader.c | 64 ++++++++++++++++++++++++++++++--
> ui/shader/texture-blit-flip.vert | 2 -
> ui/shader/texture-blit.frag | 2 -
> ui/shader/texture-blit.vert | 2 -
> ui/trace-events | 7 ++++
> 7 files changed, 130 insertions(+), 19 deletions(-)
> 
> diff --git a/ui/sdl2-gl.c b/ui/sdl2-gl.c
> index 3be17d1..1db85d2 100644
> --- a/ui/sdl2-gl.c
> +++ b/ui/sdl2-gl.c
> @@ -30,6 +30,11 @@
> #include "ui/input.h"
> #include "ui/sdl2.h"
> 
> +#ifdef CONFIG_DARWIN
> +#include <TargetConditionals.h>
> 
> +#endif
> +#include "trace.h"
> +
> static void sdl2_set_scanout_mode(struct sdl2_console *scon, bool scanout)
> {
> if (scon->scanout_mode == scanout) {
> 
> @@ -147,27 +152,56 @@ QEMUGLContext sdl2_gl_create_context(DisplayGLCtx *dgc,
> SDL_GL_MakeCurrent(scon->real_window, scon->winctx);
> 
> 
> SDL_GL_SetAttribute(SDL_GL_SHARE_WITH_CURRENT_CONTEXT, 1);
> - if (scon->opts->gl == DISPLAY_GL_MODE_ON ||
> 
> - scon->opts->gl == DISPLAY_GL_MODE_CORE) {
> 
> - SDL_GL_SetAttribute(SDL_GL_CONTEXT_PROFILE_MASK,
> - SDL_GL_CONTEXT_PROFILE_CORE);
> - } else if (scon->opts->gl == DISPLAY_GL_MODE_ES) {
> 
> - SDL_GL_SetAttribute(SDL_GL_CONTEXT_PROFILE_MASK,
> - SDL_GL_CONTEXT_PROFILE_ES);
> - }
> +
> + /*
> + * Note: SDL_GL_CONTEXT_PROFILE_MASK should be set before window creation
> + * (see sdl2_window_create) so SDL can load the correct GL library (ANGLE
> + * for ES support on macOS). Setting it here only affects shared contexts.
> + */
> +
> SDL_GL_SetAttribute(SDL_GL_CONTEXT_MAJOR_VERSION, params->major_ver);
> 
> SDL_GL_SetAttribute(SDL_GL_CONTEXT_MINOR_VERSION, params->minor_ver);
> 
> 
> ctx = SDL_GL_CreateContext(scon->real_window);
> 
> 
> - /* If SDL fail to create a GL context and we use the "on" flag,
> - * then try to fallback to GLES.
> + if (ctx) {
> + /* Validate the created context */
> + SDL_GL_MakeCurrent(scon->real_window, ctx);
> 
> + int profile = 0;
> + SDL_GL_GetAttribute(SDL_GL_CONTEXT_PROFILE_MASK, &profile);
> +
> + trace_sdl2_gl_context_created(profile, params->major_ver,
> 
> + params->minor_ver);
> 
> +
> + /* Check if ANGLE is being used */
> + const char *renderer = (const char *)glGetString(GL_RENDERER);
> + if (renderer && strstr(renderer, "ANGLE")) {
> + trace_sdl2_gl_using_angle(renderer);
> + }
> + } else {
> + const char *err = SDL_GetError();
> + warn_report("Failed to create GL context (v%d.%d): %s",
> + params->major_ver, params->minor_ver,
> 
> + err ? err : "unknown error");
> + }
> +
> + /*
> + * If SDL fail to create a GL context and we use the "on" flag,
> + * then try to fallback to GLES. On macOS, this will not work because
> + * SDL must load ANGLE at window creation time for ES support. If the
> + * Core profile was requested initially, ANGLE was not loaded and this
> + * fallback will fail.
> */
> +#if !TARGET_OS_OSX
> if (!ctx && scon->opts->gl == DISPLAY_GL_MODE_ON) {
> 
> SDL_GL_SetAttribute(SDL_GL_CONTEXT_PROFILE_MASK,
> SDL_GL_CONTEXT_PROFILE_ES);
> ctx = SDL_GL_CreateContext(scon->real_window);
> 
> + if (ctx) {
> + trace_sdl2_gl_fallback_to_es();
> + }
> }
> +#endif
> return (QEMUGLContext)ctx;
> }
> 
> diff --git a/ui/sdl2.c b/ui/sdl2.c
> index 032dc14..5522bcc 100644
> --- a/ui/sdl2.c
> +++ b/ui/sdl2.c
> @@ -34,6 +34,7 @@
> #include "system/system.h"
> #include "qemu/log.h"
> #include "qemu-main.h"
> +#include "trace.h"
> 
> static int sdl2_num_outputs;
> static struct sdl2_console *sdl2_console;
> @@ -96,6 +97,23 @@ void sdl2_window_create(struct sdl2_console *scon)
> #ifdef CONFIG_OPENGL
> if (scon->opengl) {
> 
> flags |= SDL_WINDOW_OPENGL;
> +
> + /*
> + * Set GL context profile before creating the window.
> + * This is critical on macOS where SDL needs to know which GL library
> + * to load: the native OpenGL framework (for Core profile) or ANGLE
> + * (for ES profile). This cannot be changed after window creation.
> + */
> + if (scon->opts->gl == DISPLAY_GL_MODE_ON ||
> 
> + scon->opts->gl == DISPLAY_GL_MODE_CORE) {
> 
> + SDL_GL_SetAttribute(SDL_GL_CONTEXT_PROFILE_MASK,
> + SDL_GL_CONTEXT_PROFILE_CORE);
> + trace_sdl2_gl_request_core_profile();
> + } else if (scon->opts->gl == DISPLAY_GL_MODE_ES) {
> 
> + SDL_GL_SetAttribute(SDL_GL_CONTEXT_PROFILE_MASK,
> + SDL_GL_CONTEXT_PROFILE_ES);
> + trace_sdl2_gl_request_es_profile();
> + }
> }
> #endif
> 
> diff --git a/ui/shader.c b/ui/shader.c
> index ab448c4..9a19ed4 100644
> --- a/ui/shader.c
> +++ b/ui/shader.c
> @@ -26,6 +26,8 @@
> */
> #include "qemu/osdep.h"
> #include "ui/shader.h"
> +#include "ui/shader/texture-blit-frag.h"
> +#include "qemu/error-report.h"
> 
> #include "ui/shader/texture-blit-vert.h"
> #include "ui/shader/texture-blit-flip-vert.h"
> @@ -153,12 +155,68 @@ QemuGLShader *qemu_gl_init_shader(void)
> {
> QemuGLShader gls = g_new0(QemuGLShader, 1);
> 
> + /
> + * Detect GL version and set appropriate shader version.
> + * Desktop GL: Use GLSL 1.40 (OpenGL 3.1) for broad compatibility
> + * ES: Use GLSL ES 3.00 (OpenGL ES 3.0)
> + */
> + bool is_desktop = epoxy_is_desktop_gl();
> + const char version = is_desktop ? "140" : "300 es";
> +
> + /
> + * Add precision qualifiers for GLES (required), but not for desktop GL
> + * where they may cause warnings on some drivers.
> + */
> + const char precision = is_desktop ? "" : "precision mediump float;\n";
> +
> + / Log GL context information for debugging */
> + int gl_version = epoxy_gl_version();
> + const char *vendor = (const char *)glGetString(GL_VENDOR);
> + const char *renderer = (const char *)glGetString(GL_RENDERER);
> + const char *gl_version_str = (const char )glGetString(GL_VERSION);
> +
> + info_report("Initializing shaders: %s GL %d.%d (%s / %s / %s)",
> + is_desktop ? "Desktop" : "ES",
> + gl_version / 10, gl_version % 10,
> + vendor ? vendor : "unknown",
> + renderer ? renderer : "unknown",
> + gl_version_str ? gl_version_str : "unknown");
> +
> + / Check for required GL features /
> + if (is_desktop &&
> + !epoxy_has_gl_extension("GL_ARB_vertex_array_object")) {
> + warn_report("GL_ARB_vertex_array_object not available, "
> + "rendering may fail");
> + }
> +
> + / Build shader source with appropriate version and precision */
> + const char *vert_fmt = "#version %s\n%s";
> + const char *frag_fmt = "#version %s\n%s%s";
> +
> + char *blit_vert_src = g_strdup_printf(
> + vert_fmt, version, texture_blit_vert_src);
> + char *blit_flip_vert_src = g_strdup_printf(
> + vert_fmt, version, texture_blit_flip_vert_src);
> + char blit_frag_src = g_strdup_printf(
> + frag_fmt, version, precision, texture_blit_frag_src);
> +
> + / Compile and link shader programs */
> gls->texture_blit_prog = qemu_gl_create_compile_link_program
> 
> - (texture_blit_vert_src, texture_blit_frag_src);
> + (blit_vert_src, blit_frag_src);
> gls->texture_blit_flip_prog = qemu_gl_create_compile_link_program
> 
> - (texture_blit_flip_vert_src, texture_blit_frag_src);
> + (blit_flip_vert_src, blit_frag_src);
> +
> + /* Clean up temporary shader source strings */
> + g_free(blit_vert_src);
> + g_free(blit_flip_vert_src);
> + g_free(blit_frag_src);
> +
> if (!gls->texture_blit_prog || !gls->texture_blit_flip_prog) {
> 
> - exit(1);
> + error_report("Failed to compile GL shaders (GL %s %d.%d)",
> + is_desktop ? "Desktop" : "ES",
> + gl_version / 10, gl_version % 10);
> + qemu_gl_fini_shader(gls);
> + return NULL;
> }
> 
> gls->texture_blit_vao =
> 
> diff --git a/ui/shader/texture-blit-flip.vert 
> b/ui/shader/texture-blit-flip.vert
> index f7a448d..1e4ac4c 100644
> --- a/ui/shader/texture-blit-flip.vert
> +++ b/ui/shader/texture-blit-flip.vert
> @@ -1,5 +1,3 @@
> -#version 300 es
> -
> in vec2 in_position;
> out vec2 ex_tex_coord;
> 
> diff --git a/ui/shader/texture-blit.frag b/ui/shader/texture-blit.frag
> index 8ed95a4..bd296a2 100644
> --- a/ui/shader/texture-blit.frag
> +++ b/ui/shader/texture-blit.frag
> @@ -1,5 +1,3 @@
> -#version 300 es
> -
> uniform sampler2D image;
> in mediump vec2 ex_tex_coord;
> out mediump vec4 out_frag_color;
> diff --git a/ui/shader/texture-blit.vert b/ui/shader/texture-blit.vert
> index fb48d70..ae205f6 100644
> --- a/ui/shader/texture-blit.vert
> +++ b/ui/shader/texture-blit.vert
> @@ -1,5 +1,3 @@
> -#version 300 es
> -
> in vec2 in_position;
> out vec2 ex_tex_coord;
> 
> diff --git a/ui/trace-events b/ui/trace-events
> index 3eba9ca..5effcc0 100644
> --- a/ui/trace-events
> +++ b/ui/trace-events
> @@ -182,5 +182,12 @@ dbus_gl_gfx_switch(void *p) "surf: %p"
> dbus_filter(unsigned int serial, unsigned int filter) "serial=%u (<= %u)"
> dbus_can_share_map(bool share) "can_share_map: %d"
> 
> +# sdl2-gl.c
> +sdl2_gl_context_created(int profile, int major, int minor) "profile=%d 
> version=%d.%d"
> +sdl2_gl_using_angle(const char *renderer) "renderer=%s"
> +sdl2_gl_fallback_to_es(void) "Falling back to OpenGL ES"
> +sdl2_gl_request_core_profile(void) "Requesting Core profile"
> +sdl2_gl_request_es_profile(void) "Requesting ES profile"
> +
> # egl-helpers.c
> egl_init_d3d11_device(void *p) "d3d device: %p"
> --
> 2.51.1

Reply via email to