text: /**********************************************************
   * Copyright 2008-2009 VMware, Inc.  All rights reserved.
   *
   * Permission is hereby granted, free of charge, to any person
   * obtaining a copy of this software and associated documentation
   * files (the "Software"), to deal in the Software without
   * restriction, including without limitation the rights to use, copy,
   * modify, merge, publish, distribute, sublicense, and/or sell copies
   * of the Software, and to permit persons to whom the Software is
   * furnished to do so, subject to the following conditions:
   *
   * The above copyright notice and this permission notice shall be
   * included in all copies or substantial portions of the Software.
   *
   * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
   * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
   * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
   * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
   * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
   * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
   * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
   * SOFTWARE.
   *
   **********************************************************/
  
  #ifndef SVGA_TGSI_EMIT_H
  #define SVGA_TGSI_EMIT_H
  
  #include "tgsi/tgsi_scan.h"
  #include "svga_hw_reg.h"
  #include "svga_shader.h"
  #include "svga_tgsi.h"
  #include "svga3d_shaderdefs.h"
  
  struct src_register
  {
     SVGA3dShaderSrcToken base;
     SVGA3dShaderSrcToken indirect;
  };
  
  
  struct svga_arl_consts
  {
     int number;
     int idx;
     int swizzle;
     int arl_num;
  };
  
  
  /**
   * This is the context/state used during TGSI->SVGA shader translation.
   */
  struct svga_shader_emitter
  {
     unsigned size;
     char *buf;
     char *ptr;
  
     struct svga_compile_key key;
     struct tgsi_shader_info info;
     int unit;
  
     int imm_start;
  
     int nr_hw_float_const;
     int nr_hw_int_const;
     int nr_hw_temp;
  
     int insn_offset;
  
     int internal_temp_count;
     int internal_imm_count;
  
     int internal_color_idx[2]; /* diffuse, specular */
     int internal_color_count;
  
     boolean emitted_vface;
     boolean emit_frontface;
     int internal_frontface_idx;
  
     int ps30_input_count;
     int vs30_output_count;
  
     int dynamic_branching_level;
  
     unsigned num_output_writes;
     boolean constant_color_output;
  
     boolean in_main_func;
  
     boolean created_common_immediate;
     int common_immediate_idx[2];
  
     boolean created_loop_const;
     int loop_const_idx;
  
     unsigned inverted_texcoords;  /**< bitmask of which texcoords are flipped */
     struct src_register ps_true_texcoord[PIPE_MAX_ATTRIBS];
     struct src_register ps_inverted_texcoord[PIPE_MAX_ATTRIBS];
     unsigned ps_inverted_texcoord_input[PIPE_MAX_ATTRIBS];
  
     unsigned label[32];
     unsigned nr_labels;
  
     /** input/output register mappings, indexed by register number */
     struct src_register input_map[PIPE_MAX_ATTRIBS];
     SVGA3dShaderDestToken output_map[PIPE_MAX_ATTRIBS];
  
     boolean ps_reads_pos;
     boolean emitted_depth_fog;
     struct src_register ps_true_pos;
     struct src_register ps_depth_pos;
     SVGA3dShaderDestToken ps_temp_pos;
  
     /* shared input for depth and fog */
     struct src_register ps_depth_fog;
  
     struct src_register imm_0055;
     SVGA3dShaderDestToken temp_pos;
     SVGA3dShaderDestToken true_pos;
     SVGA3dShaderDestToken depth_pos;
  
     /* shared output for depth and fog */
     SVGA3dShaderDestToken vs_depth_fog;
  
     /* PS output colors (indexed by color semantic index) */
     SVGA3dShaderDestToken temp_color_output[PIPE_MAX_COLOR_BUFS];
     SVGA3dShaderDestToken true_color_output[PIPE_MAX_COLOR_BUFS];
  
     SVGA3dShaderDestToken temp_psiz;
     SVGA3dShaderDestToken true_psiz;
  
     struct svga_arl_consts arl_consts[12];
     int num_arl_consts;
     int current_arl;
  
     unsigned pstipple_sampler_unit;
  
     int num_samplers;
     uint8_t sampler_target[PIPE_MAX_SAMPLERS];
  };
  
  
  boolean
  svga_shader_emit_dword(struct svga_shader_emitter *emit, unsigned dword);
  
  boolean
  svga_shader_emit_dwords(struct svga_shader_emitter *emit,
                          const unsigned *dwords, unsigned nr);
  
  boolean
  svga_shader_emit_opcode(struct svga_shader_emitter *emit,
                          unsigned opcode);
  
  boolean
  svga_shader_emit_instructions(struct svga_shader_emitter *emit,
                                const struct tgsi_token *tokens);
  
  boolean
  svga_shader_emit_samplers_decl(struct svga_shader_emitter *emit);
  
  boolean
  svga_translate_decl_sm30(struct svga_shader_emitter *emit,
                           const struct tgsi_full_declaration *decl);
  
  
  #define TRANSLATE_SWIZZLE(x,y,z,w)  ((x) | ((y) << 2) | ((z) << 4) | ((w) << 6))
  #define SWIZZLE_XYZW  \
   TRANSLATE_SWIZZLE(TGSI_SWIZZLE_X,TGSI_SWIZZLE_Y,TGSI_SWIZZLE_Z,TGSI_SWIZZLE_W)
  #define SWIZZLE_XXXX  \
   TRANSLATE_SWIZZLE(TGSI_SWIZZLE_X,TGSI_SWIZZLE_X,TGSI_SWIZZLE_X,TGSI_SWIZZLE_X)
  #define SWIZZLE_YYYY  \
   TRANSLATE_SWIZZLE(TGSI_SWIZZLE_Y,TGSI_SWIZZLE_Y,TGSI_SWIZZLE_Y,TGSI_SWIZZLE_Y)
  #define SWIZZLE_ZZZZ  \
   TRANSLATE_SWIZZLE(TGSI_SWIZZLE_Z,TGSI_SWIZZLE_Z,TGSI_SWIZZLE_Z,TGSI_SWIZZLE_Z)
  #define SWIZZLE_WWWW  \
   TRANSLATE_SWIZZLE(TGSI_SWIZZLE_W,TGSI_SWIZZLE_W,TGSI_SWIZZLE_W,TGSI_SWIZZLE_W)
  
  
  /** Emit the given SVGA3dShaderInstToken opcode */
  static inline boolean
  emit_instruction(struct svga_shader_emitter *emit,
                   SVGA3dShaderInstToken opcode)
  {
     return svga_shader_emit_opcode(emit, opcode.value);
  }
  
  
  /** Generate a SVGA3dShaderInstToken for the given SVGA3D shader opcode */
  static inline SVGA3dShaderInstToken
  inst_token(SVGA3dShaderOpCodeType opcode)
  {
     SVGA3dShaderInstToken inst;
  
     inst.value = 0;
     inst.op = opcode;
  
     return inst;
  }
  
  
  /**
   * Generate a SVGA3dShaderInstToken for the given SVGA3D shader opcode
   * with the predication flag set.
   */
  static inline SVGA3dShaderInstToken
  inst_token_predicated(SVGA3dShaderOpCodeType opcode)
  {
     SVGA3dShaderInstToken inst;
  
     inst.value = 0;
     inst.op = opcode;
     inst.predicated = 1;
  
     return inst;
  }
  
  
  /**
   * Generate a SVGA3dShaderInstToken for a SETP instruction (set predicate)
   * using the given comparison operator (one of SVGA3DOPCOMP_xx).
   */
  static inline SVGA3dShaderInstToken
  inst_token_setp(SVGA3dShaderOpCodeCompFnType operator)
  {
     SVGA3dShaderInstToken inst;
  
     inst.value = 0;
     inst.op = SVGA3DOP_SETP;
     inst.control = operator;
  
     return inst;
  }
  
  
  /**
   * Create an instance of a SVGA3dShaderDestToken.
   * Note that this function is used to create tokens for output registers,
   * temp registers AND constants (see emit_def_const()).
   */
  static inline SVGA3dShaderDestToken
  dst_register(SVGA3dShaderRegType file, int number)
  {
     SVGA3dShaderDestToken dest;
  
     /* check values against bitfield sizes */
     assert(number < (1 << 11));
     assert(file <= SVGA3DREG_PREDICATE);
  
     dest.value = 0;
     dest.num = number;
     dest.type_upper = file >> 3;
     dest.relAddr = 0;
     dest.reserved1 = 0;
     dest.mask = 0xf;
     dest.dstMod = 0;
     dest.shfScale = 0;
     dest.type_lower = file & 0x7;
     dest.reserved0 = 1;          /* is_reg */
  
     return dest;
  }
  
  
  /**
   * Apply a writemask to the given SVGA3dShaderDestToken, returning a
   * new SVGA3dShaderDestToken.
   */
  static inline SVGA3dShaderDestToken
  writemask(SVGA3dShaderDestToken dest, unsigned mask)
  {
     assert(dest.mask & mask);
     dest.mask &= mask;
     return dest;
  }
  
  
  /** Create a SVGA3dShaderSrcToken given a register file and number */
  static inline SVGA3dShaderSrcToken
  src_token(SVGA3dShaderRegType file, int number)
  {
     SVGA3dShaderSrcToken src;
  
     /* check values against bitfield sizes */
     assert(number < (1 << 11));
     assert(file <= SVGA3DREG_PREDICATE);
  
     src.value = 0;
     src.num = number;
     src.type_upper = file >> 3;
     src.relAddr = 0;
     src.reserved1 = 0;
     src.swizzle = SWIZZLE_XYZW;
     src.srcMod = 0;
     src.type_lower = file & 0x7;
     src.reserved0 = 1;           /* is_reg */
  
     return src;
  }
  
  
  /** Create a src_register given a register file and register number */
  static inline struct src_register
  src_register(SVGA3dShaderRegType file, int number)
  {
     struct src_register src;
  
     src.base = src_token(file, number);
     src.indirect.value = 0;
  
     return src;
  }
  
  /** Translate src_register into SVGA3dShaderDestToken */
  static inline SVGA3dShaderDestToken
  dst(struct src_register src)
  {
     return dst_register(SVGA3dShaderGetRegType(src.base.value), src.base.num);
  }
  
  
  /** Translate SVGA3dShaderDestToken to a src_register */
  static inline struct src_register
  src(SVGA3dShaderDestToken dst)
  {
     return src_register(SVGA3dShaderGetRegType(dst.value), dst.num);
  }
  
  #endif
  