All of lore.kernel.org
 help / color / mirror / Atom feed
* [PATCH] ui/console: Assert graphic console surface is not NULL
@ 2021-02-19 10:17 Akihiko Odaki
  2021-02-19 14:48 ` Gerd Hoffmann
  0 siblings, 1 reply; 14+ messages in thread
From: Akihiko Odaki @ 2021-02-19 10:17 UTC (permalink / raw)
  Cc: Michael S. Tsirkin, qemu-devel, Akihiko Odaki, Gerd Hoffmann

ui/console used to accept NULL as graphic console surface, but its
semantics was inconsistent among displays:
- cocoa and gtk-egl perform NULL dereference.
- egl-headless, spice and spice-egl do nothing.
- gtk releases underlying resources.
- sdl2-2d and sdl2-gl destroys the window.
- vnc shows a message, "Display output is not active."

Fortunately, there are only three cases where NULL is assigned as
graphic console surface, and we can study them to figure out the
desired behavior:
- virtio-gpu-base assigns NULL when the device is realized.
  We have nothing to do in the case because graphic consoles
  already have a surface with a message saying the content is
  not initializd yet.
- virtio-gpu-3d assigns NULL when the device is reset. The initial
  graphic console surfaces shows a message, so it would be
  appropriate to do similar.
- virtio-gpu-3d assigns NULL when scanout is disabled. That
  affects its operations later but itself do not mean any effects
  on displays. Removing the operation should be fine.

This change eliminates NULL as graphic console surface by
implementing those behaviors.

An assertion is added and NULL checks are removed in ui/console
to prevent NULL from being set again. However, this do not change
any references except those in ui/console because there are too
many of them to fix for a mere motal.

Signed-off-by: Akihiko Odaki <akihiko.odaki@gmail.com>
---
 hw/display/virtio-gpu-3d.c   | 11 ++++++-----
 hw/display/virtio-gpu-base.c |  3 ---
 ui/console.c                 | 31 +++++++++----------------------
 3 files changed, 15 insertions(+), 30 deletions(-)

diff --git a/hw/display/virtio-gpu-3d.c b/hw/display/virtio-gpu-3d.c
index 0b0c11474dd..4cf1901b47f 100644
--- a/hw/display/virtio-gpu-3d.c
+++ b/hw/display/virtio-gpu-3d.c
@@ -179,10 +179,6 @@ static void virgl_cmd_set_scanout(VirtIOGPU *g,
             info.width, info.height,
             ss.r.x, ss.r.y, ss.r.width, ss.r.height);
     } else {
-        if (ss.scanout_id != 0) {
-            dpy_gfx_replace_surface(
-                g->parent_obj.scanout[ss.scanout_id].con, NULL);
-        }
         dpy_gl_scanout_disable(g->parent_obj.scanout[ss.scanout_id].con);
     }
     g->parent_obj.scanout[ss.scanout_id].resource_id = ss.resource_id;
@@ -596,7 +592,12 @@ void virtio_gpu_virgl_reset(VirtIOGPU *g)
     virgl_renderer_reset();
     for (i = 0; i < g->parent_obj.conf.max_outputs; i++) {
         if (i != 0) {
-            dpy_gfx_replace_surface(g->parent_obj.scanout[i].con, NULL);
+            DisplaySurface *surface =
+                qemu_create_message_surface(g->parent_obj.conf.xres,
+                                            g->parent_obj.conf.yres,
+                                            "Guest reset display.");
+
+            dpy_gfx_replace_surface(g->parent_obj.scanout[i].con, surface);
         }
         dpy_gl_scanout_disable(g->parent_obj.scanout[i].con);
     }
diff --git a/hw/display/virtio-gpu-base.c b/hw/display/virtio-gpu-base.c
index 40ccd00f942..abc5fc89b9b 100644
--- a/hw/display/virtio-gpu-base.c
+++ b/hw/display/virtio-gpu-base.c
@@ -168,9 +168,6 @@ virtio_gpu_base_device_realize(DeviceState *qdev,
     for (i = 0; i < g->conf.max_outputs; i++) {
         g->scanout[i].con =
             graphic_console_init(DEVICE(g), i, &virtio_gpu_ops, g);
-        if (i > 0) {
-            dpy_gfx_replace_surface(g->scanout[i].con, NULL);
-        }
     }
 
     return true;
diff --git a/ui/console.c b/ui/console.c
index d80ce7037c3..bc300182c84 100644
--- a/ui/console.c
+++ b/ui/console.c
@@ -1099,10 +1099,8 @@ void console_select(unsigned int index)
                     dcl->ops->dpy_gfx_switch(dcl, s->surface);
                 }
             }
-            if (s->surface) {
-                dpy_gfx_update(s, 0, 0, surface_width(s->surface),
-                               surface_height(s->surface));
-            }
+            dpy_gfx_update(s, 0, 0, surface_width(s->surface),
+                           surface_height(s->surface));
         }
         if (ds->have_text) {
             dpy_text_resize(s, s->width, s->height);
@@ -1587,13 +1585,9 @@ void dpy_gfx_update(QemuConsole *con, int x, int y, int w, int h)
 {
     DisplayState *s = con->ds;
     DisplayChangeListener *dcl;
-    int width = w;
-    int height = h;
+    int width = surface_width(con->surface);
+    int height = surface_height(con->surface);
 
-    if (con->surface) {
-        width = surface_width(con->surface);
-        height = surface_height(con->surface);
-    }
     x = MAX(x, 0);
     y = MAX(y, 0);
     x = MIN(x, width);
@@ -1616,9 +1610,6 @@ void dpy_gfx_update(QemuConsole *con, int x, int y, int w, int h)
 
 void dpy_gfx_update_full(QemuConsole *con)
 {
-    if (!con->surface) {
-        return;
-    }
     dpy_gfx_update(con, 0, 0,
                    surface_width(con->surface),
                    surface_height(con->surface));
@@ -1631,7 +1622,8 @@ void dpy_gfx_replace_surface(QemuConsole *con,
     DisplaySurface *old_surface = con->surface;
     DisplayChangeListener *dcl;
 
-    assert(old_surface != surface || surface == NULL);
+    assert(surface);
+    assert(old_surface != surface);
 
     con->surface = surface;
     QLIST_FOREACH(dcl, &s->listeners, next) {
@@ -1976,13 +1968,8 @@ void graphic_console_close(QemuConsole *con)
     static const char unplugged[] =
         "Guest display has been unplugged";
     DisplaySurface *surface;
-    int width = 640;
-    int height = 480;
-
-    if (con->surface) {
-        width = surface_width(con->surface);
-        height = surface_height(con->surface);
-    }
+    int width = surface_width(con->surface);
+    int height = surface_height(con->surface);
 
     trace_console_gfx_close(con->index);
     object_property_set_link(OBJECT(con), "device", NULL, &error_abort);
@@ -2293,7 +2280,7 @@ void qemu_console_resize(QemuConsole *s, int width, int height)
 
     assert(s->console_type == GRAPHIC_CONSOLE);
 
-    if (s->surface && (s->surface->flags & QEMU_ALLOCATED_FLAG) &&
+    if ((s->surface->flags & QEMU_ALLOCATED_FLAG) &&
         pixman_image_get_width(s->surface->image) == width &&
         pixman_image_get_height(s->surface->image) == height) {
         return;
-- 
2.24.3 (Apple Git-128)



^ permalink raw reply related	[flat|nested] 14+ messages in thread

* Re: [PATCH] ui/console: Assert graphic console surface is not NULL
  2021-02-19 10:17 [PATCH] ui/console: Assert graphic console surface is not NULL Akihiko Odaki
@ 2021-02-19 14:48 ` Gerd Hoffmann
  2021-02-20 11:38   ` [PATCH v2] ui/console: Pass placeholder surface to displays Akihiko Odaki
  0 siblings, 1 reply; 14+ messages in thread
From: Gerd Hoffmann @ 2021-02-19 14:48 UTC (permalink / raw)
  To: Akihiko Odaki; +Cc: qemu-devel, Michael S. Tsirkin

On Fri, Feb 19, 2021 at 07:17:02PM +0900, Akihiko Odaki wrote:
> ui/console used to accept NULL as graphic console surface, but its
> semantics was inconsistent among displays:
> - cocoa and gtk-egl perform NULL dereference.
> - egl-headless, spice and spice-egl do nothing.
> - gtk releases underlying resources.
> - sdl2-2d and sdl2-gl destroys the window.
> - vnc shows a message, "Display output is not active."
> 
> Fortunately, there are only three cases where NULL is assigned as
> graphic console surface, and we can study them to figure out the
> desired behavior:
> - virtio-gpu-base assigns NULL when the device is realized.
>   We have nothing to do in the case because graphic consoles
>   already have a surface with a message saying the content is
>   not initializd yet.
> - virtio-gpu-3d assigns NULL when the device is reset. The initial
>   graphic console surfaces shows a message, so it would be
>   appropriate to do similar.
> - virtio-gpu-3d assigns NULL when scanout is disabled. That
>   affects its operations later but itself do not mean any effects
>   on displays. Removing the operation should be fine.
> 
> This change eliminates NULL as graphic console surface by
> implementing those behaviors.

No.

Background: Some display devices (qxl, virtio) support multiple outputs.
For secondary displays it totally makes sense to allow them being
disabled and the ui hiding the window then.  For the primary display it
usually is problematic though.

So in case the guest disabled the display virtio-gpu will create a
message surface for head 0 and pass NULL otherwise.

We certainly can make the whole thing more consistent.  One option I see
is deal with the surface == NULL case in dpy_gfx_replace_surface().  The
function can check whenever the display is primary (con->index == 0) and
show a message in that case and pass on the NULL otherwise.  We could
maybe also add a flag to the DisplayChangeListener struct to indicate
whenever surface == NULL can be handled (sdl for example) or not (vnc)
so dpy_gfx_replace_surface() could also create a message surface for
secondary displays if needed.

With that in plase virtio-gpu can just pass NULL for disabled displays
no matter what.  DisplayChangeListeners can ask for non-NULL surfaces if
they want.  All logic is in one place (dpy_gfx_replace_surface).

take care,
  Gerd



^ permalink raw reply	[flat|nested] 14+ messages in thread

* [PATCH v2] ui/console: Pass placeholder surface to displays
  2021-02-19 14:48 ` Gerd Hoffmann
