On the way to getting stencil working.
authorVladimir Dergachev <volodya@freedesktop.org>
Sat, 15 Jan 2005 20:44:23 +0000 (20:44 +0000)
committerVladimir Dergachev <volodya@freedesktop.org>
Sat, 15 Jan 2005 20:44:23 +0000 (20:44 +0000)
src/mesa/drivers/dri/r300/r300_context.h
src/mesa/drivers/dri/r300/r300_reg.h
src/mesa/drivers/dri/r300/r300_render.c
src/mesa/drivers/dri/r300/r300_state.c

index 3260722..f0a186d 100644 (file)
@@ -616,6 +616,7 @@ struct r300_state {
        struct r300_aos_rec aos[R300_MAX_AOS_ARRAYS];
        int aos_count;
        
+       int hw_stencil;
 };
 
 
index 1eab9f8..d07eb75 100644 (file)
@@ -1069,6 +1069,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_STENCIL_ENABLE               0x00000000  /* UNKNOWN yet.. */
 
 #define R300_RB3D_ZSTENCILCNTL_1                   0x4F04
                /* functions */
index cdf972a..2f832d2 100644 (file)
@@ -584,8 +584,8 @@ static void r300_check_render(GLcontext *ctx, struct tnl_pipeline_stage *stage)
        /* I'm almost certain I forgot something here */
        #if 0 /* This should work now.. */
        FALLBACK_IF(ctx->Color.AlphaEnabled); // GL_ALPHA_TEST
+       FALLBACK_IF(ctx->Color.BlendEnabled); // GL_BLEND
        #endif
-       //FALLBACK_IF(ctx->Color.BlendEnabled); // GL_BLEND
        FALLBACK_IF(ctx->Fog.Enabled); // GL_FOG
        FALLBACK_IF(ctx->Line.SmoothFlag); // GL_LINE_SMOOTH
        FALLBACK_IF(ctx->Line.StippleFlag); // GL_LINE_STIPPLE
@@ -597,11 +597,11 @@ static void r300_check_render(GLcontext *ctx, struct tnl_pipeline_stage *stage)
        FALLBACK_IF(ctx->Polygon.OffsetFill); // GL_POLYGON_OFFSET_FILL
        FALLBACK_IF(ctx->Polygon.SmoothFlag); // GL_POLYGON_SMOOTH
        FALLBACK_IF(ctx->Polygon.StippleFlag); // GL_POLYGON_STIPPLE
-       FALLBACK_IF(ctx->Stencil.Enabled); // GL_STENCIL_TEST
+       //FALLBACK_IF(ctx->Stencil.Enabled); // GL_STENCIL_TEST
        FALLBACK_IF(ctx->Multisample.Enabled); // GL_MULTISAMPLE_ARB
 
        /* One step at a time - let one texture pass.. */
-       for (i = 2; i < ctx->Const.MaxTextureUnits; i++)
+       for (i = 1; i < ctx->Const.MaxTextureUnits; i++)
                FALLBACK_IF(ctx->Texture.Unit[i].Enabled);
 
 
index 32b77fb..f4dd8be 100644 (file)
@@ -470,6 +470,21 @@ static void r300Enable(GLcontext* ctx, GLenum cap, GLboolean state)
 
                r300->hw.zs.cmd[R300_ZS_CNTL_0] = newval;
                break;
+       
+       case GL_STENCIL_TEST:
+               if (r300->state.hw_stencil) {
+                       R300_STATECHANGE(r300, zs);
+                       if (state) {
+                               r300->hw.zs.cmd[R300_ZS_CNTL_0] |=
+                                   R300_STENCIL_ENABLE;
+                       } else {
+                               r300->hw.zs.cmd[R300_ZS_CNTL_0] &=
+                                   ~R300_STENCIL_ENABLE;
+                       }
+               } else {
+                       FALLBACK(&r300->radeon, RADEON_FALLBACK_STENCIL, state);
+               }
+               break;
 
        case GL_CULL_FACE:
                r300UpdateCulling(ctx);
@@ -548,7 +563,6 @@ static void r300DepthFunc(GLcontext* ctx, GLenum func)
                break;
        }
 
-       fprintf(stderr, "ZS_CNTL_1=%08x\n", r300->hw.zs.cmd[R300_ZS_CNTL_1]);
 }
 
 
@@ -596,6 +610,122 @@ static void r300PointSize(GLcontext * ctx, GLfloat size)
        R300_STATECHANGE(r300, vps);
        r300->hw.vps.cmd[R300_VPS_POINTSIZE] = r300PackFloat32(1.0);
 }
