i965: Share emit_fb_write() between brw_wm_emit.c and brw_wm_glsl.c
[mesa.git] / src / mesa / drivers / dri / i965 / brw_wm_glsl.c
index 2df47344d5545a00402687b869eccffcfa90a754..be89bcf4ba6b5438c8bb371f8e7e10ff8b3d9992 100644 (file)
@@ -550,42 +550,6 @@ static struct brw_reg get_src_reg(struct brw_wm_compile *c,
     }
 }
 
-
-/**
- * Same as \sa get_src_reg() but if the register is a literal, emit
- * a brw_reg encoding the literal.
- * Note that a brw instruction only allows one src operand to be a literal.
- * For instructions with more than one operand, only the second can be a
- * literal.  This means that we treat some literals as constants/uniforms
- * (which why PROGRAM_CONSTANT is checked in fetch_constants()).
- * 
- */
-static struct brw_reg get_src_reg_imm(struct brw_wm_compile *c, 
-                                      const struct prog_instruction *inst,
-                                      GLuint srcRegIndex, GLuint channel)
-{
-    const struct prog_src_register *src = &inst->SrcReg[srcRegIndex];
-    if (src->File == PROGRAM_CONSTANT) {
-       /* a literal */
-       const int component = GET_SWZ(src->Swizzle, channel);
-       const GLfloat *param =
-          c->fp->program.Base.Parameters->ParameterValues[src->Index];
-       GLfloat value = param[component];
-       if (src->Negate & (1 << channel))
-          value = -value;
-       if (src->Abs)
-          value = FABSF(value);
-#if 0
-       printf("  form immed value %f for chan %d\n", value, channel);
-#endif
-       return brw_imm_f(value);
-    }
-    else {
-       return get_src_reg(c, inst, srcRegIndex, channel);
-    }
-}
-
-
 /**
  * Subroutines are minimal support for resusable instruction sequences.
  * They are implemented as simply as possible to minimise overhead: there
@@ -707,406 +671,6 @@ unalias3(struct brw_wm_compile *c,
     release_tmps(c, mark);
 }
 
-static void emit_pixel_xy(struct brw_wm_compile *c,
-                          const struct prog_instruction *inst)
-{
-    struct brw_reg r1 = brw_vec1_grf(1, 0);
-    struct brw_reg r1_uw = retype(r1, BRW_REGISTER_TYPE_UW);
-
-    struct brw_reg dst0, dst1;
-    struct brw_compile *p = &c->func;
-    GLuint mask = inst->DstReg.WriteMask;
-
-    dst0 = get_dst_reg(c, inst, 0);
-    dst1 = get_dst_reg(c, inst, 1);
-    /* Calculate pixel centers by adding 1 or 0 to each of the
-     * micro-tile coordinates passed in r1.
-     */
-    if (mask & WRITEMASK_X) {
-       brw_ADD(p,
-               vec8(retype(dst0, BRW_REGISTER_TYPE_UW)),
-               stride(suboffset(r1_uw, 4), 2, 4, 0),
-               brw_imm_v(0x10101010));
-    }
-
-    if (mask & WRITEMASK_Y) {
-       brw_ADD(p,
-               vec8(retype(dst1, BRW_REGISTER_TYPE_UW)),
-               stride(suboffset(r1_uw, 5), 2, 4, 0),
-               brw_imm_v(0x11001100));
-    }
-}
-
-static void emit_delta_xy(struct brw_wm_compile *c,
-                          const struct prog_instruction *inst)
-{
-    struct brw_reg r1 = brw_vec1_grf(1, 0);
-    struct brw_reg dst0, dst1, src0, src1;
-    struct brw_compile *p = &c->func;
-    GLuint mask = inst->DstReg.WriteMask;
-
-    dst0 = get_dst_reg(c, inst, 0);
-    dst1 = get_dst_reg(c, inst, 1);
-    src0 = get_src_reg(c, inst, 0, 0);
-    src1 = get_src_reg(c, inst, 0, 1);
-    /* Calc delta X,Y by subtracting origin in r1 from the pixel
-     * centers.
-     */
-    if (mask & WRITEMASK_X) {
-       brw_ADD(p,
-               dst0,
-               retype(src0, BRW_REGISTER_TYPE_UW),
-               negate(r1));
-    }
-
-    if (mask & WRITEMASK_Y) {
-       brw_ADD(p,
-               dst1,
-               retype(src1, BRW_REGISTER_TYPE_UW),
-               negate(suboffset(r1,1)));
-
-    }
-}
-
-static void fire_fb_write( struct brw_wm_compile *c,
-                           GLuint base_reg,
-                           GLuint nr,
-                           GLuint target,
-                           GLuint eot)
-{
-    struct brw_compile *p = &c->func;
-    /* Pass through control information:
-     */
-    /*  mov (8) m1.0<1>:ud   r1.0<8;8,1>:ud   { Align1 NoMask } */
-    {
-       brw_push_insn_state(p);
-       brw_set_mask_control(p, BRW_MASK_DISABLE); /* ? */
-       brw_MOV(p,
-               brw_message_reg(base_reg + 1),
-               brw_vec8_grf(1, 0));
-       brw_pop_insn_state(p);
-    }
-    /* Send framebuffer write message: */
-    brw_fb_WRITE(p,
-           retype(vec8(brw_null_reg()), BRW_REGISTER_TYPE_UW),
-           base_reg,
-           retype(brw_vec8_grf(0, 0), BRW_REGISTER_TYPE_UW),
-           target,              
-           nr,
-           0,
-           eot);
-}
-
-static void emit_fb_write(struct brw_wm_compile *c,
-                          const struct prog_instruction *inst)
-{
-    struct brw_compile *p = &c->func;
-    int nr = 2;
-    int channel;
-    GLuint target, eot;
-    struct brw_reg src0;
-
-    /* Reserve a space for AA - may not be needed:
-     */
-    if (c->key.aa_dest_stencil_reg)
-       nr += 1;
-
-    brw_push_insn_state(p);
-    for (channel = 0; channel < 4; channel++) {
-        src0 = get_src_reg(c,  inst, 0, channel);
-        /*  mov (8) m2.0<1>:ud   r28.0<8;8,1>:ud  { Align1 } */
-        /*  mov (8) m6.0<1>:ud   r29.0<8;8,1>:ud  { Align1 SecHalf } */
-        brw_MOV(p, brw_message_reg(nr + channel), src0);
-    }
-    /* skip over the regs populated above: */
-    nr += 8;
-    brw_pop_insn_state(p);
-
-    if (c->key.source_depth_to_render_target) {
-       if (c->key.computes_depth) {
-          src0 = get_src_reg(c, inst, 2, 2);
-          brw_MOV(p, brw_message_reg(nr), src0);
-       }
-       else {
-          src0 = get_src_reg(c, inst, 1, 1);
-          brw_MOV(p, brw_message_reg(nr), src0);
-       }
-
-       nr += 2;
-    }
-
-    if (c->key.dest_depth_reg) {
-        const GLuint comp = c->key.dest_depth_reg / 2;
-        const GLuint off = c->key.dest_depth_reg % 2;
-
-        if (off != 0) {
-            /* XXX this code needs review/testing */
-            struct brw_reg arg1_0 = get_src_reg(c, inst, 1, comp);
-            struct brw_reg arg1_1 = get_src_reg(c, inst, 1, comp+1);
-
-            brw_push_insn_state(p);
-            brw_set_compression_control(p, BRW_COMPRESSION_NONE);
-
-            brw_MOV(p, brw_message_reg(nr), offset(arg1_0, 1));
-            /* 2nd half? */
-            brw_MOV(p, brw_message_reg(nr+1), arg1_1);
-            brw_pop_insn_state(p);
-        }
-        else
-        {
-            struct brw_reg src =  get_src_reg(c, inst, 1, 1);
-            brw_MOV(p, brw_message_reg(nr), src);
-        }
-        nr += 2;
-   }
-
-    target = INST_AUX_GET_TARGET(inst->Aux);
-    eot = inst->Aux & INST_AUX_EOT;
-    fire_fb_write(c, 0, nr, target, eot);
-}
-
-static void emit_pixel_w( struct brw_wm_compile *c,
-                          const struct prog_instruction *inst)
-{
-    struct brw_compile *p = &c->func;
-    GLuint mask = inst->DstReg.WriteMask;
-    if (mask & WRITEMASK_W) {
-       struct brw_reg dst, src0, delta0, delta1;
-       struct brw_reg interp3;
-
-       dst = get_dst_reg(c, inst, 3);
-       src0 = get_src_reg(c, inst, 0, 0);
-       delta0 = get_src_reg(c, inst, 1, 0);
-       delta1 = get_src_reg(c, inst, 1, 1);
-
-       interp3 = brw_vec1_grf(src0.nr+1, 4);
-       /* Calc 1/w - just linterp wpos[3] optimized by putting the
-        * result straight into a message reg.
-        */
-       brw_LINE(p, brw_null_reg(), interp3, delta0);
-       brw_MAC(p, brw_message_reg(2), suboffset(interp3, 1), delta1);
-
-       /* Calc w */
-       brw_math_16( p, dst,
-               BRW_MATH_FUNCTION_INV,
-               BRW_MATH_SATURATE_NONE,
-               2, brw_null_reg(),
-               BRW_MATH_PRECISION_FULL);
-    }
-}
-
-static void emit_linterp(struct brw_wm_compile *c,
-                         const struct prog_instruction *inst)
-{
-    struct brw_compile *p = &c->func;
-    GLuint mask = inst->DstReg.WriteMask;
-    struct brw_reg interp[4];
-    struct brw_reg dst, delta0, delta1;
-    struct brw_reg src0;
-    GLuint nr, i;
-
-    src0 = get_src_reg(c, inst, 0, 0);
-    delta0 = get_src_reg(c, inst, 1, 0);
-    delta1 = get_src_reg(c, inst, 1, 1);
-    nr = src0.nr;
-
-    interp[0] = brw_vec1_grf(nr, 0);
-    interp[1] = brw_vec1_grf(nr, 4);
-    interp[2] = brw_vec1_grf(nr+1, 0);
-    interp[3] = brw_vec1_grf(nr+1, 4);
-
-    for(i = 0; i < 4; i++ ) {
-       if (mask & (1<<i)) {
-           dst = get_dst_reg(c, inst, i);
-           brw_LINE(p, brw_null_reg(), interp[i], delta0);
-           brw_MAC(p, dst, suboffset(interp[i],1), delta1);
-       }
-    }
-}
-
-static void emit_cinterp(struct brw_wm_compile *c,
-                         const struct prog_instruction *inst)
-{
-    struct brw_compile *p = &c->func;
-    GLuint mask = inst->DstReg.WriteMask;
-
-    struct brw_reg interp[4];
-    struct brw_reg dst, src0;
-    GLuint nr, i;
-
-    src0 = get_src_reg(c, inst, 0, 0);
-    nr = src0.nr;
-
-    interp[0] = brw_vec1_grf(nr, 0);
-    interp[1] = brw_vec1_grf(nr, 4);
-    interp[2] = brw_vec1_grf(nr+1, 0);
-    interp[3] = brw_vec1_grf(nr+1, 4);
-
-    for(i = 0; i < 4; i++ ) {
-       if (mask & (1<<i)) {
-           dst = get_dst_reg(c, inst, i);
-           brw_MOV(p, dst, suboffset(interp[i],3));
-       }
-    }
-}
-
-static void emit_pinterp(struct brw_wm_compile *c,
-                         const struct prog_instruction *inst)
-{
-    struct brw_compile *p = &c->func;
-    GLuint mask = inst->DstReg.WriteMask;
-
-    struct brw_reg interp[4];
-    struct brw_reg dst, delta0, delta1;
-    struct brw_reg src0, w;
-    GLuint nr, i;
-
-    src0 = get_src_reg(c, inst, 0, 0);
-    delta0 = get_src_reg(c, inst, 1, 0);
-    delta1 = get_src_reg(c, inst, 1, 1);
-    w = get_src_reg(c, inst, 2, 3);
-    nr = src0.nr;
-
-    interp[0] = brw_vec1_grf(nr, 0);
-    interp[1] = brw_vec1_grf(nr, 4);
-    interp[2] = brw_vec1_grf(nr+1, 0);
-    interp[3] = brw_vec1_grf(nr+1, 4);
-
-    for(i = 0; i < 4; i++ ) {
-       if (mask & (1<<i)) {
-           dst = get_dst_reg(c, inst, i);
-           brw_LINE(p, brw_null_reg(), interp[i], delta0);
-           brw_MAC(p, dst, suboffset(interp[i],1), 
-                   delta1);
-           brw_MUL(p, dst, dst, w);
-       }
-    }
-}
-
-/* Sets the destination channels to 1.0 or 0.0 according to glFrontFacing. */
-static void emit_frontfacing(struct brw_wm_compile *c,
-                            const struct prog_instruction *inst)
-{
-    struct brw_compile *p = &c->func;
-    struct brw_reg r1_6ud = retype(brw_vec1_grf(1, 6), BRW_REGISTER_TYPE_UD);
-    struct brw_reg dst;
-    GLuint mask = inst->DstReg.WriteMask;
-    int i;
-
-    for (i = 0; i < 4; i++) {
-       if (mask & (1<<i)) {
-           dst = get_dst_reg(c, inst, i);
-           brw_MOV(p, dst, brw_imm_f(0.0));
-       }
-    }
-
-    /* bit 31 is "primitive is back face", so checking < (1 << 31) gives
-     * us front face
-     */
-    brw_CMP(p, brw_null_reg(), BRW_CONDITIONAL_L, r1_6ud, brw_imm_ud(1 << 31));
-    for (i = 0; i < 4; i++) {
-       if (mask & (1<<i)) {
-           dst = get_dst_reg(c, inst, i);
-           brw_MOV(p, dst, brw_imm_f(1.0));
-       }
-    }
-    brw_set_predicate_control_flag_value(p, 0xff);
-}
-
-static void emit_xpd(struct brw_wm_compile *c,
-                     const struct prog_instruction *inst)
-{
-    int i;
-    struct brw_compile *p = &c->func;
-    GLuint mask = inst->DstReg.WriteMask;
-    for (i = 0; i < 4; i++) {
-       GLuint i2 = (i+2)%3;
-       GLuint i1 = (i+1)%3;
-       if (mask & (1<<i)) {
-           struct brw_reg src0, src1, dst;
-           dst = get_dst_reg(c, inst, i);
-           src0 = negate(get_src_reg(c, inst, 0, i2));
-           src1 = get_src_reg_imm(c, inst, 1, i1);
-           brw_MUL(p, brw_null_reg(), src0, src1);
-           src0 = get_src_reg(c, inst, 0, i1);
-           src1 = get_src_reg_imm(c, inst, 1, i2);
-           brw_set_saturate(p, inst->SaturateMode != SATURATE_OFF);
-           brw_MAC(p, dst, src0, src1);
-           brw_set_saturate(p, 0);
-       }
-    }
-    brw_set_saturate(p, 0);
-}
-
-/**
- * Emit a scalar instruction, like RCP, RSQ, LOG, EXP.
- * Note that the result of the function is smeared across the dest
- * register's X, Y, Z and W channels (subject to writemasking of course).
- */
-static void emit_math1(struct brw_wm_compile *c,
-                       const struct prog_instruction *inst, GLuint func)
-{
-    struct brw_compile *p = &c->func;
-    struct brw_reg src0, dst;
-    GLuint mask = inst->DstReg.WriteMask;
-    int dst_chan = _mesa_ffs(mask & WRITEMASK_XYZW) - 1;
-
-    if (!(mask & WRITEMASK_XYZW))
-       return;
-
-    assert(is_power_of_two(mask & WRITEMASK_XYZW));
-
-    /* Get first component of source register */
-    dst = get_dst_reg(c, inst, dst_chan);
-    src0 = get_src_reg(c, inst, 0, 0);
-
-    brw_MOV(p, brw_message_reg(2), src0);
-    brw_math(p,
-             dst,
-             func,
-             (inst->SaturateMode != SATURATE_OFF) ? BRW_MATH_SATURATE_SATURATE : BRW_MATH_SATURATE_NONE,
-             2,
-             brw_null_reg(),
-             BRW_MATH_DATA_VECTOR,
-             BRW_MATH_PRECISION_FULL);
-}
-
-static void emit_rcp(struct brw_wm_compile *c,
-                     const struct prog_instruction *inst)
-{
-    emit_math1(c, inst, BRW_MATH_FUNCTION_INV);
-}
-
-static void emit_rsq(struct brw_wm_compile *c,
-                     const struct prog_instruction *inst)
-{
-    emit_math1(c, inst, BRW_MATH_FUNCTION_RSQ);
-}
-
-static void emit_sin(struct brw_wm_compile *c,
-                     const struct prog_instruction *inst)
-{
-    emit_math1(c, inst, BRW_MATH_FUNCTION_SIN);
-}
-
-static void emit_cos(struct brw_wm_compile *c,
-                     const struct prog_instruction *inst)
-{
-    emit_math1(c, inst, BRW_MATH_FUNCTION_COS);
-}
-
-static void emit_ex2(struct brw_wm_compile *c,
-                     const struct prog_instruction *inst)
-{
-    emit_math1(c, inst, BRW_MATH_FUNCTION_EXP);
-}
-
-static void emit_lg2(struct brw_wm_compile *c,
-                     const struct prog_instruction *inst)
-{
-    emit_math1(c, inst, BRW_MATH_FUNCTION_LOG);
-}
-
 static void emit_arl(struct brw_wm_compile *c,
                      const struct prog_instruction *inst)
 {
@@ -1169,36 +733,6 @@ static void emit_min_max(struct brw_wm_compile *c,
     release_tmps(c, mark);
 }
 
-static void emit_pow(struct brw_wm_compile *c,
-                     const struct prog_instruction *inst)
-{
-    struct brw_compile *p = &c->func;
-    struct brw_reg dst, src0, src1;
-    GLuint mask = inst->DstReg.WriteMask;
-    int dst_chan = _mesa_ffs(mask & WRITEMASK_XYZW) - 1;
-
-    if (!(mask & WRITEMASK_XYZW))
-       return;
-
-    assert(is_power_of_two(mask & WRITEMASK_XYZW));
-
-    dst = get_dst_reg(c, inst, dst_chan);
-    src0 = get_src_reg_imm(c, inst, 0, 0);
-    src1 = get_src_reg_imm(c, inst, 1, 0);
-
-    brw_MOV(p, brw_message_reg(2), src0);
-    brw_MOV(p, brw_message_reg(3), src1);
-
-    brw_math(p,
-           dst,
-           BRW_MATH_FUNCTION_POW,
-           (inst->SaturateMode != SATURATE_OFF) ? BRW_MATH_SATURATE_SATURATE : BRW_MATH_SATURATE_NONE,
-           2,
-           brw_null_reg(),
-           BRW_MATH_DATA_VECTOR,
-           BRW_MATH_PRECISION_FULL);
-}
-
 /**
  * For GLSL shaders, this KIL will be unconditional.
  * It may be contained inside an IF/ENDIF structure of course.
@@ -2266,39 +1800,7 @@ static void emit_noise4( struct brw_wm_compile *c,
     
     release_tmps( c, mark );
 }
-    
-static void emit_wpos_xy(struct brw_wm_compile *c,
-                         const struct prog_instruction *inst)
-{
-    struct brw_compile *p = &c->func;
-    GLuint mask = inst->DstReg.WriteMask;
-    struct brw_reg src0[2], dst[2];
-
-    dst[0] = get_dst_reg(c, inst, 0);
-    dst[1] = get_dst_reg(c, inst, 1);
 
-    src0[0] = get_src_reg(c, inst, 0, 0);
-    src0[1] = get_src_reg(c, inst, 0, 1);
-
-    /* Calculate the pixel offset from window bottom left into destination
-     * X and Y channels.
-     */
-    if (mask & WRITEMASK_X) {
-       /* X' = X - origin_x */
-       brw_ADD(p,
-               dst[0],
-               retype(src0[0], BRW_REGISTER_TYPE_W),
-               brw_imm_d(0 - c->key.origin_x));
-    }
-
-    if (mask & WRITEMASK_Y) {
-       /* Y' = height - (Y - origin_y) = height + origin_y - Y */
-       brw_ADD(p,
-               dst[1],
-               negate(retype(src0[1], BRW_REGISTER_TYPE_W)),
-               brw_imm_d(c->key.origin_y + c->key.drawable_height - 1));
-    }
-}
 
 /* TODO
    BIAS on SIMD8 not working yet...
@@ -2538,31 +2040,33 @@ static void brw_wm_emit_glsl(struct brw_context *brw, struct brw_wm_compile *c)
 
        switch (inst->Opcode) {
            case WM_PIXELXY:
-               emit_pixel_xy(c, inst);
+               emit_pixel_xy(c, dst, dst_flags);
                break;
            case WM_DELTAXY: 
-               emit_delta_xy(c, inst);
+               emit_delta_xy(p, dst, dst_flags, args[0]);
                break;
            case WM_PIXELW:
-               emit_pixel_w(c, inst);
+               emit_pixel_w(c, dst, dst_flags, args[0], args[1]);
                break;  
            case WM_LINTERP:
-               emit_linterp(c, inst);
+               emit_linterp(p, dst, dst_flags, args[0], args[1]);
                break;
            case WM_PINTERP:
-               emit_pinterp(c, inst);
+               emit_pinterp(p, dst, dst_flags, args[0], args[1], args[2]);
                break;
            case WM_CINTERP:
-               emit_cinterp(c, inst);
+               emit_cinterp(p, dst, dst_flags, args[0]);
                break;
            case WM_WPOSXY:
-               emit_wpos_xy(c, inst);
+               emit_wpos_xy(c, dst, dst_flags, args[0]);
                break;
            case WM_FB_WRITE:
-               emit_fb_write(c, inst);
+               emit_fb_write(c, args[0], args[1], args[2],
+                             INST_AUX_GET_TARGET(inst->Aux),
+                             inst->Aux & INST_AUX_EOT);
                break;
            case WM_FRONTFACING:
-               emit_frontfacing(c, inst);
+               emit_frontfacing(p, dst, dst_flags);
                break;
            case OPCODE_ADD:
                emit_alu2(p, brw_ADD, dst, dst_flags, args[0], args[1]);
@@ -2594,28 +2098,28 @@ static void brw_wm_emit_glsl(struct brw_context *brw, struct brw_wm_compile *c)
                emit_dp4(p, dst, dst_flags, args[0], args[1]);
                break;
            case OPCODE_XPD:
-               emit_xpd(c, inst);
+               emit_xpd(p, dst, dst_flags, args[0], args[1]);
                break;
            case OPCODE_DPH:
                emit_dph(p, dst, dst_flags, args[0], args[1]);
                break;
            case OPCODE_RCP:
-               emit_rcp(c, inst);
+               emit_math1(c, BRW_MATH_FUNCTION_INV, dst, dst_flags, args[0]);
                break;
            case OPCODE_RSQ:
-               emit_rsq(c, inst);
+               emit_math1(c, BRW_MATH_FUNCTION_RSQ, dst, dst_flags, args[0]);
                break;
            case OPCODE_SIN:
-               emit_sin(c, inst);
+               emit_math1(c, BRW_MATH_FUNCTION_SIN, dst, dst_flags, args[0]);
                break;
            case OPCODE_COS:
-               emit_cos(c, inst);
+               emit_math1(c, BRW_MATH_FUNCTION_COS, dst, dst_flags, args[0]);
                break;
            case OPCODE_EX2:
-               emit_ex2(c, inst);
+               emit_math1(c, BRW_MATH_FUNCTION_EXP, dst, dst_flags, args[0]);
                break;
            case OPCODE_LG2:
-               emit_lg2(c, inst);
+               emit_math1(c, BRW_MATH_FUNCTION_LOG, dst, dst_flags, args[0]);
                break;
            case OPCODE_MIN:    
            case OPCODE_MAX:    
@@ -2654,7 +2158,8 @@ static void brw_wm_emit_glsl(struct brw_context *brw, struct brw_wm_compile *c)
                emit_alu2(p, brw_MUL, dst, dst_flags, args[0], args[1]);
                break;
            case OPCODE_POW:
-               emit_pow(c, inst);
+               emit_math2(c, BRW_MATH_FUNCTION_POW,
+                          dst, dst_flags, args[0], args[1]);
                break;
            case OPCODE_MAD:
                emit_mad(p, dst, dst_flags, args[0], args[1], args[2]);