All of lore.kernel.org
 help / color / mirror / Atom feed
* [PATCH v4 1/3] ui/console: Add placeholder flag to message surface
@ 2021-02-25 10:13 Akihiko Odaki
  2021-02-25 10:13 ` [PATCH v4 2/3] ui/console: Pass placeholder surface to displays Akihiko Odaki
  2021-02-25 10:13 ` [PATCH v4 3/3] virtio-gpu: Do not distinguish the primary console Akihiko Odaki
  0 siblings, 2 replies; 3+ messages in thread
From: Akihiko Odaki @ 2021-02-25 10:13 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                | 11 ++++++-----
 ui/vnc.c                    |  2 +-
 5 files changed, 20 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..32823faf414 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];
@@ -1454,6 +1454,7 @@ DisplaySurface *qemu_create_message_surface(int w, int h,
                                  x+i, y, FONT_WIDTH, FONT_HEIGHT);
         qemu_pixman_image_unref(glyph);
     }
+    surface->flags |= QEMU_PLACEHOLDER_FLAG;
     return surface;
 }
 
@@ -1550,7 +1551,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 +1999,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 +2028,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] 3+ messages in thread

* [PATCH v4 2/3] ui/console: Pass placeholder surface to displays
  2021-02-25 10:13 [PATCH v4 1/3] ui/console: Add placeholder flag to message surface Akihiko Odaki
@ 2021-02-25 10:13 ` Akihiko Odaki
  2021-02-25 10:13 ` [PATCH v4 3/3] virtio-gpu: Do not distinguish the primary console Akihiko Odaki
  1 sibling, 0 replies; 3+ messages in thread
From: Akihiko Odaki @ 2021-02-25 10:13 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       | 17 ++++++++++++++++-
 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, 23 insertions(+), 25 deletions(-)

diff --git a/ui/console.c b/ui/console.c
index 32823faf414..171a7bf14b9 100644
--- a/ui/console.c
+++ b/ui/console.c
@@ -1675,11 +1675,26 @@ void dpy_gfx_update_full(QemuConsole *con)
 void dpy_gfx_replace_surface(QemuConsole *con,
                              DisplaySurface *surface)
 {
+    static const char placeholder_msg[] = "Display output is not active.";
     DisplayState *s = con->ds;
     DisplaySurface *old_surface = con->surface;
     DisplayChangeListener *dcl;
+    int width;
+    int height;
+
+    if (!surface) {
+        if (old_surface) {
+            width = surface_width(old_surface);
+            height = surface_height(old_surface);
+        } else {
+            width = 640;
+            height = 480;
+        }
+
+        surface = qemu_create_placeholder_surface(width, height, placeholder_msg);
+    }
 
-    assert(old_surface != surface || surface == NULL);
+    assert(old_surface != surface);
 
     con->surface = surface;
     QLIST_FOREACH(dcl, &s->listeners, next) {
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] 3+ messages in thread

* [PATCH v4 3/3] virtio-gpu: Do not distinguish the primary console
  2021-02-25 10:13 [PATCH v4 1/3] ui/console: Add placeholder flag to message surface Akihiko Odaki
  2021-02-25 10:13 ` [PATCH v4 2/3] ui/console: Pass placeholder surface to displays Akihiko Odaki
@ 2021-02-25 10:13 ` Akihiko Odaki
  1 sibling, 0 replies; 3+ messages in thread
From: Akihiko Odaki @ 2021-02-25 10:13 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  |  6 ++----
 hw/display/virtio-gpu-3d.c   | 10 +++-------
 hw/display/virtio-gpu-base.c |  3 ---
 hw/display/virtio-gpu.c      |  9 +--------
 4 files changed, 6 insertions(+), 22 deletions(-)

diff --git a/hw/display/vhost-user-gpu.c b/hw/display/vhost-user-gpu.c
index 3e911da795e..a01f9315e19 100644
--- a/hw/display/vhost-user-gpu.c
+++ b/hw/display/vhost-user-gpu.c
@@ -193,10 +193,8 @@ 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) {
-            s->ds = qemu_create_placeholder_surface(640, 480,
-                                                    "Guest disabled display.");
-            dpy_gfx_replace_surface(con, s->ds);
+        if (m->width == 0) {
+            dpy_gfx_replace_surface(con, NULL);
         } else {
             s->ds = qemu_create_displaysurface(m->width, m->height);
             /* replace surface on next update */
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..c9f5e36fd07 100644
--- a/hw/display/virtio-gpu.c
+++ b/hw/display/virtio-gpu.c
@@ -325,7 +325,6 @@ 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;
 
     if (scanout->resource_id == 0) {
         return;
@@ -336,13 +335,7 @@ 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.");
-    }
-    dpy_gfx_replace_surface(scanout->con, ds);
+    dpy_gfx_replace_surface(scanout->con, NULL);
     scanout->resource_id = 0;
     scanout->ds = NULL;
     scanout->width = 0;
-- 
2.24.3 (Apple Git-128)



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

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

Thread overview: 3+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2021-02-25 10:13 [PATCH v4 1/3] ui/console: Add placeholder flag to message surface Akihiko Odaki
2021-02-25 10:13 ` [PATCH v4 2/3] ui/console: Pass placeholder surface to displays Akihiko Odaki
2021-02-25 10:13 ` [PATCH v4 3/3] virtio-gpu: Do not distinguish the primary console Akihiko Odaki

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.