[PATCH v1 2/6] ui/sdl2: Implement dpy dmabuf functions

Dmitry Osipenko posted 6 patches 1 month, 2 weeks ago
There is a newer version of this series
[PATCH v1 2/6] ui/sdl2: Implement dpy dmabuf functions
Posted by Dmitry Osipenko 1 month, 2 weeks ago
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
Re: [PATCH v1 2/6] ui/sdl2: Implement dpy dmabuf functions
Posted by Akihiko Odaki 1 month, 2 weeks ago
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);