Revision 3512779a vnc.c

b/vnc.c
42 42

  
43 43
typedef int VncReadEvent(VncState *vs, char *data, size_t len);
44 44

  
45
typedef void VncWritePixels(VncState *vs, void *data, int size);
46

  
47
typedef void VncSendHextileTile(VncState *vs,
48
                                int x, int y, int w, int h,
49
                                uint32_t *last_bg, 
50
                                uint32_t *last_fg,
51
                                int *has_bg, int *has_fg);
52

  
45 53
struct VncState
46 54
{
47 55
    QEMUTimer *timer;
......
53 61
    int height;
54 62
    uint64_t dirty_row[768];
55 63
    char *old_data;
56
    int depth;
64
    int depth; /* internal VNC frame buffer byte per pixel */
57 65
    int has_resize;
58 66
    int has_hextile;
59 67
    Buffer output;
60 68
    Buffer input;
61 69
    kbd_layout_t *kbd_layout;
70
    /* current output mode information */
71
    VncWritePixels *write_pixels;
72
    VncSendHextileTile *send_hextile_tile;
73
    int pix_bpp, pix_big_endian;
74
    int red_shift, red_max, red_shift1;
75
    int green_shift, green_max, green_shift1;
76
    int blue_shift, blue_max, blue_shift1;
62 77

  
63 78
    VncReadEvent *read_handler;
64 79
    size_t read_handler_expect;
......
130 145
    }
131 146
}
132 147

  
148
/* fastest code */
149
static void vnc_write_pixels_copy(VncState *vs, void *pixels, int size)
150
{
151
    vnc_write(vs, pixels, size);
152
}
153

  
154
/* slowest but generic code. */
155
static void vnc_convert_pixel(VncState *vs, uint8_t *buf, uint32_t v)
156
{
157
    unsigned int r, g, b;
158

  
159
    r = (v >> vs->red_shift1) & vs->red_max;
160
    g = (v >> vs->green_shift1) & vs->green_max;
161
    b = (v >> vs->blue_shift1) & vs->blue_max;
162
    v = (r << vs->red_shift) | 
163
        (g << vs->green_shift) | 
164
        (b << vs->blue_shift);
165
    switch(vs->pix_bpp) {
166
    case 1:
167
        buf[0] = v;
168
        break;
169
    case 2:
170
        if (vs->pix_big_endian) {
171
            buf[0] = v >> 8;
172
            buf[1] = v;
173
        } else {
174
            buf[1] = v >> 8;
175
            buf[0] = v;
176
        }
177
        break;
178
    default:
179
    case 4:
180
        if (vs->pix_big_endian) {
181
            buf[0] = v >> 24;
182
            buf[1] = v >> 16;
183
            buf[2] = v >> 8;
184
            buf[3] = v;
185
        } else {
186
            buf[3] = v >> 24;
187
            buf[2] = v >> 16;
188
            buf[1] = v >> 8;
189
            buf[0] = v;
190
        }
191
        break;
192
    }
193
}
194

  
195
static void vnc_write_pixels_generic(VncState *vs, void *pixels1, int size)
196
{
197
    uint32_t *pixels = pixels1;
198
    uint8_t buf[4];
199
    int n, i;
200

  
201
    n = size >> 2;
202
    for(i = 0; i < n; i++) {
203
        vnc_convert_pixel(vs, buf, pixels[i]);
204
        vnc_write(vs, buf, vs->pix_bpp);
205
    }
206
}
207

  
133 208
static void send_framebuffer_update_raw(VncState *vs, int x, int y, int w, int h)
134 209
{
135 210
    int i;
......
139 214

  
140 215
    row = vs->ds->data + y * vs->ds->linesize + x * vs->depth;
141 216
    for (i = 0; i < h; i++) {
142
	vnc_write(vs, row, w * vs->depth);
217
	vs->write_pixels(vs, row, w * vs->depth);
143 218
	row += vs->ds->linesize;
144 219
    }
145 220
}
......
162 237
#include "vnchextile.h"
163 238
#undef BPP
164 239

  
240
#define GENERIC
241
#define BPP 32
242
#include "vnchextile.h"
243
#undef BPP
244
#undef GENERIC
245

  
165 246
static void send_framebuffer_update_hextile(VncState *vs, int x, int y, int w, int h)
166 247
{
167 248
    int i, j;
168 249
    int has_fg, has_bg;
169 250
    uint32_t last_fg32, last_bg32;
170
    uint16_t last_fg16, last_bg16;
171
    uint8_t last_fg8, last_bg8;
172 251

  
173 252
    vnc_framebuffer_update(vs, x, y, w, h, 5);
174 253

  
175 254
    has_fg = has_bg = 0;
176 255
    for (j = y; j < (y + h); j += 16) {
177 256
	for (i = x; i < (x + w); i += 16) {
178
	    switch (vs->depth) {
179
	    case 1:
180
		send_hextile_tile_8(vs, i, j, MIN(16, x + w - i), MIN(16, y + h - j),
181
				    &last_bg8, &last_fg8, &has_bg, &has_fg);
182
		break;
183
	    case 2:
184
		send_hextile_tile_16(vs, i, j, MIN(16, x + w - i), MIN(16, y + h - j),
185
				     &last_bg16, &last_fg16, &has_bg, &has_fg);
186
		break;
187
	    case 4:
188
		send_hextile_tile_32(vs, i, j, MIN(16, x + w - i), MIN(16, y + h - j),
189
				     &last_bg32, &last_fg32, &has_bg, &has_fg);
190
		break;
191
	    default:
192
		break;
193
	    }
257
            vs->send_hextile_tile(vs, i, j, 
258
                                  MIN(16, x + w - i), MIN(16, y + h - j),
259
                                  &last_bg32, &last_fg32, &has_bg, &has_fg);
194 260
	}
195 261
    }
196 262
}
......
660 726
    }
