[Spice-devel] [PATCH v2 10/10] gtk: add GtkGLArea
Marc-André Lureau
marcandre.lureau at gmail.com
Mon Mar 14 10:31:52 UTC 2016
On Mon, Mar 14, 2016 at 9:22 AM, Fabiano Fidêncio <fidencio at redhat.com> wrote:
> On Fri, Mar 11, 2016 at 9:50 PM, Marc-André Lureau
> <marcandre.lureau at gmail.com> 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 at gmail.com>
>> ---
>> 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 at lists.freedesktop.org
>> https://lists.freedesktop.org/mailman/listinfo/spice-devel
--
Marc-André Lureau
More information about the Spice-devel
mailing list