2 * Copyright 2014 VMware, Inc.
5 * Permission is hereby granted, free of charge, to any person obtaining a
6 * copy of this software and associated documentation files (the
7 * "Software"), to deal in the Software without restriction, including
8 * without limitation the rights to use, copy, modify, merge, publish,
9 * distribute, sub license, and/or sell copies of the Software, and to
10 * permit persons to whom the Software is furnished to do so, subject to
11 * the following conditions:
13 * The above copyright notice and this permission notice (including the
14 * next paragraph) shall be included in all copies or substantial portions
17 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
18 * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
19 * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT.
20 * IN NO EVENT SHALL THE AUTHORS AND/OR ITS SUPPLIERS BE LIABLE FOR
21 * ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
22 * TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
23 * SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
28 * This utility transforms the geometry shader to emulate point sprite by
29 * drawing a quad. It also adds an extra output for the original point position
30 * if the point position is to be written to a stream output buffer.
31 * Note: It assumes the driver will add a constant for the inverse viewport
32 * after the user defined constants.
35 #include "util/u_debug.h"
36 #include "util/u_math.h"
37 #include "tgsi_info.h"
38 #include "tgsi_point_sprite.h"
39 #include "tgsi_transform.h"
40 #include "pipe/p_state.h"
42 #define INVALID_INDEX 9999
44 /* Set swizzle based on the immediates (0, 1, 0, -1) */
45 static inline unsigned
46 set_swizzle(int x
, int y
, int z
, int w
)
48 static const unsigned map
[3] = {TGSI_SWIZZLE_W
, TGSI_SWIZZLE_X
,
59 return map
[x
+1] | (map
[y
+1] << 2) | (map
[z
+1] << 4) | (map
[w
+1] << 6);
62 static inline unsigned
63 get_swizzle(unsigned swizzle
, unsigned component
)
65 assert(component
< 4);
66 return (swizzle
>> (component
* 2)) & 0x3;
69 struct psprite_transform_context
71 struct tgsi_transform_context base
;
74 unsigned num_orig_out
;
77 unsigned point_size_in
; // point size input
78 unsigned point_size_out
; // point size output
79 unsigned point_size_tmp
; // point size temp
80 unsigned point_pos_in
; // point pos input
81 unsigned point_pos_out
; // point pos output
82 unsigned point_pos_sout
; // original point pos for streamout
83 unsigned point_pos_tmp
; // point pos temp
84 unsigned point_scale_tmp
; // point scale temp
85 unsigned point_color_out
; // point color output
86 unsigned point_color_tmp
; // point color temp
87 unsigned point_imm
; // point immediates
88 unsigned point_ivp
; // point inverseViewport constant
89 unsigned point_dir_swz
[4]; // point direction swizzle
90 unsigned point_coord_swz
[4]; // point coord swizzle
91 unsigned point_coord_enable
; // point coord enable mask
92 unsigned point_coord_decl
; // point coord output declared mask
93 unsigned point_coord_out
; // point coord output starting index
94 unsigned point_coord_aa
; // aa point coord semantic index
95 unsigned point_coord_k
; // aa point coord threshold distance
96 unsigned stream_out_point_pos
:1; // set if to stream out original point pos
97 unsigned aa_point
:1; // set if doing aa point
98 unsigned out_tmp_index
[PIPE_MAX_SHADER_OUTPUTS
];
99 int max_generic
; // max generic semantic index
102 static inline struct psprite_transform_context
*
103 psprite_transform_context(struct tgsi_transform_context
*ctx
)
105 return (struct psprite_transform_context
*) ctx
;
110 * TGSI declaration transform callback.
113 psprite_decl(struct tgsi_transform_context
*ctx
,
114 struct tgsi_full_declaration
*decl
)
116 struct psprite_transform_context
*ts
= psprite_transform_context(ctx
);
117 unsigned range_end
= decl
->Range
.Last
+ 1;
119 if (decl
->Declaration
.File
== TGSI_FILE_INPUT
) {
120 if (decl
->Semantic
.Name
== TGSI_SEMANTIC_PSIZE
) {
121 ts
->point_size_in
= decl
->Range
.First
;
123 else if (decl
->Semantic
.Name
== TGSI_SEMANTIC_POSITION
) {
124 ts
->point_pos_in
= decl
->Range
.First
;
127 else if (decl
->Declaration
.File
== TGSI_FILE_OUTPUT
) {
128 if (decl
->Semantic
.Name
== TGSI_SEMANTIC_PSIZE
) {
129 ts
->point_size_out
= decl
->Range
.First
;
131 else if (decl
->Semantic
.Name
== TGSI_SEMANTIC_POSITION
) {
132 ts
->point_pos_out
= decl
->Range
.First
;
134 else if (decl
->Semantic
.Name
== TGSI_SEMANTIC_GENERIC
&&
135 decl
->Semantic
.Index
< 32) {
136 ts
->point_coord_decl
|= 1 << decl
->Semantic
.Index
;
137 ts
->max_generic
= MAX2(ts
->max_generic
, (int)decl
->Semantic
.Index
);
139 ts
->num_out
= MAX2(ts
->num_out
, range_end
);
141 else if (decl
->Declaration
.File
== TGSI_FILE_TEMPORARY
) {
142 ts
->num_tmp
= MAX2(ts
->num_tmp
, range_end
);
144 else if (decl
->Declaration
.File
== TGSI_FILE_CONSTANT
) {
145 ts
->num_const
= MAX2(ts
->num_const
, range_end
);
148 ctx
->emit_declaration(ctx
, decl
);
152 * TGSI immediate declaration transform callback.
155 psprite_immediate(struct tgsi_transform_context
*ctx
,
156 struct tgsi_full_immediate
*imm
)
158 struct psprite_transform_context
*ts
= psprite_transform_context(ctx
);
160 ctx
->emit_immediate(ctx
, imm
);
166 * TGSI transform prolog callback.
169 psprite_prolog(struct tgsi_transform_context
*ctx
)
171 struct psprite_transform_context
*ts
= psprite_transform_context(ctx
);
172 unsigned point_coord_enable
, en
;
175 /* Replace output registers with temporary registers */
176 for (i
= 0; i
< ts
->num_out
; i
++) {
177 ts
->out_tmp_index
[i
] = ts
->num_tmp
++;
179 ts
->num_orig_out
= ts
->num_out
;
181 /* Declare a tmp register for point scale */
182 ts
->point_scale_tmp
= ts
->num_tmp
++;
184 if (ts
->point_size_out
!= INVALID_INDEX
)
185 ts
->point_size_tmp
= ts
->out_tmp_index
[ts
->point_size_out
];
187 ts
->point_size_tmp
= ts
->num_tmp
++;
189 assert(ts
->point_pos_out
!= INVALID_INDEX
);
190 ts
->point_pos_tmp
= ts
->out_tmp_index
[ts
->point_pos_out
];
191 ts
->out_tmp_index
[ts
->point_pos_out
] = INVALID_INDEX
;
193 /* Declare one more tmp register for point coord threshold distance
194 * if we are generating anti-aliased point.
197 ts
->point_coord_k
= ts
->num_tmp
++;
199 tgsi_transform_temps_decl(ctx
, ts
->point_size_tmp
, ts
->num_tmp
-1);
201 /* Declare an extra output for the original point position for stream out */
202 if (ts
->stream_out_point_pos
) {
203 ts
->point_pos_sout
= ts
->num_out
++;
204 tgsi_transform_output_decl(ctx
, ts
->point_pos_sout
,
205 TGSI_SEMANTIC_GENERIC
, 0, 0);
208 /* point coord outputs to be declared */
209 point_coord_enable
= ts
->point_coord_enable
& ~ts
->point_coord_decl
;
211 /* Declare outputs for those point coord that are enabled but are not
212 * already declared in this shader.
214 ts
->point_coord_out
= ts
->num_out
;
215 if (point_coord_enable
) {
216 for (i
= 0, en
= point_coord_enable
; en
; en
>>=1, i
++) {
218 tgsi_transform_output_decl(ctx
, ts
->num_out
++,
219 TGSI_SEMANTIC_GENERIC
, i
, 0);
220 ts
->max_generic
= MAX2(ts
->max_generic
, (int)i
);
225 /* add an extra generic output for aa point texcoord */
227 ts
->point_coord_aa
= ts
->max_generic
+ 1;
228 assert((ts
->point_coord_enable
& (1 << ts
->point_coord_aa
)) == 0);
229 ts
->point_coord_enable
|= 1 << (ts
->point_coord_aa
);
230 tgsi_transform_output_decl(ctx
, ts
->num_out
++, TGSI_SEMANTIC_GENERIC
,
231 ts
->point_coord_aa
, 0);
234 /* Declare extra immediates */
235 ts
->point_imm
= ts
->num_imm
;
236 tgsi_transform_immediate_decl(ctx
, 0, 1, 0.5, -1);
238 /* Declare point constant -
239 * constant.xy -- inverseViewport
240 * constant.z -- current point size
241 * constant.w -- max point size
242 * The driver needs to add this constant to the constant buffer
244 ts
->point_ivp
= ts
->num_const
++;
245 tgsi_transform_const_decl(ctx
, ts
->point_ivp
, ts
->point_ivp
);
247 /* If this geometry shader does not specify point size,
248 * get the current point size from the point constant.
250 if (ts
->point_size_out
== INVALID_INDEX
) {
251 struct tgsi_full_instruction inst
;
253 inst
= tgsi_default_full_instruction();
254 inst
.Instruction
.Opcode
= TGSI_OPCODE_MOV
;
255 inst
.Instruction
.NumDstRegs
= 1;
256 tgsi_transform_dst_reg(&inst
.Dst
[0], TGSI_FILE_TEMPORARY
,
257 ts
->point_size_tmp
, TGSI_WRITEMASK_XYZW
);
258 inst
.Instruction
.NumSrcRegs
= 1;
259 tgsi_transform_src_reg(&inst
.Src
[0], TGSI_FILE_CONSTANT
,
260 ts
->point_ivp
, TGSI_SWIZZLE_Z
,
261 TGSI_SWIZZLE_Z
, TGSI_SWIZZLE_Z
, TGSI_SWIZZLE_Z
);
262 ctx
->emit_instruction(ctx
, &inst
);
268 * Add the point sprite emulation instructions at the emit vertex instruction
271 psprite_emit_vertex_inst(struct tgsi_transform_context
*ctx
,
272 struct tgsi_full_instruction
*vert_inst
)
274 struct psprite_transform_context
*ts
= psprite_transform_context(ctx
);
275 struct tgsi_full_instruction inst
;
276 unsigned point_coord_enable
, en
;
279 /* new point coord outputs */
280 point_coord_enable
= ts
->point_coord_enable
& ~ts
->point_coord_decl
;
282 /* OUTPUT[pos_sout] = TEMP[pos] */
283 if (ts
->point_pos_sout
!= INVALID_INDEX
) {
284 tgsi_transform_op1_inst(ctx
, TGSI_OPCODE_MOV
,
285 TGSI_FILE_OUTPUT
, ts
->point_pos_sout
,
287 TGSI_FILE_TEMPORARY
, ts
->point_pos_tmp
);
291 * Set up the point scale vector
292 * scale = pointSize * pos.w * inverseViewport
295 /* MUL point_scale.x, point_size.x, point_pos.w */
296 tgsi_transform_op2_swz_inst(ctx
, TGSI_OPCODE_MUL
,
297 TGSI_FILE_TEMPORARY
, ts
->point_scale_tmp
, TGSI_WRITEMASK_X
,
298 TGSI_FILE_TEMPORARY
, ts
->point_size_tmp
, TGSI_SWIZZLE_X
,
299 TGSI_FILE_TEMPORARY
, ts
->point_pos_tmp
, TGSI_SWIZZLE_W
, false);
301 /* MUL point_scale.xy, point_scale.xx, inverseViewport.xy */
302 inst
= tgsi_default_full_instruction();
303 inst
.Instruction
.Opcode
= TGSI_OPCODE_MUL
;
304 inst
.Instruction
.NumDstRegs
= 1;
305 tgsi_transform_dst_reg(&inst
.Dst
[0], TGSI_FILE_TEMPORARY
,
306 ts
->point_scale_tmp
, TGSI_WRITEMASK_XY
);
307 inst
.Instruction
.NumSrcRegs
= 2;
308 tgsi_transform_src_reg(&inst
.Src
[0], TGSI_FILE_TEMPORARY
,
309 ts
->point_scale_tmp
, TGSI_SWIZZLE_X
,
310 TGSI_SWIZZLE_X
, TGSI_SWIZZLE_X
, TGSI_SWIZZLE_X
);
311 tgsi_transform_src_reg(&inst
.Src
[1], TGSI_FILE_CONSTANT
,
312 ts
->point_ivp
, TGSI_SWIZZLE_X
,
313 TGSI_SWIZZLE_Y
, TGSI_SWIZZLE_Z
, TGSI_SWIZZLE_Z
);
314 ctx
->emit_instruction(ctx
, &inst
);
317 * Set up the point coord threshold distance
318 * k = 0.5 - 1 / pointsize
321 tgsi_transform_op2_swz_inst(ctx
, TGSI_OPCODE_DIV
,
322 TGSI_FILE_TEMPORARY
, ts
->point_coord_k
,
324 TGSI_FILE_IMMEDIATE
, ts
->point_imm
,
326 TGSI_FILE_TEMPORARY
, ts
->point_size_tmp
,
327 TGSI_SWIZZLE_X
, false);
329 tgsi_transform_op2_swz_inst(ctx
, TGSI_OPCODE_ADD
,
330 TGSI_FILE_TEMPORARY
, ts
->point_coord_k
,
332 TGSI_FILE_IMMEDIATE
, ts
->point_imm
,
334 TGSI_FILE_TEMPORARY
, ts
->point_coord_k
,
335 TGSI_SWIZZLE_X
, true);
339 for (i
= 0; i
< 4; i
++) {
340 unsigned point_dir_swz
= ts
->point_dir_swz
[i
];
341 unsigned point_coord_swz
= ts
->point_coord_swz
[i
];
343 /* All outputs need to be emitted for each vertex */
344 for (j
= 0; j
< ts
->num_orig_out
; j
++) {
345 if (ts
->out_tmp_index
[j
] != INVALID_INDEX
) {
346 tgsi_transform_op1_inst(ctx
, TGSI_OPCODE_MOV
,
349 TGSI_FILE_TEMPORARY
, ts
->out_tmp_index
[j
]);
353 /* pos = point_scale * point_dir + point_pos */
354 inst
= tgsi_default_full_instruction();
355 inst
.Instruction
.Opcode
= TGSI_OPCODE_MAD
;
356 inst
.Instruction
.NumDstRegs
= 1;
357 tgsi_transform_dst_reg(&inst
.Dst
[0], TGSI_FILE_OUTPUT
, ts
->point_pos_out
,
358 TGSI_WRITEMASK_XYZW
);
359 inst
.Instruction
.NumSrcRegs
= 3;
360 tgsi_transform_src_reg(&inst
.Src
[0], TGSI_FILE_TEMPORARY
, ts
->point_scale_tmp
,
361 TGSI_SWIZZLE_X
, TGSI_SWIZZLE_Y
, TGSI_SWIZZLE_X
,
363 tgsi_transform_src_reg(&inst
.Src
[1], TGSI_FILE_IMMEDIATE
, ts
->point_imm
,
364 get_swizzle(point_dir_swz
, 0),
365 get_swizzle(point_dir_swz
, 1),
366 get_swizzle(point_dir_swz
, 2),
367 get_swizzle(point_dir_swz
, 3));
368 tgsi_transform_src_reg(&inst
.Src
[2], TGSI_FILE_TEMPORARY
, ts
->point_pos_tmp
,
369 TGSI_SWIZZLE_X
, TGSI_SWIZZLE_Y
, TGSI_SWIZZLE_Z
,
371 ctx
->emit_instruction(ctx
, &inst
);
374 for (j
= 0, s
= 0, en
= point_coord_enable
; en
; en
>>=1, s
++) {
378 dstReg
= ts
->point_coord_out
+ j
;
380 inst
= tgsi_default_full_instruction();
381 inst
.Instruction
.Opcode
= TGSI_OPCODE_MOV
;
382 inst
.Instruction
.NumDstRegs
= 1;
383 tgsi_transform_dst_reg(&inst
.Dst
[0], TGSI_FILE_OUTPUT
,
384 dstReg
, TGSI_WRITEMASK_XYZW
);
385 inst
.Instruction
.NumSrcRegs
= 1;
386 tgsi_transform_src_reg(&inst
.Src
[0], TGSI_FILE_IMMEDIATE
, ts
->point_imm
,
387 get_swizzle(point_coord_swz
, 0),
388 get_swizzle(point_coord_swz
, 1),
389 get_swizzle(point_coord_swz
, 2),
390 get_swizzle(point_coord_swz
, 3));
391 ctx
->emit_instruction(ctx
, &inst
);
393 /* MOV point_coord.z point_coord_k.x */
394 if (s
== ts
->point_coord_aa
) {
395 tgsi_transform_op1_swz_inst(ctx
, TGSI_OPCODE_MOV
,
396 TGSI_FILE_OUTPUT
, dstReg
, TGSI_WRITEMASK_Z
,
397 TGSI_FILE_TEMPORARY
, ts
->point_coord_k
,
400 j
++; /* the next point coord output offset */
404 /* Emit the EMIT instruction for each vertex of the quad */
405 ctx
->emit_instruction(ctx
, vert_inst
);
408 /* Emit the ENDPRIM instruction for the quad */
409 inst
= tgsi_default_full_instruction();
410 inst
.Instruction
.Opcode
= TGSI_OPCODE_ENDPRIM
;
411 inst
.Instruction
.NumDstRegs
= 0;
412 inst
.Instruction
.NumSrcRegs
= 1;
413 inst
.Src
[0] = vert_inst
->Src
[0];
414 ctx
->emit_instruction(ctx
, &inst
);
419 * TGSI instruction transform callback.
422 psprite_inst(struct tgsi_transform_context
*ctx
,
423 struct tgsi_full_instruction
*inst
)
425 struct psprite_transform_context
*ts
= psprite_transform_context(ctx
);
427 if (inst
->Instruction
.Opcode
== TGSI_OPCODE_EMIT
) {
428 psprite_emit_vertex_inst(ctx
, inst
);
430 else if (inst
->Dst
[0].Register
.File
== TGSI_FILE_OUTPUT
&&
431 inst
->Dst
[0].Register
.Index
== (int)ts
->point_size_out
) {
433 * Replace point size output reg with tmp reg.
434 * The tmp reg will be later used as a src reg for computing
435 * the point scale factor.
437 inst
->Dst
[0].Register
.File
= TGSI_FILE_TEMPORARY
;
438 inst
->Dst
[0].Register
.Index
= ts
->point_size_tmp
;
439 ctx
->emit_instruction(ctx
, inst
);
441 /* Clamp the point size */
442 /* MAX point_size_tmp.x, point_size_tmp.x, point_imm.y */
443 tgsi_transform_op2_swz_inst(ctx
, TGSI_OPCODE_MAX
,
444 TGSI_FILE_TEMPORARY
, ts
->point_size_tmp
, TGSI_WRITEMASK_X
,
445 TGSI_FILE_TEMPORARY
, ts
->point_size_tmp
, TGSI_SWIZZLE_X
,
446 TGSI_FILE_IMMEDIATE
, ts
->point_imm
, TGSI_SWIZZLE_Y
, false);
448 /* MIN point_size_tmp.x, point_size_tmp.x, point_ivp.w */
449 tgsi_transform_op2_swz_inst(ctx
, TGSI_OPCODE_MIN
,
450 TGSI_FILE_TEMPORARY
, ts
->point_size_tmp
, TGSI_WRITEMASK_X
,
451 TGSI_FILE_TEMPORARY
, ts
->point_size_tmp
, TGSI_SWIZZLE_X
,
452 TGSI_FILE_CONSTANT
, ts
->point_ivp
, TGSI_SWIZZLE_W
, false);
454 else if (inst
->Dst
[0].Register
.File
== TGSI_FILE_OUTPUT
&&
455 inst
->Dst
[0].Register
.Index
== (int)ts
->point_pos_out
) {
457 * Replace point pos output reg with tmp reg.
459 inst
->Dst
[0].Register
.File
= TGSI_FILE_TEMPORARY
;
460 inst
->Dst
[0].Register
.Index
= ts
->point_pos_tmp
;
461 ctx
->emit_instruction(ctx
, inst
);
463 else if (inst
->Dst
[0].Register
.File
== TGSI_FILE_OUTPUT
) {
465 * Replace output reg with tmp reg.
467 inst
->Dst
[0].Register
.File
= TGSI_FILE_TEMPORARY
;
468 inst
->Dst
[0].Register
.Index
= ts
->out_tmp_index
[inst
->Dst
[0].Register
.Index
];
469 ctx
->emit_instruction(ctx
, inst
);
472 ctx
->emit_instruction(ctx
, inst
);
478 * TGSI property instruction transform callback.
479 * Transforms a point into a 4-vertex triangle strip.
482 psprite_property(struct tgsi_transform_context
*ctx
,
483 struct tgsi_full_property
*prop
)
485 switch (prop
->Property
.PropertyName
) {
486 case TGSI_PROPERTY_GS_OUTPUT_PRIM
:
487 prop
->u
[0].Data
= PIPE_PRIM_TRIANGLE_STRIP
;
489 case TGSI_PROPERTY_GS_MAX_OUTPUT_VERTICES
:
490 prop
->u
[0].Data
*= 4;
495 ctx
->emit_property(ctx
, prop
);
499 * TGSI utility to transform a geometry shader to support point sprite.
502 tgsi_add_point_sprite(const struct tgsi_token
*tokens_in
,
503 const unsigned point_coord_enable
,
504 const bool sprite_origin_lower_left
,
505 const bool stream_out_point_pos
,
506 int *aa_point_coord_index
)
508 struct psprite_transform_context transform
;
509 const uint num_new_tokens
= 200; /* should be enough */
510 const uint new_len
= tgsi_num_tokens(tokens_in
) + num_new_tokens
;
511 struct tgsi_token
*new_tokens
;
513 /* setup transformation context */
514 memset(&transform
, 0, sizeof(transform
));
515 transform
.base
.transform_declaration
= psprite_decl
;
516 transform
.base
.transform_instruction
= psprite_inst
;
517 transform
.base
.transform_property
= psprite_property
;
518 transform
.base
.transform_immediate
= psprite_immediate
;
519 transform
.base
.prolog
= psprite_prolog
;
521 transform
.point_size_in
= INVALID_INDEX
;
522 transform
.point_size_out
= INVALID_INDEX
;
523 transform
.point_size_tmp
= INVALID_INDEX
;
524 transform
.point_pos_in
= INVALID_INDEX
;
525 transform
.point_pos_out
= INVALID_INDEX
;
526 transform
.point_pos_sout
= INVALID_INDEX
;
527 transform
.point_pos_tmp
= INVALID_INDEX
;
528 transform
.point_scale_tmp
= INVALID_INDEX
;
529 transform
.point_imm
= INVALID_INDEX
;
530 transform
.point_coord_aa
= INVALID_INDEX
;
531 transform
.point_coord_k
= INVALID_INDEX
;
533 transform
.stream_out_point_pos
= stream_out_point_pos
;
534 transform
.point_coord_enable
= point_coord_enable
;
535 transform
.aa_point
= aa_point_coord_index
!= NULL
;
536 transform
.max_generic
= -1;
538 /* point sprite directions based on the immediates (0, 1, 0.5, -1) */
540 transform
.point_dir_swz
[0] = set_swizzle(-1, -1, 0, 0);
542 transform
.point_dir_swz
[1] = set_swizzle(-1, 1, 0, 0);
544 transform
.point_dir_swz
[2] = set_swizzle(1, -1, 0, 0);
546 transform
.point_dir_swz
[3] = set_swizzle(1, 1, 0, 0);
548 /* point coord based on the immediates (0, 1, 0, -1) */
549 if (sprite_origin_lower_left
) {
551 transform
.point_coord_swz
[0] = set_swizzle(0, 0, 0, 1);
553 transform
.point_coord_swz
[1] = set_swizzle(0, 1, 0, 1);
555 transform
.point_coord_swz
[2] = set_swizzle(1, 0, 0, 1);
557 transform
.point_coord_swz
[3] = set_swizzle(1, 1, 0, 1);
561 transform
.point_coord_swz
[0] = set_swizzle(0, 1, 0, 1);
563 transform
.point_coord_swz
[1] = set_swizzle(0, 0, 0, 1);
565 transform
.point_coord_swz
[2] = set_swizzle(1, 1, 0, 1);
567 transform
.point_coord_swz
[3] = set_swizzle(1, 0, 0, 1);
571 /* allocate new tokens buffer */
572 new_tokens
= tgsi_alloc_tokens(new_len
);
576 /* transform the shader */
577 tgsi_transform_shader(tokens_in
, new_tokens
, new_len
, &transform
.base
);
579 if (aa_point_coord_index
)
580 *aa_point_coord_index
= transform
.point_coord_aa
;