Ejemplo n.º 1
0
static GLuint get_dest( struct i915_fragment_program *p, int unit )
{
   if (p->ctx->_TriangleCaps & DD_SEPARATE_SPECULAR)
      return i915_get_temp( p );
   else if (unit != p->last_tex_stage)
      return i915_get_temp( p );
   else
      return UREG(REG_TYPE_OC, 0);
}
Ejemplo n.º 2
0
static GLuint emit_combine_source( struct i915_fragment_program *p, 
				   GLuint mask,
				   GLuint unit,
				   GLenum source, 
				   GLenum operand )
{
   GLuint arg, src;

   src = get_source(p, source, unit);

   switch (operand) {
   case GL_ONE_MINUS_SRC_COLOR: 
      /* Get unused tmp,
       * Emit tmp = 1.0 + arg.-x-y-z-w
       */
      arg = i915_get_temp( p );
      return i915_emit_arith( p, A0_ADD, arg, mask, 0,
		  swizzle(src, ONE, ONE, ONE, ONE ),
		  negate(src, 1,1,1,1), 0);

   case GL_SRC_ALPHA: 
      if (mask == A0_DEST_CHANNEL_W)
	 return src;
      else
	 return swizzle( src, W, W, W, W );
   case GL_ONE_MINUS_SRC_ALPHA: 
      /* Get unused tmp,
       * Emit tmp = 1.0 + arg.-w-w-w-w
       */
      arg = i915_get_temp( p );
      return i915_emit_arith( p, A0_ADD, arg, mask, 0,
			 swizzle(src, ONE, ONE, ONE, ONE ),
			 negate( swizzle(src,W,W,W,W), 1,1,1,1), 0);
   case GL_SRC_COLOR: 
   default:
      return src;
   }
}
Ejemplo n.º 3
0
static GLuint get_source( struct i915_fragment_program *p, 
			  GLenum src, GLuint unit )
{
   switch (src) {
   case GL_TEXTURE: 
      if (p->src_texture == UREG_BAD) {

	 /* TODO: Use D0_CHANNEL_XY where possible.
	  */
	 GLuint dim = translate_tex_src_bit( p, p->ctx->Texture.Unit[unit]._ReallyEnabled);
	 GLuint sampler = i915_emit_decl(p, REG_TYPE_S, unit, dim);
	 GLuint texcoord = i915_emit_decl(p, REG_TYPE_T, unit, D0_CHANNEL_ALL);
	 GLuint tmp = i915_get_temp( p );
	 GLuint op = T0_TEXLD;

	 if (p->VB->TexCoordPtr[unit]->size == 4)
	    op = T0_TEXLDP;

	 p->src_texture = i915_emit_texld( p, tmp, A0_DEST_CHANNEL_ALL, 
					  sampler, texcoord, op );
      }

      return p->src_texture;

      /* Crossbar: */
   case GL_TEXTURE0:
   case GL_TEXTURE1:
   case GL_TEXTURE2:
   case GL_TEXTURE3:
   case GL_TEXTURE4:
   case GL_TEXTURE5:
   case GL_TEXTURE6:
   case GL_TEXTURE7: {
      return UREG_BAD;
   }

   case GL_CONSTANT:
      return i915_emit_const4fv( p, p->ctx->Texture.Unit[unit].EnvColor );
   case GL_PRIMARY_COLOR:
      return i915_emit_decl(p, REG_TYPE_T, T_DIFFUSE, D0_CHANNEL_ALL);
   case GL_PREVIOUS:
   default: 
      i915_emit_decl(p, 
		GET_UREG_TYPE(p->src_previous),
		GET_UREG_NR(p->src_previous), D0_CHANNEL_ALL); 
      return p->src_previous;
   }
}
Ejemplo n.º 4
0
/**
 * Emit a texture load or texkill instruction.
 * \param dest  the dest i915 register
 * \param destmask  the dest register writemask
 * \param sampler  the i915 sampler register
 * \param coord  the i915 source texcoord operand
 * \param opcode  the instruction opcode
 */
