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 | 5 +++++
ui/sdl2-gl.c | 39 +++++++++++++++++++++++++++++++++++++++
ui/sdl2.c | 8 ++++++++
3 files changed, 52 insertions(+)
diff --git a/include/ui/sdl2.h b/include/ui/sdl2.h
index dbe6e3d9739b..b14552f5cd71 100644
--- a/include/ui/sdl2.h
+++ b/include/ui/sdl2.h
@@ -96,5 +96,10 @@ 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);
#endif /* SDL2_H */
diff --git a/ui/sdl2-gl.c b/ui/sdl2-gl.c
index b1fe96d6af22..24aa9108682e 100644
--- a/ui/sdl2-gl.c
+++ b/ui/sdl2-gl.c
@@ -26,6 +26,7 @@
*/
#include "qemu/osdep.h"
+#include "qemu/main-loop.h"
#include "ui/console.h"
#include "ui/input.h"
#include "ui/sdl2.h"
@@ -227,6 +228,44 @@ void sdl2_gl_scanout_texture(DisplayChangeListener *dcl,
backing_id, false);
}
+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)) {
+ fprintf(stderr, "sdl2_gl_scanout_dmabuf failed fd=%d\n",
+ 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)
+{
+ return qemu_egl_has_dmabuf();
+}
+
void sdl2_gl_scanout_flush(DisplayChangeListener *dcl,
uint32_t x, uint32_t y, uint32_t w, uint32_t h)
{
diff --git a/ui/sdl2.c b/ui/sdl2.c
index bd4f5a9da14a..8c7b01c5e62f 100644
--- a/ui/sdl2.c
+++ b/ui/sdl2.c
@@ -120,6 +120,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 +823,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
@@ -877,6 +884,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");
+ SDL_SetHint(SDL_HINT_VIDEO_X11_FORCE_EGL, "1");
SDL_EnableScreenSaver();
memset(&info, 0, sizeof(info));
SDL_VERSION(&info.version);
--
2.46.0
On 2024/10/07 8:23, 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 | 5 +++++
> ui/sdl2-gl.c | 39 +++++++++++++++++++++++++++++++++++++++
> ui/sdl2.c | 8 ++++++++
> 3 files changed, 52 insertions(+)
>
> diff --git a/include/ui/sdl2.h b/include/ui/sdl2.h
> index dbe6e3d9739b..b14552f5cd71 100644
> --- a/include/ui/sdl2.h
> +++ b/include/ui/sdl2.h
> @@ -96,5 +96,10 @@ 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);
>
> #endif /* SDL2_H */
> diff --git a/ui/sdl2-gl.c b/ui/sdl2-gl.c
> index b1fe96d6af22..24aa9108682e 100644
> --- a/ui/sdl2-gl.c
> +++ b/ui/sdl2-gl.c
> @@ -26,6 +26,7 @@
> */
>
> #include "qemu/osdep.h"
> +#include "qemu/main-loop.h"
> #include "ui/console.h"
> #include "ui/input.h"
> #include "ui/sdl2.h"
> @@ -227,6 +228,44 @@ void sdl2_gl_scanout_texture(DisplayChangeListener *dcl,
> backing_id, false);
> }
>
> +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)) {
> + fprintf(stderr, "sdl2_gl_scanout_dmabuf failed fd=%d\n",
> + qemu_dmabuf_get_fd(dmabuf));
Use error_report(). Use __func__ to print the function name.
> + }
> +
> + 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)
> +{
> + return qemu_egl_has_dmabuf();
> +}
> +
> void sdl2_gl_scanout_flush(DisplayChangeListener *dcl,
> uint32_t x, uint32_t y, uint32_t w, uint32_t h)
> {
> diff --git a/ui/sdl2.c b/ui/sdl2.c
> index bd4f5a9da14a..8c7b01c5e62f 100644
> --- a/ui/sdl2.c
> +++ b/ui/sdl2.c
> @@ -120,6 +120,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 +823,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
> @@ -877,6 +884,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");
> + SDL_SetHint(SDL_HINT_VIDEO_X11_FORCE_EGL, "1");
I think it needs to handle cases where X11 is not used or only GLX is
available.
> SDL_EnableScreenSaver();
> memset(&info, 0, sizeof(info));
> SDL_VERSION(&info.version);
© 2016 - 2026 Red Hat, Inc.