diff --git a/include/pixels.h b/include/pixels.h index 3ebd1d9..aa4c9ad 100644 --- a/include/pixels.h +++ b/include/pixels.h @@ -1,5 +1,5 @@ /* - * Copyright (c) 2019 Andri Yngvason + * Copyright (c) 2019 - 2021 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 @@ -18,6 +18,8 @@ #include #include +#include +#include struct rfb_pixel_format; @@ -31,3 +33,5 @@ int rfb_pixfmt_from_fourcc(struct rfb_pixel_format *dst, uint32_t src); uint32_t rfb_pixfmt_to_fourcc(const struct rfb_pixel_format* fmt); int pixel_size_from_fourcc(uint32_t fourcc); + +bool fourcc_to_pixman_fmt(pixman_format_code_t* dst, uint32_t src); diff --git a/src/pixels.c b/src/pixels.c index 9b25909..ad7d2ff 100644 --- a/src/pixels.c +++ b/src/pixels.c @@ -247,3 +247,72 @@ int pixel_size_from_fourcc(uint32_t fourcc) return 0; } + +bool fourcc_to_pixman_fmt(pixman_format_code_t* dst, uint32_t src) +{ + assert(!(src & DRM_FORMAT_BIG_ENDIAN)); + +#define LOWER_R r +#define LOWER_G g +#define LOWER_B b +#define LOWER_A a +#define LOWER_X x +#define LOWER_ +#define LOWER(x) LOWER_##x + +#define CONCAT_(a, b) a ## b +#define CONCAT(a, b) CONCAT_(a, b) + +#define FMT_DRM(x, y, z, v, a, b, c, d) DRM_FORMAT_##x##y##z##v##a##b##c##d + +#if __BYTE_ORDER__ == __ORDER_LITTLE_ENDIAN__ +#define FMT_PIXMAN(x, y, z, v, a, b, c, d) \ + CONCAT(CONCAT(CONCAT(CONCAT(CONCAT(CONCAT(CONCAT(CONCAT(\ + PIXMAN_, LOWER(x)), a), LOWER(y)), b), LOWER(z)), c), LOWER(v)), d) +#else +#define FMT_PIXMAN(x, y, z, v, a, b, c, d) \ + CONCAT(CONCAT(CONCAT(CONCAT(CONCAT(CONCAT(CONCAT(CONCAT(\ + PIXMAN_, LOWER(v)), d), LOWER(z)), c), LOWER(y)), b), LOWER(x)), a) +#endif + + switch (src) { +#define X(...) \ + case FMT_DRM(__VA_ARGS__): *dst = FMT_PIXMAN(__VA_ARGS__); break + + /* 32 bits */ + X(A,R,G,B,8,8,8,8); + X(A,B,G,R,8,8,8,8); + X(X,R,G,B,8,8,8,8); + X(X,B,G,R,8,8,8,8); + X(R,G,B,A,8,8,8,8); + X(B,G,R,A,8,8,8,8); + X(R,G,B,X,8,8,8,8); + X(B,G,R,X,8,8,8,8); + + /* 24 bits */ + X(R,G,B,,8,8,8,); + X(B,G,R,,8,8,8,); + + /* 16 bits */ + X(R,G,B,,5,6,5,); + X(B,G,R,,5,6,5,); + + /* These are incompatible on big endian */ +#if __BYTE_ORDER__ == __ORDER_LITTLE_ENDIAN__ + X(A,R,G,B,1,5,5,5); + X(A,B,G,R,1,5,5,5); + X(X,R,G,B,1,5,5,5); + X(X,B,G,R,1,5,5,5); + X(A,R,G,B,4,4,4,4); + X(A,B,G,R,4,4,4,4); + X(X,R,G,B,4,4,4,4); + X(X,B,G,R,4,4,4,4); +#endif + +#undef X + + default: return false; + } + + return true; +}