diff --git a/tests/util/pattern.c b/tests/util/pattern.c index f1c844ea..34d9d3e4 100644 --- a/tests/util/pattern.c +++ b/tests/util/pattern.c @@ -79,10 +79,12 @@ static inline uint32_t swap32(uint32_t x) #define cpu_to_be16(x) (x) #define cpu_to_le16(x) swap16(x) #define cpu_to_le32(x) swap32(x) +#define fb_foreign_endian(format) (!((format) & DRM_FORMAT_BIG_ENDIAN)) #else #define cpu_to_be16(x) swap16(x) #define cpu_to_le16(x) (x) #define cpu_to_le32(x) (x) +#define fb_foreign_endian(format) ((format) & DRM_FORMAT_BIG_ENDIAN) #endif #define cpu_to_fb16(x) (fb_be ? cpu_to_be16(x) : cpu_to_le16(x)) @@ -1290,6 +1292,32 @@ static void fill_smpte(const struct util_format_info *info, void *planes[3], } } +#if HAVE_CAIRO +static void byteswap_buffer16(void *mem, unsigned int width, unsigned int height, + unsigned int stride) +{ + unsigned int x, y; + + for (y = 0; y < height; ++y) { + for (x = 0; x < width; ++x) + ((uint16_t *)mem)[x] = swap16(((uint16_t *)mem)[x]); + mem += stride; + } +} + +static void byteswap_buffer32(void *mem, unsigned int width, unsigned int height, + unsigned int stride) +{ + unsigned int x, y; + + for (y = 0; y < height; ++y) { + for (x = 0; x < width; ++x) + ((uint32_t *)mem)[x] = swap32(((uint32_t *)mem)[x]); + mem += stride; + } +} +#endif + static void make_pwetty(void *data, unsigned int width, unsigned int height, unsigned int stride, uint32_t format) { @@ -1297,6 +1325,8 @@ static void make_pwetty(void *data, unsigned int width, unsigned int height, cairo_surface_t *surface; cairo_t *cr; cairo_format_t cairo_format; + bool swap16 = false; + bool swap32 = false; /* we can ignore the order of R,G,B channels */ switch (format) { @@ -1309,6 +1339,7 @@ static void make_pwetty(void *data, unsigned int width, unsigned int height, case DRM_FORMAT_RGB565: case DRM_FORMAT_BGR565: cairo_format = CAIRO_FORMAT_RGB16_565; + swap16 = fb_foreign_endian(format); break; #if CAIRO_VERSION_MAJOR > 1 || (CAIRO_VERSION_MAJOR == 1 && CAIRO_VERSION_MINOR >= 12) case DRM_FORMAT_ARGB2101010: @@ -1316,12 +1347,19 @@ static void make_pwetty(void *data, unsigned int width, unsigned int height, case DRM_FORMAT_ABGR2101010: case DRM_FORMAT_XBGR2101010: cairo_format = CAIRO_FORMAT_RGB30; + swap32 = fb_foreign_endian(format); break; #endif default: return; } + /* Cairo uses native byte order, so we may have to byteswap before... */ + if (swap16) + byteswap_buffer16(data, width, height, stride); + if (swap32) + byteswap_buffer32(data, width, height, stride); + surface = cairo_image_surface_create_for_data(data, cairo_format, width, height, @@ -1357,6 +1395,12 @@ static void make_pwetty(void *data, unsigned int width, unsigned int height, } cairo_destroy(cr); + + /* ... and after */ + if (swap16) + byteswap_buffer16(data, width, height, stride); + if (swap32) + byteswap_buffer32(data, width, height, stride); #endif }