static int zrle_send_framebuffer_update(VncState *vs, int x, int y,

                                        int w, int h)

{

    bool be = !!(vs->clientds.flags & QEMU_BIG_ENDIAN_FLAG);

    size_t bytes;

    int zywrle_level;



    if (vs->zrle.type == VNC_ENCODING_ZYWRLE) {

        if (!vs->vd->lossy || vs->tight.quality < 0 || vs->tight.quality == 9) {

            zywrle_level = 0;

            vs->zrle.type = VNC_ENCODING_ZRLE;

        } else if (vs->tight.quality < 3) {

            zywrle_level = 3;

        } else if (vs->tight.quality < 6) {

            zywrle_level = 2;

        } else {

            zywrle_level = 1;

        }

    } else {

        zywrle_level = 0;

    }



    vnc_zrle_start(vs);



    switch(vs->clientds.pf.bytes_per_pixel) {

    case 1:

        zrle_encode_8ne(vs, x, y, w, h, zywrle_level);

        break;



    case 2:

        if (vs->clientds.pf.gmax > 0x1F) {

            if (be) {

                zrle_encode_16be(vs, x, y, w, h, zywrle_level);

            } else {

                zrle_encode_16le(vs, x, y, w, h, zywrle_level);

            }

        } else {

            if (be) {

                zrle_encode_15be(vs, x, y, w, h, zywrle_level);

            } else {

                zrle_encode_15le(vs, x, y, w, h, zywrle_level);

            }

        }

        break;



    case 4:

    {

        bool fits_in_ls3bytes;

        bool fits_in_ms3bytes;



        fits_in_ls3bytes =

            ((vs->clientds.pf.rmax << vs->clientds.pf.rshift) < (1 << 24) &&

             (vs->clientds.pf.gmax << vs->clientds.pf.gshift) < (1 << 24) &&

             (vs->clientds.pf.bmax << vs->clientds.pf.bshift) < (1 << 24));



        fits_in_ms3bytes = (vs->clientds.pf.rshift > 7 &&

                            vs->clientds.pf.gshift > 7 &&

                            vs->clientds.pf.bshift > 7);



        if ((fits_in_ls3bytes && !be) || (fits_in_ms3bytes && be)) {

            if (be) {

                zrle_encode_24abe(vs, x, y, w, h, zywrle_level);

            } else {

                zrle_encode_24ale(vs, x, y, w, h, zywrle_level);

          }

        } else if ((fits_in_ls3bytes && be) || (fits_in_ms3bytes && !be)) {

            if (be) {

                zrle_encode_24bbe(vs, x, y, w, h, zywrle_level);

            } else {

                zrle_encode_24ble(vs, x, y, w, h, zywrle_level);

            }

        } else {

            if (be) {

                zrle_encode_32be(vs, x, y, w, h, zywrle_level);

            } else {

                zrle_encode_32le(vs, x, y, w, h, zywrle_level);

            }

        }

    }

    break;

    }



    vnc_zrle_stop(vs);

    bytes = zrle_compress_data(vs, Z_DEFAULT_COMPRESSION);

    vnc_framebuffer_update(vs, x, y, w, h, vs->zrle.type);

    vnc_write_u32(vs, bytes);

    vnc_write(vs, vs->zrle.zlib.buffer, vs->zrle.zlib.offset);

    return 1;

}
