From 10ea8567f49f4daaa654b6e4c365a816f855073b Mon Sep 17 00:00:00 2001 From: =?utf8?q?Marek=20Ol=C5=A1=C3=A1k?= Date: Fri, 8 Apr 2011 03:11:22 +0200 Subject: [PATCH] r300g: fix texturing with sizes > 2048 on r500 --- src/gallium/drivers/r300/r300_chipset.c | 1 + src/gallium/drivers/r300/r300_chipset.h | 2 + src/gallium/drivers/r300/r300_context.h | 3 +- src/gallium/drivers/r300/r300_emit.c | 6 +++ src/gallium/drivers/r300/r300_screen.c | 3 ++ src/gallium/drivers/r300/r300_state_derived.c | 5 ++- src/gallium/drivers/r300/r300_texture.c | 40 ++++++++++++++++--- 7 files changed, 52 insertions(+), 8 deletions(-) diff --git a/src/gallium/drivers/r300/r300_chipset.c b/src/gallium/drivers/r300/r300_chipset.c index 990acea9f44..1068d357c94 100644 --- a/src/gallium/drivers/r300/r300_chipset.c +++ b/src/gallium/drivers/r300/r300_chipset.c @@ -419,4 +419,5 @@ void r300_parse_chipset(struct r300_capabilities* caps) caps->is_rv350 = caps->family >= CHIP_FAMILY_RV350; caps->z_compress = caps->is_rv350 ? R300_ZCOMP_8X8 : R300_ZCOMP_4X4; caps->dxtc_swizzle = caps->is_r400 || caps->is_r500; + caps->has_us_format = caps->is_r500; } diff --git a/src/gallium/drivers/r300/r300_chipset.h b/src/gallium/drivers/r300/r300_chipset.h index 68943d561ba..3777f0cfae3 100644 --- a/src/gallium/drivers/r300/r300_chipset.h +++ b/src/gallium/drivers/r300/r300_chipset.h @@ -90,6 +90,8 @@ struct r300_capabilities { boolean high_second_pipe; /* DXTC texture swizzling. */ boolean dxtc_swizzle; + /* Whether R500_US_FORMAT0_0 is supported (depends on DRM). */ + boolean has_us_format; }; /* Enumerations for legibility and telling which card we're running on. */ diff --git a/src/gallium/drivers/r300/r300_context.h b/src/gallium/drivers/r300/r300_context.h index 550d3a75d27..c1f766f6180 100644 --- a/src/gallium/drivers/r300/r300_context.h +++ b/src/gallium/drivers/r300/r300_context.h @@ -190,6 +190,7 @@ struct r300_texture_format_state { uint32_t format1; /* R300_TX_FORMAT1: 0x44c0 */ uint32_t format2; /* R300_TX_FORMAT2: 0x4500 */ uint32_t tile_config; /* R300_TX_OFFSET (subset thereof) */ + uint32_t us_format0; /* R500_US_FORMAT0_0: 0x4640 (through 15) */ }; struct r300_sampler_view { @@ -211,7 +212,7 @@ struct r300_texture_sampler_state { struct r300_texture_format_state format; uint32_t filter0; /* R300_TX_FILTER0: 0x4400 */ uint32_t filter1; /* R300_TX_FILTER1: 0x4440 */ - uint32_t border_color; /* R300_TX_BORDER_COLOR: 0x45c0 */ + uint32_t border_color; /* R300_TX_BORDER_COLOR: 0x45c0 */ }; struct r300_textures_state { diff --git a/src/gallium/drivers/r300/r300_emit.c b/src/gallium/drivers/r300/r300_emit.c index 6b91f93e6d6..a21668a6fc5 100644 --- a/src/gallium/drivers/r300/r300_emit.c +++ b/src/gallium/drivers/r300/r300_emit.c @@ -775,6 +775,7 @@ void r300_emit_textures_state(struct r300_context *r300, struct r300_texture_sampler_state *texstate; struct r300_resource *tex; unsigned i; + boolean has_us_format = r300->screen->caps.has_us_format; CS_LOCALS(r300); BEGIN_CS(size); @@ -796,6 +797,11 @@ void r300_emit_textures_state(struct r300_context *r300, OUT_CS_REG(R300_TX_OFFSET_0 + (i * 4), texstate->format.tile_config); OUT_CS_RELOC(tex); + + if (has_us_format) { + OUT_CS_REG(R500_US_FORMAT0_0 + (i * 4), + texstate->format.us_format0); + } } } END_CS; diff --git a/src/gallium/drivers/r300/r300_screen.c b/src/gallium/drivers/r300/r300_screen.c index 07d854d633c..eb1b4523533 100644 --- a/src/gallium/drivers/r300/r300_screen.c +++ b/src/gallium/drivers/r300/r300_screen.c @@ -482,6 +482,9 @@ struct pipe_screen* r300_screen_create(struct r300_winsys_screen *rws) if (SCREEN_DBG_ON(r300screen, DBG_NO_HIZ)) r300screen->caps.hiz_ram = 0; + if (!rws->get_value(rws, R300_VID_DRM_2_8_0)) + r300screen->caps.has_us_format = FALSE; + pipe_mutex_init(r300screen->num_contexts_mutex); util_slab_create(&r300screen->pool_buffers, diff --git a/src/gallium/drivers/r300/r300_state_derived.c b/src/gallium/drivers/r300/r300_state_derived.c index e943f1a715f..c80cf7860cb 100644 --- a/src/gallium/drivers/r300/r300_state_derived.c +++ b/src/gallium/drivers/r300/r300_state_derived.c @@ -771,6 +771,7 @@ static void r300_merge_textures_and_samplers(struct r300_context* r300) unsigned min_level, max_level, i, j, size; unsigned count = MIN2(state->sampler_view_count, state->sampler_state_count); + boolean has_us_format = r300->screen->caps.has_us_format; /* The KIL opcode fix, see below. */ if (!count && !r300->screen->caps.is_r500) @@ -923,7 +924,7 @@ static void r300_merge_textures_and_samplers(struct r300_context* r300) texstate->filter0 |= i << 28; - size += 16; + size += 16 + (has_us_format ? 2 : 0); state->count = i+1; } else { /* For the KIL opcode to work on r3xx-r4xx, the texture unit @@ -952,7 +953,7 @@ static void r300_merge_textures_and_samplers(struct r300_context* r300) texstate->border_color = 0; texstate->filter0 |= i << 28; - size += 16; + size += 16 + (has_us_format ? 2 : 0); state->count = i+1; } } diff --git a/src/gallium/drivers/r300/r300_texture.c b/src/gallium/drivers/r300/r300_texture.c index ea6d9824030..47d1c3ef75e 100644 --- a/src/gallium/drivers/r300/r300_texture.c +++ b/src/gallium/drivers/r300/r300_texture.c @@ -751,6 +751,16 @@ void r300_texture_setup_format_state(struct r300_screen *screen, struct pipe_resource *pt = &tex->b.b.b; struct r300_texture_desc *desc = &tex->tex; boolean is_r500 = screen->caps.is_r500; + unsigned width, height, depth; + unsigned txwidth, txheight, txdepth; + + width = u_minify(desc->width0, level); + height = u_minify(desc->height0, level); + depth = u_minify(desc->depth0, level); + + txwidth = (width - 1) & 0x7ff; + txheight = (height - 1) & 0x7ff; + txdepth = util_logbase2(depth) & 0xf; /* Mask out all the fields we change. */ out->format0 = 0; @@ -760,9 +770,9 @@ void r300_texture_setup_format_state(struct r300_screen *screen, /* Set sampler state. */ out->format0 = - R300_TX_WIDTH((u_minify(desc->width0, level) - 1) & 0x7ff) | - R300_TX_HEIGHT((u_minify(desc->height0, level) - 1) & 0x7ff) | - R300_TX_DEPTH(util_logbase2(u_minify(desc->depth0, level)) & 0xf); + R300_TX_WIDTH(txwidth) | + R300_TX_HEIGHT(txheight) | + R300_TX_DEPTH(txdepth); if (desc->uses_stride_addressing) { /* rectangles love this */ @@ -780,12 +790,32 @@ void r300_texture_setup_format_state(struct r300_screen *screen, /* large textures on r500 */ if (is_r500) { - if (desc->width0 > 2048) { + unsigned us_width = txwidth; + unsigned us_height = txheight; + unsigned us_depth = txdepth; + + if (width > 2048) { out->format2 |= R500_TXWIDTH_BIT11; } - if (desc->height0 > 2048) { + if (height > 2048) { out->format2 |= R500_TXHEIGHT_BIT11; } + + /* The US_FORMAT register fixes an R500 TX addressing bug. + * Don't ask why it must be set like this. I don't know it either. */ + if (width > 2048) { + us_width = (0x000007FF + us_width) >> 1; + us_depth |= 0x0000000D; + } + if (height > 2048) { + us_height = (0x000007FF + us_height) >> 1; + us_depth |= 0x0000000E; + } + + out->us_format0 = + R300_TX_WIDTH(us_width) | + R300_TX_HEIGHT(us_height) | + R300_TX_DEPTH(us_depth); } out->tile_config = R300_TXO_MACRO_TILE(desc->macrotile[level]) | -- 2.30.2