diff --git a/Makefile b/Makefile index 5910dca..eff63d9 100644 --- a/Makefile +++ b/Makefile @@ -5,6 +5,7 @@ SOURCES := \ src/util.c \ src/vec.c \ src/zrle.c \ + src/pixels.c \ include common.mk diff --git a/inc/pixels.h b/inc/pixels.h new file mode 100644 index 0000000..2229760 --- /dev/null +++ b/inc/pixels.h @@ -0,0 +1,25 @@ +/* + * Copyright (c) 2019 Andri Yngvason + * + * Permission to use, copy, modify, and/or distribute this software for any + * purpose with or without fee is hereby granted, provided that the above + * copyright notice and this permission notice appear in all copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES WITH + * REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY + * AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT, + * INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM + * LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE + * OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR + * PERFORMANCE OF THIS SOFTWARE. + */ + +#pragma once + +#include + +void pixel32_to_cpixel(uint8_t *restrict dst, + const struct rfb_pixel_format* dst_fmt, + const uint32_t *restrict src, + const struct rfb_pixel_format* src_fmt, + size_t bytes_per_cpixel, size_t len); diff --git a/inc/zrle.h b/inc/zrle.h index 8e85a68..954dd5b 100644 --- a/inc/zrle.h +++ b/inc/zrle.h @@ -26,12 +26,6 @@ struct rfb_pixel_format; struct pixman_region16; struct vec; -void pixel32_to_cpixel(uint8_t *restrict dst, - const struct rfb_pixel_format* dst_fmt, - const uint32_t *restrict src, - const struct rfb_pixel_format* src_fmt, - size_t bytes_per_cpixel, size_t len); - int zrle_encode_frame(z_stream *zs, struct vec *dst, const struct rfb_pixel_format *dst_fmt, diff --git a/src/pixels.c b/src/pixels.c new file mode 100644 index 0000000..15457c5 --- /dev/null +++ b/src/pixels.c @@ -0,0 +1,127 @@ +/* + * Copyright (c) 2019 Andri Yngvason + * + * Permission to use, copy, modify, and/or distribute this software for any + * purpose with or without fee is hereby granted, provided that the above + * copyright notice and this permission notice appear in all copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES WITH + * REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY + * AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT, + * INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM + * LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE + * OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR + * PERFORMANCE OF THIS SOFTWARE. + */ + +#include "rfb-proto.h" +#include +#include + +#define POPCOUNT(x) __builtin_popcount(x) + +void pixel32_to_cpixel(uint8_t *restrict dst, + const struct rfb_pixel_format* dst_fmt, + const uint32_t *restrict src, + const struct rfb_pixel_format* src_fmt, + size_t bytes_per_cpixel, size_t len) +{ + assert(src_fmt->true_colour_flag); + assert(src_fmt->bits_per_pixel == 32); + assert(src_fmt->depth <= 32); + assert(dst_fmt->true_colour_flag); + assert(dst_fmt->bits_per_pixel <= 32); + assert(dst_fmt->depth <= 24); + assert(bytes_per_cpixel <= 3 && bytes_per_cpixel >= 1); + + uint32_t src_red_shift = src_fmt->red_shift; + uint32_t src_green_shift = src_fmt->green_shift; + uint32_t src_blue_shift = src_fmt->blue_shift; + + uint32_t dst_red_shift = dst_fmt->red_shift; + uint32_t dst_green_shift = dst_fmt->green_shift; + uint32_t dst_blue_shift = dst_fmt->blue_shift; + + uint32_t src_red_max = src_fmt->red_max; + uint32_t src_green_max = src_fmt->green_max; + uint32_t src_blue_max = src_fmt->blue_max; + + uint32_t dst_red_max = dst_fmt->red_max; + uint32_t dst_green_max = dst_fmt->green_max; + uint32_t dst_blue_max = dst_fmt->blue_max; + + uint32_t src_red_bits = POPCOUNT(src_fmt->red_max); + uint32_t src_green_bits = POPCOUNT(src_fmt->green_max); + uint32_t src_blue_bits = POPCOUNT(src_fmt->blue_max); + + uint32_t dst_red_bits = POPCOUNT(dst_fmt->red_max); + uint32_t dst_green_bits = POPCOUNT(dst_fmt->green_max); + uint32_t dst_blue_bits = POPCOUNT(dst_fmt->blue_max); + + uint32_t dst_endian_correction; + +#define CONVERT_PIXELS(cpx, px) \ + { \ + uint32_t r, g, b; \ + r = ((px >> src_red_shift) & src_red_max) << dst_red_bits \ + >> src_red_bits << dst_red_shift; \ + g = ((px >> src_green_shift) & src_green_max) << dst_green_bits \ + >> src_green_bits << dst_green_shift; \ + b = ((px >> src_blue_shift) & src_blue_max) << dst_blue_bits \ + >> src_blue_bits << dst_blue_shift; \ + cpx = r | g | b; \ + } + + switch (bytes_per_cpixel) { + case 3: + if (dst_fmt->bits_per_pixel == 32 && dst_fmt->depth <= 24) { + uint32_t min_dst_shift = dst_red_shift; + if (min_dst_shift > dst_green_shift) + min_dst_shift = dst_green_shift; + if (min_dst_shift > dst_blue_shift) + min_dst_shift = dst_blue_shift; + + dst_red_shift -= min_dst_shift; + dst_green_shift -= min_dst_shift; + dst_blue_shift -= min_dst_shift; + } + + dst_endian_correction = dst_fmt->big_endian_flag ? 16 : 0; + + while (len--) { + uint32_t cpx, px = *src++; + + CONVERT_PIXELS(cpx, px) + + *dst++ = (cpx >> (16 ^ dst_endian_correction)) & 0xff; + *dst++ = (cpx >> 8) & 0xff; + *dst++ = (cpx >> (0 ^ dst_endian_correction)) & 0xff; + } + break; + case 2: + dst_endian_correction = dst_fmt->big_endian_flag ? 8 : 0; + + while (len--) { + uint32_t cpx, px = *src++; + + CONVERT_PIXELS(cpx, px) + + *dst++ = (cpx >> (8 ^ dst_endian_correction)) & 0xff; + *dst++ = (cpx >> (0 ^ dst_endian_correction)) & 0xff; + } + break; + case 1: + while (len--) { + uint32_t cpx, px = *src++; + + CONVERT_PIXELS(cpx, px) + + *dst++ = cpx & 0xff; + } + break; + default: + abort(); + } + +#undef CONVERT_PIXELS +} diff --git a/src/zrle.c b/src/zrle.c index 1a2fd57..8295455 100644 --- a/src/zrle.c +++ b/src/zrle.c @@ -20,6 +20,7 @@ #include "zrle.h" #include "miniz.h" #include "neatvnc.h" +#include "pixels.h" #include #include @@ -32,134 +33,8 @@ #define TILE_LENGTH 64 -#define POPCOUNT(x) __builtin_popcount(x) #define UDIV_UP(a, b) (((a) + (b) - 1) / (b)) -void pixel_format_into_native(struct rfb_pixel_format *fmt) -{ -#if __BYTE_ORDER__ == __LITTLE_ENDIAN__ - if (!fmt->big_endian_flag) - return; - - fmt->big_endian_flag = 0; -#else - if (fmt->big_endian_flag) - return; - - fmt->big_endian_flag = 1; -#endif - - fmt->red_shift = fmt->bits_per_pixel - fmt->red_shift; - fmt->green_shift = fmt->bits_per_pixel - fmt->green_shift; - fmt->blue_shift = fmt->bits_per_pixel - fmt->blue_shift; -} - -void pixel32_to_cpixel(uint8_t *restrict dst, - const struct rfb_pixel_format* dst_fmt, - const uint32_t *restrict src, - const struct rfb_pixel_format* src_fmt, - size_t bytes_per_cpixel, size_t len) -{ - assert(src_fmt->true_colour_flag); - assert(src_fmt->bits_per_pixel == 32); - assert(src_fmt->depth <= 32); - assert(dst_fmt->true_colour_flag); - assert(dst_fmt->bits_per_pixel <= 32); - assert(dst_fmt->depth <= 24); - assert(bytes_per_cpixel <= 3 && bytes_per_cpixel >= 1); - - uint32_t src_red_shift = src_fmt->red_shift; - uint32_t src_green_shift = src_fmt->green_shift; - uint32_t src_blue_shift = src_fmt->blue_shift; - - uint32_t dst_red_shift = dst_fmt->red_shift; - uint32_t dst_green_shift = dst_fmt->green_shift; - uint32_t dst_blue_shift = dst_fmt->blue_shift; - - uint32_t src_red_max = src_fmt->red_max; - uint32_t src_green_max = src_fmt->green_max; - uint32_t src_blue_max = src_fmt->blue_max; - - uint32_t dst_red_max = dst_fmt->red_max; - uint32_t dst_green_max = dst_fmt->green_max; - uint32_t dst_blue_max = dst_fmt->blue_max; - - uint32_t src_red_bits = POPCOUNT(src_fmt->red_max); - uint32_t src_green_bits = POPCOUNT(src_fmt->green_max); - uint32_t src_blue_bits = POPCOUNT(src_fmt->blue_max); - - uint32_t dst_red_bits = POPCOUNT(dst_fmt->red_max); - uint32_t dst_green_bits = POPCOUNT(dst_fmt->green_max); - uint32_t dst_blue_bits = POPCOUNT(dst_fmt->blue_max); - - uint32_t dst_endian_correction; - -#define CONVERT_PIXELS(cpx, px) \ - { \ - uint32_t r, g, b; \ - r = ((px >> src_red_shift) & src_red_max) << dst_red_bits \ - >> src_red_bits << dst_red_shift; \ - g = ((px >> src_green_shift) & src_green_max) << dst_green_bits \ - >> src_green_bits << dst_green_shift; \ - b = ((px >> src_blue_shift) & src_blue_max) << dst_blue_bits \ - >> src_blue_bits << dst_blue_shift; \ - cpx = r | g | b; \ - } - - switch (bytes_per_cpixel) { - case 3: - if (dst_fmt->bits_per_pixel == 32 && dst_fmt->depth <= 24) { - uint32_t min_dst_shift = dst_red_shift; - if (min_dst_shift > dst_green_shift) - min_dst_shift = dst_green_shift; - if (min_dst_shift > dst_blue_shift) - min_dst_shift = dst_blue_shift; - - dst_red_shift -= min_dst_shift; - dst_green_shift -= min_dst_shift; - dst_blue_shift -= min_dst_shift; - } - - dst_endian_correction = dst_fmt->big_endian_flag ? 16 : 0; - - while (len--) { - uint32_t cpx, px = *src++; - - CONVERT_PIXELS(cpx, px) - - *dst++ = (cpx >> (16 ^ dst_endian_correction)) & 0xff; - *dst++ = (cpx >> 8) & 0xff; - *dst++ = (cpx >> (0 ^ dst_endian_correction)) & 0xff; - } - break; - case 2: - dst_endian_correction = dst_fmt->big_endian_flag ? 8 : 0; - - while (len--) { - uint32_t cpx, px = *src++; - - CONVERT_PIXELS(cpx, px) - - *dst++ = (cpx >> (8 ^ dst_endian_correction)) & 0xff; - *dst++ = (cpx >> (0 ^ dst_endian_correction)) & 0xff; - } - break; - case 1: - while (len--) { - uint32_t cpx, px = *src++; - - CONVERT_PIXELS(cpx, px) - - *dst++ = cpx & 0xff; - } - break; - default: - abort(); - } - -#undef CONVERT_PIXELS -} - static inline int find_colour_in_palette(uint32_t *palette, int len, uint32_t colour) {