i915: Add support for EXT_stencil_two_side and ATI_separate_stencil.
authorEric Anholt <eric@anholt.net>
Wed, 29 Jul 2009 21:06:05 +0000 (14:06 -0700)
committerEric Anholt <eric@anholt.net>
Thu, 30 Jul 2009 04:25:39 +0000 (21:25 -0700)
Passes tests/stencil_twoside and glean/stencil2.

src/mesa/drivers/dri/i915/i915_context.c
src/mesa/drivers/dri/i915/i915_context.h
src/mesa/drivers/dri/i915/i915_reg.h
src/mesa/drivers/dri/i915/i915_state.c
src/mesa/drivers/dri/i915/i915_vtbl.c
src/mesa/drivers/dri/intel/intel_extensions.c

index 367d2a3..5aa4133 100644 (file)
@@ -75,6 +75,8 @@ i915InvalidateState(GLcontext * ctx, GLuint new_state)
 
    if (new_state & (_NEW_FOG | _NEW_HINT | _NEW_PROGRAM | _NEW_PROGRAM_CONSTANTS))
       i915_update_fog(ctx);
+   if (new_state & (_NEW_STENCIL | _NEW_BUFFERS | _NEW_POLYGON))
+      i915_update_stencil(ctx);
 }
 
 
index 87bbf5f..c6b7377 100644 (file)
@@ -82,7 +82,9 @@
 #define I915_CTXREG_IAB                6
 #define I915_CTXREG_BLENDCOLOR0                7
 #define I915_CTXREG_BLENDCOLOR1                8
-#define I915_CTX_SETUP_SIZE            9
+#define I915_CTXREG_BF_STENCIL_OPS     9
+#define I915_CTXREG_BF_STENCIL_MASKS   10
+#define I915_CTX_SETUP_SIZE            11
 
 #define I915_FOGREG_COLOR              0
 #define I915_FOGREG_MODE0              1
@@ -321,6 +323,7 @@ extern void i915_print_ureg(const char *msg, GLuint ureg);
 extern void i915InitStateFunctions(struct dd_function_table *functions);
 extern void i915InitState(struct i915_context *i915);
 extern void i915_update_fog(GLcontext * ctx);
