Message ID | 20241024233355.136867-3-dmitry.osipenko@collabora.com (mailing list archive) |
---|---|
State | New |
Headers | show |
Series | Support virtio-gpu DRM native context | expand |
On 2024/10/25 8:33, Dmitry Osipenko wrote: > From: Pierre-Eric Pelloux-Prayer <pierre-eric.pelloux-prayer@amd.com> > > If EGL is used, we can rely on dmabuf to import textures without > doing copies. > > To get this working on X11, we use the existing SDL hint: > SDL_HINT_VIDEO_X11_FORCE_EGL (because dmabuf can't be used with GLX). > > Signed-off-by: Pierre-Eric Pelloux-Prayer <pierre-eric.pelloux-prayer@amd.com> > Signed-off-by: Dmitry Osipenko <dmitry.osipenko@collabora.com> > --- > include/ui/sdl2.h | 7 ++++++ > meson.build | 4 +++ > ui/sdl2-gl.c | 63 +++++++++++++++++++++++++++++++++++++++++++++++ > ui/sdl2.c | 40 ++++++++++++++++++++++++++++++ > 4 files changed, 114 insertions(+) > > diff --git a/include/ui/sdl2.h b/include/ui/sdl2.h > index dbe6e3d9739b..9daf5ecffae7 100644 > --- a/include/ui/sdl2.h > +++ b/include/ui/sdl2.h > @@ -45,6 +45,7 @@ struct sdl2_console { > bool gui_keysym; > SDL_GLContext winctx; > QKbdState *kbd; > + bool has_dmabuf; > #ifdef CONFIG_OPENGL > QemuGLShader *gls; > egl_fb guest_fb; > @@ -96,5 +97,11 @@ void sdl2_gl_scanout_texture(DisplayChangeListener *dcl, > void *d3d_tex2d); > void sdl2_gl_scanout_flush(DisplayChangeListener *dcl, > uint32_t x, uint32_t y, uint32_t w, uint32_t h); > +void sdl2_gl_scanout_dmabuf(DisplayChangeListener *dcl, > + QemuDmaBuf *dmabuf); > +void sdl2_gl_release_dmabuf(DisplayChangeListener *dcl, > + QemuDmaBuf *dmabuf); > +bool sdl2_gl_has_dmabuf(DisplayChangeListener *dcl); > +void sdl2_gl_console_init(struct sdl2_console *scon); > > #endif /* SDL2_H */ > diff --git a/meson.build b/meson.build > index 089cbd2bb364..1ace2bfa0ebe 100644 > --- a/meson.build > +++ b/meson.build > @@ -1531,6 +1531,9 @@ else > sdl_image = not_found > endif > > +# libx11 presents together with SDL or GTK libs on systems that support X11 > +xlib = dependency('x11', required: false) There is a line saying: x11 = dependency('x11', method: 'pkg-config', required: gtkx11.found()) Please reuse it. > + > rbd = not_found > if not get_option('rbd').auto() or have_block > librados = cc.find_library('rados', required: get_option('rbd')) > @@ -2397,6 +2400,7 @@ config_host_data.set('CONFIG_RELOCATABLE', get_option('relocatable')) > config_host_data.set('CONFIG_SAFESTACK', get_option('safe_stack')) > config_host_data.set('CONFIG_SDL', sdl.found()) > config_host_data.set('CONFIG_SDL_IMAGE', sdl_image.found()) > +config_host_data.set('CONFIG_XLIB', xlib.found()) > config_host_data.set('CONFIG_SECCOMP', seccomp.found()) > if seccomp.found() > config_host_data.set('CONFIG_SECCOMP_SYSRAWRC', seccomp_has_sysrawrc) > diff --git a/ui/sdl2-gl.c b/ui/sdl2-gl.c > index b1fe96d6af22..7612af18292c 100644 > --- a/ui/sdl2-gl.c > +++ b/ui/sdl2-gl.c > @@ -26,6 +26,8 @@ > */ > > #include "qemu/osdep.h" > +#include "qemu/main-loop.h" > +#include "qemu/error-report.h" > #include "ui/console.h" > #include "ui/input.h" > #include "ui/sdl2.h" > @@ -249,3 +251,64 @@ void sdl2_gl_scanout_flush(DisplayChangeListener *dcl, > > SDL_GL_SwapWindow(scon->real_window); > } > + > +void sdl2_gl_scanout_dmabuf(DisplayChangeListener *dcl, > + QemuDmaBuf *dmabuf) > +{ > + struct sdl2_console *scon = container_of(dcl, struct sdl2_console, dcl); > + > + assert(scon->opengl); > + SDL_GL_MakeCurrent(scon->real_window, scon->winctx); > + > + egl_dmabuf_import_texture(dmabuf); > + if (!qemu_dmabuf_get_texture(dmabuf)) { > + error_report("%s: failed fd=%d", __func__, qemu_dmabuf_get_fd(dmabuf)); It still continues to call sdl2_gl_scanout_texture() and I doubt that's what you meant. > + } > + > + sdl2_gl_scanout_texture(dcl, qemu_dmabuf_get_texture(dmabuf), false, > + qemu_dmabuf_get_width(dmabuf), > + qemu_dmabuf_get_height(dmabuf), > + 0, 0, > + qemu_dmabuf_get_width(dmabuf), > + qemu_dmabuf_get_height(dmabuf), > + NULL); > + > + if (qemu_dmabuf_get_allow_fences(dmabuf)) { > + scon->guest_fb.dmabuf = dmabuf; > + } > +} > + > +void sdl2_gl_release_dmabuf(DisplayChangeListener *dcl, > + QemuDmaBuf *dmabuf) > +{ > + egl_dmabuf_release_texture(dmabuf); > +} > + > +bool sdl2_gl_has_dmabuf(DisplayChangeListener *dcl) > +{ > + struct sdl2_console *scon = container_of(dcl, struct sdl2_console, dcl); > + > + return scon->has_dmabuf; > +} > + > +void sdl2_gl_console_init(struct sdl2_console *scon) > +{ > + bool hidden = scon->hidden; > + > + scon->hidden = true; > + scon->surface = qemu_create_displaysurface(1, 1); > + sdl2_window_create(scon); > + > + /* > + * QEMU checks whether console supports dma-buf before switching > + * to the console. To break this chicken-egg problem we pre-check > + * dma-buf availability beforehand using a dummy SDL window. > + */ > + scon->has_dmabuf = qemu_egl_has_dmabuf(); > + > + sdl2_window_destroy(scon); > + qemu_free_displaysurface(scon->surface); > + > + scon->surface = NULL; > + scon->hidden = hidden; > +} > diff --git a/ui/sdl2.c b/ui/sdl2.c > index bd4f5a9da14a..5a1e5940c66a 100644 > --- a/ui/sdl2.c > +++ b/ui/sdl2.c > @@ -35,6 +35,10 @@ > #include "ui/win32-kbd-hook.h" > #include "qemu/log.h" > > +#ifdef CONFIG_XLIB > +#include <X11/Xlib.h> > +#endif > + > static int sdl2_num_outputs; > static struct sdl2_console *sdl2_console; > > @@ -120,6 +124,9 @@ void sdl2_window_create(struct sdl2_console *scon) > /* The SDL renderer is only used by sdl2-2D, when OpenGL is disabled */ > scon->real_renderer = SDL_CreateRenderer(scon->real_window, -1, 0); > } > + > + qemu_egl_display = eglGetCurrentDisplay(); > + > sdl_update_caption(scon); > } > > @@ -820,6 +827,10 @@ static const DisplayChangeListenerOps dcl_gl_ops = { > .dpy_gl_scanout_disable = sdl2_gl_scanout_disable, > .dpy_gl_scanout_texture = sdl2_gl_scanout_texture, > .dpy_gl_update = sdl2_gl_scanout_flush, > + > + .dpy_gl_scanout_dmabuf = sdl2_gl_scanout_dmabuf, > + .dpy_gl_release_dmabuf = sdl2_gl_release_dmabuf, > + .dpy_has_dmabuf = sdl2_gl_has_dmabuf, > }; > > static bool > @@ -847,6 +858,33 @@ static void sdl2_display_early_init(DisplayOptions *o) > } > } > > +static void sdl2_set_hint_x11_force_egl(void) > +{ > +#if defined(SDL_HINT_VIDEO_X11_FORCE_EGL) && defined(CONFIG_OPENGL) && \ > + defined(CONFIG_XLIB) > + Display *x_disp = XOpenDisplay(NULL); > + EGLDisplay egl_display; > + > + if (!x_disp) { > + return; > + } > + > + /* Prefer EGL over GLX to get dma-buf support. */ > + egl_display = eglGetDisplay((EGLNativeDisplayType)x_disp); > + > + if (egl_display != EGL_NO_DISPLAY) { > + /* > + * Setting X11_FORCE_EGL hint doesn't make SDL to prefer 11 over s/prefer 11 over/prefer X11 over/ Personally, I'm more concerned whether setting that hint will make an invalid argument error or something. > + * Wayland. I.e. SDL will use Wayland driver even if XWayland presents. > + */ > + SDL_SetHint(SDL_HINT_VIDEO_X11_FORCE_EGL, "1"); > + eglTerminate(egl_display); > + } > + > + XCloseDisplay(x_disp); > +#endif > +} > + > static void sdl2_display_init(DisplayState *ds, DisplayOptions *o) > { > uint8_t data = 0; > @@ -877,6 +915,7 @@ static void sdl2_display_init(DisplayState *ds, DisplayOptions *o) > SDL_SetHint(SDL_HINT_ALLOW_ALT_TAB_WHILE_GRABBED, "0"); > #endif > SDL_SetHint(SDL_HINT_WINDOWS_NO_CLOSE_ON_ALT_F4, "1"); > + sdl2_set_hint_x11_force_egl(); > SDL_EnableScreenSaver(); > memset(&info, 0, sizeof(info)); > SDL_VERSION(&info.version); > @@ -923,6 +962,7 @@ static void sdl2_display_init(DisplayState *ds, DisplayOptions *o) > sdl2_console[i].kbd = qkbd_state_init(con); > if (display_opengl) { > qemu_console_set_display_gl_ctx(con, &sdl2_console[i].dgc); > + sdl2_gl_console_init(&sdl2_console[i]); > } > register_displaychangelistener(&sdl2_console[i].dcl); >
Accidentally missed this email a week ago. Thanks again for all the reviews! On 10/31/24 10:32, Akihiko Odaki wrote: ... >> +# libx11 presents together with SDL or GTK libs on systems that >> support X11 >> +xlib = dependency('x11', required: false) > > There is a line saying: > x11 = dependency('x11', method: 'pkg-config', required: gtkx11.found()) > > Please reuse it. I've seen this option and choose not to use it because despite the brief 'X11' name, it's about X11 support specifically for GTK and not SDL. Though, we can use this GTK/X11 for now and improve Meson dependencies later on because in practice GTK is enabled for all distro-built QEMUs. Will switch to it in v3. ... >> +void sdl2_gl_scanout_dmabuf(DisplayChangeListener *dcl, >> + QemuDmaBuf *dmabuf) >> +{ >> + struct sdl2_console *scon = container_of(dcl, struct >> sdl2_console, dcl); >> + >> + assert(scon->opengl); >> + SDL_GL_MakeCurrent(scon->real_window, scon->winctx); >> + >> + egl_dmabuf_import_texture(dmabuf); >> + if (!qemu_dmabuf_get_texture(dmabuf)) { >> + error_report("%s: failed fd=%d", __func__, >> qemu_dmabuf_get_fd(dmabuf)); > > It still continues to call sdl2_gl_scanout_texture() and I doubt that's > what you meant. Indeed, better to bail out early on a error. ... >> +static void sdl2_set_hint_x11_force_egl(void) >> +{ >> +#if defined(SDL_HINT_VIDEO_X11_FORCE_EGL) && defined(CONFIG_OPENGL) && \ >> + defined(CONFIG_XLIB) >> + Display *x_disp = XOpenDisplay(NULL); >> + EGLDisplay egl_display; >> + >> + if (!x_disp) { >> + return; >> + } >> + >> + /* Prefer EGL over GLX to get dma-buf support. */ >> + egl_display = eglGetDisplay((EGLNativeDisplayType)x_disp); >> + >> + if (egl_display != EGL_NO_DISPLAY) { >> + /* >> + * Setting X11_FORCE_EGL hint doesn't make SDL to prefer 11 over > > s/prefer 11 over/prefer X11 over/ > > Personally, I'm more concerned whether setting that hint will make an > invalid argument error or something. There are no known side effects from setting that hint for QEMU and libsdl code looks sane. AFAICT, EGL is not enabled by default in SDL only because there are older SDL applications that use GLX features and they will be broken if SDL will switch to EGL by default. Technically, should be possible to make SDL use EGL on demand, like only when QEMU runs with enabled native-context for example. But there is no point in doing that today since there are no known problems with the EGL hint, IMO. We will be able to address problems if somebody will report a bug.
On 2024/11/09 15:52, Dmitry Osipenko wrote: > Accidentally missed this email a week ago. Thanks again for all the reviews! > > On 10/31/24 10:32, Akihiko Odaki wrote: > ... >>> +# libx11 presents together with SDL or GTK libs on systems that >>> support X11 >>> +xlib = dependency('x11', required: false) >> >> There is a line saying: >> x11 = dependency('x11', method: 'pkg-config', required: gtkx11.found()) >> >> Please reuse it. > > I've seen this option and choose not to use it because despite the brief > 'X11' name, it's about X11 support specifically for GTK and not SDL. > > Though, we can use this GTK/X11 for now and improve Meson dependencies > later on because in practice GTK is enabled for all distro-built QEMUs. > Will switch to it in v3. I think you can just remove "if gtkx11.found()" to use it for SDL. > > ... >>> +void sdl2_gl_scanout_dmabuf(DisplayChangeListener *dcl, >>> + QemuDmaBuf *dmabuf) >>> +{ >>> + struct sdl2_console *scon = container_of(dcl, struct >>> sdl2_console, dcl); >>> + >>> + assert(scon->opengl); >>> + SDL_GL_MakeCurrent(scon->real_window, scon->winctx); >>> + >>> + egl_dmabuf_import_texture(dmabuf); >>> + if (!qemu_dmabuf_get_texture(dmabuf)) { >>> + error_report("%s: failed fd=%d", __func__, >>> qemu_dmabuf_get_fd(dmabuf)); >> >> It still continues to call sdl2_gl_scanout_texture() and I doubt that's >> what you meant. > > Indeed, better to bail out early on a error. > > ... >>> +static void sdl2_set_hint_x11_force_egl(void) >>> +{ >>> +#if defined(SDL_HINT_VIDEO_X11_FORCE_EGL) && defined(CONFIG_OPENGL) && \ >>> + defined(CONFIG_XLIB) >>> + Display *x_disp = XOpenDisplay(NULL); >>> + EGLDisplay egl_display; >>> + >>> + if (!x_disp) { >>> + return; >>> + } >>> + >>> + /* Prefer EGL over GLX to get dma-buf support. */ >>> + egl_display = eglGetDisplay((EGLNativeDisplayType)x_disp); >>> + >>> + if (egl_display != EGL_NO_DISPLAY) { >>> + /* >>> + * Setting X11_FORCE_EGL hint doesn't make SDL to prefer 11 over >> >> s/prefer 11 over/prefer X11 over/ >> >> Personally, I'm more concerned whether setting that hint will make an >> invalid argument error or something. > > There are no known side effects from setting that hint for QEMU and > libsdl code looks sane. AFAICT, EGL is not enabled by default in SDL > only because there are older SDL applications that use GLX features and > they will be broken if SDL will switch to EGL by default. > > Technically, should be possible to make SDL use EGL on demand, like only > when QEMU runs with enabled native-context for example. But there is no > point in doing that today since there are no known problems with the EGL > hint, IMO. We will be able to address problems if somebody will report a > bug. > I was thinking of scenarios where X11 is not used. A convincing scenario of failure is that SDL emits an error for the flag and stops working. The fact that this code just works implies it is not the case, but it's worth noting if you leave a comment anyway. Regards, Akihiko Odaki
On 11/9/24 13:07, Akihiko Odaki wrote: > On 2024/11/09 15:52, Dmitry Osipenko wrote: >> Accidentally missed this email a week ago. Thanks again for all the >> reviews! >> >> On 10/31/24 10:32, Akihiko Odaki wrote: >> ... >>>> +# libx11 presents together with SDL or GTK libs on systems that >>>> support X11 >>>> +xlib = dependency('x11', required: false) >>> >>> There is a line saying: >>> x11 = dependency('x11', method: 'pkg-config', required: gtkx11.found()) >>> >>> Please reuse it. >> >> I've seen this option and choose not to use it because despite the brief >> 'X11' name, it's about X11 support specifically for GTK and not SDL. >> >> Though, we can use this GTK/X11 for now and improve Meson dependencies >> later on because in practice GTK is enabled for all distro-built QEMUs. >> Will switch to it in v3. > > I think you can just remove "if gtkx11.found()" to use it for SDL. Right, thanks. >> ... >>>> +static void sdl2_set_hint_x11_force_egl(void) >>>> +{ >>>> +#if defined(SDL_HINT_VIDEO_X11_FORCE_EGL) && defined(CONFIG_OPENGL) >>>> && \ >>>> + defined(CONFIG_XLIB) >>>> + Display *x_disp = XOpenDisplay(NULL); >>>> + EGLDisplay egl_display; >>>> + >>>> + if (!x_disp) { >>>> + return; >>>> + } >>>> + >>>> + /* Prefer EGL over GLX to get dma-buf support. */ >>>> + egl_display = eglGetDisplay((EGLNativeDisplayType)x_disp); >>>> + >>>> + if (egl_display != EGL_NO_DISPLAY) { >>>> + /* >>>> + * Setting X11_FORCE_EGL hint doesn't make SDL to prefer 11 >>>> over >>> >>> s/prefer 11 over/prefer X11 over/ >>> >>> Personally, I'm more concerned whether setting that hint will make an >>> invalid argument error or something. >> >> There are no known side effects from setting that hint for QEMU and >> libsdl code looks sane. AFAICT, EGL is not enabled by default in SDL >> only because there are older SDL applications that use GLX features and >> they will be broken if SDL will switch to EGL by default. >> > Technically, should be possible to make SDL use EGL on demand, like > only >> when QEMU runs with enabled native-context for example. But there is no >> point in doing that today since there are no known problems with the EGL >> hint, IMO. We will be able to address problems if somebody will report a >> bug. >> > > I was thinking of scenarios where X11 is not used. A convincing scenario > of failure is that SDL emits an error for the flag and stops working. > The fact that this code just works implies it is not the case, but it's > worth noting if you leave a comment anyway. We check X11 presence using XOpenDisplay() and hint won't be set if Xorg is unavailable. For the case of XWayland, there is already a comment in this patch telling that flag has no effect on Wayland. Will extend this comment, thanks.
diff --git a/include/ui/sdl2.h b/include/ui/sdl2.h index dbe6e3d9739b..9daf5ecffae7 100644 --- a/include/ui/sdl2.h +++ b/include/ui/sdl2.h @@ -45,6 +45,7 @@ struct sdl2_console { bool gui_keysym; SDL_GLContext winctx; QKbdState *kbd; + bool has_dmabuf; #ifdef CONFIG_OPENGL QemuGLShader *gls; egl_fb guest_fb; @@ -96,5 +97,11 @@ void sdl2_gl_scanout_texture(DisplayChangeListener *dcl, void *d3d_tex2d); void sdl2_gl_scanout_flush(DisplayChangeListener *dcl, uint32_t x, uint32_t y, uint32_t w, uint32_t h); +void sdl2_gl_scanout_dmabuf(DisplayChangeListener *dcl, + QemuDmaBuf *dmabuf); +void sdl2_gl_release_dmabuf(DisplayChangeListener *dcl, + QemuDmaBuf *dmabuf); +bool sdl2_gl_has_dmabuf(DisplayChangeListener *dcl); +void sdl2_gl_console_init(struct sdl2_console *scon); #endif /* SDL2_H */ diff --git a/meson.build b/meson.build index 089cbd2bb364..1ace2bfa0ebe 100644 --- a/meson.build +++ b/meson.build @@ -1531,6 +1531,9 @@ else sdl_image = not_found endif +# libx11 presents together with SDL or GTK libs on systems that support X11 +xlib = dependency('x11', required: false) + rbd = not_found if not get_option('rbd').auto() or have_block librados = cc.find_library('rados', required: get_option('rbd')) @@ -2397,6 +2400,7 @@ config_host_data.set('CONFIG_RELOCATABLE', get_option('relocatable')) config_host_data.set('CONFIG_SAFESTACK', get_option('safe_stack')) config_host_data.set('CONFIG_SDL', sdl.found()) config_host_data.set('CONFIG_SDL_IMAGE', sdl_image.found()) +config_host_data.set('CONFIG_XLIB', xlib.found()) config_host_data.set('CONFIG_SECCOMP', seccomp.found()) if seccomp.found() config_host_data.set('CONFIG_SECCOMP_SYSRAWRC', seccomp_has_sysrawrc) diff --git a/ui/sdl2-gl.c b/ui/sdl2-gl.c index b1fe96d6af22..7612af18292c 100644 --- a/ui/sdl2-gl.c +++ b/ui/sdl2-gl.c @@ -26,6 +26,8 @@ */ #include "qemu/osdep.h" +#include "qemu/main-loop.h" +#include "qemu/error-report.h" #include "ui/console.h" #include "ui/input.h" #include "ui/sdl2.h" @@ -249,3 +251,64 @@ void sdl2_gl_scanout_flush(DisplayChangeListener *dcl, SDL_GL_SwapWindow(scon->real_window); } + +void sdl2_gl_scanout_dmabuf(DisplayChangeListener *dcl, + QemuDmaBuf *dmabuf) +{ + struct sdl2_console *scon = container_of(dcl, struct sdl2_console, dcl); + + assert(scon->opengl); + SDL_GL_MakeCurrent(scon->real_window, scon->winctx); + + egl_dmabuf_import_texture(dmabuf); + if (!qemu_dmabuf_get_texture(dmabuf)) { + error_report("%s: failed fd=%d", __func__, qemu_dmabuf_get_fd(dmabuf)); + } + + sdl2_gl_scanout_texture(dcl, qemu_dmabuf_get_texture(dmabuf), false, + qemu_dmabuf_get_width(dmabuf), + qemu_dmabuf_get_height(dmabuf), + 0, 0, + qemu_dmabuf_get_width(dmabuf), + qemu_dmabuf_get_height(dmabuf), + NULL); + + if (qemu_dmabuf_get_allow_fences(dmabuf)) { + scon->guest_fb.dmabuf = dmabuf; + } +} + +void sdl2_gl_release_dmabuf(DisplayChangeListener *dcl, + QemuDmaBuf *dmabuf) +{ + egl_dmabuf_release_texture(dmabuf); +} + +bool sdl2_gl_has_dmabuf(DisplayChangeListener *dcl) +{ + struct sdl2_console *scon = container_of(dcl, struct sdl2_console, dcl); + + return scon->has_dmabuf; +} + +void sdl2_gl_console_init(struct sdl2_console *scon) +{ + bool hidden = scon->hidden; + + scon->hidden = true; + scon->surface = qemu_create_displaysurface(1, 1); + sdl2_window_create(scon); + + /* + * QEMU checks whether console supports dma-buf before switching + * to the console. To break this chicken-egg problem we pre-check + * dma-buf availability beforehand using a dummy SDL window. + */ + scon->has_dmabuf = qemu_egl_has_dmabuf(); + + sdl2_window_destroy(scon); + qemu_free_displaysurface(scon->surface); + + scon->surface = NULL; + scon->hidden = hidden; +} diff --git a/ui/sdl2.c b/ui/sdl2.c index bd4f5a9da14a..5a1e5940c66a 100644 --- a/ui/sdl2.c +++ b/ui/sdl2.c @@ -35,6 +35,10 @@ #include "ui/win32-kbd-hook.h" #include "qemu/log.h" +#ifdef CONFIG_XLIB +#include <X11/Xlib.h> +#endif + static int sdl2_num_outputs; static struct sdl2_console *sdl2_console; @@ -120,6 +124,9 @@ void sdl2_window_create(struct sdl2_console *scon) /* The SDL renderer is only used by sdl2-2D, when OpenGL is disabled */ scon->real_renderer = SDL_CreateRenderer(scon->real_window, -1, 0); } + + qemu_egl_display = eglGetCurrentDisplay(); + sdl_update_caption(scon); } @@ -820,6 +827,10 @@ static const DisplayChangeListenerOps dcl_gl_ops = { .dpy_gl_scanout_disable = sdl2_gl_scanout_disable, .dpy_gl_scanout_texture = sdl2_gl_scanout_texture, .dpy_gl_update = sdl2_gl_scanout_flush, + + .dpy_gl_scanout_dmabuf = sdl2_gl_scanout_dmabuf, + .dpy_gl_release_dmabuf = sdl2_gl_release_dmabuf, + .dpy_has_dmabuf = sdl2_gl_has_dmabuf, }; static bool @@ -847,6 +858,33 @@ static void sdl2_display_early_init(DisplayOptions *o) } } +static void sdl2_set_hint_x11_force_egl(void) +{ +#if defined(SDL_HINT_VIDEO_X11_FORCE_EGL) && defined(CONFIG_OPENGL) && \ + defined(CONFIG_XLIB) + Display *x_disp = XOpenDisplay(NULL); + EGLDisplay egl_display; + + if (!x_disp) { + return; + } + + /* Prefer EGL over GLX to get dma-buf support. */ + egl_display = eglGetDisplay((EGLNativeDisplayType)x_disp); + + if (egl_display != EGL_NO_DISPLAY) { + /* + * Setting X11_FORCE_EGL hint doesn't make SDL to prefer 11 over + * Wayland. I.e. SDL will use Wayland driver even if XWayland presents. + */ + SDL_SetHint(SDL_HINT_VIDEO_X11_FORCE_EGL, "1"); + eglTerminate(egl_display); + } + + XCloseDisplay(x_disp); +#endif +} + static void sdl2_display_init(DisplayState *ds, DisplayOptions *o) { uint8_t data = 0; @@ -877,6 +915,7 @@ static void sdl2_display_init(DisplayState *ds, DisplayOptions *o) SDL_SetHint(SDL_HINT_ALLOW_ALT_TAB_WHILE_GRABBED, "0"); #endif SDL_SetHint(SDL_HINT_WINDOWS_NO_CLOSE_ON_ALT_F4, "1"); + sdl2_set_hint_x11_force_egl(); SDL_EnableScreenSaver(); memset(&info, 0, sizeof(info)); SDL_VERSION(&info.version); @@ -923,6 +962,7 @@ static void sdl2_display_init(DisplayState *ds, DisplayOptions *o) sdl2_console[i].kbd = qkbd_state_init(con); if (display_opengl) { qemu_console_set_display_gl_ctx(con, &sdl2_console[i].dgc); + sdl2_gl_console_init(&sdl2_console[i]); } register_displaychangelistener(&sdl2_console[i].dcl);