Stencil support
authorPeter Zubaj <pzubaj@gaya.sk>
Mon, 14 Mar 2005 20:35:00 +0000 (20:35 +0000)
committerPeter Zubaj <pzubaj@gaya.sk>
Mon, 14 Mar 2005 20:35:00 +0000 (20:35 +0000)
Reflex from mesa demos doesn't work
TODO - double side stencil
I hope that I didn't break anything

src/mesa/drivers/dri/r300/r300_context.h
src/mesa/drivers/dri/r300/r300_ioctl.c
src/mesa/drivers/dri/r300/r300_reg.h
src/mesa/drivers/dri/r300/r300_state.c

index d956848..75aeb3e 100644 (file)
@@ -500,6 +500,12 @@ struct r300_depthbuffer_state {
        GLfloat scale;
 };
 
+struct r300_stencilbuffer_state {
+       GLuint clear;
+       GLboolean hw_stencil;
+
+};
+
 struct r300_vap_reg_state {
           /* input register assigments */
           int i_coords;
@@ -678,7 +684,9 @@ struct r300_state {
        struct {
                int transform_offset;  /* Transform matrix offset, -1 if none */
                } vap_param;  /* vertex processor parameter allocation - tells where to write parameters */
-       int hw_stencil;
+       
+       struct r300_stencilbuffer_state stencil;
+       
 };
 
 
index 45cff5b..31515c0 100644 (file)
@@ -58,6 +58,7 @@ WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
 
 #define CLEARBUFFER_COLOR      0x1
 #define CLEARBUFFER_DEPTH      0x2
+#define CLEARBUFFER_STENCIL    0x4
 
 static void r300ClearBuffer(r300ContextPtr r300, int flags, int buffer)
 {
@@ -205,8 +206,10 @@ static void r300ClearBuffer(r300ContextPtr r300, int flags, int buffer)
 
        R300_STATECHANGE(r300, zs);
        if (flags & CLEARBUFFER_DEPTH) {
-               r300->hw.zs.cmd[R300_ZS_CNTL_0] = 0x6; // test and write
-               r300->hw.zs.cmd[R300_ZS_CNTL_1] = (R300_ZS_ALWAYS<<R300_RB3D_ZS1_DEPTH_FUNC_SHIFT);
+               r300->hw.zs.cmd[R300_ZS_CNTL_0] &= R300_RB3D_STENCIL_ENABLE;
+               r300->hw.zs.cmd[R300_ZS_CNTL_0] |= 0x6; // test and write
+               r300->hw.zs.cmd[R300_ZS_CNTL_1] &= ~(R300_ZS_MASK << R300_RB3D_ZS1_DEPTH_FUNC_SHIFT);
+               r300->hw.zs.cmd[R300_ZS_CNTL_1] |= (R300_ZS_ALWAYS<<R300_RB3D_ZS1_DEPTH_FUNC_SHIFT);
 /*
                R300_STATECHANGE(r300, zb);
                r300->hw.zb.cmd[R300_ZB_OFFSET] =
@@ -217,8 +220,27 @@ static void r300ClearBuffer(r300ContextPtr r300, int flags, int buffer)
                        r300->radeon.radeonScreen->depthPitch;
 */
        } else {
-               r300->hw.zs.cmd[R300_ZS_CNTL_0] = 0; // disable
-               r300->hw.zs.cmd[R300_ZS_CNTL_1] = 0;
+               r300->hw.zs.cmd[R300_ZS_CNTL_0] &= R300_RB3D_STENCIL_ENABLE;
+               r300->hw.zs.cmd[R300_ZS_CNTL_0] |= R300_RB3D_Z_DISABLED_1; // disable
+               r300->hw.zs.cmd[R300_ZS_CNTL_1] &= ~(R300_ZS_MASK << R300_RB3D_ZS1_DEPTH_FUNC_SHIFT);
+       }
+       
+       R300_STATECHANGE(r300, zs);
+       if (flags & CLEARBUFFER_STENCIL) {
+               r300->hw.zs.cmd[R300_ZS_CNTL_0] &= ~R300_RB3D_STENCIL_ENABLE;
+               r300->hw.zs.cmd[R300_ZS_CNTL_0] |= R300_RB3D_STENCIL_ENABLE;
+               r300->hw.zs.cmd[R300_ZS_CNTL_1] &= 
+                   ~((R300_ZS_MASK << R300_RB3D_ZS1_FRONT_FUNC_SHIFT) | (R300_ZS_MASK << R300_RB3D_ZS1_BACK_FUNC_SHIFT));
+               r300->hw.zs.cmd[R300_ZS_CNTL_1] |= 
+                   (R300_ZS_ALWAYS<<R300_RB3D_ZS1_FRONT_FUNC_SHIFT) | 
+                   (R300_ZS_REPLACE<<R300_RB3D_ZS1_FRONT_FAIL_OP_SHIFT) |
+                   (R300_ZS_REPLACE<<R300_RB3D_ZS1_FRONT_ZPASS_OP_SHIFT) |
+                   (R300_ZS_REPLACE<<R300_RB3D_ZS1_FRONT_ZFAIL_OP_SHIFT) |
+                   (R300_ZS_ALWAYS<<R300_RB3D_ZS1_BACK_FUNC_SHIFT) |
+                   (R300_ZS_REPLACE<<R300_RB3D_ZS1_BACK_FAIL_OP_SHIFT) |
+                   (R300_ZS_REPLACE<<R300_RB3D_ZS1_BACK_ZPASS_OP_SHIFT) |
+                   (R300_ZS_REPLACE<<R300_RB3D_ZS1_BACK_ZFAIL_OP_SHIFT) ;
+               r300->hw.zs.cmd[R300_ZS_CNTL_2] = r300->state.stencil.clear;
        }
                        
        /* Make sure we have enough space */
@@ -314,6 +336,11 @@ static void r300Clear(GLcontext * ctx, GLbitfield mask, GLboolean all,
                bits |= CLEARBUFFER_DEPTH;
                mask &= ~DD_DEPTH_BIT;
        }
+       
+       if ( (mask & DD_STENCIL_BIT) && r300->state.stencil.hw_stencil) {
+               bits |= CLEARBUFFER_STENCIL;
+               mask &= ~DD_STENCIL_BIT;
+       }
 
        if (mask) {
                if (RADEON_DEBUG & DEBUG_FALLBACKS)
index f98e9b3..a9cb88c 100644 (file)
@@ -1109,7 +1109,7 @@ I am fairly certain that they are correct unless stated otherwise in comments.
 #       define R300_RB3D_Z_TEST                  0x00000012
 #       define R300_RB3D_Z_TEST_AND_WRITE        0x00000016
 #       define R300_RB3D_Z_WRITE_ONLY           0x00000006
-#      define R300_RB3D_STENCIL_ENABLE          (0<<1)  /* UNKNOWN yet.. */
+#      define R300_RB3D_STENCIL_ENABLE          0x00000001
 
 #define R300_RB3D_ZSTENCIL_CNTL_1                   0x4F04
                /* functions */
@@ -1148,6 +1148,7 @@ I am fairly certain that they are correct unless stated otherwise in comments.
 
 #define R300_RB3D_ZSTENCIL_CNTL_2                   0x4F08
 #      define R300_RB3D_ZS2_STENCIL_REF_SHIFT          0
+#      define R300_RB3D_ZS2_STENCIL_MASK               0xFF
 #      define R300_RB3D_ZS2_STENCIL_MASK_SHIFT         8
 #      define R300_RB3D_ZS2_STENCIL_WRITE_MASK_SHIFT   16
 
index 874bd85..c3c0120 100644 (file)
@@ -483,17 +483,15 @@ static void r300Enable(GLcontext* ctx, GLenum cap, GLboolean state)
                        else
                                newval = R300_RB3D_Z_TEST;
                } else
-                       newval = 0;
+                       newval = R300_RB3D_Z_DISABLED_1;
 
-               r300->hw.zs.cmd[R300_ZS_CNTL_0] = newval;
+               r300->hw.zs.cmd[R300_ZS_CNTL_0] &= R300_RB3D_STENCIL_ENABLE;
+               r300->hw.zs.cmd[R300_ZS_CNTL_0] |= newval;
                break;
 
        case GL_STENCIL_TEST:
-
-               WARN_ONCE("Do not know how to enable stencil. Help me !\n");
-
-               if (r300->state.hw_stencil) {
-                       //fprintf(stderr, "Stencil %s\n", state ? "enabled" : "disabled");
+               WARN_ONCE("TODO - double side stencil !\n");
+               if (r300->state.stencil.hw_stencil) {
                        R300_STATECHANGE(r300, zs);
                        if (state) {
                                r300->hw.zs.cmd[R300_ZS_CNTL_0] |=
@@ -609,7 +607,6 @@ static void r300DepthFunc(GLcontext* ctx, GLenum func)
                r300->hw.zs.cmd[R300_ZS_CNTL_1] |= R300_ZS_ALWAYS << R300_RB3D_ZS1_DEPTH_FUNC_SHIFT;
                break;
        }
-
 }
 
 
@@ -626,8 +623,9 @@ static void r300DepthMask(GLcontext* ctx, GLboolean mask)
                return;
 
        R300_STATECHANGE(r300, zs);
-       r300->hw.zs.cmd[R300_ZS_CNTL_0] = mask
-               ? R300_RB3D_Z_TEST_AND_WRITE : R300_RB3D_Z_TEST;
+       r300->hw.zs.cmd[R300_ZS_CNTL_0] &= R300_RB3D_STENCIL_ENABLE;
+       r300->hw.zs.cmd[R300_ZS_CNTL_0] |= mask 
+           ? R300_RB3D_Z_TEST_AND_WRITE : R300_RB3D_Z_TEST;
 }
 
 
@@ -866,8 +864,8 @@ static void r300StencilFunc(GLcontext * ctx, GLenum func,
 {
        r300ContextPtr rmesa = R300_CONTEXT(ctx);
        GLuint refmask = ((ctx->Stencil.Ref[0] << R300_RB3D_ZS2_STENCIL_REF_SHIFT) |
-                         (ctx->Stencil.
-                          ValueMask[0] << R300_RB3D_ZS2_STENCIL_MASK_SHIFT));
+                         (ctx->Stencil.ValueMask[0] << R300_RB3D_ZS2_STENCIL_MASK_SHIFT));
+                         
        GLuint flag;
 
        R300_STATECHANGE(rmesa, zs);
@@ -875,9 +873,10 @@ static void r300StencilFunc(GLcontext * ctx, GLenum func,
        rmesa->hw.zs.cmd[R300_ZS_CNTL_1] &= ~(
                (R300_ZS_MASK << R300_RB3D_ZS1_FRONT_FUNC_SHIFT)
                | (R300_ZS_MASK << R300_RB3D_ZS1_BACK_FUNC_SHIFT));
-       rmesa->hw.zs.cmd[R300_ZS_CNTL_2] &=  ~((R300_ZS_MASK << R300_RB3D_ZS2_STENCIL_REF_SHIFT) |
-                                               (R300_ZS_MASK << R300_RB3D_ZS2_STENCIL_MASK_SHIFT));
-
+       
+       rmesa->hw.zs.cmd[R300_ZS_CNTL_2] &=  ~((R300_RB3D_ZS2_STENCIL_MASK << R300_RB3D_ZS2_STENCIL_REF_SHIFT) |
+                                               (R300_RB3D_ZS2_STENCIL_MASK << R300_RB3D_ZS2_STENCIL_MASK_SHIFT));
+       
        flag = translate_stencil_func(ctx->Stencil.Function[0]);
 
        rmesa->hw.zs.cmd[R300_ZS_CNTL_1] |= (flag << R300_RB3D_ZS1_FRONT_FUNC_SHIFT)
@@ -890,7 +889,7 @@ static void r300StencilMask(GLcontext * ctx, GLuint mask)
        r300ContextPtr rmesa = R300_CONTEXT(ctx);
 
        R300_STATECHANGE(rmesa, zs);
-       rmesa->hw.zs.cmd[R300_ZS_CNTL_2]  &= ~(R300_ZS_MASK << R300_RB3D_ZS2_STENCIL_WRITE_MASK_SHIFT);
+       rmesa->hw.zs.cmd[R300_ZS_CNTL_2]  &= ~(R300_RB3D_ZS2_STENCIL_MASK << R300_RB3D_ZS2_STENCIL_WRITE_MASK_SHIFT);
        rmesa->hw.zs.cmd[R300_ZS_CNTL_2] |= ctx->Stencil.WriteMask[0] << R300_RB3D_ZS2_STENCIL_WRITE_MASK_SHIFT;
 }
 
@@ -902,7 +901,10 @@ static void r300StencilOp(GLcontext * ctx, GLenum fail,
 
        R300_STATECHANGE(rmesa, zs);
                /* It is easier to mask what's left.. */
-       rmesa->hw.zs.cmd[R300_ZS_CNTL_1] &= (R300_ZS_MASK << R300_RB3D_ZS1_DEPTH_FUNC_SHIFT);
+       rmesa->hw.zs.cmd[R300_ZS_CNTL_1] &= 
+           (R300_ZS_MASK << R300_RB3D_ZS1_DEPTH_FUNC_SHIFT) | 
+           (R300_ZS_MASK << R300_RB3D_ZS1_FRONT_FUNC_SHIFT) | 
+           (R300_ZS_MASK << R300_RB3D_ZS1_BACK_FUNC_SHIFT);
 
        rmesa->hw.zs.cmd[R300_ZS_CNTL_1] |=
                 (translate_stencil_op(ctx->Stencil.FailFunc[0]) << R300_RB3D_ZS1_FRONT_FAIL_OP_SHIFT)
@@ -911,19 +913,16 @@ static void r300StencilOp(GLcontext * ctx, GLenum fail,
                |(translate_stencil_op(ctx->Stencil.FailFunc[0]) << R300_RB3D_ZS1_BACK_FAIL_OP_SHIFT)
                |(translate_stencil_op(ctx->Stencil.ZFailFunc[0]) << R300_RB3D_ZS1_BACK_ZFAIL_OP_SHIFT)
                |(translate_stencil_op(ctx->Stencil.ZPassFunc[0]) << R300_RB3D_ZS1_BACK_ZPASS_OP_SHIFT);
-
 }
 
 static void r300ClearStencil(GLcontext * ctx, GLint s)
 {
        r300ContextPtr rmesa = R300_CONTEXT(ctx);
 
-       /* Not sure whether this is correct.. */
-       R300_STATECHANGE(rmesa, zs);
-       rmesa->hw.zs.cmd[R300_ZS_CNTL_2] =
+       rmesa->state.stencil.clear =
            ((GLuint) ctx->Stencil.Clear |
-            (0xff << R200_STENCIL_MASK_SHIFT) |
-            (ctx->Stencil.WriteMask[0] << R200_STENCIL_WRITEMASK_SHIFT));
+            (R300_RB3D_ZS2_STENCIL_MASK << R300_RB3D_ZS2_STENCIL_MASK_SHIFT) |
+            (ctx->Stencil.WriteMask[0] << R300_RB3D_ZS2_STENCIL_WRITE_MASK_SHIFT));
 }
 
 /* =============================================================
@@ -1978,9 +1977,18 @@ void r300ResetHwState(r300ContextPtr r300)
                   have bitfields accessed by different functions
                   and not all bits are used */
 #if 0
+       /* initialize similiar to r200 */
        r300->hw.zs.cmd[R300_ZS_CNTL_0] = 0;
-       r300->hw.zs.cmd[R300_ZS_CNTL_1] = 0;
-       r300->hw.zs.cmd[R300_ZS_CNTL_2] = 0xffff00;
+       r300->hw.zs.cmd[R300_ZS_CNTL_1] =
+           (R300_ZS_ALWAYS << R300_RB3D_ZS1_FRONT_FUNC_SHIFT) |
+           (R300_ZS_KEEP << R300_RB3D_ZS1_FRONT_FAIL_OP_SHIFT) |
+           (R300_ZS_KEEP << R300_RB3D_ZS1_FRONT_ZPASS_OP_SHIFT) |
+           (R300_ZS_KEEP << R300_RB3D_ZS1_FRONT_ZFAIL_OP_SHIFT) |
+           (R300_ZS_ALWAYS << R300_RB3D_ZS1_BACK_FUNC_SHIFT) |
+           (R300_ZS_KEEP << R300_RB3D_ZS1_BACK_FAIL_OP_SHIFT) |
+           (R300_ZS_KEEP << R300_RB3D_ZS1_BACK_ZPASS_OP_SHIFT) |
+           (R300_ZS_KEEP << R300_RB3D_ZS1_BACK_ZFAIL_OP_SHIFT);
+       r300->hw.zs.cmd[R300_ZS_CNTL_2] = 0x00ffff00;
 #endif
 
                /* go and compute register values from GL state */
@@ -1996,6 +2004,12 @@ void r300ResetHwState(r300ContextPtr r300)
        r300Enable(ctx, GL_DEPTH_TEST, ctx->Depth.Test);
        r300DepthMask(ctx, ctx->Depth.Mask);
        r300DepthFunc(ctx, ctx->Depth.Func);
+       
+       /* stencil */
+       r300Enable(ctx, GL_STENCIL_TEST, ctx->Stencil.Enabled);
+       r300StencilMask(ctx, ctx->Stencil.WriteMask[0]);
+       r300StencilFunc(ctx, ctx->Stencil.Function[0], ctx->Stencil.Ref[0], ctx->Stencil.ValueMask[0]);
+       r300StencilOp(ctx, ctx->Stencil.FailFunc[0], ctx->Stencil.ZFailFunc[0], ctx->Stencil.ZPassFunc[0]);
 
        r300UpdateCulling(ctx);
 
@@ -2293,12 +2307,12 @@ void r300InitState(r300ContextPtr r300)
        case 16:
                r300->state.depth.scale = 1.0 / (GLfloat) 0xffff;
                depth_fmt = R200_DEPTH_FORMAT_16BIT_INT_Z;
-               //r300->state.stencil.clear = 0x00000000;
+               r300->state.stencil.clear = 0x00000000;
                break;
        case 24:
                r300->state.depth.scale = 1.0 / (GLfloat) 0xffffff;
                depth_fmt = R200_DEPTH_FORMAT_24BIT_INT_Z;
-               //r300->state.stencil.clear = 0xff000000;
+               r300->state.stencil.clear = 0x00ff0000;
                break;
        default:
                fprintf(stderr, "Error: Unsupported depth %d... exiting\n",
@@ -2307,7 +2321,7 @@ void r300InitState(r300ContextPtr r300)
        }
 
        /* Only have hw stencil when depth buffer is 24 bits deep */
-       r300->state.hw_stencil = (ctx->Visual.stencilBits > 0 &&
+       r300->state.stencil.hw_stencil = (ctx->Visual.stencilBits > 0 &&
                                         ctx->Visual.depthBits == 24);
 
        memset(&(r300->state.texture), 0, sizeof(r300->state.texture));