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 #ifndef TGSI_TRANSFORM_H
29 #define TGSI_TRANSFORM_H
30
31
32 #include "pipe/p_shader_tokens.h"
33 #include "tgsi/tgsi_parse.h"
34 #include "tgsi/tgsi_build.h"
35
36
37
38 /**
39 * Subclass this to add caller-specific data
40 */
41 struct tgsi_transform_context
42 {
43 /**** PUBLIC ***/
44
45 /**
46 * User-defined callbacks invoked per instruction.
47 */
48 void (*transform_instruction)(struct tgsi_transform_context *ctx,
49 struct tgsi_full_instruction *inst);
50
51 void (*transform_declaration)(struct tgsi_transform_context *ctx,
52 struct tgsi_full_declaration *decl);
53
54 void (*transform_immediate)(struct tgsi_transform_context *ctx,
55 struct tgsi_full_immediate *imm);
56 void (*transform_property)(struct tgsi_transform_context *ctx,
57 struct tgsi_full_property *prop);
58
59 /**
60 * Called after last declaration, before first instruction. This is
61 * where the user might insert new declarations and/or instructions.
62 */
63 void (*prolog)(struct tgsi_transform_context *ctx);
64
65 /**
66 * Called at end of input program to allow caller to append extra
67 * instructions. Return number of tokens emitted.
68 */
69 void (*epilog)(struct tgsi_transform_context *ctx);
70
71
72 /*** PRIVATE ***/
73
74 /**
75 * These are setup by tgsi_transform_shader() and cannot be overridden.
76 * Meant to be called from in the above user callback functions.
77 */
78 void (*emit_instruction)(struct tgsi_transform_context *ctx,
79 const struct tgsi_full_instruction *inst);
80 void (*emit_declaration)(struct tgsi_transform_context *ctx,
81 const struct tgsi_full_declaration *decl);
82 void (*emit_immediate)(struct tgsi_transform_context *ctx,
83 const struct tgsi_full_immediate *imm);
84 void (*emit_property)(struct tgsi_transform_context *ctx,
85 const struct tgsi_full_property *prop);
86
87 struct tgsi_header *header;
88 uint max_tokens_out;
89 struct tgsi_token *tokens_out;
90 uint ti;
91 };
92
93
94 /**
95 * Helper for emitting temporary register declarations.
96 */
97 static inline void
tgsi_transform_temps_decl(struct tgsi_transform_context * ctx,unsigned firstIdx,unsigned lastIdx)98 tgsi_transform_temps_decl(struct tgsi_transform_context *ctx,
99 unsigned firstIdx, unsigned lastIdx)
100 {
101 struct tgsi_full_declaration decl;
102
103 decl = tgsi_default_full_declaration();
104 decl.Declaration.File = TGSI_FILE_TEMPORARY;
105 decl.Range.First = firstIdx;
106 decl.Range.Last = lastIdx;
107 ctx->emit_declaration(ctx, &decl);
108 }
109
110 static inline void
tgsi_transform_temp_decl(struct tgsi_transform_context * ctx,unsigned index)111 tgsi_transform_temp_decl(struct tgsi_transform_context *ctx,
112 unsigned index)
113 {
114 tgsi_transform_temps_decl(ctx, index, index);
115 }
116
117 static inline void
tgsi_transform_const_decl(struct tgsi_transform_context * ctx,unsigned firstIdx,unsigned lastIdx)118 tgsi_transform_const_decl(struct tgsi_transform_context *ctx,
119 unsigned firstIdx, unsigned lastIdx)
120 {
121 struct tgsi_full_declaration decl;
122
123 decl = tgsi_default_full_declaration();
124 decl.Declaration.File = TGSI_FILE_CONSTANT;
125 decl.Range.First = firstIdx;
126 decl.Range.Last = lastIdx;
127 decl.Declaration.Dimension = 1;
128 /* Dim.Index2D is already 0 */
129 ctx->emit_declaration(ctx, &decl);
130 }
131
132 static inline void
tgsi_transform_input_decl(struct tgsi_transform_context * ctx,unsigned index,unsigned sem_name,unsigned sem_index,unsigned interp)133 tgsi_transform_input_decl(struct tgsi_transform_context *ctx,
134 unsigned index,
135 unsigned sem_name, unsigned sem_index,
136 unsigned interp)
137 {
138 struct tgsi_full_declaration decl;
139
140 decl = tgsi_default_full_declaration();
141 decl.Declaration.File = TGSI_FILE_INPUT;
142 decl.Declaration.Interpolate = 1;
143 decl.Declaration.Semantic = 1;
144 decl.Semantic.Name = sem_name;
145 decl.Semantic.Index = sem_index;
146 decl.Range.First =
147 decl.Range.Last = index;
148 decl.Interp.Interpolate = interp;
149
150 ctx->emit_declaration(ctx, &decl);
151 }
152
153 static inline void
tgsi_transform_output_decl(struct tgsi_transform_context * ctx,unsigned index,unsigned sem_name,unsigned sem_index,unsigned interp)154 tgsi_transform_output_decl(struct tgsi_transform_context *ctx,
155 unsigned index,
156 unsigned sem_name, unsigned sem_index,
157 unsigned interp)
158 {
159 struct tgsi_full_declaration decl;
160
161 decl = tgsi_default_full_declaration();
162 decl.Declaration.File = TGSI_FILE_OUTPUT;
163 decl.Declaration.Interpolate = 1;
164 decl.Declaration.Semantic = 1;
165 decl.Semantic.Name = sem_name;
166 decl.Semantic.Index = sem_index;
167 decl.Range.First =
168 decl.Range.Last = index;
169 decl.Interp.Interpolate = interp;
170
171 ctx->emit_declaration(ctx, &decl);
172 }
173
174 static inline void
tgsi_transform_sampler_decl(struct tgsi_transform_context * ctx,unsigned index)175 tgsi_transform_sampler_decl(struct tgsi_transform_context *ctx,
176 unsigned index)
177 {
178 struct tgsi_full_declaration decl;
179
180 decl = tgsi_default_full_declaration();
181 decl.Declaration.File = TGSI_FILE_SAMPLER;
182 decl.Range.First =
183 decl.Range.Last = index;
184 ctx->emit_declaration(ctx, &decl);
185 }
186
187 static inline void
tgsi_transform_sampler_view_decl(struct tgsi_transform_context * ctx,unsigned index,unsigned target,enum tgsi_return_type type)188 tgsi_transform_sampler_view_decl(struct tgsi_transform_context *ctx,
189 unsigned index,
190 unsigned target,
191 enum tgsi_return_type type)
192 {
193 struct tgsi_full_declaration decl;
194
195 decl = tgsi_default_full_declaration();
196 decl.Declaration.File = TGSI_FILE_SAMPLER_VIEW;
197 decl.Declaration.UsageMask = TGSI_WRITEMASK_XYZW;
198 decl.Range.First =
199 decl.Range.Last = index;
200 decl.SamplerView.Resource = target;
201 decl.SamplerView.ReturnTypeX = type;
202 decl.SamplerView.ReturnTypeY = type;
203 decl.SamplerView.ReturnTypeZ = type;
204 decl.SamplerView.ReturnTypeW = type;
205
206 ctx->emit_declaration(ctx, &decl);
207 }
208
209 static inline void
tgsi_transform_immediate_decl(struct tgsi_transform_context * ctx,float x,float y,float z,float w)210 tgsi_transform_immediate_decl(struct tgsi_transform_context *ctx,
211 float x, float y, float z, float w)
212 {
213 struct tgsi_full_immediate immed;
214 unsigned size = 4;
215
216 immed = tgsi_default_full_immediate();
217 immed.Immediate.NrTokens = 1 + size; /* one for the token itself */
218 immed.u[0].Float = x;
219 immed.u[1].Float = y;
220 immed.u[2].Float = z;
221 immed.u[3].Float = w;
222
223 ctx->emit_immediate(ctx, &immed);
224 }
225
226 static inline void
tgsi_transform_dst_reg(struct tgsi_full_dst_register * reg,unsigned file,unsigned index,unsigned writemask)227 tgsi_transform_dst_reg(struct tgsi_full_dst_register *reg,
228 unsigned file, unsigned index, unsigned writemask)
229 {
230 reg->Register.File = file;
231 reg->Register.Index = index;
232 reg->Register.WriteMask = writemask;
233 }
234
235 static inline void
tgsi_transform_src_reg_xyzw(struct tgsi_full_src_register * reg,unsigned file,unsigned index)236 tgsi_transform_src_reg_xyzw(struct tgsi_full_src_register *reg,
237 unsigned file, unsigned index)
238 {
239 reg->Register.File = file;
240 reg->Register.Index = index;
241 if (file == TGSI_FILE_CONSTANT) {
242 reg->Register.Dimension = 1;
243 reg->Dimension.Index = 0;
244 }
245 }
246
247 static inline void
tgsi_transform_src_reg(struct tgsi_full_src_register * reg,unsigned file,unsigned index,unsigned swizzleX,unsigned swizzleY,unsigned swizzleZ,unsigned swizzleW)248 tgsi_transform_src_reg(struct tgsi_full_src_register *reg,
249 unsigned file, unsigned index,
250 unsigned swizzleX, unsigned swizzleY,
251 unsigned swizzleZ, unsigned swizzleW)
252 {
253 reg->Register.File = file;
254 reg->Register.Index = index;
255 if (file == TGSI_FILE_CONSTANT) {
256 reg->Register.Dimension = 1;
257 reg->Dimension.Index = 0;
258 }
259 reg->Register.SwizzleX = swizzleX;
260 reg->Register.SwizzleY = swizzleY;
261 reg->Register.SwizzleZ = swizzleZ;
262 reg->Register.SwizzleW = swizzleW;
263 }
264
265 /**
266 * Helper for emitting 1-operand instructions.
267 */
268 static inline void
tgsi_transform_op1_inst(struct tgsi_transform_context * ctx,unsigned opcode,unsigned dst_file,unsigned dst_index,unsigned dst_writemask,unsigned src0_file,unsigned src0_index)269 tgsi_transform_op1_inst(struct tgsi_transform_context *ctx,
270 unsigned opcode,
271 unsigned dst_file,
272 unsigned dst_index,
273 unsigned dst_writemask,
274 unsigned src0_file,
275 unsigned src0_index)
276 {
277 struct tgsi_full_instruction inst;
278
279 inst = tgsi_default_full_instruction();
280 inst.Instruction.Opcode = opcode;
281 inst.Instruction.NumDstRegs = 1;
282 inst.Dst[0].Register.File = dst_file,
283 inst.Dst[0].Register.Index = dst_index;
284 inst.Dst[0].Register.WriteMask = dst_writemask;
285 inst.Instruction.NumSrcRegs = 1;
286 tgsi_transform_src_reg_xyzw(&inst.Src[0], src0_file, src0_index);
287
288 ctx->emit_instruction(ctx, &inst);
289 }
290
291
292 static inline void
tgsi_transform_op2_inst(struct tgsi_transform_context * ctx,unsigned opcode,unsigned dst_file,unsigned dst_index,unsigned dst_writemask,unsigned src0_file,unsigned src0_index,unsigned src1_file,unsigned src1_index,bool src1_negate)293 tgsi_transform_op2_inst(struct tgsi_transform_context *ctx,
294 unsigned opcode,
295 unsigned dst_file,
296 unsigned dst_index,
297 unsigned dst_writemask,
298 unsigned src0_file,
299 unsigned src0_index,
300 unsigned src1_file,
301 unsigned src1_index,
302 bool src1_negate)
303 {
304 struct tgsi_full_instruction inst;
305
306 inst = tgsi_default_full_instruction();
307 inst.Instruction.Opcode = opcode;
308 inst.Instruction.NumDstRegs = 1;
309 inst.Dst[0].Register.File = dst_file,
310 inst.Dst[0].Register.Index = dst_index;
311 inst.Dst[0].Register.WriteMask = dst_writemask;
312 inst.Instruction.NumSrcRegs = 2;
313 tgsi_transform_src_reg_xyzw(&inst.Src[0], src0_file, src0_index);
314 tgsi_transform_src_reg_xyzw(&inst.Src[1], src1_file, src1_index);
315 inst.Src[1].Register.Negate = src1_negate;
316
317 ctx->emit_instruction(ctx, &inst);
318 }
319
320
321 static inline void
tgsi_transform_op3_inst(struct tgsi_transform_context * ctx,unsigned opcode,unsigned dst_file,unsigned dst_index,unsigned dst_writemask,unsigned src0_file,unsigned src0_index,unsigned src1_file,unsigned src1_index,unsigned src2_file,unsigned src2_index)322 tgsi_transform_op3_inst(struct tgsi_transform_context *ctx,
323 unsigned opcode,
324 unsigned dst_file,
325 unsigned dst_index,
326 unsigned dst_writemask,
327 unsigned src0_file,
328 unsigned src0_index,
329 unsigned src1_file,
330 unsigned src1_index,
331 unsigned src2_file,
332 unsigned src2_index)
333 {
334 struct tgsi_full_instruction inst;
335
336 inst = tgsi_default_full_instruction();
337 inst.Instruction.Opcode = opcode;
338 inst.Instruction.NumDstRegs = 1;
339 inst.Dst[0].Register.File = dst_file,
340 inst.Dst[0].Register.Index = dst_index;
341 inst.Dst[0].Register.WriteMask = dst_writemask;
342 inst.Instruction.NumSrcRegs = 3;
343 tgsi_transform_src_reg_xyzw(&inst.Src[0], src0_file, src0_index);
344 tgsi_transform_src_reg_xyzw(&inst.Src[1], src1_file, src1_index);
345 tgsi_transform_src_reg_xyzw(&inst.Src[2], src2_file, src2_index);
346
347 ctx->emit_instruction(ctx, &inst);
348 }
349
350
351
352 static inline void
tgsi_transform_op1_swz_inst(struct tgsi_transform_context * ctx,unsigned opcode,unsigned dst_file,unsigned dst_index,unsigned dst_writemask,unsigned src0_file,unsigned src0_index,unsigned src0_swizzle)353 tgsi_transform_op1_swz_inst(struct tgsi_transform_context *ctx,
354 unsigned opcode,
355 unsigned dst_file,
356 unsigned dst_index,
357 unsigned dst_writemask,
358 unsigned src0_file,
359 unsigned src0_index,
360 unsigned src0_swizzle)
361 {
362 struct tgsi_full_instruction inst;
363
364 inst = tgsi_default_full_instruction();
365 inst.Instruction.Opcode = opcode;
366 inst.Instruction.NumDstRegs = 1;
367 inst.Dst[0].Register.File = dst_file,
368 inst.Dst[0].Register.Index = dst_index;
369 inst.Dst[0].Register.WriteMask = dst_writemask;
370 inst.Instruction.NumSrcRegs = 1;
371 tgsi_transform_src_reg_xyzw(&inst.Src[0], src0_file, src0_index);
372 switch (dst_writemask) {
373 case TGSI_WRITEMASK_X:
374 inst.Src[0].Register.SwizzleX = src0_swizzle;
375 break;
376 case TGSI_WRITEMASK_Y:
377 inst.Src[0].Register.SwizzleY = src0_swizzle;
378 break;
379 case TGSI_WRITEMASK_Z:
380 inst.Src[0].Register.SwizzleZ = src0_swizzle;
381 break;
382 case TGSI_WRITEMASK_W:
383 inst.Src[0].Register.SwizzleW = src0_swizzle;
384 break;
385 default:
386 ; /* nothing */
387 }
388
389 ctx->emit_instruction(ctx, &inst);
390 }
391
392
393 static inline void
tgsi_transform_op2_swz_inst(struct tgsi_transform_context * ctx,unsigned opcode,unsigned dst_file,unsigned dst_index,unsigned dst_writemask,unsigned src0_file,unsigned src0_index,unsigned src0_swizzle,unsigned src1_file,unsigned src1_index,unsigned src1_swizzle,bool src1_negate)394 tgsi_transform_op2_swz_inst(struct tgsi_transform_context *ctx,
395 unsigned opcode,
396 unsigned dst_file,
397 unsigned dst_index,
398 unsigned dst_writemask,
399 unsigned src0_file,
400 unsigned src0_index,
401 unsigned src0_swizzle,
402 unsigned src1_file,
403 unsigned src1_index,
404 unsigned src1_swizzle,
405 bool src1_negate)
406 {
407 struct tgsi_full_instruction inst;
408
409 inst = tgsi_default_full_instruction();
410 inst.Instruction.Opcode = opcode;
411 inst.Instruction.NumDstRegs = 1;
412 inst.Dst[0].Register.File = dst_file,
413 inst.Dst[0].Register.Index = dst_index;
414 inst.Dst[0].Register.WriteMask = dst_writemask;
415 inst.Instruction.NumSrcRegs = 2;
416 tgsi_transform_src_reg_xyzw(&inst.Src[0], src0_file, src0_index);
417 tgsi_transform_src_reg_xyzw(&inst.Src[1], src1_file, src1_index);
418 inst.Src[1].Register.Negate = src1_negate;
419 switch (dst_writemask) {
420 case TGSI_WRITEMASK_X:
421 inst.Src[0].Register.SwizzleX = src0_swizzle;
422 inst.Src[1].Register.SwizzleX = src1_swizzle;
423 break;
424 case TGSI_WRITEMASK_Y:
425 inst.Src[0].Register.SwizzleY = src0_swizzle;
426 inst.Src[1].Register.SwizzleY = src1_swizzle;
427 break;
428 case TGSI_WRITEMASK_Z:
429 inst.Src[0].Register.SwizzleZ = src0_swizzle;
430 inst.Src[1].Register.SwizzleZ = src1_swizzle;
431 break;
432 case TGSI_WRITEMASK_W:
433 inst.Src[0].Register.SwizzleW = src0_swizzle;
434 inst.Src[1].Register.SwizzleW = src1_swizzle;
435 break;
436 default:
437 ; /* nothing */
438 }
439
440 ctx->emit_instruction(ctx, &inst);
441 }
442
443
444 static inline void
tgsi_transform_op3_swz_inst(struct tgsi_transform_context * ctx,unsigned opcode,unsigned dst_file,unsigned dst_index,unsigned dst_writemask,unsigned src0_file,unsigned src0_index,unsigned src0_swizzle,unsigned src0_negate,unsigned src1_file,unsigned src1_index,unsigned src1_swizzle,unsigned src2_file,unsigned src2_index,unsigned src2_swizzle)445 tgsi_transform_op3_swz_inst(struct tgsi_transform_context *ctx,
446 unsigned opcode,
447 unsigned dst_file,
448 unsigned dst_index,
449 unsigned dst_writemask,
450 unsigned src0_file,
451 unsigned src0_index,
452 unsigned src0_swizzle,
453 unsigned src0_negate,
454 unsigned src1_file,
455 unsigned src1_index,
456 unsigned src1_swizzle,
457 unsigned src2_file,
458 unsigned src2_index,
459 unsigned src2_swizzle)
460 {
461 struct tgsi_full_instruction inst;
462
463 inst = tgsi_default_full_instruction();
464 inst.Instruction.Opcode = opcode;
465 inst.Instruction.NumDstRegs = 1;
466 inst.Dst[0].Register.File = dst_file,
467 inst.Dst[0].Register.Index = dst_index;
468 inst.Dst[0].Register.WriteMask = dst_writemask;
469 inst.Instruction.NumSrcRegs = 3;
470 tgsi_transform_src_reg_xyzw(&inst.Src[0], src0_file, src0_index);
471 inst.Src[0].Register.Negate = src0_negate;
472 tgsi_transform_src_reg_xyzw(&inst.Src[1], src1_file, src1_index);
473 tgsi_transform_src_reg_xyzw(&inst.Src[2], src2_file, src2_index);
474 switch (dst_writemask) {
475 case TGSI_WRITEMASK_X:
476 inst.Src[0].Register.SwizzleX = src0_swizzle;
477 inst.Src[1].Register.SwizzleX = src1_swizzle;
478 inst.Src[2].Register.SwizzleX = src2_swizzle;
479 break;
480 case TGSI_WRITEMASK_Y:
481 inst.Src[0].Register.SwizzleY = src0_swizzle;
482 inst.Src[1].Register.SwizzleY = src1_swizzle;
483 inst.Src[2].Register.SwizzleY = src2_swizzle;
484 break;
485 case TGSI_WRITEMASK_Z:
486 inst.Src[0].Register.SwizzleZ = src0_swizzle;
487 inst.Src[1].Register.SwizzleZ = src1_swizzle;
488 inst.Src[2].Register.SwizzleZ = src2_swizzle;
489 break;
490 case TGSI_WRITEMASK_W:
491 inst.Src[0].Register.SwizzleW = src0_swizzle;
492 inst.Src[1].Register.SwizzleW = src1_swizzle;
493 inst.Src[2].Register.SwizzleW = src2_swizzle;
494 break;
495 default:
496 ; /* nothing */
497 }
498
499 ctx->emit_instruction(ctx, &inst);
500 }
501
502
503 static inline void
tgsi_transform_kill_inst(struct tgsi_transform_context * ctx,unsigned src_file,unsigned src_index,unsigned src_swizzle,boolean negate)504 tgsi_transform_kill_inst(struct tgsi_transform_context *ctx,
505 unsigned src_file,
506 unsigned src_index,
507 unsigned src_swizzle,
508 boolean negate)
509 {
510 struct tgsi_full_instruction inst;
511
512 inst = tgsi_default_full_instruction();
513 inst.Instruction.Opcode = TGSI_OPCODE_KILL_IF;
514 inst.Instruction.NumDstRegs = 0;
515 inst.Instruction.NumSrcRegs = 1;
516 tgsi_transform_src_reg_xyzw(&inst.Src[0], src_file, src_index);
517 inst.Src[0].Register.SwizzleX =
518 inst.Src[0].Register.SwizzleY =
519 inst.Src[0].Register.SwizzleZ =
520 inst.Src[0].Register.SwizzleW = src_swizzle;
521 inst.Src[0].Register.Negate = negate;
522
523 ctx->emit_instruction(ctx, &inst);
524 }
525
526
527 static inline void
tgsi_transform_tex_inst(struct tgsi_transform_context * ctx,unsigned dst_file,unsigned dst_index,unsigned src_file,unsigned src_index,unsigned tex_target,unsigned sampler_index)528 tgsi_transform_tex_inst(struct tgsi_transform_context *ctx,
529 unsigned dst_file,
530 unsigned dst_index,
531 unsigned src_file,
532 unsigned src_index,
533 unsigned tex_target,
534 unsigned sampler_index)
535 {
536 struct tgsi_full_instruction inst;
537
538 assert(tex_target < TGSI_TEXTURE_COUNT);
539
540 inst = tgsi_default_full_instruction();
541 inst.Instruction.Opcode = TGSI_OPCODE_TEX;
542 inst.Instruction.NumDstRegs = 1;
543 inst.Dst[0].Register.File = dst_file;
544 inst.Dst[0].Register.Index = dst_index;
545 inst.Instruction.NumSrcRegs = 2;
546 inst.Instruction.Texture = TRUE;
547 inst.Texture.Texture = tex_target;
548 tgsi_transform_src_reg_xyzw(&inst.Src[0], src_file, src_index);
549 tgsi_transform_src_reg_xyzw(&inst.Src[1], TGSI_FILE_SAMPLER, sampler_index);
550
551 ctx->emit_instruction(ctx, &inst);
552 }
553
554
555 extern int
556 tgsi_transform_shader(const struct tgsi_token *tokens_in,
557 struct tgsi_token *tokens_out,
558 uint max_tokens_out,
559 struct tgsi_transform_context *ctx);
560
561
562 #endif /* TGSI_TRANSFORM_H */
563