Merge tgsi/exec and tgsi/util directories.
[mesa.git] / src / gallium / auxiliary / tgsi / tgsi_transform.c
1 /**************************************************************************
2 *
3 * Copyright 2008 Tungsten Graphics, Inc., Cedar Park, Texas.
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 TUNGSTEN GRAPHICS 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
35 #include "tgsi_transform.h"
36
37
38
39 static void
40 emit_instruction(struct tgsi_transform_context *ctx,
41 const struct tgsi_full_instruction *inst)
42 {
43 uint ti = ctx->ti;
44
45 ti += tgsi_build_full_instruction(inst,
46 ctx->tokens_out + ti,
47 ctx->header,
48 ctx->max_tokens_out - ti);
49 ctx->ti = ti;
50 }
51
52
53 static void
54 emit_declaration(struct tgsi_transform_context *ctx,
55 const struct tgsi_full_declaration *decl)
56 {
57 uint ti = ctx->ti;
58
59 ti += tgsi_build_full_declaration(decl,
60 ctx->tokens_out + ti,
61 ctx->header,
62 ctx->max_tokens_out - ti);
63 ctx->ti = ti;
64 }
65
66
67 static void
68 emit_immediate(struct tgsi_transform_context *ctx,
69 const struct tgsi_full_immediate *imm)
70 {
71 uint ti = ctx->ti;
72
73 ti += tgsi_build_full_immediate(imm,
74 ctx->tokens_out + ti,
75 ctx->header,
76 ctx->max_tokens_out - ti);
77 ctx->ti = ti;
78 }
79
80
81
82 /**
83 * Apply user-defined transformations to the input shader to produce
84 * the output shader.
85 * For example, a register search-and-replace operation could be applied
86 * by defining a transform_instruction() callback that examined and changed
87 * the instruction src/dest regs.
88 *
89 * \return number of tokens emitted
90 */
91 int
92 tgsi_transform_shader(const struct tgsi_token *tokens_in,
93 struct tgsi_token *tokens_out,
94 uint max_tokens_out,
95 struct tgsi_transform_context *ctx)
96 {
97 uint procType;
98
99 /* input shader */
100 struct tgsi_parse_context parse;
101
102 /* output shader */
103 struct tgsi_processor *processor;
104
105
106 /**
107 ** callback context init
108 **/
109 ctx->emit_instruction = emit_instruction;
110 ctx->emit_declaration = emit_declaration;
111 ctx->emit_immediate = emit_immediate;
112 ctx->tokens_out = tokens_out;
113 ctx->max_tokens_out = max_tokens_out;
114
115
116 /**
117 ** Setup to begin parsing input shader
118 **/
119 if (tgsi_parse_init( &parse, tokens_in ) != TGSI_PARSE_OK) {
120 debug_printf("tgsi_parse_init() failed in tgsi_transform_shader()!\n");
121 return -1;
122 }
123 procType = parse.FullHeader.Processor.Processor;
124 assert(procType == TGSI_PROCESSOR_FRAGMENT ||
125 procType == TGSI_PROCESSOR_VERTEX ||
126 procType == TGSI_PROCESSOR_GEOMETRY);
127
128
129 /**
130 ** Setup output shader
131 **/
132 *(struct tgsi_version *) &tokens_out[0] = tgsi_build_version();
133
134 ctx->header = (struct tgsi_header *) (tokens_out + 1);
135 *ctx->header = tgsi_build_header();
136
137 processor = (struct tgsi_processor *) (tokens_out + 2);
138 *processor = tgsi_build_processor( procType, ctx->header );
139
140 ctx->ti = 3;
141
142
143 /**
144 ** Loop over incoming program tokens/instructions
145 */
146 while( !tgsi_parse_end_of_tokens( &parse ) ) {
147
148 tgsi_parse_token( &parse );
149
150 switch( parse.FullToken.Token.Type ) {
151 case TGSI_TOKEN_TYPE_INSTRUCTION:
152 {
153 struct tgsi_full_instruction *fullinst
154 = &parse.FullToken.FullInstruction;
155
156 if (ctx->transform_instruction)
157 ctx->transform_instruction(ctx, fullinst);
158 else
159 ctx->emit_instruction(ctx, fullinst);
160 }
161 break;
162
163 case TGSI_TOKEN_TYPE_DECLARATION:
164 {
165 struct tgsi_full_declaration *fulldecl
166 = &parse.FullToken.FullDeclaration;
167
168 if (ctx->transform_declaration)
169 ctx->transform_declaration(ctx, fulldecl);
170 else
171 ctx->emit_declaration(ctx, fulldecl);
172 }
173 break;
174
175 case TGSI_TOKEN_TYPE_IMMEDIATE:
176 {
177 struct tgsi_full_immediate *fullimm
178 = &parse.FullToken.FullImmediate;
179
180 if (ctx->transform_immediate)
181 ctx->transform_immediate(ctx, fullimm);
182 else
183 ctx->emit_immediate(ctx, fullimm);
184 }
185 break;
186
187 default:
188 assert( 0 );
189 }
190 }
191
192 if (ctx->epilog) {
193 ctx->epilog(ctx);
194 }
195
196 tgsi_parse_free (&parse);
197
198 return ctx->ti;
199 }