Revision 1fc62412

b/vnc.c
215 215
   3) resolutions > 1024
216 216
*/
217 217

  
218
static void vnc_update_client(VncState *vs);
218
static void vnc_update_client(VncState *vs, int has_dirty);
219 219
static void vnc_disconnect_start(VncState *vs);
220 220
static void vnc_disconnect_finish(VncState *vs);
221 221
static void vnc_init_timer(VncDisplay *vd);
222 222
static void vnc_remove_timer(VncDisplay *vd);
223 223

  
224 224
static void vnc_colordepth(VncState *vs);
225
static void framebuffer_update_request(VncState *vs, int incremental,
226
                                       int x_position, int y_position,
227
                                       int w, int h);
228
static void vnc_refresh(void *opaque);
229
static int vnc_refresh_server_surface(VncDisplay *vd);
225 230

  
226 231
static inline void vnc_set_bit(uint32_t *d, int k)
227 232
{
......
264 269
    return 0;
265 270
}
266 271

  
267
static void vnc_update(VncState *vs, int x, int y, int w, int h)
272
static void vnc_dpy_update(DisplayState *ds, int x, int y, int w, int h)
268 273
{
269
    struct VncSurface *s = &vs->guest;
270 274
    int i;
275
    VncDisplay *vd = ds->opaque;
276
    struct VncSurface *s = &vd->guest;
271 277

  
272 278
    h += y;
273 279

  
......
288 294
            vnc_set_bit(s->dirty[y], (x + i) / 16);
289 295
}
290 296

  
291
static void vnc_dpy_update(DisplayState *ds, int x, int y, int w, int h)
292
{
293
    VncDisplay *vd = ds->opaque;
294
    VncState *vs = vd->clients;
295
    while (vs != NULL) {
296
        vnc_update(vs, x, y, w, h);
297
        vs = vs->next;
298
    }
299
}
300

  
301 297
static void vnc_framebuffer_update(VncState *vs, int x, int y, int w, int h,
302 298
                                   int32_t encoding)
