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"
553dde6be908d827f4d6d54e0968ae83c2c4dfa87cBrian Paul#include "tgsi/tgsi_scan.h"
567dcf019af2e76a4c6e0391c3c5e1d50966367df8Brian Paul
577dcf019af2e76a4c6e0391c3c5e1d50966367df8Brian Paul/** Approx number of new tokens for instructions in pstip_transform_inst() */
587dcf019af2e76a4c6e0391c3c5e1d50966367df8Brian Paul#define NUM_NEW_TOKENS 50
597dcf019af2e76a4c6e0391c3c5e1d50966367df8Brian Paul
607dcf019af2e76a4c6e0391c3c5e1d50966367df8Brian Paul
617dcf019af2e76a4c6e0391c3c5e1d50966367df8Brian Paulstatic void
627dcf019af2e76a4c6e0391c3c5e1d50966367df8Brian Paulutil_pstipple_update_stipple_texture(struct pipe_context *pipe,
637dcf019af2e76a4c6e0391c3c5e1d50966367df8Brian Paul                                     struct pipe_resource *tex,
647dcf019af2e76a4c6e0391c3c5e1d50966367df8Brian Paul                                     const uint32_t pattern[32])
657dcf019af2e76a4c6e0391c3c5e1d50966367df8Brian Paul{
667dcf019af2e76a4c6e0391c3c5e1d50966367df8Brian Paul   static const uint bit31 = 1 << 31;
677dcf019af2e76a4c6e0391c3c5e1d50966367df8Brian Paul   struct pipe_transfer *transfer;
687dcf019af2e76a4c6e0391c3c5e1d50966367df8Brian Paul   ubyte *data;
697dcf019af2e76a4c6e0391c3c5e1d50966367df8Brian Paul   int i, j;
707dcf019af2e76a4c6e0391c3c5e1d50966367df8Brian Paul
717dcf019af2e76a4c6e0391c3c5e1d50966367df8Brian Paul   /* map texture memory */
727dcf019af2e76a4c6e0391c3c5e1d50966367df8Brian Paul   transfer = pipe_get_transfer(pipe, tex, 0, 0,
737dcf019af2e76a4c6e0391c3c5e1d50966367df8Brian Paul                                PIPE_TRANSFER_WRITE, 0, 0, 32, 32);
747dcf019af2e76a4c6e0391c3c5e1d50966367df8Brian Paul   data = pipe->transfer_map(pipe, transfer);
757dcf019af2e76a4c6e0391c3c5e1d50966367df8Brian Paul
767dcf019af2e76a4c6e0391c3c5e1d50966367df8Brian Paul   /*
777dcf019af2e76a4c6e0391c3c5e1d50966367df8Brian Paul    * Load alpha texture.
787dcf019af2e76a4c6e0391c3c5e1d50966367df8Brian Paul    * Note: 0 means keep the fragment, 255 means kill it.
797dcf019af2e76a4c6e0391c3c5e1d50966367df8Brian Paul    * We'll negate the texel value and use KILP which kills if value
807dcf019af2e76a4c6e0391c3c5e1d50966367df8Brian Paul    * is negative.
817dcf019af2e76a4c6e0391c3c5e1d50966367df8Brian Paul    */
827dcf019af2e76a4c6e0391c3c5e1d50966367df8Brian Paul   for (i = 0; i < 32; i++) {
837dcf019af2e76a4c6e0391c3c5e1d50966367df8Brian Paul      for (j = 0; j < 32; j++) {
847dcf019af2e76a4c6e0391c3c5e1d50966367df8Brian Paul         if (pattern[i] & (bit31 >> j)) {
857dcf019af2e76a4c6e0391c3c5e1d50966367df8Brian Paul            /* fragment "on" */
867dcf019af2e76a4c6e0391c3c5e1d50966367df8Brian Paul            data[i * transfer->stride + j] = 0;
877dcf019af2e76a4c6e0391c3c5e1d50966367df8Brian Paul         }
887dcf019af2e76a4c6e0391c3c5e1d50966367df8Brian Paul         else {
897dcf019af2e76a4c6e0391c3c5e1d50966367df8Brian Paul            /* fragment "off" */
907dcf019af2e76a4c6e0391c3c5e1d50966367df8Brian Paul            data[i * transfer->stride + j] = 255;
917dcf019af2e76a4c6e0391c3c5e1d50966367df8Brian Paul         }
927dcf019af2e76a4c6e0391c3c5e1d50966367df8Brian Paul      }
937dcf019af2e76a4c6e0391c3c5e1d50966367df8Brian Paul   }
947dcf019af2e76a4c6e0391c3c5e1d50966367df8Brian Paul
957dcf019af2e76a4c6e0391c3c5e1d50966367df8Brian Paul   /* unmap */
967dcf019af2e76a4c6e0391c3c5e1d50966367df8Brian Paul   pipe->transfer_unmap(pipe, transfer);
977dcf019af2e76a4c6e0391c3c5e1d50966367df8Brian Paul   pipe->transfer_destroy(pipe, transfer);
987dcf019af2e76a4c6e0391c3c5e1d50966367df8Brian Paul}
997dcf019af2e76a4c6e0391c3c5e1d50966367df8Brian Paul
1007dcf019af2e76a4c6e0391c3c5e1d50966367df8Brian Paul
1017dcf019af2e76a4c6e0391c3c5e1d50966367df8Brian Paul/**
1027dcf019af2e76a4c6e0391c3c5e1d50966367df8Brian Paul * Create a 32x32 alpha8 texture that encodes the given stipple pattern.
1037dcf019af2e76a4c6e0391c3c5e1d50966367df8Brian Paul */
1047dcf019af2e76a4c6e0391c3c5e1d50966367df8Brian Paulstruct pipe_resource *
1057dcf019af2e76a4c6e0391c3c5e1d50966367df8Brian Paulutil_pstipple_create_stipple_texture(struct pipe_context *pipe,
1067dcf019af2e76a4c6e0391c3c5e1d50966367df8Brian Paul                                     const uint32_t pattern[32])
1077dcf019af2e76a4c6e0391c3c5e1d50966367df8Brian Paul{
1087dcf019af2e76a4c6e0391c3c5e1d50966367df8Brian Paul   struct pipe_screen *screen = pipe->screen;
1097dcf019af2e76a4c6e0391c3c5e1d50966367df8Brian Paul   struct pipe_resource templat, *tex;
1107dcf019af2e76a4c6e0391c3c5e1d50966367df8Brian Paul
1117dcf019af2e76a4c6e0391c3c5e1d50966367df8Brian Paul   memset(&templat, 0, sizeof(templat));
1127dcf019af2e76a4c6e0391c3c5e1d50966367df8Brian Paul   templat.target = PIPE_TEXTURE_2D;
1137dcf019af2e76a4c6e0391c3c5e1d50966367df8Brian Paul   templat.format = PIPE_FORMAT_A8_UNORM;
1147dcf019af2e76a4c6e0391c3c5e1d50966367df8Brian Paul   templat.last_level = 0;
1157dcf019af2e76a4c6e0391c3c5e1d50966367df8Brian Paul   templat.width0 = 32;
1167dcf019af2e76a4c6e0391c3c5e1d50966367df8Brian Paul   templat.height0 = 32;
1177dcf019af2e76a4c6e0391c3c5e1d50966367df8Brian Paul   templat.depth0 = 1;
1187dcf019af2e76a4c6e0391c3c5e1d50966367df8Brian Paul   templat.array_size = 1;
1197dcf019af2e76a4c6e0391c3c5e1d50966367df8Brian Paul   templat.bind = PIPE_BIND_SAMPLER_VIEW;
1207dcf019af2e76a4c6e0391c3c5e1d50966367df8Brian Paul
1217dcf019af2e76a4c6e0391c3c5e1d50966367df8Brian Paul   tex = screen->resource_create(screen, &templat);
1227dcf019af2e76a4c6e0391c3c5e1d50966367df8Brian Paul
1237dcf019af2e76a4c6e0391c3c5e1d50966367df8Brian Paul   if (tex)
1247dcf019af2e76a4c6e0391c3c5e1d50966367df8Brian Paul      util_pstipple_update_stipple_texture(pipe, tex, pattern);
1257dcf019af2e76a4c6e0391c3c5e1d50966367df8Brian Paul
1267dcf019af2e76a4c6e0391c3c5e1d50966367df8Brian Paul   return tex;
1277dcf019af2e76a4c6e0391c3c5e1d50966367df8Brian Paul}
1287dcf019af2e76a4c6e0391c3c5e1d50966367df8Brian Paul
1297dcf019af2e76a4c6e0391c3c5e1d50966367df8Brian Paul
1307dcf019af2e76a4c6e0391c3c5e1d50966367df8Brian Paul/**
1317dcf019af2e76a4c6e0391c3c5e1d50966367df8Brian Paul * Create sampler view to sample the stipple texture.
1327dcf019af2e76a4c6e0391c3c5e1d50966367df8Brian Paul */
1337dcf019af2e76a4c6e0391c3c5e1d50966367df8Brian Paulstruct pipe_sampler_view *
1347dcf019af2e76a4c6e0391c3c5e1d50966367df8Brian Paulutil_pstipple_create_sampler_view(struct pipe_context *pipe,
1357dcf019af2e76a4c6e0391c3c5e1d50966367df8Brian Paul                                  struct pipe_resource *tex)
1367dcf019af2e76a4c6e0391c3c5e1d50966367df8Brian Paul{
1377dcf019af2e76a4c6e0391c3c5e1d50966367df8Brian Paul   struct pipe_sampler_view templat, *sv;
1387dcf019af2e76a4c6e0391c3c5e1d50966367df8Brian Paul
1397dcf019af2e76a4c6e0391c3c5e1d50966367df8Brian Paul   u_sampler_view_default_template(&templat, tex, tex->format);
1407dcf019af2e76a4c6e0391c3c5e1d50966367df8Brian Paul   sv = pipe->create_sampler_view(pipe, tex, &templat);
1417dcf019af2e76a4c6e0391c3c5e1d50966367df8Brian Paul
1427dcf019af2e76a4c6e0391c3c5e1d50966367df8Brian Paul   return sv;
1437dcf019af2e76a4c6e0391c3c5e1d50966367df8Brian Paul}
1447dcf019af2e76a4c6e0391c3c5e1d50966367df8Brian Paul
1457dcf019af2e76a4c6e0391c3c5e1d50966367df8Brian Paul
1467dcf019af2e76a4c6e0391c3c5e1d50966367df8Brian Paul/**
1477dcf019af2e76a4c6e0391c3c5e1d50966367df8Brian Paul * Create the sampler CSO that'll be used for stippling.
1487dcf019af2e76a4c6e0391c3c5e1d50966367df8Brian Paul */
1497dcf019af2e76a4c6e0391c3c5e1d50966367df8Brian Paulvoid *
1507dcf019af2e76a4c6e0391c3c5e1d50966367df8Brian Paulutil_pstipple_create_sampler(struct pipe_context *pipe)
1517dcf019af2e76a4c6e0391c3c5e1d50966367df8Brian Paul{
1527dcf019af2e76a4c6e0391c3c5e1d50966367df8Brian Paul   struct pipe_sampler_state templat;
1537dcf019af2e76a4c6e0391c3c5e1d50966367df8Brian Paul   void *s;
1547dcf019af2e76a4c6e0391c3c5e1d50966367df8Brian Paul
1557dcf019af2e76a4c6e0391c3c5e1d50966367df8Brian Paul   memset(&templat, 0, sizeof(templat));
1567dcf019af2e76a4c6e0391c3c5e1d50966367df8Brian Paul   templat.wrap_s = PIPE_TEX_WRAP_REPEAT;
1577dcf019af2e76a4c6e0391c3c5e1d50966367df8Brian Paul   templat.wrap_t = PIPE_TEX_WRAP_REPEAT;
1587dcf019af2e76a4c6e0391c3c5e1d50966367df8Brian Paul   templat.wrap_r = PIPE_TEX_WRAP_REPEAT;
1597dcf019af2e76a4c6e0391c3c5e1d50966367df8Brian Paul   templat.min_mip_filter = PIPE_TEX_MIPFILTER_NONE;
1607dcf019af2e76a4c6e0391c3c5e1d50966367df8Brian Paul   templat.min_img_filter = PIPE_TEX_FILTER_NEAREST;
1617dcf019af2e76a4c6e0391c3c5e1d50966367df8Brian Paul   templat.mag_img_filter = PIPE_TEX_FILTER_NEAREST;
1627dcf019af2e76a4c6e0391c3c5e1d50966367df8Brian Paul   templat.normalized_coords = 1;
1637dcf019af2e76a4c6e0391c3c5e1d50966367df8Brian Paul   templat.min_lod = 0.0f;
1647dcf019af2e76a4c6e0391c3c5e1d50966367df8Brian Paul   templat.max_lod = 0.0f;
1657dcf019af2e76a4c6e0391c3c5e1d50966367df8Brian Paul
1667dcf019af2e76a4c6e0391c3c5e1d50966367df8Brian Paul   s = pipe->create_sampler_state(pipe, &templat);
1677dcf019af2e76a4c6e0391c3c5e1d50966367df8Brian Paul   return s;
1687dcf019af2e76a4c6e0391c3c5e1d50966367df8Brian Paul}
1697dcf019af2e76a4c6e0391c3c5e1d50966367df8Brian Paul
1707dcf019af2e76a4c6e0391c3c5e1d50966367df8Brian Paul
1717dcf019af2e76a4c6e0391c3c5e1d50966367df8Brian Paul
1727dcf019af2e76a4c6e0391c3c5e1d50966367df8Brian Paul/**
1737dcf019af2e76a4c6e0391c3c5e1d50966367df8Brian Paul * Subclass of tgsi_transform_context, used for transforming the
1747dcf019af2e76a4c6e0391c3c5e1d50966367df8Brian Paul * user's fragment shader to add the extra texture sample and fragment kill
1757dcf019af2e76a4c6e0391c3c5e1d50966367df8Brian Paul * instructions.
1767dcf019af2e76a4c6e0391c3c5e1d50966367df8Brian Paul */
1777dcf019af2e76a4c6e0391c3c5e1d50966367df8Brian Paulstruct pstip_transform_context {
1787dcf019af2e76a4c6e0391c3c5e1d50966367df8Brian Paul   struct tgsi_transform_context base;
1793dde6be908d827f4d6d54e0968ae83c2c4dfa87cBrian Paul   struct tgsi_shader_info info;
1807dcf019af2e76a4c6e0391c3c5e1d50966367df8Brian Paul   uint tempsUsed;  /**< bitmask */
1817dcf019af2e76a4c6e0391c3c5e1d50966367df8Brian Paul   int wincoordInput;
1827dcf019af2e76a4c6e0391c3c5e1d50966367df8Brian Paul   int maxInput;
1837dcf019af2e76a4c6e0391c3c5e1d50966367df8Brian Paul   uint samplersUsed;  /**< bitfield of samplers used */
1847dcf019af2e76a4c6e0391c3c5e1d50966367df8Brian Paul   int freeSampler;  /** an available sampler for the pstipple */
1857dcf019af2e76a4c6e0391c3c5e1d50966367df8Brian Paul   int texTemp;  /**< temp registers */
1867dcf019af2e76a4c6e0391c3c5e1d50966367df8Brian Paul   int numImmed;
1877dcf019af2e76a4c6e0391c3c5e1d50966367df8Brian Paul   boolean firstInstruction;
1883dde6be908d827f4d6d54e0968ae83c2c4dfa87cBrian Paul   uint coordOrigin;
1897dcf019af2e76a4c6e0391c3c5e1d50966367df8Brian Paul};
1907dcf019af2e76a4c6e0391c3c5e1d50966367df8Brian Paul
1917dcf019af2e76a4c6e0391c3c5e1d50966367df8Brian Paul
1927dcf019af2e76a4c6e0391c3c5e1d50966367df8Brian Paul/**
1937dcf019af2e76a4c6e0391c3c5e1d50966367df8Brian Paul * TGSI declaration transform callback.
1943dde6be908d827f4d6d54e0968ae83c2c4dfa87cBrian Paul * Track samplers used, temps used, inputs used.
1957dcf019af2e76a4c6e0391c3c5e1d50966367df8Brian Paul */
1967dcf019af2e76a4c6e0391c3c5e1d50966367df8Brian Paulstatic void
1977dcf019af2e76a4c6e0391c3c5e1d50966367df8Brian Paulpstip_transform_decl(struct tgsi_transform_context *ctx,
1987dcf019af2e76a4c6e0391c3c5e1d50966367df8Brian Paul                     struct tgsi_full_declaration *decl)
1997dcf019af2e76a4c6e0391c3c5e1d50966367df8Brian Paul{
2007dcf019af2e76a4c6e0391c3c5e1d50966367df8Brian Paul   struct pstip_transform_context *pctx =
2017dcf019af2e76a4c6e0391c3c5e1d50966367df8Brian Paul      (struct pstip_transform_context *) ctx;
2027dcf019af2e76a4c6e0391c3c5e1d50966367df8Brian Paul
2033dde6be908d827f4d6d54e0968ae83c2c4dfa87cBrian Paul   /* XXX we can use tgsi_shader_info instead of some of this */
2043dde6be908d827f4d6d54e0968ae83c2c4dfa87cBrian Paul
2057dcf019af2e76a4c6e0391c3c5e1d50966367df8Brian Paul   if (decl->Declaration.File == TGSI_FILE_SAMPLER) {
2067dcf019af2e76a4c6e0391c3c5e1d50966367df8Brian Paul      uint i;
2073dde6be908d827f4d6d54e0968ae83c2c4dfa87cBrian Paul      for (i = decl->Range.First; i <= decl->Range.Last; i++) {
2087dcf019af2e76a4c6e0391c3c5e1d50966367df8Brian Paul         pctx->samplersUsed |= 1 << i;
2097dcf019af2e76a4c6e0391c3c5e1d50966367df8Brian Paul      }
2107dcf019af2e76a4c6e0391c3c5e1d50966367df8Brian Paul   }
2117dcf019af2e76a4c6e0391c3c5e1d50966367df8Brian Paul   else if (decl->Declaration.File == TGSI_FILE_INPUT) {
2127dcf019af2e76a4c6e0391c3c5e1d50966367df8Brian Paul      pctx->maxInput = MAX2(pctx->maxInput, (int) decl->Range.Last);
2137dcf019af2e76a4c6e0391c3c5e1d50966367df8Brian Paul      if (decl->Semantic.Name == TGSI_SEMANTIC_POSITION)
2147dcf019af2e76a4c6e0391c3c5e1d50966367df8Brian Paul         pctx->wincoordInput = (int) decl->Range.First;
2157dcf019af2e76a4c6e0391c3c5e1d50966367df8Brian Paul   }
2167dcf019af2e76a4c6e0391c3c5e1d50966367df8Brian Paul   else if (decl->Declaration.File == TGSI_FILE_TEMPORARY) {
2177dcf019af2e76a4c6e0391c3c5e1d50966367df8Brian Paul      uint i;
2183dde6be908d827f4d6d54e0968ae83c2c4dfa87cBrian Paul      for (i = decl->Range.First; i <= decl->Range.Last; i++) {
2197dcf019af2e76a4c6e0391c3c5e1d50966367df8Brian Paul         pctx->tempsUsed |= (1 << i);
2207dcf019af2e76a4c6e0391c3c5e1d50966367df8Brian Paul      }
2217dcf019af2e76a4c6e0391c3c5e1d50966367df8Brian Paul   }
2227dcf019af2e76a4c6e0391c3c5e1d50966367df8Brian Paul
2237dcf019af2e76a4c6e0391c3c5e1d50966367df8Brian Paul   ctx->emit_declaration(ctx, decl);
2247dcf019af2e76a4c6e0391c3c5e1d50966367df8Brian Paul}
2257dcf019af2e76a4c6e0391c3c5e1d50966367df8Brian Paul
2267dcf019af2e76a4c6e0391c3c5e1d50966367df8Brian Paul
2277dcf019af2e76a4c6e0391c3c5e1d50966367df8Brian Paulstatic void
2287dcf019af2e76a4c6e0391c3c5e1d50966367df8Brian Paulpstip_transform_immed(struct tgsi_transform_context *ctx,
2297dcf019af2e76a4c6e0391c3c5e1d50966367df8Brian Paul                      struct tgsi_full_immediate *immed)
2307dcf019af2e76a4c6e0391c3c5e1d50966367df8Brian Paul{
2317dcf019af2e76a4c6e0391c3c5e1d50966367df8Brian Paul   struct pstip_transform_context *pctx =
2327dcf019af2e76a4c6e0391c3c5e1d50966367df8Brian Paul      (struct pstip_transform_context *) ctx;
2337dcf019af2e76a4c6e0391c3c5e1d50966367df8Brian Paul   pctx->numImmed++;
2347dcf019af2e76a4c6e0391c3c5e1d50966367df8Brian Paul}
2357dcf019af2e76a4c6e0391c3c5e1d50966367df8Brian Paul
2367dcf019af2e76a4c6e0391c3c5e1d50966367df8Brian Paul
2377dcf019af2e76a4c6e0391c3c5e1d50966367df8Brian Paul/**
2387dcf019af2e76a4c6e0391c3c5e1d50966367df8Brian Paul * Find the lowest zero bit in the given word, or -1 if bitfield is all ones.
2397dcf019af2e76a4c6e0391c3c5e1d50966367df8Brian Paul */
2407dcf019af2e76a4c6e0391c3c5e1d50966367df8Brian Paulstatic int
2417dcf019af2e76a4c6e0391c3c5e1d50966367df8Brian Paulfree_bit(uint bitfield)
2427dcf019af2e76a4c6e0391c3c5e1d50966367df8Brian Paul{
2437dcf019af2e76a4c6e0391c3c5e1d50966367df8Brian Paul   return ffs(~bitfield) - 1;
2447dcf019af2e76a4c6e0391c3c5e1d50966367df8Brian Paul}
2457dcf019af2e76a4c6e0391c3c5e1d50966367df8Brian Paul
2467dcf019af2e76a4c6e0391c3c5e1d50966367df8Brian Paul
2477dcf019af2e76a4c6e0391c3c5e1d50966367df8Brian Paul/**
2487dcf019af2e76a4c6e0391c3c5e1d50966367df8Brian Paul * TGSI instruction transform callback.
2493dde6be908d827f4d6d54e0968ae83c2c4dfa87cBrian Paul * Before the first instruction, insert our new code to sample the
2503dde6be908d827f4d6d54e0968ae83c2c4dfa87cBrian Paul * stipple texture (using the fragment coord register) then kill the
2513dde6be908d827f4d6d54e0968ae83c2c4dfa87cBrian Paul * fragment if the stipple texture bit is off.
2523dde6be908d827f4d6d54e0968ae83c2c4dfa87cBrian Paul *
2533dde6be908d827f4d6d54e0968ae83c2c4dfa87cBrian Paul * Insert:
2543dde6be908d827f4d6d54e0968ae83c2c4dfa87cBrian Paul *   declare new registers
2553dde6be908d827f4d6d54e0968ae83c2c4dfa87cBrian Paul *   MUL texTemp, INPUT[wincoord], 1/32;
2563dde6be908d827f4d6d54e0968ae83c2c4dfa87cBrian Paul *   TEX texTemp, texTemp, sampler;
2573dde6be908d827f4d6d54e0968ae83c2c4dfa87cBrian Paul *   KIL -texTemp;   # if -texTemp < 0, KILL fragment
2583dde6be908d827f4d6d54e0968ae83c2c4dfa87cBrian Paul *   [...original code...]
2597dcf019af2e76a4c6e0391c3c5e1d50966367df8Brian Paul */
2607dcf019af2e76a4c6e0391c3c5e1d50966367df8Brian Paulstatic void
2617dcf019af2e76a4c6e0391c3c5e1d50966367df8Brian Paulpstip_transform_inst(struct tgsi_transform_context *ctx,
2627dcf019af2e76a4c6e0391c3c5e1d50966367df8Brian Paul                     struct tgsi_full_instruction *inst)
2637dcf019af2e76a4c6e0391c3c5e1d50966367df8Brian Paul{
2647dcf019af2e76a4c6e0391c3c5e1d50966367df8Brian Paul   struct pstip_transform_context *pctx =
2657dcf019af2e76a4c6e0391c3c5e1d50966367df8Brian Paul      (struct pstip_transform_context *) ctx;
2667dcf019af2e76a4c6e0391c3c5e1d50966367df8Brian Paul
2677dcf019af2e76a4c6e0391c3c5e1d50966367df8Brian Paul   if (pctx->firstInstruction) {
2687dcf019af2e76a4c6e0391c3c5e1d50966367df8Brian Paul      /* emit our new declarations before the first instruction */
2697dcf019af2e76a4c6e0391c3c5e1d50966367df8Brian Paul
2707dcf019af2e76a4c6e0391c3c5e1d50966367df8Brian Paul      struct tgsi_full_declaration decl;
2717dcf019af2e76a4c6e0391c3c5e1d50966367df8Brian Paul      struct tgsi_full_instruction newInst;
2727dcf019af2e76a4c6e0391c3c5e1d50966367df8Brian Paul      uint i;
2737dcf019af2e76a4c6e0391c3c5e1d50966367df8Brian Paul      int wincoordInput;
2747dcf019af2e76a4c6e0391c3c5e1d50966367df8Brian Paul
2753dde6be908d827f4d6d54e0968ae83c2c4dfa87cBrian Paul      /* find free texture sampler */
2767dcf019af2e76a4c6e0391c3c5e1d50966367df8Brian Paul      pctx->freeSampler = free_bit(pctx->samplersUsed);
2777dcf019af2e76a4c6e0391c3c5e1d50966367df8Brian Paul      if (pctx->freeSampler >= PIPE_MAX_SAMPLERS)
2787dcf019af2e76a4c6e0391c3c5e1d50966367df8Brian Paul         pctx->freeSampler = PIPE_MAX_SAMPLERS - 1;
2797dcf019af2e76a4c6e0391c3c5e1d50966367df8Brian Paul
2807dcf019af2e76a4c6e0391c3c5e1d50966367df8Brian Paul      if (pctx->wincoordInput < 0)
2817dcf019af2e76a4c6e0391c3c5e1d50966367df8Brian Paul         wincoordInput = pctx->maxInput + 1;
2827dcf019af2e76a4c6e0391c3c5e1d50966367df8Brian Paul      else
2837dcf019af2e76a4c6e0391c3c5e1d50966367df8Brian Paul         wincoordInput = pctx->wincoordInput;
2847dcf019af2e76a4c6e0391c3c5e1d50966367df8Brian Paul
2853dde6be908d827f4d6d54e0968ae83c2c4dfa87cBrian Paul      /* find one free temp register */
2867dcf019af2e76a4c6e0391c3c5e1d50966367df8Brian Paul      for (i = 0; i < 32; i++) {
2877dcf019af2e76a4c6e0391c3c5e1d50966367df8Brian Paul         if ((pctx->tempsUsed & (1 << i)) == 0) {
2887dcf019af2e76a4c6e0391c3c5e1d50966367df8Brian Paul            /* found a free temp */
2897dcf019af2e76a4c6e0391c3c5e1d50966367df8Brian Paul            if (pctx->texTemp < 0)
2907dcf019af2e76a4c6e0391c3c5e1d50966367df8Brian Paul               pctx->texTemp  = i;
2917dcf019af2e76a4c6e0391c3c5e1d50966367df8Brian Paul            else
2927dcf019af2e76a4c6e0391c3c5e1d50966367df8Brian Paul               break;
2937dcf019af2e76a4c6e0391c3c5e1d50966367df8Brian Paul         }
2947dcf019af2e76a4c6e0391c3c5e1d50966367df8Brian Paul      }
2957dcf019af2e76a4c6e0391c3c5e1d50966367df8Brian Paul      assert(pctx->texTemp >= 0);
2967dcf019af2e76a4c6e0391c3c5e1d50966367df8Brian Paul
2977dcf019af2e76a4c6e0391c3c5e1d50966367df8Brian Paul      if (pctx->wincoordInput < 0) {
2987dcf019af2e76a4c6e0391c3c5e1d50966367df8Brian Paul         /* declare new position input reg */
2997dcf019af2e76a4c6e0391c3c5e1d50966367df8Brian Paul         decl = tgsi_default_full_declaration();
3007dcf019af2e76a4c6e0391c3c5e1d50966367df8Brian Paul         decl.Declaration.File = TGSI_FILE_INPUT;
3011279923d72942ee201fcc6ad40d552143f651f03Francisco Jerez         decl.Declaration.Interpolate = 1;
3027dcf019af2e76a4c6e0391c3c5e1d50966367df8Brian Paul         decl.Declaration.Semantic = 1;
3037dcf019af2e76a4c6e0391c3c5e1d50966367df8Brian Paul         decl.Semantic.Name = TGSI_SEMANTIC_POSITION;
3047dcf019af2e76a4c6e0391c3c5e1d50966367df8Brian Paul         decl.Semantic.Index = 0;
3057dcf019af2e76a4c6e0391c3c5e1d50966367df8Brian Paul         decl.Range.First =
3067dcf019af2e76a4c6e0391c3c5e1d50966367df8Brian Paul            decl.Range.Last = wincoordInput;
3071279923d72942ee201fcc6ad40d552143f651f03Francisco Jerez         decl.Interp.Interpolate = TGSI_INTERPOLATE_LINEAR;
3087dcf019af2e76a4c6e0391c3c5e1d50966367df8Brian Paul         ctx->emit_declaration(ctx, &decl);
3097dcf019af2e76a4c6e0391c3c5e1d50966367df8Brian Paul      }
3107dcf019af2e76a4c6e0391c3c5e1d50966367df8Brian Paul
3117dcf019af2e76a4c6e0391c3c5e1d50966367df8Brian Paul      /* declare new sampler */
3127dcf019af2e76a4c6e0391c3c5e1d50966367df8Brian Paul      decl = tgsi_default_full_declaration();
3137dcf019af2e76a4c6e0391c3c5e1d50966367df8Brian Paul      decl.Declaration.File = TGSI_FILE_SAMPLER;
3147dcf019af2e76a4c6e0391c3c5e1d50966367df8Brian Paul      decl.Range.First =
3157dcf019af2e76a4c6e0391c3c5e1d50966367df8Brian Paul      decl.Range.Last = pctx->freeSampler;
3167dcf019af2e76a4c6e0391c3c5e1d50966367df8Brian Paul      ctx->emit_declaration(ctx, &decl);
3177dcf019af2e76a4c6e0391c3c5e1d50966367df8Brian Paul
3187dcf019af2e76a4c6e0391c3c5e1d50966367df8Brian Paul      /* declare new temp regs */
3197dcf019af2e76a4c6e0391c3c5e1d50966367df8Brian Paul      decl = tgsi_default_full_declaration();
3207dcf019af2e76a4c6e0391c3c5e1d50966367df8Brian Paul      decl.Declaration.File = TGSI_FILE_TEMPORARY;
3217dcf019af2e76a4c6e0391c3c5e1d50966367df8Brian Paul      decl.Range.First =
3227dcf019af2e76a4c6e0391c3c5e1d50966367df8Brian Paul      decl.Range.Last = pctx->texTemp;
3237dcf019af2e76a4c6e0391c3c5e1d50966367df8Brian Paul      ctx->emit_declaration(ctx, &decl);
3247dcf019af2e76a4c6e0391c3c5e1d50966367df8Brian Paul
3257dcf019af2e76a4c6e0391c3c5e1d50966367df8Brian Paul      /* emit immediate = {1/32, 1/32, 1, 1}
3267dcf019af2e76a4c6e0391c3c5e1d50966367df8Brian Paul       * The index/position of this immediate will be pctx->numImmed
3277dcf019af2e76a4c6e0391c3c5e1d50966367df8Brian Paul       */
3287dcf019af2e76a4c6e0391c3c5e1d50966367df8Brian Paul      {
3297dcf019af2e76a4c6e0391c3c5e1d50966367df8Brian Paul         static const float value[4] = { 1.0/32, 1.0/32, 1.0, 1.0 };
3307dcf019af2e76a4c6e0391c3c5e1d50966367df8Brian Paul         struct tgsi_full_immediate immed;
3317dcf019af2e76a4c6e0391c3c5e1d50966367df8Brian Paul         uint size = 4;
3327dcf019af2e76a4c6e0391c3c5e1d50966367df8Brian Paul         immed = tgsi_default_full_immediate();
3337dcf019af2e76a4c6e0391c3c5e1d50966367df8Brian Paul         immed.Immediate.NrTokens = 1 + size; /* one for the token itself */
3347dcf019af2e76a4c6e0391c3c5e1d50966367df8Brian Paul         immed.u[0].Float = value[0];
3357dcf019af2e76a4c6e0391c3c5e1d50966367df8Brian Paul         immed.u[1].Float = value[1];
3367dcf019af2e76a4c6e0391c3c5e1d50966367df8Brian Paul         immed.u[2].Float = value[2];
3377dcf019af2e76a4c6e0391c3c5e1d50966367df8Brian Paul         immed.u[3].Float = value[3];
3387dcf019af2e76a4c6e0391c3c5e1d50966367df8Brian Paul         ctx->emit_immediate(ctx, &immed);
3397dcf019af2e76a4c6e0391c3c5e1d50966367df8Brian Paul      }
3407dcf019af2e76a4c6e0391c3c5e1d50966367df8Brian Paul
3417dcf019af2e76a4c6e0391c3c5e1d50966367df8Brian Paul      pctx->firstInstruction = FALSE;
3427dcf019af2e76a4c6e0391c3c5e1d50966367df8Brian Paul
3437dcf019af2e76a4c6e0391c3c5e1d50966367df8Brian Paul
3447dcf019af2e76a4c6e0391c3c5e1d50966367df8Brian Paul      /*
3457dcf019af2e76a4c6e0391c3c5e1d50966367df8Brian Paul       * Insert new MUL/TEX/KILP instructions at start of program
3467dcf019af2e76a4c6e0391c3c5e1d50966367df8Brian Paul       * Take gl_FragCoord, divide by 32 (stipple size), sample the
3477dcf019af2e76a4c6e0391c3c5e1d50966367df8Brian Paul       * texture and kill fragment if needed.
3487dcf019af2e76a4c6e0391c3c5e1d50966367df8Brian Paul       *
3497dcf019af2e76a4c6e0391c3c5e1d50966367df8Brian Paul       * We'd like to use non-normalized texcoords to index into a RECT
3507dcf019af2e76a4c6e0391c3c5e1d50966367df8Brian Paul       * texture, but we can only use REPEAT wrap mode with normalized
3517dcf019af2e76a4c6e0391c3c5e1d50966367df8Brian Paul       * texcoords.  Darn.
3527dcf019af2e76a4c6e0391c3c5e1d50966367df8Brian Paul       */
3537dcf019af2e76a4c6e0391c3c5e1d50966367df8Brian Paul
3547dcf019af2e76a4c6e0391c3c5e1d50966367df8Brian Paul      /* XXX invert wincoord if origin isn't lower-left... */
3557dcf019af2e76a4c6e0391c3c5e1d50966367df8Brian Paul
3567dcf019af2e76a4c6e0391c3c5e1d50966367df8Brian Paul      /* MUL texTemp, INPUT[wincoord], 1/32; */
3577dcf019af2e76a4c6e0391c3c5e1d50966367df8Brian Paul      newInst = tgsi_default_full_instruction();
3587dcf019af2e76a4c6e0391c3c5e1d50966367df8Brian Paul      newInst.Instruction.Opcode = TGSI_OPCODE_MUL;
3597dcf019af2e76a4c6e0391c3c5e1d50966367df8Brian Paul      newInst.Instruction.NumDstRegs = 1;
3607dcf019af2e76a4c6e0391c3c5e1d50966367df8Brian Paul      newInst.Dst[0].Register.File = TGSI_FILE_TEMPORARY;
3617dcf019af2e76a4c6e0391c3c5e1d50966367df8Brian Paul      newInst.Dst[0].Register.Index = pctx->texTemp;
3627dcf019af2e76a4c6e0391c3c5e1d50966367df8Brian Paul      newInst.Instruction.NumSrcRegs = 2;
3637dcf019af2e76a4c6e0391c3c5e1d50966367df8Brian Paul      newInst.Src[0].Register.File = TGSI_FILE_INPUT;
3647dcf019af2e76a4c6e0391c3c5e1d50966367df8Brian Paul      newInst.Src[0].Register.Index = wincoordInput;
3657dcf019af2e76a4c6e0391c3c5e1d50966367df8Brian Paul      newInst.Src[1].Register.File = TGSI_FILE_IMMEDIATE;
3667dcf019af2e76a4c6e0391c3c5e1d50966367df8Brian Paul      newInst.Src[1].Register.Index = pctx->numImmed;
3677dcf019af2e76a4c6e0391c3c5e1d50966367df8Brian Paul      ctx->emit_instruction(ctx, &newInst);
3687dcf019af2e76a4c6e0391c3c5e1d50966367df8Brian Paul
3697dcf019af2e76a4c6e0391c3c5e1d50966367df8Brian Paul      /* TEX texTemp, texTemp, sampler; */
3707dcf019af2e76a4c6e0391c3c5e1d50966367df8Brian Paul      newInst = tgsi_default_full_instruction();
3717dcf019af2e76a4c6e0391c3c5e1d50966367df8Brian Paul      newInst.Instruction.Opcode = TGSI_OPCODE_TEX;
3727dcf019af2e76a4c6e0391c3c5e1d50966367df8Brian Paul      newInst.Instruction.NumDstRegs = 1;
3737dcf019af2e76a4c6e0391c3c5e1d50966367df8Brian Paul      newInst.Dst[0].Register.File = TGSI_FILE_TEMPORARY;
3747dcf019af2e76a4c6e0391c3c5e1d50966367df8Brian Paul      newInst.Dst[0].Register.Index = pctx->texTemp;
3757dcf019af2e76a4c6e0391c3c5e1d50966367df8Brian Paul      newInst.Instruction.NumSrcRegs = 2;
3767dcf019af2e76a4c6e0391c3c5e1d50966367df8Brian Paul      newInst.Instruction.Texture = TRUE;
3777dcf019af2e76a4c6e0391c3c5e1d50966367df8Brian Paul      newInst.Texture.Texture = TGSI_TEXTURE_2D;
3787dcf019af2e76a4c6e0391c3c5e1d50966367df8Brian Paul      newInst.Src[0].Register.File = TGSI_FILE_TEMPORARY;
3797dcf019af2e76a4c6e0391c3c5e1d50966367df8Brian Paul      newInst.Src[0].Register.Index = pctx->texTemp;
3807dcf019af2e76a4c6e0391c3c5e1d50966367df8Brian Paul      newInst.Src[1].Register.File = TGSI_FILE_SAMPLER;
3817dcf019af2e76a4c6e0391c3c5e1d50966367df8Brian Paul      newInst.Src[1].Register.Index = pctx->freeSampler;
3827dcf019af2e76a4c6e0391c3c5e1d50966367df8Brian Paul      ctx->emit_instruction(ctx, &newInst);
3837dcf019af2e76a4c6e0391c3c5e1d50966367df8Brian Paul
3847dcf019af2e76a4c6e0391c3c5e1d50966367df8Brian Paul      /* KIL -texTemp;   # if -texTemp < 0, KILL fragment */
3857dcf019af2e76a4c6e0391c3c5e1d50966367df8Brian Paul      newInst = tgsi_default_full_instruction();
3867dcf019af2e76a4c6e0391c3c5e1d50966367df8Brian Paul      newInst.Instruction.Opcode = TGSI_OPCODE_KIL;
3877dcf019af2e76a4c6e0391c3c5e1d50966367df8Brian Paul      newInst.Instruction.NumDstRegs = 0;
3887dcf019af2e76a4c6e0391c3c5e1d50966367df8Brian Paul      newInst.Instruction.NumSrcRegs = 1;
3897dcf019af2e76a4c6e0391c3c5e1d50966367df8Brian Paul      newInst.Src[0].Register.File = TGSI_FILE_TEMPORARY;
3907dcf019af2e76a4c6e0391c3c5e1d50966367df8Brian Paul      newInst.Src[0].Register.Index = pctx->texTemp;
3917dcf019af2e76a4c6e0391c3c5e1d50966367df8Brian Paul      newInst.Src[0].Register.Negate = 1;
3927dcf019af2e76a4c6e0391c3c5e1d50966367df8Brian Paul      ctx->emit_instruction(ctx, &newInst);
3937dcf019af2e76a4c6e0391c3c5e1d50966367df8Brian Paul   }
3947dcf019af2e76a4c6e0391c3c5e1d50966367df8Brian Paul
3957dcf019af2e76a4c6e0391c3c5e1d50966367df8Brian Paul   /* emit this instruction */
3967dcf019af2e76a4c6e0391c3c5e1d50966367df8Brian Paul   ctx->emit_instruction(ctx, inst);
3977dcf019af2e76a4c6e0391c3c5e1d50966367df8Brian Paul}
3987dcf019af2e76a4c6e0391c3c5e1d50966367df8Brian Paul
3997dcf019af2e76a4c6e0391c3c5e1d50966367df8Brian Paul
4007dcf019af2e76a4c6e0391c3c5e1d50966367df8Brian Paul/**
4017dcf019af2e76a4c6e0391c3c5e1d50966367df8Brian Paul * Given a fragment shader, return a new fragment shader which
4027dcf019af2e76a4c6e0391c3c5e1d50966367df8Brian Paul * samples a stipple texture and executes KILL.
4037dcf019af2e76a4c6e0391c3c5e1d50966367df8Brian Paul */
4047dcf019af2e76a4c6e0391c3c5e1d50966367df8Brian Paulstruct pipe_shader_state *
4057dcf019af2e76a4c6e0391c3c5e1d50966367df8Brian Paulutil_pstipple_create_fragment_shader(struct pipe_context *pipe,
4067dcf019af2e76a4c6e0391c3c5e1d50966367df8Brian Paul                                     struct pipe_shader_state *fs,
4077dcf019af2e76a4c6e0391c3c5e1d50966367df8Brian Paul                                     unsigned *samplerUnitOut)
4087dcf019af2e76a4c6e0391c3c5e1d50966367df8Brian Paul{
4097dcf019af2e76a4c6e0391c3c5e1d50966367df8Brian Paul   struct pipe_shader_state *new_fs;
4107dcf019af2e76a4c6e0391c3c5e1d50966367df8Brian Paul   struct pstip_transform_context transform;
4117dcf019af2e76a4c6e0391c3c5e1d50966367df8Brian Paul   const uint newLen = tgsi_num_tokens(fs->tokens) + NUM_NEW_TOKENS;
4123dde6be908d827f4d6d54e0968ae83c2c4dfa87cBrian Paul   unsigned i;
4137dcf019af2e76a4c6e0391c3c5e1d50966367df8Brian Paul
4147dcf019af2e76a4c6e0391c3c5e1d50966367df8Brian Paul   new_fs = MALLOC(sizeof(*new_fs));
4157dcf019af2e76a4c6e0391c3c5e1d50966367df8Brian Paul   if (!new_fs)
4167dcf019af2e76a4c6e0391c3c5e1d50966367df8Brian Paul      return NULL;
4177dcf019af2e76a4c6e0391c3c5e1d50966367df8Brian Paul
4187dcf019af2e76a4c6e0391c3c5e1d50966367df8Brian Paul   new_fs->tokens = tgsi_alloc_tokens(newLen);
4197dcf019af2e76a4c6e0391c3c5e1d50966367df8Brian Paul   if (!new_fs->tokens) {
4207dcf019af2e76a4c6e0391c3c5e1d50966367df8Brian Paul      FREE(new_fs);
4217dcf019af2e76a4c6e0391c3c5e1d50966367df8Brian Paul      return NULL;
4227dcf019af2e76a4c6e0391c3c5e1d50966367df8Brian Paul   }
4237dcf019af2e76a4c6e0391c3c5e1d50966367df8Brian Paul
4243dde6be908d827f4d6d54e0968ae83c2c4dfa87cBrian Paul   /* Setup shader transformation info/context.
4253dde6be908d827f4d6d54e0968ae83c2c4dfa87cBrian Paul    */
4267dcf019af2e76a4c6e0391c3c5e1d50966367df8Brian Paul   memset(&transform, 0, sizeof(transform));
4277dcf019af2e76a4c6e0391c3c5e1d50966367df8Brian Paul   transform.wincoordInput = -1;
4287dcf019af2e76a4c6e0391c3c5e1d50966367df8Brian Paul   transform.maxInput = -1;
4297dcf019af2e76a4c6e0391c3c5e1d50966367df8Brian Paul   transform.texTemp = -1;
4307dcf019af2e76a4c6e0391c3c5e1d50966367df8Brian Paul   transform.firstInstruction = TRUE;
4313dde6be908d827f4d6d54e0968ae83c2c4dfa87cBrian Paul   transform.coordOrigin = TGSI_FS_COORD_ORIGIN_UPPER_LEFT;
4327dcf019af2e76a4c6e0391c3c5e1d50966367df8Brian Paul   transform.base.transform_instruction = pstip_transform_inst;
4337dcf019af2e76a4c6e0391c3c5e1d50966367df8Brian Paul   transform.base.transform_declaration = pstip_transform_decl;
4347dcf019af2e76a4c6e0391c3c5e1d50966367df8Brian Paul   transform.base.transform_immediate = pstip_transform_immed;
4357dcf019af2e76a4c6e0391c3c5e1d50966367df8Brian Paul
4363dde6be908d827f4d6d54e0968ae83c2c4dfa87cBrian Paul   tgsi_scan_shader(fs->tokens, &transform.info);
4373dde6be908d827f4d6d54e0968ae83c2c4dfa87cBrian Paul
4383dde6be908d827f4d6d54e0968ae83c2c4dfa87cBrian Paul   /* find fragment coordinate origin property */
4393dde6be908d827f4d6d54e0968ae83c2c4dfa87cBrian Paul   for (i = 0; i < transform.info.num_properties; i++) {
4403dde6be908d827f4d6d54e0968ae83c2c4dfa87cBrian Paul      if (transform.info.properties[i].name == TGSI_PROPERTY_FS_COORD_ORIGIN)
4413dde6be908d827f4d6d54e0968ae83c2c4dfa87cBrian Paul         transform.coordOrigin = transform.info.properties[i].data[0];
4423dde6be908d827f4d6d54e0968ae83c2c4dfa87cBrian Paul   }
4433dde6be908d827f4d6d54e0968ae83c2c4dfa87cBrian Paul
4447dcf019af2e76a4c6e0391c3c5e1d50966367df8Brian Paul   tgsi_transform_shader(fs->tokens,
4457dcf019af2e76a4c6e0391c3c5e1d50966367df8Brian Paul                         (struct tgsi_token *) new_fs->tokens,
4467dcf019af2e76a4c6e0391c3c5e1d50966367df8Brian Paul                         newLen, &transform.base);
4477dcf019af2e76a4c6e0391c3c5e1d50966367df8Brian Paul
4487dcf019af2e76a4c6e0391c3c5e1d50966367df8Brian Paul#if 0 /* DEBUG */
4497dcf019af2e76a4c6e0391c3c5e1d50966367df8Brian Paul   tgsi_dump(fs->tokens, 0);
4503dde6be908d827f4d6d54e0968ae83c2c4dfa87cBrian Paul   tgsi_dump(new_fs->tokens, 0);
4517dcf019af2e76a4c6e0391c3c5e1d50966367df8Brian Paul#endif
4527dcf019af2e76a4c6e0391c3c5e1d50966367df8Brian Paul
4537dcf019af2e76a4c6e0391c3c5e1d50966367df8Brian Paul   assert(transform.freeSampler < PIPE_MAX_SAMPLERS);
4547dcf019af2e76a4c6e0391c3c5e1d50966367df8Brian Paul   *samplerUnitOut = transform.freeSampler;
4557dcf019af2e76a4c6e0391c3c5e1d50966367df8Brian Paul
4567dcf019af2e76a4c6e0391c3c5e1d50966367df8Brian Paul   return new_fs;
4577dcf019af2e76a4c6e0391c3c5e1d50966367df8Brian Paul}
4587dcf019af2e76a4c6e0391c3c5e1d50966367df8Brian Paul
459