[g3dvl] move top/bottom field selection into mc code
authorChristian König <deathsimple@vodafone.de>
Sun, 17 Apr 2011 10:04:18 +0000 (12:04 +0200)
committerChristian König <deathsimple@vodafone.de>
Sun, 17 Apr 2011 10:04:18 +0000 (12:04 +0200)
Removes the workaround and get interlaced videos to work 100% correctly.

src/gallium/auxiliary/vl/vl_mpeg12_mc_renderer.c
src/gallium/auxiliary/vl/vl_vertex_buffers.c

index b87bd6b14c9cda2728bc84c6ac9ffc96ef85db06..eae546aefcc733f5d94837b7046b7de77ed76710 100644 (file)
@@ -218,12 +218,12 @@ create_ref_vert_shader(struct vl_mpeg12_mc_renderer *r)
    mv_scale = ureg_imm4f(shader,
       0.5f / r->buffer_width,
       0.5f / r->buffer_height,
-      1.0f,
+      1.0f / 4.0f,
       1.0f / 255.0f);
 
    for (i = 0; i < 2; ++i) {
       ureg_MAD(shader, ureg_writemask(o_vmv[i], TGSI_WRITEMASK_XY), mv_scale, vmv[i], ureg_src(t_vpos));
-      ureg_MUL(shader, ureg_writemask(o_vmv[i], TGSI_WRITEMASK_W), mv_scale, vmv[i]);
+      ureg_MUL(shader, ureg_writemask(o_vmv[i], TGSI_WRITEMASK_ZW), mv_scale, vmv[i]);
    }
 
    ureg_release_temporary(shader, t_vpos);
