util: assorted updates to polygon stipple helper
authorBrian Paul <brianp@vmware.com>
Thu, 21 Jul 2011 15:55:22 +0000 (09:55 -0600)
committerBrian Paul <brianp@vmware.com>
Thu, 21 Jul 2011 15:57:37 +0000 (09:57 -0600)
src/gallium/auxiliary/util/u_pstipple.c

index f79a693..ac0df8c 100644 (file)
@@ -52,6 +52,7 @@
 
 #include "tgsi/tgsi_transform.h"
 #include "tgsi/tgsi_dump.h"
+#include "tgsi/tgsi_scan.h"
 
 /** Approx number of new tokens for instructions in pstip_transform_inst() */
 #define NUM_NEW_TOKENS 50
@@ -175,6 +176,7 @@ util_pstipple_create_sampler(struct pipe_context *pipe)
  */
 struct pstip_transform_context {
    struct tgsi_transform_context base;
+   struct tgsi_shader_info info;
    uint tempsUsed;  /**< bitmask */
    int wincoordInput;
    int maxInput;
@@ -183,12 +185,13 @@ struct pstip_transform_context {
    int texTemp;  /**< temp registers */
    int numImmed;
    boolean firstInstruction;
+   uint coordOrigin;
 };
 
 
 /**
  * TGSI declaration transform callback.
- * Look for a free sampler, a free input attrib, and two free temp regs.
+ * Track samplers used, temps used, inputs used.
  */
 static void
 pstip_transform_decl(struct tgsi_transform_context *ctx,
@@ -197,10 +200,11 @@ pstip_transform_decl(struct tgsi_transform_context *ctx,
    struct pstip_transform_context *pctx =
       (struct pstip_transform_context *) ctx;
 
+   /* XXX we can use tgsi_shader_info instead of some of this */
+
    if (decl->Declaration.File == TGSI_FILE_SAMPLER) {
       uint i;
-      for (i = decl->Range.First;
-           i <= decl->Range.Last; i++) {
+      for (i = decl->Range.First; i <= decl->Range.Last; i++) {
          pctx->samplersUsed |= 1 << i;
       }
    }
@@ -211,8 +215,7 @@ pstip_transform_decl(struct tgsi_transform_context *ctx,
    }
    else if (decl->Declaration.File == TGSI_FILE_TEMPORARY) {
       uint i;
-      for (i = decl->Range.First;
-           i <= decl->Range.Last; i++) {
+      for (i = decl->Range.First; i <= decl->Range.Last; i++) {
          pctx->tempsUsed |= (1 << i);
       }
    }
@@ -243,8 +246,16 @@ free_bit(uint bitfield)
 
 /**
  * TGSI instruction transform callback.
- * Replace writes to result.color w/ a temp reg.
- * Upon END instruction, insert texture sampling code for antialiasing.
+ * Before the first instruction, insert our new code to sample the
+ * stipple texture (using the fragment coord register) then kill the
+ * fragment if the stipple texture bit is off.
+ *
+ * Insert:
+ *   declare new registers
+ *   MUL texTemp, INPUT[wincoord], 1/32;
+ *   TEX texTemp, texTemp, sampler;
+ *   KIL -texTemp;   # if -texTemp < 0, KILL fragment
+ *   [...original code...]
  */
 static void
 pstip_transform_inst(struct tgsi_transform_context *ctx,
@@ -261,7 +272,7 @@ pstip_transform_inst(struct tgsi_transform_context *ctx,
       uint i;
       int wincoordInput;
 
-      /* find free sampler */
+      /* find free texture sampler */
       pctx->freeSampler = free_bit(pctx->samplersUsed);
       if (pctx->freeSampler >= PIPE_MAX_SAMPLERS)
          pctx->freeSampler = PIPE_MAX_SAMPLERS - 1;
@@ -271,7 +282,7 @@ pstip_transform_inst(struct tgsi_transform_context *ctx,
       else
          wincoordInput = pctx->wincoordInput;
 
-      /* find one free temp reg */
+      /* find one free temp register */
       for (i = 0; i < 32; i++) {
          if ((pctx->tempsUsed & (1 << i)) == 0) {
             /* found a free temp */
@@ -397,6 +408,7 @@ util_pstipple_create_fragment_shader(struct pipe_context *pipe,
    struct pipe_shader_state *new_fs;
    struct pstip_transform_context transform;
    const uint newLen = tgsi_num_tokens(fs->tokens) + NUM_NEW_TOKENS;
+   unsigned i;
 
    new_fs = MALLOC(sizeof(*new_fs));
    if (!new_fs)
@@ -408,22 +420,33 @@ util_pstipple_create_fragment_shader(struct pipe_context *pipe,
       return NULL;
    }
 
+   /* Setup shader transformation info/context.
+    */
    memset(&transform, 0, sizeof(transform));
    transform.wincoordInput = -1;
    transform.maxInput = -1;
    transform.texTemp = -1;
    transform.firstInstruction = TRUE;
+   transform.coordOrigin = TGSI_FS_COORD_ORIGIN_UPPER_LEFT;
    transform.base.transform_instruction = pstip_transform_inst;
    transform.base.transform_declaration = pstip_transform_decl;
    transform.base.transform_immediate = pstip_transform_immed;
 
+   tgsi_scan_shader(fs->tokens, &transform.info);
+
+   /* find fragment coordinate origin property */
+   for (i = 0; i < transform.info.num_properties; i++) {
+      if (transform.info.properties[i].name == TGSI_PROPERTY_FS_COORD_ORIGIN)
+         transform.coordOrigin = transform.info.properties[i].data[0];
+   }
+
    tgsi_transform_shader(fs->tokens,
                          (struct tgsi_token *) new_fs->tokens,
                          newLen, &transform.base);
 
 #if 0 /* DEBUG */
    tgsi_dump(fs->tokens, 0);
-   tgsi_dump(pstip_fs.tokens, 0);
+   tgsi_dump(new_fs->tokens, 0);
 #endif
 
    assert(transform.freeSampler < PIPE_MAX_SAMPLERS);