+/* =============================================================
+ * Stencil
+ */
+
+static void r300StencilFunc(GLcontext * ctx, GLenum func,
+                           GLint ref, GLuint mask)
+{
+       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));
+
+       R200_STATECHANGE(rmesa, zs);
+
+       rmesa->hw.zs.cmd[R300_ZS_CNTL_1] &= ~(R300_ZS_MASK << R300_RB3D_ZS1_STENCIL_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));
+
+       switch (ctx->Stencil.Function[0]) {
+       case GL_NEVER:
+               rmesa->hw.zs.cmd[R300_ZS_CNTL_1] |=
+                   R300_ZS_NEVER << R300_RB3D_ZS1_STENCIL_FUNC_SHIFT;
+               break;
+       case GL_LESS:
+               rmesa->hw.zs.cmd[R300_ZS_CNTL_1] |=
+                   R300_ZS_LESS << R300_RB3D_ZS1_STENCIL_FUNC_SHIFT;
+               break;
+       case GL_EQUAL:
+               rmesa->hw.zs.cmd[R300_ZS_CNTL_1] |=
+                   R300_ZS_EQUAL << R300_RB3D_ZS1_STENCIL_FUNC_SHIFT;
+               break;
+       case GL_LEQUAL:
+               rmesa->hw.zs.cmd[R300_ZS_CNTL_1] |=
+                   R300_ZS_LEQUAL << R300_RB3D_ZS1_STENCIL_FUNC_SHIFT;
+               break;
+       case GL_GREATER:
+               rmesa->hw.zs.cmd[R300_ZS_CNTL_1] |=
+                   R300_ZS_GREATER << R300_RB3D_ZS1_STENCIL_FUNC_SHIFT;
+               break;
+       case GL_NOTEQUAL:
+               rmesa->hw.zs.cmd[R300_ZS_CNTL_1] |=
+                   R300_ZS_NOTEQUAL << R300_RB3D_ZS1_STENCIL_FUNC_SHIFT;
+               break;
+       case GL_GEQUAL:
+               rmesa->hw.zs.cmd[R300_ZS_CNTL_1] |=
+                   R300_ZS_GEQUAL << R300_RB3D_ZS1_STENCIL_FUNC_SHIFT;
+               break;
+       case GL_ALWAYS:
+               rmesa->hw.zs.cmd[R300_ZS_CNTL_1] |=
+                   R300_ZS_ALWAYS << R300_RB3D_ZS1_STENCIL_FUNC_SHIFT;
+               break;
+       }
+
+       rmesa->hw.zs.cmd[R300_ZS_CNTL_2] |= refmask;
+}
+
+static void r300StencilMask(GLcontext * ctx, GLuint mask)
+{
+       r300ContextPtr rmesa = R300_CONTEXT(ctx);
+
+       R200_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] |= ctx->Stencil.WriteMask[0] << R300_RB3D_ZS2_STENCIL_WRITE_MASK_SHIFT;
+}
+
+static int translate_stencil_op(int op)
+{
+       switch (op) {
+       case GL_KEEP:
+                   return R300_ZS_KEEP;
+       case GL_ZERO:
+                   return R300_ZS_ZERO;
+       case GL_REPLACE:
+                   return R300_ZS_REPLACE;
+       case GL_INCR:
+                   return R300_ZS_INCR;
+       case GL_DECR:
+                   return R300_ZS_DECR;
+       case GL_INCR_WRAP_EXT:
+                   return R300_ZS_INCR_WRAP;
+       case GL_DECR_WRAP_EXT:
+                   return R300_ZS_DECR_WRAP;
+       case GL_INVERT:
+                   return R300_ZS_INVERT;
+       }
+}
+
+static void r300StencilOp(GLcontext * ctx, GLenum fail,
+                         GLenum zfail, GLenum zpass)
+{
+       r300ContextPtr rmesa = R300_CONTEXT(ctx);
+
+       R200_STATECHANGE(rmesa, zs);
+       rmesa->hw.zs.cmd[R300_ZS_CNTL_1] &= ~((R300_ZS_MASK << R300_RB3D_ZS1_STENCIL_FAIL_OP_SHIFT)
+                                       | (R300_ZS_MASK << R300_RB3D_ZS1_STENCIL_ZPASS_OP_SHIFT)
+                                       | (R300_ZS_MASK << R300_RB3D_ZS1_STENCIL_ZFAIL_OP_SHIFT)
+                                       );
+
+       rmesa->hw.zs.cmd[R300_ZS_CNTL_1] |= 
+                (translate_stencil_op(ctx->Stencil.FailFunc[0]) << R300_RB3D_ZS1_STENCIL_FAIL_OP_SHIFT)
+               |(translate_stencil_op(ctx->Stencil.ZFailFunc[0]) << R300_RB3D_ZS1_STENCIL_ZFAIL_OP_SHIFT)
+               |(translate_stencil_op(ctx->Stencil.ZPassFunc[0]) << R300_RB3D_ZS1_STENCIL_ZPASS_OP_SHIFT);
+       
+}
+
+static void r300ClearStencil(GLcontext * ctx, GLint s)
+{
+       r300ContextPtr rmesa = R300_CONTEXT(ctx);
+
+       /* Not sure whether this is correct.. */
+       R200_STATECHANGE(rmesa, zs);
+       rmesa->hw.zs.cmd[R300_ZS_CNTL_2] =
+           ((GLuint) ctx->Stencil.Clear |
+            (0xff << R200_STENCIL_MASK_SHIFT) |
+            (ctx->Stencil.WriteMask[0] << R200_STENCIL_WRITEMASK_SHIFT));
+}
 
 /* =============================================================
  * Window position and viewport transformation
@@ -1673,6 +1803,10 @@ void r300InitState(r300ContextPtr r300)
                exit(-1);
        }
        
+       /* Only have hw stencil when depth buffer is 24 bits deep */
+       r300->state.hw_stencil = (ctx->Visual.stencilBits > 0 &&
+                                        ctx->Visual.depthBits == 24);
+
        memset(&(r300->state.texture), 0, sizeof(r300->state.texture));
 
        r300ResetHwState(r300);
@@ -1699,6 +1833,12 @@ void r300InitStateFuncs(struct dd_function_table* functions)
        functions->CullFace = r300CullFace;
        functions->FrontFace = r300FrontFace;
 
+       /* Stencil related */
+       functions->ClearStencil = r300ClearStencil;
+       functions->StencilFunc = r300StencilFunc;
+       functions->StencilMask = r300StencilMask;
+       functions->StencilOp = r300StencilOp;
+       
        /* Viewport related */
        functions->Viewport = r300Viewport;
        functions->DepthRange = r300DepthRange;