r300g: fix texturing with sizes > 2048 on r500
authorMarek Olšák <maraeo@gmail.com>
Fri, 8 Apr 2011 01:11:22 +0000 (03:11 +0200)
committerMarek Olšák <maraeo@gmail.com>
Fri, 8 Apr 2011 02:38:36 +0000 (04:38 +0200)
src/gallium/drivers/r300/r300_chipset.c
src/gallium/drivers/r300/r300_chipset.h
src/gallium/drivers/r300/r300_context.h
src/gallium/drivers/r300/r300_emit.c
src/gallium/drivers/r300/r300_screen.c
src/gallium/drivers/r300/r300_state_derived.c
src/gallium/drivers/r300/r300_texture.c

index 990acea9f445c0a8692d82e50159e306511cd72d..1068d357c9442136678f26f6b89de77fd5f315e5 100644 (file)
@@ -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;
 }
index 68943d561ba7de9761920c534ab1b0c81620789e..3777f0cfae3acffed051af64bc6dea45aa0e9700 100644 (file)
@@ -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. */
index 550d3a75d2751a6ad5cb8bbd09243142e377a8f6..c1f766f61806af130fe8b46d500a125ebca8bfb3 100644 (file)
@@ -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 {
index 6b91f93e6d69701fd2f996ee709b0d664f46a34f..a21668a6fc59a609b729d04bfc87c1233558347e 100644 (file)
@@ -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;
index 07d854d633caaba3b96c885a9efe86e1c93cd58f..eb1b45235335cc5dc2355cb45dab7851ff6ddca0 100644 (file)
@@ -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,
index e943f1a715f4ae4fd77330dd1be33a9ce7de5c7b..c80cf7860cbe152917fb11b3a982b35810b7537c 100644 (file)
@@ -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;
             }
         }
index ea6d9824030b80b21921db62b4dce2cc4ea32f60..47d1c3ef75ec574d92c50555f9bcfefd1efa9008 100644 (file)
@@ -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]) |