Commit efe556ad authored by Corentin Chary's avatar Corentin Chary Committed by Anthony Liguori

vnc: tight add PNG encoding

Introduce a new encoding: VNC_ENCODING_TIGHT_PNG [1] (-269) with a new
tight filter VNC_TIGHT_PNG (0x0A). When the client tells it supports the Tight PNG
encoding, the server will use tight, but will always send encoding pixels using
PNG instead of zlib. If the client also told it support JPEG, then the server can
send JPEG, because PNG will only be used in the cases zlib was used in normal tight.

This encoding was introduced to speed up HTML5 based VNC clients like noVNC [2], but
can also be used on devices like iPhone where PNG can be rendered in hardware.

[1] http://wiki.qemu.org/VNC_Tight_PNG
[2] http://github.com/kanaka/noVNC/Signed-off-by: default avatarCorentin Chary <corentincj@iksaif.net>
Signed-off-by: default avatarAnthony Liguori <aliguori@us.ibm.com>
parent d9c18c24
......@@ -178,6 +178,7 @@ LIBS+=-lz
QEMU_CFLAGS += $(VNC_TLS_CFLAGS)
QEMU_CFLAGS += $(VNC_SASL_CFLAGS)
QEMU_CFLAGS += $(VNC_JPEG_CFLAGS)
QEMU_CFLAGS += $(VNC_PNG_CFLAGS)
# xen backend driver support
obj-$(CONFIG_XEN) += xen_machine_pv.o xen_domainbuild.o
......
......@@ -269,6 +269,7 @@ vde=""
vnc_tls=""
vnc_sasl=""
vnc_jpeg=""
vnc_png=""
xen=""
linux_aio=""
attr=""
......@@ -580,6 +581,10 @@ for opt do
;;
--enable-vnc-jpeg) vnc_jpeg="yes"
;;
--disable-vnc-png) vnc_png="no"
;;
--enable-vnc-png) vnc_png="yes"
;;
--disable-slirp) slirp="no"
;;
--disable-uuid) uuid="no"
......@@ -832,6 +837,8 @@ echo " --disable-vnc-sasl disable SASL encryption for VNC server"
echo " --enable-vnc-sasl enable SASL encryption for VNC server"
echo " --disable-vnc-jpeg disable JPEG lossy compression for VNC server"
echo " --enable-vnc-jpeg enable JPEG lossy compression for VNC server"
echo " --disable-vnc-png disable PNG compression for VNC server"
echo " --enable-vnc-png enable PNG compression for VNC server"
echo " --disable-curses disable curses output"
echo " --enable-curses enable curses output"
echo " --disable-curl disable curl connectivity"
......@@ -1273,6 +1280,31 @@ EOF
fi
fi
##########################################
# VNC PNG detection
if test "$vnc_png" = "yes" ; then
cat > $TMPC <<EOF
//#include <stdio.h>
#include <png.h>
int main(void) {
png_structp png_ptr;
png_ptr = png_create_write_struct(PNG_LIBPNG_VER_STRING, NULL, NULL, NULL);
return 0;
}
EOF
vnc_png_cflags=""
vnc_png_libs="-lpng"
if compile_prog "$vnc_png_cflags" "$vnc_png_libs" ; then
vnc_png=yes
libs_softmmu="$vnc_png_libs $libs_softmmu"
else
if test "$vnc_png" = "yes" ; then
feature_not_found "vnc-png"
fi
vnc_png=no
fi
fi
##########################################
# fnmatch() probe, used for ACL routines
fnmatch="no"
......@@ -2123,6 +2155,7 @@ echo "Mixer emulation $mixemu"
echo "VNC TLS support $vnc_tls"
echo "VNC SASL support $vnc_sasl"
echo "VNC JPEG support $vnc_jpeg"
echo "VNC PNG support $vnc_png"
if test -n "$sparc_cpu"; then
echo "Target Sparc Arch $sparc_cpu"
fi
......@@ -2264,6 +2297,10 @@ if test "$vnc_jpeg" = "yes" ; then
echo "CONFIG_VNC_JPEG=y" >> $config_host_mak
echo "VNC_JPEG_CFLAGS=$vnc_jpeg_cflags" >> $config_host_mak
fi
if test "$vnc_png" = "yes" ; then
echo "CONFIG_VNC_PNG=y" >> $config_host_mak
echo "VNC_PNG_CFLAGS=$vnc_png_cflags" >> $config_host_mak
fi
if test "$fnmatch" = "yes" ; then
echo "CONFIG_FNMATCH=y" >> $config_host_mak
fi
......
This diff is collapsed.
......@@ -42,8 +42,9 @@
* bit 3: if 1, then compression stream 3 should be reset;
* bits 7-4: if 1000 (0x08), then the compression type is "fill",
* if 1001 (0x09), then the compression type is "jpeg",
* if 1010 (0x0A), then the compression type is "png",
* if 0xxx, then the compression type is "basic",
* values greater than 1001 are not valid.
* values greater than 1010 are not valid.
*
* If the compression type is "basic", then bits 6..4 of the
* compression control byte (those xxx in 0xxx) specify the following:
......@@ -53,17 +54,17 @@
* bit 6: if 1, then a "filter id" byte is following this byte.
*
*-- The data that follows after the compression control byte described
* above depends on the compression type ("fill", "jpeg" or "basic").
* above depends on the compression type ("fill", "jpeg", "png" or "basic").
*
*-- If the compression type is "fill", then the only pixel value follows, in
* client pixel format (see NOTE 1). This value applies to all pixels of the
* rectangle.
*
*-- If the compression type is "jpeg", the following data stream looks like
* this:
*-- If the compression type is "jpeg" or "png", the following data stream
* looks like this:
*
* 1..3 bytes: data size (N) in compact representation;
* N bytes: JPEG image.
* N bytes: JPEG or PNG image.
*
* Data size is compactly represented in one, two or three bytes, according
* to the following scheme:
......@@ -144,7 +145,7 @@
*-- NOTE 2. The decoder must reset compression streams' states before
* decoding the rectangle, if some of bits 0,1,2,3 in the compression control
* byte are set to 1. Note that the decoder must reset zlib streams even if
* the compression type is "fill" or "jpeg".
* the compression type is "fill", "jpeg" or "png".
*
*-- NOTE 3. The "gradient" filter and "jpeg" compression may be used only
* when bits-per-pixel value is either 16 or 32, not 8.
......@@ -158,7 +159,8 @@
#define VNC_TIGHT_EXPLICIT_FILTER 0x04
#define VNC_TIGHT_FILL 0x08
#define VNC_TIGHT_JPEG 0x09
#define VNC_TIGHT_MAX_SUBENCODING 0x09
#define VNC_TIGHT_PNG 0x0A
#define VNC_TIGHT_MAX_SUBENCODING 0x0A
/* Filters to improve compression efficiency */
#define VNC_TIGHT_FILTER_COPY 0x00
......
......@@ -351,10 +351,6 @@ void do_info_vnc(Monitor *mon, QObject **ret_data)
}
}
static inline uint32_t vnc_has_feature(VncState *vs, int feature) {
return (vs->features & (1 << feature));
}
/* TODO
1) Get the queue working for IO.
2) there is some weirdness when using the -S option (the screen is grey
......@@ -661,6 +657,9 @@ static int send_framebuffer_update(VncState *vs, int x, int y, int w, int h)
case VNC_ENCODING_TIGHT:
n = vnc_tight_send_framebuffer_update(vs, x, y, w, h);
break;
case VNC_ENCODING_TIGHT_PNG:
n = vnc_tight_png_send_framebuffer_update(vs, x, y, w, h);
break;
default:
vnc_framebuffer_update(vs, x, y, w, h, VNC_ENCODING_RAW);
n = vnc_raw_send_framebuffer_update(vs, x, y, w, h);
......@@ -1669,6 +1668,10 @@ static void set_encodings(VncState *vs, int32_t *encodings, size_t n_encodings)
vs->features |= VNC_FEATURE_TIGHT_MASK;
vs->vnc_encoding = enc;
break;
case VNC_ENCODING_TIGHT_PNG:
vs->features |= VNC_FEATURE_TIGHT_PNG_MASK;
vs->vnc_encoding = enc;
break;
case VNC_ENCODING_ZLIB:
vs->features |= VNC_FEATURE_ZLIB_MASK;
vs->vnc_encoding = enc;
......
......@@ -172,6 +172,7 @@ struct VncState
/* Encoding specific */
/* Tight */
int tight_type;
uint8_t tight_quality;
uint8_t tight_compression;
uint8_t tight_pixel24;
......@@ -181,6 +182,9 @@ struct VncState
Buffer tight_gradient;
#ifdef CONFIG_VNC_JPEG
Buffer tight_jpeg;
#endif
#ifdef CONFIG_VNC_PNG
Buffer tight_png;
#endif
int tight_levels[4];
z_stream tight_stream[4];
......@@ -259,6 +263,7 @@ enum {
#define VNC_ENCODING_POINTER_TYPE_CHANGE 0XFFFFFEFF /* -257 */
#define VNC_ENCODING_EXT_KEY_EVENT 0XFFFFFEFE /* -258 */
#define VNC_ENCODING_AUDIO 0XFFFFFEFD /* -259 */
#define VNC_ENCODING_TIGHT_PNG 0xFFFFFEFC /* -260 */
#define VNC_ENCODING_WMVi 0x574D5669
/*****************************************************************************
......@@ -275,6 +280,7 @@ enum {
#define VNC_TIGHT_CCB_TYPE_MASK (0x0f << 4)
#define VNC_TIGHT_CCB_TYPE_FILL (0x08 << 4)
#define VNC_TIGHT_CCB_TYPE_JPEG (0x09 << 4)
#define VNC_TIGHT_CCB_TYPE_PNG (0x0A << 4)
#define VNC_TIGHT_CCB_BASIC_MAX (0x07 << 4)
#define VNC_TIGHT_CCB_BASIC_ZLIB (0x03 << 4)
#define VNC_TIGHT_CCB_BASIC_FILTER (0x04 << 4)
......@@ -293,6 +299,7 @@ enum {
#define VNC_FEATURE_ZLIB 5
#define VNC_FEATURE_COPYRECT 6
#define VNC_FEATURE_RICH_CURSOR 7
#define VNC_FEATURE_TIGHT_PNG 8
#define VNC_FEATURE_RESIZE_MASK (1 << VNC_FEATURE_RESIZE)
#define VNC_FEATURE_HEXTILE_MASK (1 << VNC_FEATURE_HEXTILE)
......@@ -302,6 +309,7 @@ enum {
#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)
#define VNC_FEATURE_TIGHT_PNG_MASK (1 << VNC_FEATURE_TIGHT_PNG)
/* Client -> Server message IDs */
......@@ -405,6 +413,10 @@ void buffer_append(Buffer *buffer, const void *data, size_t len);
char *vnc_socket_local_addr(const char *format, int fd);
char *vnc_socket_remote_addr(const char *format, int fd);
static inline uint32_t vnc_has_feature(VncState *vs, int feature) {
return (vs->features & (1 << feature));
}
/* Framebuffer */
void vnc_framebuffer_update(VncState *vs, int x, int y, int w, int h,
int32_t encoding);
......@@ -423,8 +435,9 @@ void vnc_zlib_zfree(void *x, void *addr);
int vnc_zlib_send_framebuffer_update(VncState *vs, int x, int y, int w, int h);
void vnc_zlib_clear(VncState *vs);
int vnc_tight_send_framebuffer_update(VncState *vs, int x, int y, int w, int h);
int vnc_tight_png_send_framebuffer_update(VncState *vs, int x, int y,
int w, int h);
void vnc_tight_clear(VncState *vs);
#endif /* __QEMU_VNC_H */
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment