Merge branch 'gallium-0.1' into gallium-0.2
[mesa.git] / src / mesa / drivers / dri / i965 / brw_wm_glsl.c
index 9b0b7aaa5511b76daa79da0df160149ad4cf68fb..305100f8833993321ba7dedba147d909aae0de14 100644 (file)
@@ -5,7 +5,7 @@
 #include "brw_wm.h"
 
 /* Only guess, need a flag in gl_fragment_program later */
-GLboolean brw_wm_is_glsl(struct gl_fragment_program *fp)
+GLboolean brw_wm_is_glsl(const struct gl_fragment_program *fp)
 {
     int i;
     for (i = 0; i < fp->Base.NumInstructions; i++) {
@@ -172,7 +172,7 @@ static void emit_abs( struct brw_wm_compile *c,
     brw_set_saturate(p, 0);
 }
 
-static void emit_mov_int( struct brw_wm_compile *c,
+static void emit_int( struct brw_wm_compile *c,
                struct prog_instruction *inst)
 {
     int i;
@@ -182,9 +182,9 @@ static void emit_mov_int( struct brw_wm_compile *c,
     for (i = 0; i < 4; i++) {
        if (mask & (1<<i)) {
            struct brw_reg src, dst;
-           dst = retype(get_dst_reg(c, inst, i, 1), BRW_REGISTER_TYPE_D);
-           src = retype(get_src_reg(c, &inst->SrcReg[0], i, 1), BRW_REGISTER_TYPE_D);
-           brw_MOV(p, dst, src);
+           dst = get_dst_reg(c, inst, i, 1) ;
+           src = get_src_reg(c, &inst->SrcReg[0], i, 1);
+           brw_RNDD(p, dst, src);
        }
     }
     brw_set_saturate(p, 0);
@@ -274,10 +274,11 @@ static void emit_delta_xy(struct brw_wm_compile *c,
 
 static void fire_fb_write( struct brw_wm_compile *c,
                            GLuint base_reg,
-                           GLuint nr )
+                           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 } */
@@ -294,10 +295,10 @@ static void fire_fb_write( struct brw_wm_compile *c,
            retype(vec8(brw_null_reg()), BRW_REGISTER_TYPE_UW),
            base_reg,
            retype(brw_vec8_grf(0, 0), BRW_REGISTER_TYPE_UW),
-           0,              /* render surface always 0 */
+           target,              
            nr,
            0,
-           1);
+           eot);
 }
 
 static void emit_fb_write(struct brw_wm_compile *c,
@@ -306,7 +307,8 @@ static void emit_fb_write(struct brw_wm_compile *c,
     struct brw_compile *p = &c->func;
     int nr = 2;
     int channel;
-    struct brw_reg src0;//, src1, src2, dst;
+    GLuint target, eot;
+    struct brw_reg src0;
 
     /* Reserve a space for AA - may not be needed:
      */
@@ -324,7 +326,22 @@ static void emit_fb_write(struct brw_wm_compile *c,
        nr += 8;
        brw_pop_insn_state(p);
     }
-    fire_fb_write(c, 0, nr);
+
+   if (c->key.source_depth_to_render_target)
+   {
+      if (c->key.computes_depth) {
+         src0 = get_src_reg(c, &inst->SrcReg[2], 2, 1);
+         brw_MOV(p, brw_message_reg(nr), src0);
+      } else {
+         src0 = get_src_reg(c, &inst->SrcReg[1], 1, 1);
+         brw_MOV(p, brw_message_reg(nr), src0);
+      }
+
+      nr += 2;
+   }
+    target = inst->Sampler >> 1;
+    eot = inst->Sampler & 1;
+    fire_fb_write(c, 0, nr, target, eot);
 }
 
 static void emit_pixel_w( struct brw_wm_compile *c,
@@ -940,6 +957,39 @@ static void emit_ddy(struct brw_wm_compile *c,
     brw_set_saturate(p, 0);
 }
 
+static void emit_wpos_xy(struct brw_wm_compile *c,
+                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, 1);
+    dst[1] = get_dst_reg(c, inst, 1, 1);
+
+    src0[0] = get_src_reg(c, &inst->SrcReg[0], 0, 1);
+    src0[1] = get_src_reg(c, &inst->SrcReg[0], 1, 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 workind yet...
  */    
@@ -948,6 +998,8 @@ static void emit_txb(struct brw_wm_compile *c,
 {
     struct brw_compile *p = &c->func;
     struct brw_reg dst[4], src[4], payload_reg;
+    GLuint unit = c->fp->program.Base.SamplerUnits[inst->TexSrcUnit];
+
     GLuint i;
     payload_reg = get_reg(c, PROGRAM_PAYLOAD, PAYLOAD_DEPTH, 0, 1, 0, 0);
     for (i = 0; i < 4; i++) 
@@ -979,8 +1031,8 @@ static void emit_txb(struct brw_wm_compile *c,
            retype(vec8(dst[0]), BRW_REGISTER_TYPE_UW),
            1,
            retype(payload_reg, BRW_REGISTER_TYPE_UW),
-           inst->TexSrcUnit + 1, /* surface */
-           inst->TexSrcUnit,     /* sampler */
+           unit + MAX_DRAW_BUFFERS, /* surface */
+           unit,     /* sampler */
            inst->DstReg.WriteMask,
            BRW_SAMPLER_MESSAGE_SIMD16_SAMPLE_BIAS,
            4,
@@ -993,11 +1045,15 @@ static void emit_tex(struct brw_wm_compile *c,
 {
     struct brw_compile *p = &c->func;
     struct brw_reg dst[4], src[4], payload_reg;
+    GLuint unit = c->fp->program.Base.SamplerUnits[inst->TexSrcUnit];
+
     GLuint msg_len;
     GLuint i, nr;
     GLuint emit;
+    GLboolean shadow = (c->key.shadowtex_mask & (1<<unit)) ? 1 : 0;
 
     payload_reg = get_reg(c, PROGRAM_PAYLOAD, PAYLOAD_DEPTH, 0, 1, 0, 0);
+
     for (i = 0; i < 4; i++) 
        dst[i] = get_dst_reg(c, inst, i, 1);
     for (i = 0; i < 4; i++)
@@ -1030,17 +1086,25 @@ static void emit_tex(struct brw_wm_compile *c,
        msg_len += 1;
     }
 
+    if (shadow) {
+       brw_MOV(p, brw_message_reg(5), brw_imm_f(0));
+       brw_MOV(p, brw_message_reg(6), src[2]);
+    }
+
     brw_SAMPLE(p,
            retype(vec8(dst[0]), BRW_REGISTER_TYPE_UW),
            1,
            retype(payload_reg, BRW_REGISTER_TYPE_UW),
-           inst->TexSrcUnit + 1, /* surface */
-           inst->TexSrcUnit,     /* sampler */
+           unit + MAX_DRAW_BUFFERS, /* surface */
+           unit,     /* sampler */
            inst->DstReg.WriteMask,
            BRW_SAMPLER_MESSAGE_SIMD8_SAMPLE,
            4,
-           4,
+           shadow ? 6 : 4,
            0);
+
+    if (shadow)
+       brw_MOV(p, dst[3], brw_imm_f(1.0));
 }
 
 static void post_wm_emit( struct brw_wm_compile *c )
@@ -1067,8 +1131,7 @@ static void post_wm_emit( struct brw_wm_compile *c )
     }
 }
 
-static void brw_wm_emit_glsl(struct brw_wm_compile *c)
-
+static void brw_wm_emit_glsl(struct brw_context *brw, struct brw_wm_compile *c)
 {
 #define MAX_IFSN 32
 #define MAX_LOOP_DEPTH 32
@@ -1078,7 +1141,6 @@ static void brw_wm_emit_glsl(struct brw_wm_compile *c)
     struct brw_compile *p = &c->func;
     struct brw_indirect stack_index = brw_indirect(0, 0);
 
-    brw_init_compile(&c->func);
     c->reg_index = 0;
     prealloc_reg(c);
     brw_set_compression_control(p, BRW_COMPRESSION_NONE);
@@ -1091,6 +1153,11 @@ static void brw_wm_emit_glsl(struct brw_wm_compile *c)
        if ((orig_inst = inst->Data) != 0)
            orig_inst->Data = current_insn(p);
 
+       if (inst->CondUpdate)
+           brw_set_conditionalmod(p, BRW_CONDITIONAL_NZ);
+       else
+           brw_set_conditionalmod(p, BRW_CONDITIONAL_NONE);
+
        switch (inst->Opcode) {
            case WM_PIXELXY:
                emit_pixel_xy(c, inst);
@@ -1110,6 +1177,9 @@ static void brw_wm_emit_glsl(struct brw_wm_compile *c)
            case WM_CINTERP:
                emit_cinterp(c, inst);
                break;
+           case WM_WPOSXY:
+               emit_wpos_xy(c, inst);
+               break;
            case WM_FB_WRITE:
                emit_fb_write(c, inst);
                break;
@@ -1132,7 +1202,7 @@ static void brw_wm_emit_glsl(struct brw_wm_compile *c)
                emit_lrp(c, inst);
                break;
            case OPCODE_INT:
-               emit_mov_int(c, inst);
+               emit_int(c, inst);
                break;
            case OPCODE_MOV:
                emit_mov(c, inst);
@@ -1233,7 +1303,7 @@ static void brw_wm_emit_glsl(struct brw_wm_compile *c)
                brw_push_insn_state(p);
                brw_set_mask_control(p, BRW_MASK_DISABLE);
                 brw_set_access_mode(p, BRW_ALIGN_1);
-                brw_ADD(p, deref_1uw(stack_index, 0), brw_ip_reg(), brw_imm_d(3*16));
+                brw_ADD(p, deref_1ud(stack_index, 0), brw_ip_reg(), brw_imm_d(3*16));
                 brw_set_access_mode(p, BRW_ALIGN_16);
                 brw_ADD(p, get_addr_reg(stack_index),
                          get_addr_reg(stack_index), brw_imm_d(4));
@@ -1249,7 +1319,7 @@ static void brw_wm_emit_glsl(struct brw_wm_compile *c)
                 brw_ADD(p, get_addr_reg(stack_index),
                         get_addr_reg(stack_index), brw_imm_d(-4));
                 brw_set_access_mode(p, BRW_ALIGN_1);
-                brw_MOV(p, brw_ip_reg(), deref_1uw(stack_index, 0));
+                brw_MOV(p, brw_ip_reg(), deref_1ud(stack_index, 0));
                 brw_set_access_mode(p, BRW_ALIGN_16);
                brw_pop_insn_state(p);
 
@@ -1258,10 +1328,13 @@ static void brw_wm_emit_glsl(struct brw_wm_compile *c)
                loop_inst[loop_insn++] = brw_DO(p, BRW_EXECUTE_8);
                break;
            case OPCODE_BRK:
-               brw_set_predicate_control(p, BRW_PREDICATE_NORMAL);
                brw_BREAK(p);
                brw_set_predicate_control(p, BRW_PREDICATE_NONE);
                break;
+           case OPCODE_CONT:
+               brw_CONT(p);
+               brw_set_predicate_control(p, BRW_PREDICATE_NONE);
+               break;
            case OPCODE_ENDLOOP: 
                loop_insn--;
                inst0 = inst1 = brw_WHILE(p, loop_inst[loop_insn]);
@@ -1272,24 +1345,31 @@ static void brw_wm_emit_glsl(struct brw_wm_compile *c)
                    if (inst0->header.opcode == BRW_OPCODE_BREAK) {
                        inst0->bits3.if_else.jump_count = inst1 - inst0 + 1;
                        inst0->bits3.if_else.pop_count = 0;
-                   }
+                   } else if (inst0->header.opcode == BRW_OPCODE_CONTINUE) {
+                        inst0->bits3.if_else.jump_count = inst1 - inst0;
+                        inst0->bits3.if_else.pop_count = 0;
+                    }
                }
                break;
            default:
                _mesa_printf("unsupported IR in fragment shader %d\n",
                        inst->Opcode);
        }
+       if (inst->CondUpdate)
+           brw_set_predicate_control(p, BRW_PREDICATE_NORMAL);
+       else
+           brw_set_predicate_control(p, BRW_PREDICATE_NONE);
     }
     post_wm_emit(c);
     for (i = 0; i < c->fp->program.Base.NumInstructions; i++)
        c->fp->program.Base.Instructions[i].Data = NULL;
 }
 
-void brw_wm_glsl_emit(struct brw_wm_compile *c)
+void brw_wm_glsl_emit(struct brw_context *brw, struct brw_wm_compile *c)
 {
     brw_wm_pass_fp(c);
     c->tmp_index = 127;
-    brw_wm_emit_glsl(c);
+    brw_wm_emit_glsl(brw, c);
     c->prog_data.total_grf = c->reg_index;
     c->prog_data.total_scratch = 0;
 }