draw: use util_pstipple_create_fragment_shader
authorNicolai Hähnle <nicolai.haehnle@amd.com>
Thu, 21 Jan 2016 21:03:17 +0000 (16:03 -0500)
committerNicolai Hähnle <nicolai.haehnle@amd.com>
Tue, 9 Feb 2016 15:01:32 +0000 (10:01 -0500)
This reduces code duplication. It also adds support for drivers where the
fragment position is a system value.

Suggested-by: Jose Fonseca <jfonseca@vmware.com>
Reviewed-by: Brian Paul <brianp@vmware.com>
Reviewed-by: Jose Fonseca <jfonseca@vmware.com>
src/gallium/auxiliary/draw/draw_pipe_pstipple.c

index cf52ca48b26d49b4779732aba4d04fccc8a31d5b..e468cc3891086933bf431d64fb6ffc4a9cee9d90 100644 (file)
 #include "util/u_format.h"
 #include "util/u_math.h"
 #include "util/u_memory.h"
+#include "util/u_pstipple.h"
 #include "util/u_sampler.h"
 
 #include "tgsi/tgsi_transform.h"
-#include "tgsi/tgsi_dump.h"
 
 #include "draw_context.h"
 #include "draw_pipe.h"
@@ -114,178 +114,6 @@ struct pstip_stage
 };
 
 
-
-/**
- * Subclass of tgsi_transform_context, used for transforming the
- * user's fragment shader to add the extra texture sample and fragment kill
- * instructions.
- */
-struct pstip_transform_context {
-   struct tgsi_transform_context base;
-   uint tempsUsed;  /**< bitmask */
-   int wincoordInput;
-   int maxInput;
-   uint samplersUsed;  /**< bitfield of samplers used */
-   bool hasSview;
-   int freeSampler;  /** an available sampler for the pstipple */
-   int texTemp;  /**< temp registers */
-   int numImmed;
-};
-
-
-/**
- * TGSI declaration transform callback.
- * Look for a free sampler, a free input attrib, and two free temp regs.
- */
-static void
-pstip_transform_decl(struct tgsi_transform_context *ctx,
-                     struct tgsi_full_declaration *decl)
-{
-   struct pstip_transform_context *pctx = (struct pstip_transform_context *) ctx;
-
-   if (decl->Declaration.File == TGSI_FILE_SAMPLER) {
-      uint i;
-      for (i = decl->Range.First;
-           i <= decl->Range.Last; i++) {
-         pctx->samplersUsed |= 1 << i;
-      }
-   }
-   else if (decl->Declaration.File == TGSI_FILE_SAMPLER_VIEW) {
-      pctx->hasSview = true;
-   }
-   else if (decl->Declaration.File == TGSI_FILE_INPUT) {
-      pctx->maxInput = MAX2(pctx->maxInput, (int) decl->Range.Last);
-      if (decl->Semantic.Name == TGSI_SEMANTIC_POSITION)
-         pctx->wincoordInput = (int) decl->Range.First;
-   }
-   else if (decl->Declaration.File == TGSI_FILE_TEMPORARY) {
-      uint i;
-      for (i = decl->Range.First;
-           i <= decl->Range.Last; i++) {
-         pctx->tempsUsed |= (1 << i);
-      }
-   }
-
-   ctx->emit_declaration(ctx, decl);
-}
-
-
-/**
- * TGSI immediate declaration transform callback.
- * We're just counting the number of immediates here.
- */
-static void
-pstip_transform_immed(struct tgsi_transform_context *ctx,
-                      struct tgsi_full_immediate *immed)
-{
-   struct pstip_transform_context *pctx = (struct pstip_transform_context *) ctx;
-   ctx->emit_immediate(ctx, immed); /* emit to output shader */
-   pctx->numImmed++;
-}
-
-
-/**
- * Find the lowest zero bit in the given word, or -1 if bitfield is all ones.
- */
-static int
-free_bit(uint bitfield)
-{
-   return ffs(~bitfield) - 1;
-}
-
-
-/**
- * TGSI transform prolog callback.
- */
-static void
-pstip_transform_prolog(struct tgsi_transform_context *ctx)
-{
-   struct pstip_transform_context *pctx = (struct pstip_transform_context *) ctx;
-   uint i;
-   int wincoordInput;
-
-   /* find free sampler */
-   pctx->freeSampler = free_bit(pctx->samplersUsed);
-   if (pctx->freeSampler >= PIPE_MAX_SAMPLERS)
-      pctx->freeSampler = PIPE_MAX_SAMPLERS - 1;
-
-   if (pctx->wincoordInput < 0)
-      wincoordInput = pctx->maxInput + 1;
-   else
-      wincoordInput = pctx->wincoordInput;
-
-   /* find one free temp reg */
-   for (i = 0; i < 32; i++) {
-      if ((pctx->tempsUsed & (1 << i)) == 0) {
-      /* found a free temp */
-      if (pctx->texTemp < 0)
-         pctx->texTemp  = i;
-      else
-         break;
-      }
-   }
-   assert(pctx->texTemp >= 0);
-
-   if (pctx->wincoordInput < 0) {
-      /* declare new position input reg */
-      tgsi_transform_input_decl(ctx, wincoordInput,
-                                TGSI_SEMANTIC_POSITION, 1,
-                                TGSI_INTERPOLATE_LINEAR);
-   }
-
-   /* declare new sampler */
-   tgsi_transform_sampler_decl(ctx, pctx->freeSampler);
-
-   /* if the src shader has SVIEW decl's for each SAMP decl, we
-    * need to continue the trend and ensure there is a matching
-    * SVIEW for the new SAMP we just created
-    */
-   if (pctx->hasSview) {
-      tgsi_transform_sampler_view_decl(ctx,
-                                       pctx->freeSampler,
-                                       TGSI_TEXTURE_2D,
-                                       TGSI_RETURN_TYPE_FLOAT);
-   }
-
-   /* declare new temp regs */
-   tgsi_transform_temp_decl(ctx, pctx->texTemp);
-
-   /* emit immediate = {1/32, 1/32, 1, 1}
-    * The index/position of this immediate will be pctx->numImmed
-    */
-   tgsi_transform_immediate_decl(ctx, 1.0/32.0, 1.0/32.0, 1.0, 1.0);
-
-   /* 
-    * Insert new MUL/TEX/KILL_IF instructions at start of program
-    * Take gl_FragCoord, divide by 32 (stipple size), sample the
-    * texture and kill fragment if needed.
-    *
-    * We'd like to use non-normalized texcoords to index into a RECT
-    * texture, but we can only use GL_REPEAT wrap mode with normalized
-    * texcoords.  Darn.
-    */
-
-   /* MUL texTemp, INPUT[wincoord], 1/32; */
-   tgsi_transform_op2_inst(ctx, TGSI_OPCODE_MUL,
-                           TGSI_FILE_TEMPORARY, pctx->texTemp,
-                           TGSI_WRITEMASK_XYZW,
-                           TGSI_FILE_INPUT, wincoordInput,
-                           TGSI_FILE_IMMEDIATE, pctx->numImmed);
-
-   /* TEX texTemp, texTemp, sampler; */
-   tgsi_transform_tex_2d_inst(ctx,
-                              TGSI_FILE_TEMPORARY, pctx->texTemp,
-                              TGSI_FILE_TEMPORARY, pctx->texTemp,
-                              pctx->freeSampler);
-
-   /* KILL_IF -texTemp.wwww;   # if -texTemp < 0, KILL fragment */
-   tgsi_transform_kill_inst(ctx,
-                            TGSI_FILE_TEMPORARY, pctx->texTemp,
-                            TGSI_SWIZZLE_W, TRUE);
-}
-
-
-
 /**
  * Generate the frag shader we'll use for doing polygon stipple.
  * This will be the user's shader prefixed with a TEX and KIL instruction.
@@ -293,40 +121,27 @@ pstip_transform_prolog(struct tgsi_transform_context *ctx)
 static boolean
 generate_pstip_fs(struct pstip_stage *pstip)
 {
+   struct pipe_context *pipe = pstip->pipe;
+   struct pipe_screen *screen = pipe->screen;
    const struct pipe_shader_state *orig_fs = &pstip->fs->state;
    /*struct draw_context *draw = pstip->stage.draw;*/
    struct pipe_shader_state pstip_fs;