+extern void i915_update_stencil(GLcontext * ctx);
 
 
 /*======================================================================
index 84db58e..80ec461 100644 (file)
 #define BFM_ENABLE_STENCIL_WRITE_MASK     (1<<16)
 #define BFM_STENCIL_TEST_MASK_SHIFT       8
 #define BFM_STENCIL_TEST_MASK_MASK        (0xff<<8)
+#define BFM_STENCIL_TEST_MASK(x)         (((x)&0xff) << 8)
 #define BFM_STENCIL_WRITE_MASK_SHIFT      0
 #define BFM_STENCIL_WRITE_MASK_MASK       (0xff<<0)
+#define BFM_STENCIL_WRITE_MASK(x)        ((x)&0xff)
 
 
 
index 814fb59..670451b 100644 (file)
 
 #define FILE_DEBUG_FLAG DEBUG_STATE
 
-static void
-i915StencilFuncSeparate(GLcontext * ctx, GLenum face, GLenum func, GLint ref,
-                        GLuint mask)
+void
+i915_update_stencil(GLcontext * ctx)
 {
    struct i915_context *i915 = I915_CONTEXT(ctx);
-   int test = intel_translate_compare_func(func);
-
-   mask = mask & 0xff;
+   GLuint front_ref, front_writemask, front_mask;
+   GLenum front_func, front_fail, front_pass_z_fail, front_pass_z_pass;
+   GLuint back_ref, back_writemask, back_mask;
+   GLenum back_func, back_fail, back_pass_z_fail, back_pass_z_pass;
 
-   DBG("%s : func: %s, ref : 0x%x, mask: 0x%x\n", __FUNCTION__,
-       _mesa_lookup_enum_by_nr(func), ref, mask);
+   I915_STATECHANGE(i915, I915_UPLOAD_CTX);
 
+   /* The 915 considers CW to be "front" for two-sided stencil, so choose
+    * appropriately.
+    */
+   /* _NEW_POLYGON | _NEW_STENCIL */
+   if (ctx->Polygon.FrontFace == GL_CW) {
+      front_ref = ctx->Stencil.Ref[0];
+      front_mask = ctx->Stencil.ValueMask[0];
+      front_writemask = ctx->Stencil.WriteMask[0];
+      front_func = ctx->Stencil.Function[0];
+      front_fail = ctx->Stencil.FailFunc[0];
+      front_pass_z_fail = ctx->Stencil.ZFailFunc[0];
+      front_pass_z_pass = ctx->Stencil.ZPassFunc[0];
+      back_ref = ctx->Stencil.Ref[ctx->Stencil._BackFace];
+      back_mask = ctx->Stencil.ValueMask[ctx->Stencil._BackFace];
+      back_writemask = ctx->Stencil.WriteMask[ctx->Stencil._BackFace];
+      back_func = ctx->Stencil.Function[ctx->Stencil._BackFace];
+      back_fail = ctx->Stencil.FailFunc[ctx->Stencil._BackFace];
+      back_pass_z_fail = ctx->Stencil.ZFailFunc[ctx->Stencil._BackFace];
+      back_pass_z_pass = ctx->Stencil.ZPassFunc[ctx->Stencil._BackFace];
+   } else {
+      front_ref = ctx->Stencil.Ref[ctx->Stencil._BackFace];
+      front_mask = ctx->Stencil.ValueMask[ctx->Stencil._BackFace];
+      front_writemask = ctx->Stencil.WriteMask[ctx->Stencil._BackFace];
+      front_func = ctx->Stencil.Function[ctx->Stencil._BackFace];
+      front_fail = ctx->Stencil.FailFunc[ctx->Stencil._BackFace];
+      front_pass_z_fail = ctx->Stencil.ZFailFunc[ctx->Stencil._BackFace];
+      front_pass_z_pass = ctx->Stencil.ZPassFunc[ctx->Stencil._BackFace];
+      back_ref = ctx->Stencil.Ref[0];
+      back_mask = ctx->Stencil.ValueMask[0];
+      back_writemask = ctx->Stencil.WriteMask[0];
+      back_func = ctx->Stencil.Function[0];
+      back_fail = ctx->Stencil.FailFunc[0];
+      back_pass_z_fail = ctx->Stencil.ZFailFunc[0];
+      back_pass_z_pass = ctx->Stencil.ZPassFunc[0];
+   }
 
