cell: adapt to stencil ref changes
authorRoland Scheidegger <sroland@vmware.com>
Thu, 11 Feb 2010 17:18:11 +0000 (18:18 +0100)
committerRoland Scheidegger <sroland@vmware.com>
Thu, 11 Feb 2010 17:18:11 +0000 (18:18 +0100)
not betting this compiles, some of the code handling stencil test seems
incomplete and/or never called?

src/gallium/drivers/cell/ppu/cell_context.h
src/gallium/drivers/cell/ppu/cell_gen_fragment.c
src/gallium/drivers/cell/ppu/cell_pipe_state.c
src/gallium/drivers/cell/ppu/cell_state_per_fragment.c

index 905cd5db390033fb754af4b41326632875f18b92..a77cc5b9067804c0df716dccfe82099bab5c1e53 100644 (file)
@@ -114,6 +114,7 @@ struct cell_context
    struct spe_function logic_op;
 
    struct pipe_blend_color blend_color;
+   struct pipe_stencil_ref stencil_ref;
    struct pipe_clip_state clip;
    struct pipe_buffer *constants[2];
    struct pipe_framebuffer_state framebuffer;
index 0dab34075da525cec2697a5fec73de2c90492629..b58fe3764b045fd4b351f3b8f02082ef5af45139 100644 (file)
@@ -1175,7 +1175,8 @@ gen_colormask(struct spe_function *f,
  */
 static void
 gen_stencil_test(struct spe_function *f,
-                 const struct pipe_stencil_state *state, 
+                 const struct pipe_stencil_state *state,
+                 const unsigned ref_value,
                  uint stencil_max_value,
                  int fragment_mask_reg,
                  int fbS_reg, 
@@ -1189,7 +1190,7 @@ gen_stencil_test(struct spe_function *f,
    case PIPE_FUNC_EQUAL:
       if (state->valuemask == stencil_max_value) {
          /* stencil_pass = fragment_mask & (s == reference) */
-         spe_compare_equal_uint(f, stencil_pass_reg, fbS_reg, state->ref_value);
+         spe_compare_equal_uint(f, stencil_pass_reg, fbS_reg, ref_value);
          spe_and(f, stencil_pass_reg, fragment_mask_reg, stencil_pass_reg);
       }
       else {
@@ -1197,7 +1198,7 @@ gen_stencil_test(struct spe_function *f,
          uint tmp_masked_stencil = spe_allocate_available_register(f);
          spe_and_uint(f, tmp_masked_stencil, fbS_reg, state->valuemask);
          spe_compare_equal_uint(f, stencil_pass_reg, tmp_masked_stencil,
-                                state->valuemask & state->ref_value);
+                                state->valuemask & ref_value);
          spe_and(f, stencil_pass_reg, fragment_mask_reg, stencil_pass_reg);
          spe_release_register(f, tmp_masked_stencil);
       }
@@ -1206,7 +1207,7 @@ gen_stencil_test(struct spe_function *f,
    case PIPE_FUNC_NOTEQUAL:
       if (state->valuemask == stencil_max_value) {
          /* stencil_pass = fragment_mask & ~(s == reference) */
-         spe_compare_equal_uint(f, stencil_pass_reg, fbS_reg, state->ref_value);
+         spe_compare_equal_uint(f, stencil_pass_reg, fbS_reg, ref_value);
          spe_andc(f, stencil_pass_reg, fragment_mask_reg, stencil_pass_reg);
       }
       else {
@@ -1214,7 +1215,7 @@ gen_stencil_test(struct spe_function *f,
          int tmp_masked_stencil = spe_allocate_available_register(f);
          spe_and_uint(f, tmp_masked_stencil, fbS_reg, state->valuemask);
          spe_compare_equal_uint(f, stencil_pass_reg, tmp_masked_stencil,
-                                state->valuemask & state->ref_value);
+                                state->valuemask & ref_value);
          spe_andc(f, stencil_pass_reg, fragment_mask_reg, stencil_pass_reg);
          spe_release_register(f, tmp_masked_stencil);
       }
@@ -1223,7 +1224,7 @@ gen_stencil_test(struct spe_function *f,
    case PIPE_FUNC_LESS:
       if (state->valuemask == stencil_max_value) {
          /* stencil_pass = fragment_mask & (reference < s)  */
-         spe_compare_greater_uint(f, stencil_pass_reg, fbS_reg, state->ref_value);
+         spe_compare_greater_uint(f, stencil_pass_reg, fbS_reg, ref_value);
          spe_and(f, stencil_pass_reg, fragment_mask_reg, stencil_pass_reg);
       }
       else {
@@ -1231,7 +1232,7 @@ gen_stencil_test(struct spe_function *f,
          int tmp_masked_stencil = spe_allocate_available_register(f);
          spe_and_uint(f, tmp_masked_stencil, fbS_reg, state->valuemask);
          spe_compare_greater_uint(f, stencil_pass_reg, tmp_masked_stencil,
-                                  state->valuemask & state->ref_value);
+                                  state->valuemask & ref_value);
          spe_and(f, stencil_pass_reg, fragment_mask_reg, stencil_pass_reg);
          spe_release_register(f, tmp_masked_stencil);
       }
@@ -1246,7 +1247,7 @@ gen_stencil_test(struct spe_function *f,
           * treats its operands as unsigned - no sign extension.
           */
          int tmp_reg = spe_allocate_available_register(f);
-         spe_load_uint(f, tmp_reg, state->ref_value);
+         spe_load_uint(f, tmp_reg, ref_value);
          spe_clgt(f, stencil_pass_reg, tmp_reg, fbS_reg);
          spe_and(f, stencil_pass_reg, fragment_mask_reg, stencil_pass_reg);
          spe_release_register(f, tmp_reg);
@@ -1255,7 +1256,7 @@ gen_stencil_test(struct spe_function *f,
          /* stencil_pass = fragment_mask & ((reference&mask) > (s&mask)) */
          int tmp_reg = spe_allocate_available_register(f);
          int tmp_masked_stencil = spe_allocate_available_register(f);
-         spe_load_uint(f, tmp_reg, state->valuemask & state->ref_value);
+         spe_load_uint(f, tmp_reg, state->valuemask & ref_value);
          spe_and_uint(f, tmp_masked_stencil, fbS_reg, state->valuemask);
          spe_clgt(f, stencil_pass_reg, tmp_reg, tmp_masked_stencil);
          spe_and(f, stencil_pass_reg, fragment_mask_reg, stencil_pass_reg);
@@ -1269,7 +1270,7 @@ gen_stencil_test(struct spe_function *f,
          /* stencil_pass = fragment_mask & (reference >= s) 
           *              = fragment_mask & ~(s > reference) */
          spe_compare_greater_uint(f, stencil_pass_reg, fbS_reg,
-                                  state->ref_value);
+                                  ref_value);
          spe_andc(f, stencil_pass_reg, fragment_mask_reg, stencil_pass_reg);
       }
       else {
@@ -1277,7 +1278,7 @@ gen_stencil_test(struct spe_function *f,
          int tmp_masked_stencil = spe_allocate_available_register(f);
          spe_and_uint(f, tmp_masked_stencil, fbS_reg, state->valuemask);
          spe_compare_greater_uint(f, stencil_pass_reg, tmp_masked_stencil,
-                                  state->valuemask & state->ref_value);
+                                  state->valuemask & ref_value);
          spe_andc(f, stencil_pass_reg, fragment_mask_reg, stencil_pass_reg);
          spe_release_register(f, tmp_masked_stencil);
       }
@@ -1289,7 +1290,7 @@ gen_stencil_test(struct spe_function *f,
           *               = fragment_mask & ~(reference > s) */
          /* As above, we have to do this by loading a register */
          int tmp_reg = spe_allocate_available_register(f);
-         spe_load_uint(f, tmp_reg, state->ref_value);
+         spe_load_uint(f, tmp_reg, ref_value);
          spe_clgt(f, stencil_pass_reg, tmp_reg, fbS_reg);
          spe_andc(f, stencil_pass_reg, fragment_mask_reg, stencil_pass_reg);
          spe_release_register(f, tmp_reg);
@@ -1298,7 +1299,7 @@ gen_stencil_test(struct spe_function *f,
          /* stencil_pass = fragment_mask & ~((reference&mask) > (s&mask)) */
          int tmp_reg = spe_allocate_available_register(f);
          int tmp_masked_stencil = spe_allocate_available_register(f);
-         spe_load_uint(f, tmp_reg, state->ref_value & state->valuemask);
+         spe_load_uint(f, tmp_reg, ref_value & state->valuemask);
          spe_and_uint(f, tmp_masked_stencil, fbS_reg, state->valuemask);
          spe_clgt(f, stencil_pass_reg, tmp_reg, tmp_masked_stencil);
          spe_andc(f, stencil_pass_reg, fragment_mask_reg, stencil_pass_reg);
@@ -1453,6 +1454,7 @@ gen_stencil_values(struct spe_function *f,
 static void
 gen_get_stencil_values(struct spe_function *f,
                        const struct pipe_stencil_state *stencil,
+                       const unsigned ref_value,
                        const uint depth_enabled,
                        int fbS_reg, 
                        int *fail_reg,
@@ -1488,7 +1490,7 @@ gen_get_stencil_values(struct spe_function *f,
    }
    else {
       *fail_reg = spe_allocate_available_register(f);
-      gen_stencil_values(f, stencil->fail_op, stencil->ref_value, 
+      gen_stencil_values(f, stencil->fail_op, ref_value, 
          0xff, fbS_reg, *fail_reg);
    }
 
@@ -1501,7 +1503,7 @@ gen_get_stencil_values(struct spe_function *f,
    }
    else {
       *zfail_reg = spe_allocate_available_register(f);
-      gen_stencil_values(f, stencil->zfail_op, stencil->ref_value, 
+      gen_stencil_values(f, stencil->zfail_op, ref_value, 
          0xff, fbS_reg, *zfail_reg);
    }
 
@@ -1516,7 +1518,7 @@ gen_get_stencil_values(struct spe_function *f,
    }
    else {
       *zpass_reg = spe_allocate_available_register(f);
-      gen_stencil_values(f, stencil->zpass_op, stencil->ref_value, 
+      gen_stencil_values(f, stencil->zpass_op, ref_value, 
          0xff, fbS_reg, *zpass_reg);
    }
 }
@@ -1528,7 +1530,8 @@ gen_get_stencil_values(struct spe_function *f,
  */
 static boolean
 gen_stencil_depth_test(struct spe_function *f, 
-                       const struct pipe_depth_stencil_alpha_state *dsa, 
+                       const struct pipe_depth_stencil_alpha_state *dsa,
+                       const struct pipe_stencil_ref *stencil_ref,
                        const uint facing,
                        const int mask_reg, const int fragZ_reg, 
                        const int fbZ_reg, const int fbS_reg)
@@ -1542,6 +1545,7 @@ gen_stencil_depth_test(struct spe_function *f,
    boolean need_to_writemask_stencil_values;
 
    struct pipe_stencil_state *stencil;
+   unsigned stencil_ref_value;
 
    /* Registers.  We may or may not actually allocate these, depending
     * on whether the state values indicate that we need them.
@@ -1579,9 +1583,11 @@ gen_stencil_depth_test(struct spe_function *f,
     */
    if (facing == CELL_FACING_BACK && dsa->stencil[1].enabled) {
       stencil = &dsa->stencil[1];
+      ref_value = stencil_ref->ref_value[1];
    }
    else {
       stencil = &dsa->stencil[0];
+      ref_value = stencil_ref->ref_value[0];
    }
 
    /* Calculate the writemask.  If the writemask is trivial (either
@@ -1641,7 +1647,7 @@ gen_stencil_depth_test(struct spe_function *f,
     */
    spe_comment(f, 0, "Running basic stencil test");
    stencil_pass_reg = spe_allocate_available_register(f);
-   gen_stencil_test(f, stencil, 0xff, mask_reg, fbS_reg, stencil_pass_reg);
+   gen_stencil_test(f, stencil, ref_value, 0xff, mask_reg, fbS_reg, stencil_pass_reg);
 
    /* Generate code that, given the mask of valid fragments and the
     * mask of valid fragments that passed the stencil test, computes
@@ -1678,7 +1684,7 @@ gen_stencil_depth_test(struct spe_function *f,
       spe_comment(f, 0, facing == CELL_FACING_FRONT
                   ? "Computing front-facing stencil values"
                   : "Computing back-facing stencil values");
-      gen_get_stencil_values(f, stencil, dsa->depth.enabled, fbS_reg, 
+      gen_get_stencil_values(f, stencil, ref_value, dsa->depth.enabled, fbS_reg, 
          &stencil_fail_values, &stencil_pass_depth_fail_values, 
          &stencil_pass_depth_pass_values);
    }  
@@ -1818,6 +1824,7 @@ gen_stencil_depth_test(struct spe_function *f,
 static void
 gen_depth_stencil(struct cell_context *cell,
                   const struct pipe_depth_stencil_alpha_state *dsa,
+                  const struct pipe_stencil_ref *stencil_ref,
                   struct spe_function *f,
                   uint facing,
                   int mask_reg,
@@ -1940,7 +1947,7 @@ gen_depth_stencil(struct cell_context *cell,
        * gen_stencil_depth_test() function must ignore the
        * fbZ_reg register if depth is not enabled.
        */
-      write_depth_stencil = gen_stencil_depth_test(f, dsa, facing,
+      write_depth_stencil = gen_stencil_depth_test(f, dsa, stencil_ref, facing,
                                                    mask_reg, fragZ_reg,
                                                    fbZ_reg, fbS_reg);
    }
@@ -2029,6 +2036,7 @@ cell_gen_fragment_function(struct cell_context *cell,
                            struct spe_function *f)
 {
    const struct pipe_depth_stencil_alpha_state *dsa = cell->depth_stencil;
+   const struct pipe_stencil_ref *stencil_ref = &cell->stencil_ref;
    const struct pipe_blend_state *blend = cell->blend;
    const struct pipe_blend_color *blend_color = &cell->blend_color;
    const enum pipe_format color_format = cell->framebuffer.cbufs[0]->format;
@@ -2101,7 +2109,7 @@ cell_gen_fragment_function(struct cell_context *cell,
 
    /* generate depth and/or stencil test code */
    if (dsa->depth.enabled || dsa->stencil[0].enabled) {
-      gen_depth_stencil(cell, dsa, f,
+      gen_depth_stencil(cell, dsa, stencil_ref, f,
                         facing,
                         mask_reg,
                         depth_tile_reg,
index 3259c58687cf1c4b1c114d2448695950b702313d..3d8b4409c75cb8cd13f793c9a4a6aa12ede81f8d 100644 (file)
@@ -112,6 +112,19 @@ cell_delete_depth_stencil_alpha_state(struct pipe_context *pipe, void *dsa)
 }
 
 
+static void
+cell_set_stencil_ref(struct pipe_context *pipe,
+                     const struct pipe_stencil_ref *stencil_ref)
+{
+   struct cell_context *cell = cell_context(pipe);
+
+   draw_flush(cell->draw);
+
+   cell->stencil_ref = *stencil_ref;
+
+   cell->dirty |= CELL_NEW_DEPTH_STENCIL;
+}
+
 static void
 cell_set_clip_state(struct pipe_context *pipe,
                     const struct pipe_clip_state *clip)
@@ -397,6 +410,7 @@ cell_init_state_functions(struct cell_context *cell)
    cell->pipe.delete_rasterizer_state = cell_delete_rasterizer_state;
 
    cell->pipe.set_blend_color = cell_set_blend_color;
+   cell->pipe.set_stencil_ref = cell_set_stencil_ref;
    cell->pipe.set_clip_state = cell_set_clip_state;
 
    cell->pipe.set_framebuffer_state = cell_set_framebuffer_state;
index 21af7ed1c3fbd066a8dc5b017e9afc310f9fdd7f..07be5e92ea7cf2b5430b27e1e5979b4a7397199a 100644 (file)
@@ -282,6 +282,7 @@ emit_stencil_op(struct spe_function *f,
  */
 static int
 emit_stencil_test(struct pipe_depth_stencil_alpha_state *dsa,
+                  struct pipe_stencil_ref *sr,
                   unsigned face,
                   struct spe_function *f,
                   int mask,
@@ -296,7 +297,7 @@ emit_stencil_test(struct pipe_depth_stencil_alpha_state *dsa,
    int stencil_pass = spe_allocate_available_register(f);
    int face_stencil = spe_allocate_available_register(f);
    int stencil_src = stencil;
-   const unsigned ref = (dsa->stencil[face].ref_value
+   const unsigned ref = (sr->ref_value[face]
                          & dsa->stencil[face].valuemask);
    boolean complement = FALSE;
    int stored;
@@ -406,7 +407,7 @@ emit_stencil_test(struct pipe_depth_stencil_alpha_state *dsa,
 
          emit_stencil_op(f, face_stencil, stencil_src, stencil_fail,
                          dsa->stencil[face].fail_op,
-                         dsa->stencil[face].ref_value);
+                         sr->ref_value[face]);
 
          stencil_src = face_stencil;
       }
@@ -421,7 +422,7 @@ emit_stencil_test(struct pipe_depth_stencil_alpha_state *dsa,
 
          emit_stencil_op(f, face_stencil, stencil_src, depth_fail,
                          dsa->stencil[face].zfail_op,
-                         dsa->stencil[face].ref_value);
+                         sr->ref_value[face]);
          stencil_src = face_stencil;
       }
 
@@ -429,7 +430,7 @@ emit_stencil_test(struct pipe_depth_stencil_alpha_state *dsa,
           && (dsa->stencil[face].zpass_op != PIPE_STENCIL_OP_KEEP)) {
          emit_stencil_op(f, face_stencil, stencil_src, depth_pass,
                          dsa->stencil[face].zpass_op,
-                         dsa->stencil[face].ref_value);
+                         sr->ref_value[face]);
          stencil_src = face_stencil;
       }
    }
@@ -463,7 +464,8 @@ emit_stencil_test(struct pipe_depth_stencil_alpha_state *dsa,
 
 
 void
-cell_generate_depth_stencil_test(struct cell_depth_stencil_alpha_state *cdsa)
+cell_generate_depth_stencil_test(struct cell_depth_stencil_alpha_state *cdsa,
+                                 struct pipe_stencil_ref *sr)
 {
    struct pipe_depth_stencil_alpha_state *const dsa = &cdsa->base;
    struct spe_function *const f = &cdsa->code;
@@ -499,13 +501,13 @@ cell_generate_depth_stencil_test(struct cell_depth_stencil_alpha_state *cdsa)
 
    if (dsa->stencil[0].enabled) {
       const int front_depth_pass = spe_allocate_available_register(f);
-      int front_stencil = emit_stencil_test(dsa, 0, f, mask,
+      int front_stencil = emit_stencil_test(dsa, sr, 0, f, mask,
                                             depth_mask, depth_complement,
                                             stencil, front_depth_pass);
 
       if (dsa->stencil[1].enabled) {
          const int back_depth_pass = spe_allocate_available_register(f);
-         int back_stencil = emit_stencil_test(dsa, 1, f, mask,
+         int back_stencil = emit_stencil_test(dsa, sr, 1, f, mask,
                                               depth_mask,  depth_complement,
                                               stencil, back_depth_pass);
 
@@ -579,7 +581,7 @@ cell_generate_depth_stencil_test(struct cell_depth_stencil_alpha_state *cdsa)
                 dsa->stencil[i].zfail_op,
                 dsa->stencil[i].zpass_op);
          printf("#    ref value / value mask / write mask: %02x %02x %02x\n",
-                dsa->stencil[i].ref_value,
+                sr->ref_value[i],
                 dsa->stencil[i].valuemask,
                 dsa->stencil[i].writemask);
       }