From patchwork Mon May 3 11:59:13 2010 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Gerd Hoffmann X-Patchwork-Id: 51495 Return-Path: X-Original-To: incoming@patchwork.ozlabs.org Delivered-To: patchwork-incoming@bilbo.ozlabs.org Received: from lists.gnu.org (lists.gnu.org [199.232.76.165]) (using TLSv1 with cipher DHE-RSA-AES256-SHA (256/256 bits)) (Client did not present a certificate) by ozlabs.org (Postfix) with ESMTPS id CAB6DB7D7A for ; Mon, 3 May 2010 22:00:09 +1000 (EST) Received: from localhost ([127.0.0.1]:54348 helo=lists.gnu.org) by lists.gnu.org with esmtp (Exim 4.43) id 1O8uJh-0001W1-Ts for incoming@patchwork.ozlabs.org; Mon, 03 May 2010 08:00:05 -0400 Received: from mailman by lists.gnu.org with tmda-scanned (Exim 4.43) id 1O8uJ3-0001Vl-Vq for qemu-devel@nongnu.org; Mon, 03 May 2010 07:59:26 -0400 Received: from [140.186.70.92] (port=36642 helo=eggs.gnu.org) by lists.gnu.org with esmtp (Exim 4.43) id 1O8uJ1-0001Ui-Ff for qemu-devel@nongnu.org; Mon, 03 May 2010 07:59:24 -0400 Received: from Debian-exim by eggs.gnu.org with spam-scanned (Exim 4.69) (envelope-from ) id 1O8uIz-00030v-5m for qemu-devel@nongnu.org; Mon, 03 May 2010 07:59:23 -0400 Received: from mx1.redhat.com ([209.132.183.28]:52824) by eggs.gnu.org with esmtp (Exim 4.69) (envelope-from ) id 1O8uIy-00030N-NL for qemu-devel@nongnu.org; Mon, 03 May 2010 07:59:21 -0400 Received: from int-mx08.intmail.prod.int.phx2.redhat.com (int-mx08.intmail.prod.int.phx2.redhat.com [10.5.11.21]) by mx1.redhat.com (8.13.8/8.13.8) with ESMTP id o43BxG1p020094 (version=TLSv1/SSLv3 cipher=DHE-RSA-AES256-SHA bits=256 verify=OK) for ; Mon, 3 May 2010 07:59:16 -0400 Received: from zweiblum.home.kraxel.org (vpn2-10-114.ams2.redhat.com [10.36.10.114]) by int-mx08.intmail.prod.int.phx2.redhat.com (8.13.8/8.13.8) with ESMTP id o43BxE98002394; Mon, 3 May 2010 07:59:15 -0400 Received: by zweiblum.home.kraxel.org (Postfix, from userid 500) id E66D47011C; Mon, 3 May 2010 13:59:13 +0200 (CEST) From: Gerd Hoffmann To: qemu-devel@nongnu.org Date: Mon, 3 May 2010 13:59:13 +0200 Message-Id: <1272887953-28305-1-git-send-email-kraxel@redhat.com> X-Scanned-By: MIMEDefang 2.67 on 10.5.11.21 X-detected-operating-system: by eggs.gnu.org: Genre and OS details not recognized. Cc: Gerd Hoffmann Subject: [Qemu-devel] [RfC PATCH] vnc: rich cursor support. X-BeenThere: qemu-devel@nongnu.org X-Mailman-Version: 2.1.5 Precedence: list List-Id: qemu-devel.nongnu.org List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Sender: qemu-devel-bounces+incoming=patchwork.ozlabs.org@nongnu.org Errors-To: qemu-devel-bounces+incoming=patchwork.ozlabs.org@nongnu.org Hi, Simple patch. Difficuilt matter. Not really sure where to go from here ... The whole thing is about local cursor support, i.e. just let the UI (sdl, vnc viewer, spice client, ...) draw the mouse pointer directly, without round trip to the guest for mouse pointer rendering. Current state in upstream qemu: vmware svga supports it. sdl supports it. When running vmware vga on sdl you should get it. In theory. In practice it doesn't work correctly. SDL can only handle 1bit (black/white) mouse cursors (with mask) I've seen vmware vga send only 1bit cursors (with mask, winxp guest), althougth it seems to be designed to support colored pointers too. vnc has two extentions for it: xcursor (1bit too, using a mask, but also allows to specify foreground/backgrund color) and rich cursor (uses pixelformat of the display, i.e. allows color). spice supports a whole bunch of formats, although I've seen only two of them used in practice: 1bit (with mask) and 32bit (rgb + alpha). The current hooks supporting local pointer (mouse_set, cursor_define) are in DisplayState, although I think they belong into DisplayChangeListener. Ok, how to sort this mess? I think we should put everything into a QEMUCursor struct, so we don't have to pass tons of parameters to the ->cursor_define() callback. Does it make sense to reuse "struct PixelFormat" for the cursor? I tend to think not. I expect we'll see three different cases be used in practice: (1) 1-bit image (and mask). (2) Same pixelformat as DisplayState (and mask). (3) 32bit RGB + alpha. Current PixelFormat can cover only (2) and even in that case it is redundant with DisplayState->pf. I think we also better allow only certain sizes. Minimum requirement should be that the width is a multiple of 8. Handling bitmasks just become too ugly without that. I'd tend to go further even and allow only 32x32 and 64x64 mouse pointers. Maybe 48x48 too. Comments? cheers, Gerd --- vnc.c | 35 +++++++++++++++++++++++++++++++++++ vnc.h | 2 ++ 2 files changed, 37 insertions(+), 0 deletions(-) diff --git a/vnc.c b/vnc.c index 9ba603c..5d9b9cb 100644 --- a/vnc.c +++ b/vnc.c @@ -925,6 +925,36 @@ static void vnc_dpy_copy(DisplayState *ds, int src_x, int src_y, int dst_x, int } } +static void vnc_mouse_set(int x, int y, int visible) +{ + /* can we do that ??? */ +} + +static void vnc_cursor_define(int width, int height, int bpp, + int hot_x, int hot_y, + uint8_t *image, uint8_t *mask) +{ + VncDisplay *vd = vnc_display; + int pixels, isize, msize; + VncState *vs; + + pixels = width * height; + isize = pixels * bpp / 8; + msize = pixels / 8; + + QTAILQ_FOREACH(vs, &vd->clients, next) { + if (!vnc_has_feature(vs, VNC_FEATURE_RICH_CURSOR)) + continue; + vnc_write_u8(vs, VNC_MSG_SERVER_FRAMEBUFFER_UPDATE); + vnc_write_u8(vs, 0); /* padding */ + vnc_write_u16(vs, 1); /* # of rects */ + vnc_framebuffer_update(vs, hot_x, hot_y, width, height, + VNC_ENCODING_RICH_CURSOR); + vnc_write(vs, image, isize); + vnc_write(vs, mask, msize); + } +} + static int find_and_clear_dirty_height(struct VncState *vs, int y, int last_x, int x) { @@ -1800,6 +1830,9 @@ static void set_encodings(VncState *vs, int32_t *encodings, size_t n_encodings) case VNC_ENCODING_POINTER_TYPE_CHANGE: vs->features |= VNC_FEATURE_POINTER_TYPE_CHANGE_MASK; break; + case VNC_ENCODING_RICH_CURSOR: + vs->features |= VNC_FEATURE_RICH_CURSOR_MASK; + break; case VNC_ENCODING_EXT_KEY_EVENT: send_ext_key_event_ack(vs); break; @@ -2487,6 +2520,8 @@ void vnc_display_init(DisplayState *ds) dcl->dpy_resize = vnc_dpy_resize; dcl->dpy_setdata = vnc_dpy_setdata; register_displaychangelistener(ds, dcl); + ds->mouse_set = vnc_mouse_set; + ds->cursor_define = vnc_cursor_define; } diff --git a/vnc.h b/vnc.h index b593608..ede9040 100644 --- a/vnc.h +++ b/vnc.h @@ -266,6 +266,7 @@ enum { #define VNC_FEATURE_TIGHT 4 #define VNC_FEATURE_ZLIB 5 #define VNC_FEATURE_COPYRECT 6 +#define VNC_FEATURE_RICH_CURSOR 7 #define VNC_FEATURE_RESIZE_MASK (1 << VNC_FEATURE_RESIZE) #define VNC_FEATURE_HEXTILE_MASK (1 << VNC_FEATURE_HEXTILE) @@ -274,6 +275,7 @@ enum { #define VNC_FEATURE_TIGHT_MASK (1 << VNC_FEATURE_TIGHT) #define VNC_FEATURE_ZLIB_MASK (1 << VNC_FEATURE_ZLIB) #define VNC_FEATURE_COPYRECT_MASK (1 << VNC_FEATURE_COPYRECT) +#define VNC_FEATURE_RICH_CURSOR_MASK (1 << VNC_FEATURE_RICH_CURSOR) /* Client -> Server message IDs */