示例#1
0
static void precalc_lit( struct brw_wm_compile *c,
			 const struct prog_instruction *inst )
{
   struct prog_src_register src0 = inst->SrcReg[0];
   struct prog_dst_register dst = inst->DstReg;
   
   if (dst.WriteMask & WRITEMASK_XW) {
      struct prog_instruction *swz;

      /* dst.xw = swz src0.1111
       */
      swz = emit_op(c,
		    OPCODE_SWZ,
		    dst_mask(dst, WRITEMASK_XW),
		    0,
		    src_swizzle1(src0, SWIZZLE_ONE),
		    src_undef(),
		    src_undef());
      /* Avoid letting the negation flag of src0 affect our 1 constant. */
      swz->SrcReg[0].Negate = NEGATE_NONE;
   }

   if (dst.WriteMask & WRITEMASK_YZ) {
      emit_op(c,
	      OPCODE_LIT,
	      dst_mask(dst, WRITEMASK_YZ),
	      inst->SaturateMode,
	      src0,
	      src_undef(),
	      src_undef());
   }
}
示例#2
0
/* Many Mesa opcodes produce the same value across all the result channels.
 * We'd rather not have to support that splatting in the opcode implementations,
 * and brw_wm_pass*.c wants to optimize them out by shuffling references around
 * anyway.  We can easily get both by emitting the opcode to one channel, and
 * then MOVing it to the others, which brw_wm_pass*.c already understands.
 */
static struct prog_instruction *emit_scalar_insn(struct brw_wm_compile *c,
						 const struct prog_instruction *inst0)
{
   struct prog_instruction *inst;
   unsigned int dst_chan;
   unsigned int other_channel_mask;

   if (inst0->DstReg.WriteMask == 0)
      return NULL;

   dst_chan = _mesa_ffs(inst0->DstReg.WriteMask) - 1;
   inst = get_fp_inst(c);
   *inst = *inst0;
   inst->DstReg.WriteMask = 1 << dst_chan;

   other_channel_mask = inst0->DstReg.WriteMask & ~(1 << dst_chan);
   if (other_channel_mask != 0) {
      inst = emit_op(c,
		     OPCODE_MOV,
		     dst_mask(inst0->DstReg, other_channel_mask),
		     0,
		     src_swizzle1(src_reg_from_dst(inst0->DstReg), dst_chan),
		     src_undef(),
		     src_undef());
   }
   return inst;
}
示例#3
0
static void precalc_lit( struct brw_wm_compile *c,
			 const struct prog_instruction *inst )
{
   struct prog_src_register src0 = inst->SrcReg[0];
   struct prog_dst_register dst = inst->DstReg;
   
   if (dst.WriteMask & WRITEMASK_XW) {
      /* dst.xw = swz src0.1111
       */
      emit_op(c,
	      OPCODE_SWZ,
	      dst_mask(dst, WRITEMASK_XW),
	      0, 0, 0,
	      src_swizzle1(src0, SWIZZLE_ONE),
	      src_undef(),
	      src_undef());
   }


   if (dst.WriteMask & WRITEMASK_YZ) {
      emit_op(c,
	      OPCODE_LIT,
	      dst_mask(dst, WRITEMASK_YZ),
	      inst->SaturateMode, 0, 0,
	      src0,
	      src_undef(),
	      src_undef());
   }
}
示例#4
0
/* This one is simple - just take the interpolated fog coordinate and
 * use it as the fog blend factor.
 */
static void fog_interpolated( struct brw_wm_compile *c )
{
   struct prog_src_register fogc = src_reg(PROGRAM_INPUT, FRAG_ATTRIB_FOGC);
   
   if (!(c->fp_interp_emitted & (1<<FRAG_ATTRIB_FOGC))) 
      emit_interp(c, FRAG_ATTRIB_FOGC);

   fog_blend( c, src_swizzle1(fogc, GET_SWZ(fogc.Swizzle,X)));
}
示例#5
0
/**
 * Emit code for TXP.
 */
