GtkGLArea is the proper modern way to have opengl in an gtk+ application. Unfortunately, it may use various backends and interfaces to initialize it, but dmabuf image sharing requires egl atm. This patch keeps using our egl setup on X11, while it uses gtkglarea on known gdk backend based on egl, such as the wayland one. This brings wayland support for local gl to spice-gtk. Signed-off-by: Marc-André Lureau <marcandre.lureau@xxxxxxxxx> --- src/spice-widget-egl.c | 9 ++++++ src/spice-widget-priv.h | 1 + src/spice-widget.c | 79 ++++++++++++++++++++++++++++++++++++++++++++----- 3 files changed, 81 insertions(+), 8 deletions(-) diff --git a/src/spice-widget-egl.c b/src/spice-widget-egl.c index 1748189..1b3cd07 100644 --- a/src/spice-widget-egl.c +++ b/src/spice-widget-egl.c @@ -29,6 +29,7 @@ #include <libdrm/drm_fourcc.h> #include <gdk/gdkx.h> +#include <gdk/gdkwayland.h> #define VERTS_ARRAY_SIZE (sizeof(GLfloat) * 4 * 4) #define TEX_ARRAY_SIZE (sizeof(GLfloat) * 4 * 2) @@ -200,6 +201,14 @@ gboolean spice_egl_init(SpiceDisplay *display, GError **err) EGLNativeDisplayType dpy = 0; GdkDisplay *gdk_dpy = gdk_display_get_default(); +#ifdef GDK_WINDOWING_WAYLAND + if (GDK_IS_WAYLAND_DISPLAY(gdk_dpy)) { + d->egl.ctx = eglGetCurrentContext(); + dpy = (EGLNativeDisplayType)gdk_wayland_display_get_wl_display(gdk_dpy); + d->egl.display = eglGetDisplay(dpy); + return spice_egl_init_shaders(display, err); + } +#endif #ifdef GDK_WINDOWING_X11 if (GDK_IS_X11_DISPLAY(gdk_dpy)) { dpy = (EGLNativeDisplayType)gdk_x11_display_get_xdisplay(gdk_dpy); diff --git a/src/spice-widget-priv.h b/src/spice-widget-priv.h index cf055d3..a60e72c 100644 --- a/src/spice-widget-priv.h +++ b/src/spice-widget-priv.h @@ -137,6 +137,7 @@ struct _SpiceDisplayPrivate { guint tex_pointer_id; guint prog; EGLImageKHR image; + gboolean ack; SpiceGlScanout scanout; } egl; }; diff --git a/src/spice-widget.c b/src/spice-widget.c index 286eeca..9399e86 100644 --- a/src/spice-widget.c +++ b/src/spice-widget.c @@ -539,12 +539,48 @@ static void grab_notify(SpiceDisplay *display, gboolean was_grabbed) release_keys(display); } +static gboolean +gl_area_render(GtkGLArea *area, GdkGLContext *context, gpointer user_data) +{ + SpiceDisplay *display = SPICE_DISPLAY(user_data); + SpiceDisplayPrivate *d = display->priv; + + spice_egl_update_display(display); + glFlush(); + if (d->egl.ack) { + spice_display_gl_draw_done(SPICE_DISPLAY_CHANNEL(d->display)); + d->egl.ack = false; + } + + return TRUE; +} + +static void +gl_area_realize(GtkGLArea *area, gpointer user_data) +{ + SpiceDisplay *display = SPICE_DISPLAY(user_data); + GError *err = NULL; + + gtk_gl_area_make_current(area); + if (gtk_gl_area_get_error(area) != NULL) + return; + + if (!spice_egl_init(display, &err)) { + g_critical("egl init failed: %s", err->message); + g_clear_error(&err); + } +} + static void drawing_area_realize(GtkWidget *area, gpointer user_data) { +#ifdef GDK_WINDOWING_X11 SpiceDisplay *display = SPICE_DISPLAY(user_data); GError *err = NULL; + if (!GDK_IS_X11_DISPLAY(gdk_display_get_default())) + return; + if (!spice_egl_init(display, &err)) { g_critical("egl init failed: %s", err->message); g_clear_error(&err); @@ -554,6 +590,7 @@ drawing_area_realize(GtkWidget *area, gpointer user_data) g_critical("egl realize failed: %s", err->message); g_clear_error(&err); } +#endif } static void spice_display_init(SpiceDisplay *display) @@ -574,6 +611,16 @@ static void spice_display_init(SpiceDisplay *display) gtk_widget_set_double_buffered(area, true); gtk_stack_set_visible_child(GTK_STACK(widget), area); + area = gtk_gl_area_new(); + gtk_gl_area_set_required_version(GTK_GL_AREA(area), 3, 2); + gtk_gl_area_set_auto_render(GTK_GL_AREA(area), false); + g_object_connect(area, + "signal::render", gl_area_render, display, + "signal::realize", gl_area_realize, display, + NULL); + gtk_stack_add_named(GTK_STACK(widget), area, "gl-area"); + gtk_widget_show_all(widget); + g_signal_connect(display, "grab-broken-event", G_CALLBACK(grab_broken), NULL); g_signal_connect(display, "grab-notify", G_CALLBACK(grab_notify), NULL); @@ -1152,11 +1199,20 @@ static void set_egl_enabled(SpiceDisplay *display, bool enabled) if (d->egl.enabled == enabled) return; - /* even though the function is marked as deprecated, it's the - * only way I found to prevent glitches when the window is - * resized. */ - area = gtk_stack_get_child_by_name(GTK_STACK(display), "draw-area"); - gtk_widget_set_double_buffered(GTK_WIDGET(area), !enabled); +#ifdef GDK_WINDOWING_X11 + if (GDK_IS_X11_DISPLAY(gdk_display_get_default())) { + /* even though the function is marked as deprecated, it's the + * only way I found to prevent glitches when the window is + * resized. */ + area = gtk_stack_get_child_by_name(GTK_STACK(display), "draw-area"); + gtk_widget_set_double_buffered(GTK_WIDGET(area), !enabled); + } else +#endif + { + area = gtk_stack_get_child_by_name(GTK_STACK(display), "gl-area"); + gtk_stack_set_visible_child_name(GTK_STACK(display), + enabled ? "gl-area" : "draw-area"); + } if (enabled) { spice_egl_resize_display(display, d->ww, d->wh); @@ -1171,7 +1227,8 @@ static gboolean draw_event(GtkWidget *widget, cairo_t *cr, gpointer data) SpiceDisplayPrivate *d = display->priv; g_return_val_if_fail(d != NULL, false); - if (d->egl.enabled) { + if (d->egl.enabled && + g_str_equal(gtk_stack_get_visible_child_name(GTK_STACK(display)), "draw-area")) { spice_egl_update_display(display); return false; } @@ -2437,12 +2494,18 @@ static void gl_draw(SpiceDisplay *display, guint32 x, guint32 y, guint32 w, guint32 h) { SpiceDisplayPrivate *d = display->priv; + GtkWidget *gl = gtk_stack_get_child_by_name(GTK_STACK(display), "gl-area"); SPICE_DEBUG("%s", __FUNCTION__); set_egl_enabled(display, true); - spice_egl_update_display(display); - spice_display_gl_draw_done(SPICE_DISPLAY_CHANNEL(d->display)); + if (gtk_stack_get_visible_child(GTK_STACK(display)) == gl) { + gtk_gl_area_queue_render(GTK_GL_AREA(gl)); + d->egl.ack = true; + } else { + spice_egl_update_display(display); + spice_display_gl_draw_done(SPICE_DISPLAY_CHANNEL(d->display)); + } } static void channel_new(SpiceSession *s, SpiceChannel *channel, gpointer data) -- 2.5.0 _______________________________________________ Spice-devel mailing list Spice-devel@xxxxxxxxxxxxxxxxxxxxx https://lists.freedesktop.org/mailman/listinfo/spice-devel