[Spice-commits] 3 commits - gtk/channel-display.c gtk/channel-display-mjpeg.c gtk/spice-widget.c

Marc-André Lureau elmarco at kemper.freedesktop.org
Mon Apr 2 05:40:11 PDT 2012


 gtk/channel-display-mjpeg.c |   25 +++++++++++++++++++------
 gtk/channel-display.c       |   27 +++++++--------------------
 gtk/spice-widget.c          |   20 +++++++++++++++++++-
 3 files changed, 45 insertions(+), 27 deletions(-)

New commits:
commit b9f70814586ffff68e2805443152c30418b10741
Author: Marc-André Lureau <marcandre.lureau at redhat.com>
Date:   Fri Mar 30 18:58:03 2012 +0200

    Handle grab-broken event
    
    This fixes the pointer being "trapped" in the center of the screen in
    server-side mouse mode. It also correctly inform the client that the
    pointer/keyboard is no longer grabbed so it can adjust its UI state
    accordingly (remote the "press ctrl+alt to ungrab" messages etc).
    
    I can reproduce only with RHEVM22 host, and a RHEL6 guest, when
    switching consoles.

diff --git a/gtk/spice-widget.c b/gtk/spice-widget.c
index c13f758..0defb60 100644
--- a/gtk/spice-widget.c
+++ b/gtk/spice-widget.c
@@ -346,6 +346,23 @@ static GdkCursor* get_blank_cursor(void)
     return gdk_cursor_new(GDK_BLANK_CURSOR);
 }
 
