Home | History | Annotate | Download | only in tgsi
      1 /**************************************************************************
      2  *
      3  * Copyright 2008 VMware, Inc.
      4  * All Rights Reserved.
      5  *
      6  * Permission is hereby granted, free of charge, to any person obtaining a
      7  * copy of this software and associated documentation files (the
      8  * "Software"), to deal in the Software without restriction, including
      9  * without limitation the rights to use, copy, modify, merge, publish,
     10  * distribute, sub license, and/or sell copies of the Software, and to
     11  * permit persons to whom the Software is furnished to do so, subject to
     12  * the following conditions:
     13  *
     14  * The above copyright notice and this permission notice (including the
     15  * next paragraph) shall be included in all copies or substantial portions
     16  * of the Software.
     17  *
     18  * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
     19  * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
     20  * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT.
     21  * IN NO EVENT SHALL VMWARE AND/OR ITS SUPPLIERS BE LIABLE FOR
     22  * ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
     23  * TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
     24  * SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
     25  *
     26  **************************************************************************/
     27 
     28 /**
     29  * TGSI program transformation utility.
     30  *
     31  * Authors:  Brian Paul
     32  */
     33 
     34 #include "util/u_debug.h"
     35 
     36 #include "tgsi_transform.h"
     37 
     38 
     39 
     40 static void
     41 emit_instruction(struct tgsi_transform_context *ctx,
     42                  const struct tgsi_full_instruction *inst)
     43 {
     44    uint ti = ctx->ti;
     45 
     46    ti += tgsi_build_full_instruction(inst,
     47                                      ctx->tokens_out + ti,
     48                                      ctx->header,
     49                                      ctx->max_tokens_out - ti);
     50    ctx->ti = ti;
     51 }
     52 
     53 
     54 static void
     55 emit_declaration(struct tgsi_transform_context *ctx,
     56                  const struct tgsi_full_declaration *decl)
     57 {
     58    uint ti = ctx->ti;
     59 
     60    ti += tgsi_build_full_declaration(decl,
     61                                      ctx->tokens_out + ti,
     62                                      ctx->header,
     63                                      ctx->max_tokens_out - ti);
     64    ctx->ti = ti;
     65 }
     66 
     67 
     68 static void
     69 emit_immediate(struct tgsi_transform_context *ctx,
     70                const struct tgsi_full_immediate *imm)
     71 {
     72    uint ti = ctx->ti;
     73 
     74    ti += tgsi_build_full_immediate(imm,
     75                                    ctx->tokens_out + ti,
     76                                    ctx->header,
     77                                    ctx->max_tokens_out - ti);
     78    ctx->ti = ti;
     79 }
     80 
     81 
     82 static void
     83 emit_property(struct tgsi_transform_context *ctx,
     84               const struct tgsi_full_property *prop)
     85 {
     86    uint ti = ctx->ti;
     87 
     88    ti += tgsi_build_full_property(prop,
     89                                   ctx->tokens_out + ti,
     90                                   ctx->header,
     91                                   ctx->max_tokens_out - ti);
     92    ctx->ti = ti;
     93 }
     94 
     95 
     96 /**
     97  * Apply user-defined transformations to the input shader to produce
     98  * the output shader.
     99  * For example, a register search-and-replace operation could be applied
    100  * by defining a transform_instruction() callback that examined and changed
    101  * the instruction src/dest regs.
    102  *
    103  * \return number of tokens emitted
    104  */
    105 int
    106 tgsi_transform_shader(const struct tgsi_token *tokens_in,
    107                       struct tgsi_token *tokens_out,
    108                       uint max_tokens_out,
    109                       struct tgsi_transform_context *ctx)
    110 {
    111    uint procType;
    112 
    113    /* input shader */
    114    struct tgsi_parse_context parse;
    115 
    116    /* output shader */
    117    struct tgsi_processor *processor;
    118 
    119 
    120    /**
    121     ** callback context init
    122     **/
    123    ctx->emit_instruction = emit_instruction;
    124    ctx->emit_declaration = emit_declaration;
    125    ctx->emit_immediate = emit_immediate;
    126    ctx->emit_property = emit_property;
    127    ctx->tokens_out = tokens_out;
    128    ctx->max_tokens_out = max_tokens_out;
    129 
    130 
    131    /**
    132     ** Setup to begin parsing input shader
    133     **/
    134    if (tgsi_parse_init( &parse, tokens_in ) != TGSI_PARSE_OK) {
    135       debug_printf("tgsi_parse_init() failed in tgsi_transform_shader()!\n");
    136       return -1;
    137    }
    138    procType = parse.FullHeader.Processor.Processor;
    139    assert(procType == TGSI_PROCESSOR_FRAGMENT ||
    140           procType == TGSI_PROCESSOR_VERTEX ||
    141           procType == TGSI_PROCESSOR_GEOMETRY);
    142 
    143 
    144    /**
    145     **  Setup output shader
    146     **/
    147    ctx->header = (struct tgsi_header *)tokens_out;
    148    *ctx->header = tgsi_build_header();
    149 
    150    processor = (struct tgsi_processor *) (tokens_out + 1);
    151    *processor = tgsi_build_processor( procType, ctx->header );
    152 
    153    ctx->ti = 2;
    154 
    155 
    156    /**
    157     ** Loop over incoming program tokens/instructions
    158     */
    159    while( !tgsi_parse_end_of_tokens( &parse ) ) {
    160 
    161       tgsi_parse_token( &parse );
    162 
    163       switch( parse.FullToken.Token.Type ) {
    164       case TGSI_TOKEN_TYPE_INSTRUCTION:
    165          {
    166             struct tgsi_full_instruction *fullinst
    167                = &parse.FullToken.FullInstruction;
    168 
    169             if (ctx->transform_instruction)
    170                ctx->transform_instruction(ctx, fullinst);
    171             else
    172                ctx->emit_instruction(ctx, fullinst);
    173          }
    174          break;
    175 
    176       case TGSI_TOKEN_TYPE_DECLARATION:
    177          {
    178             struct tgsi_full_declaration *fulldecl
    179                = &parse.FullToken.FullDeclaration;
    180 
    181             if (ctx->transform_declaration)
    182                ctx->transform_declaration(ctx, fulldecl);
    183             else
    184                ctx->emit_declaration(ctx, fulldecl);
    185          }
    186          break;
    187 
    188       case TGSI_TOKEN_TYPE_IMMEDIATE:
    189          {
    190             struct tgsi_full_immediate *fullimm
    191                = &parse.FullToken.FullImmediate;
    192 
    193             if (ctx->transform_immediate)
    194                ctx->transform_immediate(ctx, fullimm);
    195             else
    196                ctx->emit_immediate(ctx, fullimm);
    197          }
    198          break;
    199       case TGSI_TOKEN_TYPE_PROPERTY:
    200          {
    201             struct tgsi_full_property *fullprop
    202                = &parse.FullToken.FullProperty;
    203 
    204             if (ctx->transform_property)
    205                ctx->transform_property(ctx, fullprop);
    206             else
    207                ctx->emit_property(ctx, fullprop);
    208          }
    209          break;
    210 
    211       default:
    212          assert( 0 );
    213       }
    214    }
    215 
    216    if (ctx->epilog) {
    217       ctx->epilog(ctx);
    218    }
    219 
    220    tgsi_parse_free (&parse);
    221 
    222    return ctx->ti;
    223 }
    224 
    225 
    226 #include "tgsi_text.h"
    227 
    228 extern int tgsi_transform_foo( struct tgsi_token *tokens_out,
    229                                uint max_tokens_out );
    230 
    231 /* This function exists only so that tgsi_text_translate() doesn't get
    232  * magic-ed out of the libtgsi.a archive by the build system.  Don't
    233  * remove unless you know this has been fixed - check on mingw/scons
    234  * builds as well.
    235  */
    236 int
    237 tgsi_transform_foo( struct tgsi_token *tokens_out,
    238                     uint max_tokens_out )
    239 {
    240    const char *text =
    241       "FRAG\n"
    242       "DCL IN[0], COLOR, CONSTANT\n"
    243       "DCL OUT[0], COLOR\n"
    244       "  0: MOV OUT[0], IN[0]\n"
    245       "  1: END";
    246 
    247    return tgsi_text_translate( text,
    248                                tokens_out,
    249                                max_tokens_out );
    250 }
    251