-   struct pstip_transform_context transform;
-   const uint newLen = tgsi_num_tokens(orig_fs->tokens) + NUM_NEW_TOKENS;
+   enum tgsi_file_type wincoord_file;
+
+   wincoord_file = screen->get_param(screen, PIPE_CAP_TGSI_FS_POSITION_IS_SYSVAL) ?
+                   TGSI_FILE_SYSTEM_VALUE : TGSI_FILE_INPUT;
 
    pstip_fs = *orig_fs; /* copy to init */
-   pstip_fs.tokens = tgsi_alloc_tokens(newLen);
+   pstip_fs.tokens = util_pstipple_create_fragment_shader(orig_fs->tokens,
+                                                          &pstip->fs->sampler_unit,
+                                                          0,
+                                                          wincoord_file);
    if (pstip_fs.tokens == NULL)
       return FALSE;
 
-   memset(&transform, 0, sizeof(transform));
-   transform.wincoordInput = -1;
-   transform.maxInput = -1;
-   transform.texTemp = -1;
-   transform.base.prolog = pstip_transform_prolog;
-   transform.base.transform_declaration = pstip_transform_decl;
-   transform.base.transform_immediate = pstip_transform_immed;
-
-   tgsi_transform_shader(orig_fs->tokens,
-                         (struct tgsi_token *) pstip_fs.tokens,
-                         newLen, &transform.base);
-
-#if 0 /* DEBUG */
-   tgsi_dump(orig_fs->tokens, 0);
-   tgsi_dump(pstip_fs.tokens, 0);
-#endif
-
-   assert(pstip->fs);
-
-   pstip->fs->sampler_unit = transform.freeSampler;
    assert(pstip->fs->sampler_unit < PIPE_MAX_SAMPLERS);
 
-   pstip->fs->pstip_fs = pstip->driver_create_fs_state(pstip->pipe, &pstip_fs);
+   pstip->fs->pstip_fs = pstip->driver_create_fs_state(pipe, &pstip_fs);
    
    FREE((void *)pstip_fs.tokens);