r300: Fix corner-case of KIL on R300
authorNicolai Hähnle <nhaehnle@gmail.com>
Sat, 1 Aug 2009 16:58:47 +0000 (18:58 +0200)
committerNicolai Hähnle <nhaehnle@gmail.com>
Sat, 1 Aug 2009 17:00:55 +0000 (19:00 +0200)
R300 hardware (but _not_ R500) hardware requires an enabled texture unit
if KIL is used in fragment programs. We now work around the CS checker
correctly when enabling such a fake texture unit.

Signed-off-by: Nicolai Hähnle <nhaehnle@gmail.com>
src/mesa/drivers/dri/r300/r300_cmdbuf.c
src/mesa/drivers/dri/r300/r300_state.c

index af535037d0635612a536a9c48a7dfe17e49b701c..7eb11aaf271fefd9e82e4f77304adba2841baa15 100644 (file)
@@ -164,47 +164,43 @@ static void emit_tex_offsets(GLcontext *ctx, struct radeon_state_atom * atom)
        r300ContextPtr r300 = R300_CONTEXT(ctx);
        BATCH_LOCALS(&r300->radeon);
        int numtmus = packet0_count(r300, r300->hw.tex.offset.cmd);
-       int notexture = 0;
-
-       if (numtmus) {
-               int i;
-
-               for(i = 0; i < numtmus; ++i) {
-                   radeonTexObj *t = r300->hw.textures[i];
-
-                   if (!t)
-                       notexture = 1;
-               }
-
-               if (r300->radeon.radeonScreen->kernel_mm && notexture) {
-                       return;
-               }
-               for(i = 0; i < numtmus; ++i) {
-                   radeonTexObj *t = r300->hw.textures[i];
-                   if (t && !t->image_override) {
-                BEGIN_BATCH_NO_AUTOSTATE(4);
-                OUT_BATCH_REGSEQ(R300_TX_OFFSET_0 + (i * 4), 1);
-                           OUT_BATCH_RELOC(t->tile_bits, t->mt->bo, 0,
-                                           RADEON_GEM_DOMAIN_GTT|RADEON_GEM_DOMAIN_VRAM, 0, 0);
-                END_BATCH();
-                   } else if (!t) {
-                /* Texture unit hasn't a texture bound nothings to do */
-                   } else { /* override cases */
-                           if (t->bo) {
-                    BEGIN_BATCH_NO_AUTOSTATE(4);
-                    OUT_BATCH_REGSEQ(R300_TX_OFFSET_0 + (i * 4), 1);
-                                   OUT_BATCH_RELOC(t->tile_bits, t->bo, 0,
-                                                   RADEON_GEM_DOMAIN_GTT|RADEON_GEM_DOMAIN_VRAM, 0, 0);
-                    END_BATCH();
-                           } else if (!r300->radeon.radeonScreen->kernel_mm) {
-                    BEGIN_BATCH_NO_AUTOSTATE(2);
-                    OUT_BATCH_REGSEQ(R300_TX_OFFSET_0 + (i * 4), 1);
-                                   OUT_BATCH(t->override_offset);
-                    END_BATCH();
-                           } else {
-                    /* Texture unit hasn't a texture bound nothings to do */
-                }
-                   }
+       int i;
+
+       for(i = 0; i < numtmus; ++i) {
+               radeonTexObj *t = r300->hw.textures[i];
+               if (t && !t->image_override) {
+                       BEGIN_BATCH_NO_AUTOSTATE(4);
+                       OUT_BATCH_REGSEQ(R300_TX_OFFSET_0 + (i * 4), 1);
+                       OUT_BATCH_RELOC(t->tile_bits, t->mt->bo, 0,
+                                       RADEON_GEM_DOMAIN_GTT|RADEON_GEM_DOMAIN_VRAM, 0, 0);
+                       END_BATCH();
+               } else if (!t) {
+                       /* Texture unit hasn't a texture bound.
+                        * We assign the current color buffer as a fakery to make
+                        * KIL work. */
+                       struct radeon_renderbuffer *rrb = radeon_get_colorbuffer(&r300->radeon);
+                       if (rrb && rrb->bo) {
+                               BEGIN_BATCH_NO_AUTOSTATE(4);
+                               OUT_BATCH_REGSEQ(R300_TX_OFFSET_0 + (i * 4), 1);
+                               OUT_BATCH_RELOC(0, rrb->bo, 0,
+                                               RADEON_GEM_DOMAIN_GTT|RADEON_GEM_DOMAIN_VRAM, 0, 0);
+                               END_BATCH();
+                       }
+               } else { /* override cases */
+                       if (t->bo) {
+                               BEGIN_BATCH_NO_AUTOSTATE(4);
+                               OUT_BATCH_REGSEQ(R300_TX_OFFSET_0 + (i * 4), 1);
+                               OUT_BATCH_RELOC(t->tile_bits, t->bo, 0,
+                                               RADEON_GEM_DOMAIN_GTT|RADEON_GEM_DOMAIN_VRAM, 0, 0);
+                               END_BATCH();
+                       } else if (!r300->radeon.radeonScreen->kernel_mm) {
+                               BEGIN_BATCH_NO_AUTOSTATE(2);
+                               OUT_BATCH_REGSEQ(R300_TX_OFFSET_0 + (i * 4), 1);
+                               OUT_BATCH(t->override_offset);
+                               END_BATCH();
+                       } else {
+                               /* Texture unit hasn't a texture bound nothings to do */
+                       }
                }
        }
 }
index 3c6e54473076a760b48867f7b88534ec20477d63..050e8cd2a7daf35ffb4f1676135ac3d55b25d80b 100644 (file)
@@ -1253,6 +1253,7 @@ static GLuint translate_lod_bias(GLfloat bias)
        return (((GLuint)b) << R300_LOD_BIAS_SHIFT) & R300_LOD_BIAS_MASK;
 }
 