@@ -320,10 +320,15 @@ create_ycbcr_frag_shader(struct vl_mpeg12_mc_renderer *r, float scale)
 static void *
 create_ref_frag_shader(struct vl_mpeg12_mc_renderer *r)
 {
+   const float y_scale =
+      r->buffer_height / 2 *
+      r->macroblock_size / MACROBLOCK_HEIGHT;
+
    struct ureg_program *shader;
    struct ureg_src tc[2], sampler;
    struct ureg_dst ref, field;
    struct ureg_dst fragment;
+   unsigned label;
 
    shader = ureg_create(TGSI_PROCESSOR_FRAGMENT);
    if (!shader)
@@ -340,15 +345,37 @@ create_ref_frag_shader(struct vl_mpeg12_mc_renderer *r)
    field = calc_field(shader);
 
    /*
-    * if (field.z)
-    *    ref[0..1] = tex(tc[0..1], sampler[0..1])
-    * else
-    *    ref[0..1] = tex(tc[2..3], sampler[0..1])
-    * result = LRP(info.y, ref[0..1])
+    * ref = field.z ? tc[1] : tc[0]
+    *
+    * // Adjust tc acording to top/bottom field selection
+    * if (|ref.z|) {
+    *    ref.y *= y_scale
+    *    ref.y = floor(ref.y)
+    *    ref.y += ref.z
+    *    ref.y /= y_scale
+    * }
+    * fragment.xyz = tex(ref, sampler[0])
     */
-   ureg_CMP(shader, ref, ureg_negate(ureg_scalar(ureg_src(field), TGSI_SWIZZLE_Y)), tc[1], tc[0]);
+   ureg_CMP(shader, ureg_writemask(ref, TGSI_WRITEMASK_XYZ),
+            ureg_negate(ureg_scalar(ureg_src(field), TGSI_SWIZZLE_Y)),
+            tc[1], tc[0]);
+   ureg_CMP(shader, ureg_writemask(fragment, TGSI_WRITEMASK_W),
+            ureg_negate(ureg_scalar(ureg_src(field), TGSI_SWIZZLE_Y)),
+            tc[1], tc[0]);
+
+   ureg_IF(shader, ureg_scalar(ureg_src(ref), TGSI_SWIZZLE_Z), &label);
+
+      ureg_MUL(shader, ureg_writemask(ref, TGSI_WRITEMASK_Y),
+               ureg_src(ref), ureg_imm1f(shader, y_scale));
+      ureg_FLR(shader, ureg_writemask(ref, TGSI_WRITEMASK_Y), ureg_src(ref));
+      ureg_ADD(shader, ureg_writemask(ref, TGSI_WRITEMASK_Y),
+               ureg_src(ref), ureg_scalar(ureg_src(ref), TGSI_SWIZZLE_Z));
+      ureg_MUL(shader, ureg_writemask(ref, TGSI_WRITEMASK_Y),
+               ureg_src(ref), ureg_imm1f(shader, 1.0f / y_scale));
+
+   ureg_fixup_label(shader, label, ureg_get_instruction_number(shader));
+   ureg_ENDIF(shader);
 
-   ureg_MOV(shader, ureg_writemask(fragment, TGSI_WRITEMASK_W), ureg_src(ref));
    ureg_TEX(shader, ureg_writemask(fragment, TGSI_WRITEMASK_XYZ), TGSI_TEXTURE_2D, ureg_src(ref), sampler);
 
    ureg_release_temporary(shader, ref);
index fc30e85a4d77fb7d610f927ad2c8faaa092ce40d..84dfc9eccf663c00195f689244d4c27780d8fac3 100644 (file)
@@ -228,34 +228,28 @@ get_motion_vectors(struct pipe_mpeg12_macroblock *mb, struct vertex4s mv[4])
    if (mb->mo_type == PIPE_MPEG12_MOTION_TYPE_FRAME) {
       mv[0].x = mv[1].x = mb->mv[0].top.x;
       mv[0].y = mv[1].y = mb->mv[0].top.y;
-      mv[0].z = 0; mv[1].z = 1;
+      mv[0].z = mv[1].z = 0;
 
       mv[2].x = mv[3].x = mb->mv[1].top.x;
       mv[2].y = mv[3].y = mb->mv[1].top.y;
-      mv[2].z = 0; mv[3].z = 1;
+      mv[2].z = mv[3].z = 0;
 
    } else {
       mv[0].x = mb->mv[0].top.x;
-      mv[0].y = mb->mv[0].top.y - (mb->mv[0].top.y % 4);
-      mv[0].z = mb->mv[0].top.field_select;
+      mv[0].y = mb->mv[0].top.y;
+      mv[0].z = mb->mv[0].top.field_select ? 3 : 1;
 
       mv[1].x = mb->mv[0].bottom.x;
-      mv[1].y = mb->mv[0].bottom.y - (mb->mv[0].bottom.y % 4);
-      mv[1].z = mb->mv[0].bottom.field_select;
-
-      if (mb->mv[0].top.field_select) mv[0].y += 2;
-      if (!mb->mv[0].bottom.field_select) mv[1].y -= 2;
+      mv[1].y = mb->mv[0].bottom.y;
+      mv[1].z = mb->mv[0].bottom.field_select ? 3 : 1;
 
       mv[2].x = mb->mv[1].top.x;
-      mv[2].y = mb->mv[1].top.y - (mb->mv[1].top.y % 4);
-      mv[2].z = mb->mv[1].top.field_select;
+      mv[2].y = mb->mv[1].top.y;
+      mv[2].z = mb->mv[1].top.field_select ? 3 : 1;
 
       mv[3].x = mb->mv[1].bottom.x;
-      mv[3].y = mb->mv[1].bottom.y - (mb->mv[1].bottom.y % 4);
-      mv[3].z = mb->mv[1].bottom.field_select;
-
-      if (mb->mv[1].top.field_select) mv[2].y += 2;
-      if (!mb->mv[1].bottom.field_select) mv[3].y -= 2;
+      mv[3].y = mb->mv[1].bottom.y;
+      mv[3].z = mb->mv[1].bottom.field_select ? 3 : 1;
    }
 
    mv[0].w = mv[1].w = mb->mv[0].wheight;