On 3/4/26 11:49, Alex Bennée wrote:
> Dmitry Osipenko <[email protected]> writes:
>
>> From: Pierre-Eric Pelloux-Prayer <[email protected]>
>>
>> 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).
>>
>> Reviewed-by: Akihiko Odaki <[email protected]>
>> Acked-by: Michael S. Tsirkin <[email protected]>
>> Tested-by: Alex Bennée <[email protected]>
>> Signed-off-by: Pierre-Eric Pelloux-Prayer
>> <[email protected]>
>> Reviewed-by: Yiwei Zhang <[email protected]>
>> Signed-off-by: Dmitry Osipenko <[email protected]>
>> ---
>> include/ui/sdl2.h | 7 +++++
>> meson.build | 6 ++---
>> ui/sdl2-gl.c | 66 +++++++++++++++++++++++++++++++++++++++++++++++
>> ui/sdl2.c | 42 ++++++++++++++++++++++++++++++
>> 4 files changed, 117 insertions(+), 4 deletions(-)
>>
>> 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 3cd1d8dbc669..0ce84d45e6f3 100644
>> --- a/meson.build
>> +++ b/meson.build
>> @@ -1937,10 +1937,8 @@ if get_option('gtk') \
>> endif
>> endif
>>
>> -x11 = not_found
>> -if gtkx11.found()
>> - x11 = dependency('x11', method: 'pkg-config', required: gtkx11.found())
>> -endif
>> +x11 = dependency('x11', method: 'pkg-config', required: gtkx11.found())
>> +
>> png = not_found
>> if get_option('png').allowed() and have_system
>> png = dependency('libpng', version: '>=1.6.34', required:
>> get_option('png'),
>> diff --git a/ui/sdl2-gl.c b/ui/sdl2-gl.c
>> index fbac3edbc09d..697ba2169c34 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"
>> @@ -250,3 +252,67 @@ 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);
>> + const int *fds;
>> +
>> + assert(scon->opengl);
>> + SDL_GL_MakeCurrent(scon->real_window, scon->winctx);
>> +
>> + egl_dmabuf_import_texture(dmabuf);
>> + if (!qemu_dmabuf_get_texture(dmabuf)) {
>> + fds = qemu_dmabuf_get_fds(dmabuf, NULL);
>> + error_report("%s: failed fd=%d", __func__, fds ? fds[0] : -1);
>> + return;
>> + }
>> +
>> + 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 032dc14bc398..3bb2676f847b 100644
>> --- a/ui/sdl2.c
>> +++ b/ui/sdl2.c
>> @@ -35,6 +35,10 @@
>> #include "qemu/log.h"
>> #include "qemu-main.h"
>>
>> +#ifdef CONFIG_X11
>> +#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();
>> +
>
> This fails on MacOS for some reason:
>
> o libsystem.a.p/ui_sdl2.c.o -c ../ui/sdl2.c
> ../ui/sdl2.c:128:5: error: use of undeclared identifier 'qemu_egl_display'
> 128 | qemu_egl_display = eglGetCurrentDisplay();
> | ^
> ../ui/sdl2.c:128:24: error: call to undeclared function
> 'eglGetCurrentDisplay'; ISO C99 and later do not support implicit function
> declarations [-Wimplicit-function-declaration]
> 128 | qemu_egl_display = eglGetCurrentDisplay();
> | ^
> 2 errors generated.
>
> See: https://gitlab.com/stsquad/qemu/-/jobs/13340079105
>
> Not sure what the include differences are because --enable-sdl builds
> fine on Linux.
Please try with this change and let me know if you could squash it or I
need to send a patch:
diff --git a/ui/sdl2.c b/ui/sdl2.c
index 3bb2676f847b..2603b0c2bdd8 100644
--- a/ui/sdl2.c
+++ b/ui/sdl2.c
@@ -125,7 +125,9 @@ void sdl2_window_create(struct sdl2_console *scon)
scon->real_renderer = SDL_CreateRenderer(scon->real_window, -1, 0);
}
+#ifdef CONFIG_OPENGL
qemu_egl_display = eglGetCurrentDisplay();
+#endif
sdl_update_caption(scon);
}
--
Best regards,
Dmitry