[Mesa-dev] [PATCH] r300g: fix big endian support

Marek Olšák maraeo at gmail.com
Sun May 1 14:11:46 UTC 2016


From: Marek Olšák <marek.olsak at amd.com>

The problem was that A8R8G8B8 was not supported, which is required
for DRI2 window framebuffers on BE.

This patch:
- adds support for ARGB 32bpp array formats for LE & BE using byteswapping
- sets endian swap for packed formats as expected

ARGB is the only byteswapped array format. It's supported by programming it
just like BGRA but also setting the swap control to get the reversed
component order. Tested on R580 and little endian CPU.

Bugzilla: https://bugs.freedesktop.org/show_bug.cgi?id=71789

Cc: 11.1 11.2 <mesa-stable at lists.freedesktop.org>
---
 src/gallium/drivers/r300/r300_reg.h     | 20 ++++-----
 src/gallium/drivers/r300/r300_texture.c | 72 +++++++++++++++++++++++++++++++--
 2 files changed, 77 insertions(+), 15 deletions(-)

diff --git a/src/gallium/drivers/r300/r300_reg.h b/src/gallium/drivers/r300/r300_reg.h
index 9c373c5..9c93b84 100644
--- a/src/gallium/drivers/r300/r300_reg.h
+++ b/src/gallium/drivers/r300/r300_reg.h
@@ -1700,10 +1700,7 @@ USE OR OTHER DEALINGS IN THE SOFTWARE.
 #define R300_TX_OFFSET_6                    0x4558
 #define R300_TX_OFFSET_7                    0x455C
 
-#       define R300_TXO_ENDIAN_NO_SWAP           (0 << 0)
-#       define R300_TXO_ENDIAN_BYTE_SWAP         (1 << 0)
-#       define R300_TXO_ENDIAN_WORD_SWAP         (2 << 0)
-#       define R300_TXO_ENDIAN_HALFDW_SWAP       (3 << 0)
+#       define R300_TXO_ENDIAN(x)                ((x) << 0)
 #       define R300_TXO_MACRO_TILE_LINEAR        (0 << 2)
 #       define R300_TXO_MACRO_TILE_TILED         (1 << 2)
 #       define R300_TXO_MACRO_TILE(x)            ((x) << 2)
@@ -2418,10 +2415,7 @@ USE OR OTHER DEALINGS IN THE SOFTWARE.
 #       define R300_COLOR_MICROTILE_ENABLE        (1 << 17)
 #       define R300_COLOR_MICROTILE_ENABLE_SQUARE (2 << 17) /* Only available in 16-bit */
 #       define R300_COLOR_MICROTILE(x)            ((x) << 17)
-#       define R300_COLOR_ENDIAN_NO_SWAP          (0 << 19)
-#       define R300_COLOR_ENDIAN_WORD_SWAP        (1 << 19)
-#       define R300_COLOR_ENDIAN_DWORD_SWAP       (2 << 19)
-#       define R300_COLOR_ENDIAN_HALF_DWORD_SWAP  (3 << 19)
+#       define R300_COLOR_ENDIAN(x)               ((x) << 19)
 #	define R500_COLOR_FORMAT_ARGB10101010     (0 << 21)
 #	define R500_COLOR_FORMAT_UV1010           (1 << 21)
 #	define R500_COLOR_FORMAT_CI8              (2 << 21) /* 2D only */
@@ -2693,10 +2687,12 @@ USE OR OTHER DEALINGS IN THE SOFTWARE.
 #       define R300_DEPTHMICROTILE_TILED        (1 << 17)
 #       define R300_DEPTHMICROTILE_TILED_SQUARE (2 << 17)
 #       define R300_DEPTHMICROTILE(x)           ((x) << 17)
-#       define R300_DEPTHENDIAN_NO_SWAP         (0 << 18)
-#       define R300_DEPTHENDIAN_WORD_SWAP       (1 << 18)
-#       define R300_DEPTHENDIAN_DWORD_SWAP      (2 << 18)
-#       define R300_DEPTHENDIAN_HALF_DWORD_SWAP (3 << 18)
+#       define R300_DEPTHENDIAN(x)              ((x) << 19)
+
+#define R300_SURF_NO_SWAP         0
+#define R300_SURF_WORD_SWAP       1
+#define R300_SURF_DWORD_SWAP      2
+#define R300_SURF_HALF_DWORD_SWAP 3
 
 /* Z Buffer Clear Value */
 #define R300_ZB_DEPTHCLEARVALUE                  0x4f28
diff --git a/src/gallium/drivers/r300/r300_texture.c b/src/gallium/drivers/r300/r300_texture.c
index df01673..14372da 100644
--- a/src/gallium/drivers/r300/r300_texture.c
+++ b/src/gallium/drivers/r300/r300_texture.c
@@ -38,6 +38,63 @@
 
 #include "pipe/p_screen.h"
 
