diff options
author | Marc-André Lureau <marcandre.lureau@gmail.com> | 2025-04-30 09:46:03 +0000 |
---|---|---|
committer | Marc-André Lureau <marcandre.lureau@gmail.com> | 2025-04-30 09:46:03 +0000 |
commit | a3a7d6d7504ddf79c1aa7cd8595c8c2a61e7b54e (patch) | |
tree | 8a441cb6678522f621c692b45bcffbab8f17939a | |
parent | f610ac6ca5ed23a214be5b9365de91fbc5d0676f (diff) | |
parent | dec888140b8a5429e38c42281d817565e7944e47 (diff) |
channel-display: support gl_scanout2_unix message
See merge request spice/spice-gtk!132
-rw-r--r-- | meson.build | 4 | ||||
-rw-r--r-- | src/channel-display.c | 109 | ||||
-rw-r--r-- | src/channel-display.h | 38 | ||||
-rw-r--r-- | src/map-file-glib | 1 | ||||
-rw-r--r-- | src/spice-channel-priv.h | 2 | ||||
-rw-r--r-- | src/spice-channel.c | 32 | ||||
-rw-r--r-- | src/spice-widget-egl.c | 80 | ||||
-rw-r--r-- | src/spice-widget-priv.h | 4 | ||||
-rw-r--r-- | src/spice-widget.c | 12 | ||||
m--------- | subprojects/spice-common | 0 |
10 files changed, 222 insertions, 60 deletions
diff --git a/meson.build b/meson.build index 44017e5..923f719 100644 --- a/meson.build +++ b/meson.build @@ -4,7 +4,7 @@ project('spice-gtk', 'c', version : run_command('build-aux/git-version-gen', '@0@/.tarball-version'.format(meson.project_source_root()), check : true).stdout().strip(), license : 'LGPLv2.1', - meson_version : '>= 0.56', + meson_version : '>= 0.58', default_options : ['buildtype=debugoptimized', 'warning_level=2']) @@ -35,7 +35,7 @@ spice_glib_deps = [] spice_gtk_deps = [] spice_wayland_deps = [] spice_acl_deps = [] -spice_protocol_version = '0.14.3' +spice_protocol_version = '0.14.5' # # Set up subprojects diff --git a/src/channel-display.c b/src/channel-display.c index e47fc3f..4794a2d 100644 --- a/src/channel-display.c +++ b/src/channel-display.c @@ -21,6 +21,10 @@ #endif #include <glib/gi18n-lib.h> +#ifdef G_OS_UNIX +#include <drm/drm_fourcc.h> +#endif + #include "spice-client.h" #include "spice-common.h" @@ -67,7 +71,8 @@ struct _SpiceDisplayChannelPrivate { GArray *monitors; guint monitors_max; gboolean enable_adaptive_streaming; - SpiceGlScanout scanout; + SpiceGlScanout scanout_ret; + SpiceGlScanout2 scanout; }; G_DEFINE_TYPE_WITH_PRIVATE(SpiceDisplayChannel, spice_display_channel, SPICE_TYPE_CHANNEL) @@ -151,9 +156,11 @@ static void spice_display_channel_dispose(GObject *object) c->mark_false_event_id = 0; } - if (c->scanout.fd >= 0) { - close(c->scanout.fd); - c->scanout.fd = -1; + for (int i = 0; i < c->scanout.num_planes; i++) { + if (c->scanout.fd[i] >= 0) { + close(c->scanout.fd[i]); + c->scanout.fd[i] = -1; + } } if (G_OBJECT_CLASS(spice_display_channel_parent_class)->dispose) @@ -765,13 +772,43 @@ spice_display_get_gl_scanout(SpiceDisplayChannel *channel) * Returns: the current GL scanout, or %NULL if none or not valid * * Since: 0.35 + * Deprecated: 0.43: use spice_display_channel_get_gl_scanout2() instead. **/ const SpiceGlScanout * spice_display_channel_get_gl_scanout(SpiceDisplayChannel *channel) { g_return_val_if_fail(SPICE_IS_DISPLAY_CHANNEL(channel), NULL); - return channel->priv->scanout.fd != -1 ? &channel->priv->scanout : NULL; + SpiceGlScanout2 *scanout = &channel->priv->scanout; + if (scanout->fd[0] < 0 || scanout->num_planes > 1) + return NULL; + + SpiceGlScanout *scanout_ret = &channel->priv->scanout_ret; + scanout_ret->fd = scanout->fd[0]; + scanout_ret->width = scanout->width; + scanout_ret->height = scanout->height; + scanout_ret->stride = scanout->stride[0]; + scanout_ret->format = scanout->format; + scanout_ret->y0top = scanout->y0top; + return scanout_ret; +} + +/** + * spice_display_channel_get_gl_scanout2: + * @channel: a #SpiceDisplayChannel + * + * Retrieves the GL scanout with multi plane info if available + * + * Returns: the current GL scanout, or %NULL if none or not valid + * + * Since: 0.43 + **/ +const SpiceGlScanout2 * +spice_display_channel_get_gl_scanout2(SpiceDisplayChannel *channel) +{ + g_return_val_if_fail(SPICE_IS_DISPLAY_CHANNEL(channel), NULL); + + return channel->priv->scanout.fd[0] != -1 ? &channel->priv->scanout : NULL; } /* ------------------------------------------------------------------ */ @@ -940,6 +977,7 @@ static void spice_display_channel_set_capabilities(SpiceChannel *channel) } if (spice_session_get_gl_scanout_enabled(s)) { spice_channel_set_capability(channel, SPICE_DISPLAY_CAP_GL_SCANOUT); + spice_channel_set_capability(channel, SPICE_DISPLAY_CAP_GL_SCANOUT2); } spice_channel_set_capability(channel, SPICE_DISPLAY_CAP_MULTI_CODEC); #ifdef HAVE_BUILTIN_MJPEG @@ -973,7 +1011,8 @@ static void spice_display_channel_init(SpiceDisplayChannel *channel) c->palette_cache.ops = &palette_cache_ops; c->image_surfaces.ops = &image_surfaces_ops; c->monitors_max = 1; - c->scanout.fd = -1; + for (int i = 0; i < 4; i++) + c->scanout.fd[i] = -1; if (g_getenv("SPICE_DISABLE_ADAPTIVE_STREAMING")) { SPICE_DEBUG("adaptive video disabled"); @@ -2079,19 +2118,66 @@ static void display_handle_gl_scanout_unix(SpiceChannel *channel, SpiceMsgIn *in scanout->drm_dma_buf_fd = -1; if (scanout->drm_fourcc_format != 0) { - scanout->drm_dma_buf_fd = spice_channel_unix_read_fd(channel); + if (!spice_channel_unix_read_fds(channel, &scanout->drm_dma_buf_fd, 1)) { + g_warning("Failed to read dmabuf fds"); + return; + } CHANNEL_DEBUG(channel, "gl scanout fd: %d", scanout->drm_dma_buf_fd); } + for (int i = 0; i < c->scanout.num_planes; i++) { + if (c->scanout.fd[i] >= 0) { + close(c->scanout.fd[i]); + c->scanout.fd[i] = -1; + } + } + c->scanout.y0top = scanout->flags & SPICE_GL_SCANOUT_FLAGS_Y0TOP; - if (c->scanout.fd >= 0) - close(c->scanout.fd); - c->scanout.fd = scanout->drm_dma_buf_fd; + c->scanout.fd[0] = scanout->drm_dma_buf_fd; c->scanout.width = scanout->width; c->scanout.height = scanout->height; - c->scanout.stride = scanout->stride; + c->scanout.stride[0] = scanout->stride; c->scanout.format = scanout->drm_fourcc_format; + c->scanout.offset[0] = 0; + c->scanout.modifier = DRM_FORMAT_MOD_INVALID; + c->scanout.num_planes = 1; + + g_coroutine_object_notify(G_OBJECT(channel), "gl-scanout"); +} + +static void display_handle_gl_scanout2_unix(SpiceChannel *channel, SpiceMsgIn *in) +{ + SpiceDisplayChannel *display = SPICE_DISPLAY_CHANNEL(channel); + SpiceDisplayChannelPrivate *c = display->priv; + SpiceMsgDisplayGlScanout2Unix *scanout = spice_msg_in_parsed(in); + + for (int i = 0; i < c->scanout.num_planes; i++) { + if (c->scanout.fd[i] >= 0) { + close(c->scanout.fd[i]); + c->scanout.fd[i] = -1; + } + } + + if (scanout->num_planes) { + if (!spice_channel_unix_read_fds(channel, c->scanout.fd, scanout->num_planes)) { + g_warning("Failed to read dmabuf fds"); + return; + } + } + + c->scanout.y0top = scanout->flags & SPICE_GL_SCANOUT_FLAGS_Y0TOP; + c->scanout.width = scanout->width; + c->scanout.height = scanout->height; + c->scanout.format = scanout->fourcc; + c->scanout.modifier = scanout->modifier; + c->scanout.num_planes = scanout->num_planes; + + for (int i = 0; i < scanout->num_planes; i++) { + c->scanout.offset[i] = scanout->planes[i].offset; + c->scanout.stride[i] = scanout->planes[i].stride; + } + g_coroutine_object_notify(G_OBJECT(channel), "gl-scanout"); } #endif @@ -2190,6 +2276,7 @@ static void channel_set_handlers(SpiceChannelClass *klass) [ SPICE_MSG_DISPLAY_MONITORS_CONFIG ] = display_handle_monitors_config, #ifdef G_OS_UNIX [ SPICE_MSG_DISPLAY_GL_SCANOUT_UNIX ] = display_handle_gl_scanout_unix, + [ SPICE_MSG_DISPLAY_GL_SCANOUT2_UNIX ] = display_handle_gl_scanout2_unix, #endif [ SPICE_MSG_DISPLAY_GL_DRAW ] = display_handle_gl_draw, }; diff --git a/src/channel-display.h b/src/channel-display.h index 7121c6e..fa3c1de 100644 --- a/src/channel-display.h +++ b/src/channel-display.h @@ -60,6 +60,33 @@ struct _SpiceGlScanout { }; /** + * SpiceGlScanout2: + * @fd: drm DMABUF file for each plane that can be imported with eglCreateImageKHR + * @width: width of the scanout + * @height: height of the scanout + * @offset: offset of each plane + * @stride: stride of each plane + * @num_plane: number of planes + * @format: the drm fourcc format + * @y0top: orientation of the scanout + * @modifier: the drm modifier + * + * Holds the information necessary for using the GL display scanout. + **/ +typedef struct _SpiceGlScanout2 SpiceGlScanout2; +struct _SpiceGlScanout2 { + gint fd[4]; + guint32 width; + guint32 height; + guint32 offset[4]; + guint32 stride[4]; + guint32 num_planes; + guint32 format; + gboolean y0top; + guint64 modifier; +}; + +/** * SpiceDisplayMonitorConfig: * @id: monitor id * @surface_id: monitor surface id @@ -151,8 +178,6 @@ gboolean spice_display_channel_get_primary(SpiceChannel *channel, guint32 SPICE_GTK_AVAILABLE_IN_0_35 void spice_display_channel_change_preferred_compression(SpiceChannel *channel, gint compression); -SPICE_GTK_DEPRECATED_IN_0_38_FOR(spice_display_channel_change_preferred_video_codec_types) -void spice_display_channel_change_preferred_video_codec_type(SpiceChannel *channel, gint codec_type); SPICE_GTK_AVAILABLE_IN_0_38 gboolean spice_display_channel_change_preferred_video_codec_types(SpiceChannel *channel, const gint *codecs, gsize ncodecs, GError **err); @@ -163,11 +188,16 @@ SPICE_GTK_AVAILABLE_IN_0_31 void spice_gl_scanout_free (SpiceGlScanout *scanout); SPICE_GTK_AVAILABLE_IN_0_35 -const SpiceGlScanout* spice_display_channel_get_gl_scanout(SpiceDisplayChannel *channel); -SPICE_GTK_AVAILABLE_IN_0_35 void spice_display_channel_gl_draw_done(SpiceDisplayChannel *channel); +SPICE_GTK_AVAILABLE_IN_0_43 +const SpiceGlScanout2 *spice_display_channel_get_gl_scanout2(SpiceDisplayChannel *channel); #ifndef SPICE_DISABLE_DEPRECATED +SPICE_GTK_DEPRECATED_IN_0_38_FOR(spice_display_channel_change_preferred_video_codec_types) +void spice_display_channel_change_preferred_video_codec_type(SpiceChannel *channel, gint codec_type); +SPICE_GTK_AVAILABLE_IN_0_35 +SPICE_GTK_DEPRECATED_IN_0_43_FOR(spice_display_channel_get_gl_scanout2) +const SpiceGlScanout* spice_display_channel_get_gl_scanout(SpiceDisplayChannel *channel); SPICE_GTK_DEPRECATED_IN_0_35_FOR(spice_display_channel_change_preferred_compression) void spice_display_change_preferred_compression(SpiceChannel *channel, gint compression); SPICE_GTK_DEPRECATED_IN_0_35_FOR(spice_display_channel_change_preferred_video_codec_type) diff --git a/src/map-file-glib b/src/map-file-glib index e06ff2c..24b3859 100644 --- a/src/map-file-glib +++ b/src/map-file-glib @@ -27,6 +27,7 @@ spice_display_channel_change_preferred_compression; spice_display_channel_change_preferred_video_codec_type; spice_display_channel_change_preferred_video_codec_types; spice_display_channel_get_gl_scanout; +spice_display_channel_get_gl_scanout2; spice_display_channel_get_primary; spice_display_channel_get_type; spice_display_channel_gl_draw_done; diff --git a/src/spice-channel-priv.h b/src/spice-channel-priv.h index d17099d..0939806 100644 --- a/src/spice-channel-priv.h +++ b/src/spice-channel-priv.h @@ -204,7 +204,7 @@ void spice_vmc_write_async(SpiceChannel *self, gssize spice_vmc_write_finish(SpiceChannel *self, GAsyncResult *result, GError **error); #ifdef G_OS_UNIX -gint spice_channel_unix_read_fd(SpiceChannel *channel); +gboolean spice_channel_unix_read_fds(SpiceChannel *channel, int *fds, int max_num_fds); #endif G_END_DECLS diff --git a/src/spice-channel.c b/src/spice-channel.c index 168260d..242886a 100644 --- a/src/spice-channel.c +++ b/src/spice-channel.c @@ -43,6 +43,7 @@ #include <arpa/inet.h> #endif #include <ctype.h> +#include <assert.h> #include "gio-coroutine.h" @@ -928,58 +929,59 @@ static void spice_channel_write_msg(SpiceChannel *channel, SpiceMsgOut *out) } #ifdef G_OS_UNIX -static ssize_t read_fd(int fd, int *msgfd) +static ssize_t read_fds(int fd, int *msgfds, int max_num_fds) { struct msghdr msg = { NULL, }; struct iovec iov[1]; union { struct cmsghdr cmsg; - char control[CMSG_SPACE(sizeof(int))]; + char control[CMSG_SPACE(sizeof(int) * 4)]; } msg_control; struct cmsghdr *cmsg; ssize_t ret; char c; + assert(max_num_fds <= 4); + iov[0].iov_base = &c; iov[0].iov_len = 1; msg.msg_iov = iov; msg.msg_iovlen = 1; msg.msg_control = &msg_control; - msg.msg_controllen = sizeof(msg_control); + msg.msg_controllen = CMSG_SPACE(sizeof(int) * max_num_fds); ret = recvmsg(fd, &msg, 0); if (ret > 0) { for (cmsg = CMSG_FIRSTHDR(&msg); cmsg != NULL; cmsg = CMSG_NXTHDR(&msg, cmsg)) { - if (cmsg->cmsg_len != CMSG_LEN(sizeof(int)) || - cmsg->cmsg_level != SOL_SOCKET || + size_t cmsg_data_len; + + if (cmsg->cmsg_level != SOL_SOCKET || cmsg->cmsg_type != SCM_RIGHTS) { continue; } - memcpy(msgfd, CMSG_DATA(cmsg), sizeof(int)); - if (*msgfd < 0) { - continue; - } + cmsg_data_len = cmsg->cmsg_len - CMSG_LEN(0); + memcpy(msgfds, CMSG_DATA(cmsg), cmsg_data_len); + break; } } return ret; } G_GNUC_INTERNAL -gint spice_channel_unix_read_fd(SpiceChannel *channel) +gboolean spice_channel_unix_read_fds(SpiceChannel *channel, int *fds, int max_num_fds) { SpiceChannelPrivate *c = channel->priv; - gint fd = -1; - g_return_val_if_fail(g_socket_get_family(c->sock) == G_SOCKET_FAMILY_UNIX, -1); + g_return_val_if_fail(g_socket_get_family(c->sock) == G_SOCKET_FAMILY_UNIX, FALSE); while (1) { /* g_socket_receive_message() is not convenient here because it * reads all control messages, and overly complicated to deal with */ - if (read_fd(g_socket_get_fd(c->sock), &fd) > 0) { + if (read_fds(g_socket_get_fd(c->sock), fds, max_num_fds) > 0) { break; } @@ -987,11 +989,11 @@ gint spice_channel_unix_read_fd(SpiceChannel *channel) g_coroutine_socket_wait(&c->coroutine, c->sock, G_IO_IN); } else { g_warning("failed to get fd: %s", g_strerror(errno)); - return -1; + return FALSE; } } - return fd; + return TRUE; } #endif diff --git a/src/spice-widget-egl.c b/src/spice-widget-egl.c index b069ec1..8a2bd64 100644 --- a/src/spice-widget-egl.c +++ b/src/spice-widget-egl.c @@ -284,7 +284,7 @@ end: d->egl.context_ready = TRUE; - if (spice_display_channel_get_gl_scanout(d->display) != NULL) { + if (spice_display_channel_get_gl_scanout2(d->display) != NULL) { DISPLAY_DEBUG(display, "scanout present during egl init, updating widget"); spice_display_widget_gl_scanout(display); spice_display_widget_update_monitor_area(display); @@ -626,14 +626,48 @@ void spice_egl_update_display(SpiceDisplay *display) G_GNUC_INTERNAL gboolean spice_egl_update_scanout(SpiceDisplay *display, - const SpiceGlScanout *scanout, + const SpiceGlScanout2 *scanout, GError **err) { SpiceDisplayPrivate *d = display->priv; - EGLint attrs[13]; + EGLint attrs[64]; guint32 format; + int i = 0, j; + + EGLint fd_attrs[] = { + EGL_DMA_BUF_PLANE0_FD_EXT, + EGL_DMA_BUF_PLANE1_FD_EXT, + EGL_DMA_BUF_PLANE2_FD_EXT, + EGL_DMA_BUF_PLANE3_FD_EXT, + }; + EGLint offset_attrs[] = { + EGL_DMA_BUF_PLANE0_OFFSET_EXT, + EGL_DMA_BUF_PLANE1_OFFSET_EXT, + EGL_DMA_BUF_PLANE2_OFFSET_EXT, + EGL_DMA_BUF_PLANE3_OFFSET_EXT, + }; + EGLint stride_attrs[] = { + EGL_DMA_BUF_PLANE0_PITCH_EXT, + EGL_DMA_BUF_PLANE1_PITCH_EXT, + EGL_DMA_BUF_PLANE2_PITCH_EXT, + EGL_DMA_BUF_PLANE3_PITCH_EXT, + }; + EGLint modifier_lo_attrs[] = { + EGL_DMA_BUF_PLANE0_MODIFIER_LO_EXT, + EGL_DMA_BUF_PLANE1_MODIFIER_LO_EXT, + EGL_DMA_BUF_PLANE2_MODIFIER_LO_EXT, + EGL_DMA_BUF_PLANE3_MODIFIER_LO_EXT, + }; + EGLint modifier_hi_attrs[] = { + EGL_DMA_BUF_PLANE0_MODIFIER_HI_EXT, + EGL_DMA_BUF_PLANE1_MODIFIER_HI_EXT, + EGL_DMA_BUF_PLANE2_MODIFIER_HI_EXT, + EGL_DMA_BUF_PLANE3_MODIFIER_HI_EXT, + }; g_return_val_if_fail(scanout != NULL, FALSE); + g_return_val_if_fail(scanout->num_planes <= 4, FALSE); + format = scanout->format; if (d->egl.image != NULL) { @@ -641,24 +675,32 @@ gboolean spice_egl_update_scanout(SpiceDisplay *display, d->egl.image = NULL; } - if (scanout->fd == -1) + if (scanout->fd[0] == -1) return TRUE; - attrs[0] = EGL_DMA_BUF_PLANE0_FD_EXT; - attrs[1] = scanout->fd; - attrs[2] = EGL_DMA_BUF_PLANE0_PITCH_EXT; - attrs[3] = scanout->stride; - attrs[4] = EGL_DMA_BUF_PLANE0_OFFSET_EXT; - attrs[5] = 0; - attrs[6] = EGL_WIDTH; - attrs[7] = scanout->width; - attrs[8] = EGL_HEIGHT; - attrs[9] = scanout->height; - attrs[10] = EGL_LINUX_DRM_FOURCC_EXT; - attrs[11] = format; - attrs[12] = EGL_NONE; - DISPLAY_DEBUG(display, "fd:%d stride:%u y0:%d %ux%u format:0x%x (%c%c%c%c)", - scanout->fd, scanout->stride, scanout->y0top, + attrs[i++] = EGL_WIDTH; + attrs[i++] = scanout->width; + attrs[i++] = EGL_HEIGHT; + attrs[i++] = scanout->height; + attrs[i++] = EGL_LINUX_DRM_FOURCC_EXT; + attrs[i++] = format; + + for (j = 0; j < scanout->num_planes; j++) { + attrs[i++] = fd_attrs[j]; + attrs[i++] = scanout->fd[j] >= 0 ? scanout->fd[j] : scanout->fd[0]; + attrs[i++] = stride_attrs[j]; + attrs[i++] = scanout->stride[j]; + attrs[i++] = offset_attrs[j]; + attrs[i++] = scanout->offset[j]; + attrs[i++] = modifier_lo_attrs[j]; + attrs[i++] = (scanout->modifier >> 0) & 0xffffffff; + attrs[i++] = modifier_hi_attrs[j]; + attrs[i++] = (scanout->modifier >> 32) & 0xffffffff; + } + attrs[i++] = EGL_NONE; + + DISPLAY_DEBUG(display, "fd[0]:%d stride[0]:%u y0:%d %ux%u format:0x%x (%c%c%c%c)", + scanout->fd[0], scanout->stride[0], scanout->y0top, scanout->width, scanout->height, format, (int)format & 0xff, (int)(format >> 8) & 0xff, (int)(format >> 16) & 0xff, (int)format >> 24); diff --git a/src/spice-widget-priv.h b/src/spice-widget-priv.h index b15714e..33a5249 100644 --- a/src/spice-widget-priv.h +++ b/src/spice-widget-priv.h @@ -148,7 +148,7 @@ struct _SpiceDisplayPrivate { guint prog; EGLImageKHR image; gboolean call_draw_done; - SpiceGlScanout scanout; + SpiceGlScanout2 scanout; } egl; #endif // HAVE_EGL double scroll_delta_y; @@ -167,7 +167,7 @@ void spice_egl_unrealize_display (SpiceDisplay *display); void spice_egl_update_display (SpiceDisplay *display); void spice_egl_resize_display (SpiceDisplay *display, int w, int h); gboolean spice_egl_update_scanout (SpiceDisplay *display, - const SpiceGlScanout *scanout, + const SpiceGlScanout2 *scanout, GError **err); void spice_egl_cursor_set (SpiceDisplay *display); diff --git a/src/spice-widget.c b/src/spice-widget.c index 8a269bc..2c1aca6 100644 --- a/src/spice-widget.c +++ b/src/spice-widget.c @@ -649,7 +649,7 @@ drawing_area_realize(GtkWidget *area, gpointer user_data) SpiceDisplay *display = SPICE_DISPLAY(user_data); if (GDK_IS_X11_DISPLAY(gdk_display_get_default()) && - spice_display_channel_get_gl_scanout(display->priv->display) != NULL) { + spice_display_channel_get_gl_scanout2(display->priv->display) != NULL) { spice_display_widget_gl_scanout(display); } #endif @@ -2710,8 +2710,8 @@ static void update_area(SpiceDisplay *display, #ifdef HAVE_EGL if (egl_enabled(d)) { - const SpiceGlScanout *so = - spice_display_channel_get_gl_scanout(d->display); + const SpiceGlScanout2 *so = + spice_display_channel_get_gl_scanout2(d->display); g_return_if_fail(so != NULL); primary = (GdkRectangle) { .width = so->width, @@ -3326,9 +3326,9 @@ void spice_display_widget_gl_scanout(SpiceDisplay *display) set_egl_enabled(display, true); if (d->egl.context_ready) { - const SpiceGlScanout *scanout; + const SpiceGlScanout2 *scanout; - scanout = spice_display_channel_get_gl_scanout(d->display); + scanout = spice_display_channel_get_gl_scanout2(d->display); /* should only be called when the display has a scanout */ g_return_if_fail(scanout != NULL); @@ -3420,7 +3420,7 @@ static void channel_new(SpiceSession *s, SpiceChannel *channel, SpiceDisplay *di G_CALLBACK(spice_display_widget_gl_scanout), display, G_CONNECT_SWAPPED); - if (spice_display_channel_get_gl_scanout(d->display)) { + if (spice_display_channel_get_gl_scanout2(d->display)) { spice_display_widget_gl_scanout(display); } #ifdef HAVE_EGL diff --git a/subprojects/spice-common b/subprojects/spice-common -Subproject bb8f66983af6b7f38dc80efa6b6ca8f34c2ab85 +Subproject 492c22f4447eec9d430a7c737bdd20cbe93263c |