Add qemu 2.4.0
[kvmfornfv.git] / qemu / ui / vnc-enc-hextile-template.h
diff --git a/qemu/ui/vnc-enc-hextile-template.h b/qemu/ui/vnc-enc-hextile-template.h
new file mode 100644 (file)
index 0000000..d868d75
--- /dev/null
@@ -0,0 +1,211 @@
+#define CONCAT_I(a, b) a ## b
+#define CONCAT(a, b) CONCAT_I(a, b)
+#define pixel_t CONCAT(uint, CONCAT(BPP, _t))
+#ifdef GENERIC
+#define NAME CONCAT(generic_, BPP)
+#else
+#define NAME BPP
+#endif
+
+static void CONCAT(send_hextile_tile_, NAME)(VncState *vs,
+                                             int x, int y, int w, int h,
+                                             void *last_bg_,
+                                             void *last_fg_,
+                                             int *has_bg, int *has_fg)
+{
+    VncDisplay *vd = vs->vd;
+    uint8_t *row = vnc_server_fb_ptr(vd, x, y);
+    pixel_t *irow = (pixel_t *)row;
+    int j, i;
+    pixel_t *last_bg = (pixel_t *)last_bg_;
+    pixel_t *last_fg = (pixel_t *)last_fg_;
+    pixel_t bg = 0;
+    pixel_t fg = 0;
+    int n_colors = 0;
+    int bg_count = 0;
+    int fg_count = 0;
+    int flags = 0;
+    uint8_t data[(vs->client_pf.bytes_per_pixel + 2) * 16 * 16];
+    int n_data = 0;
+    int n_subtiles = 0;
+
+    for (j = 0; j < h; j++) {
+       for (i = 0; i < w; i++) {
+           switch (n_colors) {
+           case 0:
+               bg = irow[i];
+               n_colors = 1;
+               break;
+           case 1:
+               if (irow[i] != bg) {
+                   fg = irow[i];
+                   n_colors = 2;
+               }
+               break;
+           case 2:
+               if (irow[i] != bg && irow[i] != fg) {
+                   n_colors = 3;
+               } else {
+                   if (irow[i] == bg)
+                       bg_count++;
+                   else if (irow[i] == fg)
+                       fg_count++;
+               }
+               break;
+           default:
+               break;
+           }
+       }
+       if (n_colors > 2)
+           break;
+       irow += vnc_server_fb_stride(vd) / sizeof(pixel_t);
+    }
+
+    if (n_colors > 1 && fg_count > bg_count) {
+       pixel_t tmp = fg;
+       fg = bg;
+       bg = tmp;
+    }
+
+    if (!*has_bg || *last_bg != bg) {
+       flags |= 0x02;
+       *has_bg = 1;
+       *last_bg = bg;
+    }
+
+    if (n_colors < 3 && (!*has_fg || *last_fg != fg)) {
+       flags |= 0x04;
+       *has_fg = 1;
+       *last_fg = fg;
+    }
+
+    switch (n_colors) {
+    case 1:
+       n_data = 0;
+       break;
+    case 2:
+       flags |= 0x08;
+
+       irow = (pixel_t *)row;
+
+       for (j = 0; j < h; j++) {
+           int min_x = -1;
+           for (i = 0; i < w; i++) {
+               if (irow[i] == fg) {
+                   if (min_x == -1)
+                       min_x = i;
+               } else if (min_x != -1) {
+                   hextile_enc_cord(data + n_data, min_x, j, i - min_x, 1);
+                   n_data += 2;
+                   n_subtiles++;
+                   min_x = -1;
+               }
+           }
+           if (min_x != -1) {
+               hextile_enc_cord(data + n_data, min_x, j, i - min_x, 1);
+               n_data += 2;
+               n_subtiles++;
+           }
+           irow += vnc_server_fb_stride(vd) / sizeof(pixel_t);
+       }
+       break;
+    case 3:
+       flags |= 0x18;
+
+       irow = (pixel_t *)row;
+
+       if (!*has_bg || *last_bg != bg)
+           flags |= 0x02;
+
+       for (j = 0; j < h; j++) {
+           int has_color = 0;
+           int min_x = -1;
+           pixel_t color = 0; /* shut up gcc */
+
+           for (i = 0; i < w; i++) {
+               if (!has_color) {
+                   if (irow[i] == bg)
+                       continue;
+                   color = irow[i];
+                   min_x = i;
+                   has_color = 1;
+               } else if (irow[i] != color) {
+                   has_color = 0;
+#ifdef GENERIC
+                    vnc_convert_pixel(vs, data + n_data, color);
+                    n_data += vs->client_pf.bytes_per_pixel;
+#else
+                   memcpy(data + n_data, &color, sizeof(color));
+                    n_data += sizeof(pixel_t);
+#endif
+                   hextile_enc_cord(data + n_data, min_x, j, i - min_x, 1);
+                   n_data += 2;
+                   n_subtiles++;
+
+                   min_x = -1;
+                   if (irow[i] != bg) {
+                       color = irow[i];
+                       min_x = i;
+                       has_color = 1;
+                   }
+               }
+           }
+           if (has_color) {
+#ifdef GENERIC
+                vnc_convert_pixel(vs, data + n_data, color);
+                n_data += vs->client_pf.bytes_per_pixel;
+#else
+                memcpy(data + n_data, &color, sizeof(color));
+                n_data += sizeof(pixel_t);
+#endif
+               hextile_enc_cord(data + n_data, min_x, j, i - min_x, 1);
+               n_data += 2;
+               n_subtiles++;
+           }
+           irow += vnc_server_fb_stride(vd) / sizeof(pixel_t);
+       }
+
+       /* A SubrectsColoured subtile invalidates the foreground color */
+       *has_fg = 0;
+       if (n_data > (w * h * sizeof(pixel_t))) {
+           n_colors = 4;
+           flags = 0x01;
+           *has_bg = 0;
+
+           /* we really don't have to invalidate either the bg or fg
+              but we've lost the old values.  oh well. */
+       }
+        break;
+    default:
+       break;
+    }
+
+    if (n_colors > 3) {
+       flags = 0x01;
+       *has_fg = 0;
+       *has_bg = 0;
+       n_colors = 4;
+    }
+
+    vnc_write_u8(vs, flags);
+    if (n_colors < 4) {
+       if (flags & 0x02)
+           vs->write_pixels(vs, last_bg, sizeof(pixel_t));
+       if (flags & 0x04)
+           vs->write_pixels(vs, last_fg, sizeof(pixel_t));
+       if (n_subtiles) {
+           vnc_write_u8(vs, n_subtiles);
+           vnc_write(vs, data, n_data);
+       }
+    } else {
+       for (j = 0; j < h; j++) {
+           vs->write_pixels(vs, row, w * 4);
+           row += vnc_server_fb_stride(vd);
+       }
+    }
+}
+
+#undef NAME
+#undef pixel_t
+#undef CONCAT_I
+#undef CONCAT