+/* These formats are supported by swapping their bytes.
+ * The swizzles must be set exactly like their non-swapped counterparts,
+ * because byte-swapping is what reverses the component order, not swizzling.
+ *
+ * This function returns the format that must be used to program CB and TX
+ * swizzles.
+ */
+static enum pipe_format r300_unbyteswap_array_format(enum pipe_format format)
+{
+    /* Only BGRA 8888 array formats are supported for simplicity of
+     * the implementation. */
+    switch (format) {
+    case PIPE_FORMAT_A8R8G8B8_UNORM:
+        return PIPE_FORMAT_B8G8R8A8_UNORM;
+    case PIPE_FORMAT_A8R8G8B8_SRGB:
+        return PIPE_FORMAT_B8G8R8A8_SRGB;
+    case PIPE_FORMAT_X8R8G8B8_UNORM:
+        return PIPE_FORMAT_B8G8R8X8_UNORM;
+    case PIPE_FORMAT_X8R8G8B8_SRGB:
+        return PIPE_FORMAT_B8G8R8X8_SRGB;
+    default:
+        return format;
+    }
+}
+
+static unsigned r300_get_endian_swap(enum pipe_format format)
+{
+    const struct util_format_description *desc;
+    unsigned swap_size;
+
+    if (r300_unbyteswap_array_format(format) != format)
+        return R300_SURF_DWORD_SWAP;
+
+    if (PIPE_ENDIAN_NATIVE != PIPE_ENDIAN_BIG)
+        return R300_SURF_NO_SWAP;
+
+    desc = util_format_description(format);
+    if (!desc)
+        return R300_SURF_NO_SWAP;
+
+    /* Compressed formats should be in the little endian format. */
+    if (desc->block.width != 1 || desc->block.height != 1)
+        return R300_SURF_NO_SWAP;
+
+    swap_size = desc->is_array ? desc->channel[0].size : desc->block.bits;
+
+    switch (swap_size) {
+    default: /* shouldn't happen? */
+    case 8:
+        return R300_SURF_NO_SWAP;
+    case 16:
+        return R300_SURF_WORD_SWAP;
+    case 32:
+        return R300_SURF_DWORD_SWAP;
+    }
+}
+
 unsigned r300_get_swizzle_combined(const unsigned char *swizzle_format,
                                    const unsigned char *swizzle_view,
                                    boolean dxtc_swizzle)
@@ -118,6 +175,7 @@ uint32_t r300_translate_texformat(enum pipe_format format,
         R300_TX_FORMAT_SIGNED_X,
     };
 
+    format = r300_unbyteswap_array_format(format);
     desc = util_format_description(format);
 
     /* Colorspace (return non-RGB formats directly). */
@@ -400,6 +458,8 @@ uint32_t r500_tx_format_msb_bit(enum pipe_format format)
  * output. For the swizzling of the targets, check the shader's format. */
 static uint32_t r300_translate_colorformat(enum pipe_format format)
 {
+    format = r300_unbyteswap_array_format(format);
+
     switch (format) {
         /* 8-bit buffers. */
         case PIPE_FORMAT_A8_UNORM:
@@ -534,6 +594,7 @@ static uint32_t r300_translate_out_fmt(enum pipe_format format)
     const struct util_format_description *desc;
     boolean uniform_sign;
 
+    format = r300_unbyteswap_array_format(format);
     desc = util_format_description(format);
 
     /* Find the first non-VOID channel. */
@@ -730,6 +791,8 @@ static uint32_t r300_translate_out_fmt(enum pipe_format format)
 
 static uint32_t r300_translate_colormask_swizzle(enum pipe_format format)
 {
+    format = r300_unbyteswap_array_format(format);
+
     switch (format) {
     case PIPE_FORMAT_A8_UNORM:
     case PIPE_FORMAT_A8_SNORM:
@@ -918,7 +981,8 @@ void r300_texture_setup_format_state(struct r300_screen *screen,
     }
 
     out->tile_config = R300_TXO_MACRO_TILE(desc->macrotile[level]) |
-                       R300_TXO_MICRO_TILE(desc->microtile);
+                       R300_TXO_MICRO_TILE(desc->microtile) |
+                       R300_TXO_ENDIAN(r300_get_endian_swap(format));
 }
 
 static void r300_texture_setup_fb_state(struct r300_surface *surf)
@@ -933,7 +997,8 @@ static void r300_texture_setup_fb_state(struct r300_surface *surf)
         surf->pitch =
                 stride |
                 R300_DEPTHMACROTILE(tex->tex.macrotile[level]) |
-                R300_DEPTHMICROTILE(tex->tex.microtile);
+                R300_DEPTHMICROTILE(tex->tex.microtile) |
+                R300_DEPTHENDIAN(r300_get_endian_swap(surf->base.format));
         surf->format = r300_translate_zsformat(surf->base.format);
         surf->pitch_zmask = tex->tex.zmask_stride_in_pixels[level];
         surf->pitch_hiz = tex->tex.hiz_stride_in_pixels[level];
@@ -944,7 +1009,8 @@ static void r300_texture_setup_fb_state(struct r300_surface *surf)
                 stride |
                 r300_translate_colorformat(format) |
                 R300_COLOR_TILE(tex->tex.macrotile[level]) |
-                R300_COLOR_MICROTILE(tex->tex.microtile);
+                R300_COLOR_MICROTILE(tex->tex.microtile) |
+                R300_COLOR_ENDIAN(r300_get_endian_swap(format));
         surf->format = r300_translate_out_fmt(format);
         surf->colormask_swizzle =
             r300_translate_colormask_swizzle(format);
-- 
2.7.4



More information about the mesa-dev mailing list