diff options
author | Marek Olšák <maraeo@gmail.com> | 2010-05-03 22:56:27 +0200 |
---|---|---|
committer | Alex Deucher <alexdeucher@gmail.com> | 2010-05-04 17:35:46 -0400 |
commit | 766024dcc61c83490540910ce752f9bfe6dddba4 (patch) | |
tree | 6d9d9f95e78d13852a5540bf4bd7ce6612c873f2 /src/radeon_exa.c | |
parent | 6aedd57f6c2f08d0151a8bd1c5893d40d3db709a (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.c | 41 |
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; |