+static gboolean grab_broken(SpiceDisplay *self, GdkEventGrabBroken *event,
+                            gpointer user_data G_GNUC_UNUSED)
+{
+    SpiceDisplayPrivate *d = self->priv;
+
+    SPICE_DEBUG("%s (%d)", __FUNCTION__, event->implicit);
+    if (event->keyboard) {
+        d->keyboard_grab_active = false;
+        g_signal_emit(self, signals[SPICE_DISPLAY_KEYBOARD_GRAB], 0, false);
+    } else {
+        d->mouse_grab_active = false;
+        g_signal_emit(self, signals[SPICE_DISPLAY_MOUSE_GRAB], 0, false);
+    }
+
+    return false;
+}
+
 static void spice_display_init(SpiceDisplay *display)
 {
     GtkWidget *widget = GTK_WIDGET(display);
@@ -353,6 +370,7 @@ static void spice_display_init(SpiceDisplay *display)
 
     d = display->priv = SPICE_DISPLAY_GET_PRIVATE(display);
 
+    g_signal_connect(display, "grab-broken-event", G_CALLBACK(grab_broken), NULL);
     gtk_widget_add_events(widget,
                           GDK_STRUCTURE_MASK |
                           GDK_POINTER_MOTION_MASK |
@@ -365,7 +383,6 @@ static void spice_display_init(SpiceDisplay *display)
     gtk_widget_set_double_buffered(widget, false);
     gtk_widget_set_can_focus(widget, true);
     gtk_widget_set_has_window(widget, true);
-
     d->keycode_map = vnc_display_keymap_gdk2xtkbd_table(&d->keycode_maplen);
     d->grabseq = spice_grab_sequence_new_from_string("Control_L+Alt_L");
     d->activeseq = g_new0(gboolean, d->grabseq->nkeysyms);
commit d16df7dab09c2966227c1f5b915921d4b62bfda9
Author: Marc-André Lureau <marcandre.lureau at redhat.com>
Date:   Sat Mar 31 00:49:54 2012 +0200

    widget: fix invalid memory ref after channel is distroyed
    
    When the display channel is destroyed, we disconnect all signals
    handlers, but we don't remove the reference on the primary surface
    data, and that can lead to crashes in a later expose event, reusing
    the canvas surface (ex, if scaling is disabled). Call
    primary_destroy() when disconnecting the channel from the widget.
    
    We now keep the primary surface during channel reset (right after
    disconnect for example), so the primary surface can be eventually
    recycled, and the widget still holds a valid reference until the
    signal is received. The primary surface is ultimately destroyed during
    finalize, or if the new primary surface size doesn't match.
    
    Program received signal SIGSEGV, Segmentation fault.
    __memmove_ssse3_back () at ../sysdeps/x86_64/multiarch/memcpy-ssse3-back.S:2130
    2130		lddqu	-68(%rsi), %xmm0
    Missing separate debuginfos, use: debuginfo-install gtk2-engines-2.20.2-2.fc15.x86_64 libusb1-1.0.9-0.3.rc1.fc16.x86_64 p11-kit-0.6-1.fc16.x86_64
    (gdb) bt
        at ../sysdeps/x86_64/multiarch/memcpy-ssse3-back.S:2130
        srclen=<optimized out>, srcinc=4096, destinc=68, height=<optimized out>,
        half_order=0) at /usr/include/bits/string3.h:52
        dest_bits_per_pixel=32, req_yoffset=<optimized out>, req_xoffset=0,
        image=0x7fffffffb9a0, req=<optimized out>, dpy=0x64a630) at PutImage.c:821
        req_height=<optimized out>, req_width=<optimized out>, y=<optimized out>,
        x=0, req_yoffset=<optimized out>, req_xoffset=0, image=0x7fffffffb9a0,
        gc=0xa817e0, d=33554452, dpy=0x64a630) at PutImage.c:870
        req_xoffset=0, req_yoffset=<optimized out>, x=0, y=26, req_width=17,
        req_height=20, dest_bits_per_pixel=32, dest_scanline_pad=32)
        at PutImage.c:908
        image=0x7fffffffb9a0, req_xoffset=0, req_yoffset=0, x=0, y=26,
        req_width=17, req_height=20) at PutImage.c:1027
        image=<optimized out>, src_x=0, src_y=0, width=17, height=20, dst_x=0,
        dst_y=26) at cairo-xlib-surface.c:1357
    ---Type <return> to continue, or q <return> to quit---c
        height=20, width=17, dst_y=26, dst_x=0, src_y=<optimized out>,
        src_x=<optimized out>, pattern=0x7fffffffc6b0, op=CAIRO_OPERATOR_OVER,
        surface=0xb9a650) at cairo-xlib-surface.c:2403
        dst_y=26, dst_x=0, mask_y=0, mask_x=0, src_y=26, src_x=0,
        abstract_dst=0xb9a650, mask_pattern=0x0, src_pattern=0x7fffffffc6b0,
        op=CAIRO_OPERATOR_OVER) at cairo-xlib-surface.c:2452
        src_pattern=0x7fffffffc6b0, mask_pattern=0x0, abstract_dst=0xb9a650,
        src_x=0, src_y=26, mask_x=0, mask_y=0, dst_x=0, dst_y=26, width=17,
        height=20, clip_region=0x0) at cairo-xlib-surface.c:2415
        src=0x7fffffffc6b0, mask=0x0, dst=0xb9a650, src_x=0, src_y=26, mask_x=0,
        mask_y=0, dst_x=0, dst_y=26, width=17, height=20, clip_region=0x0)
        at cairo-surface.c:1802
        traps=0x7fffffffbee0, src=0x7fffffffc6b0, op=CAIRO_OPERATOR_OVER,
        dst=0xb9a650) at cairo-surface-fallback.c:762
        op=CAIRO_OPERATOR_OVER, dst=0xb9a650, traps=0x7fffffffbee0,
        antialias=CAIRO_ANTIALIAS_DEFAULT, clip=0x0, extents=0x7fffffffc600)
        at cairo-surface-fallback.c:812
    ---Type <return> to continue, or q <return> to quit---bt
        op=CAIRO_OPERATOR_OVER, source=0x7fffffffc6b0, clip=0x0)
        at cairo-surface-fallback.c:935
        source=0x7fffffffc6b0, op=CAIRO_OPERATOR_OVER, surface=0xb9a650)
        at cairo-surface.c:2027
        source=0x7fffffffc6b0, clip=0x7fffffffc7b0) at cairo-surface.c:1993
        at cairo-gstate.c:1049
        at spice-widget-cairo.c:104
        expose=0x7fffffffceb0) at spice-widget-cairo.c:133
        expose=0x7fffffffceb0) at spice-widget.c:885
        return_value=0x7fffffffca60, n_param_values=<optimized out>,
        param_values=0x7fffffffcad0, invocation_hint=<optimized out>,
        marshal_data=<optimized out>) at gtkmarshalers.c:86
        return_value=0x7fffffffca60, n_param_values=2,
        param_values=0x7fffffffcad0, invocation_hint=<optimized out>)
    ---Type <return> to continue, or q <return> to quit---c
        at gclosure.c:777
        detail=0, instance=<optimized out>, emission_return=0x7fffffffccb0,
        instance_and_params=0x7fffffffcad0) at gsignal.c:3584
        signal_id=<optimized out>, detail=0, var_args=<optimized out>)
        at gsignal.c:3305
        signal_id=<optimized out>, detail=<optimized out>) at gsignal.c:3351
        event=0x7fffffffceb0) at gtkwidget.c:4999

