All of lore.kernel.org
 help / color / mirror / Atom feed
From: Geert Uytterhoeven <geert@linux-m68k.org>
To: dri-devel@lists.freedesktop.org
Cc: Geert Uytterhoeven <geert@linux-m68k.org>
Subject: [PATCH libdrm v2 08/10] util: Fix pwetty on big-endian
Date: Fri,  8 Jul 2022 20:21:47 +0200	[thread overview]
Message-ID: <e8597038478f12e9eda5e86b309b52988f69f2eb.1657302103.git.geert@linux-m68k.org> (raw)
In-Reply-To: <cover.1657302103.git.geert@linux-m68k.org>

Cairo always uses native byte order for rendering.

Hence if the byte order of the frame buffer differs from the byte order
of the CPU, the frame buffer contents need to be byteswapped twice: once
before rendering, to convert to native byte order, and a second time
after rendering, to restore the frame buffer format's byte order.

Note that byte swapping is not done for ARGB32 formats, as for these
formats, byte order only affects the order of the red, green, and blue
channels, which we do not care about here.

Signed-off-by: Geert Uytterhoeven <geert@linux-m68k.org>
---
This is ugly, but I see no better solution.

v2:
  - RGB30 is untested.
---
 tests/util/pattern.c | 54 +++++++++++++++++++++++++++++++++++++++-----
 1 file changed, 48 insertions(+), 6 deletions(-)

diff --git a/tests/util/pattern.c b/tests/util/pattern.c
index e693892bb3cf93c1..627f402be1d02e1c 100644
--- a/tests/util/pattern.c
+++ b/tests/util/pattern.c
@@ -76,13 +76,15 @@ static inline uint32_t swap32(uint32_t x)
 }
 
 #if defined(__BIG_ENDIAN__) || defined(__ARM_BIG_ENDIAN) || defined(__mc68000__) || defined(__MIPSEB__) || defined(__s390__) || defined(__sparc__)
-#define cpu_to_be16(x)	(x)
-#define cpu_to_le16(x)	swap16(x)
-#define cpu_to_le32(x)	swap32(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 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))
@@ -1133,6 +1135,30 @@ static void fill_smpte(const struct util_format_info *info, void *planes[3],
 #define GREEN 1
 #define BLUE  0
 
+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;
+	}
+}
+
 static void make_pwetty(void *data, unsigned int width, unsigned int height,
 			unsigned int stride, uint32_t format)
 {
@@ -1140,6 +1166,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) {
@@ -1152,6 +1180,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:
@@ -1159,12 +1188,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,
@@ -1200,6 +1236,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
 }
 
-- 
2.25.1


  parent reply	other threads:[~2022-07-08 18:22 UTC|newest]

Thread overview: 15+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2022-07-08 18:21 [PATCH libdrm v2 00/10] Big-endian fixes Geert Uytterhoeven
2022-07-08 18:21 ` [PATCH libdrm v2 01/10] intel: Improve checks for big-endian Geert Uytterhoeven
2022-07-08 18:21 ` [PATCH libdrm v2 02/10] util: Fix 32 bpp patterns on big-endian Geert Uytterhoeven
2022-07-08 18:21 ` [PATCH libdrm v2 03/10] util: Fix 16 " Geert Uytterhoeven
2022-07-08 18:21 ` [PATCH libdrm v2 04/10] util: Add missing big-endian RGB16 frame buffer formats Geert Uytterhoeven
2022-07-11 12:17   ` Ville Syrjälä
2022-07-11 12:34     ` Geert Uytterhoeven
2022-07-12 10:20       ` Michel Dänzer
2023-07-05 16:08       ` Geert Uytterhoeven
2022-07-08 18:21 ` [PATCH libdrm v2 05/10] modetest: Fix printing of big-endian fourcc values Geert Uytterhoeven
2022-07-08 18:21 ` [PATCH libdrm v2 06/10] modetest: Add support for parsing big-endian formats Geert Uytterhoeven
2022-07-08 18:21 ` [PATCH libdrm v2 07/10] util: Add test pattern support for big-endian XRGB1555/RGB565 Geert Uytterhoeven
2022-07-08 18:21 ` Geert Uytterhoeven [this message]
2022-07-08 18:21 ` [PATCH libdrm v2 09/10] util: Add pwetty support for big-endian RGB565 Geert Uytterhoeven
2022-07-08 18:21 ` [PATCH libdrm v2 10/10] modetest: Add support for big-endian XRGB1555/RGB565 Geert Uytterhoeven

Reply instructions:

You may reply publicly to this message via plain-text email
using any one of the following methods:

* Save the following mbox file, import it into your mail client,
  and reply-to-all from there: mbox

  Avoid top-posting and favor interleaved quoting:
  https://en.wikipedia.org/wiki/Posting_style#Interleaved_style

* Reply using the --to, --cc, and --in-reply-to
  switches of git-send-email(1):

  git send-email \
    --in-reply-to=e8597038478f12e9eda5e86b309b52988f69f2eb.1657302103.git.geert@linux-m68k.org \
    --to=geert@linux-m68k.org \
    --cc=dri-devel@lists.freedesktop.org \
    /path/to/YOUR_REPLY

  https://kernel.org/pub/software/scm/git/docs/git-send-email.html

* If your mail client supports setting the In-Reply-To header
  via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line before the message body.
This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.