diff --git a/bench/zrle-bench.c b/bench/zrle-bench.c index f03da9d..1b6f0ca 100644 --- a/bench/zrle-bench.c +++ b/bench/zrle-bench.c @@ -3,6 +3,7 @@ #include "util.h" #include "vec.h" #include "neatvnc.h" +#include "miniz.h" #include #include @@ -39,15 +40,21 @@ int run_benchmark(const char *image) struct vec frame; vec_init(&frame, fb.width * fb.height * 3 / 2); + z_stream zs = { 0 }; + + deflateInit(&zs, Z_DEFAULT_COMPRESSION); + uint64_t start_time = gettime_us(CLOCK_PROCESS_CPUTIME_ID); - rc = zrle_encode_frame(&frame, &pixfmt, fb.addr, &pixfmt, + rc = zrle_encode_frame(&zs, &frame, &pixfmt, fb.addr, &pixfmt, fb.width, fb.height, ®ion); uint64_t end_time = gettime_us(CLOCK_PROCESS_CPUTIME_ID); printf("Encoding %s took %"PRIu64" micro seconds\n", image, end_time - start_time); + deflateEnd(&zs); + if (rc < 0) goto failure; diff --git a/examples/draw.c b/examples/draw.c index 5bd048f..ac07171 100644 --- a/examples/draw.c +++ b/examples/draw.c @@ -50,7 +50,7 @@ void on_pointer_event(struct nvnc_client *client, uint16_t x, uint16_t y, struct pixman_region16 region; pixman_region_init_rect(®ion, 0, 0, draw->fb.width, draw->fb.height); -// pixman_region_init_rect(®ion, x, y, 1, 1); + pixman_region_intersect_rect(®ion, ®ion, x, y, 1, 1); nvnc_update_fb(server, &draw->fb, ®ion); pixman_region_fini(®ion); } diff --git a/inc/rfb-proto.h b/inc/rfb-proto.h index 8c1d9b7..ea5c3d7 100644 --- a/inc/rfb-proto.h +++ b/inc/rfb-proto.h @@ -132,7 +132,6 @@ struct rfb_server_fb_update_msg { uint8_t type; uint8_t padding; uint16_t n_rects; - struct rfb_server_fb_rect rects[0]; } RFB_PACKED; static inline int rfb_send_security_types(void *client) diff --git a/inc/zrle.h b/inc/zrle.h index 2cf9ec8..dba4195 100644 --- a/inc/zrle.h +++ b/inc/zrle.h @@ -4,6 +4,8 @@ #include #include +#include "miniz.h" + struct rfb_pixel_format; struct pixman_region16; struct vec; @@ -14,7 +16,8 @@ void pixel32_to_cpixel(uint8_t *restrict dst, const struct rfb_pixel_format* src_fmt, size_t bytes_per_cpixel, size_t len); -int zrle_encode_frame(struct vec *dst, +int zrle_encode_frame(z_stream *zs, + struct vec *dst, const struct rfb_pixel_format *dst_fmt, const uint8_t *src, const struct rfb_pixel_format *src_fmt, diff --git a/src/server.c b/src/server.c index 63c6567..0723795 100644 --- a/src/server.c +++ b/src/server.c @@ -55,6 +55,7 @@ struct nvnc_client { LIST_ENTRY(nvnc_client) link; struct pixman_region16 requested_region; nvnc_client_fn cleanup_fn; + z_stream z_stream; size_t buffer_index; size_t buffer_len; uint8_t msg_buffer[MSG_BUFFER_SIZE]; @@ -113,6 +114,8 @@ static void cleanup_client(uv_handle_t* handle) if (fn) fn(client); + deflateEnd(&client->z_stream); + LIST_REMOVE(client, link); pixman_region_fini(&client->requested_region); free(client); @@ -655,6 +658,11 @@ static void on_connection(uv_stream_t *server_stream, int status) client->server = server; + if (deflateInit(&client->z_stream, Z_DEFAULT_COMPRESSION) != Z_OK) { + free(client); + return; + } + pixman_region_init(&client->requested_region); uv_tcp_init(uv_default_loop(), &client->stream_handle); @@ -771,8 +779,9 @@ int nvnc_update_fb(struct nvnc *self, const struct nvnc_fb *fb, pixman_region_intersect(cregion, cregion, ®ion); - zrle_encode_frame(&frame, &client->pixfmt, fb->addr, - &server_fmt, fb->width, fb->height, ®ion); + zrle_encode_frame(&client->z_stream, &frame, &client->pixfmt, + fb->addr, &server_fmt, fb->width, fb->height, + ®ion); pixman_region_clear(cregion); diff --git a/src/zrle.c b/src/zrle.c index 9d005b7..940bf3b 100644 --- a/src/zrle.c +++ b/src/zrle.c @@ -180,36 +180,30 @@ int zrle_deflate(struct vec* dst, const struct vec* src, z_stream* zs, zs->next_out = ((Bytef*)dst->data) + dst->len; zs->avail_out = dst->cap - dst->len; - r = deflate(zs, flush ? Z_FINISH : Z_NO_FLUSH); + r = deflate(zs, flush ? Z_SYNC_FLUSH : Z_NO_FLUSH); assert(r != Z_STREAM_ERROR); dst->len = zs->next_out - (Bytef*)dst->data; } while (zs->avail_out == 0); assert(zs->avail_in == 0); - assert(!flush || r == Z_STREAM_END); return 0; } int zrle_encode_box(struct vec* out, const struct rfb_pixel_format *dst_fmt, const uint8_t *src, const struct rfb_pixel_format *src_fmt, - int x, int y, int stride, int width, int height) + int x, int y, int stride, int width, int height, + z_stream* zs) { int r = -1; int bytes_per_cpixel = dst_fmt->depth / 8; int chunk_size = 1 + bytes_per_cpixel * 64 * 64; - z_stream zs = { 0 }; - struct vec in; if (vec_init(&in, 1 + bytes_per_cpixel * 64 * 64) < 0) goto failure; - r = deflateInit(&zs, Z_DEFAULT_COMPRESSION); - if (r != Z_OK) - goto failure; - struct rfb_server_fb_rect rect = { .encoding = htonl(RFB_ENCODING_ZRLE), .x = htons(x), @@ -239,16 +233,11 @@ int zrle_encode_box(struct vec* out, const struct rfb_pixel_format *dst_fmt, ((uint32_t*)src) + x + tile_x + (y + tile_y) * stride, src_fmt, stride, tile_width, tile_height); - r = zrle_deflate(out, &in, &zs, i == n_tiles - 1); + r = zrle_deflate(out, &in, zs, i == n_tiles - 1); if (r < 0) goto failure; } - deflateEnd(&zs); - - /* There seems to be something extra at the end */ - out->len -= 4; - uint32_t out_size = htonl(out->len - size_index - 4); memcpy(((uint8_t*)out->data) + size_index, &out_size, sizeof(out_size)); @@ -258,7 +247,8 @@ failure: #undef CHUNK } -int zrle_encode_frame(struct vec* dst, +int zrle_encode_frame(z_stream *zs, + struct vec* dst, const struct rfb_pixel_format *dst_fmt, const uint8_t *src, const struct rfb_pixel_format *src_fmt, @@ -290,7 +280,7 @@ int zrle_encode_frame(struct vec* dst, int box_height = box[i].y2 - y; rc = zrle_encode_box(dst, dst_fmt, src, src_fmt, x, y, - width, box_width, box_height); + width, box_width, box_height, zs); if (rc < 0) return -1; }