diff --git a/gtk/channel-display.c b/gtk/channel-display.c
index 8269705..d3109bc 100644
--- a/gtk/channel-display.c
+++ b/gtk/channel-display.c
@@ -73,7 +73,6 @@ struct _SpiceDisplayChannelPrivate {
 #ifdef WIN32
     HDC dc;
 #endif
-    gboolean                    migrate_wait_primary;
 };
 
 G_DEFINE_TYPE(SpiceDisplayChannel, spice_display_channel, SPICE_TYPE_CHANNEL)
@@ -99,7 +98,7 @@ static guint signals[SPICE_DISPLAY_LAST_SIGNAL];
 static void spice_display_handle_msg(SpiceChannel *channel, SpiceMsgIn *msg);
 static void spice_display_channel_up(SpiceChannel *channel);
 
-static void clear_surfaces(SpiceChannel *channel);
+static void clear_surfaces(SpiceChannel *channel, gboolean keep_primary);
 static void clear_streams(SpiceChannel *channel);
 static display_surface *find_surface(SpiceDisplayChannelPrivate *c, int surface_id);
 static gboolean display_stream_render(display_stream *st);
@@ -123,11 +122,7 @@ static void spice_display_channel_dispose(GObject *object)
 
 static void spice_display_channel_finalize(GObject *object)
 {
-    SpiceDisplayChannelPrivate *c = SPICE_DISPLAY_CHANNEL(object)->priv;
-
-    c->migrate_wait_primary = FALSE;
-
-    clear_surfaces(SPICE_CHANNEL(object));
+    clear_surfaces(SPICE_CHANNEL(object), FALSE);
     clear_streams(SPICE_CHANNEL(object));
 
     if (G_OBJECT_CLASS(spice_display_channel_parent_class)->finalize)
@@ -190,13 +185,9 @@ static void spice_display_set_property(GObject      *object,
 /* main or coroutine context */
 static void spice_display_channel_reset(SpiceChannel *channel, gboolean migrating)
 {
-    SpiceDisplayChannelPrivate *c = SPICE_DISPLAY_CHANNEL(channel)->priv;
-
     /* palettes, images, and glz_window are cleared in the session */
-
-    c->migrate_wait_primary = migrating;
     clear_streams(channel);
-    clear_surfaces(channel);
+    clear_surfaces(channel, TRUE);
 
     SPICE_CHANNEL_CLASS(spice_display_channel_parent_class)->channel_reset(channel, migrating);
 }
@@ -618,10 +609,8 @@ static int create_canvas(SpiceChannel *channel, display_surface *surface)
         display_surface *primary = find_surface(c, 0);
 
         if (primary) {
-            if (c->migrate_wait_primary &&
-                primary->width == surface->width &&
+            if (primary->width == surface->width &&
                 primary->height == surface->height) {
-                c->migrate_wait_primary = FALSE;
                 SPICE_DEBUG("Reusing existing primary surface");
                 return 0;
             }
@@ -633,8 +622,6 @@ static int create_canvas(SpiceChannel *channel, display_surface *surface)
         }
 
         SPICE_DEBUG("display: create primary canvas");
-        c->migrate_wait_primary = FALSE;
-
 #ifdef HAVE_SYS_SHM_H
         surface->shmid = shmget(IPC_PRIVATE, surface->size, IPC_CREAT | 0777);
         if (surface->shmid >= 0) {
@@ -730,7 +717,7 @@ static display_surface *find_surface(SpiceDisplayChannelPrivate *c, int surface_
     return NULL;
 }
 
-static void clear_surfaces(SpiceChannel *channel)
+static void clear_surfaces(SpiceChannel *channel, gboolean keep_primary)
 {
     SpiceDisplayChannelPrivate *c = SPICE_DISPLAY_CHANNEL(channel)->priv;
     display_surface *surface;
@@ -740,8 +727,8 @@ static void clear_surfaces(SpiceChannel *channel)
         surface = SPICE_CONTAINEROF(item, display_surface, link);
         item = ring_next(&c->surfaces, item);
 
-        if (c->migrate_wait_primary && surface->primary) {
-            SPICE_DEBUG("Try to keep exisiting primary surface during migration");
+        if (keep_primary && surface->primary) {
+            SPICE_DEBUG("keeping exisiting primary surface, migration or reset");
             continue;
         }
 
diff --git a/gtk/spice-widget.c b/gtk/spice-widget.c
index db53928..c13f758 100644
--- a/gtk/spice-widget.c
+++ b/gtk/spice-widget.c
@@ -1740,6 +1740,7 @@ static void disconnect_display(SpiceDisplay *display)
                                          display);
     g_signal_handlers_disconnect_by_func(d->display, G_CALLBACK(invalidate),
                                          display);
+    primary_destroy(d->display, display);
     d->display = NULL;
 }
 
commit d19e1b0f21be63697e32f8de4a51482caf5444d5
Author: Marc-André Lureau <marcandre.lureau at redhat.com>
Date:   Fri Mar 30 23:46:33 2012 +0200

    mjpeg: fix blue-tinted video stream with old server
    
    The major == 1 uses RGB colorspace for mjpeg streams.

diff --git a/gtk/channel-display-mjpeg.c b/gtk/channel-display-mjpeg.c
index cb1bc87..aed3adf 100644
--- a/gtk/channel-display-mjpeg.c
+++ b/gtk/channel-display-mjpeg.c
@@ -65,6 +65,7 @@ G_GNUC_INTERNAL
 void stream_mjpeg_data(display_stream *st)
 {
     SpiceMsgDisplayStreamCreate *info = spice_msg_in_parsed(st->msg_create);
+    gboolean back_compat = st->channel->priv->peer_hdr.major_version == 1;
     int width = info->stream_width;
     int height = info->stream_height;
     uint8_t *dest;
@@ -80,7 +81,10 @@ void stream_mjpeg_data(display_stream *st)
     jpeg_read_header(&st->mjpeg_cinfo, 1);
 #ifdef JCS_EXTENSIONS
     // requires jpeg-turbo
-    st->mjpeg_cinfo.out_color_space = JCS_EXT_BGRX;
+    if (back_compat)
+        st->mjpeg_cinfo.out_color_space = JCS_EXT_RGBX;
+    else
+        st->mjpeg_cinfo.out_color_space = JCS_EXT_BGRX;
 #else
 #warning "You should consider building with libjpeg-turbo"
     st->mjpeg_cinfo.out_color_space = JCS_RGB;
@@ -121,11 +125,20 @@ void stream_mjpeg_data(display_stream *st)
             uint8_t *s = lines[0];
             uint32_t *d = (uint32_t *)s;
 
-            for (unsigned int j = lines_read * width; j > 0; ) {
-                j -= 1; // reverse order, bad for cache?
-                d[j] = s[j * 3 + 0] << 16 |
-                    s[j * 3 + 1] << 8 |
-                    s[j * 3 + 2];
+            if (back_compat) {
+                for (unsigned int j = lines_read * width; j > 0; ) {
+                    j -= 1; // reverse order, bad for cache?
+                    d[j] = s[j * 3 + 0] |
+                        s[j * 3 + 1] << 8 |
+                        s[j * 3 + 2] << 16;
+                }
+            } else {
+                for (unsigned int j = lines_read * width; j > 0; ) {
+                    j -= 1; // reverse order, bad for cache?
+                    d[j] = s[j * 3 + 0] << 16 |
+                        s[j * 3 + 1] << 8 |
+                        s[j * 3 + 2];
+                }
             }
         }
 #endif


More information about the Spice-commits mailing list