static void precalc_txp( struct brw_wm_compile *c,
			       const struct prog_instruction *inst )
{
   struct prog_src_register src0 = inst->SrcReg[0];

   if (projtex(c, inst)) {
      struct prog_dst_register tmp = get_temp(c);
      struct prog_instruction tmp_inst;

      /* tmp0.w = RCP inst.arg[0][3]
       */
      emit_op(c,
	      OPCODE_RCP,
	      dst_mask(tmp, WRITEMASK_W),
	      0,
	      src_swizzle1(src0, GET_SWZ(src0.Swizzle, W)),
	      src_undef(),
	      src_undef());

      /* tmp0.xyz =  MUL inst.arg[0], tmp0.wwww
       */
      emit_op(c,
	      OPCODE_MUL,
	      dst_mask(tmp, WRITEMASK_XYZ),
	      0,
	      src0,
	      src_swizzle1(src_reg_from_dst(tmp), W),
	      src_undef());

      /* dst = precalc(TEX tmp0)
       */
      tmp_inst = *inst;
      tmp_inst.SrcReg[0] = src_reg_from_dst(tmp);
      precalc_tex(c, &tmp_inst);

      release_temp(c, tmp);
   }
   else
   {
      /* dst = precalc(TEX src0)
       */
      precalc_tex(c, inst);
   }
}
示例#6
0
/**
 * Some TEX instructions require extra code, cube map coordinate
 * normalization, or coordinate scaling for RECT textures, etc.
 * This function emits those extra instructions and the TEX
 * instruction itself.
 */
