#include "qemu-common.h"
#include "qemu-queue.h"
+#ifdef CONFIG_VNC_THREAD
+#include "qemu-thread.h"
+#endif
#include "console.h"
#include "monitor.h"
#include "audio/audio.h"
+#include "bitmap.h"
#include <zlib.h>
#include <stdbool.h>
#include "keymaps.h"
+#include "vnc-palette.h"
+#include "vnc-enc-zrle.h"
// #define _VNC_DEBUG 1
} Buffer;
typedef struct VncState VncState;
+typedef struct VncJob VncJob;
+typedef struct VncRect VncRect;
+typedef struct VncRectEntry VncRectEntry;
typedef int VncReadEvent(VncState *vs, uint8_t *data, size_t len);
void *last_fg,
int *has_bg, int *has_fg);
+/* VNC_MAX_WIDTH must be a multiple of 16. */
#define VNC_MAX_WIDTH 2560
#define VNC_MAX_HEIGHT 2048
-#define VNC_DIRTY_WORDS (VNC_MAX_WIDTH / (16 * 32))
+
+/* VNC_DIRTY_BITS is the number of bits in the dirty bitmap. */
+#define VNC_DIRTY_BITS (VNC_MAX_WIDTH / 16)
+
+#define VNC_STAT_RECT 64
+#define VNC_STAT_COLS (VNC_MAX_WIDTH / VNC_STAT_RECT)
+#define VNC_STAT_ROWS (VNC_MAX_HEIGHT / VNC_STAT_RECT)
#define VNC_AUTH_CHALLENGE_SIZE 16
#include "vnc-auth-sasl.h"
#endif
+struct VncRectStat
+{
+ /* time of last 10 updates, to find update frequency */
+ struct timeval times[10];
+ int idx;
+
+ double freq; /* Update frequency (in Hz) */
+ bool updated; /* Already updated during this refresh */
+};
+
+typedef struct VncRectStat VncRectStat;
+
struct VncSurface
{
- uint32_t dirty[VNC_MAX_HEIGHT][VNC_DIRTY_WORDS];
+ struct timeval last_freq_check;
+ DECLARE_BITMAP(dirty[VNC_MAX_HEIGHT], VNC_MAX_WIDTH / 16);
+ VncRectStat stats[VNC_STAT_ROWS][VNC_STAT_COLS];
DisplaySurface *ds;
};
DisplayState *ds;
kbd_layout_t *kbd_layout;
int lock_key_sync;
+#ifdef CONFIG_VNC_THREAD
+ QemuMutex mutex;
+#endif
QEMUCursor *cursor;
int cursor_msize;
char *display;
char *password;
+ time_t expires;
int auth;
bool lossy;
+ bool non_adaptive;
#ifdef CONFIG_VNC_TLS
int subauth; /* Used by VeNCrypt */
VncDisplayTLS tls;
#endif
};
+typedef struct VncTight {
+ int type;
+ uint8_t quality;
+ uint8_t compression;
+ uint8_t pixel24;
+ Buffer tight;
+ Buffer tmp;
+ Buffer zlib;
+ Buffer gradient;
+#ifdef CONFIG_VNC_JPEG
+ Buffer jpeg;
+#endif
+#ifdef CONFIG_VNC_PNG
+ Buffer png;
+#endif
+ int levels[4];
+ z_stream stream[4];
+} VncTight;
+
+typedef struct VncHextile {
+ VncSendHextileTile *send_tile;
+} VncHextile;
+
+typedef struct VncZlib {
+ Buffer zlib;
+ Buffer tmp;
+ z_stream stream;
+ int level;
+} VncZlib;
+
+typedef struct VncZrle {
+ int type;
+ Buffer fb;
+ Buffer zrle;
+ Buffer tmp;
+ Buffer zlib;
+ z_stream stream;
+ VncPalette palette;
+} VncZrle;
+
+typedef struct VncZywrle {
+ int buf[VNC_ZRLE_TILE_WIDTH * VNC_ZRLE_TILE_HEIGHT];
+} VncZywrle;
+
+#ifdef CONFIG_VNC_THREAD
+struct VncRect
+{
+ int x;
+ int y;
+ int w;
+ int h;
+};
+
+struct VncRectEntry
+{
+ struct VncRect rect;
+ QLIST_ENTRY(VncRectEntry) next;
+};
+
+struct VncJob
+{
+ VncState *vs;
+
+ QLIST_HEAD(, VncRectEntry) rectangles;
+ QTAILQ_ENTRY(VncJob) next;
+};
+#else
+struct VncJob
+{
+ VncState *vs;
+ int rectangles;
+ size_t saved_offset;
+};
+#endif
+
struct VncState
{
int csock;
DisplayState *ds;
- uint32_t dirty[VNC_MAX_HEIGHT][VNC_DIRTY_WORDS];
+ DECLARE_BITMAP(dirty[VNC_MAX_HEIGHT], VNC_DIRTY_BITS);
+ uint8_t **lossy_rect; /* Not an Array to avoid costly memcpy in
+ * vnc-jobs-async.c */
VncDisplay *vd;
int need_update;
int major;
int minor;
+ int auth;
char challenge[VNC_AUTH_CHALLENGE_SIZE];
#ifdef CONFIG_VNC_TLS
+ int subauth; /* Used by VeNCrypt */
VncStateTLS tls;
#endif
#ifdef CONFIG_VNC_SASL
uint8_t modifiers_state[256];
QEMUPutLEDEntry *led;
- /* Encoding specific */
-
- /* Tight */
- uint8_t tight_quality;
- uint8_t tight_compression;
- uint8_t tight_pixel24;
- Buffer tight;
- Buffer tight_tmp;
- Buffer tight_zlib;
- Buffer tight_gradient;
-#ifdef CONFIG_VNC_JPEG
- Buffer tight_jpeg;
+ bool abort;
+#ifndef CONFIG_VNC_THREAD
+ VncJob job;
+#else
+ QemuMutex output_mutex;
#endif
- int tight_levels[4];
- z_stream tight_stream[4];
- /* Hextile */
- VncSendHextileTile *send_hextile_tile;
-
- /* Zlib */
- Buffer zlib;
- Buffer zlib_tmp;
- z_stream zlib_stream;
- int zlib_level;
+ /* Encoding specific, if you add something here, don't forget to
+ * update vnc_async_encoding_start()
+ */
+ VncTight tight;
+ VncZlib zlib;
+ VncHextile hextile;
+ VncZrle zrle;
+ VncZywrle zywrle;
Notifier mouse_mode_notifier;
#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
/*****************************************************************************
#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)
#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_ZRLE 9
+#define VNC_FEATURE_ZYWRLE 10
#define VNC_FEATURE_RESIZE_MASK (1 << VNC_FEATURE_RESIZE)
#define VNC_FEATURE_HEXTILE_MASK (1 << VNC_FEATURE_HEXTILE)
#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)
+#define VNC_FEATURE_ZRLE_MASK (1 << VNC_FEATURE_ZRLE)
+#define VNC_FEATURE_ZYWRLE_MASK (1 << VNC_FEATURE_ZYWRLE)
/* Client -> Server message IDs */
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);
void vnc_convert_pixel(VncState *vs, uint8_t *buf, uint32_t v);
+double vnc_update_freq(VncState *vs, int x, int y, int w, int h);
+void vnc_sent_lossy_rect(VncState *vs, int x, int y, int w, int h);
/* Encodings */
+int vnc_send_framebuffer_update(VncState *vs, int x, int y, int w, int h);
+
int vnc_raw_send_framebuffer_update(VncState *vs, int x, int y, int w, int h);
int vnc_hextile_send_framebuffer_update(VncState *vs, int x,
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);
+int vnc_zrle_send_framebuffer_update(VncState *vs, int x, int y, int w, int h);
+int vnc_zywrle_send_framebuffer_update(VncState *vs, int x, int y, int w, int h);
+void vnc_zrle_clear(VncState *vs);
+
#endif /* __QEMU_VNC_H */