303 299
{
......
342 338
    buffer->offset += len;
343 339
}
344 340

  
345
static void vnc_resize(VncState *vs)
341
static void vnc_dpy_resize(DisplayState *ds)
346 342
{
347
    DisplayState *ds = vs->ds;
348 343
    int size_changed;
344
    VncDisplay *vd = ds->opaque;
345
    VncState *vs = vd->clients;
346

  
347
    /* server surface */
348
    if (!vd->server)
349
        vd->server = qemu_mallocz(sizeof(*vd->server));
350
    if (vd->server->data)
351
        qemu_free(vd->server->data);
352
    *(vd->server) = *(ds->surface);
353
    vd->server->data = qemu_mallocz(vd->server->linesize *
354
                                    vd->server->height);
349 355

  
350 356
    /* guest surface */
351
    if (!vs->guest.ds)
352
        vs->guest.ds = qemu_mallocz(sizeof(*vs->guest.ds));
353
    if (ds_get_bytes_per_pixel(ds) != vs->guest.ds->pf.bytes_per_pixel)
357
    if (!vd->guest.ds)
358
        vd->guest.ds = qemu_mallocz(sizeof(*vd->guest.ds));
359
    if (ds_get_bytes_per_pixel(ds) != vd->guest.ds->pf.bytes_per_pixel)
354 360
        console_color_init(ds);
355
    vnc_colordepth(vs);
356
    size_changed = ds_get_width(ds) != vs->guest.ds->width ||
357
                   ds_get_height(ds) != vs->guest.ds->height;
358
    *(vs->guest.ds) = *(ds->surface);
359
    if (size_changed) {
360
        if (vs->csock != -1 && vnc_has_feature(vs, VNC_FEATURE_RESIZE)) {
361
            vnc_write_u8(vs, 0);  /* msg id */
362
            vnc_write_u8(vs, 0);
363
            vnc_write_u16(vs, 1); /* number of rects */
364
            vnc_framebuffer_update(vs, 0, 0, ds_get_width(ds), ds_get_height(ds),
365
                                   VNC_ENCODING_DESKTOPRESIZE);
366
            vnc_flush(vs);
367
        }
368
    }
369
    memset(vs->guest.dirty, 0xFF, sizeof(vs->guest.dirty));
361
    size_changed = ds_get_width(ds) != vd->guest.ds->width ||
362
                   ds_get_height(ds) != vd->guest.ds->height;
363
    *(vd->guest.ds) = *(ds->surface);
364
    memset(vd->guest.dirty, 0xFF, sizeof(vd->guest.dirty));
370 365

  
371
    /* server surface */
372
    if (!vs->server.ds)
373
        vs->server.ds = qemu_mallocz(sizeof(*vs->server.ds));
374
    if (vs->server.ds->data)
375
        qemu_free(vs->server.ds->data);
376
    *(vs->server.ds) = *(ds->surface);
377
    vs->server.ds->data = qemu_mallocz(vs->server.ds->linesize *
378
                                       vs->server.ds->height);
379
    memset(vs->server.dirty, 0xFF, sizeof(vs->guest.dirty));
380
}
381

  
382
static void vnc_dpy_resize(DisplayState *ds)
383
{
384
    VncDisplay *vd = ds->opaque;
385
    VncState *vs = vd->clients;
386 366
    while (vs != NULL) {
387
        vnc_resize(vs);
367
        vnc_colordepth(vs);
368
        if (size_changed) {
369
            if (vs->csock != -1 && vnc_has_feature(vs, VNC_FEATURE_RESIZE)) {
370
                vnc_write_u8(vs, 0);  /* msg id */
371
                vnc_write_u8(vs, 0);
372
                vnc_write_u16(vs, 1); /* number of rects */
373
                vnc_framebuffer_update(vs, 0, 0, ds_get_width(ds), ds_get_height(ds),
374
                        VNC_ENCODING_DESKTOPRESIZE);
375
                vnc_flush(vs);
376
            }
377
        }
378
        memset(vs->dirty, 0xFF, sizeof(vs->dirty));
388 379
        vs = vs->next;
389 380
    }
390 381
}
......
399 390
static void vnc_convert_pixel(VncState *vs, uint8_t *buf, uint32_t v)
400 391
{
401 392
    uint8_t r, g, b;
402

  
403
    r = ((((v & vs->server.ds->pf.rmask) >> vs->server.ds->pf.rshift) << vs->clientds.pf.rbits) >>
404
        vs->server.ds->pf.rbits);
405
    g = ((((v & vs->server.ds->pf.gmask) >> vs->server.ds->pf.gshift) << vs->clientds.pf.gbits) >>
406
        vs->server.ds->pf.gbits);
407
    b = ((((v & vs->server.ds->pf.bmask) >> vs->server.ds->pf.bshift) << vs->clientds.pf.bbits) >>
408
        vs->server.ds->pf.bbits);
393
    VncDisplay *vd = vs->vd;
394

  
395
    r = ((((v & vd->server->pf.rmask) >> vd->server->pf.rshift) << vs->clientds.pf.rbits) >>
396
        vd->server->pf.rbits);
397
    g = ((((v & vd->server->pf.gmask) >> vd->server->pf.gshift) << vs->clientds.pf.gbits) >>
398
        vd->server->pf.gbits);
399
    b = ((((v & vd->server->pf.bmask) >> vd->server->pf.bshift) << vs->clientds.pf.bbits) >>
400
        vd->server->pf.bbits);
409 401
    v = (r << vs->clientds.pf.rshift) |
410 402
        (g << vs->clientds.pf.gshift) |
411 403
        (b << vs->clientds.pf.bshift);
......
442 434
static void vnc_write_pixels_generic(VncState *vs, void *pixels1, int size)
443 435
{
444 436
    uint8_t buf[4];
437
    VncDisplay *vd = vs->vd;
445 438

  
446
    if (vs->server.ds->pf.bytes_per_pixel == 4) {
439
    if (vd->server->pf.bytes_per_pixel == 4) {
447 440
        uint32_t *pixels = pixels1;
448 441
        int n, i;
449 442
        n = size >> 2;
......
451 444
            vnc_convert_pixel(vs, buf, pixels[i]);
452 445
            vnc_write(vs, buf, vs->clientds.pf.bytes_per_pixel);
453 446
        }
454
    } else if (vs->server.ds->pf.bytes_per_pixel == 2) {
447
    } else if (vd->server->pf.bytes_per_pixel == 2) {
455 448
        uint16_t *pixels = pixels1;
456 449
        int n, i;
457 450
        n = size >> 1;
......
459 452
            vnc_convert_pixel(vs, buf, pixels[i]);
460 453
            vnc_write(vs, buf, vs->clientds.pf.bytes_per_pixel);
461 454
        }
462
    } else if (vs->server.ds->pf.bytes_per_pixel == 1) {
455
    } else if (vd->server->pf.bytes_per_pixel == 1) {
463 456
        uint8_t *pixels = pixels1;
464 457
        int n, i;
465 458
        n = size;
......
476 469
{
477 470
    int i;
478 471
    uint8_t *row;
472
    VncDisplay *vd = vs->vd;
479 473

  
480
    row = vs->server.ds->data + y * ds_get_linesize(vs->ds) + x * ds_get_bytes_per_pixel(vs->ds);
474
    row = vd->server->data + y * ds_get_linesize(vs->ds) + x * ds_get_bytes_per_pixel(vs->ds);
481 475
    for (i = 0; i < h; i++) {
482 476
        vs->write_pixels(vs, row, w * ds_get_bytes_per_pixel(vs->ds));
483 477
        row += ds_get_linesize(vs->ds);
......
525 519
    int i, j;
526 520
    int has_fg, has_bg;
527 521
    uint8_t *last_fg, *last_bg;
522
    VncDisplay *vd = vs->vd;
528 523

  
529
    last_fg = (uint8_t *) qemu_malloc(vs->server.ds->pf.bytes_per_pixel);
530
    last_bg = (uint8_t *) qemu_malloc(vs->server.ds->pf.bytes_per_pixel);
524
    last_fg = (uint8_t *) qemu_malloc(vd->server->pf.bytes_per_pixel);
525
    last_bg = (uint8_t *) qemu_malloc(vd->server->pf.bytes_per_pixel);
531 526
    has_fg = has_bg = 0;
532 527
    for (j = y; j < (y + h); j += 16) {
533 528
        for (i = x; i < (x + w); i += 16) {
......
656 651

  
657 652
static void vnc_copy(VncState *vs, int src_x, int src_y, int dst_x, int dst_y, int w, int h)
658 653
{
659
    uint8_t *src_row;
660
    uint8_t *dst_row;
661
    int y,pitch,depth;
662

  
663 654
    /* send bitblit op to the vnc client */
664 655
    vnc_write_u8(vs, 0);  /* msg id */
665 656
    vnc_write_u8(vs, 0);
......
668 659
    vnc_write_u16(vs, src_x);
669 660
    vnc_write_u16(vs, src_y);
670 661
    vnc_flush(vs);
671

  
672
    /* do bitblit op on the local surface too */
673
    pitch = ds_get_linesize(vs->ds);
674
    depth = ds_get_bytes_per_pixel(vs->ds);
675
    src_row = vs->server.ds->data + pitch * src_y + depth * src_x;
676
    dst_row = vs->server.ds->data + pitch * dst_y + depth * dst_x;
677
    if (dst_y > src_y) {
678
        /* copy backwards */
679
        src_row += pitch * (h-1);
680
        dst_row += pitch * (h-1);
681
        pitch = -pitch;
682
    }
683
    for (y = 0; y < h; y++) {
684
        memmove(dst_row, src_row, w * depth);
685
        src_row += pitch;
686
        dst_row += pitch;
687
    }
688 662
}
689 663

  
690 664
static void vnc_dpy_copy(DisplayState *ds, int src_x, int src_y, int dst_x, int dst_y, int w, int h)
691 665
{
692 666
    VncDisplay *vd = ds->opaque;
693 667
    VncState *vs, *vn;
668
    uint8_t *src_row;
669
    uint8_t *dst_row;
670
    int i,x,y,pitch,depth,inc,w_lim,s;
671
    int cmp_bytes;
694 672

  
673
    vnc_refresh_server_surface(vd);
695 674
    for (vs = vd->clients; vs != NULL; vs = vn) {
696 675
        vn = vs->next;
697 676
        if (vnc_has_feature(vs, VNC_FEATURE_COPYRECT)) {
698 677
            vs->force_update = 1;
699
            vnc_update_client(vs);
678
            vnc_update_client(vs, 1);
700 679
            /* vs might be free()ed here */
701 680
        }
702 681
    }
703 682

  
683
    /* do bitblit op on the local surface too */
684
    pitch = ds_get_linesize(vd->ds);
685
    depth = ds_get_bytes_per_pixel(vd->ds);
686
    src_row = vd->server->data + pitch * src_y + depth * src_x;
687
    dst_row = vd->server->data + pitch * dst_y + depth * dst_x;
688
    y = dst_y;
689
    inc = 1;
690
    if (dst_y > src_y) {
691
        /* copy backwards */
692
        src_row += pitch * (h-1);
693
        dst_row += pitch * (h-1);
694
        pitch = -pitch;
695
        y = dst_y + h - 1;
696
        inc = -1;
697
    }
698
    w_lim = w - (16 - (dst_x % 16));
699
    if (w_lim < 0)
700
        w_lim = w;
701
    else
702
        w_lim = w - (w_lim % 16);
703
    for (i = 0; i < h; i++) {
704
        for (x = 0; x <= w_lim;
705
                x += s, src_row += cmp_bytes, dst_row += cmp_bytes) {
706
            if (x == w_lim) {
707
                if ((s = w - w_lim) == 0)
708
                    break;
709
            } else if (!x) {
710
                s = (16 - (dst_x % 16));
711
                s = MIN(s, w_lim);
712
            } else {
713
                s = 16;
714
            }
715
            cmp_bytes = s * depth;
716
            if (memcmp(src_row, dst_row, cmp_bytes) == 0)
717
                continue;
718
            memmove(dst_row, src_row, cmp_bytes);
719
            vs = vd->clients;
720
            while (vs != NULL) {
721
                if (!vnc_has_feature(vs, VNC_FEATURE_COPYRECT))
722
                    vnc_set_bit(vs->dirty[y], ((x + dst_x) / 16));
723
                vs = vs->next;
724
            }
725
        }
726
        src_row += pitch - w * depth;
727
        dst_row += pitch - w * depth;
728
        y += inc;
729
    }
730

  
704 731
    for (vs = vd->clients; vs != NULL; vs = vs->next) {
705 732
        if (vnc_has_feature(vs, VNC_FEATURE_COPYRECT))
706 733
            vnc_copy(vs, src_x, src_y, dst_x, dst_y, w, h);
707
        else /* TODO */
708
            vnc_update(vs, dst_x, dst_y, w, h);
709 734
    }
710 735
}
711 736

  
712
static int find_and_clear_dirty_height(struct VncSurface *s,
737
static int find_and_clear_dirty_height(struct VncState *vs,
713 738
                                       int y, int last_x, int x)
714 739
{
715 740
    int h;
741
    VncDisplay *vd = vs->vd;
716 742

  
717
    for (h = 1; h < (s->ds->height - y); h++) {
743
    for (h = 1; h < (vd->server->height - y); h++) {
718 744
        int tmp_x;
719
        if (!vnc_get_bit(s->dirty[y + h], last_x))
745
        if (!vnc_get_bit(vs->dirty[y + h], last_x))
720 746
            break;
721 747
        for (tmp_x = last_x; tmp_x < x; tmp_x++)
722
            vnc_clear_bit(s->dirty[y + h], tmp_x);
748
            vnc_clear_bit(vs->dirty[y + h], tmp_x);
723 749
    }
724 750

  
725 751
    return h;
726 752
}
727 753

  
728
static void vnc_update_client(VncState *vs)
754
static void vnc_update_client(VncState *vs, int has_dirty)
729 755
{
730 756
    if (vs->need_update && vs->csock != -1) {
757
        VncDisplay *vd = vs->vd;
731 758
        int y;
732
        uint8_t *guest_row;
733
        uint8_t *server_row;
734
        int cmp_bytes;
735
        uint32_t width_mask[VNC_DIRTY_WORDS];
736 759
        int n_rectangles;
737 760
        int saved_offset;
738
        int has_dirty = 0;
739 761

  
740 762
        if (vs->output.offset && !vs->audio_cap && !vs->force_update)
741 763
            /* kernel send buffers are full -> drop frames to throttle */
742 764
            return;
743 765

  
744
        /*
745
         * Walk through the guest dirty map.
746
         * Check and copy modified bits from guest to server surface.
747
         * Update server dirty map.
748
         */
749
        vnc_set_bits(width_mask, (ds_get_width(vs->ds) / 16), VNC_DIRTY_WORDS);
750
        cmp_bytes = 16 * ds_get_bytes_per_pixel(vs->ds);
751
        guest_row  = vs->guest.ds->data;
752
        server_row = vs->server.ds->data;
753
        for (y = 0; y < vs->guest.ds->height; y++) {
754
            if (vnc_and_bits(vs->guest.dirty[y], width_mask, VNC_DIRTY_WORDS)) {
755
                int x;
756
                uint8_t *guest_ptr;
757
                uint8_t *server_ptr;
758

  
759
                guest_ptr  = guest_row;
760
                server_ptr = server_row;
761

  
762
                for (x = 0; x < vs->guest.ds->width;
763
                     x += 16, guest_ptr += cmp_bytes, server_ptr += cmp_bytes) {
764
                    if (!vnc_get_bit(vs->guest.dirty[y], (x / 16)))
765
                        continue;
766
                    vnc_clear_bit(vs->guest.dirty[y], (x / 16));
767
                    if (memcmp(server_ptr, guest_ptr, cmp_bytes) == 0)
768
                        continue;
769
                    memcpy(server_ptr, guest_ptr, cmp_bytes);
770
                    vnc_set_bit(vs->server.dirty[y], (x / 16));
771
                    has_dirty++;
772
                }
773
            }
774
            guest_row  += ds_get_linesize(vs->ds);
775
            server_row += ds_get_linesize(vs->ds);
776
        }
777

  
778 766
        if (!has_dirty && !vs->audio_cap && !vs->force_update)
779 767
            return;
780 768

  
......
790 778
        saved_offset = vs->output.offset;
791 779
        vnc_write_u16(vs, 0);
792 780

  
793
        for (y = 0; y < vs->server.ds->height; y++) {
781
        for (y = 0; y < vd->server->height; y++) {
794 782
            int x;
795 783
            int last_x = -1;
796
            for (x = 0; x < vs->server.ds->width / 16; x++) {
797
                if (vnc_get_bit(vs->server.dirty[y], x)) {
784
            for (x = 0; x < vd->server->width / 16; x++) {
785
                if (vnc_get_bit(vs->dirty[y], x)) {
798 786
                    if (last_x == -1) {
799 787
                        last_x = x;
800 788
                    }
801
                    vnc_clear_bit(vs->server.dirty[y], x);
789
                    vnc_clear_bit(vs->dirty[y], x);
802 790
                } else {
803 791
                    if (last_x != -1) {
804
                        int h = find_and_clear_dirty_height(&vs->server, y, last_x, x);
792
                        int h = find_and_clear_dirty_height(vs, y, last_x, x);
805 793
                        send_framebuffer_update(vs, last_x * 16, y, (x - last_x) * 16, h);
806 794
                        n_rectangles++;
807 795
                    }
......
809 797
                }
810 798
            }
811 799
            if (last_x != -1) {
812
                int h = find_and_clear_dirty_height(&vs->server, y, last_x, x);
800
                int h = find_and_clear_dirty_height(vs, y, last_x, x);
813 801
                send_framebuffer_update(vs, last_x * 16, y, (x - last_x) * 16, h);
814 802
                n_rectangles++;
815 803
            }
......
926 914
    if (!vs->vd->clients)
927 915
        dcl->idle = 1;
928 916

  
929
    qemu_free(vs->server.ds->data);
930
    qemu_free(vs->server.ds);
931
    qemu_free(vs->guest.ds);
932 917
    qemu_free(vs);
933 918
    vnc_remove_timer(vs->vd);
934 919
}
......
1507 1492
    if (!incremental) {
1508 1493
        vs->force_update = 1;
1509 1494
        for (i = 0; i < h; i++) {
1510
            vnc_set_bits(vs->guest.dirty[y_position + i],
1511
                         (ds_get_width(vs->ds) / 16), VNC_DIRTY_WORDS);
1512
            vnc_set_bits(vs->server.dirty[y_position + i],
1495
            vnc_set_bits(vs->dirty[y_position + i],
1513 1496
                         (ds_get_width(vs->ds) / 16), VNC_DIRTY_WORDS);
1514 1497
        }
1515 1498
    }
......
1638 1621
        return;
1639 1622
    }
1640 1623

  
1641
    vs->clientds = *(vs->guest.ds);
1624
    vs->clientds = *(vs->vd->guest.ds);
1642 1625
    vs->clientds.pf.rmax = red_max;
1643 1626
    count_bits(vs->clientds.pf.rbits, red_max);
1644 1627
    vs->clientds.pf.rshift = red_shift;
......
2067 2050
    return 0;
2068 2051
}
2069 2052

  
2053
static int vnc_refresh_server_surface(VncDisplay *vd)
2054
{
2055
    int y;
2056
    uint8_t *guest_row;
2057
    uint8_t *server_row;
2058
    int cmp_bytes;
2059
    uint32_t width_mask[VNC_DIRTY_WORDS];
2060
    VncState *vs = NULL;
2061
    int has_dirty = 0;
2062

  
2063
    /*
2064
     * Walk through the guest dirty map.
2065
     * Check and copy modified bits from guest to server surface.
2066
     * Update server dirty map.
2067
     */
2068
    vnc_set_bits(width_mask, (ds_get_width(vd->ds) / 16), VNC_DIRTY_WORDS);
2069
    cmp_bytes = 16 * ds_get_bytes_per_pixel(vd->ds);
2070
    guest_row  = vd->guest.ds->data;
2071
    server_row = vd->server->data;
2072
    for (y = 0; y < vd->guest.ds->height; y++) {
2073
        if (vnc_and_bits(vd->guest.dirty[y], width_mask, VNC_DIRTY_WORDS)) {
2074
            int x;
2075
            uint8_t *guest_ptr;
2076
            uint8_t *server_ptr;
2077

  
2078
            guest_ptr  = guest_row;
2079
            server_ptr = server_row;
2080

  
2081
            for (x = 0; x < vd->guest.ds->width;
2082
                    x += 16, guest_ptr += cmp_bytes, server_ptr += cmp_bytes) {
2083
                if (!vnc_get_bit(vd->guest.dirty[y], (x / 16)))
2084
                    continue;
2085
                vnc_clear_bit(vd->guest.dirty[y], (x / 16));
2086
                if (memcmp(server_ptr, guest_ptr, cmp_bytes) == 0)
2087
                    continue;
2088
                memcpy(server_ptr, guest_ptr, cmp_bytes);
2089
                vs = vd->clients;
2090
                while (vs != NULL) {
2091
                    vnc_set_bit(vs->dirty[y], (x / 16));
2092
                    vs = vs->next;
2093
                }
2094
                has_dirty++;
2095
            }
2096
        }
2097
        guest_row  += ds_get_linesize(vd->ds);
2098
        server_row += ds_get_linesize(vd->ds);
2099
    }
2100
    return has_dirty;
2101
}
2102

  
2070 2103
static void vnc_refresh(void *opaque)
2071 2104
{
2072 2105
    VncDisplay *vd = opaque;
2073
    VncState *vs = vd->clients;
2106
    VncState *vs = NULL;
2107
    int has_dirty = 0;
2074 2108

  
2075 2109
    vga_hw_update();
2076 2110

  
2111
    has_dirty = vnc_refresh_server_surface(vd);
2112

  
2113
    vs = vd->clients;
2077 2114
    while (vs != NULL) {
2078
        vnc_update_client(vs);
2115
        vnc_update_client(vs, has_dirty);
2079 2116
        vs = vs->next;
2080 2117
    }
2081 2118

  
......
2086 2123
{
2087 2124
    if (vd->timer == NULL && vd->clients != NULL) {
2088 2125
        vd->timer = qemu_new_timer(rt_clock, vnc_refresh, vd);
2089
        qemu_mod_timer(vd->timer, qemu_get_clock(rt_clock) + VNC_REFRESH_INTERVAL);
2126
        vnc_refresh(vd);
2090 2127
    }
2091 2128
}
2092 2129

  
......
2119 2156
    vs->as.fmt = AUD_FMT_S16;
2120 2157
    vs->as.endianness = 0;
2121 2158

  
2122
    vnc_resize(vs);
2159
    vs->next = vd->clients;
2160
    vd->clients = vs;
2161

  
2162
    vga_hw_update();
2163

  
2123 2164
    vnc_write(vs, "RFB 003.008\n", 12);
2124 2165
    vnc_flush(vs);
2125 2166
    vnc_read_when(vs, protocol_version, 12);
2126 2167
    reset_keys(vs);
2127 2168

  
2128
    vs->next = vd->clients;
2129
    vd->clients = vs;
2130

  
2131 2169
    vnc_init_timer(vd);
2132
    vnc_update_client(vs);
2170

  
2133 2171
    /* vs might be free()ed here */
2134 2172
}
2135 2173

  
b/vnc.h
84 84
#include "vnc-auth-sasl.h"
85 85
#endif
86 86

  
87
struct VncSurface
88
{
89
    uint32_t dirty[VNC_MAX_HEIGHT][VNC_DIRTY_WORDS];
90
    DisplaySurface *ds;
91
};
87 92

  
88 93
struct VncDisplay
89 94
{
......
93 98
    VncState *clients;
94 99
    kbd_layout_t *kbd_layout;
95 100

  
101
    struct VncSurface guest;   /* guest visible surface (aka ds->surface) */
102
    DisplaySurface *server;  /* vnc server surface */
103

  
96 104
    char *display;
97 105
    char *password;
98 106
    int auth;
......
105 113
#endif
106 114
};
107 115

  
108
struct VncSurface
109
{
110
    uint32_t dirty[VNC_MAX_HEIGHT][VNC_DIRTY_WORDS];
111
    DisplaySurface *ds;
112
};
113

  
114 116
struct VncState
115 117
{
116 118
    int csock;
117 119

  
118 120
    DisplayState *ds;
119
    struct VncSurface guest;   /* guest visible surface (aka ds->surface) */
120
    struct VncSurface server;  /* vnc server surface */
121
    uint32_t dirty[VNC_MAX_HEIGHT][VNC_DIRTY_WORDS];
121 122

  
122 123
    VncDisplay *vd;
123 124
    int need_update;
b/vnchextile.h
13 13
                                             void *last_fg_,
14 14
                                             int *has_bg, int *has_fg)
15 15
{
16
    uint8_t *row = vs->server.ds->data + y * ds_get_linesize(vs->ds) + x * ds_get_bytes_per_pixel(vs->ds);
16
    VncDisplay *vd = vs->vd;
17
    uint8_t *row = vd->server->data + y * ds_get_linesize(vs->ds) + x * ds_get_bytes_per_pixel(vs->ds);
17 18
    pixel_t *irow = (pixel_t *)row;
18 19
    int j, i;
19 20
    pixel_t *last_bg = (pixel_t *)last_bg_;

Also available in: Unified diff