static void precalc_tex( struct brw_wm_compile *c,
			 const struct prog_instruction *inst )
{
   struct prog_src_register coord;
   struct prog_dst_register tmpcoord;
   const GLuint unit = c->fp->program.Base.SamplerUnits[inst->TexSrcUnit];

   assert(unit < BRW_MAX_TEX_UNIT);

   if (inst->TexSrcTarget == TEXTURE_CUBE_INDEX) {
       struct prog_instruction *out;
       struct prog_dst_register tmp0 = get_temp(c);
       struct prog_src_register tmp0src = src_reg_from_dst(tmp0);
       struct prog_dst_register tmp1 = get_temp(c);
       struct prog_src_register tmp1src = src_reg_from_dst(tmp1);
       struct prog_src_register src0 = inst->SrcReg[0];

       /* find longest component of coord vector and normalize it */
       tmpcoord = get_temp(c);
       coord = src_reg_from_dst(tmpcoord);

       /* tmpcoord = src0 (i.e.: coord = src0) */
       out = emit_op(c, OPCODE_MOV,
                     tmpcoord,
                     0,
                     src0,
                     src_undef(),
                     src_undef());
       out->SrcReg[0].Negate = NEGATE_NONE;
       out->SrcReg[0].Abs = 1;

       /* tmp0 = MAX(coord.X, coord.Y) */
       emit_op(c, OPCODE_MAX,
               tmp0,
               0,
               src_swizzle1(coord, X),
               src_swizzle1(coord, Y),
               src_undef());

       /* tmp1 = MAX(tmp0, coord.Z) */
       emit_op(c, OPCODE_MAX,
               tmp1,
               0,
               tmp0src,
               src_swizzle1(coord, Z),
               src_undef());

       /* tmp0 = 1 / tmp1 */
       emit_op(c, OPCODE_RCP,
               dst_mask(tmp0, WRITEMASK_X),
               0,
               tmp1src,
               src_undef(),
               src_undef());

       /* tmpCoord = src0 * tmp0 */
       emit_op(c, OPCODE_MUL,
               tmpcoord,
               0,
               src0,
               src_swizzle1(tmp0src, SWIZZLE_X),
               src_undef());

       release_temp(c, tmp0);
       release_temp(c, tmp1);
   }
   else if (inst->TexSrcTarget == TEXTURE_RECT_INDEX) {
      struct prog_src_register scale = 
	 search_or_add_param5( c, 
			       STATE_INTERNAL, 
			       STATE_TEXRECT_SCALE,
			       unit,
			       0,0 );

      tmpcoord = get_temp(c);

      /* coord.xy   = MUL inst->SrcReg[0], { 1/width, 1/height }
       */
      emit_op(c,
	      OPCODE_MUL,
	      tmpcoord,
	      0,
	      inst->SrcReg[0],
	      src_swizzle(scale,
			  SWIZZLE_X,
			  SWIZZLE_Y,
			  SWIZZLE_ONE,
			  SWIZZLE_ONE),
	      src_undef());

      coord = src_reg_from_dst(tmpcoord);
   }
   else {
      coord = inst->SrcReg[0];
   }

   /* Need to emit YUV texture conversions by hand.  Probably need to
    * do this here - the alternative is in brw_wm_emit.c, but the
    * conversion requires allocating a temporary variable which we
    * don't have the facility to do that late in the compilation.
    */
   if (c->key.yuvtex_mask & (1 << unit)) {
      /* convert ycbcr to RGBA */
      GLboolean  swap_uv = c->key.yuvtex_swap_mask & (1<<unit);

      /* 
	 CONST C0 = { -.5, -.0625,  -.5, 1.164 }
	 CONST C1 = { 1.596, -0.813, 2.018, -.391 }
	 UYV     = TEX ...
	 UYV.xyz = ADD UYV,     C0
	 UYV.y   = MUL UYV.y,   C0.w
 	 if (UV swaped)
	    RGB.xyz = MAD UYV.zzx, C1,   UYV.y
	 else
	    RGB.xyz = MAD UYV.xxz, C1,   UYV.y 
	 RGB.y   = MAD UYV.z,   C1.w, RGB.y
      */
      struct prog_dst_register dst = inst->DstReg;
      struct prog_dst_register tmp = get_temp(c);
      struct prog_src_register tmpsrc = src_reg_from_dst(tmp);
      struct prog_src_register C0 = search_or_add_const4f( c,  -.5, -.0625, -.5, 1.164 );
      struct prog_src_register C1 = search_or_add_const4f( c, 1.596, -0.813, 2.018, -.391 );
     
      /* tmp     = TEX ...
       */
      emit_tex_op(c, 
                  OPCODE_TEX,
                  tmp,
                  inst->SaturateMode,
                  unit,
                  inst->TexSrcTarget,
                  inst->TexShadow,
                  coord,
                  src_undef(),
                  src_undef());

      /* tmp.xyz =  ADD TMP, C0
       */
      emit_op(c,
	      OPCODE_ADD,
	      dst_mask(tmp, WRITEMASK_XYZ),
	      0,
	      tmpsrc,
	      C0,
	      src_undef());

      /* YUV.y   = MUL YUV.y, C0.w
       */

      emit_op(c,
	      OPCODE_MUL,
	      dst_mask(tmp, WRITEMASK_Y),
	      0,
	      tmpsrc,
	      src_swizzle1(C0, W),
	      src_undef());

      /* 
       * if (UV swaped)
       *     RGB.xyz = MAD YUV.zzx, C1, YUV.y
       * else
       *     RGB.xyz = MAD YUV.xxz, C1, YUV.y
       */

      emit_op(c,
	      OPCODE_MAD,
	      dst_mask(dst, WRITEMASK_XYZ),
	      0,
	      swap_uv?src_swizzle(tmpsrc, Z,Z,X,X):src_swizzle(tmpsrc, X,X,Z,Z),
	      C1,
	      src_swizzle1(tmpsrc, Y));

      /*  RGB.y   = MAD YUV.z, C1.w, RGB.y
       */
      emit_op(c,
	      OPCODE_MAD,
	      dst_mask(dst, WRITEMASK_Y),
	      0,
	      src_swizzle1(tmpsrc, Z),
	      src_swizzle1(C1, W),
	      src_swizzle1(src_reg_from_dst(dst), Y));

      release_temp(c, tmp);
   }
   else {
      /* ordinary RGBA tex instruction */
      emit_tex_op(c, 
                  OPCODE_TEX,
                  inst->DstReg,
                  inst->SaturateMode,
                  unit,
                  inst->TexSrcTarget,
                  inst->TexShadow,
                  coord,
                  src_undef(),
                  src_undef());
   }

   /* For GL_EXT_texture_swizzle: */
   if (c->key.tex_swizzles[unit] != SWIZZLE_NOOP) {
      /* swizzle the result of the TEX instruction */
      struct prog_src_register tmpsrc = src_reg_from_dst(inst->DstReg);
      emit_op(c, OPCODE_SWZ,
              inst->DstReg,
              SATURATE_OFF, /* saturate already done above */
              src_swizzle4(tmpsrc, c->key.tex_swizzles[unit]),
              src_undef(),
              src_undef());
   }

   if ((inst->TexSrcTarget == TEXTURE_RECT_INDEX) ||
       (inst->TexSrcTarget == TEXTURE_CUBE_INDEX))
      release_temp(c, tmpcoord);
}
示例#7
0
static void precalc_tex( struct brw_wm_compile *c,
			 const struct prog_instruction *inst )
{
   struct prog_src_register coord;
   struct prog_dst_register tmpcoord;

   if (inst->TexSrcTarget == TEXTURE_RECT_INDEX) {
      struct prog_src_register scale = 
	 search_or_add_param5( c, 
			       STATE_INTERNAL, 
			       STATE_TEXRECT_SCALE,
			       inst->TexSrcUnit,
			       0,0 );

      tmpcoord = get_temp(c);

      /* coord.xy   = MUL inst->SrcReg[0], { 1/width, 1/height }
       */
      emit_op(c,
	      OPCODE_MUL,
	      tmpcoord,
	      0, 0, 0,
	      inst->SrcReg[0],
	      scale,
	      src_undef());

      coord = src_reg_from_dst(tmpcoord);
   }
   else {
      coord = inst->SrcReg[0];
   }

   /* Need to emit YUV texture conversions by hand.  Probably need to
    * do this here - the alternative is in brw_wm_emit.c, but the
    * conversion requires allocating a temporary variable which we
    * don't have the facility to do that late in the compilation.
    */
   if (!(c->key.yuvtex_mask & (1<<inst->TexSrcUnit))) {
      emit_op(c, 
	      OPCODE_TEX,
	      inst->DstReg,
	      inst->SaturateMode,
	      inst->TexSrcUnit,
	      inst->TexSrcTarget,
	      coord,
	      src_undef(),
	      src_undef());
   }
   else {
      /* 
	 CONST C0 = { -.5, -.0625,  -.5, 1.164 }
	 CONST C1 = { 1.596, -0.813, 2.018, -.391 }
	 UYV     = TEX ...
	 UYV.xyz = ADD UYV,     C0
	 UYV.y   = MUL UYV.y,   C0.w
	 RGB.xyz = MAD UYV.xxz, C1,   UYV.y
	 RGB.y   = MAD UYV.z,   C1.w, RGB.y
      */
      struct prog_dst_register dst = inst->DstReg;
      struct prog_src_register src0 = inst->SrcReg[0];
      struct prog_dst_register tmp = get_temp(c);
      struct prog_src_register tmpsrc = src_reg_from_dst(tmp);
      struct prog_src_register C0 = search_or_add_const4f( c,  -.5, -.0625, -.5, 1.164 );
      struct prog_src_register C1 = search_or_add_const4f( c, 1.596, -0.813, 2.018, -.391 );
     
      /* tmp     = TEX ...
       */
      emit_op(c, 
	      OPCODE_TEX,
	      tmp,
	      inst->SaturateMode,
	      inst->TexSrcUnit,
	      inst->TexSrcTarget,
	      src0,
	      src_undef(),
	      src_undef());

      /* tmp.xyz =  ADD TMP, C0
       */
      emit_op(c,
	      OPCODE_ADD,
	      dst_mask(tmp, WRITEMASK_XYZ),
	      0, 0, 0,
	      tmpsrc,
	      C0,
	      src_undef());

      /* YUV.y   = MUL YUV.y, C0.w
       */
      emit_op(c,
	      OPCODE_MUL,
	      dst_mask(tmp, WRITEMASK_Y),
	      0, 0, 0,
	      tmpsrc,
	      src_swizzle1(C0, W),
	      src_undef());

      /* RGB.xyz = MAD YUV.xxz, C1, YUV.y
       */
      emit_op(c,
	      OPCODE_MAD,
	      dst_mask(dst, WRITEMASK_XYZ),
	      0, 0, 0,
	      src_swizzle(tmpsrc, X,X,Z,Z),
	      C1,
	      src_swizzle1(tmpsrc, Y));

      /*  RGB.y   = MAD YUV.z, C1.w, RGB.y
       */
      emit_op(c,
	      OPCODE_MAD,
	      dst_mask(dst, WRITEMASK_Y),
	      0, 0, 0,
	      src_swizzle1(tmpsrc, Z),
	      src_swizzle1(C1, W),
	      src_swizzle1(src_reg_from_dst(dst), Y));

      release_temp(c, tmp);
   }

   if (inst->TexSrcTarget == GL_TEXTURE_RECTANGLE_NV) 
      release_temp(c, tmpcoord);
}