Hi all,
the patch "qemu-vnc-wmvi.patch" adds support for the WMVi pseudoencoding
in qemu vnc server.
If the client implements it, it is supposed to be able to change colour
depth when receiving a WMVi message.
Since I didn't know any client that supports it and I wanted to test the
implementation before submitting any patch I also modified vncviewer to
support WMVi.
The patch "vncviewer-wmvi.patch" is meant to be applied to the realvnc
vncviewer unix client version 4.1.2, using patch -p1.
Try executing vncviewer with FullColour=1 AutoSelect=0.
Signed-off-by: Stefano Stabellini <stefano.stabellini@xxxxxxxxxxxxx>
Regards,
Stefano Stabellini
diff -r e85399173769 tools/ioemu/vl.c
--- a/tools/ioemu/vl.c Tue Feb 12 16:59:08 2008 +0000
+++ b/tools/ioemu/vl.c Wed Feb 13 12:41:42 2008 +0000
@@ -154,7 +154,6 @@ int nographic;
int nographic;
int vncviewer;
int vncunused;
-int vncswitchbpp;
const char* keyboard_layout = NULL;
int64_t ticks_per_sec;
char *boot_device = NULL;
@@ -6560,7 +6559,6 @@ void help(void)
"-vnc display start a VNC server on display\n"
"-vncviewer start a vncviewer process for this domain\n"
"-vncunused bind the VNC server to an unused port\n"
- "-vnc-switch-bpp VNC server closes connections when the guest OS
changes colour depth\n"
#ifndef NO_DAEMONIZE
"-daemonize daemonize QEMU after initializing\n"
#endif
@@ -6662,7 +6660,6 @@ enum {
QEMU_OPTION_acpi,
QEMU_OPTION_vncviewer,
QEMU_OPTION_vncunused,
- QEMU_OPTION_vncswitchbpp,
QEMU_OPTION_pci,
};
@@ -6746,7 +6743,6 @@ const QEMUOption qemu_options[] = {
{ "vnc", HAS_ARG, QEMU_OPTION_vnc },
{ "vncviewer", 0, QEMU_OPTION_vncviewer },
{ "vncunused", 0, QEMU_OPTION_vncunused },
- { "vnc-switch-bpp", 0, QEMU_OPTION_vncswitchbpp },
/* temporary options */
{ "usb", 0, QEMU_OPTION_usb },
@@ -7164,7 +7160,6 @@ int main(int argc, char **argv)
nographic = 0;
vncviewer = 0;
vncunused = 0;
- vncswitchbpp = 0;
kernel_filename = NULL;
kernel_cmdline = "";
#ifndef CONFIG_DM
@@ -7595,9 +7590,6 @@ int main(int argc, char **argv)
case QEMU_OPTION_vncunused:
vncunused++;
break;
- case QEMU_OPTION_vncswitchbpp:
- vncswitchbpp++;
- break;
case QEMU_OPTION_pci:
direct_pci = optarg;
break;
@@ -7830,7 +7822,6 @@ int main(int argc, char **argv)
} else if (vnc_display != NULL || vncunused != 0) {
int vnc_display_port;
char password[20];
- ds->switchbpp = vncswitchbpp;
vnc_display_init(ds);
xenstore_read_vncpasswd(domid, password, sizeof(password));
vnc_display_password(ds, password);
diff -r e85399173769 tools/ioemu/vnc.c
--- a/tools/ioemu/vnc.c Tue Feb 12 16:59:08 2008 +0000
+++ b/tools/ioemu/vnc.c Wed Feb 13 13:59:04 2008 +0000
@@ -157,6 +157,7 @@ struct VncState
int has_resize;
int has_hextile;
int has_pointer_type_change;
+ int has_WMVi;
int absolute;
int last_x;
int last_y;
@@ -1310,6 +1311,7 @@ static void set_encodings(VncState *vs,
vs->has_hextile = 0;
vs->has_resize = 0;
vs->has_pointer_type_change = 0;
+ vs->has_WMVi = 0;
vs->absolute = -1;
vs->ds->dpy_copy = NULL;
@@ -1330,6 +1332,8 @@ static void set_encodings(VncState *vs,
case -257:
vs->has_pointer_type_change = 1;
break;
+ case 0x574D5669:
+ vs->has_WMVi = 1;
default:
break;
}
@@ -1408,6 +1412,57 @@ static void set_pixel_format(VncState *v
vga_hw_invalidate();
vga_hw_update();
+}
+
+static void pixel_format_message (VncState *vs) {
+ char pad[3] = { 0, 0, 0 };
+
+ vnc_write_u8(vs, vs->depth * 8); /* bits-per-pixel */
+ if (vs->depth == 4) vnc_write_u8(vs, 24); /* depth */
+ else vnc_write_u8(vs, vs->depth * 8); /* depth */
+
+#ifdef WORDS_BIGENDIAN
+ vnc_write_u8(vs, 1); /* big-endian-flag */
+#else
+ vnc_write_u8(vs, 0); /* big-endian-flag */
+#endif
+ vnc_write_u8(vs, 1); /* true-color-flag */
+ if (vs->depth == 4) {
+ vnc_write_u16(vs, 0xFF); /* red-max */
+ vnc_write_u16(vs, 0xFF); /* green-max */
+ vnc_write_u16(vs, 0xFF); /* blue-max */
+ vnc_write_u8(vs, 16); /* red-shift */
+ vnc_write_u8(vs, 8); /* green-shift */
+ vnc_write_u8(vs, 0); /* blue-shift */
+ vs->send_hextile_tile = send_hextile_tile_32;
+ } else if (vs->depth == 2) {
+ vnc_write_u16(vs, 31); /* red-max */
+ vnc_write_u16(vs, 63); /* green-max */
+ vnc_write_u16(vs, 31); /* blue-max */
+ vnc_write_u8(vs, 11); /* red-shift */
+ vnc_write_u8(vs, 5); /* green-shift */
+ vnc_write_u8(vs, 0); /* blue-shift */
+ vs->send_hextile_tile = send_hextile_tile_16;
+ } else if (vs->depth == 1) {
+ /* XXX: change QEMU pixel 8 bit pixel format to match the VNC one ? */
+ vnc_write_u16(vs, 7); /* red-max */
+ vnc_write_u16(vs, 7); /* green-max */
+ vnc_write_u16(vs, 3); /* blue-max */
+ vnc_write_u8(vs, 5); /* red-shift */
+ vnc_write_u8(vs, 2); /* green-shift */
+ vnc_write_u8(vs, 0); /* blue-shift */
+ vs->send_hextile_tile = send_hextile_tile_8;
+ }
+ vs->red_max = vs->red_max1;
+ vs->green_max = vs->green_max1;
+ vs->blue_max = vs->blue_max1;
+ vs->red_shift = vs->red_shift1;
+ vs->green_shift = vs->green_shift1;
+ vs->blue_shift = vs->blue_shift1;
+ vs->pix_bpp = vs->depth * 8;
+ vs->write_pixels = vnc_write_pixels_copy;
+
+ vnc_write(vs, pad, 3); /* padding */
}
static void vnc_dpy_colourdepth(DisplayState *ds, int depth)
@@ -1457,6 +1512,14 @@ static void vnc_dpy_colourdepth(DisplayS
}
if (ds->switchbpp) {
vnc_client_error(vs);
+ } else if (vs->csock != -1 && vs->has_WMVi) {
+ /* Sending a WMVi message to notify the client*/
+ vnc_write_u8(vs, 0); /* msg id */
+ vnc_write_u8(vs, 0);
+ vnc_write_u16(vs, 1); /* number of rects */
+ vnc_framebuffer_update(vs, 0, 0, ds->width, ds->height, 0x574D5669);
+ pixel_format_message(vs);
+ vnc_flush(vs);
} else {
if (vs->pix_bpp == 4 && vs->depth == 4 &&
host_big_endian_flag == vs->pix_big_endian &&
@@ -1578,7 +1641,6 @@ static int protocol_client_init(VncState
static int protocol_client_init(VncState *vs, uint8_t *data, size_t len)
{
size_t l;
- char pad[3] = { 0, 0, 0 };
vga_hw_update();
@@ -1587,45 +1649,7 @@ static int protocol_client_init(VncState
vnc_write_u16(vs, vs->ds->width);
vnc_write_u16(vs, vs->ds->height);
- vnc_write_u8(vs, vs->depth * 8); /* bits-per-pixel */
- if (vs->depth == 4) vnc_write_u8(vs, 24); /* depth */
- else vnc_write_u8(vs, vs->depth * 8); /* depth */
-
-#ifdef WORDS_BIGENDIAN
- vnc_write_u8(vs, 1); /* big-endian-flag */
-#else
- vnc_write_u8(vs, 0); /* big-endian-flag */
-#endif
- vnc_write_u8(vs, 1); /* true-color-flag */
- if (vs->depth == 4) {
- vnc_write_u16(vs, 0xFF); /* red-max */
- vnc_write_u16(vs, 0xFF); /* green-max */
- vnc_write_u16(vs, 0xFF); /* blue-max */
- vnc_write_u8(vs, 16); /* red-shift */
- vnc_write_u8(vs, 8); /* green-shift */
- vnc_write_u8(vs, 0); /* blue-shift */
- vs->send_hextile_tile = send_hextile_tile_32;
- } else if (vs->depth == 2) {
- vnc_write_u16(vs, 31); /* red-max */
- vnc_write_u16(vs, 63); /* green-max */
- vnc_write_u16(vs, 31); /* blue-max */
- vnc_write_u8(vs, 11); /* red-shift */
- vnc_write_u8(vs, 5); /* green-shift */
- vnc_write_u8(vs, 0); /* blue-shift */
- vs->send_hextile_tile = send_hextile_tile_16;
- } else if (vs->depth == 1) {
- /* XXX: change QEMU pixel 8 bit pixel format to match the VNC one ? */
- vnc_write_u16(vs, 7); /* red-max */
- vnc_write_u16(vs, 7); /* green-max */
- vnc_write_u16(vs, 3); /* blue-max */
- vnc_write_u8(vs, 5); /* red-shift */
- vnc_write_u8(vs, 2); /* green-shift */
- vnc_write_u8(vs, 0); /* blue-shift */
- vs->send_hextile_tile = send_hextile_tile_8;
- }
- vs->write_pixels = vnc_write_pixels_copy;
-
- vnc_write(vs, pad, 3); /* padding */
+ pixel_format_message(vs);
l = strlen(domain_name);
vnc_write_u32(vs, l);
@@ -2436,6 +2460,8 @@ int vnc_display_open(DisplayState *ds, c
options++;
if (strncmp(options, "password", 8) == 0) {
password = 1; /* Require password auth */
+ } else if (strncmp(options, "switchbpp", 9) == 0) {
+ ds->switchbpp = 1;
#if CONFIG_VNC_TLS
} else if (strncmp(options, "tls", 3) == 0) {
tls = 1; /* Require TLS */
diff -upr vnc-4_1_2-unixsrc/common/rfb/CMsgReaderV3.cxx
../vnc-4_1_2-unixsrc-new/common/rfb/CMsgReaderV3.cxx
--- vnc-4_1_2-unixsrc/common/rfb/CMsgReaderV3.cxx 2006-05-15
17:56:20.000000000 +0100
+++ ../vnc-4_1_2-unixsrc-new/common/rfb/CMsgReaderV3.cxx 2008-02-13
14:13:05.000000000 +0000
@@ -74,6 +74,13 @@ void CMsgReaderV3::readMsg()
case pseudoEncodingDesktopSize:
handler->setDesktopSize(w, h);
break;
+ case pseudoEncodingWMVi:
+ {
+ PixelFormat pf;
+ pf.read(is);
+ handler->setPixelFormat(pf);
+ }
+ break;
case pseudoEncodingCursor:
readSetCursor(w, h, Point(x,y));
break;
diff -upr vnc-4_1_2-unixsrc/common/rfb/CMsgWriter.cxx
../vnc-4_1_2-unixsrc-new/common/rfb/CMsgWriter.cxx
--- vnc-4_1_2-unixsrc/common/rfb/CMsgWriter.cxx 2006-05-15 17:56:20.000000000
+0100
+++ ../vnc-4_1_2-unixsrc-new/common/rfb/CMsgWriter.cxx 2008-02-13
14:13:32.000000000 +0000
@@ -64,6 +64,8 @@ void CMsgWriter::writeSetEncodings(int p
encodings[nEncodings++] = pseudoEncodingCursor;
if (cp->supportsDesktopResize)
encodings[nEncodings++] = pseudoEncodingDesktopSize;
+ if (cp->supportsWMVi)
+ encodings[nEncodings++] = pseudoEncodingWMVi;
if (Decoder::supported(preferredEncoding)) {
encodings[nEncodings++] = preferredEncoding;
}
diff -upr vnc-4_1_2-unixsrc/common/rfb/ConnParams.cxx
../vnc-4_1_2-unixsrc-new/common/rfb/ConnParams.cxx
--- vnc-4_1_2-unixsrc/common/rfb/ConnParams.cxx 2006-05-15 17:56:20.000000000
+0100
+++ ../vnc-4_1_2-unixsrc-new/common/rfb/ConnParams.cxx 2008-02-13
14:14:14.000000000 +0000
@@ -88,6 +88,7 @@ void ConnParams::setEncodings(int nEncod
useCopyRect = false;
supportsLocalCursor = false;
supportsDesktopResize = false;
+ supportsWMVi = false;
currentEncoding_ = encodingRaw;
for (int i = nEncodings-1; i >= 0; i--) {
@@ -99,6 +100,8 @@ void ConnParams::setEncodings(int nEncod
supportsLocalCursor = true;
else if (encodings[i] == pseudoEncodingDesktopSize)
supportsDesktopResize = true;
+ else if (encodings[i] == pseudoEncodingWMVi)
+ supportsWMVi = true;
else if (encodings[i] <= encodingMax && Encoder::supported(encodings[i]))
currentEncoding_ = encodings[i];
}
diff -upr vnc-4_1_2-unixsrc/common/rfb/ConnParams.h
../vnc-4_1_2-unixsrc-new/common/rfb/ConnParams.h
--- vnc-4_1_2-unixsrc/common/rfb/ConnParams.h 2006-05-15 17:56:20.000000000
+0100
+++ ../vnc-4_1_2-unixsrc-new/common/rfb/ConnParams.h 2008-02-13
14:14:33.000000000 +0000
@@ -71,6 +71,7 @@ namespace rfb {
bool supportsLocalCursor;
bool supportsDesktopResize;
+ bool supportsWMVi;
private:
diff -upr vnc-4_1_2-unixsrc/common/rfb/encodings.h
../vnc-4_1_2-unixsrc-new/common/rfb/encodings.h
--- vnc-4_1_2-unixsrc/common/rfb/encodings.h 2006-05-15 17:56:20.000000000
+0100
+++ ../vnc-4_1_2-unixsrc-new/common/rfb/encodings.h 2008-02-13
14:14:58.000000000 +0000
@@ -31,6 +31,7 @@ namespace rfb {
const unsigned int pseudoEncodingCursor = 0xffffff11;
const unsigned int pseudoEncodingDesktopSize = 0xffffff21;
+ const unsigned int pseudoEncodingWMVi = 0x574D5669;
int encodingNum(const char* name);
const char* encodingName(unsigned int num);
diff -upr vnc-4_1_2-unixsrc/unix/vncviewer/CConn.cxx
../vnc-4_1_2-unixsrc-new/unix/vncviewer/CConn.cxx
--- vnc-4_1_2-unixsrc/unix/vncviewer/CConn.cxx 2006-05-15 17:56:20.000000000
+0100
+++ ../vnc-4_1_2-unixsrc-new/unix/vncviewer/CConn.cxx 2008-02-13
14:15:51.000000000 +0000
@@ -75,6 +75,7 @@ CConn::CConn(Display* dpy_, int argc_, c
autoSelect = false;
}
cp.supportsDesktopResize = true;
+ cp.supportsWMVi = true;
cp.supportsLocalCursor = useLocalCursor;
initMenu();
@@ -260,6 +261,17 @@ void CConn::setDesktopSize(int w, int h)
}
}
+// setPixelFormat is called upon receving a WMVi message
+void CConn::setPixelFormat(const PixelFormat &pf) {
+ cp.setPF(pf);
+ if (desktop) {
+ char str[256];
+ desktop->setPF(pf);
+ desktop->getPF().print(str, 256);
+ vlog.info("Using pixel format %s",str);
+ }
+ }
+
// framebufferUpdateEnd() is called at the end of an update.
// For each rectangle, the FdInStream will have timed the speed
// of the connection, allowing us to select format and encoding
diff -upr vnc-4_1_2-unixsrc/unix/vncviewer/CConn.h
../vnc-4_1_2-unixsrc-new/unix/vncviewer/CConn.h
--- vnc-4_1_2-unixsrc/unix/vncviewer/CConn.h 2006-05-15 17:56:20.000000000
+0100
+++ ../vnc-4_1_2-unixsrc-new/unix/vncviewer/CConn.h 2008-02-13
14:16:17.000000000 +0000
@@ -26,6 +26,7 @@
#include <rfb/Exception.h>
#include <rfb/UserPasswdGetter.h>
#include <rdr/FdInStream.h>
+#include <rfb/PixelFormat.h>
#include <list>
#include "TXWindow.h"
@@ -74,6 +75,7 @@ public:
rfb::CSecurity* getCSecurity(int secType);
void serverInit();
void setDesktopSize(int w, int h);
+ void setPixelFormat(const rfb::PixelFormat& pf);
void setColourMapEntries(int firstColour, int nColours, rdr::U16* rgbs);
void bell();
void serverCutText(const char* str, int len);
_______________________________________________
Xen-devel mailing list
Xen-devel@xxxxxxxxxxxxxxxxxxx
http://lists.xensource.com/xen-devel
|