@ 2021-02-20 11:38   ` Akihiko Odaki
  2021-02-22 10:51     ` Gerd Hoffmann
  0 siblings, 1 reply; 14+ messages in thread
From: Akihiko Odaki @ 2021-02-20 11:38 UTC (permalink / raw)
  Cc: Michael S. Tsirkin, qemu-devel, Akihiko Odaki, Gerd Hoffmann

ui/console used to accept NULL as graphic console surface, but its
semantics was inconsistent among displays:
- cocoa and gtk-egl perform NULL dereference.
- egl-headless, spice and spice-egl do nothing.
- gtk releases underlying resources.
- sdl2-2d and sdl2-gl destroys the window.
- vnc shows a message, "Display output is not active."

Fortunately, only virtio-gpu and virtio-gpu-3d assign NULL so
we can study them to figure out the desired behavior. They assign
NULL *except* for the primary display when the device is realized,
reset, or its scanout is disabled. This effectively destroys
windows for the (uninitialized) secondary displays.

To implement the consistent behavior of display device
realization/reset, this change embeds it to the operation
switching the surface. When NULL was given as a new surface when
switching, ui/console will instead passes a placeholder down
to each display listeners.

sdl calls is_placeholder when switching surfaces, and
destroys the window if the given surface was a placeholder. The
other displays simply shows the placeholder when the console is
inactive.

Signed-off-by: Akihiko Odaki <akihiko.odaki@gmail.com>
---
 include/ui/console.h |  6 ++++++
 ui/console.c         | 46 ++++++++++++++++++++++++++++++--------------
 ui/gtk.c             |  4 ----
 ui/sdl2-2d.c         |  7 ++-----
 ui/sdl2-gl.c         |  4 ++--
 ui/spice-display.c   |  6 +++---
 ui/vnc.c             | 10 ----------
 7 files changed, 45 insertions(+), 38 deletions(-)

diff --git a/include/ui/console.h b/include/ui/console.h
index d30e972d0b5..e0ac3850858 100644
--- a/include/ui/console.h
+++ b/include/ui/console.h
@@ -106,6 +106,7 @@ struct QemuConsoleClass {
 };
 
 #define QEMU_ALLOCATED_FLAG     0x01
+#define QEMU_PLACEHOLDER_FLAG   0x02
 
 typedef struct DisplaySurface {
     pixman_format_code_t format;
@@ -281,6 +282,11 @@ static inline int is_buffer_shared(DisplaySurface *surface)
     return !(surface->flags & QEMU_ALLOCATED_FLAG);
 }
 
+static inline int is_placeholder(DisplaySurface *surface)
+{
+    return surface->flags & QEMU_PLACEHOLDER_FLAG;
+}
+
 void register_displaychangelistener(DisplayChangeListener *dcl);
 void update_displaychangelistener(DisplayChangeListener *dcl,
                                   uint64_t interval);
diff --git a/ui/console.c b/ui/console.c
index c5d11bc7017..b786c36d5b1 100644
--- a/ui/console.c
+++ b/ui/console.c
@@ -1088,6 +1088,30 @@ static void console_putchar(QemuConsole *s, int ch)
     }
 }
 
