intel-gem: Move bit 6 x tiling swizzle to a driconf option, and add new mode.
authorEric Anholt <eric@anholt.net>
Tue, 1 Jul 2008 22:09:24 +0000 (15:09 -0700)
committerEric Anholt <eric@anholt.net>
Tue, 1 Jul 2008 23:14:08 +0000 (16:14 -0700)
It turns out that it's not just deviceID dependent, and there's some additional
undefined factor that determines the bit 6 swizzling.  It's now controllable
with swizzle_mode=[012] until we get a response on how to automatically detect.

src/mesa/drivers/dri/intel/intel_context.c
src/mesa/drivers/dri/intel/intel_context.h
src/mesa/drivers/dri/intel/intel_screen.c
src/mesa/drivers/dri/intel/intel_span.c

index 46acf79..33b8843 100644 (file)
@@ -697,6 +697,9 @@ intelInitContext(struct intel_context *intel,
       intel->no_rast = 1;
    }
 
+   intel->tiling_swizzle_mode = driQueryOptioni(&intel->optionCache,
+                                               "swizzle_mode");
+
    /* Disable all hardware rendering (skip emitting batches and fences/waits
     * to the kernel)
     */
index f1116d2..6ed9a37 100644 (file)
@@ -266,6 +266,7 @@ struct intel_context
    GLuint lastStamp;
 
    GLboolean no_hw;
+   int tiling_swizzle_mode;
 
    /**
     * Configuration cache
index 8fd503e..6597dbf 100644 (file)
@@ -69,13 +69,20 @@ PUBLIC const char __driConfigOptions[] =
    DRI_CONF_SECTION_QUALITY
       DRI_CONF_FORCE_S3TC_ENABLE(false)
       DRI_CONF_ALLOW_LARGE_TEXTURES(2)
+      DRI_CONF_OPT_BEGIN_V(swizzle_mode, enum, 0, "0:2")
+        DRI_CONF_DESC_BEGIN(en, "Tiling swizzle mode for software fallbacks")
+           DRI_CONF_ENUM(0, "No swizzling")
+           DRI_CONF_ENUM(1, "addr[6] = addr[6] ^ addr[9]")
+           DRI_CONF_ENUM(2, "addr[6] = addr[6] ^ addr[9] ^ addr[10]")
+        DRI_CONF_DESC_END
+      DRI_CONF_OPT_END
    DRI_CONF_SECTION_END
    DRI_CONF_SECTION_DEBUG
      DRI_CONF_NO_RAST(false)
    DRI_CONF_SECTION_END
 DRI_CONF_END;
 
-const GLuint __driNConfigOptions = 6;
+const GLuint __driNConfigOptions = 7;
 
 #ifdef USE_NEW_INTERFACE
 static PFNGLXCREATECONTEXTMODES create_context_modes = NULL;
index c6778b1..8d7d913 100644 (file)
@@ -106,29 +106,46 @@ static GLubyte *x_tile_swizzle(struct intel_renderbuffer *irb, struct intel_cont
        x_tile_off = xbyte & 0x1ff;
        y_tile_off = y & 7;
 
-#ifndef I915
-       /* The documentation says that X tile layout is arranged in 8 512-byte
-        * lines of pixel data.  However, that doesn't appear to be the case
-        * on GM965, tested by drawing a 128x8 quad in no_rast mode.  For lines
-        * 1,2,4, and 7 of each tile, each consecutive pair of 64-byte spans
-        * has the locations of those spans swapped.
+       x_tile_number = xbyte >> 9;
+       y_tile_number = y >> 3;
+
+       tile_off = (y_tile_off << 9) + x_tile_off;
+
+       /* bit swizzling tricks your parents never told you about:
+        *
+        * The specs say that the X tiling layout is just 8 512-byte rows
+        * packed into a page.  It turns out that there's some additional
+        * swizzling of bit 6 to reduce cache aliasing issues.  Experimental
+        * results below:
+        *
+        * line    bit   GM965  945G/Q965
+        *      9 10 11
+        * 0    0  0  0  0      0
+        * 1    0  1  0  1      1
+        * 2    1  0  0  1      1
+        * 3    1  1  0  0      0
+        * 4    0  0  1  1      0
+        * 5    0  1  1  0      1
+        * 6    1  0  1  0      1
+        * 7    1  1  1  1      0
+        *
+        * So we see that the GM965 is bit 6 ^ 9 ^ 10 ^ 11, while other
+        * parts were just 6 ^ 9 ^ 10.  However, some systems, including a
+        * GM965 we've seen, don't perform the swizzling at all.  Information
+        * on how to detect it through register reads is expected soon.
         */
-       switch (y_tile_off) {
+       switch (intel->tiling_swizzle_mode) {
+       case 0:
+          break;
        case 1:
+          tile_off ^= ((tile_off >> 3) & 64) ^ ((tile_off >> 4) & 64);
+          break;
        case 2:
-       case 4:
-       case 7:
-               x_tile_off ^= 64;
-               break;
-       default:
+          tile_off ^= ((tile_off >> 3) & 64) ^ ((tile_off >> 4) & 64) ^
+             ((tile_off >> 5) & 64);
           break;
        }
-#endif
-
-       x_tile_number = xbyte >> 9;
-       y_tile_number = y >> 3;
 
-       tile_off = (y_tile_off << 9) + x_tile_off;
        tile_base = (x_tile_number << 12) + y_tile_number * tile_stride;
 
 #if 0