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