Revision 7eac3a87

b/vnc.c
71 71

  
72 72
typedef void VncSendHextileTile(VncState *vs,
73 73
                                int x, int y, int w, int h,
74
                                uint32_t *last_bg,
75
                                uint32_t *last_fg,
74
                                void *last_bg,
75
                                void *last_fg,
76 76
                                int *has_bg, int *has_fg);
77 77

  
78 78
#define VNC_MAX_WIDTH 2048
......
164 164
    VncWritePixels *write_pixels;
165 165
    VncSendHextileTile *send_hextile_tile;
166 166
    int pix_bpp, pix_big_endian;
167
    int red_shift, red_max, red_shift1;
168
    int green_shift, green_max, green_shift1;
169
    int blue_shift, blue_max, blue_shift1;
167
    int client_red_shift, client_red_max, server_red_shift, server_red_max;
168
    int client_green_shift, client_green_max, server_green_shift, server_green_max;
169
    int client_blue_shift, client_blue_max, server_blue_shift, server_blue_max;
170 170

  
171 171
    VncReadEvent *read_handler;
172 172
    size_t read_handler_expect;
......
208 208
static void vnc_update_client(void *opaque);
209 209
static void vnc_client_read(void *opaque);
210 210

  
211
static void vnc_colordepth(DisplayState *ds, int depth);
212

  
211 213
static inline void vnc_set_bit(uint32_t *d, int k)
212 214
{
213 215
    d[k >> 5] |= 1 << (k & 0x1f);
......
330 332
/* slowest but generic code. */
331 333
static void vnc_convert_pixel(VncState *vs, uint8_t *buf, uint32_t v)
332 334
{
333
    unsigned int r, g, b;
334

  
335
    r = (v >> vs->red_shift1) & vs->red_max;
336
    g = (v >> vs->green_shift1) & vs->green_max;
337
    b = (v >> vs->blue_shift1) & vs->blue_max;
338
    v = (r << vs->red_shift) |
339
        (g << vs->green_shift) |
340
        (b << vs->blue_shift);
335
    uint8_t r, g, b;
336

  
337
    r = ((v >> vs->server_red_shift) & vs->server_red_max) * (vs->client_red_max + 1) /
338
        (vs->server_red_max + 1);
339
    g = ((v >> vs->server_green_shift) & vs->server_green_max) * (vs->client_green_max + 1) /
340
        (vs->server_green_max + 1);
341
    b = ((v >> vs->server_blue_shift) & vs->server_blue_max) * (vs->client_blue_max + 1) /
342
        (vs->server_blue_max + 1);
343
    v = (r << vs->client_red_shift) |
344
        (g << vs->client_green_shift) |
345
        (b << vs->client_blue_shift);
341 346
    switch(vs->pix_bpp) {
342 347
    case 1:
343 348
        buf[0] = v;
......
370 375

  
371 376
static void vnc_write_pixels_generic(VncState *vs, void *pixels1, int size)
372 377
{
373
    uint32_t *pixels = pixels1;
374 378
    uint8_t buf[4];
375
    int n, i;
376 379

  
377
    n = size >> 2;
378
    for(i = 0; i < n; i++) {
379
        vnc_convert_pixel(vs, buf, pixels[i]);
380
        vnc_write(vs, buf, vs->pix_bpp);
380
    if (vs->depth == 4) {
381
        uint32_t *pixels = pixels1;
382
        int n, i;
383
        n = size >> 2;
384
        for(i = 0; i < n; i++) {
385
            vnc_convert_pixel(vs, buf, pixels[i]);
386
            vnc_write(vs, buf, vs->pix_bpp);
387
        }
388
    } else if (vs->depth == 2) {
389
        uint16_t *pixels = pixels1;
390
        int n, i;
391
        n = size >> 1;
392
        for(i = 0; i < n; i++) {
393
            vnc_convert_pixel(vs, buf, pixels[i]);
394
            vnc_write(vs, buf, vs->pix_bpp);
395
        }
396
    } else if (vs->depth == 1) {
397
        uint8_t *pixels = pixels1;
398
        int n, i;
399
        n = size;
400
        for(i = 0; i < n; i++) {
401
            vnc_convert_pixel(vs, buf, pixels[i]);
402
            vnc_write(vs, buf, vs->pix_bpp);
403
        }
404
    } else {
405
        fprintf(stderr, "vnc_write_pixels_generic: VncState color depth not supported\n");
381 406
    }
382 407
}
383 408

  
......
414 439
#undef BPP
415 440

  
416 441
#define GENERIC
442
#define BPP 8
443
#include "vnchextile.h"
444
#undef BPP
445
#undef GENERIC
446

  
447
#define GENERIC
448
#define BPP 16
449
#include "vnchextile.h"
450
#undef BPP
451
#undef GENERIC
452

  
453
#define GENERIC
417 454
#define BPP 32
418 455
#include "vnchextile.h"
419 456
#undef BPP
......
423 460
{
424 461
    int i, j;
425 462
    int has_fg, has_bg;
426
    uint32_t last_fg32, last_bg32;
463
    uint8_t *last_fg, *last_bg;
427 464

  
428 465
    vnc_framebuffer_update(vs, x, y, w, h, 5);
429 466

  
467
    last_fg = (uint8_t *) malloc(vs->depth);
468
    last_bg = (uint8_t *) malloc(vs->depth);
430 469
    has_fg = has_bg = 0;
431 470
    for (j = y; j < (y + h); j += 16) {
432 471
	for (i = x; i < (x + w); i += 16) {
433 472
            vs->send_hextile_tile(vs, i, j,
434 473
                                  MIN(16, x + w - i), MIN(16, y + h - j),
435
                                  &last_bg32, &last_fg32, &has_bg, &has_fg);
474
                                  last_bg, last_fg, &has_bg, &has_fg);
436 475
	}
437 476
    }
477
    free(last_fg);
478
    free(last_bg);
479

  
438 480
}
439 481

  
440 482
static void send_framebuffer_update(VncState *vs, int x, int y, int w, int h)
......
1133 1175
    check_pointer_type_change(vs, kbd_mouse_is_absolute());
1134 1176
}
1135 1177

  
1136
static int compute_nbits(unsigned int val)
1137
{
1138
    int n;
1139
    n = 0;
1140
    while (val != 0) {
1141
        n++;
1142
        val >>= 1;
1143
    }
1144
    return n;
1145
}
1146

  
1147 1178
static void set_pixel_format(VncState *vs,
1148 1179
			     int bits_per_pixel, int depth,
1149 1180
			     int big_endian_flag, int true_color_flag,
......
1163 1194
        return;
1164 1195
    }
1165 1196
    if (bits_per_pixel == 32 &&
1197
        bits_per_pixel == vs->depth * 8 &&
1166 1198
        host_big_endian_flag == big_endian_flag &&
1167 1199
        red_max == 0xff && green_max == 0xff && blue_max == 0xff &&
1168 1200
        red_shift == 16 && green_shift == 8 && blue_shift == 0) {
......
1171 1203
        vs->send_hextile_tile = send_hextile_tile_32;
1172 1204
    } else
1173 1205
    if (bits_per_pixel == 16 &&
1206
        bits_per_pixel == vs->depth * 8 && 
1174 1207
        host_big_endian_flag == big_endian_flag &&
1175 1208
        red_max == 31 && green_max == 63 && blue_max == 31 &&
1176 1209
        red_shift == 11 && green_shift == 5 && blue_shift == 0) {
......
1179 1212
        vs->send_hextile_tile = send_hextile_tile_16;
1180 1213
    } else
1181 1214
    if (bits_per_pixel == 8 &&
1215
        bits_per_pixel == vs->depth * 8 &&
1182 1216
        red_max == 7 && green_max == 7 && blue_max == 3 &&
1183 1217
        red_shift == 5 && green_shift == 2 && blue_shift == 0) {
1184 1218
        vs->depth = 1;
......
1191 1225
            bits_per_pixel != 16 &&
1192 1226
            bits_per_pixel != 32)
1193 1227
            goto fail;
1194
        vs->depth = 4;
1195
        vs->red_shift = red_shift;
1196
        vs->red_max = red_max;
1197
        vs->red_shift1 = 24 - compute_nbits(red_max);
1198
        vs->green_shift = green_shift;
1199
        vs->green_max = green_max;
1200
        vs->green_shift1 = 16 - compute_nbits(green_max);
1201
        vs->blue_shift = blue_shift;
1202
        vs->blue_max = blue_max;
1203
        vs->blue_shift1 = 8 - compute_nbits(blue_max);
1204
        vs->pix_bpp = bits_per_pixel / 8;
1228
        if (vs->depth == 4) {
1229
            vs->send_hextile_tile = send_hextile_tile_generic_32;
1230
        } else if (vs->depth == 2) {
1231
           vs->send_hextile_tile = send_hextile_tile_generic_16;
1232
        } else {
1233
            vs->send_hextile_tile = send_hextile_tile_generic_8;
1234
        }
1235

  
1205 1236
        vs->pix_big_endian = big_endian_flag;
1206 1237
        vs->write_pixels = vnc_write_pixels_generic;
1207
        vs->send_hextile_tile = send_hextile_tile_generic;
1208 1238
    }
1209 1239

  
1210
    vnc_dpy_resize(vs->ds, vs->ds->width, vs->ds->height);
1240
    vs->client_red_shift = red_shift;
1241
    vs->client_red_max = red_max;
1242
    vs->client_green_shift = green_shift;
1243
    vs->client_green_max = green_max;
1244
    vs->client_blue_shift = blue_shift;
1245
    vs->client_blue_max = blue_max;
1246
    vs->pix_bpp = bits_per_pixel / 8;
1211 1247

  
1212 1248
    vga_hw_invalidate();
1213 1249
    vga_hw_update();
1214 1250
}
1215 1251

  
1252
static void vnc_colordepth(DisplayState *ds, int depth)
1253
{
1254
    int host_big_endian_flag;
1255
    struct VncState *vs = ds->opaque;
1256

  
1257
    switch (depth) {
1258
        case 24:
1259
            if (ds->depth == 32) return;
1260
            depth = 32;
1261
            break;
1262
        case 15:
1263
        case 8:
1264
        case 0:
1265
            return;
1266
        default:
1267
            break;
1268
    }
1269

  
1270
#ifdef WORDS_BIGENDIAN
1271
    host_big_endian_flag = 1;
1272
#else
1273
    host_big_endian_flag = 0;
1274
#endif   
1275
    
1276
    switch (depth) {
1277
        case 8:
1278
            vs->depth = depth / 8;
1279
            vs->server_red_max = 7;
1280
            vs->server_green_max = 7;
1281
            vs->server_blue_max = 3;
1282
            vs->server_red_shift = 5;
1283
            vs->server_green_shift = 2;
1284
            vs->server_blue_shift = 0;
1285
            break;
1286
        case 16:
1287
            vs->depth = depth / 8;
1288
            vs->server_red_max = 31;
1289
            vs->server_green_max = 63;
1290
            vs->server_blue_max = 31;
1291
            vs->server_red_shift = 11;
1292
            vs->server_green_shift = 5;
1293
            vs->server_blue_shift = 0;
1294
            break;
1295
        case 32:
1296
            vs->depth = 4;
1297
            vs->server_red_max = 255;
1298
            vs->server_green_max = 255;
1299
            vs->server_blue_max = 255;
1300
            vs->server_red_shift = 16;
1301
            vs->server_green_shift = 8;
1302
            vs->server_blue_shift = 0;
1303
            break;
1304
        default:
1305
            return;
1306
    }
1307

  
1308
    if (vs->pix_bpp == 4 && vs->depth == 4 &&
1309
            host_big_endian_flag == vs->pix_big_endian &&
1310
            vs->client_red_max == 0xff && vs->client_green_max == 0xff && vs->client_blue_max == 0xff &&
1311
            vs->client_red_shift == 16 && vs->client_green_shift == 8 && vs->client_blue_shift == 0) {
1312
        vs->write_pixels = vnc_write_pixels_copy;
1313
        vs->send_hextile_tile = send_hextile_tile_32;
1314
    } else if (vs->pix_bpp == 2 && vs->depth == 2 &&
1315
            host_big_endian_flag == vs->pix_big_endian &&
1316
            vs->client_red_max == 31 && vs->client_green_max == 63 && vs->client_blue_max == 31 &&
1317
            vs->client_red_shift == 11 && vs->client_green_shift == 5 && vs->client_blue_shift == 0) {
1318
        vs->write_pixels = vnc_write_pixels_copy;
1319
        vs->send_hextile_tile = send_hextile_tile_16;
1320
    } else if (vs->pix_bpp == 1 && vs->depth == 1 &&
1321
            host_big_endian_flag == vs->pix_big_endian &&
1322
            vs->client_red_max == 7 && vs->client_green_max == 7 && vs->client_blue_max == 3 &&
1323
            vs->client_red_shift == 5 && vs->client_green_shift == 2 && vs->client_blue_shift == 0) {
1324
        vs->write_pixels = vnc_write_pixels_copy;
1325
        vs->send_hextile_tile = send_hextile_tile_8;
1326
    } else {
1327
        if (vs->depth == 4) {
1328
            vs->send_hextile_tile = send_hextile_tile_generic_32;
1329
        } else if (vs->depth == 2) {
1330
            vs->send_hextile_tile = send_hextile_tile_generic_16;
1331
        } else {
1332
            vs->send_hextile_tile = send_hextile_tile_generic_8;
1333
        }
1334
        vs->write_pixels = vnc_write_pixels_generic;
1335
    }
1336
}
1337

  
1216 1338
static int protocol_client_msg(VncState *vs, uint8_t *data, size_t len)
1217 1339
{
1218 1340
    int i;
......
1316 1438
    vnc_write_u16(vs, vs->ds->height);
1317 1439

  
1318 1440
    vnc_write_u8(vs, vs->depth * 8); /* bits-per-pixel */
1319
    vnc_write_u8(vs, vs->depth * 8); /* depth */
1441
    if (vs->depth == 4) vnc_write_u8(vs, 24); /* depth */
1442
    else vnc_write_u8(vs, vs->depth * 8); /* depth */
1443

  
1320 1444
#ifdef WORDS_BIGENDIAN
1321 1445
    vnc_write_u8(vs, 1);             /* big-endian-flag */
1322 1446
#else
......
2006 2130

  
2007 2131
    vs->lsock = -1;
2008 2132
    vs->csock = -1;
2009
    vs->depth = 4;
2010 2133
    vs->last_x = -1;
2011 2134
    vs->last_y = -1;
2012 2135

  
......
2027 2150
    vs->ds->dpy_resize = vnc_dpy_resize;
2028 2151
    vs->ds->dpy_refresh = NULL;
2029 2152

  
2153
    vnc_colordepth(vs->ds, 32);
2030 2154
    vnc_dpy_resize(vs->ds, 640, 400);
2031 2155
}
2032 2156

  
b/vnchextile.h
2 2
#define CONCAT(a, b) CONCAT_I(a, b)
3 3
#define pixel_t CONCAT(uint, CONCAT(BPP, _t))
4 4
#ifdef GENERIC
5
#define NAME generic
5
#define NAME CONCAT(generic_, BPP)
6 6
#else
7 7
#define NAME BPP
8 8
#endif
9 9

  
10 10
static void CONCAT(send_hextile_tile_, NAME)(VncState *vs,
11 11
                                             int x, int y, int w, int h,
12
                                             uint32_t *last_bg32,
13
                                             uint32_t *last_fg32,
12
                                             void *last_bg_,
13
                                             void *last_fg_,
14 14
                                             int *has_bg, int *has_fg)
15 15
{
16 16
    uint8_t *row = (vs->ds->data + y * vs->ds->linesize + x * vs->depth);
17 17
    pixel_t *irow = (pixel_t *)row;
18 18
    int j, i;
19
    pixel_t *last_bg = (pixel_t *)last_bg32;
20
    pixel_t *last_fg = (pixel_t *)last_fg32;
19
    pixel_t *last_bg = (pixel_t *)last_bg_;
20
    pixel_t *last_fg = (pixel_t *)last_fg_;
21 21
    pixel_t bg = 0;
22 22
    pixel_t fg = 0;
23 23
    int n_colors = 0;
24 24
    int bg_count = 0;
25 25
    int fg_count = 0;
26 26
    int flags = 0;
27
    uint8_t data[(sizeof(pixel_t) + 2) * 16 * 16];
27
    uint8_t data[(vs->pix_bpp + 2) * 16 * 16];
28 28
    int n_data = 0;
29 29
    int n_subtiles = 0;
30 30

  

Also available in: Unified diff