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