draw: use common exit path in pipeline finish.
[mesa.git] / src / gallium / auxiliary / tgsi / tgsi_ureg.h
1 /**************************************************************************
2 *
3 * Copyright 2009 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, INC 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_UREG_H
29 #define TGSI_UREG_H
30
31 #include "pipe/p_defines.h"
32 #include "pipe/p_format.h"
33 #include "pipe/p_compiler.h"
34 #include "pipe/p_shader_tokens.h"
35 #include "util/u_debug.h"
36
37 #ifdef __cplusplus
38 extern "C" {
39 #endif
40
41 struct pipe_screen;
42 struct ureg_program;
43 struct pipe_stream_output_info;
44
45 /* Almost a tgsi_src_register, but we need to pull in the Absolute
46 * flag from the _ext token. Indirect flag always implies ADDR[0].
47 */
48 struct ureg_src
49 {
50 unsigned File : 4; /* TGSI_FILE_ */
51 unsigned SwizzleX : 2; /* TGSI_SWIZZLE_ */
52 unsigned SwizzleY : 2; /* TGSI_SWIZZLE_ */
53 unsigned SwizzleZ : 2; /* TGSI_SWIZZLE_ */
54 unsigned SwizzleW : 2; /* TGSI_SWIZZLE_ */
55 unsigned Indirect : 1; /* BOOL */
56 unsigned DimIndirect : 1; /* BOOL */
57 unsigned Dimension : 1; /* BOOL */
58 unsigned Absolute : 1; /* BOOL */
59 unsigned Negate : 1; /* BOOL */
60 unsigned IndirectFile : 4; /* TGSI_FILE_ */
61 unsigned IndirectSwizzle : 2; /* TGSI_SWIZZLE_ */
62 unsigned DimIndFile : 4; /* TGSI_FILE_ */
63 unsigned DimIndSwizzle : 2; /* TGSI_SWIZZLE_ */
64 int Index : 16; /* SINT */
65 int IndirectIndex : 16; /* SINT */
66 int DimensionIndex : 16; /* SINT */
67 int DimIndIndex : 16; /* SINT */
68 unsigned ArrayID : 10; /* UINT */
69 };
70
71 /* Very similar to a tgsi_dst_register, removing unsupported fields
72 * and adding a Saturate flag. It's easier to push saturate into the
73 * destination register than to try and create a _SAT variant of each
74 * instruction function.
75 */
76 struct ureg_dst
77 {
78 unsigned File : 4; /* TGSI_FILE_ */
79 unsigned WriteMask : 4; /* TGSI_WRITEMASK_ */
80 unsigned Indirect : 1; /* BOOL */
81 unsigned DimIndirect : 1; /* BOOL */
82 unsigned Dimension : 1; /* BOOL */
83 unsigned Saturate : 1; /* BOOL */
84 unsigned Invariant : 1; /* BOOL */
85 int Index : 16; /* SINT */
86 int IndirectIndex : 16; /* SINT */
87 unsigned IndirectFile : 4; /* TGSI_FILE_ */
88 int IndirectSwizzle : 2; /* TGSI_SWIZZLE_ */
89 unsigned DimIndFile : 4; /* TGSI_FILE_ */
90 unsigned DimIndSwizzle : 2; /* TGSI_SWIZZLE_ */
91 int DimensionIndex : 16; /* SINT */
92 int DimIndIndex : 16; /* SINT */
93 unsigned ArrayID : 10; /* UINT */
94 };
95
96 struct pipe_context;
97
98 struct ureg_program *
99 ureg_create(enum pipe_shader_type processor);
100
101 struct ureg_program *
102 ureg_create_with_screen(enum pipe_shader_type processor,
103 struct pipe_screen *screen);
104
105 const struct tgsi_token *
106 ureg_finalize( struct ureg_program * );
107
108 /* Create and return a shader:
109 */
110 void *
111 ureg_create_shader( struct ureg_program *,
112 struct pipe_context *pipe,
113 const struct pipe_stream_output_info *so );
114
115 void
116 ureg_set_next_shader_processor(struct ureg_program *ureg, unsigned processor);
117
118 /* Alternately, return the built token stream and hand ownership of
119 * that memory to the caller:
120 */
121 const struct tgsi_token *
122 ureg_get_tokens( struct ureg_program *ureg,
123 unsigned *nr_tokens );
124
125 /*
126 * Returns the number of currently declared outputs.
127 */
128 unsigned
129 ureg_get_nr_outputs( const struct ureg_program *ureg );
130
131
132 /* Free the tokens created by ureg_get_tokens() */
133 void ureg_free_tokens( const struct tgsi_token *tokens );
134
135
136 void
137 ureg_destroy( struct ureg_program * );
138
139
140 /***********************************************************************
141 * Convenience routine:
142 */
143 static inline void *
144 ureg_create_shader_with_so_and_destroy( struct ureg_program *p,
145 struct pipe_context *pipe,
146 const struct pipe_stream_output_info *so )
147 {
148 void *result = ureg_create_shader( p, pipe, so );
149 ureg_destroy( p );
150 return result;
151 }
152
153 static inline void *
154 ureg_create_shader_and_destroy( struct ureg_program *p,
155 struct pipe_context *pipe )
156 {
157 return ureg_create_shader_with_so_and_destroy(p, pipe, NULL);
158 }
159
160
161 /***********************************************************************
162 * Build shader properties:
163 */
164
165 void
166 ureg_property(struct ureg_program *ureg, unsigned name, unsigned value);
167
168
169 /***********************************************************************
170 * Build shader declarations:
171 */
172
173 struct ureg_src
174 ureg_DECL_fs_input_cyl_centroid_layout(struct ureg_program *,
175 enum tgsi_semantic semantic_name,
176 unsigned semantic_index,
177 enum tgsi_interpolate_mode interp_mode,
178 unsigned cylindrical_wrap,
179 enum tgsi_interpolate_loc interp_location,
180 unsigned index,
181 unsigned usage_mask,
182 unsigned array_id,
183 unsigned array_size);
184
185 struct ureg_src
186 ureg_DECL_fs_input_cyl_centroid(struct ureg_program *,
187 enum tgsi_semantic semantic_name,
188 unsigned semantic_index,
189 enum tgsi_interpolate_mode interp_mode,
190 unsigned cylindrical_wrap,
191 enum tgsi_interpolate_loc interp_location,
192 unsigned array_id,
193 unsigned array_size);
194
195 static inline struct ureg_src
196 ureg_DECL_fs_input_cyl(struct ureg_program *ureg,
197 enum tgsi_semantic semantic_name,
198 unsigned semantic_index,
199 enum tgsi_interpolate_mode interp_mode,
200 unsigned cylindrical_wrap)
201 {
202 return ureg_DECL_fs_input_cyl_centroid(ureg,
203 semantic_name,
204 semantic_index,
205 interp_mode,
206 cylindrical_wrap,
207 TGSI_INTERPOLATE_LOC_CENTER, 0, 1);
208 }
209
210 static inline struct ureg_src
211 ureg_DECL_fs_input(struct ureg_program *ureg,
212 enum tgsi_semantic semantic_name,
213 unsigned semantic_index,
214 enum tgsi_interpolate_mode interp_mode)
215 {
216 return ureg_DECL_fs_input_cyl_centroid(ureg,
217 semantic_name,
218 semantic_index,
219 interp_mode,
220 0, TGSI_INTERPOLATE_LOC_CENTER, 0, 1);
221 }
222
223 struct ureg_src
224 ureg_DECL_vs_input( struct ureg_program *,
225 unsigned index );
226
227 struct ureg_src
228 ureg_DECL_input_layout(struct ureg_program *,
229 enum tgsi_semantic semantic_name,
230 unsigned semantic_index,
231 unsigned index,
232 unsigned usage_mask,
233 unsigned array_id,
234 unsigned array_size);
235
236 struct ureg_src
237 ureg_DECL_input(struct ureg_program *,
238 enum tgsi_semantic semantic_name,
239 unsigned semantic_index,
240 unsigned array_id,
241 unsigned array_size);
242
243 struct ureg_src
244 ureg_DECL_system_value(struct ureg_program *,
245 enum tgsi_semantic semantic_name,
246 unsigned semantic_index);
247
248 struct ureg_dst
249 ureg_DECL_output_layout(struct ureg_program *,
250 enum tgsi_semantic semantic_name,
251 unsigned semantic_index,
252 unsigned streams,
253 unsigned index,
254 unsigned usage_mask,
255 unsigned array_id,
256 unsigned array_size,
257 boolean invariant);
258
259 struct ureg_dst
260 ureg_DECL_output_masked(struct ureg_program *,
261 enum tgsi_semantic semantic_name,
262 unsigned semantic_index,
263 unsigned usage_mask,
264 unsigned array_id,
265 unsigned array_size);
266
267 struct ureg_dst
268 ureg_DECL_output(struct ureg_program *,
269 enum tgsi_semantic semantic_name,
270 unsigned semantic_index);
271
272 struct ureg_dst
273 ureg_DECL_output_array(struct ureg_program *ureg,
274 enum tgsi_semantic semantic_name,
275 unsigned semantic_index,
276 unsigned array_id,
277 unsigned array_size);
278
279 struct ureg_src
280 ureg_DECL_immediate( struct ureg_program *,
281 const float *v,
282 unsigned nr );
283
284 struct ureg_src
285 ureg_DECL_immediate_f64( struct ureg_program *,
286 const double *v,
287 unsigned nr );
288
289 struct ureg_src
290 ureg_DECL_immediate_uint( struct ureg_program *,
291 const unsigned *v,
292 unsigned nr );
293
294 struct ureg_src
295 ureg_DECL_immediate_block_uint( struct ureg_program *,
296 const unsigned *v,
297 unsigned nr );
298
299 struct ureg_src
300 ureg_DECL_immediate_int( struct ureg_program *,
301 const int *v,
302 unsigned nr );
303
304 struct ureg_src
305 ureg_DECL_immediate_uint64( struct ureg_program *,
306 const uint64_t *v,
307 unsigned nr );
308
309 struct ureg_src
310 ureg_DECL_immediate_int64( struct ureg_program *,
311 const int64_t *v,
312 unsigned nr );
313
314 void
315 ureg_DECL_constant2D(struct ureg_program *ureg,
316 unsigned first,
317 unsigned last,
318 unsigned index2D);
319
320 struct ureg_src
321 ureg_DECL_constant( struct ureg_program *,
322 unsigned index );
323
324 void
325 ureg_DECL_hw_atomic(struct ureg_program *ureg,
326 unsigned first,
327 unsigned last,
328 unsigned buffer_id,
329 unsigned array_id);
330
331 struct ureg_dst
332 ureg_DECL_temporary( struct ureg_program * );
333
334 /**
335 * Emit a temporary with the LOCAL declaration flag set. For use when
336 * the register value is not required to be preserved across
337 * subroutine boundaries.
338 */
339 struct ureg_dst
340 ureg_DECL_local_temporary( struct ureg_program * );
341
342 /**
343 * Declare "size" continuous temporary registers.
344 */
345 struct ureg_dst
346 ureg_DECL_array_temporary( struct ureg_program *,
347 unsigned size,
348 boolean local );
349
350 void
351 ureg_release_temporary( struct ureg_program *ureg,
352 struct ureg_dst tmp );
353
354 struct ureg_dst
355 ureg_DECL_address( struct ureg_program * );
356
357 /* Supply an index to the sampler declaration as this is the hook to
358 * the external pipe_sampler state. Users of this function probably
359 * don't want just any sampler, but a specific one which they've set
360 * up state for in the context.
361 */
362 struct ureg_src
363 ureg_DECL_sampler( struct ureg_program *,
364 unsigned index );
365
366 struct ureg_src
367 ureg_DECL_sampler_view(struct ureg_program *,
368 unsigned index,
369 enum tgsi_texture_type target,
370 enum tgsi_return_type return_type_x,
371 enum tgsi_return_type return_type_y,
372 enum tgsi_return_type return_type_z,
373 enum tgsi_return_type return_type_w );
374
375 struct ureg_src
376 ureg_DECL_image(struct ureg_program *ureg,
377 unsigned index,
378 enum tgsi_texture_type target,
379 enum pipe_format format,
380 boolean wr,
381 boolean raw);
382
383 struct ureg_src
384 ureg_DECL_buffer(struct ureg_program *ureg, unsigned nr, bool atomic);
385
386 struct ureg_src
387 ureg_DECL_memory(struct ureg_program *ureg, unsigned memory_type);
388
389 static inline struct ureg_src
390 ureg_imm4f( struct ureg_program *ureg,
391 float a, float b,
392 float c, float d)
393 {
394 float v[4];
395 v[0] = a;
396 v[1] = b;
397 v[2] = c;
398 v[3] = d;
399 return ureg_DECL_immediate( ureg, v, 4 );
400 }
401
402 static inline struct ureg_src
403 ureg_imm3f( struct ureg_program *ureg,
404 float a, float b,
405 float c)
406 {
407 float v[3];
408 v[0] = a;
409 v[1] = b;
410 v[2] = c;
411 return ureg_DECL_immediate( ureg, v, 3 );
412 }
413
414 static inline struct ureg_src
415 ureg_imm2f( struct ureg_program *ureg,
416 float a, float b)
417 {
418 float v[2];
419 v[0] = a;
420 v[1] = b;
421 return ureg_DECL_immediate( ureg, v, 2 );
422 }
423
424 static inline struct ureg_src
425 ureg_imm1f( struct ureg_program *ureg,
426 float a)
427 {
428 float v[1];
429 v[0] = a;
430 return ureg_DECL_immediate( ureg, v, 1 );
431 }
432
433 static inline struct ureg_src
434 ureg_imm4u( struct ureg_program *ureg,
435 unsigned a, unsigned b,
436 unsigned c, unsigned d)
437 {
438 unsigned v[4];
439 v[0] = a;
440 v[1] = b;
441 v[2] = c;
442 v[3] = d;
443 return ureg_DECL_immediate_uint( ureg, v, 4 );
444 }
445
446 static inline struct ureg_src
447 ureg_imm3u( struct ureg_program *ureg,
448 unsigned a, unsigned b,
449 unsigned c)
450 {
451 unsigned v[3];
452 v[0] = a;
453 v[1] = b;
454 v[2] = c;
455 return ureg_DECL_immediate_uint( ureg, v, 3 );
456 }
457
458 static inline struct ureg_src
459 ureg_imm2u( struct ureg_program *ureg,
460 unsigned a, unsigned b)
461 {
462 unsigned v[2];
463 v[0] = a;
464 v[1] = b;
465 return ureg_DECL_immediate_uint( ureg, v, 2 );
466 }
467
468 static inline struct ureg_src
469 ureg_imm1u( struct ureg_program *ureg,
470 unsigned a)
471 {
472 return ureg_DECL_immediate_uint( ureg, &a, 1 );
473 }
474
475 static inline struct ureg_src
476 ureg_imm4i( struct ureg_program *ureg,
477 int a, int b,
478 int c, int d)
479 {
480 int v[4];
481 v[0] = a;
482 v[1] = b;
483 v[2] = c;
484 v[3] = d;
485 return ureg_DECL_immediate_int( ureg, v, 4 );
486 }
487
488 static inline struct ureg_src
489 ureg_imm3i( struct ureg_program *ureg,
490 int a, int b,
491 int c)
492 {
493 int v[3];
494 v[0] = a;
495 v[1] = b;
496 v[2] = c;
497 return ureg_DECL_immediate_int( ureg, v, 3 );
498 }
499
500 static inline struct ureg_src
501 ureg_imm2i( struct ureg_program *ureg,
502 int a, int b)
503 {
504 int v[2];
505 v[0] = a;
506 v[1] = b;
507 return ureg_DECL_immediate_int( ureg, v, 2 );
508 }
509
510 static inline struct ureg_src
511 ureg_imm1i( struct ureg_program *ureg,
512 int a)
513 {
514 return ureg_DECL_immediate_int( ureg, &a, 1 );
515 }
516
517 /* Where the destination register has a valid file, but an empty
518 * writemask.
519 */
520 static inline boolean
521 ureg_dst_is_empty( struct ureg_dst dst )
522 {
523 return dst.File != TGSI_FILE_NULL &&
524 dst.WriteMask == 0;
525 }
526
527 /***********************************************************************
528 * Functions for patching up labels
529 */
530
531
532 /* Will return a number which can be used in a label to point to the
533 * next instruction to be emitted.
534 */
535 unsigned
536 ureg_get_instruction_number( struct ureg_program *ureg );
537
538
539 /* Patch a given label (expressed as a token number) to point to a
540 * given instruction (expressed as an instruction number).
541 *
542 * Labels are obtained from instruction emitters, eg ureg_CAL().
543 * Instruction numbers are obtained from ureg_get_instruction_number(),
544 * above.
545 */
546 void
547 ureg_fixup_label(struct ureg_program *ureg,
548 unsigned label_token,
549 unsigned instruction_number );
550
551
552 /* Generic instruction emitter. Use if you need to pass the opcode as
553 * a parameter, rather than using the emit_OP() variants below.
554 */
555 void
556 ureg_insn(struct ureg_program *ureg,
557 enum tgsi_opcode opcode,
558 const struct ureg_dst *dst,
559 unsigned nr_dst,
560 const struct ureg_src *src,
561 unsigned nr_src,
562 unsigned precise );
563
564
565 void
566 ureg_tex_insn(struct ureg_program *ureg,
567 enum tgsi_opcode opcode,
568 const struct ureg_dst *dst,
569 unsigned nr_dst,
570 enum tgsi_texture_type target,
571 enum tgsi_return_type return_type,
572 const struct tgsi_texture_offset *texoffsets,
573 unsigned nr_offset,
574 const struct ureg_src *src,
575 unsigned nr_src );
576
577
578 void
579 ureg_memory_insn(struct ureg_program *ureg,
580 enum tgsi_opcode opcode,
581 const struct ureg_dst *dst,
582 unsigned nr_dst,
583 const struct ureg_src *src,
584 unsigned nr_src,
585 unsigned qualifier,
586 enum tgsi_texture_type texture,
587 enum pipe_format format);
588
589 /***********************************************************************
590 * Internal instruction helpers, don't call these directly:
591 */
592
593 struct ureg_emit_insn_result {
594 unsigned insn_token; /*< Used to fixup insn size. */
595 unsigned extended_token; /*< Used to set the Extended bit, usually the same as insn_token. */
596 };
597
598 struct ureg_emit_insn_result
599 ureg_emit_insn(struct ureg_program *ureg,
600 enum tgsi_opcode opcode,
601 boolean saturate,
602 unsigned precise,
603 unsigned num_dst,
604 unsigned num_src);
605
606 void
607 ureg_emit_label(struct ureg_program *ureg,
608 unsigned insn_token,
609 unsigned *label_token );
610
611 void
612 ureg_emit_texture(struct ureg_program *ureg,
613 unsigned insn_token,
614 enum tgsi_texture_type target,
615 enum tgsi_return_type return_type,
616 unsigned num_offsets);
617
618 void
619 ureg_emit_texture_offset(struct ureg_program *ureg,
620 const struct tgsi_texture_offset *offset);
621
622 void
623 ureg_emit_memory(struct ureg_program *ureg,
624 unsigned insn_token,
625 unsigned qualifier,
626 enum tgsi_texture_type texture,
627 enum pipe_format format);
628
629 void
630 ureg_emit_dst( struct ureg_program *ureg,
631 struct ureg_dst dst );
632
633 void
634 ureg_emit_src( struct ureg_program *ureg,
635 struct ureg_src src );
636
637 void
638 ureg_fixup_insn_size(struct ureg_program *ureg,
639 unsigned insn );
640
641
642 #define OP00( op ) \
643 static inline void ureg_##op( struct ureg_program *ureg ) \
644 { \
645 enum tgsi_opcode opcode = TGSI_OPCODE_##op; \
646 struct ureg_emit_insn_result insn; \
647 insn = ureg_emit_insn(ureg, \
648 opcode, \
649 FALSE, \
650 0, \
651 0, \
652 0); \
653 ureg_fixup_insn_size( ureg, insn.insn_token ); \
654 }
655
656 #define OP01( op ) \
657 static inline void ureg_##op( struct ureg_program *ureg, \
658 struct ureg_src src ) \
659 { \
660 enum tgsi_opcode opcode = TGSI_OPCODE_##op; \
661 struct ureg_emit_insn_result insn; \
662 insn = ureg_emit_insn(ureg, \
663 opcode, \
664 FALSE, \
665 0, \
666 0, \
667 1); \
668 ureg_emit_src( ureg, src ); \
669 ureg_fixup_insn_size( ureg, insn.insn_token ); \
670 }
671
672 #define OP00_LBL( op ) \
673 static inline void ureg_##op( struct ureg_program *ureg, \
674 unsigned *label_token ) \
675 { \
676 enum tgsi_opcode opcode = TGSI_OPCODE_##op; \
677 struct ureg_emit_insn_result insn; \
678 insn = ureg_emit_insn(ureg, \
679 opcode, \
680 FALSE, \
681 0, \
682 0, \
683 0); \
684 ureg_emit_label( ureg, insn.extended_token, label_token ); \
685 ureg_fixup_insn_size( ureg, insn.insn_token ); \
686 }
687
688 #define OP01_LBL( op ) \
689 static inline void ureg_##op( struct ureg_program *ureg, \
690 struct ureg_src src, \
691 unsigned *label_token ) \
692 { \
693 enum tgsi_opcode opcode = TGSI_OPCODE_##op; \
694 struct ureg_emit_insn_result insn; \
695 insn = ureg_emit_insn(ureg, \
696 opcode, \
697 FALSE, \
698 0, \
699 0, \
700 1); \
701 ureg_emit_label( ureg, insn.extended_token, label_token ); \
702 ureg_emit_src( ureg, src ); \
703 ureg_fixup_insn_size( ureg, insn.insn_token ); \
704 }
705
706 #define OP10( op ) \
707 static inline void ureg_##op( struct ureg_program *ureg, \
708 struct ureg_dst dst ) \
709 { \
710 enum tgsi_opcode opcode = TGSI_OPCODE_##op; \
711 struct ureg_emit_insn_result insn; \
712 if (ureg_dst_is_empty(dst)) \
713 return; \
714 insn = ureg_emit_insn(ureg, \
715 opcode, \
716 dst.Saturate, \
717 0, \
718 1, \
719 0); \
720 ureg_emit_dst( ureg, dst ); \
721 ureg_fixup_insn_size( ureg, insn.insn_token ); \
722 }
723
724
725 #define OP11( op ) \
726 static inline void ureg_##op( struct ureg_program *ureg, \
727 struct ureg_dst dst, \
728 struct ureg_src src ) \
729 { \
730 enum tgsi_opcode opcode = TGSI_OPCODE_##op; \
731 struct ureg_emit_insn_result insn; \
732 if (ureg_dst_is_empty(dst)) \
733 return; \
734 insn = ureg_emit_insn(ureg, \
735 opcode, \
736 dst.Saturate, \
737 0, \
738 1, \
739 1); \
740 ureg_emit_dst( ureg, dst ); \
741 ureg_emit_src( ureg, src ); \
742 ureg_fixup_insn_size( ureg, insn.insn_token ); \
743 }
744
745 #define OP12( op ) \
746 static inline void ureg_##op( struct ureg_program *ureg, \
747 struct ureg_dst dst, \
748 struct ureg_src src0, \
749 struct ureg_src src1 ) \
750 { \
751 enum tgsi_opcode opcode = TGSI_OPCODE_##op; \
752 struct ureg_emit_insn_result insn; \
753 if (ureg_dst_is_empty(dst)) \
754 return; \
755 insn = ureg_emit_insn(ureg, \
756 opcode, \
757 dst.Saturate, \
758 0, \
759 1, \
760 2); \
761 ureg_emit_dst( ureg, dst ); \
762 ureg_emit_src( ureg, src0 ); \
763 ureg_emit_src( ureg, src1 ); \
764 ureg_fixup_insn_size( ureg, insn.insn_token ); \
765 }
766
767 #define OP12_TEX( op ) \
768 static inline void ureg_##op( struct ureg_program *ureg, \
769 struct ureg_dst dst, \
770 enum tgsi_texture_type target, \
771 struct ureg_src src0, \
772 struct ureg_src src1 ) \
773 { \
774 enum tgsi_opcode opcode = TGSI_OPCODE_##op; \
775 enum tgsi_return_type return_type = TGSI_RETURN_TYPE_UNKNOWN; \
776 struct ureg_emit_insn_result insn; \
777 if (ureg_dst_is_empty(dst)) \
778 return; \
779 insn = ureg_emit_insn(ureg, \
780 opcode, \
781 dst.Saturate, \
782 0, \
783 1, \
784 2); \
785 ureg_emit_texture( ureg, insn.extended_token, target, \
786 return_type, 0 ); \
787 ureg_emit_dst( ureg, dst ); \
788 ureg_emit_src( ureg, src0 ); \
789 ureg_emit_src( ureg, src1 ); \
790 ureg_fixup_insn_size( ureg, insn.insn_token ); \
791 }
792
793 #define OP13( op ) \
794 static inline void ureg_##op( struct ureg_program *ureg, \
795 struct ureg_dst dst, \
796 struct ureg_src src0, \
797 struct ureg_src src1, \
798 struct ureg_src src2 ) \
799 { \
800 enum tgsi_opcode opcode = TGSI_OPCODE_##op; \
801 struct ureg_emit_insn_result insn; \
802 if (ureg_dst_is_empty(dst)) \
803 return; \
804 insn = ureg_emit_insn(ureg, \
805 opcode, \
806 dst.Saturate, \
807 0, \
808 1, \
809 3); \
810 ureg_emit_dst( ureg, dst ); \
811 ureg_emit_src( ureg, src0 ); \
812 ureg_emit_src( ureg, src1 ); \
813 ureg_emit_src( ureg, src2 ); \
814 ureg_fixup_insn_size( ureg, insn.insn_token ); \
815 }
816
817 #define OP14_TEX( op ) \
818 static inline void ureg_##op( struct ureg_program *ureg, \
819 struct ureg_dst dst, \
820 enum tgsi_texture_type target, \
821 struct ureg_src src0, \
822 struct ureg_src src1, \
823 struct ureg_src src2, \
824 struct ureg_src src3 ) \
825 { \
826 enum tgsi_opcode opcode = TGSI_OPCODE_##op; \
827 enum tgsi_return_type return_type = TGSI_RETURN_TYPE_UNKNOWN; \
828 struct ureg_emit_insn_result insn; \
829 if (ureg_dst_is_empty(dst)) \
830 return; \
831 insn = ureg_emit_insn(ureg, \
832 opcode, \
833 dst.Saturate, \
834 0, \
835 1, \
836 4); \
837 ureg_emit_texture( ureg, insn.extended_token, target, \
838 return_type, 0 ); \
839 ureg_emit_dst( ureg, dst ); \
840 ureg_emit_src( ureg, src0 ); \
841 ureg_emit_src( ureg, src1 ); \
842 ureg_emit_src( ureg, src2 ); \
843 ureg_emit_src( ureg, src3 ); \
844 ureg_fixup_insn_size( ureg, insn.insn_token ); \
845 }
846
847 /* Use a template include to generate a correctly-typed ureg_OP()
848 * function for each TGSI opcode:
849 */
850 #include "tgsi_opcode_tmp.h"
851
852
853 /***********************************************************************
854 * Inline helpers for manipulating register structs:
855 */
856 static inline struct ureg_src
857 ureg_negate( struct ureg_src reg )
858 {
859 assert(reg.File != TGSI_FILE_NULL);
860 reg.Negate ^= 1;
861 return reg;
862 }
863
864 static inline struct ureg_src
865 ureg_abs( struct ureg_src reg )
866 {
867 assert(reg.File != TGSI_FILE_NULL);
868 reg.Absolute = 1;
869 reg.Negate = 0;
870 return reg;
871 }
872
873 static inline struct ureg_src
874 ureg_swizzle( struct ureg_src reg,
875 int x, int y, int z, int w )
876 {
877 unsigned swz = ( (reg.SwizzleX << 0) |
878 (reg.SwizzleY << 2) |
879 (reg.SwizzleZ << 4) |
880 (reg.SwizzleW << 6));
881
882 assert(reg.File != TGSI_FILE_NULL);
883 assert(x < 4);
884 assert(y < 4);
885 assert(z < 4);
886 assert(w < 4);
887
888 reg.SwizzleX = (swz >> (x*2)) & 0x3;
889 reg.SwizzleY = (swz >> (y*2)) & 0x3;
890 reg.SwizzleZ = (swz >> (z*2)) & 0x3;
891 reg.SwizzleW = (swz >> (w*2)) & 0x3;
892 return reg;
893 }
894
895 static inline struct ureg_src
896 ureg_scalar( struct ureg_src reg, int x )
897 {
898 return ureg_swizzle(reg, x, x, x, x);
899 }
900
901 static inline struct ureg_dst
902 ureg_writemask( struct ureg_dst reg,
903 unsigned writemask )
904 {
905 assert(reg.File != TGSI_FILE_NULL);
906 reg.WriteMask &= writemask;
907 return reg;
908 }
909
910 static inline struct ureg_dst
911 ureg_saturate( struct ureg_dst reg )
912 {
913 assert(reg.File != TGSI_FILE_NULL);
914 reg.Saturate = 1;
915 return reg;
916 }
917
918 static inline struct ureg_dst
919 ureg_dst_indirect( struct ureg_dst reg, struct ureg_src addr )
920 {
921 assert(reg.File != TGSI_FILE_NULL);
922 reg.Indirect = 1;
923 reg.IndirectFile = addr.File;
924 reg.IndirectIndex = addr.Index;
925 reg.IndirectSwizzle = addr.SwizzleX;
926 return reg;
927 }
928
929 static inline struct ureg_src
930 ureg_src_indirect( struct ureg_src reg, struct ureg_src addr )
931 {
932 assert(reg.File != TGSI_FILE_NULL);
933 reg.Indirect = 1;
934 reg.IndirectFile = addr.File;
935 reg.IndirectIndex = addr.Index;
936 reg.IndirectSwizzle = addr.SwizzleX;
937 return reg;
938 }
939
940 static inline struct ureg_dst
941 ureg_dst_dimension( struct ureg_dst reg, int index )
942 {
943 assert(reg.File != TGSI_FILE_NULL);
944 reg.Dimension = 1;
945 reg.DimIndirect = 0;
946 reg.DimensionIndex = index;
947 return reg;
948 }
949
950 static inline struct ureg_src
951 ureg_src_dimension( struct ureg_src reg, int index )
952 {
953 assert(reg.File != TGSI_FILE_NULL);
954 reg.Dimension = 1;
955 reg.DimIndirect = 0;
956 reg.DimensionIndex = index;
957 return reg;
958 }
959
960 static inline struct ureg_dst
961 ureg_dst_dimension_indirect( struct ureg_dst reg, struct ureg_src addr,
962 int index )
963 {
964 assert(reg.File != TGSI_FILE_NULL);
965 reg.Dimension = 1;
966 reg.DimIndirect = 1;
967 reg.DimensionIndex = index;
968 reg.DimIndFile = addr.File;
969 reg.DimIndIndex = addr.Index;
970 reg.DimIndSwizzle = addr.SwizzleX;
971 return reg;
972 }
973
974 static inline struct ureg_src
975 ureg_src_dimension_indirect( struct ureg_src reg, struct ureg_src addr,
976 int index )
977 {
978 assert(reg.File != TGSI_FILE_NULL);
979 reg.Dimension = 1;
980 reg.DimIndirect = 1;
981 reg.DimensionIndex = index;
982 reg.DimIndFile = addr.File;
983 reg.DimIndIndex = addr.Index;
984 reg.DimIndSwizzle = addr.SwizzleX;
985 return reg;
986 }
987
988 static inline struct ureg_src
989 ureg_src_array_offset(struct ureg_src reg, int offset)
990 {
991 reg.Index += offset;
992 return reg;
993 }
994
995 static inline struct ureg_dst
996 ureg_dst_array_offset( struct ureg_dst reg, int offset )
997 {
998 reg.Index += offset;
999 return reg;
1000 }
1001
1002 static inline struct ureg_dst
1003 ureg_dst_array_register(unsigned file,
1004 unsigned index,
1005 unsigned array_id)
1006 {
1007 struct ureg_dst dst;
1008
1009 dst.File = file;
1010 dst.WriteMask = TGSI_WRITEMASK_XYZW;
1011 dst.Indirect = 0;
1012 dst.IndirectFile = TGSI_FILE_NULL;
1013 dst.IndirectIndex = 0;
1014 dst.IndirectSwizzle = 0;
1015 dst.Saturate = 0;
1016 dst.Index = index;
1017 dst.Dimension = 0;
1018 dst.DimensionIndex = 0;
1019 dst.DimIndirect = 0;
1020 dst.DimIndFile = TGSI_FILE_NULL;
1021 dst.DimIndIndex = 0;
1022 dst.DimIndSwizzle = 0;
1023 dst.ArrayID = array_id;
1024 dst.Invariant = 0;
1025
1026 return dst;
1027 }
1028
1029 static inline struct ureg_dst
1030 ureg_dst_register(unsigned file,
1031 unsigned index)
1032 {
1033 return ureg_dst_array_register(file, index, 0);
1034 }
1035
1036 static inline struct ureg_dst
1037 ureg_dst( struct ureg_src src )
1038 {
1039 struct ureg_dst dst;
1040
1041 dst.File = src.File;
1042 dst.WriteMask = TGSI_WRITEMASK_XYZW;
1043 dst.IndirectFile = src.IndirectFile;
1044 dst.Indirect = src.Indirect;
1045 dst.IndirectIndex = src.IndirectIndex;
1046 dst.IndirectSwizzle = src.IndirectSwizzle;
1047 dst.Saturate = 0;
1048 dst.Index = src.Index;
1049 dst.Dimension = src.Dimension;
1050 dst.DimensionIndex = src.DimensionIndex;
1051 dst.DimIndirect = src.DimIndirect;
1052 dst.DimIndFile = src.DimIndFile;
1053 dst.DimIndIndex = src.DimIndIndex;
1054 dst.DimIndSwizzle = src.DimIndSwizzle;
1055 dst.ArrayID = src.ArrayID;
1056 dst.Invariant = 0;
1057
1058 return dst;
1059 }
1060
1061 static inline struct ureg_src
1062 ureg_src_array_register(unsigned file,
1063 unsigned index,
1064 unsigned array_id)
1065 {
1066 struct ureg_src src;
1067
1068 src.File = file;
1069 src.SwizzleX = TGSI_SWIZZLE_X;
1070 src.SwizzleY = TGSI_SWIZZLE_Y;
1071 src.SwizzleZ = TGSI_SWIZZLE_Z;
1072 src.SwizzleW = TGSI_SWIZZLE_W;
1073 src.Indirect = 0;
1074 src.IndirectFile = TGSI_FILE_NULL;
1075 src.IndirectIndex = 0;
1076 src.IndirectSwizzle = 0;
1077 src.Absolute = 0;
1078 src.Index = index;
1079 src.Negate = 0;
1080 src.Dimension = 0;
1081 src.DimensionIndex = 0;
1082 src.DimIndirect = 0;
1083 src.DimIndFile = TGSI_FILE_NULL;
1084 src.DimIndIndex = 0;
1085 src.DimIndSwizzle = 0;
1086 src.ArrayID = array_id;
1087
1088 return src;
1089 }
1090
1091 static inline struct ureg_src
1092 ureg_src_register(unsigned file,
1093 unsigned index)
1094 {
1095 return ureg_src_array_register(file, index, 0);
1096 }
1097
1098 static inline struct ureg_src
1099 ureg_src( struct ureg_dst dst )
1100 {
1101 struct ureg_src src;
1102
1103 src.File = dst.File;
1104 src.SwizzleX = TGSI_SWIZZLE_X;
1105 src.SwizzleY = TGSI_SWIZZLE_Y;
1106 src.SwizzleZ = TGSI_SWIZZLE_Z;
1107 src.SwizzleW = TGSI_SWIZZLE_W;
1108 src.Indirect = dst.Indirect;
1109 src.IndirectFile = dst.IndirectFile;
1110 src.IndirectIndex = dst.IndirectIndex;
1111 src.IndirectSwizzle = dst.IndirectSwizzle;
1112 src.Absolute = 0;
1113 src.Index = dst.Index;
1114 src.Negate = 0;
1115 src.Dimension = dst.Dimension;
1116 src.DimensionIndex = dst.DimensionIndex;
1117 src.DimIndirect = dst.DimIndirect;
1118 src.DimIndFile = dst.DimIndFile;
1119 src.DimIndIndex = dst.DimIndIndex;
1120 src.DimIndSwizzle = dst.DimIndSwizzle;
1121 src.ArrayID = dst.ArrayID;
1122
1123 return src;
1124 }
1125
1126
1127
1128 static inline struct ureg_dst
1129 ureg_dst_undef( void )
1130 {
1131 struct ureg_dst dst;
1132
1133 dst.File = TGSI_FILE_NULL;
1134 dst.WriteMask = 0;
1135 dst.Indirect = 0;
1136 dst.IndirectFile = TGSI_FILE_NULL;
1137 dst.IndirectIndex = 0;
1138 dst.IndirectSwizzle = 0;
1139 dst.Saturate = 0;
1140 dst.Index = 0;
1141 dst.Dimension = 0;
1142 dst.DimensionIndex = 0;
1143 dst.DimIndirect = 0;
1144 dst.DimIndFile = TGSI_FILE_NULL;
1145 dst.DimIndIndex = 0;
1146 dst.DimIndSwizzle = 0;
1147 dst.ArrayID = 0;
1148 dst.Invariant = 0;
1149
1150 return dst;
1151 }
1152
1153 static inline struct ureg_src
1154 ureg_src_undef( void )
1155 {
1156 struct ureg_src src;
1157
1158 src.File = TGSI_FILE_NULL;
1159 src.SwizzleX = 0;
1160 src.SwizzleY = 0;
1161 src.SwizzleZ = 0;
1162 src.SwizzleW = 0;
1163 src.Indirect = 0;
1164 src.IndirectFile = TGSI_FILE_NULL;
1165 src.IndirectIndex = 0;
1166 src.IndirectSwizzle = 0;
1167 src.Absolute = 0;
1168 src.Index = 0;
1169 src.Negate = 0;
1170 src.Dimension = 0;
1171 src.DimensionIndex = 0;
1172 src.DimIndirect = 0;
1173 src.DimIndFile = TGSI_FILE_NULL;
1174 src.DimIndIndex = 0;
1175 src.DimIndSwizzle = 0;
1176 src.ArrayID = 0;
1177
1178 return src;
1179 }
1180
1181 static inline boolean
1182 ureg_src_is_undef( struct ureg_src src )
1183 {
1184 return src.File == TGSI_FILE_NULL;
1185 }
1186
1187 static inline boolean
1188 ureg_dst_is_undef( struct ureg_dst dst )
1189 {
1190 return dst.File == TGSI_FILE_NULL;
1191 }
1192
1193
1194 #ifdef __cplusplus
1195 }
1196 #endif
1197
1198 #endif