summaryrefslogtreecommitdiff
path: root/src/radeon_exa.c
diff options
context:
space:
mode:
authorMarek Olšák <maraeo@gmail.com>2010-05-03 22:56:27 +0200
committerAlex Deucher <alexdeucher@gmail.com>2010-05-04 17:35:46 -0400
commit766024dcc61c83490540910ce752f9bfe6dddba4 (patch)
tree6d9d9f95e78d13852a5540bf4bd7ce6612c873f2 /src/radeon_exa.c
parent6aedd57f6c2f08d0151a8bd1c5893d40d3db709a (diff)
r3xx-r5xx: fix texturing with small macrotiled pixmaps
Pixmaps smaller than a macrotile cannot be used as textures because hardware automatically switches to macro-linear and therefore sampled pixels are messed up. This behavior is known as MACRO_SWITCH. The only sane workaround seems to be not using macrotiling for small pixmaps. The function RADEONMacroSwitch has been ported from r300g and implements MACRO_SWITCH the same way it's implemented in hardware. It's been well tested in r300g. This commit also fixes blit-based framebuffer reads, which are used for tiled surfaces in r300g, when ColorTiling is enabled. Signed-off-by: Marek Olšák <maraeo@gmail.com>
Diffstat (limited to 'src/radeon_exa.c')
-rw-r--r--src/radeon_exa.c41
1 files changed, 41 insertions, 0 deletions
diff --git a/src/radeon_exa.c b/src/radeon_exa.c
index 217a0fef..b285f65c 100644
--- a/src/radeon_exa.c
+++ b/src/radeon_exa.c
@@ -391,6 +391,37 @@ void *RADEONEXACreatePixmap(ScreenPtr pScreen, int size, int align)
}
+static const unsigned MicroBlockTable[5][3][2] = {
+ /*linear tiled square-tiled */
+ {{32, 1}, {8, 4}, {0, 0}}, /* 8 bits per pixel */
+ {{16, 1}, {8, 2}, {4, 4}}, /* 16 bits per pixel */
+ {{ 8, 1}, {4, 2}, {0, 0}}, /* 32 bits per pixel */
+ {{ 4, 1}, {0, 0}, {2, 2}}, /* 64 bits per pixel */
+ {{ 2, 1}, {0, 0}, {0, 0}} /* 128 bits per pixel */
+};
+
+/* Return true if macrotiling can be enabled */
+static Bool RADEONMacroSwitch(int width, int height, int bpp,
+ uint32_t flags, Bool rv350_mode)
+{
+ unsigned tilew, tileh, microtiled, logbpp;
+
+ logbpp = RADEONLog2(bpp / 8);
+ if (logbpp > 4)
+ return 0;
+
+ microtiled = !!(flags & RADEON_TILING_MICRO);
+ tilew = MicroBlockTable[logbpp][microtiled][0] * 8;
+ tileh = MicroBlockTable[logbpp][microtiled][1] * 8;
+
+ /* See TX_FILTER1_n.MACRO_SWITCH. */
+ if (rv350_mode) {
+ return width >= tilew && height >= tileh;
+ } else {
+ return width > tilew && height > tileh;
+ }
+}
+
void *RADEONEXACreatePixmap2(ScreenPtr pScreen, int width, int height,
int depth, int usage_hint, int bitsPerPixel,
int *new_pitch)
@@ -420,6 +451,16 @@ void *RADEONEXACreatePixmap2(ScreenPtr pScreen, int width, int height,
}
}
+ /* Small pixmaps must not be macrotiled on R300, hw cannot sample them
+ * correctly because samplers automatically switch to macrolinear. */
+ if (info->ChipFamily >= CHIP_FAMILY_R300 &&
+ info->ChipFamily <= CHIP_FAMILY_RS690 &&
+ (tiling & RADEON_TILING_MACRO) &&
+ !RADEONMacroSwitch(width, height, bitsPerPixel, tiling,
+ info->ChipFamily >= CHIP_FAMILY_RV350)) {
+ tiling &= ~RADEON_TILING_MACRO;
+ }
+
if (tiling) {
height = RADEON_ALIGN(height, 16);
pixmap_align = 256;