-   I915_STATECHANGE(i915, I915_UPLOAD_CTX);
-   i915->state.Ctx[I915_CTXREG_STATE4] &= ~MODE4_ENABLE_STENCIL_TEST_MASK;
+   /* Set front state. */
+   i915->state.Ctx[I915_CTXREG_STATE4] &= ~(MODE4_ENABLE_STENCIL_TEST_MASK |
+                                           MODE4_ENABLE_STENCIL_WRITE_MASK);
    i915->state.Ctx[I915_CTXREG_STATE4] |= (ENABLE_STENCIL_TEST_MASK |
-                                           STENCIL_TEST_MASK(mask));
+                                          ENABLE_STENCIL_WRITE_MASK |
+                                          STENCIL_TEST_MASK(front_mask) |
+                                          STENCIL_WRITE_MASK(front_writemask));
 
    i915->state.Ctx[I915_CTXREG_LIS5] &= ~(S5_STENCIL_REF_MASK |
-                                          S5_STENCIL_TEST_FUNC_MASK);
+                                         S5_STENCIL_TEST_FUNC_MASK |
+                                         S5_STENCIL_FAIL_MASK |
+                                         S5_STENCIL_PASS_Z_FAIL_MASK |
+                                         S5_STENCIL_PASS_Z_PASS_MASK);
+
+   i915->state.Ctx[I915_CTXREG_LIS5] |=
+      (front_ref << S5_STENCIL_REF_SHIFT) |
+      (intel_translate_compare_func(front_func) << S5_STENCIL_TEST_FUNC_SHIFT) |
+      (intel_translate_stencil_op(front_fail) << S5_STENCIL_FAIL_SHIFT) |
+      (intel_translate_stencil_op(front_pass_z_fail) <<
+       S5_STENCIL_PASS_Z_FAIL_SHIFT) |
+      (intel_translate_stencil_op(front_pass_z_pass) <<
+       S5_STENCIL_PASS_Z_PASS_SHIFT);
+
+   /* Set back state if different from front. */
+   if (ctx->Stencil._TestTwoSide) {
+      i915->state.Ctx[I915_CTXREG_BF_STENCIL_OPS] &=
+        ~(BFO_STENCIL_REF_MASK |
+          BFO_STENCIL_TEST_MASK |
+          BFO_STENCIL_FAIL_MASK |
+          BFO_STENCIL_PASS_Z_FAIL_MASK |
+          BFO_STENCIL_PASS_Z_PASS_MASK);
+      i915->state.Ctx[I915_CTXREG_BF_STENCIL_OPS] |= BFO_STENCIL_TWO_SIDE |
+        (back_ref << BFO_STENCIL_REF_SHIFT) |
+        (intel_translate_compare_func(back_func) << BFO_STENCIL_TEST_SHIFT) |
+        (intel_translate_stencil_op(back_fail) << BFO_STENCIL_FAIL_SHIFT) |
+        (intel_translate_stencil_op(back_pass_z_fail) <<
+         BFO_STENCIL_PASS_Z_FAIL_SHIFT) |
+        (intel_translate_stencil_op(back_pass_z_pass) <<
+         BFO_STENCIL_PASS_Z_PASS_SHIFT);
+
+      i915->state.Ctx[I915_CTXREG_BF_STENCIL_MASKS] &=
+        ~(BFM_STENCIL_TEST_MASK_MASK |
+          BFM_STENCIL_WRITE_MASK_MASK);
+      i915->state.Ctx[I915_CTXREG_BF_STENCIL_MASKS] |=
+        BFM_STENCIL_TEST_MASK(back_mask) |
+        BFM_STENCIL_WRITE_MASK(back_writemask);
+   } else {
+      i915->state.Ctx[I915_CTXREG_BF_STENCIL_OPS] &= ~BFO_STENCIL_TWO_SIDE;
+   }
+}
 
-   i915->state.Ctx[I915_CTXREG_LIS5] |= ((ref << S5_STENCIL_REF_SHIFT) |
-                                         (test <<
-                                          S5_STENCIL_TEST_FUNC_SHIFT));
+static void
+i915StencilFuncSeparate(GLcontext * ctx, GLenum face, GLenum func, GLint ref,
+                        GLuint mask)
+{
 }
 
 static void
 i915StencilMaskSeparate(GLcontext * ctx, GLenum face, GLuint mask)
 {
-   struct i915_context *i915 = I915_CONTEXT(ctx);
-
-   DBG("%s : mask 0x%x\n", __FUNCTION__, mask);
-   
-   mask = mask & 0xff;
-
-   I915_STATECHANGE(i915, I915_UPLOAD_CTX);
-   i915->state.Ctx[I915_CTXREG_STATE4] &= ~MODE4_ENABLE_STENCIL_WRITE_MASK;
-   i915->state.Ctx[I915_CTXREG_STATE4] |= (ENABLE_STENCIL_WRITE_MASK |
-                                           STENCIL_WRITE_MASK(mask));
 }
 
