I mistakenly dropped CC (again). My apologies.

---------- Forwarded message ---------
From: Akihiko Odaki <akihiko.od...@gmail.com>
Date: Thu, Feb 17, 2022 at 9:38 PM
Subject: Re: [PATCH v2 12/12] ui/dbus: fix texture sharing
To: Marc-André Lureau <marcandre.lur...@redhat.com>


On Thu, Feb 17, 2022 at 9:02 PM <marcandre.lur...@redhat.com> wrote:
>
> From: Marc-André Lureau <marcandre.lur...@redhat.com>
>
> The DBus listener naively create, update and destroy textures without
> taking into account other listeners. The texture were shared, but
> texture update was unnecessarily duplicated.
>
> Teach DisplayGLCtx to do optionally shared texture handling. This is
> only implemented for DBus display at this point, however the same
> infrastructure could potentially be used for egl-headless & VNC
> listeners for example, or other future combinations.

egl-headless only needs one DisplayChangeListener per console since
its output is propagated by ui/console. The vnc protocol is for remote
access and therefore cannot have OpenGL textures. The functionality is
unique to dbus.

>
> Reported-by: Akihiko Odaki <akihiko.od...@gmail.com>
> Signed-off-by: Marc-André Lureau <marcandre.lur...@redhat.com>
> ---
>  include/ui/console.h | 10 ++++++++++
>  ui/console.c         | 26 ++++++++++++++++++++++++++
>  ui/dbus-listener.c   | 11 -----------
>  ui/dbus.c            | 24 ++++++++++++++++++++++++
>  4 files changed, 60 insertions(+), 11 deletions(-)
>
> diff --git a/include/ui/console.h b/include/ui/console.h
> index 18a10c0b7db0..0f84861933e1 100644
> --- a/include/ui/console.h
> +++ b/include/ui/console.h
> @@ -290,10 +290,20 @@ typedef struct DisplayGLCtxOps {
>                                 QEMUGLContext ctx);
>      int (*dpy_gl_ctx_make_current)(DisplayGLCtx *dgc,
>                                     QEMUGLContext ctx);
> +    void (*dpy_gl_ctx_create_texture)(DisplayGLCtx *dgc,
> +                                      DisplaySurface *surface);
> +    void (*dpy_gl_ctx_destroy_texture)(DisplayGLCtx *dgc,
> +                                      DisplaySurface *surface);
> +    void (*dpy_gl_ctx_update_texture)(DisplayGLCtx *dgc,
> +                                      DisplaySurface *surface,
> +                                      int x, int y, int w, int h);
>  } DisplayGLCtxOps;
>
>  struct DisplayGLCtx {
>      const DisplayGLCtxOps *ops;
> +#ifdef CONFIG_OPENGL
> +    QemuGLShader *gls; /* optional shared shader */
> +#endif
>  };
>
>  DisplayState *init_displaystate(void);
> diff --git a/ui/console.c b/ui/console.c
> index 102fcf0a5068..b9188559fb12 100644
> --- a/ui/console.c
> +++ b/ui/console.c
> @@ -1066,6 +1066,27 @@ static void 
> displaychangelistener_gfx_switch(DisplayChangeListener *dcl,
>      }
>  }
>
> +static void dpy_gfx_create_texture(QemuConsole *con, DisplaySurface *surface)
> +{
> +    if (con->gl && con->gl->ops->dpy_gl_ctx_create_texture) {
> +        con->gl->ops->dpy_gl_ctx_create_texture(con->gl, surface);
> +    }
> +}
> +
> +static void dpy_gfx_destroy_texture(QemuConsole *con, DisplaySurface 
> *surface)
> +{
> +    if (con->gl && con->gl->ops->dpy_gl_ctx_destroy_texture) {
> +        con->gl->ops->dpy_gl_ctx_destroy_texture(con->gl, surface);
> +    }
> +}
> +
> +static void dpy_gfx_update_texture(QemuConsole *con, DisplaySurface *surface,
> +                                   int x, int y, int w, int h)
> +{
> +    if (con->gl && con->gl->ops->dpy_gl_ctx_update_texture) {
> +        con->gl->ops->dpy_gl_ctx_update_texture(con->gl, surface, x, y, w, 
> h);
> +    }
> +}
>
>  static void displaychangelistener_display_console(DisplayChangeListener *dcl,
>                                                    QemuConsole *con,
> @@ -1078,6 +1099,7 @@ static void 
> displaychangelistener_display_console(DisplayChangeListener *dcl,
>      if (!con || !console_compatible_with(con, dcl, errp)) {
>          if (!dummy) {
>              dummy = qemu_create_placeholder_surface(640, 480, nodev);
> +            dpy_gfx_create_texture(con, dummy);
>          }
>          displaychangelistener_gfx_switch(dcl, dummy);
>          return;
> @@ -1098,6 +1120,7 @@ static void 
> displaychangelistener_display_console(DisplayChangeListener *dcl,
>                                           con->scanout.texture.width,
>                                           con->scanout.texture.height);
>      } else if (con->scanout.kind == SCANOUT_SURFACE) {
> +        dpy_gfx_create_texture(con, con->surface);
>          displaychangelistener_gfx_switch(dcl, con->surface);
>      }
>
> @@ -1634,6 +1657,7 @@ void dpy_gfx_update(QemuConsole *con, int x, int y, int 
> w, int h)
>      if (!qemu_console_is_visible(con)) {
>          return;
>      }
> +    dpy_gfx_update_texture(con, con->surface, x, y, w, h);
>      QLIST_FOREACH(dcl, &s->listeners, next) {
>          if (con != (dcl->con ? dcl->con : active_console)) {
>              continue;
> @@ -1678,12 +1702,14 @@ void dpy_gfx_replace_surface(QemuConsole *con,
>
>      con->scanout.kind = SCANOUT_SURFACE;
>      con->surface = surface;
> +    dpy_gfx_create_texture(con, surface);
>      QLIST_FOREACH(dcl, &s->listeners, next) {
>          if (con != (dcl->con ? dcl->con : active_console)) {
>              continue;
>          }
>          displaychangelistener_gfx_switch(dcl, surface);
>      }
> +    dpy_gfx_destroy_texture(con, old_surface);
>      qemu_free_displaysurface(old_surface);
>  }
>
> diff --git a/ui/dbus-listener.c b/ui/dbus-listener.c
> index 81c119b13a2c..a287edd2fc15 100644
> --- a/ui/dbus-listener.c
> +++ b/ui/dbus-listener.c
> @@ -42,7 +42,6 @@ struct _DBusDisplayListener {
>
>      DisplayChangeListener dcl;
>      DisplaySurface *ds;
> -    QemuGLShader *gls;
>      int gl_updates;
>  };
>
> @@ -240,10 +239,6 @@ static void dbus_gl_gfx_update(DisplayChangeListener 
> *dcl,
>  {
>      DBusDisplayListener *ddl = container_of(dcl, DBusDisplayListener, dcl);
>
> -    if (ddl->ds) {
> -        surface_gl_update_texture(ddl->gls, ddl->ds, x, y, w, h);
> -    }
> -
>      ddl->gl_updates++;
>  }
>
> @@ -285,15 +280,11 @@ static void dbus_gl_gfx_switch(DisplayChangeListener 
> *dcl,
>  {
>      DBusDisplayListener *ddl = container_of(dcl, DBusDisplayListener, dcl);
>
> -    if (ddl->ds) {
> -        surface_gl_destroy_texture(ddl->gls, ddl->ds);
> -    }
>      ddl->ds = new_surface;
>      if (ddl->ds) {
>          int width = surface_width(ddl->ds);
>          int height = surface_height(ddl->ds);
>
> -        surface_gl_create_texture(ddl->gls, ddl->ds);
>          /* TODO: lazy send dmabuf (there are unnecessary sent otherwise) */
>          dbus_scanout_texture(&ddl->dcl, ddl->ds->texture, false,
>                               width, height, 0, 0, width, height);
> @@ -403,7 +394,6 @@ dbus_display_listener_dispose(GObject *object)
>      g_clear_object(&ddl->conn);
>      g_clear_pointer(&ddl->bus_name, g_free);
>      g_clear_object(&ddl->proxy);
> -    g_clear_pointer(&ddl->gls, qemu_gl_fini_shader);
>
>      G_OBJECT_CLASS(dbus_display_listener_parent_class)->dispose(object);
>  }
> @@ -414,7 +404,6 @@ dbus_display_listener_constructed(GObject *object)
>      DBusDisplayListener *ddl = DBUS_DISPLAY_LISTENER(object);
>
>      if (display_opengl) {
> -        ddl->gls = qemu_gl_init_shader();
>          ddl->dcl.ops = &dbus_gl_dcl_ops;
>      } else {
>          ddl->dcl.ops = &dbus_dcl_ops;
> diff --git a/ui/dbus.c b/ui/dbus.c
> index 22c82d2f323a..8e2e4c9cad28 100644
> --- a/ui/dbus.c
> +++ b/ui/dbus.c
> @@ -55,11 +55,33 @@ dbus_is_compatible_dcl(DisplayGLCtx *dgc,
>      return dcl->ops == &dbus_gl_dcl_ops || dcl->ops == &dbus_console_dcl_ops;
>  }
>
> +static void
> +dbus_create_texture(DisplayGLCtx *ctx, DisplaySurface *surface)
> +{
> +    surface_gl_create_texture(ctx->gls, surface);
> +}
> +
> +static void
> +dbus_destroy_texture(DisplayGLCtx *ctx, DisplaySurface *surface)
> +{
> +    surface_gl_destroy_texture(ctx->gls, surface);
> +}
> +
> +static void
> +dbus_update_texture(DisplayGLCtx *ctx, DisplaySurface *surface,
> +                    int x, int y, int w, int h)
> +{
> +    surface_gl_update_texture(ctx->gls, surface, x, y, w, h);
> +}
> +
>  static const DisplayGLCtxOps dbus_gl_ops = {
>      .dpy_gl_ctx_is_compatible_dcl = dbus_is_compatible_dcl,
>      .dpy_gl_ctx_create       = dbus_create_context,
>      .dpy_gl_ctx_destroy      = qemu_egl_destroy_context,
>      .dpy_gl_ctx_make_current = qemu_egl_make_context_current,
> +    .dpy_gl_ctx_create_texture = dbus_create_texture,
> +    .dpy_gl_ctx_destroy_texture = dbus_destroy_texture,
> +    .dpy_gl_ctx_update_texture = dbus_update_texture,
>  };
>
>  static NotifierList dbus_display_notifiers =
> @@ -90,6 +112,7 @@ dbus_display_init(Object *o)
>      g_autoptr(GDBusObjectSkeleton) vm = NULL;
>
>      dd->glctx.ops = &dbus_gl_ops;
> +    dd->glctx.gls = qemu_gl_init_shader();
>      dd->iface = qemu_dbus_display1_vm_skeleton_new();
>      dd->consoles = g_ptr_array_new_with_free_func(g_object_unref);
>
> @@ -126,6 +149,7 @@ dbus_display_finalize(Object *o)
>      g_clear_object(&dd->iface);
>      g_free(dd->dbus_addr);
>      g_free(dd->audiodev);
> +    g_clear_pointer(&dd->glctx.gls, qemu_gl_fini_shader);
>      dbus_display = NULL;
>  }
>
> --
> 2.34.1.428.gdcc0cd074f0c
>

Reply via email to