Subversion Repositories Kolibri OS

Rev

Blame | Last modification | View Log | RSS feed

  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.    boolean first_instruction = TRUE;
  113.  
  114.    /* input shader */
  115.    struct tgsi_parse_context parse;
  116.  
  117.    /* output shader */
  118.    struct tgsi_processor *processor;
  119.  
  120.  
  121.    /**
  122.     ** callback context init
  123.     **/
  124.    ctx->emit_instruction = emit_instruction;
  125.    ctx->emit_declaration = emit_declaration;
  126.    ctx->emit_immediate = emit_immediate;
  127.    ctx->emit_property = emit_property;
  128.    ctx->tokens_out = tokens_out;
  129.    ctx->max_tokens_out = max_tokens_out;
  130.  
  131.  
  132.    /**
  133.     ** Setup to begin parsing input shader
  134.     **/
  135.    if (tgsi_parse_init( &parse, tokens_in ) != TGSI_PARSE_OK) {
  136.       debug_printf("tgsi_parse_init() failed in tgsi_transform_shader()!\n");
  137.       return -1;
  138.    }
  139.    procType = parse.FullHeader.Processor.Processor;
  140.    assert(procType == TGSI_PROCESSOR_FRAGMENT ||
  141.           procType == TGSI_PROCESSOR_VERTEX ||
  142.           procType == TGSI_PROCESSOR_GEOMETRY);
  143.  
  144.  
  145.    /**
  146.     **  Setup output shader
  147.     **/
  148.    ctx->header = (struct tgsi_header *)tokens_out;
  149.    *ctx->header = tgsi_build_header();
  150.  
  151.    processor = (struct tgsi_processor *) (tokens_out + 1);
  152.    *processor = tgsi_build_processor( procType, ctx->header );
  153.  
  154.    ctx->ti = 2;
  155.  
  156.  
  157.    /**
  158.     ** Loop over incoming program tokens/instructions
  159.     */
  160.    while( !tgsi_parse_end_of_tokens( &parse ) ) {
  161.  
  162.       tgsi_parse_token( &parse );
  163.  
  164.       switch( parse.FullToken.Token.Type ) {
  165.       case TGSI_TOKEN_TYPE_INSTRUCTION:
  166.          {
  167.             struct tgsi_full_instruction *fullinst
  168.                = &parse.FullToken.FullInstruction;
  169.  
  170.             if (first_instruction && ctx->prolog) {
  171.                ctx->prolog(ctx);
  172.             }
  173.  
  174.             /* XXX Note: we may also want to look for a main/top-level
  175.              * TGSI_OPCODE_RET instruction in the future.
  176.              */
  177.             if (fullinst->Instruction.Opcode == TGSI_OPCODE_END
  178.                 && ctx->epilog) {
  179.                /* Emit caller's epilog */
  180.                ctx->epilog(ctx);
  181.                /* Emit END */
  182.                ctx->emit_instruction(ctx, fullinst);
  183.             }
  184.             else {
  185.                if (ctx->transform_instruction)
  186.                   ctx->transform_instruction(ctx, fullinst);
  187.                else
  188.                   ctx->emit_instruction(ctx, fullinst);
  189.             }
  190.  
  191.             first_instruction = FALSE;
  192.          }
  193.          break;
  194.  
  195.       case TGSI_TOKEN_TYPE_DECLARATION:
  196.          {
  197.             struct tgsi_full_declaration *fulldecl
  198.                = &parse.FullToken.FullDeclaration;
  199.  
  200.             if (ctx->transform_declaration)
  201.                ctx->transform_declaration(ctx, fulldecl);
  202.             else
  203.                ctx->emit_declaration(ctx, fulldecl);
  204.          }
  205.          break;
  206.  
  207.       case TGSI_TOKEN_TYPE_IMMEDIATE:
  208.          {
  209.             struct tgsi_full_immediate *fullimm
  210.                = &parse.FullToken.FullImmediate;
  211.  
  212.             if (ctx->transform_immediate)
  213.                ctx->transform_immediate(ctx, fullimm);
  214.             else
  215.                ctx->emit_immediate(ctx, fullimm);
  216.          }
  217.          break;
  218.       case TGSI_TOKEN_TYPE_PROPERTY:
  219.          {
  220.             struct tgsi_full_property *fullprop
  221.                = &parse.FullToken.FullProperty;
  222.  
  223.             if (ctx->transform_property)
  224.                ctx->transform_property(ctx, fullprop);
  225.             else
  226.                ctx->emit_property(ctx, fullprop);
  227.          }
  228.          break;
  229.  
  230.       default:
  231.          assert( 0 );
  232.       }
  233.    }
  234.  
  235.    tgsi_parse_free (&parse);
  236.  
  237.    return ctx->ti;
  238. }
  239.  
  240.  
  241. #include "tgsi_text.h"
  242.  
  243. extern int tgsi_transform_foo( struct tgsi_token *tokens_out,
  244.                                uint max_tokens_out );
  245.  
  246. /* This function exists only so that tgsi_text_translate() doesn't get
  247.  * magic-ed out of the libtgsi.a archive by the build system.  Don't
  248.  * remove unless you know this has been fixed - check on mingw/scons
  249.  * builds as well.
  250.  */
  251. int
  252. tgsi_transform_foo( struct tgsi_token *tokens_out,
  253.                     uint max_tokens_out )
  254. {
  255.    const char *text =
  256.       "FRAG\n"
  257.       "DCL IN[0], COLOR, CONSTANT\n"
  258.       "DCL OUT[0], COLOR\n"
  259.       "  0: MOV OUT[0], IN[0]\n"
  260.       "  1: END";
  261.        
  262.    return tgsi_text_translate( text,
  263.                                tokens_out,
  264.                                max_tokens_out );
  265. }
  266.