[Spice-devel] [PATCH v2 10/10] gtk: add GtkGLArea

Fabiano Fidêncio fidencio at redhat.com
Mon Mar 14 12:34:55 UTC 2016


On Mon, Mar 14, 2016 at 11:31 AM, Marc-André Lureau
<marcandre.lureau at gmail.com> wrote:
> 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?

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;
>>
>> 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