On Mon, Mar 14, 2016 at 9:22 AM, Fabiano Fidêncio <fidencio@xxxxxxxxxx> wrote: > On Fri, Mar 11, 2016 at 9:50 PM, Marc-André Lureau > <marcandre.lureau@xxxxxxxxx> wrote: >> 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; > > Not sure if ack is the best name here. call_draw_done? > >> 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; > > s/false/FALSE ? > ok >> + } >> + >> + 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; > > s/true/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 -- Marc-André Lureau _______________________________________________ Spice-devel mailing list Spice-devel@xxxxxxxxxxxxxxxxxxxxx https://lists.freedesktop.org/mailman/listinfo/spice-devel