+
 static void r300SetupTextures(GLcontext * ctx)
 {
        int i, mtu;
@@ -1345,6 +1346,28 @@ static void r300SetupTextures(GLcontext * ctx)
                }
        }
 
+       /* R3xx and R4xx chips require that the texture unit corresponding to
+        * KIL instructions is really enabled.
+        *
+        * We do some fakery here and in the state atom emit logic to enable
+        * the texture without tripping up the CS checker in the kernel.
+        */
+       if (r300->radeon.radeonScreen->chip_family < CHIP_FAMILY_RV515) {
+               if (ctx->FragmentProgram._Current->UsesKill && last_hw_tmu < 0) {
+                       last_hw_tmu++;
+
+                       r300->hw.txe.cmd[R300_TXE_ENABLE] |= 1;
+
+                       r300->hw.tex.border_color.cmd[R300_TEX_VALUE_0] = 0;
+                       r300->hw.tex.chroma_key.cmd[R300_TEX_VALUE_0] = 0;
+                       r300->hw.tex.filter.cmd[R300_TEX_VALUE_0] = 0;
+                       r300->hw.tex.filter_1.cmd[R300_TEX_VALUE_0] = 0;
+                       r300->hw.tex.size.cmd[R300_TEX_VALUE_0] = 0; /* 1x1 texture */
+                       r300->hw.tex.format.cmd[R300_TEX_VALUE_0] = 0; /* A8 format */
+                       r300->hw.tex.pitch.cmd[R300_TEX_VALUE_0] = 0;
+               }
+       }
+
        r300->hw.tex.filter.cmd[R300_TEX_CMD_0] =
            cmdpacket0(r300->radeon.radeonScreen, R300_TX_FILTER0_0, last_hw_tmu + 1);
        r300->hw.tex.filter_1.cmd[R300_TEX_CMD_0] =
@@ -1362,16 +1385,6 @@ static void r300SetupTextures(GLcontext * ctx)
        r300->hw.tex.border_color.cmd[R300_TEX_CMD_0] =
            cmdpacket0(r300->radeon.radeonScreen, R300_TX_BORDER_COLOR_0, last_hw_tmu + 1);
 
-       if (r300->radeon.radeonScreen->chip_family < CHIP_FAMILY_RV515) {
-               if (ctx->FragmentProgram._Current->UsesKill && last_hw_tmu < 0) {
-                       // The KILL operation requires the first texture unit
-                       // to be enabled.
-                       r300->hw.txe.cmd[R300_TXE_ENABLE] |= 1;
-                       r300->hw.tex.filter.cmd[R300_TEX_VALUE_0] = 0;
-                       r300->hw.tex.filter.cmd[R300_TEX_CMD_0] =
-                               cmdpacket0(r300->radeon.radeonScreen, R300_TX_FILTER0_0, 1);
-               }
-       }
        r300->vtbl.SetupFragmentShaderTextures(ctx, tmu_mappings);
 
        if (RADEON_DEBUG & DEBUG_STATE)