661 727
}
662 728

  
729
static int compute_nbits(unsigned int val)
730
{
731
    int n;
732
    n = 0;
733
    while (val != 0) {
734
        n++;
735
        val >>= 1;
736
    }
737
    return n;
738
}
739

  
663 740
static void set_pixel_format(VncState *vs,
664 741
			     int bits_per_pixel, int depth,
665 742
			     int big_endian_flag, int true_color_flag,
666 743
			     int red_max, int green_max, int blue_max,
667 744
			     int red_shift, int green_shift, int blue_shift)
668 745
{
669
    switch (bits_per_pixel) {
670
    case 32:
671
    case 24:
672
	vs->depth = 4;
673
	break;
674
    case 16:
675
	vs->depth = 2;
676
	break;
677
    case 8:
678
	vs->depth = 1;
679
	break;
680
    default:
746
    int host_big_endian_flag;
747

  
748
#ifdef WORDS_BIGENDIAN
749
    host_big_endian_flag = 1;
750
#else
751
    host_big_endian_flag = 0;
752
#endif
753
    if (!true_color_flag) {
754
    fail:
681 755
	vnc_client_error(vs);
682
	break;
756
        return;
757
    }
758
    if (bits_per_pixel == 32 && 
759
        host_big_endian_flag == big_endian_flag &&
760
        red_max == 0xff && green_max == 0xff && blue_max == 0xff &&
761
        red_shift == 16 && green_shift == 8 && blue_shift == 0) {
762
        vs->depth = 4;
763
        vs->write_pixels = vnc_write_pixels_copy;
764
        vs->send_hextile_tile = send_hextile_tile_32;
765
    } else 
766
    if (bits_per_pixel == 16 && 
767
        host_big_endian_flag == big_endian_flag &&
768
        red_max == 31 && green_max == 63 && blue_max == 31 &&
769
        red_shift == 11 && green_shift == 5 && blue_shift == 0) {
770
        vs->depth = 2;
771
        vs->write_pixels = vnc_write_pixels_copy;
772
        vs->send_hextile_tile = send_hextile_tile_16;
773
    } else 
774
    if (bits_per_pixel == 8 && 
775
        red_max == 7 && green_max == 7 && blue_max == 3 &&
776
        red_shift == 5 && green_shift == 2 && blue_shift == 0) {
777
        vs->depth = 1;
778
        vs->write_pixels = vnc_write_pixels_copy;
779
        vs->send_hextile_tile = send_hextile_tile_8;
780
    } else 
781
    {
782
        /* generic and slower case */
783
        if (bits_per_pixel != 8 &&
784
            bits_per_pixel != 16 &&
785
            bits_per_pixel != 32)
786
            goto fail;
787
        vs->depth = 4;
788
        vs->red_shift = red_shift;
789
        vs->red_max = red_max;
790
        vs->red_shift1 = 24 - compute_nbits(red_max);
791
        vs->green_shift = green_shift;
792
        vs->green_max = green_max;
793
        vs->green_shift1 = 16 - compute_nbits(green_max);
794
        vs->blue_shift = blue_shift;
795
        vs->blue_max = blue_max;
796
        vs->blue_shift1 = 8 - compute_nbits(blue_max);
797
        vs->pix_bpp = bits_per_pixel / 8;
798
        vs->pix_big_endian = big_endian_flag;
799
        vs->write_pixels = vnc_write_pixels_generic;
800
        vs->send_hextile_tile = send_hextile_tile_generic;
683 801
    }
684

  
685
    if (!true_color_flag)
686
	vnc_client_error(vs);
687 802

  
688 803
    vnc_dpy_resize(vs->ds, vs->ds->width, vs->ds->height);
689 804
    memset(vs->dirty_row, 0xFF, sizeof(vs->dirty_row));
......
774 889

  
775 890
    vnc_write_u8(vs, vs->depth * 8); /* bits-per-pixel */
776 891
    vnc_write_u8(vs, vs->depth * 8); /* depth */
892
#ifdef WORDS_BIGENDIAN
893
    vnc_write_u8(vs, 1);             /* big-endian-flag */
894
#else
777 895
    vnc_write_u8(vs, 0);             /* big-endian-flag */
896
#endif
778 897
    vnc_write_u8(vs, 1);             /* true-color-flag */
779 898
    if (vs->depth == 4) {
780 899
	vnc_write_u16(vs, 0xFF);     /* red-max */
......
783 902
	vnc_write_u8(vs, 16);        /* red-shift */
784 903
	vnc_write_u8(vs, 8);         /* green-shift */
785 904
	vnc_write_u8(vs, 0);         /* blue-shift */
905
        vs->send_hextile_tile = send_hextile_tile_32;
786 906
    } else if (vs->depth == 2) {
787 907
	vnc_write_u16(vs, 31);       /* red-max */
788 908
	vnc_write_u16(vs, 63);       /* green-max */
......
790 910
	vnc_write_u8(vs, 11);        /* red-shift */
791 911
	vnc_write_u8(vs, 5);         /* green-shift */
792 912
	vnc_write_u8(vs, 0);         /* blue-shift */
913
        vs->send_hextile_tile = send_hextile_tile_16;
793 914
    } else if (vs->depth == 1) {
794
	vnc_write_u16(vs, 3);        /* red-max */
915
        /* XXX: change QEMU pixel 8 bit pixel format to match the VNC one ? */
916
	vnc_write_u16(vs, 7);        /* red-max */
795 917
	vnc_write_u16(vs, 7);        /* green-max */
796 918
	vnc_write_u16(vs, 3);        /* blue-max */
797 919
	vnc_write_u8(vs, 5);         /* red-shift */
798 920
	vnc_write_u8(vs, 2);         /* green-shift */
799 921
	vnc_write_u8(vs, 0);         /* blue-shift */
922
        vs->send_hextile_tile = send_hextile_tile_8;
800 923
    }
924
    vs->write_pixels = vnc_write_pixels_copy;
801 925
	
802 926
    vnc_write(vs, pad, 3);           /* padding */
803 927

  

Also available in: Unified diff