mirror of
https://github.com/qemu/qemu.git
synced 2026-04-05 22:00:58 +00:00
ui/sdl2: Implement dpy dmabuf functions
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 <akihiko.odaki@daynix.com> Acked-by: Michael S. Tsirkin <mst@redhat.com> Tested-by: Alex Bennée <alex.bennee@linaro.org> Signed-off-by: Pierre-Eric Pelloux-Prayer <pierre-eric.pelloux-prayer@amd.com> Reviewed-by: Yiwei Zhang <zzyiwei@gmail.com> Signed-off-by: Dmitry Osipenko <dmitry.osipenko@collabora.com> Message-ID: <20260303151422.977399-7-dmitry.osipenko@collabora.com> [AJB: ifdef CONFIG_OPENGL/CONFIG_GBM for non-linux hosts] Message-ID: <20260304165043.1437519-9-alex.bennee@linaro.org> Signed-off-by: Alex Bennée <alex.bennee@linaro.org>
This commit is contained in:
committed by
Alex Bennée
parent
2b0e2edc83
commit
52053b7e0a
@@ -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 */
|
||||
|
||||
@@ -1946,10 +1946,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'),
|
||||
|
||||
68
ui/sdl2-gl.c
68
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,69 @@ void sdl2_gl_scanout_flush(DisplayChangeListener *dcl,
|
||||
|
||||
SDL_GL_SwapWindow(scon->real_window);
|
||||
}
|
||||
|
||||
#ifdef CONFIG_GBM
|
||||
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;
|
||||
}
|
||||
#endif
|
||||
|
||||
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;
|
||||
}
|
||||
|
||||
48
ui/sdl2.c
48
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,11 @@ 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);
|
||||
}
|
||||
|
||||
#ifdef CONFIG_OPENGL
|
||||
qemu_egl_display = eglGetCurrentDisplay();
|
||||
#endif
|
||||
|
||||
sdl_update_caption(scon);
|
||||
}
|
||||
|
||||
@@ -808,6 +817,12 @@ 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,
|
||||
|
||||
#ifdef CONFIG_GBM
|
||||
.dpy_gl_scanout_dmabuf = sdl2_gl_scanout_dmabuf,
|
||||
.dpy_gl_release_dmabuf = sdl2_gl_release_dmabuf,
|
||||
.dpy_has_dmabuf = sdl2_gl_has_dmabuf,
|
||||
#endif
|
||||
};
|
||||
|
||||
static bool
|
||||
@@ -835,6 +850,35 @@ 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_X11)
|
||||
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 X11 over
|
||||
* Wayland. SDL will use Wayland driver even if XWayland presents.
|
||||
* It's always safe to set the hint even if X11 is not used by SDL.
|
||||
* SDL will work regardless of the hint.
|
||||
*/
|
||||
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;
|
||||
@@ -862,6 +906,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);
|
||||
@@ -906,9 +951,12 @@ static void sdl2_display_init(DisplayState *ds, DisplayOptions *o)
|
||||
#endif
|
||||
sdl2_console[i].dcl.con = con;
|
||||
sdl2_console[i].kbd = qkbd_state_init(con);
|
||||
#ifdef CONFIG_OPENGL
|
||||
if (display_opengl) {
|
||||
qemu_console_set_display_gl_ctx(con, &sdl2_console[i].dgc);
|
||||
sdl2_gl_console_init(&sdl2_console[i]);
|
||||
}
|
||||
#endif
|
||||
register_displaychangelistener(&sdl2_console[i].dcl);
|
||||
|
||||
#if defined(SDL_VIDEO_DRIVER_WINDOWS) || defined(SDL_VIDEO_DRIVER_X11)
|
||||
|
||||
Reference in New Issue
Block a user