uint i915_emit_texld( struct i915_fp_compile *p,
                      uint dest,
                      uint destmask,
                      uint sampler,
                      uint coord,
                      uint opcode,
                      uint num_coord )
{
   const uint k = UREG(GET_UREG_TYPE(coord), GET_UREG_NR(coord));

   int temp = -1;
   uint ignore = 0;

   /* Eliminate the useless texture coordinates. Otherwise we end up generating
    * a swizzle for no reason below. */
   switch(num_coord) {
      case 0:
         /* Ignore x */
         ignore |= (0xf << UREG_CHANNEL_X_SHIFT);
      case 1:
         /* Ignore y */
         ignore |= (0xf << UREG_CHANNEL_Y_SHIFT);
      case 2:
         /* Ignore z */
         ignore |= (0xf << UREG_CHANNEL_Z_SHIFT);
      case 3:
         /* Ignore w */
         ignore |= (0xf << UREG_CHANNEL_W_SHIFT);
   }

   if ( (coord &~ignore ) != (k & ~ignore) ) {
      /* texcoord is swizzled or negated.  Need to allocate a new temporary
       * register (a utemp / unpreserved temp) won't do.
       */
      uint tempReg;

      temp = i915_get_temp(p);           /* get temp reg index */
      tempReg = UREG(REG_TYPE_R, temp);  /* make i915 register */

      i915_emit_arith( p, A0_MOV,
                       tempReg, A0_DEST_CHANNEL_ALL, /* dest reg, writemask */
                       0,                            /* saturate */
                       coord, 0, 0 );                /* src0, src1, src2 */

      /* new src texcoord is tempReg */
      coord = tempReg;
   }

   /* Don't worry about saturate as we only support  
    */
   if (destmask != A0_DEST_CHANNEL_ALL) {
      /* if not writing to XYZW... */
      uint tmp = i915_get_utemp(p);
      i915_emit_texld( p, tmp, A0_DEST_CHANNEL_ALL, sampler, coord, opcode, num_coord );
      i915_emit_arith( p, A0_MOV, dest, destmask, 0, tmp, 0, 0 );
      /* XXX release utemp here? */
   }
   else {
      assert(GET_UREG_TYPE(dest) != REG_TYPE_CONST);
      assert(dest == UREG(GET_UREG_TYPE(dest), GET_UREG_NR(dest)));

      /* Output register being oC or oD defines a phase boundary */
      if (GET_UREG_TYPE(dest) == REG_TYPE_OC ||
          GET_UREG_TYPE(dest) == REG_TYPE_OD)
         p->nr_tex_indirect++;

      /* Reading from an r# register whose contents depend on output of the
       * current phase defines a phase boundary.
       */
      if (GET_UREG_TYPE(coord) == REG_TYPE_R &&
          p->register_phases[GET_UREG_NR(coord)] == p->nr_tex_indirect)
         p->nr_tex_indirect++;

      if (p->csr< p->program + I915_PROGRAM_SIZE) {
         *(p->csr++) = (opcode |
                        T0_DEST( dest ) |
                        T0_SAMPLER( sampler ));

         *(p->csr++) = T1_ADDRESS_REG( coord );
         *(p->csr++) = T2_MBZ;
      }
      else
         i915_program_error(p, "Out of instructions");

      if (GET_UREG_TYPE(dest) == REG_TYPE_R)
         p->register_phases[GET_UREG_NR(dest)] = p->nr_tex_indirect;

      p->nr_tex_insn++;
   }

   if (temp >= 0)
      i915_release_temp(p, temp);

   return dest;
}
Ejemplo n.º 5
0
static GLuint emit_combine( struct i915_fragment_program *p,
			    GLuint dest,
			    GLuint mask,
			    GLuint saturate,
			    GLuint unit,
			    GLenum mode,
			    const GLenum *source,
			    const GLenum *operand)
{
   int tmp, src[3], nr = nr_args(mode);
   int i;

   for (i = 0; i < nr; i++)
      src[i] = emit_combine_source( p, mask, unit, source[i], operand[i] );

   switch (mode) {
   case GL_REPLACE: 
      if (mask == A0_DEST_CHANNEL_ALL && !saturate)
	 return src[0];
      else
	 return i915_emit_arith( p, A0_MOV, dest, mask, saturate, src[0], 0, 0 );
   case GL_MODULATE: 
      return i915_emit_arith( p, A0_MUL, dest, mask, saturate,
			     src[0], src[1], 0 );
   case GL_ADD: 
      return i915_emit_arith( p, A0_ADD, dest, mask, saturate, 
			     src[0], src[1], 0 );
   case GL_ADD_SIGNED:
      /* tmp = arg0 + arg1
       * result = tmp + -.5
       */
      tmp = i915_emit_const1f(p, .5);
      tmp = negate(swizzle(tmp,X,X,X,X),1,1,1,1);
      i915_emit_arith( p, A0_ADD, dest, mask, 0, src[0], src[1], 0 );
      i915_emit_arith( p, A0_ADD, dest, mask, saturate, dest, tmp, 0 );
      return dest;
   case GL_INTERPOLATE:		/* TWO INSTRUCTIONS */
      /* Arg0 * (Arg2) + Arg1 * (1-Arg2)
       *
       * Arg0*Arg2 + Arg1 - Arg1Arg2 
       *
       * tmp = Arg0*Arg2 + Arg1, 
       * result = (-Arg1)Arg2 + tmp 
       */
      tmp = i915_get_temp( p );
      i915_emit_arith( p, A0_MAD, tmp, mask, 0, src[0], src[2], src[1] );
      i915_emit_arith( p, A0_MAD, dest, mask, saturate, 
		      negate(src[1], 1,1,1,1), src[2], tmp );
      return dest;
   case GL_SUBTRACT: 
      /* negate src[1] */
      return i915_emit_arith( p, A0_ADD, dest, mask, saturate, src[0],
			 negate(src[1],1,1,1,1), 0 );

   case GL_DOT3_RGBA:
   case GL_DOT3_RGBA_EXT: 
   case GL_DOT3_RGB_EXT:
   case GL_DOT3_RGB: {
      GLuint tmp0 = i915_get_temp( p );
      GLuint tmp1 = i915_get_temp( p );
      GLuint neg1 = negate(swizzle(i915_emit_const1f(p, 1),X,X,X,X), 1,1,1,1);
      GLuint two = swizzle(i915_emit_const1f(p, 2),X,X,X,X);
      i915_emit_arith( p, A0_MAD, tmp0, A0_DEST_CHANNEL_ALL, 0, 
		      two, src[0], neg1);
      if (src[0] == src[1])
	 tmp1 = tmp0;
      else
	 i915_emit_arith( p, A0_MAD, tmp1, A0_DEST_CHANNEL_ALL, 0, 
			 two, src[1], neg1);
      i915_emit_arith( p, A0_DP3, dest, mask, saturate, tmp0, tmp1, 0);
      return dest;
   }

   default: 
      return src[0];
   }
}