+static void dpy_gfx_switch(DisplayChangeListener *dcl, DisplaySurface *surface)
+{
+    static DisplaySurface *placeholder;
+    static const char placeholder_msg[] = "Display output is not active.";
+    DisplaySurface *broadcast;
+
+    if (!dcl->ops->dpy_gfx_switch) {
+        return;
+    }
+
+    if (surface) {
+        broadcast = surface;
+    } else {
+        if (!placeholder) {
+            placeholder = qemu_create_message_surface(640, 480, placeholder_msg);
+            placeholder->flags |= QEMU_PLACEHOLDER_FLAG;
+        }
+
+        broadcast = placeholder;
+    }
+
+    dcl->ops->dpy_gfx_switch(dcl, broadcast);
+}
+
 void console_select(unsigned int index)
 {
     DisplayChangeListener *dcl;
@@ -1104,9 +1128,7 @@ void console_select(unsigned int index)
                 if (dcl->con != NULL) {
                     continue;
                 }
-                if (dcl->ops->dpy_gfx_switch) {
-                    dcl->ops->dpy_gfx_switch(dcl, s->surface);
-                }
+                dpy_gfx_switch(dcl, s->surface);
             }
             if (s->surface) {
                 dpy_gfx_update(s, 0, 0, surface_width(s->surface),
@@ -1545,15 +1567,13 @@ void register_displaychangelistener(DisplayChangeListener *dcl)
     } else {
         con = active_console;
     }
-    if (dcl->ops->dpy_gfx_switch) {
-        if (con) {
-            dcl->ops->dpy_gfx_switch(dcl, con->surface);
-        } else {
-            if (!dummy) {
-                dummy = qemu_create_message_surface(640, 480, nodev);
-            }
-            dcl->ops->dpy_gfx_switch(dcl, dummy);
+    if (con) {
+        dpy_gfx_switch(dcl, con->surface);
+    } else {
+        if (!dummy) {
+            dummy = qemu_create_message_surface(640, 480, nodev);
         }
+        dpy_gfx_switch(dcl, dummy);
     }
     text_console_update_cursor(NULL);
 }
@@ -1685,9 +1705,7 @@ void dpy_gfx_replace_surface(QemuConsole *con,
         if (con != (dcl->con ? dcl->con : active_console)) {
             continue;
         }
-        if (dcl->ops->dpy_gfx_switch) {
-            dcl->ops->dpy_gfx_switch(dcl, surface);
-        }
+        dpy_gfx_switch(dcl, surface);
     }
     qemu_free_displaysurface(old_surface);
 }
diff --git a/ui/gtk.c b/ui/gtk.c
index 79dc2401203..a4a5f981e2a 100644
--- a/ui/gtk.c
+++ b/ui/gtk.c
@@ -567,10 +567,6 @@ static void gd_switch(DisplayChangeListener *dcl,
     }
     vc->gfx.ds = surface;
 
-    if (!surface) {
-        return;
-    }
-
     if (surface->format == PIXMAN_x8r8g8b8) {
         /*
          * PIXMAN_x8r8g8b8 == CAIRO_FORMAT_RGB24
diff --git a/ui/sdl2-2d.c b/ui/sdl2-2d.c
index a2ea85127d5..ddd2e05734e 100644
--- a/ui/sdl2-2d.c
+++ b/ui/sdl2-2d.c
@@ -32,14 +32,11 @@ void sdl2_2d_update(DisplayChangeListener *dcl,
                     int x, int y, int w, int h)
 {
     struct sdl2_console *scon = container_of(dcl, struct sdl2_console, dcl);
-    DisplaySurface *surf = qemu_console_surface(dcl->con);
+    DisplaySurface *surf = scon->surface;
     SDL_Rect rect;
     size_t surface_data_offset;
     assert(!scon->opengl);
 
-    if (!surf) {
-        return;
-    }
     if (!scon->texture) {
         return;
     }
@@ -75,7 +72,7 @@ void sdl2_2d_switch(DisplayChangeListener *dcl,
         scon->texture = NULL;
     }
 
-    if (!new_surface) {
+    if (is_placeholder(new_surface)) {
         sdl2_window_destroy(scon);
         return;
     }
diff --git a/ui/sdl2-gl.c b/ui/sdl2-gl.c
index fd594d74611..a68697714f0 100644
--- a/ui/sdl2-gl.c
+++ b/ui/sdl2-gl.c
@@ -86,7 +86,7 @@ void sdl2_gl_switch(DisplayChangeListener *dcl,
 
     scon->surface = new_surface;
 
-    if (!new_surface) {
+    if (is_placeholder(new_surface)) {
         qemu_gl_fini_shader(scon->gls);
         scon->gls = NULL;
         sdl2_window_destroy(scon);
@@ -112,7 +112,7 @@ void sdl2_gl_refresh(DisplayChangeListener *dcl)
     assert(scon->opengl);
 
     graphic_hw_update(dcl->con);
-    if (scon->updates && scon->surface) {
+    if (scon->updates && scon->real_window) {
         scon->updates = 0;
         sdl2_gl_render_surface(scon);
     }
diff --git a/ui/spice-display.c b/ui/spice-display.c
index 6f32b66a6e7..222c7c20a2a 100644
--- a/ui/spice-display.c
+++ b/ui/spice-display.c
@@ -388,7 +388,7 @@ void qemu_spice_display_switch(SimpleSpiceDisplay *ssd,
     SimpleSpiceUpdate *update;
     bool need_destroy;
 
-    if (surface && ssd->surface &&
+    if (ssd->surface &&
         surface_width(surface) == pixman_image_get_width(ssd->surface) &&
         surface_height(surface) == pixman_image_get_height(ssd->surface) &&
         surface_format(surface) == pixman_image_get_format(ssd->surface)) {
@@ -410,8 +410,8 @@ void qemu_spice_display_switch(SimpleSpiceDisplay *ssd,
 
     /* full mode switch */
     trace_qemu_spice_display_surface(ssd->qxl.id,
-                                     surface ? surface_width(surface)  : 0,
-                                     surface ? surface_height(surface) : 0,
+                                     surface_width(surface),
+                                     surface_height(surface),
                                      false);
 
     memset(&ssd->dirty, 0, sizeof(ssd->dirty));
diff --git a/ui/vnc.c b/ui/vnc.c
index 16bb3be770b..310abc93781 100644
--- a/ui/vnc.c
+++ b/ui/vnc.c
@@ -790,20 +790,10 @@ static bool vnc_check_pageflip(DisplaySurface *s1,
 static void vnc_dpy_switch(DisplayChangeListener *dcl,
                            DisplaySurface *surface)
 {
-    static const char placeholder_msg[] =
-        "Display output is not active.";
-    static DisplaySurface *placeholder;
     VncDisplay *vd = container_of(dcl, VncDisplay, dcl);
     bool pageflip = vnc_check_pageflip(vd->ds, surface);
     VncState *vs;
 
-    if (surface == NULL) {
-        if (placeholder == NULL) {
-            placeholder = qemu_create_message_surface(640, 480, placeholder_msg);
-        }
-        surface = placeholder;
-    }
-
     vnc_abort_display_jobs(vd);
     vd->ds = surface;
 
-- 
2.24.3 (Apple Git-128)



^ permalink raw reply related	[flat|nested] 14+ messages in thread

* Re: [PATCH v2] ui/console: Pass placeholder surface to displays
  2021-02-20 11:38   ` [PATCH v2] ui/console: Pass placeholder surface to displays Akihiko Odaki
@ 2021-02-22 10:51     ` Gerd Hoffmann
  2021-02-23  4:43       ` Akihiko Odaki
  0 siblings, 1 reply; 14+ messages in thread
From: Gerd Hoffmann @ 2021-02-22 10:51 UTC (permalink / raw)
  To: Akihiko Odaki; +Cc: qemu-devel, Michael S. Tsirkin

  Hi,

>  #define QEMU_ALLOCATED_FLAG     0x01
> +#define QEMU_PLACEHOLDER_FLAG   0x02

> +static inline int is_placeholder(DisplaySurface *surface)
> +{
> +    return surface->flags & QEMU_PLACEHOLDER_FLAG;
> +}

Interesting idea.  That approach makes sense too.

> +        if (!placeholder) {
> +            placeholder = qemu_create_message_surface(640, 480, placeholder_msg);
> +            placeholder->flags |= QEMU_PLACEHOLDER_FLAG;

I think we should set the placeholder flag in
qemu_create_message_surface() because every surface created with that
function is some kind if placeholder.

Also when replacing an existing surface we should make the placeholder
the same size, to avoid pointless ui window resizes.

> -    if (!new_surface) {
> +    if (is_placeholder(new_surface)) {

We should check whenever this is the primary or a secondary window here
and only destroy secondary windows.  qemu hiding all windows but
continuing to run has great potential for user confusion ...

> -    if (!new_surface) {
> +    if (is_placeholder(new_surface)) {

Same here.

take care,
  Gerd



^ permalink raw reply	[flat|nested] 14+ messages in thread

* Re: [PATCH v2] ui/console: Pass placeholder surface to displays
  2021-02-22 10:51     ` Gerd Hoffmann
@ 2021-02-23  4:43       ` Akihiko Odaki
  2021-02-24 11:06         ` Gerd Hoffmann
  0 siblings, 1 reply; 14+ messages in thread
From: Akihiko Odaki @ 2021-02-23  4:43 UTC (permalink / raw)
  To: Gerd Hoffmann; +Cc: qemu Developers, Michael S. Tsirkin

2021年2月22日(月) 19:51 Gerd Hoffmann <kraxel@redhat.com>:
>
>   Hi,
>
> >  #define QEMU_ALLOCATED_FLAG     0x01
> > +#define QEMU_PLACEHOLDER_FLAG   0x02
>
> > +static inline int is_placeholder(DisplaySurface *surface)
> > +{
> > +    return surface->flags & QEMU_PLACEHOLDER_FLAG;
> > +}
>
> Interesting idea.  That approach makes sense too.
>
> > +        if (!placeholder) {
> > +            placeholder = qemu_create_message_surface(640, 480, placeholder_msg);
> > +            placeholder->flags |= QEMU_PLACEHOLDER_FLAG;
>
> I think we should set the placeholder flag in
> qemu_create_message_surface() because every surface created with that
> function is some kind if placeholder.
>
> Also when replacing an existing surface we should make the placeholder
> the same size, to avoid pointless ui window resizes.
>
> > -    if (!new_surface) {
> > +    if (is_placeholder(new_surface)) {
>
> We should check whenever this is the primary or a secondary window here
> and only destroy secondary windows.  qemu hiding all windows but
> continuing to run has great potential for user confusion ...
>
> > -    if (!new_surface) {
> > +    if (is_placeholder(new_surface)) {
>
> Same here.

The other surfaces created by qemu_create_message_surface() are not
considered as "placeholder" here, and have contents to be displayed.
Since no emulated devices give NULL to dpy_gfx_replace_surface for the
primary connection, it will never get the "placeholder", and its
window will be always shown.

Regards,
Akihiko Odaki

>
> take care,
>   Gerd
>


^ permalink raw reply	[flat|nested] 14+ messages in thread

* Re: [PATCH v2] ui/console: Pass placeholder surface to displays
  2021-02-23  4:43       ` Akihiko Odaki
@ 2021-02-24 11:06         ` Gerd Hoffmann
  2021-02-25  1:36           ` [PATCH v3 1/3] ui/console: Add placeholder flag to message surface Akihiko Odaki
  0 siblings, 1 reply; 14+ messages in thread
From: Gerd Hoffmann @ 2021-02-24 11:06 UTC (permalink / raw)
  To: Akihiko Odaki; +Cc: qemu Developers, Michael S. Tsirkin

  Hi,

> > > -    if (!new_surface) {
> > > +    if (is_placeholder(new_surface)) {
> >
> > Same here.
> 
> The other surfaces created by qemu_create_message_surface() are not
> considered as "placeholder" here, and have contents to be displayed.

Which ones?  Pretty much any qemu_create_message_surface() use is
basically "we can't show the guest display for $reason".  Which is
the definition of a placeholder surface, isn't it?

> Since no emulated devices give NULL to dpy_gfx_replace_surface for the
> primary connection, it will never get the "placeholder", and its
> window will be always shown.

Well, this could change.  The special handling for scanout #0 in
virtio-gpu can go away when we have this in place.

Also:  The patch os growing, and it probably makes sense to split it
into a series, with one patch adding the placeholder flag and the core
code in console.c, next one patch for each UI, and finally one for
virtio-gpu ...

take care,
  Gerd



^ permalink raw reply	[flat|nested] 14+ messages in thread

* [PATCH v3 1/3] ui/console: Add placeholder flag to message surface
  2021-02-24 11:06         ` Gerd Hoffmann
@ 2021-02-25  1:36           ` Akihiko Odaki
  2021-02-25  1:36             ` [PATCH v3 2/3] ui/console: Pass placeholder surface to displays Akihiko Odaki
                               ` (2 more replies)
  0 siblings, 3 replies; 14+ messages in thread
From: Akihiko Odaki @ 2021-02-25  1:36 UTC (permalink / raw)
  Cc: Michael S . Tsirkin, qemu Developers, Akihiko Odaki, Gerd Hoffmann

The surfaces created with former qemu_create_message_surface
did not display the content from the guest and always contained
simple messages describing the reason.

A display backend may want to hide the window showing such a
surface. This change renames the function to
qemu_create_placeholder_surface, and adds "placeholder" flag; the
display can check the flag to decide to do anything special like
hiding the window.

Signed-off-by: Akihiko Odaki <akihiko.odaki@gmail.com>
---
 hw/display/vhost-user-gpu.c |  4 ++--
 hw/display/virtio-gpu.c     |  6 +++---
 include/ui/console.h        | 10 ++++++++--
 ui/console.c                | 10 +++++-----
 ui/vnc.c                    |  2 +-
 5 files changed, 19 insertions(+), 13 deletions(-)

diff --git a/hw/display/vhost-user-gpu.c b/hw/display/vhost-user-gpu.c
index 4d8cb3525bf..3e911da795e 100644
--- a/hw/display/vhost-user-gpu.c
+++ b/hw/display/vhost-user-gpu.c
@@ -194,8 +194,8 @@ vhost_user_gpu_handle_display(VhostUserGPU *g, VhostUserGpuMsg *msg)
         con = s->con;
 
         if (m->scanout_id == 0 && m->width == 0) {
-            s->ds = qemu_create_message_surface(640, 480,
-                                                "Guest disabled display.");
+            s->ds = qemu_create_placeholder_surface(640, 480,
+                                                    "Guest disabled display.");
             dpy_gfx_replace_surface(con, s->ds);
         } else {
             s->ds = qemu_create_displaysurface(m->width, m->height);
diff --git a/hw/display/virtio-gpu.c b/hw/display/virtio-gpu.c
index 2e4a9822b6a..c1f17bec17e 100644
--- a/hw/display/virtio-gpu.c
+++ b/hw/display/virtio-gpu.c
@@ -338,9 +338,9 @@ static void virtio_gpu_disable_scanout(VirtIOGPU *g, int scanout_id)
 
     if (scanout_id == 0) {
         /* primary head */
-        ds = qemu_create_message_surface(scanout->width  ?: 640,
-                                         scanout->height ?: 480,
-                                         "Guest disabled display.");
+        ds = qemu_create_placeholder_surface(scanout->width  ?: 640,
+                                             scanout->height ?: 480,
+                                             "Guest disabled display.");
     }
     dpy_gfx_replace_surface(scanout->con, ds);
     scanout->resource_id = 0;
diff --git a/include/ui/console.h b/include/ui/console.h
index d30e972d0b5..c960b7066cc 100644
--- a/include/ui/console.h
+++ b/include/ui/console.h
@@ -106,6 +106,7 @@ struct QemuConsoleClass {
 };
 
 #define QEMU_ALLOCATED_FLAG     0x01
+#define QEMU_PLACEHOLDER_FLAG   0x02
 
 typedef struct DisplaySurface {
     pixman_format_code_t format;
@@ -259,8 +260,8 @@ DisplaySurface *qemu_create_displaysurface_from(int width, int height,
                                                 pixman_format_code_t format,
                                                 int linesize, uint8_t *data);
 DisplaySurface *qemu_create_displaysurface_pixman(pixman_image_t *image);
-DisplaySurface *qemu_create_message_surface(int w, int h,
-                                            const char *msg);
+DisplaySurface *qemu_create_placeholder_surface(int w, int h,
+                                                const char *msg);
 PixelFormat qemu_default_pixelformat(int bpp);
 
 DisplaySurface *qemu_create_displaysurface(int width, int height);
@@ -281,6 +282,11 @@ static inline int is_buffer_shared(DisplaySurface *surface)
     return !(surface->flags & QEMU_ALLOCATED_FLAG);
 }
 
+static inline int is_placeholder(DisplaySurface *surface)
+{
+    return surface->flags & QEMU_PLACEHOLDER_FLAG;
+}
+
 void register_displaychangelistener(DisplayChangeListener *dcl);
 void update_displaychangelistener(DisplayChangeListener *dcl,
                                   uint64_t interval);
diff --git a/ui/console.c b/ui/console.c
index c5d11bc7017..0caa39a6ed3 100644
--- a/ui/console.c
+++ b/ui/console.c
@@ -1436,8 +1436,8 @@ DisplaySurface *qemu_create_displaysurface_pixman(pixman_image_t *image)
     return surface;
 }
 
-DisplaySurface *qemu_create_message_surface(int w, int h,
-                                            const char *msg)
+DisplaySurface *qemu_create_placeholder_surface(int w, int h,
+                                                const char *msg)
 {
     DisplaySurface *surface = qemu_create_displaysurface(w, h);
     pixman_color_t bg = color_table_rgb[0][QEMU_COLOR_BLACK];
@@ -1550,7 +1550,7 @@ void register_displaychangelistener(DisplayChangeListener *dcl)
             dcl->ops->dpy_gfx_switch(dcl, con->surface);
         } else {
             if (!dummy) {
-                dummy = qemu_create_message_surface(640, 480, nodev);
+                dummy = qemu_create_placeholder_surface(640, 480, nodev);
             }
             dcl->ops->dpy_gfx_switch(dcl, dummy);
         }
@@ -1998,7 +1998,7 @@ QemuConsole *graphic_console_init(DeviceState *dev, uint32_t head,
                                  &error_abort);
     }
 
-    surface = qemu_create_message_surface(width, height, noinit);
+    surface = qemu_create_placeholder_surface(width, height, noinit);
     dpy_gfx_replace_surface(s, surface);
     return s;
 }
@@ -2027,7 +2027,7 @@ void graphic_console_close(QemuConsole *con)
     if (con->gl) {
         dpy_gl_scanout_disable(con);
     }
-    surface = qemu_create_message_surface(width, height, unplugged);
+    surface = qemu_create_placeholder_surface(width, height, unplugged);
     dpy_gfx_replace_surface(con, surface);
 }
 
diff --git a/ui/vnc.c b/ui/vnc.c
index 16bb3be770b..4d2151272e5 100644
--- a/ui/vnc.c
+++ b/ui/vnc.c
@@ -799,7 +799,7 @@ static void vnc_dpy_switch(DisplayChangeListener *dcl,
 
     if (surface == NULL) {
         if (placeholder == NULL) {
-            placeholder = qemu_create_message_surface(640, 480, placeholder_msg);
+            placeholder = qemu_create_placeholder_surface(640, 480, placeholder_msg);
         }
         surface = placeholder;
     }
-- 
2.24.3 (Apple Git-128)



^ permalink raw reply related	[flat|nested] 14+ messages in thread

* [PATCH v3 2/3] ui/console: Pass placeholder surface to displays
  2021-02-25  1:36           ` [PATCH v3 1/3] ui/console: Add placeholder flag to message surface Akihiko Odaki
@ 2021-02-25  1:36             ` Akihiko Odaki
  2021-02-25  9:06               ` Gerd Hoffmann
  2021-02-25  1:36             ` [PATCH v3 3/3] virtio-gpu: Do not distinguish the primary console Akihiko Odaki
  2021-02-25  9:01             ` [PATCH v3 1/3] ui/console: Add placeholder flag to message surface Gerd Hoffmann
  2 siblings, 1 reply; 14+ messages in thread
From: Akihiko Odaki @ 2021-02-25  1:36 UTC (permalink / raw)
  Cc: Michael S . Tsirkin, qemu Developers, Akihiko Odaki, Gerd Hoffmann

ui/console used to accept NULL as graphic console surface, but its
semantics was inconsistent among displays:
- cocoa and gtk-egl perform NULL dereference.
- egl-headless, spice and spice-egl do nothing.
- gtk releases underlying resources.
- sdl2-2d and sdl2-gl destroys the window.
- vnc shows a message, "Display output is not active."

Fortunately, only virtio-gpu and virtio-gpu-3d assign NULL so
we can study them to figure out the desired behavior. They assign
NULL *except* for the primary display when the device is realized,
reset, or its scanout is disabled. This effectively destroys
windows for the (uninitialized) secondary displays.

To implement the consistent behavior of display device
realization/reset, this change embeds it to the operation
switching the surface. When NULL was given as a new surface when
switching, ui/console will instead passes a placeholder down
to each display listeners.

sdl destroys the window for a secondary console if its surface is a
placeholder. The other displays simply shows the placeholder.

Signed-off-by: Akihiko Odaki <akihiko.odaki@gmail.com>
---
 ui/console.c       | 45 +++++++++++++++++++++++++++++++--------------
 ui/gtk.c           |  4 ----
 ui/sdl2-2d.c       |  7 ++-----
 ui/sdl2-gl.c       |  4 ++--
 ui/spice-display.c |  6 +++---
 ui/vnc.c           | 10 ----------
 6 files changed, 38 insertions(+), 38 deletions(-)

diff --git a/ui/console.c b/ui/console.c
index 0caa39a6ed3..75e54651b5b 100644
--- a/ui/console.c
+++ b/ui/console.c
@@ -1088,6 +1088,29 @@ static void console_putchar(QemuConsole *s, int ch)
     }
 }
 
+static void dpy_gfx_switch(DisplayChangeListener *dcl, DisplaySurface *surface)
+{
+    static DisplaySurface *placeholder;
+    static const char placeholder_msg[] = "Display output is not active.";
+    DisplaySurface *broadcast;
+
+    if (!dcl->ops->dpy_gfx_switch) {
+        return;
+    }
+
+    if (surface) {
+        broadcast = surface;
+    } else {
+        if (!placeholder) {
+            placeholder = qemu_create_placeholder_surface(640, 480, placeholder_msg);
+        }
+
+        broadcast = placeholder;
+    }
+
+    dcl->ops->dpy_gfx_switch(dcl, broadcast);
+}
+
 void console_select(unsigned int index)
 {
     DisplayChangeListener *dcl;
@@ -1104,9 +1127,7 @@ void console_select(unsigned int index)
                 if (dcl->con != NULL) {
                     continue;
                 }
-                if (dcl->ops->dpy_gfx_switch) {
-                    dcl->ops->dpy_gfx_switch(dcl, s->surface);
-                }
+                dpy_gfx_switch(dcl, s->surface);
             }
             if (s->surface) {
                 dpy_gfx_update(s, 0, 0, surface_width(s->surface),
@@ -1545,15 +1566,13 @@ void register_displaychangelistener(DisplayChangeListener *dcl)
     } else {
         con = active_console;
     }
-    if (dcl->ops->dpy_gfx_switch) {
-        if (con) {
-            dcl->ops->dpy_gfx_switch(dcl, con->surface);
-        } else {
-            if (!dummy) {
-                dummy = qemu_create_placeholder_surface(640, 480, nodev);
-            }
-            dcl->ops->dpy_gfx_switch(dcl, dummy);
+    if (con) {
+        dpy_gfx_switch(dcl, con->surface);
+    } else {
+        if (!dummy) {
+            dummy = qemu_create_placeholder_surface(640, 480, nodev);
         }
+        dpy_gfx_switch(dcl, dummy);
     }
     text_console_update_cursor(NULL);
 }
@@ -1685,9 +1704,7 @@ void dpy_gfx_replace_surface(QemuConsole *con,
         if (con != (dcl->con ? dcl->con : active_console)) {
             continue;
         }
-        if (dcl->ops->dpy_gfx_switch) {
-            dcl->ops->dpy_gfx_switch(dcl, surface);
-        }
+        dpy_gfx_switch(dcl, surface);
     }
     qemu_free_displaysurface(old_surface);
 }
diff --git a/ui/gtk.c b/ui/gtk.c
index 79dc2401203..a4a5f981e2a 100644
--- a/ui/gtk.c
+++ b/ui/gtk.c
@@ -567,10 +567,6 @@ static void gd_switch(DisplayChangeListener *dcl,
     }
     vc->gfx.ds = surface;
 
-    if (!surface) {
-        return;
-    }
-
     if (surface->format == PIXMAN_x8r8g8b8) {
         /*
          * PIXMAN_x8r8g8b8 == CAIRO_FORMAT_RGB24
diff --git a/ui/sdl2-2d.c b/ui/sdl2-2d.c
index a2ea85127d5..bfebbdeaea8 100644
--- a/ui/sdl2-2d.c
+++ b/ui/sdl2-2d.c
@@ -32,14 +32,11 @@ void sdl2_2d_update(DisplayChangeListener *dcl,
                     int x, int y, int w, int h)
 {
     struct sdl2_console *scon = container_of(dcl, struct sdl2_console, dcl);
-    DisplaySurface *surf = qemu_console_surface(dcl->con);
+    DisplaySurface *surf = scon->surface;
     SDL_Rect rect;
     size_t surface_data_offset;
     assert(!scon->opengl);
 
-    if (!surf) {
-        return;
-    }
     if (!scon->texture) {
         return;
     }
@@ -75,7 +72,7 @@ void sdl2_2d_switch(DisplayChangeListener *dcl,
         scon->texture = NULL;
     }
 
-    if (!new_surface) {
+    if (is_placeholder(new_surface) && qemu_console_get_index(dcl->con)) {
         sdl2_window_destroy(scon);
         return;
     }
diff --git a/ui/sdl2-gl.c b/ui/sdl2-gl.c
index fd594d74611..a21d2deed91 100644
--- a/ui/sdl2-gl.c
+++ b/ui/sdl2-gl.c
@@ -86,7 +86,7 @@ void sdl2_gl_switch(DisplayChangeListener *dcl,
 
     scon->surface = new_surface;
 
-    if (!new_surface) {
+    if (is_placeholder(new_surface) && qemu_console_get_index(dcl->con)) {
         qemu_gl_fini_shader(scon->gls);
         scon->gls = NULL;
         sdl2_window_destroy(scon);
@@ -112,7 +112,7 @@ void sdl2_gl_refresh(DisplayChangeListener *dcl)
     assert(scon->opengl);
 
     graphic_hw_update(dcl->con);
-    if (scon->updates && scon->surface) {
+    if (scon->updates && scon->real_window) {
         scon->updates = 0;
         sdl2_gl_render_surface(scon);
     }
diff --git a/ui/spice-display.c b/ui/spice-display.c
index 6f32b66a6e7..222c7c20a2a 100644
--- a/ui/spice-display.c
+++ b/ui/spice-display.c
@@ -388,7 +388,7 @@ void qemu_spice_display_switch(SimpleSpiceDisplay *ssd,
     SimpleSpiceUpdate *update;
     bool need_destroy;
 
-    if (surface && ssd->surface &&
+    if (ssd->surface &&
         surface_width(surface) == pixman_image_get_width(ssd->surface) &&
         surface_height(surface) == pixman_image_get_height(ssd->surface) &&
         surface_format(surface) == pixman_image_get_format(ssd->surface)) {
@@ -410,8 +410,8 @@ void qemu_spice_display_switch(SimpleSpiceDisplay *ssd,
 
     /* full mode switch */
     trace_qemu_spice_display_surface(ssd->qxl.id,
-                                     surface ? surface_width(surface)  : 0,
-                                     surface ? surface_height(surface) : 0,
+                                     surface_width(surface),
+                                     surface_height(surface),
                                      false);
 
     memset(&ssd->dirty, 0, sizeof(ssd->dirty));
diff --git a/ui/vnc.c b/ui/vnc.c
index 4d2151272e5..310abc93781 100644
--- a/ui/vnc.c
+++ b/ui/vnc.c
@@ -790,20 +790,10 @@ static bool vnc_check_pageflip(DisplaySurface *s1,
 static void vnc_dpy_switch(DisplayChangeListener *dcl,
                            DisplaySurface *surface)
 {
-    static const char placeholder_msg[] =
-        "Display output is not active.";
-    static DisplaySurface *placeholder;
     VncDisplay *vd = container_of(dcl, VncDisplay, dcl);
     bool pageflip = vnc_check_pageflip(vd->ds, surface);
     VncState *vs;
 
-    if (surface == NULL) {
-        if (placeholder == NULL) {
-            placeholder = qemu_create_placeholder_surface(640, 480, placeholder_msg);
-        }
-        surface = placeholder;
-    }
-
     vnc_abort_display_jobs(vd);
     vd->ds = surface;
 
-- 
2.24.3 (Apple Git-128)



^ permalink raw reply related	[flat|nested] 14+ messages in thread

* [PATCH v3 3/3] virtio-gpu: Do not distinguish the primary console
  2021-02-25  1:36           ` [PATCH v3 1/3] ui/console: Add placeholder flag to message surface Akihiko Odaki
  2021-02-25  1:36             ` [PATCH v3 2/3] ui/console: Pass placeholder surface to displays Akihiko Odaki
@ 2021-02-25  1:36             ` Akihiko Odaki
  2021-02-25  9:10               ` Gerd Hoffmann
  2021-02-25  9:01             ` [PATCH v3 1/3] ui/console: Add placeholder flag to message surface Gerd Hoffmann
  2 siblings, 1 reply; 14+ messages in thread
From: Akihiko Odaki @ 2021-02-25  1:36 UTC (permalink / raw)
  Cc: Michael S . Tsirkin, qemu Developers, Akihiko Odaki, Gerd Hoffmann

In the past, virtio-gpu set NULL as the surface for the secondary
consoles to hide its window. The distinction is now handled in
ui/console and the display backends and virtio-gpu does no longer
have to do that.

Signed-off-by: Akihiko Odaki <akihiko.odaki@gmail.com>
---
 hw/display/vhost-user-gpu.c  |  2 +-
 hw/display/virtio-gpu-3d.c   | 10 +++-------
 hw/display/virtio-gpu-base.c |  3 ---
 hw/display/virtio-gpu.c      | 12 +++++-------
 4 files changed, 9 insertions(+), 18 deletions(-)

diff --git a/hw/display/vhost-user-gpu.c b/hw/display/vhost-user-gpu.c
index 3e911da795e..cb729ed5bc4 100644
--- a/hw/display/vhost-user-gpu.c
+++ b/hw/display/vhost-user-gpu.c
@@ -193,7 +193,7 @@ vhost_user_gpu_handle_display(VhostUserGPU *g, VhostUserGpuMsg *msg)
         s = &g->parent_obj.scanout[m->scanout_id];
         con = s->con;
 
-        if (m->scanout_id == 0 && m->width == 0) {
+        if (m->width == 0) {
             s->ds = qemu_create_placeholder_surface(640, 480,
                                                     "Guest disabled display.");
             dpy_gfx_replace_surface(con, s->ds);
diff --git a/hw/display/virtio-gpu-3d.c b/hw/display/virtio-gpu-3d.c
index 0b0c11474dd..9eb489077b1 100644
--- a/hw/display/virtio-gpu-3d.c
+++ b/hw/display/virtio-gpu-3d.c
@@ -179,10 +179,8 @@ static void virgl_cmd_set_scanout(VirtIOGPU *g,
             info.width, info.height,
             ss.r.x, ss.r.y, ss.r.width, ss.r.height);
     } else {
-        if (ss.scanout_id != 0) {
-            dpy_gfx_replace_surface(
-                g->parent_obj.scanout[ss.scanout_id].con, NULL);
-        }
+        dpy_gfx_replace_surface(
+            g->parent_obj.scanout[ss.scanout_id].con, NULL);
         dpy_gl_scanout_disable(g->parent_obj.scanout[ss.scanout_id].con);
     }
     g->parent_obj.scanout[ss.scanout_id].resource_id = ss.resource_id;
@@ -595,9 +593,7 @@ void virtio_gpu_virgl_reset(VirtIOGPU *g)
 
     virgl_renderer_reset();
     for (i = 0; i < g->parent_obj.conf.max_outputs; i++) {
-        if (i != 0) {
-            dpy_gfx_replace_surface(g->parent_obj.scanout[i].con, NULL);
-        }
+        dpy_gfx_replace_surface(g->parent_obj.scanout[i].con, NULL);
         dpy_gl_scanout_disable(g->parent_obj.scanout[i].con);
     }
 }
diff --git a/hw/display/virtio-gpu-base.c b/hw/display/virtio-gpu-base.c
index 4a57350917c..25f8920fdb6 100644
--- a/hw/display/virtio-gpu-base.c
+++ b/hw/display/virtio-gpu-base.c
@@ -193,9 +193,6 @@ virtio_gpu_base_device_realize(DeviceState *qdev,
     for (i = 0; i < g->conf.max_outputs; i++) {
         g->scanout[i].con =
             graphic_console_init(DEVICE(g), i, &virtio_gpu_ops, g);
-        if (i > 0) {
-            dpy_gfx_replace_surface(g->scanout[i].con, NULL);
-        }
     }
 
     return true;
diff --git a/hw/display/virtio-gpu.c b/hw/display/virtio-gpu.c
index c1f17bec17e..f6c86cb75c6 100644
--- a/hw/display/virtio-gpu.c
+++ b/hw/display/virtio-gpu.c
@@ -325,7 +325,7 @@ static void virtio_gpu_disable_scanout(VirtIOGPU *g, int scanout_id)
 {
     struct virtio_gpu_scanout *scanout = &g->parent_obj.scanout[scanout_id];
     struct virtio_gpu_simple_resource *res;
-    DisplaySurface *ds = NULL;
+    DisplaySurface *ds;
 
     if (scanout->resource_id == 0) {
         return;
@@ -336,12 +336,10 @@ static void virtio_gpu_disable_scanout(VirtIOGPU *g, int scanout_id)
         res->scanout_bitmask &= ~(1 << scanout_id);
     }
 
-    if (scanout_id == 0) {
-        /* primary head */
-        ds = qemu_create_placeholder_surface(scanout->width  ?: 640,
-                                             scanout->height ?: 480,
-                                             "Guest disabled display.");
-    }
+    /* primary head */
+    ds = qemu_create_placeholder_surface(scanout->width  ?: 640,
+                                         scanout->height ?: 480,
+                                         "Guest disabled display.");
     dpy_gfx_replace_surface(scanout->con, ds);
     scanout->resource_id = 0;
     scanout->ds = NULL;
-- 
2.24.3 (Apple Git-128)



^ permalink raw reply related	[flat|nested] 14+ messages in thread

* Re: [PATCH v3 1/3] ui/console: Add placeholder flag to message surface
  2021-02-25  1:36           ` [PATCH v3 1/3] ui/console: Add placeholder flag to message surface Akihiko Odaki
  2021-02-25  1:36             ` [PATCH v3 2/3] ui/console: Pass placeholder surface to displays Akihiko Odaki
  2021-02-25  1:36             ` [PATCH v3 3/3] virtio-gpu: Do not distinguish the primary console Akihiko Odaki
@ 2021-02-25  9:01             ` Gerd Hoffmann
  2 siblings, 0 replies; 14+ messages in thread
From: Gerd Hoffmann @ 2021-02-25  9:01 UTC (permalink / raw)
  To: Akihiko Odaki; +Cc: qemu Developers, Michael S . Tsirkin

> -DisplaySurface *qemu_create_message_surface(int w, int h,
> -                                            const char *msg)
> +DisplaySurface *qemu_create_placeholder_surface(int w, int h,
> +                                                const char *msg)
>  {
>      DisplaySurface *surface = qemu_create_displaysurface(w, h);
>      pixman_color_t bg = color_table_rgb[0][QEMU_COLOR_BLACK];

Not setting QEMU_PLACEHOLDER_FLAG here?

take care,
  Gerd



^ permalink raw reply	[flat|nested] 14+ messages in thread

* Re: [PATCH v3 2/3] ui/console: Pass placeholder surface to displays
  2021-02-25  1:36             ` [PATCH v3 2/3] ui/console: Pass placeholder surface to displays Akihiko Odaki
@ 2021-02-25  9:06               ` Gerd Hoffmann
  0 siblings, 0 replies; 14+ messages in thread
From: Gerd Hoffmann @ 2021-02-25  9:06 UTC (permalink / raw)
  To: Akihiko Odaki; +Cc: qemu Developers, Michael S . Tsirkin

> +static void dpy_gfx_switch(DisplayChangeListener *dcl, DisplaySurface *surface)

int width, int height;

> +    static DisplaySurface *placeholder;
> +    static const char placeholder_msg[] = "Display output is not active.";
> +    DisplaySurface *broadcast;
> +
> +    if (!dcl->ops->dpy_gfx_switch) {
> +        return;
> +    }
> +
> +    if (surface) {
> +        broadcast = surface;
> +    } else {
> +        if (!placeholder) {
> +            placeholder = qemu_create_placeholder_surface(640, 480, placeholder_msg);
> +        }

Just create a new one unconditionally.

> @@ -1685,9 +1704,7 @@ void dpy_gfx_replace_surface(QemuConsole *con,
>          if (con != (dcl->con ? dcl->con : active_console)) {
>              continue;
>          }
> -        if (dcl->ops->dpy_gfx_switch) {
> -            dcl->ops->dpy_gfx_switch(dcl, surface);
> -        }
> +        dpy_gfx_switch(dcl, surface);

You can look at the old_surface here and pass the size to
dpy_gfx_switch(), so the placeholder is created with the same size.

take care,
  Gerd



^ permalink raw reply	[flat|nested] 14+ messages in thread

* Re: [PATCH v3 3/3] virtio-gpu: Do not distinguish the primary console
  2021-02-25  1:36             ` [PATCH v3 3/3] virtio-gpu: Do not distinguish the primary console Akihiko Odaki
@ 2021-02-25  9:10               ` Gerd Hoffmann
  2021-02-25  9:45                 ` Akihiko Odaki
  0 siblings, 1 reply; 14+ messages in thread
From: Gerd Hoffmann @ 2021-02-25  9:10 UTC (permalink / raw)
  To: Akihiko Odaki; +Cc: qemu Developers, Michael S . Tsirkin

> -        if (m->scanout_id == 0 && m->width == 0) {
> +        if (m->width == 0) {
>              s->ds = qemu_create_placeholder_surface(640, 480,
>                                                      "Guest disabled display.");
>              dpy_gfx_replace_surface(con, s->ds);

Just call dpy_gfx_replace_surface(con, NULL) here and let console.c
create the placeholder?

>      for (i = 0; i < g->conf.max_outputs; i++) {
>          g->scanout[i].con =
>              graphic_console_init(DEVICE(g), i, &virtio_gpu_ops, g);
> -        if (i > 0) {
> -            dpy_gfx_replace_surface(g->scanout[i].con, NULL);
> -        }

I think we should call dpy_gfx_replace_surface(..., NULL)
unconditionally here instead of removing the call.

> +    /* primary head */

Comment can go away as we remove the special case for scanout == 0,

> +    ds = qemu_create_placeholder_surface(scanout->width  ?: 640,
> +                                         scanout->height ?: 480,
> +                                         "Guest disabled display.");
>      dpy_gfx_replace_surface(scanout->con, ds);

likewise "dpy_gfx_replace_surface(..., NULL);"

take care,
  Gerd



^ permalink raw reply	[flat|nested] 14+ messages in thread

* Re: [PATCH v3 3/3] virtio-gpu: Do not distinguish the primary console
  2021-02-25  9:10               ` Gerd Hoffmann
@ 2021-02-25  9:45                 ` Akihiko Odaki
  2021-02-25 11:19                   ` Gerd Hoffmann
  0 siblings, 1 reply; 14+ messages in thread
From: Akihiko Odaki @ 2021-02-25  9:45 UTC (permalink / raw)
  To: Gerd Hoffmann; +Cc: qemu Developers, Michael S . Tsirkin

2021年2月25日(木) 18:11 Gerd Hoffmann <kraxel@redhat.com>:
>
> > -        if (m->scanout_id == 0 && m->width == 0) {
> > +        if (m->width == 0) {
> >              s->ds = qemu_create_placeholder_surface(640, 480,
> >                                                      "Guest disabled display.");
> >              dpy_gfx_replace_surface(con, s->ds);
>
> Just call dpy_gfx_replace_surface(con, NULL) here and let console.c
> create the placeholder?

I'll change according to this and the comments in the other replies
and submit a new version.

>
> >      for (i = 0; i < g->conf.max_outputs; i++) {
> >          g->scanout[i].con =
> >              graphic_console_init(DEVICE(g), i, &virtio_gpu_ops, g);
> > -        if (i > 0) {
> > -            dpy_gfx_replace_surface(g->scanout[i].con, NULL);
> > -        }
>
> I think we should call dpy_gfx_replace_surface(..., NULL)
> unconditionally here instead of removing the call.

graphic_console_init will set a placeholder anyway so it does not need
an additional call.

>
> > +    /* primary head */
>
> Comment can go away as we remove the special case for scanout == 0,
>
> > +    ds = qemu_create_placeholder_surface(scanout->width  ?: 640,
> > +                                         scanout->height ?: 480,
> > +                                         "Guest disabled display.");
> >      dpy_gfx_replace_surface(scanout->con, ds);
>
> likewise "dpy_gfx_replace_surface(..., NULL);"
>
> take care,
>   Gerd
>


^ permalink raw reply	[flat|nested] 14+ messages in thread

* Re: [PATCH v3 3/3] virtio-gpu: Do not distinguish the primary console
  2021-02-25  9:45                 ` Akihiko Odaki
@ 2021-02-25 11:19                   ` Gerd Hoffmann
  0 siblings, 0 replies; 14+ messages in thread
From: Gerd Hoffmann @ 2021-02-25 11:19 UTC (permalink / raw)
  To: Akihiko Odaki; +Cc: qemu Developers, Michael S . Tsirkin

  Hi,

> > I think we should call dpy_gfx_replace_surface(..., NULL)
> > unconditionally here instead of removing the call.
> 
> graphic_console_init will set a placeholder anyway so it does not need
> an additional call.

Ah, right, with the initial surface being tagged as placeholder too this
should indeed work fine.

take care,
  Gerd



^ permalink raw reply	[flat|nested] 14+ messages in thread

end of thread, other threads:[~2021-02-25 11:20 UTC | newest]

Thread overview: 14+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2021-02-19 10:17 [PATCH] ui/console: Assert graphic console surface is not NULL Akihiko Odaki
2021-02-19 14:48 ` Gerd Hoffmann
2021-02-20 11:38   ` [PATCH v2] ui/console: Pass placeholder surface to displays Akihiko Odaki
2021-02-22 10:51     ` Gerd Hoffmann
2021-02-23  4:43       ` Akihiko Odaki
2021-02-24 11:06         ` Gerd Hoffmann
2021-02-25  1:36           ` [PATCH v3 1/3] ui/console: Add placeholder flag to message surface Akihiko Odaki
2021-02-25  1:36             ` [PATCH v3 2/3] ui/console: Pass placeholder surface to displays Akihiko Odaki
2021-02-25  9:06               ` Gerd Hoffmann
2021-02-25  1:36             ` [PATCH v3 3/3] virtio-gpu: Do not distinguish the primary console Akihiko Odaki
2021-02-25  9:10               ` Gerd Hoffmann
2021-02-25  9:45                 ` Akihiko Odaki
2021-02-25 11:19                   ` Gerd Hoffmann
2021-02-25  9:01             ` [PATCH v3 1/3] ui/console: Add placeholder flag to message surface Gerd Hoffmann

This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.