u_pstipple.c revision 7dcf019af2e76a4c6e0391c3c5e1d50966367df8
17dcf019af2e76a4c6e0391c3c5e1d50966367df8Brian Paul/**************************************************************************
27dcf019af2e76a4c6e0391c3c5e1d50966367df8Brian Paul *
37dcf019af2e76a4c6e0391c3c5e1d50966367df8Brian Paul * Copyright 2008 Tungsten Graphics, Inc., Cedar Park, Texas.
47dcf019af2e76a4c6e0391c3c5e1d50966367df8Brian Paul * Copyright 2010 VMware, Inc.
57dcf019af2e76a4c6e0391c3c5e1d50966367df8Brian Paul * All Rights Reserved.
67dcf019af2e76a4c6e0391c3c5e1d50966367df8Brian Paul *
77dcf019af2e76a4c6e0391c3c5e1d50966367df8Brian Paul * Permission is hereby granted, free of charge, to any person obtaining a
87dcf019af2e76a4c6e0391c3c5e1d50966367df8Brian Paul * copy of this software and associated documentation files (the
97dcf019af2e76a4c6e0391c3c5e1d50966367df8Brian Paul * "Software"), to deal in the Software without restriction, including
107dcf019af2e76a4c6e0391c3c5e1d50966367df8Brian Paul * without limitation the rights to use, copy, modify, merge, publish,
117dcf019af2e76a4c6e0391c3c5e1d50966367df8Brian Paul * distribute, sub license, and/or sell copies of the Software, and to
127dcf019af2e76a4c6e0391c3c5e1d50966367df8Brian Paul * permit persons to whom the Software is furnished to do so, subject to
137dcf019af2e76a4c6e0391c3c5e1d50966367df8Brian Paul * the following conditions:
147dcf019af2e76a4c6e0391c3c5e1d50966367df8Brian Paul *
157dcf019af2e76a4c6e0391c3c5e1d50966367df8Brian Paul * The above copyright notice and this permission notice (including the
167dcf019af2e76a4c6e0391c3c5e1d50966367df8Brian Paul * next paragraph) shall be included in all copies or substantial portions
177dcf019af2e76a4c6e0391c3c5e1d50966367df8Brian Paul * of the Software.
187dcf019af2e76a4c6e0391c3c5e1d50966367df8Brian Paul *
197dcf019af2e76a4c6e0391c3c5e1d50966367df8Brian Paul * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
207dcf019af2e76a4c6e0391c3c5e1d50966367df8Brian Paul * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
217dcf019af2e76a4c6e0391c3c5e1d50966367df8Brian Paul * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT.
227dcf019af2e76a4c6e0391c3c5e1d50966367df8Brian Paul * IN NO EVENT SHALL TUNGSTEN GRAPHICS AND/OR ITS SUPPLIERS BE LIABLE FOR
237dcf019af2e76a4c6e0391c3c5e1d50966367df8Brian Paul * ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
247dcf019af2e76a4c6e0391c3c5e1d50966367df8Brian Paul * TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
257dcf019af2e76a4c6e0391c3c5e1d50966367df8Brian Paul * SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
267dcf019af2e76a4c6e0391c3c5e1d50966367df8Brian Paul *
277dcf019af2e76a4c6e0391c3c5e1d50966367df8Brian Paul **************************************************************************/
287dcf019af2e76a4c6e0391c3c5e1d50966367df8Brian Paul
297dcf019af2e76a4c6e0391c3c5e1d50966367df8Brian Paul/**
307dcf019af2e76a4c6e0391c3c5e1d50966367df8Brian Paul * Polygon stipple helper module.  Drivers/GPUs which don't support polygon
317dcf019af2e76a4c6e0391c3c5e1d50966367df8Brian Paul * stipple natively can use this module to simulate it.
327dcf019af2e76a4c6e0391c3c5e1d50966367df8Brian Paul *
337dcf019af2e76a4c6e0391c3c5e1d50966367df8Brian Paul * Basically, modify fragment shader to sample the 32x32 stipple pattern
347dcf019af2e76a4c6e0391c3c5e1d50966367df8Brian Paul * texture and do a fragment kill for the 'off' bits.
357dcf019af2e76a4c6e0391c3c5e1d50966367df8Brian Paul *
367dcf019af2e76a4c6e0391c3c5e1d50966367df8Brian Paul * This was originally a 'draw' module stage, but since we don't need
377dcf019af2e76a4c6e0391c3c5e1d50966367df8Brian Paul * vertex window coords or anything, it can be a stand-alone utility module.
387dcf019af2e76a4c6e0391c3c5e1d50966367df8Brian Paul *
397dcf019af2e76a4c6e0391c3c5e1d50966367df8Brian Paul * Authors:  Brian Paul
407dcf019af2e76a4c6e0391c3c5e1d50966367df8Brian Paul */
417dcf019af2e76a4c6e0391c3c5e1d50966367df8Brian Paul
427dcf019af2e76a4c6e0391c3c5e1d50966367df8Brian Paul
437dcf019af2e76a4c6e0391c3c5e1d50966367df8Brian Paul#include "pipe/p_context.h"
447dcf019af2e76a4c6e0391c3c5e1d50966367df8Brian Paul#include "pipe/p_defines.h"
457dcf019af2e76a4c6e0391c3c5e1d50966367df8Brian Paul#include "pipe/p_shader_tokens.h"
467dcf019af2e76a4c6e0391c3c5e1d50966367df8Brian Paul#include "util/u_inlines.h"
477dcf019af2e76a4c6e0391c3c5e1d50966367df8Brian Paul
487dcf019af2e76a4c6e0391c3c5e1d50966367df8Brian Paul#include "util/u_format.h"
497dcf019af2e76a4c6e0391c3c5e1d50966367df8Brian Paul#include "util/u_memory.h"
507dcf019af2e76a4c6e0391c3c5e1d50966367df8Brian Paul#include "util/u_pstipple.h"
517dcf019af2e76a4c6e0391c3c5e1d50966367df8Brian Paul#include "util/u_sampler.h"
527dcf019af2e76a4c6e0391c3c5e1d50966367df8Brian Paul
537dcf019af2e76a4c6e0391c3c5e1d50966367df8Brian Paul#include "tgsi/tgsi_transform.h"
547dcf019af2e76a4c6e0391c3c5e1d50966367df8Brian Paul#include "tgsi/tgsi_dump.h"
557dcf019af2e76a4c6e0391c3c5e1d50966367df8Brian Paul
567dcf019af2e76a4c6e0391c3c5e1d50966367df8Brian Paul/** Approx number of new tokens for instructions in pstip_transform_inst() */
577dcf019af2e76a4c6e0391c3c5e1d50966367df8Brian Paul#define NUM_NEW_TOKENS 50
587dcf019af2e76a4c6e0391c3c5e1d50966367df8Brian Paul
597dcf019af2e76a4c6e0391c3c5e1d50966367df8Brian Paul
607dcf019af2e76a4c6e0391c3c5e1d50966367df8Brian Paulstatic void
617dcf019af2e76a4c6e0391c3c5e1d50966367df8Brian Paulutil_pstipple_update_stipple_texture(struct pipe_context *pipe,
627dcf019af2e76a4c6e0391c3c5e1d50966367df8Brian Paul                                     struct pipe_resource *tex,
637dcf019af2e76a4c6e0391c3c5e1d50966367df8Brian Paul                                     const uint32_t pattern[32])
647dcf019af2e76a4c6e0391c3c5e1d50966367df8Brian Paul{
657dcf019af2e76a4c6e0391c3c5e1d50966367df8Brian Paul   static const uint bit31 = 1 << 31;
667dcf019af2e76a4c6e0391c3c5e1d50966367df8Brian Paul   struct pipe_transfer *transfer;
677dcf019af2e76a4c6e0391c3c5e1d50966367df8Brian Paul   ubyte *data;
687dcf019af2e76a4c6e0391c3c5e1d50966367df8Brian Paul   int i, j;
697dcf019af2e76a4c6e0391c3c5e1d50966367df8Brian Paul
707dcf019af2e76a4c6e0391c3c5e1d50966367df8Brian Paul   /* map texture memory */
717dcf019af2e76a4c6e0391c3c5e1d50966367df8Brian Paul   transfer = pipe_get_transfer(pipe, tex, 0, 0,
727dcf019af2e76a4c6e0391c3c5e1d50966367df8Brian Paul                                PIPE_TRANSFER_WRITE, 0, 0, 32, 32);
737dcf019af2e76a4c6e0391c3c5e1d50966367df8Brian Paul   data = pipe->transfer_map(pipe, transfer);
747dcf019af2e76a4c6e0391c3c5e1d50966367df8Brian Paul
757dcf019af2e76a4c6e0391c3c5e1d50966367df8Brian Paul   /*
767dcf019af2e76a4c6e0391c3c5e1d50966367df8Brian Paul    * Load alpha texture.
777dcf019af2e76a4c6e0391c3c5e1d50966367df8Brian Paul    * Note: 0 means keep the fragment, 255 means kill it.
787dcf019af2e76a4c6e0391c3c5e1d50966367df8Brian Paul    * We'll negate the texel value and use KILP which kills if value
797dcf019af2e76a4c6e0391c3c5e1d50966367df8Brian Paul    * is negative.
807dcf019af2e76a4c6e0391c3c5e1d50966367df8Brian Paul    */
817dcf019af2e76a4c6e0391c3c5e1d50966367df8Brian Paul   for (i = 0; i < 32; i++) {
827dcf019af2e76a4c6e0391c3c5e1d50966367df8Brian Paul      for (j = 0; j < 32; j++) {
837dcf019af2e76a4c6e0391c3c5e1d50966367df8Brian Paul         if (pattern[i] & (bit31 >> j)) {
847dcf019af2e76a4c6e0391c3c5e1d50966367df8Brian Paul            /* fragment "on" */
857dcf019af2e76a4c6e0391c3c5e1d50966367df8Brian Paul            data[i * transfer->stride + j] = 0;
867dcf019af2e76a4c6e0391c3c5e1d50966367df8Brian Paul         }
877dcf019af2e76a4c6e0391c3c5e1d50966367df8Brian Paul         else {
887dcf019af2e76a4c6e0391c3c5e1d50966367df8Brian Paul            /* fragment "off" */
897dcf019af2e76a4c6e0391c3c5e1d50966367df8Brian Paul            data[i * transfer->stride + j] = 255;
907dcf019af2e76a4c6e0391c3c5e1d50966367df8Brian Paul         }
917dcf019af2e76a4c6e0391c3c5e1d50966367df8Brian Paul      }
927dcf019af2e76a4c6e0391c3c5e1d50966367df8Brian Paul   }
937dcf019af2e76a4c6e0391c3c5e1d50966367df8Brian Paul
947dcf019af2e76a4c6e0391c3c5e1d50966367df8Brian Paul   /* unmap */
957dcf019af2e76a4c6e0391c3c5e1d50966367df8Brian Paul   pipe->transfer_unmap(pipe, transfer);
967dcf019af2e76a4c6e0391c3c5e1d50966367df8Brian Paul   pipe->transfer_destroy(pipe, transfer);
977dcf019af2e76a4c6e0391c3c5e1d50966367df8Brian Paul}
987dcf019af2e76a4c6e0391c3c5e1d50966367df8Brian Paul
997dcf019af2e76a4c6e0391c3c5e1d50966367df8Brian Paul
1007dcf019af2e76a4c6e0391c3c5e1d50966367df8Brian Paul/**
1017dcf019af2e76a4c6e0391c3c5e1d50966367df8Brian Paul * Create a 32x32 alpha8 texture that encodes the given stipple pattern.
1027dcf019af2e76a4c6e0391c3c5e1d50966367df8Brian Paul */
1037dcf019af2e76a4c6e0391c3c5e1d50966367df8Brian Paulstruct pipe_resource *
1047dcf019af2e76a4c6e0391c3c5e1d50966367df8Brian Paulutil_pstipple_create_stipple_texture(struct pipe_context *pipe,
1057dcf019af2e76a4c6e0391c3c5e1d50966367df8Brian Paul                                     const uint32_t pattern[32])
1067dcf019af2e76a4c6e0391c3c5e1d50966367df8Brian Paul{
1077dcf019af2e76a4c6e0391c3c5e1d50966367df8Brian Paul   struct pipe_screen *screen = pipe->screen;
1087dcf019af2e76a4c6e0391c3c5e1d50966367df8Brian Paul   struct pipe_resource templat, *tex;
1097dcf019af2e76a4c6e0391c3c5e1d50966367df8Brian Paul
1107dcf019af2e76a4c6e0391c3c5e1d50966367df8Brian Paul   memset(&templat, 0, sizeof(templat));
1117dcf019af2e76a4c6e0391c3c5e1d50966367df8Brian Paul   templat.target = PIPE_TEXTURE_2D;
1127dcf019af2e76a4c6e0391c3c5e1d50966367df8Brian Paul   templat.format = PIPE_FORMAT_A8_UNORM;
1137dcf019af2e76a4c6e0391c3c5e1d50966367df8Brian Paul   templat.last_level = 0;
1147dcf019af2e76a4c6e0391c3c5e1d50966367df8Brian Paul   templat.width0 = 32;
1157dcf019af2e76a4c6e0391c3c5e1d50966367df8Brian Paul   templat.height0 = 32;
1167dcf019af2e76a4c6e0391c3c5e1d50966367df8Brian Paul   templat.depth0 = 1;
1177dcf019af2e76a4c6e0391c3c5e1d50966367df8Brian Paul   templat.array_size = 1;
1187dcf019af2e76a4c6e0391c3c5e1d50966367df8Brian Paul   templat.bind = PIPE_BIND_SAMPLER_VIEW;
1197dcf019af2e76a4c6e0391c3c5e1d50966367df8Brian Paul
1207dcf019af2e76a4c6e0391c3c5e1d50966367df8Brian Paul   tex = screen->resource_create(screen, &templat);
1217dcf019af2e76a4c6e0391c3c5e1d50966367df8Brian Paul
1227dcf019af2e76a4c6e0391c3c5e1d50966367df8Brian Paul   if (tex)
1237dcf019af2e76a4c6e0391c3c5e1d50966367df8Brian Paul      util_pstipple_update_stipple_texture(pipe, tex, pattern);
1247dcf019af2e76a4c6e0391c3c5e1d50966367df8Brian Paul
1257dcf019af2e76a4c6e0391c3c5e1d50966367df8Brian Paul   return tex;
1267dcf019af2e76a4c6e0391c3c5e1d50966367df8Brian Paul}
1277dcf019af2e76a4c6e0391c3c5e1d50966367df8Brian Paul
1287dcf019af2e76a4c6e0391c3c5e1d50966367df8Brian Paul
1297dcf019af2e76a4c6e0391c3c5e1d50966367df8Brian Paul/**
1307dcf019af2e76a4c6e0391c3c5e1d50966367df8Brian Paul * Create sampler view to sample the stipple texture.
1317dcf019af2e76a4c6e0391c3c5e1d50966367df8Brian Paul */
1327dcf019af2e76a4c6e0391c3c5e1d50966367df8Brian Paulstruct pipe_sampler_view *
1337dcf019af2e76a4c6e0391c3c5e1d50966367df8Brian Paulutil_pstipple_create_sampler_view(struct pipe_context *pipe,
1347dcf019af2e76a4c6e0391c3c5e1d50966367df8Brian Paul                                  struct pipe_resource *tex)
1357dcf019af2e76a4c6e0391c3c5e1d50966367df8Brian Paul{
1367dcf019af2e76a4c6e0391c3c5e1d50966367df8Brian Paul   struct pipe_sampler_view templat, *sv;
1377dcf019af2e76a4c6e0391c3c5e1d50966367df8Brian Paul
1387dcf019af2e76a4c6e0391c3c5e1d50966367df8Brian Paul   u_sampler_view_default_template(&templat, tex, tex->format);
1397dcf019af2e76a4c6e0391c3c5e1d50966367df8Brian Paul   sv = pipe->create_sampler_view(pipe, tex, &templat);
1407dcf019af2e76a4c6e0391c3c5e1d50966367df8Brian Paul
1417dcf019af2e76a4c6e0391c3c5e1d50966367df8Brian Paul   return sv;
1427dcf019af2e76a4c6e0391c3c5e1d50966367df8Brian Paul}
1437dcf019af2e76a4c6e0391c3c5e1d50966367df8Brian Paul
1447dcf019af2e76a4c6e0391c3c5e1d50966367df8Brian Paul
1457dcf019af2e76a4c6e0391c3c5e1d50966367df8Brian Paul/**
1467dcf019af2e76a4c6e0391c3c5e1d50966367df8Brian Paul * Create the sampler CSO that'll be used for stippling.
1477dcf019af2e76a4c6e0391c3c5e1d50966367df8Brian Paul */
1487dcf019af2e76a4c6e0391c3c5e1d50966367df8Brian Paulvoid *
1497dcf019af2e76a4c6e0391c3c5e1d50966367df8Brian Paulutil_pstipple_create_sampler(struct pipe_context *pipe)
1507dcf019af2e76a4c6e0391c3c5e1d50966367df8Brian Paul{
1517dcf019af2e76a4c6e0391c3c5e1d50966367df8Brian Paul   struct pipe_sampler_state templat;
1527dcf019af2e76a4c6e0391c3c5e1d50966367df8Brian Paul   void *s;
1537dcf019af2e76a4c6e0391c3c5e1d50966367df8Brian Paul
1547dcf019af2e76a4c6e0391c3c5e1d50966367df8Brian Paul   memset(&templat, 0, sizeof(templat));
1557dcf019af2e76a4c6e0391c3c5e1d50966367df8Brian Paul   templat.wrap_s = PIPE_TEX_WRAP_REPEAT;
1567dcf019af2e76a4c6e0391c3c5e1d50966367df8Brian Paul   templat.wrap_t = PIPE_TEX_WRAP_REPEAT;
1577dcf019af2e76a4c6e0391c3c5e1d50966367df8Brian Paul   templat.wrap_r = PIPE_TEX_WRAP_REPEAT;
1587dcf019af2e76a4c6e0391c3c5e1d50966367df8Brian Paul   templat.min_mip_filter = PIPE_TEX_MIPFILTER_NONE;
1597dcf019af2e76a4c6e0391c3c5e1d50966367df8Brian Paul   templat.min_img_filter = PIPE_TEX_FILTER_NEAREST;
1607dcf019af2e76a4c6e0391c3c5e1d50966367df8Brian Paul   templat.mag_img_filter = PIPE_TEX_FILTER_NEAREST;
1617dcf019af2e76a4c6e0391c3c5e1d50966367df8Brian Paul   templat.normalized_coords = 1;
1627dcf019af2e76a4c6e0391c3c5e1d50966367df8Brian Paul   templat.min_lod = 0.0f;
1637dcf019af2e76a4c6e0391c3c5e1d50966367df8Brian Paul   templat.max_lod = 0.0f;
1647dcf019af2e76a4c6e0391c3c5e1d50966367df8Brian Paul
1657dcf019af2e76a4c6e0391c3c5e1d50966367df8Brian Paul   s = pipe->create_sampler_state(pipe, &templat);
1667dcf019af2e76a4c6e0391c3c5e1d50966367df8Brian Paul   return s;
1677dcf019af2e76a4c6e0391c3c5e1d50966367df8Brian Paul}
1687dcf019af2e76a4c6e0391c3c5e1d50966367df8Brian Paul
1697dcf019af2e76a4c6e0391c3c5e1d50966367df8Brian Paul
1707dcf019af2e76a4c6e0391c3c5e1d50966367df8Brian Paul
1717dcf019af2e76a4c6e0391c3c5e1d50966367df8Brian Paul/**
1727dcf019af2e76a4c6e0391c3c5e1d50966367df8Brian Paul * Subclass of tgsi_transform_context, used for transforming the
1737dcf019af2e76a4c6e0391c3c5e1d50966367df8Brian Paul * user's fragment shader to add the extra texture sample and fragment kill
1747dcf019af2e76a4c6e0391c3c5e1d50966367df8Brian Paul * instructions.
1757dcf019af2e76a4c6e0391c3c5e1d50966367df8Brian Paul */
1767dcf019af2e76a4c6e0391c3c5e1d50966367df8Brian Paulstruct pstip_transform_context {
1777dcf019af2e76a4c6e0391c3c5e1d50966367df8Brian Paul   struct tgsi_transform_context base;
1787dcf019af2e76a4c6e0391c3c5e1d50966367df8Brian Paul   uint tempsUsed;  /**< bitmask */
1797dcf019af2e76a4c6e0391c3c5e1d50966367df8Brian Paul   int wincoordInput;
1807dcf019af2e76a4c6e0391c3c5e1d50966367df8Brian Paul   int maxInput;
1817dcf019af2e76a4c6e0391c3c5e1d50966367df8Brian Paul   uint samplersUsed;  /**< bitfield of samplers used */
1827dcf019af2e76a4c6e0391c3c5e1d50966367df8Brian Paul   int freeSampler;  /** an available sampler for the pstipple */
1837dcf019af2e76a4c6e0391c3c5e1d50966367df8Brian Paul   int texTemp;  /**< temp registers */
1847dcf019af2e76a4c6e0391c3c5e1d50966367df8Brian Paul   int numImmed;
1857dcf019af2e76a4c6e0391c3c5e1d50966367df8Brian Paul   boolean firstInstruction;
1867dcf019af2e76a4c6e0391c3c5e1d50966367df8Brian Paul};
1877dcf019af2e76a4c6e0391c3c5e1d50966367df8Brian Paul
1887dcf019af2e76a4c6e0391c3c5e1d50966367df8Brian Paul
1897dcf019af2e76a4c6e0391c3c5e1d50966367df8Brian Paul/**
1907dcf019af2e76a4c6e0391c3c5e1d50966367df8Brian Paul * TGSI declaration transform callback.
1917dcf019af2e76a4c6e0391c3c5e1d50966367df8Brian Paul * Look for a free sampler, a free input attrib, and two free temp regs.
1927dcf019af2e76a4c6e0391c3c5e1d50966367df8Brian Paul */
1937dcf019af2e76a4c6e0391c3c5e1d50966367df8Brian Paulstatic void
1947dcf019af2e76a4c6e0391c3c5e1d50966367df8Brian Paulpstip_transform_decl(struct tgsi_transform_context *ctx,
1957dcf019af2e76a4c6e0391c3c5e1d50966367df8Brian Paul                     struct tgsi_full_declaration *decl)
1967dcf019af2e76a4c6e0391c3c5e1d50966367df8Brian Paul{
1977dcf019af2e76a4c6e0391c3c5e1d50966367df8Brian Paul   struct pstip_transform_context *pctx =
1987dcf019af2e76a4c6e0391c3c5e1d50966367df8Brian Paul      (struct pstip_transform_context *) ctx;
1997dcf019af2e76a4c6e0391c3c5e1d50966367df8Brian Paul
2007dcf019af2e76a4c6e0391c3c5e1d50966367df8Brian Paul   if (decl->Declaration.File == TGSI_FILE_SAMPLER) {
2017dcf019af2e76a4c6e0391c3c5e1d50966367df8Brian Paul      uint i;
2027dcf019af2e76a4c6e0391c3c5e1d50966367df8Brian Paul      for (i = decl->Range.First;
2037dcf019af2e76a4c6e0391c3c5e1d50966367df8Brian Paul           i <= decl->Range.Last; i++) {
2047dcf019af2e76a4c6e0391c3c5e1d50966367df8Brian Paul         pctx->samplersUsed |= 1 << i;
2057dcf019af2e76a4c6e0391c3c5e1d50966367df8Brian Paul      }
2067dcf019af2e76a4c6e0391c3c5e1d50966367df8Brian Paul   }
2077dcf019af2e76a4c6e0391c3c5e1d50966367df8Brian Paul   else if (decl->Declaration.File == TGSI_FILE_INPUT) {
2087dcf019af2e76a4c6e0391c3c5e1d50966367df8Brian Paul      pctx->maxInput = MAX2(pctx->maxInput, (int) decl->Range.Last);
2097dcf019af2e76a4c6e0391c3c5e1d50966367df8Brian Paul      if (decl->Semantic.Name == TGSI_SEMANTIC_POSITION)
2107dcf019af2e76a4c6e0391c3c5e1d50966367df8Brian Paul         pctx->wincoordInput = (int) decl->Range.First;
2117dcf019af2e76a4c6e0391c3c5e1d50966367df8Brian Paul   }
2127dcf019af2e76a4c6e0391c3c5e1d50966367df8Brian Paul   else if (decl->Declaration.File == TGSI_FILE_TEMPORARY) {
2137dcf019af2e76a4c6e0391c3c5e1d50966367df8Brian Paul      uint i;
2147dcf019af2e76a4c6e0391c3c5e1d50966367df8Brian Paul      for (i = decl->Range.First;
2157dcf019af2e76a4c6e0391c3c5e1d50966367df8Brian Paul           i <= decl->Range.Last; i++) {
2167dcf019af2e76a4c6e0391c3c5e1d50966367df8Brian Paul         pctx->tempsUsed |= (1 << i);
2177dcf019af2e76a4c6e0391c3c5e1d50966367df8Brian Paul      }
2187dcf019af2e76a4c6e0391c3c5e1d50966367df8Brian Paul   }
2197dcf019af2e76a4c6e0391c3c5e1d50966367df8Brian Paul
2207dcf019af2e76a4c6e0391c3c5e1d50966367df8Brian Paul   ctx->emit_declaration(ctx, decl);
2217dcf019af2e76a4c6e0391c3c5e1d50966367df8Brian Paul}
2227dcf019af2e76a4c6e0391c3c5e1d50966367df8Brian Paul
2237dcf019af2e76a4c6e0391c3c5e1d50966367df8Brian Paul
2247dcf019af2e76a4c6e0391c3c5e1d50966367df8Brian Paulstatic void
2257dcf019af2e76a4c6e0391c3c5e1d50966367df8Brian Paulpstip_transform_immed(struct tgsi_transform_context *ctx,
2267dcf019af2e76a4c6e0391c3c5e1d50966367df8Brian Paul                      struct tgsi_full_immediate *immed)
2277dcf019af2e76a4c6e0391c3c5e1d50966367df8Brian Paul{
2287dcf019af2e76a4c6e0391c3c5e1d50966367df8Brian Paul   struct pstip_transform_context *pctx =
2297dcf019af2e76a4c6e0391c3c5e1d50966367df8Brian Paul      (struct pstip_transform_context *) ctx;
2307dcf019af2e76a4c6e0391c3c5e1d50966367df8Brian Paul   pctx->numImmed++;
2317dcf019af2e76a4c6e0391c3c5e1d50966367df8Brian Paul}
2327dcf019af2e76a4c6e0391c3c5e1d50966367df8Brian Paul
2337dcf019af2e76a4c6e0391c3c5e1d50966367df8Brian Paul
2347dcf019af2e76a4c6e0391c3c5e1d50966367df8Brian Paul/**
2357dcf019af2e76a4c6e0391c3c5e1d50966367df8Brian Paul * Find the lowest zero bit in the given word, or -1 if bitfield is all ones.
2367dcf019af2e76a4c6e0391c3c5e1d50966367df8Brian Paul */
2377dcf019af2e76a4c6e0391c3c5e1d50966367df8Brian Paulstatic int
2387dcf019af2e76a4c6e0391c3c5e1d50966367df8Brian Paulfree_bit(uint bitfield)
2397dcf019af2e76a4c6e0391c3c5e1d50966367df8Brian Paul{
2407dcf019af2e76a4c6e0391c3c5e1d50966367df8Brian Paul   return ffs(~bitfield) - 1;
2417dcf019af2e76a4c6e0391c3c5e1d50966367df8Brian Paul}
2427dcf019af2e76a4c6e0391c3c5e1d50966367df8Brian Paul
2437dcf019af2e76a4c6e0391c3c5e1d50966367df8Brian Paul
2447dcf019af2e76a4c6e0391c3c5e1d50966367df8Brian Paul/**
2457dcf019af2e76a4c6e0391c3c5e1d50966367df8Brian Paul * TGSI instruction transform callback.
2467dcf019af2e76a4c6e0391c3c5e1d50966367df8Brian Paul * Replace writes to result.color w/ a temp reg.
2477dcf019af2e76a4c6e0391c3c5e1d50966367df8Brian Paul * Upon END instruction, insert texture sampling code for antialiasing.
2487dcf019af2e76a4c6e0391c3c5e1d50966367df8Brian Paul */
2497dcf019af2e76a4c6e0391c3c5e1d50966367df8Brian Paulstatic void
2507dcf019af2e76a4c6e0391c3c5e1d50966367df8Brian Paulpstip_transform_inst(struct tgsi_transform_context *ctx,
2517dcf019af2e76a4c6e0391c3c5e1d50966367df8Brian Paul                     struct tgsi_full_instruction *inst)
2527dcf019af2e76a4c6e0391c3c5e1d50966367df8Brian Paul{
2537dcf019af2e76a4c6e0391c3c5e1d50966367df8Brian Paul   struct pstip_transform_context *pctx =
2547dcf019af2e76a4c6e0391c3c5e1d50966367df8Brian Paul      (struct pstip_transform_context *) ctx;
2557dcf019af2e76a4c6e0391c3c5e1d50966367df8Brian Paul
2567dcf019af2e76a4c6e0391c3c5e1d50966367df8Brian Paul   if (pctx->firstInstruction) {
2577dcf019af2e76a4c6e0391c3c5e1d50966367df8Brian Paul      /* emit our new declarations before the first instruction */
2587dcf019af2e76a4c6e0391c3c5e1d50966367df8Brian Paul
2597dcf019af2e76a4c6e0391c3c5e1d50966367df8Brian Paul      struct tgsi_full_declaration decl;
2607dcf019af2e76a4c6e0391c3c5e1d50966367df8Brian Paul      struct tgsi_full_instruction newInst;
2617dcf019af2e76a4c6e0391c3c5e1d50966367df8Brian Paul      uint i;
2627dcf019af2e76a4c6e0391c3c5e1d50966367df8Brian Paul      int wincoordInput;
2637dcf019af2e76a4c6e0391c3c5e1d50966367df8Brian Paul
2647dcf019af2e76a4c6e0391c3c5e1d50966367df8Brian Paul      /* find free sampler */
2657dcf019af2e76a4c6e0391c3c5e1d50966367df8Brian Paul      pctx->freeSampler = free_bit(pctx->samplersUsed);
2667dcf019af2e76a4c6e0391c3c5e1d50966367df8Brian Paul      if (pctx->freeSampler >= PIPE_MAX_SAMPLERS)
2677dcf019af2e76a4c6e0391c3c5e1d50966367df8Brian Paul         pctx->freeSampler = PIPE_MAX_SAMPLERS - 1;
2687dcf019af2e76a4c6e0391c3c5e1d50966367df8Brian Paul
2697dcf019af2e76a4c6e0391c3c5e1d50966367df8Brian Paul      if (pctx->wincoordInput < 0)
2707dcf019af2e76a4c6e0391c3c5e1d50966367df8Brian Paul         wincoordInput = pctx->maxInput + 1;
2717dcf019af2e76a4c6e0391c3c5e1d50966367df8Brian Paul      else
2727dcf019af2e76a4c6e0391c3c5e1d50966367df8Brian Paul         wincoordInput = pctx->wincoordInput;
2737dcf019af2e76a4c6e0391c3c5e1d50966367df8Brian Paul
2747dcf019af2e76a4c6e0391c3c5e1d50966367df8Brian Paul      /* find one free temp reg */
2757dcf019af2e76a4c6e0391c3c5e1d50966367df8Brian Paul      for (i = 0; i < 32; i++) {
2767dcf019af2e76a4c6e0391c3c5e1d50966367df8Brian Paul         if ((pctx->tempsUsed & (1 << i)) == 0) {
2777dcf019af2e76a4c6e0391c3c5e1d50966367df8Brian Paul            /* found a free temp */
2787dcf019af2e76a4c6e0391c3c5e1d50966367df8Brian Paul            if (pctx->texTemp < 0)
2797dcf019af2e76a4c6e0391c3c5e1d50966367df8Brian Paul               pctx->texTemp  = i;
2807dcf019af2e76a4c6e0391c3c5e1d50966367df8Brian Paul            else
2817dcf019af2e76a4c6e0391c3c5e1d50966367df8Brian Paul               break;
2827dcf019af2e76a4c6e0391c3c5e1d50966367df8Brian Paul         }
2837dcf019af2e76a4c6e0391c3c5e1d50966367df8Brian Paul      }
2847dcf019af2e76a4c6e0391c3c5e1d50966367df8Brian Paul      assert(pctx->texTemp >= 0);
2857dcf019af2e76a4c6e0391c3c5e1d50966367df8Brian Paul
2867dcf019af2e76a4c6e0391c3c5e1d50966367df8Brian Paul      if (pctx->wincoordInput < 0) {
2877dcf019af2e76a4c6e0391c3c5e1d50966367df8Brian Paul         /* declare new position input reg */
2887dcf019af2e76a4c6e0391c3c5e1d50966367df8Brian Paul         decl = tgsi_default_full_declaration();
2897dcf019af2e76a4c6e0391c3c5e1d50966367df8Brian Paul         decl.Declaration.File = TGSI_FILE_INPUT;
2907dcf019af2e76a4c6e0391c3c5e1d50966367df8Brian Paul         decl.Declaration.Interpolate = TGSI_INTERPOLATE_LINEAR;
2917dcf019af2e76a4c6e0391c3c5e1d50966367df8Brian Paul         decl.Declaration.Semantic = 1;
2927dcf019af2e76a4c6e0391c3c5e1d50966367df8Brian Paul         decl.Semantic.Name = TGSI_SEMANTIC_POSITION;
2937dcf019af2e76a4c6e0391c3c5e1d50966367df8Brian Paul         decl.Semantic.Index = 0;
2947dcf019af2e76a4c6e0391c3c5e1d50966367df8Brian Paul         decl.Range.First =
2957dcf019af2e76a4c6e0391c3c5e1d50966367df8Brian Paul            decl.Range.Last = wincoordInput;
2967dcf019af2e76a4c6e0391c3c5e1d50966367df8Brian Paul         ctx->emit_declaration(ctx, &decl);
2977dcf019af2e76a4c6e0391c3c5e1d50966367df8Brian Paul      }
2987dcf019af2e76a4c6e0391c3c5e1d50966367df8Brian Paul
2997dcf019af2e76a4c6e0391c3c5e1d50966367df8Brian Paul      /* declare new sampler */
3007dcf019af2e76a4c6e0391c3c5e1d50966367df8Brian Paul      decl = tgsi_default_full_declaration();
3017dcf019af2e76a4c6e0391c3c5e1d50966367df8Brian Paul      decl.Declaration.File = TGSI_FILE_SAMPLER;
3027dcf019af2e76a4c6e0391c3c5e1d50966367df8Brian Paul      decl.Range.First =
3037dcf019af2e76a4c6e0391c3c5e1d50966367df8Brian Paul      decl.Range.Last = pctx->freeSampler;
3047dcf019af2e76a4c6e0391c3c5e1d50966367df8Brian Paul      ctx->emit_declaration(ctx, &decl);
3057dcf019af2e76a4c6e0391c3c5e1d50966367df8Brian Paul
3067dcf019af2e76a4c6e0391c3c5e1d50966367df8Brian Paul      /* declare new temp regs */
3077dcf019af2e76a4c6e0391c3c5e1d50966367df8Brian Paul      decl = tgsi_default_full_declaration();
3087dcf019af2e76a4c6e0391c3c5e1d50966367df8Brian Paul      decl.Declaration.File = TGSI_FILE_TEMPORARY;
3097dcf019af2e76a4c6e0391c3c5e1d50966367df8Brian Paul      decl.Range.First =
3107dcf019af2e76a4c6e0391c3c5e1d50966367df8Brian Paul      decl.Range.Last = pctx->texTemp;
3117dcf019af2e76a4c6e0391c3c5e1d50966367df8Brian Paul      ctx->emit_declaration(ctx, &decl);
3127dcf019af2e76a4c6e0391c3c5e1d50966367df8Brian Paul
3137dcf019af2e76a4c6e0391c3c5e1d50966367df8Brian Paul      /* emit immediate = {1/32, 1/32, 1, 1}
3147dcf019af2e76a4c6e0391c3c5e1d50966367df8Brian Paul       * The index/position of this immediate will be pctx->numImmed
3157dcf019af2e76a4c6e0391c3c5e1d50966367df8Brian Paul       */
3167dcf019af2e76a4c6e0391c3c5e1d50966367df8Brian Paul      {
3177dcf019af2e76a4c6e0391c3c5e1d50966367df8Brian Paul         static const float value[4] = { 1.0/32, 1.0/32, 1.0, 1.0 };
3187dcf019af2e76a4c6e0391c3c5e1d50966367df8Brian Paul         struct tgsi_full_immediate immed;
3197dcf019af2e76a4c6e0391c3c5e1d50966367df8Brian Paul         uint size = 4;
3207dcf019af2e76a4c6e0391c3c5e1d50966367df8Brian Paul         immed = tgsi_default_full_immediate();
3217dcf019af2e76a4c6e0391c3c5e1d50966367df8Brian Paul         immed.Immediate.NrTokens = 1 + size; /* one for the token itself */
3227dcf019af2e76a4c6e0391c3c5e1d50966367df8Brian Paul         immed.u[0].Float = value[0];
3237dcf019af2e76a4c6e0391c3c5e1d50966367df8Brian Paul         immed.u[1].Float = value[1];
3247dcf019af2e76a4c6e0391c3c5e1d50966367df8Brian Paul         immed.u[2].Float = value[2];
3257dcf019af2e76a4c6e0391c3c5e1d50966367df8Brian Paul         immed.u[3].Float = value[3];
3267dcf019af2e76a4c6e0391c3c5e1d50966367df8Brian Paul         ctx->emit_immediate(ctx, &immed);
3277dcf019af2e76a4c6e0391c3c5e1d50966367df8Brian Paul      }
3287dcf019af2e76a4c6e0391c3c5e1d50966367df8Brian Paul
3297dcf019af2e76a4c6e0391c3c5e1d50966367df8Brian Paul      pctx->firstInstruction = FALSE;
3307dcf019af2e76a4c6e0391c3c5e1d50966367df8Brian Paul
3317dcf019af2e76a4c6e0391c3c5e1d50966367df8Brian Paul
3327dcf019af2e76a4c6e0391c3c5e1d50966367df8Brian Paul      /*
3337dcf019af2e76a4c6e0391c3c5e1d50966367df8Brian Paul       * Insert new MUL/TEX/KILP instructions at start of program
3347dcf019af2e76a4c6e0391c3c5e1d50966367df8Brian Paul       * Take gl_FragCoord, divide by 32 (stipple size), sample the
3357dcf019af2e76a4c6e0391c3c5e1d50966367df8Brian Paul       * texture and kill fragment if needed.
3367dcf019af2e76a4c6e0391c3c5e1d50966367df8Brian Paul       *
3377dcf019af2e76a4c6e0391c3c5e1d50966367df8Brian Paul       * We'd like to use non-normalized texcoords to index into a RECT
3387dcf019af2e76a4c6e0391c3c5e1d50966367df8Brian Paul       * texture, but we can only use REPEAT wrap mode with normalized
3397dcf019af2e76a4c6e0391c3c5e1d50966367df8Brian Paul       * texcoords.  Darn.
3407dcf019af2e76a4c6e0391c3c5e1d50966367df8Brian Paul       */
3417dcf019af2e76a4c6e0391c3c5e1d50966367df8Brian Paul
3427dcf019af2e76a4c6e0391c3c5e1d50966367df8Brian Paul      /* XXX invert wincoord if origin isn't lower-left... */
3437dcf019af2e76a4c6e0391c3c5e1d50966367df8Brian Paul
3447dcf019af2e76a4c6e0391c3c5e1d50966367df8Brian Paul      /* MUL texTemp, INPUT[wincoord], 1/32; */
3457dcf019af2e76a4c6e0391c3c5e1d50966367df8Brian Paul      newInst = tgsi_default_full_instruction();
3467dcf019af2e76a4c6e0391c3c5e1d50966367df8Brian Paul      newInst.Instruction.Opcode = TGSI_OPCODE_MUL;
3477dcf019af2e76a4c6e0391c3c5e1d50966367df8Brian Paul      newInst.Instruction.NumDstRegs = 1;
3487dcf019af2e76a4c6e0391c3c5e1d50966367df8Brian Paul      newInst.Dst[0].Register.File = TGSI_FILE_TEMPORARY;
3497dcf019af2e76a4c6e0391c3c5e1d50966367df8Brian Paul      newInst.Dst[0].Register.Index = pctx->texTemp;
3507dcf019af2e76a4c6e0391c3c5e1d50966367df8Brian Paul      newInst.Instruction.NumSrcRegs = 2;
3517dcf019af2e76a4c6e0391c3c5e1d50966367df8Brian Paul      newInst.Src[0].Register.File = TGSI_FILE_INPUT;
3527dcf019af2e76a4c6e0391c3c5e1d50966367df8Brian Paul      newInst.Src[0].Register.Index = wincoordInput;
3537dcf019af2e76a4c6e0391c3c5e1d50966367df8Brian Paul      newInst.Src[1].Register.File = TGSI_FILE_IMMEDIATE;
3547dcf019af2e76a4c6e0391c3c5e1d50966367df8Brian Paul      newInst.Src[1].Register.Index = pctx->numImmed;
3557dcf019af2e76a4c6e0391c3c5e1d50966367df8Brian Paul      ctx->emit_instruction(ctx, &newInst);
3567dcf019af2e76a4c6e0391c3c5e1d50966367df8Brian Paul
3577dcf019af2e76a4c6e0391c3c5e1d50966367df8Brian Paul      /* TEX texTemp, texTemp, sampler; */
3587dcf019af2e76a4c6e0391c3c5e1d50966367df8Brian Paul      newInst = tgsi_default_full_instruction();
3597dcf019af2e76a4c6e0391c3c5e1d50966367df8Brian Paul      newInst.Instruction.Opcode = TGSI_OPCODE_TEX;
3607dcf019af2e76a4c6e0391c3c5e1d50966367df8Brian Paul      newInst.Instruction.NumDstRegs = 1;
3617dcf019af2e76a4c6e0391c3c5e1d50966367df8Brian Paul      newInst.Dst[0].Register.File = TGSI_FILE_TEMPORARY;
3627dcf019af2e76a4c6e0391c3c5e1d50966367df8Brian Paul      newInst.Dst[0].Register.Index = pctx->texTemp;
3637dcf019af2e76a4c6e0391c3c5e1d50966367df8Brian Paul      newInst.Instruction.NumSrcRegs = 2;
3647dcf019af2e76a4c6e0391c3c5e1d50966367df8Brian Paul      newInst.Instruction.Texture = TRUE;
3657dcf019af2e76a4c6e0391c3c5e1d50966367df8Brian Paul      newInst.Texture.Texture = TGSI_TEXTURE_2D;
3667dcf019af2e76a4c6e0391c3c5e1d50966367df8Brian Paul      newInst.Src[0].Register.File = TGSI_FILE_TEMPORARY;
3677dcf019af2e76a4c6e0391c3c5e1d50966367df8Brian Paul      newInst.Src[0].Register.Index = pctx->texTemp;
3687dcf019af2e76a4c6e0391c3c5e1d50966367df8Brian Paul      newInst.Src[1].Register.File = TGSI_FILE_SAMPLER;
3697dcf019af2e76a4c6e0391c3c5e1d50966367df8Brian Paul      newInst.Src[1].Register.Index = pctx->freeSampler;
3707dcf019af2e76a4c6e0391c3c5e1d50966367df8Brian Paul      ctx->emit_instruction(ctx, &newInst);
3717dcf019af2e76a4c6e0391c3c5e1d50966367df8Brian Paul
3727dcf019af2e76a4c6e0391c3c5e1d50966367df8Brian Paul      /* KIL -texTemp;   # if -texTemp < 0, KILL fragment */
3737dcf019af2e76a4c6e0391c3c5e1d50966367df8Brian Paul      newInst = tgsi_default_full_instruction();
3747dcf019af2e76a4c6e0391c3c5e1d50966367df8Brian Paul      newInst.Instruction.Opcode = TGSI_OPCODE_KIL;
3757dcf019af2e76a4c6e0391c3c5e1d50966367df8Brian Paul      newInst.Instruction.NumDstRegs = 0;
3767dcf019af2e76a4c6e0391c3c5e1d50966367df8Brian Paul      newInst.Instruction.NumSrcRegs = 1;
3777dcf019af2e76a4c6e0391c3c5e1d50966367df8Brian Paul      newInst.Src[0].Register.File = TGSI_FILE_TEMPORARY;
3787dcf019af2e76a4c6e0391c3c5e1d50966367df8Brian Paul      newInst.Src[0].Register.Index = pctx->texTemp;
3797dcf019af2e76a4c6e0391c3c5e1d50966367df8Brian Paul      newInst.Src[0].Register.Negate = 1;
3807dcf019af2e76a4c6e0391c3c5e1d50966367df8Brian Paul      ctx->emit_instruction(ctx, &newInst);
3817dcf019af2e76a4c6e0391c3c5e1d50966367df8Brian Paul   }
3827dcf019af2e76a4c6e0391c3c5e1d50966367df8Brian Paul
3837dcf019af2e76a4c6e0391c3c5e1d50966367df8Brian Paul   /* emit this instruction */
3847dcf019af2e76a4c6e0391c3c5e1d50966367df8Brian Paul   ctx->emit_instruction(ctx, inst);
3857dcf019af2e76a4c6e0391c3c5e1d50966367df8Brian Paul}
3867dcf019af2e76a4c6e0391c3c5e1d50966367df8Brian Paul
3877dcf019af2e76a4c6e0391c3c5e1d50966367df8Brian Paul
3887dcf019af2e76a4c6e0391c3c5e1d50966367df8Brian Paul/**
3897dcf019af2e76a4c6e0391c3c5e1d50966367df8Brian Paul * Given a fragment shader, return a new fragment shader which
3907dcf019af2e76a4c6e0391c3c5e1d50966367df8Brian Paul * samples a stipple texture and executes KILL.
3917dcf019af2e76a4c6e0391c3c5e1d50966367df8Brian Paul */
3927dcf019af2e76a4c6e0391c3c5e1d50966367df8Brian Paulstruct pipe_shader_state *
3937dcf019af2e76a4c6e0391c3c5e1d50966367df8Brian Paulutil_pstipple_create_fragment_shader(struct pipe_context *pipe,
3947dcf019af2e76a4c6e0391c3c5e1d50966367df8Brian Paul                                     struct pipe_shader_state *fs,
3957dcf019af2e76a4c6e0391c3c5e1d50966367df8Brian Paul                                     unsigned *samplerUnitOut)
3967dcf019af2e76a4c6e0391c3c5e1d50966367df8Brian Paul{
3977dcf019af2e76a4c6e0391c3c5e1d50966367df8Brian Paul   struct pipe_shader_state *new_fs;
3987dcf019af2e76a4c6e0391c3c5e1d50966367df8Brian Paul   struct pstip_transform_context transform;
3997dcf019af2e76a4c6e0391c3c5e1d50966367df8Brian Paul   const uint newLen = tgsi_num_tokens(fs->tokens) + NUM_NEW_TOKENS;
4007dcf019af2e76a4c6e0391c3c5e1d50966367df8Brian Paul
4017dcf019af2e76a4c6e0391c3c5e1d50966367df8Brian Paul   new_fs = MALLOC(sizeof(*new_fs));
4027dcf019af2e76a4c6e0391c3c5e1d50966367df8Brian Paul   if (!new_fs)
4037dcf019af2e76a4c6e0391c3c5e1d50966367df8Brian Paul      return NULL;
4047dcf019af2e76a4c6e0391c3c5e1d50966367df8Brian Paul
4057dcf019af2e76a4c6e0391c3c5e1d50966367df8Brian Paul   new_fs->tokens = tgsi_alloc_tokens(newLen);
4067dcf019af2e76a4c6e0391c3c5e1d50966367df8Brian Paul   if (!new_fs->tokens) {
4077dcf019af2e76a4c6e0391c3c5e1d50966367df8Brian Paul      FREE(new_fs);
4087dcf019af2e76a4c6e0391c3c5e1d50966367df8Brian Paul      return NULL;
4097dcf019af2e76a4c6e0391c3c5e1d50966367df8Brian Paul   }
4107dcf019af2e76a4c6e0391c3c5e1d50966367df8Brian Paul
4117dcf019af2e76a4c6e0391c3c5e1d50966367df8Brian Paul   memset(&transform, 0, sizeof(transform));
4127dcf019af2e76a4c6e0391c3c5e1d50966367df8Brian Paul   transform.wincoordInput = -1;
4137dcf019af2e76a4c6e0391c3c5e1d50966367df8Brian Paul   transform.maxInput = -1;
4147dcf019af2e76a4c6e0391c3c5e1d50966367df8Brian Paul   transform.texTemp = -1;
4157dcf019af2e76a4c6e0391c3c5e1d50966367df8Brian Paul   transform.firstInstruction = TRUE;
4167dcf019af2e76a4c6e0391c3c5e1d50966367df8Brian Paul   transform.base.transform_instruction = pstip_transform_inst;
4177dcf019af2e76a4c6e0391c3c5e1d50966367df8Brian Paul   transform.base.transform_declaration = pstip_transform_decl;
4187dcf019af2e76a4c6e0391c3c5e1d50966367df8Brian Paul   transform.base.transform_immediate = pstip_transform_immed;
4197dcf019af2e76a4c6e0391c3c5e1d50966367df8Brian Paul
4207dcf019af2e76a4c6e0391c3c5e1d50966367df8Brian Paul   tgsi_transform_shader(fs->tokens,
4217dcf019af2e76a4c6e0391c3c5e1d50966367df8Brian Paul                         (struct tgsi_token *) new_fs->tokens,
4227dcf019af2e76a4c6e0391c3c5e1d50966367df8Brian Paul                         newLen, &transform.base);
4237dcf019af2e76a4c6e0391c3c5e1d50966367df8Brian Paul
4247dcf019af2e76a4c6e0391c3c5e1d50966367df8Brian Paul#if 0 /* DEBUG */
4257dcf019af2e76a4c6e0391c3c5e1d50966367df8Brian Paul   tgsi_dump(fs->tokens, 0);
4267dcf019af2e76a4c6e0391c3c5e1d50966367df8Brian Paul   tgsi_dump(pstip_fs.tokens, 0);
4277dcf019af2e76a4c6e0391c3c5e1d50966367df8Brian Paul#endif
4287dcf019af2e76a4c6e0391c3c5e1d50966367df8Brian Paul
4297dcf019af2e76a4c6e0391c3c5e1d50966367df8Brian Paul   assert(transform.freeSampler < PIPE_MAX_SAMPLERS);
4307dcf019af2e76a4c6e0391c3c5e1d50966367df8Brian Paul   *samplerUnitOut = transform.freeSampler;
4317dcf019af2e76a4c6e0391c3c5e1d50966367df8Brian Paul
4327dcf019af2e76a4c6e0391c3c5e1d50966367df8Brian Paul   return new_fs;
4337dcf019af2e76a4c6e0391c3c5e1d50966367df8Brian Paul}
4347dcf019af2e76a4c6e0391c3c5e1d50966367df8Brian Paul
435