-
 static void
 i915StencilOpSeparate(GLcontext * ctx, GLenum face, GLenum fail, GLenum zfail,
                       GLenum zpass)
 {
-   struct i915_context *i915 = I915_CONTEXT(ctx);
-   int fop = intel_translate_stencil_op(fail);
-   int dfop = intel_translate_stencil_op(zfail);
-   int dpop = intel_translate_stencil_op(zpass);
-
-
-   DBG("%s: fail : %s, zfail: %s, zpass : %s\n", __FUNCTION__,
-       _mesa_lookup_enum_by_nr(fail),
-       _mesa_lookup_enum_by_nr(zfail), _mesa_lookup_enum_by_nr(zpass));
-
-   I915_STATECHANGE(i915, I915_UPLOAD_CTX);
-
-   i915->state.Ctx[I915_CTXREG_LIS5] &= ~(S5_STENCIL_FAIL_MASK |
-                                          S5_STENCIL_PASS_Z_FAIL_MASK |
-                                          S5_STENCIL_PASS_Z_PASS_MASK);
-
-   i915->state.Ctx[I915_CTXREG_LIS5] |= ((fop << S5_STENCIL_FAIL_SHIFT) |
-                                         (dfop <<
-                                          S5_STENCIL_PASS_Z_FAIL_SHIFT) |
-                                         (dpop <<
-                                          S5_STENCIL_PASS_Z_PASS_SHIFT));
 }
 
 static void
@@ -945,6 +991,17 @@ i915_init_packets(struct i915_context *i915)
          _3DSTATE_CONST_BLEND_COLOR_CMD;
       i915->state.Ctx[I915_CTXREG_BLENDCOLOR1] = 0;
 
+      i915->state.Ctx[I915_CTXREG_BF_STENCIL_MASKS] =
+        _3DSTATE_BACKFACE_STENCIL_MASKS |
+        BFM_ENABLE_STENCIL_TEST_MASK |
+        BFM_ENABLE_STENCIL_WRITE_MASK |
+        (0xff << BFM_STENCIL_WRITE_MASK_SHIFT) |
+        (0xff << BFM_STENCIL_TEST_MASK_SHIFT);
+      i915->state.Ctx[I915_CTXREG_BF_STENCIL_OPS] =
+        _3DSTATE_BACKFACE_STENCIL_OPS |
+        BFO_ENABLE_STENCIL_REF |
+        BFO_ENABLE_STENCIL_FUNCS |
+        BFO_ENABLE_STENCIL_TWO_SIDE;
    }
 
    {
index fe1be93..707864e 100644 (file)
@@ -176,7 +176,7 @@ i915_emit_invarient_state(struct intel_context *intel)
 {
    BATCH_LOCALS;
 
-   BEGIN_BATCH(20, IGNORE_CLIPRECTS);
+   BEGIN_BATCH(18, IGNORE_CLIPRECTS);
 
    OUT_BATCH(_3DSTATE_AA_CMD |
              AA_LINE_ECAAR_WIDTH_ENABLE |
@@ -225,11 +225,6 @@ i915_emit_invarient_state(struct intel_context *intel)
    OUT_BATCH(_3DSTATE_LOAD_INDIRECT | 0);       /* disable indirect state */
    OUT_BATCH(0);
 
-
-   /* Don't support twosided stencil yet */
-   OUT_BATCH(_3DSTATE_BACKFACE_STENCIL_OPS | BFO_ENABLE_STENCIL_TWO_SIDE | 0);
-   OUT_BATCH(0);
-
    ADVANCE_BATCH();
 }
 
index 3a09a53..6a68021 100644 (file)
@@ -120,8 +120,10 @@ static const struct dri_extension i915_extensions[] = {
    { "GL_ARB_fragment_program",           NULL },
    { "GL_ARB_shadow",                     NULL },
    { "GL_ARB_texture_non_power_of_two",   NULL },
+   { "GL_ATI_separate_stencil",           GL_ATI_separate_stencil_functions },
    { "GL_ATI_texture_env_combine3",       NULL },
    { "GL_EXT_shadow_funcs",               NULL },
+   { "GL_EXT_stencil_two_side",           GL_EXT_stencil_two_side_functions },
    { "GL_NV_texture_env_combine4",        NULL },
    { NULL,                                NULL }
 };