static int vnc_update_stats(VncDisplay *vd,  struct timeval * tv)

{

    int width = pixman_image_get_width(vd->guest.fb);

    int height = pixman_image_get_height(vd->guest.fb);

    int x, y;

    struct timeval res;

    int has_dirty = 0;



    for (y = 0; y < height; y += VNC_STAT_RECT) {

        for (x = 0; x < width; x += VNC_STAT_RECT) {

            VncRectStat *rect = vnc_stat_rect(vd, x, y);



            rect->updated = false;

        }

    }



    qemu_timersub(tv, &VNC_REFRESH_STATS, &res);



    if (timercmp(&vd->guest.last_freq_check, &res, >)) {

        return has_dirty;

    }

    vd->guest.last_freq_check = *tv;



    for (y = 0; y < height; y += VNC_STAT_RECT) {

        for (x = 0; x < width; x += VNC_STAT_RECT) {

            VncRectStat *rect= vnc_stat_rect(vd, x, y);

            int count = ARRAY_SIZE(rect->times);

            struct timeval min, max;



            if (!timerisset(&rect->times[count - 1])) {

                continue ;

            }



            max = rect->times[(rect->idx + count - 1) % count];

            qemu_timersub(tv, &max, &res);



            if (timercmp(&res, &VNC_REFRESH_LOSSY, >)) {

                rect->freq = 0;

                has_dirty += vnc_refresh_lossy_rect(vd, x, y);

                memset(rect->times, 0, sizeof (rect->times));

                continue ;

            }



            min = rect->times[rect->idx];

            max = rect->times[(rect->idx + count - 1) % count];

            qemu_timersub(&max, &min, &res);



            rect->freq = res.tv_sec + res.tv_usec / 1000000.;

            rect->freq /= count;

            rect->freq = 1. / rect->freq;

        }

    }

    return has_dirty;

}
