Merge remote branch 'origin/master' into pipe-video
[mesa.git] / src / gallium / auxiliary / vl / vl_mpeg12_mc_renderer.c
index 7e73c5ced9fdd3ec7990a00a34153534b2312716..eca3452a5b4b309fd05b9fb5d4e4108e4bf24d16 100644 (file)
@@ -1,12 +1,38 @@
+/**************************************************************************
+ *
+ * Copyright 2009 Younes Manton.
+ * All Rights Reserved.
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the
+ * "Software"), to deal in the Software without restriction, including
+ * without limitation the rights to use, copy, modify, merge, publish,
+ * distribute, sub license, and/or sell copies of the Software, and to
+ * permit persons to whom the Software is furnished to do so, subject to
+ * the following conditions:
+ *
+ * The above copyright notice and this permission notice (including the
+ * next paragraph) shall be included in all copies or substantial portions
+ * of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
+ * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT.
+ * IN NO EVENT SHALL TUNGSTEN GRAPHICS AND/OR ITS SUPPLIERS BE LIABLE FOR
+ * ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
+ * TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
+ * SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+ *
+ **************************************************************************/
+
 #include "vl_mpeg12_mc_renderer.h"
 #include <assert.h>
 #include <pipe/p_context.h>
-#include <pipe/p_inlines.h>
+#include <util/u_inlines.h>
+#include <util/u_format.h>
 #include <util/u_math.h>
 #include <util/u_memory.h>
-#include <tgsi/tgsi_parse.h>
-#include <tgsi/tgsi_build.h>
-#include "vl_shader_build.h"
+#include <tgsi/tgsi_ureg.h>
 
 #define DEFAULT_BUF_ALIGNMENT 1
 #define MACROBLOCK_WIDTH 16
 #define BLOCK_HEIGHT 8
 #define ZERO_BLOCK_NIL -1.0f
 #define ZERO_BLOCK_IS_NIL(zb) ((zb).x < 0.0f)
-
-struct vertex2f
-{
-   float x, y;
-};
-
-struct vertex4f
-{
-   float x, y, z, w;
-};
+#define SCALE_FACTOR_16_TO_9 (32767.0f / 255.0f)
 
 struct vertex_shader_consts
 {
@@ -37,17 +54,6 @@ struct fragment_shader_consts
    struct vertex4f div;
 };
 
-/*
- * Muliplier renormalizes block samples from 16 bits to 12 bits.
- * Divider is used when calculating Y % 2 for choosing top or bottom
- * field for P or B macroblocks.
- * TODO: Use immediates.
- */
-static const struct fragment_shader_consts fs_consts = {
-   {32767.0f / 255.0f, 32767.0f / 255.0f, 32767.0f / 255.0f, 0.0f},
-   {0.5f, 2.0f, 0.0f, 0.0f}
-};
-
 struct vert_stream_0
 {
    struct vertex2f pos;
@@ -69,599 +75,314 @@ enum MACROBLOCK_TYPE
    NUM_MACROBLOCK_TYPES
 };
 
-static void
+static bool
 create_intra_vert_shader(struct vl_mpeg12_mc_renderer *r)
 {
-   const unsigned max_tokens = 50;
-
-   struct pipe_shader_state vs;
-   struct tgsi_token *tokens;
-   struct tgsi_header *header;
-
-   struct tgsi_full_declaration decl;
-   struct tgsi_full_instruction inst;
-
-   unsigned ti;
+   struct ureg_program *shader;
+   struct ureg_src vpos, vtex[3];
+   struct ureg_dst o_vpos, o_vtex[3];
+   unsigned i;
 
-   assert(r);
-
-   tokens = (struct tgsi_token *) malloc(max_tokens * sizeof(struct tgsi_token));
-   *(struct tgsi_version *) &tokens[0] = tgsi_build_version();
-   header = (struct tgsi_header *) &tokens[1];
-   *header = tgsi_build_header();
-   *(struct tgsi_processor *) &tokens[2] = tgsi_build_processor(TGSI_PROCESSOR_VERTEX, header);
-
-   ti = 3;
-
-   /*
-    * decl i0              ; Vertex pos
-    * decl i1              ; Luma texcoords
-    * decl i2              ; Chroma Cb texcoords
-    * decl i3              ; Chroma Cr texcoords
-    */
-   for (unsigned i = 0; i < 4; i++)
-   {
-      decl = vl_decl_input(i == 0 ? TGSI_SEMANTIC_POSITION : TGSI_SEMANTIC_GENERIC, i, i, i);
-      ti += tgsi_build_full_declaration(&decl, &tokens[ti], header, max_tokens - ti);
-   }
+   shader = ureg_create(TGSI_PROCESSOR_VERTEX);
+   if (!shader)
+      return false;
 
-   /*
-    * decl o0              ; Vertex pos
-    * decl o1              ; Luma texcoords
-    * decl o2              ; Chroma Cb texcoords
-    * decl o3              ; Chroma Cr texcoords
-    */
-   for (unsigned i = 0; i < 4; i++)
-   {
-      decl = vl_decl_output(i == 0 ? TGSI_SEMANTIC_POSITION : TGSI_SEMANTIC_GENERIC, i, i, i);
-      ti += tgsi_build_full_declaration(&decl, &tokens[ti], header, max_tokens - ti);
-   }
+   vpos = ureg_DECL_vs_input(shader, 0);
+   for (i = 0; i < 3; ++i)
+      vtex[i] = ureg_DECL_vs_input(shader, i + 1);
+   o_vpos = ureg_DECL_output(shader, TGSI_SEMANTIC_POSITION, 0);
+   for (i = 0; i < 3; ++i)
+      o_vtex[i] = ureg_DECL_output(shader, TGSI_SEMANTIC_GENERIC, i + 1);
 
    /*
-    * mov o0, i0           ; Move input vertex pos to output
-    * mov o1, i1           ; Move input luma texcoords to output
-    * mov o2, i2           ; Move input chroma Cb texcoords to output
-    * mov o3, i3           ; Move input chroma Cr texcoords to output
+    * o_vpos = vpos
+    * o_vtex[0..2] = vtex[0..2]
     */
-   for (unsigned i = 0; i < 4; ++i)
-   {
-      inst = vl_inst2(TGSI_OPCODE_MOV, TGSI_FILE_OUTPUT, i, TGSI_FILE_INPUT, i);
-      ti += tgsi_build_full_instruction(&inst, &tokens[ti], header, max_tokens - ti);
-   }
+   ureg_MOV(shader, o_vpos, vpos);
+   for (i = 0; i < 3; ++i)
+      ureg_MOV(shader, o_vtex[i], vtex[i]);
 
-   /* end */
-   inst = vl_end();
-   ti += tgsi_build_full_instruction(&inst, &tokens[ti], header, max_tokens - ti);
+   ureg_END(shader);
 
-   assert(ti <= max_tokens);
+   r->i_vs = ureg_create_shader_and_destroy(shader, r->pipe);
+   if (!r->i_vs)
+      return false;
 
-   vs.tokens = tokens;
-   r->i_vs = r->pipe->create_vs_state(r->pipe, &vs);
-   free(tokens);
+   return true;
 }
 
-static void
+static bool
 create_intra_frag_shader(struct vl_mpeg12_mc_renderer *r)
 {
-   const unsigned max_tokens = 100;
-
-   struct pipe_shader_state fs;
-   struct tgsi_token *tokens;
-   struct tgsi_header *header;
-
-   struct tgsi_full_declaration decl;
-   struct tgsi_full_instruction inst;
-
-   unsigned ti;
-
-   assert(r);
-
-   tokens = (struct tgsi_token *) malloc(max_tokens * sizeof(struct tgsi_token));
-   *(struct tgsi_version *) &tokens[0] = tgsi_build_version();
-   header = (struct tgsi_header *) &tokens[1];
-   *header = tgsi_build_header();
-   *(struct tgsi_processor *) &tokens[2] = tgsi_build_processor(TGSI_PROCESSOR_FRAGMENT, header);
-
-   ti = 3;
-
-   /*
-    * decl i0                      ; Luma texcoords
-    * decl i1                      ; Chroma Cb texcoords
-    * decl i2                      ; Chroma Cr texcoords
-    */
-   for (unsigned i = 0; i < 3; ++i)
-   {
-      decl = vl_decl_interpolated_input(TGSI_SEMANTIC_GENERIC, i + 1, i, i, TGSI_INTERPOLATE_LINEAR);
-      ti += tgsi_build_full_declaration(&decl, &tokens[ti], header, max_tokens - ti);
-   }
-
-   /* decl c0                      ; Scaling factor, rescales 16-bit snorm to 9-bit snorm */
-   decl = vl_decl_constants(TGSI_SEMANTIC_GENERIC, 0, 0, 0);
-   ti += tgsi_build_full_declaration(&decl, &tokens[ti], header, max_tokens - ti);
-
-   /* decl o0                      ; Fragment color */
-   decl = vl_decl_output(TGSI_SEMANTIC_COLOR, 0, 0, 0);
-   ti += tgsi_build_full_declaration(&decl, &tokens[ti], header, max_tokens - ti);
-
-   /* decl t0, t1 */
-   decl = vl_decl_temps(0, 1);
-   ti += tgsi_build_full_declaration(&decl, &tokens[ti], header, max_tokens - ti);
+   struct ureg_program *shader;
+   struct ureg_src tc[3];
+   struct ureg_src sampler[3];
+   struct ureg_dst texel, temp;
+   struct ureg_dst fragment;
+   unsigned i;
+
+   shader = ureg_create(TGSI_PROCESSOR_FRAGMENT);
+   if (!shader)
+      return false;
 
-   /*
-    * decl s0                      ; Sampler for luma texture
-    * decl s1                      ; Sampler for chroma Cb texture
-    * decl s2                      ; Sampler for chroma Cr texture
-    */
-   for (unsigned i = 0; i < 3; ++i)
-   {
-      decl = vl_decl_samplers(i, i);
-      ti += tgsi_build_full_declaration(&decl, &tokens[ti], header, max_tokens - ti);
+   for (i = 0; i < 3; ++i)  {
+      tc[i] = ureg_DECL_fs_input(shader, TGSI_SEMANTIC_GENERIC, i + 1, TGSI_INTERPOLATE_LINEAR);
+      sampler[i] = ureg_DECL_sampler(shader, i);
    }
+   texel = ureg_DECL_temporary(shader);
+   temp = ureg_DECL_temporary(shader);
+   fragment = ureg_DECL_output(shader, TGSI_SEMANTIC_COLOR, 0);
 
    /*
-    * tex2d t1, i0, s0             ; Read texel from luma texture
-    * mov t0.x, t1.x               ; Move luma sample into .x component
-    * tex2d t1, i1, s1             ; Read texel from chroma Cb texture
-    * mov t0.y, t1.x               ; Move Cb sample into .y component
-    * tex2d t1, i2, s2             ; Read texel from chroma Cr texture
-    * mov t0.z, t1.x               ; Move Cr sample into .z component
+    * texel.r = tex(tc[0], sampler[0])
+    * texel.g = tex(tc[1], sampler[1])
+    * texel.b = tex(tc[2], sampler[2])
+    * fragment = texel * scale
     */
-   for (unsigned i = 0; i < 3; ++i)
-   {
-      inst = vl_tex(TGSI_TEXTURE_2D, TGSI_FILE_TEMPORARY, 1, TGSI_FILE_INPUT, i, TGSI_FILE_SAMPLER, i);
-      ti += tgsi_build_full_instruction(&inst, &tokens[ti], header, max_tokens - ti);
-
-      inst = vl_inst2(TGSI_OPCODE_MOV, TGSI_FILE_TEMPORARY, 0, TGSI_FILE_TEMPORARY, 1);
-      inst.FullSrcRegisters[0].SrcRegister.SwizzleX = TGSI_SWIZZLE_X;
-      inst.FullSrcRegisters[0].SrcRegister.SwizzleY = TGSI_SWIZZLE_X;
-      inst.FullSrcRegisters[0].SrcRegister.SwizzleZ = TGSI_SWIZZLE_X;
-      inst.FullDstRegisters[0].DstRegister.WriteMask = TGSI_WRITEMASK_X << i;
-      ti += tgsi_build_full_instruction(&inst, &tokens[ti], header, max_tokens - ti);
+   for (i = 0; i < 3; ++i) {
+      /* Nouveau can't writemask tex dst regs (yet?), do in two steps */
+      ureg_TEX(shader, temp, TGSI_TEXTURE_2D, tc[i], sampler[i]);
+      ureg_MOV(shader, ureg_writemask(texel, TGSI_WRITEMASK_X << i), ureg_scalar(ureg_src(temp), TGSI_SWIZZLE_X));
    }
+   ureg_MUL(shader, fragment, ureg_src(texel), ureg_scalar(ureg_imm1f(shader, SCALE_FACTOR_16_TO_9), TGSI_SWIZZLE_X));
 
-   /* mul o0, t0, c0               ; Rescale texel to correct range */
-   inst = vl_inst3(TGSI_OPCODE_MUL, TGSI_FILE_OUTPUT, 0, TGSI_FILE_TEMPORARY, 0, TGSI_FILE_CONSTANT, 0);
-   ti += tgsi_build_full_instruction(&inst, &tokens[ti], header, max_tokens - ti);
+   ureg_release_temporary(shader, texel);
+   ureg_release_temporary(shader, temp);
+   ureg_END(shader);
 
-   /* end */
-   inst = vl_end();
-   ti += tgsi_build_full_instruction(&inst, &tokens[ti], header, max_tokens - ti);
-
-   assert(ti <= max_tokens);
+   r->i_fs = ureg_create_shader_and_destroy(shader, r->pipe);
+   if (!r->i_fs)
+      return false;
 
-   fs.tokens = tokens;
-   r->i_fs = r->pipe->create_fs_state(r->pipe, &fs);
-   free(tokens);
+   return true;
 }
 
-static void
+static bool
 create_frame_pred_vert_shader(struct vl_mpeg12_mc_renderer *r)
 {
-   const unsigned max_tokens = 100;
-
-   struct pipe_shader_state vs;
-   struct tgsi_token *tokens;
-   struct tgsi_header *header;
+   struct ureg_program *shader;
+   struct ureg_src vpos, vtex[4];
+   struct ureg_dst o_vpos, o_vtex[4];
+   unsigned i;
 
-   struct tgsi_full_declaration decl;
-   struct tgsi_full_instruction inst;
-
-   unsigned ti;
-
-   assert(r);
-
-   tokens = (struct tgsi_token *) malloc(max_tokens * sizeof(struct tgsi_token));
-   *(struct tgsi_version *) &tokens[0] = tgsi_build_version();
-   header = (struct tgsi_header *) &tokens[1];
-   *header = tgsi_build_header();
-   *(struct tgsi_processor *) &tokens[2] = tgsi_build_processor(TGSI_PROCESSOR_VERTEX, header);
-
-   ti = 3;
-
-   /*
-    * decl i0              ; Vertex pos
-    * decl i1              ; Luma texcoords
-    * decl i2              ; Chroma Cb texcoords
-    * decl i3              ; Chroma Cr texcoords
-    * decl i4              ; Ref surface top field texcoords
-    * decl i5              ; Ref surface bottom field texcoords (unused, packed in the same stream)
-    */
-   for (unsigned i = 0; i < 6; i++)
-   {
-      decl = vl_decl_input(i == 0 ? TGSI_SEMANTIC_POSITION : TGSI_SEMANTIC_GENERIC, i, i, i);
-      ti += tgsi_build_full_declaration(&decl, &tokens[ti], header, max_tokens - ti);
-   }
+   shader = ureg_create(TGSI_PROCESSOR_VERTEX);
+   if (!shader)
+      return false;
 
-   /*
-    * decl o0              ; Vertex pos
-    * decl o1              ; Luma texcoords
-    * decl o2              ; Chroma Cb texcoords
-    * decl o3              ; Chroma Cr texcoords
-    * decl o4              ; Ref macroblock texcoords
-    */
-   for (unsigned i = 0; i < 5; i++)
-   {
-      decl = vl_decl_output(i == 0 ? TGSI_SEMANTIC_POSITION : TGSI_SEMANTIC_GENERIC, i, i, i);
-      ti += tgsi_build_full_declaration(&decl, &tokens[ti], header, max_tokens - ti);
-   }
+   vpos = ureg_DECL_vs_input(shader, 0);
+   for (i = 0; i < 4; ++i)
+      vtex[i] = ureg_DECL_vs_input(shader, i + 1);
+   o_vpos = ureg_DECL_output(shader, TGSI_SEMANTIC_POSITION, 0);
+   for (i = 0; i < 4; ++i)
+      o_vtex[i] = ureg_DECL_output(shader, TGSI_SEMANTIC_GENERIC, i + 1);
 
    /*
-    * mov o0, i0           ; Move input vertex pos to output
-    * mov o1, i1           ; Move input luma texcoords to output
-    * mov o2, i2           ; Move input chroma Cb texcoords to output
-    * mov o3, i3           ; Move input chroma Cr texcoords to output
+    * o_vpos = vpos
+    * o_vtex[0..2] = vtex[0..2]
+    * o_vtex[3] = vpos + vtex[3] // Apply motion vector
     */
-   for (unsigned i = 0; i < 4; ++i)
-   {
-        inst = vl_inst2(TGSI_OPCODE_MOV, TGSI_FILE_OUTPUT, i, TGSI_FILE_INPUT, i);
-        ti += tgsi_build_full_instruction(&inst, &tokens[ti], header, max_tokens - ti);
-   }
+   ureg_MOV(shader, o_vpos, vpos);
+   for (i = 0; i < 3; ++i)
+      ureg_MOV(shader, o_vtex[i], vtex[i]);
+   ureg_ADD(shader, o_vtex[3], vpos, vtex[3]);
 
-   /* add o4, i0, i4       ; Translate vertex pos by motion vec to form ref macroblock texcoords */
-   inst = vl_inst3(TGSI_OPCODE_ADD, TGSI_FILE_OUTPUT, 4, TGSI_FILE_INPUT, 0, TGSI_FILE_INPUT, 4);
-   ti += tgsi_build_full_instruction(&inst, &tokens[ti], header, max_tokens - ti);
+   ureg_END(shader);
 
-   /* end */
-   inst = vl_end();
-   ti += tgsi_build_full_instruction(&inst, &tokens[ti], header, max_tokens - ti);
-
-   assert(ti <= max_tokens);
+   r->p_vs[0] = ureg_create_shader_and_destroy(shader, r->pipe);
+   if (!r->p_vs[0])
+      return false;
 
-   vs.tokens = tokens;
-   r->p_vs[0] = r->pipe->create_vs_state(r->pipe, &vs);
-   free(tokens);
+   return true;
 }
 
+#if 0
 static void
 create_field_pred_vert_shader(struct vl_mpeg12_mc_renderer *r)
 {
    assert(false);
 }
+#endif
 
-static void
+static bool
 create_frame_pred_frag_shader(struct vl_mpeg12_mc_renderer *r)
 {
-   const unsigned max_tokens = 100;
-
-   struct pipe_shader_state fs;
-   struct tgsi_token *tokens;
-   struct tgsi_header *header;
-
-   struct tgsi_full_declaration decl;
-   struct tgsi_full_instruction inst;
-
-   unsigned ti;
-
-   assert(r);
-
-   tokens = (struct tgsi_token *) malloc(max_tokens * sizeof(struct tgsi_token));
-   *(struct tgsi_version *) &tokens[0] = tgsi_build_version();
-   header = (struct tgsi_header *) &tokens[1];
-   *header = tgsi_build_header();
-   *(struct tgsi_processor *) &tokens[2] = tgsi_build_processor(TGSI_PROCESSOR_FRAGMENT, header);
-
-   ti = 3;
-
-   /*
-    * decl i0                      ; Luma texcoords
-    * decl i1                      ; Chroma Cb texcoords
-    * decl i2                      ; Chroma Cr texcoords
-    * decl i3                      ; Ref macroblock texcoords
-    */
-   for (unsigned i = 0; i < 4; ++i)
-   {
-      decl = vl_decl_interpolated_input(TGSI_SEMANTIC_GENERIC, i + 1, i, i, TGSI_INTERPOLATE_LINEAR);
-      ti += tgsi_build_full_declaration(&decl, &tokens[ti], header, max_tokens - ti);
-   }
-
-   /* decl c0                      ; Scaling factor, rescales 16-bit snorm to 9-bit snorm */
-   decl = vl_decl_constants(TGSI_SEMANTIC_GENERIC, 0, 0, 0);
-   ti += tgsi_build_full_declaration(&decl, &tokens[ti], header, max_tokens - ti);
-
-   /* decl o0                      ; Fragment color */
-   decl = vl_decl_output(TGSI_SEMANTIC_COLOR, 0, 0, 0);
-   ti += tgsi_build_full_declaration(&decl, &tokens[ti], header, max_tokens - ti);
-
-   /* decl t0, t1 */
-   decl = vl_decl_temps(0, 1);
-   ti += tgsi_build_full_declaration(&decl, &tokens[ti], header, max_tokens - ti);
+   struct ureg_program *shader;
+   struct ureg_src tc[4];
+   struct ureg_src sampler[4];
+   struct ureg_dst texel, ref;
+   struct ureg_dst fragment;
+   unsigned i;
+
+   shader = ureg_create(TGSI_PROCESSOR_FRAGMENT);
+   if (!shader)
+      return false;
 
-   /*
-    * decl s0                      ; Sampler for luma texture
-    * decl s1                      ; Sampler for chroma Cb texture
-    * decl s2                      ; Sampler for chroma Cr texture
-    * decl s3                      ; Sampler for ref surface texture
-    */
-   for (unsigned i = 0; i < 4; ++i)
-   {
-      decl = vl_decl_samplers(i, i);
-      ti += tgsi_build_full_declaration(&decl, &tokens[ti], header, max_tokens - ti);
+   for (i = 0; i < 4; ++i)  {
+      tc[i] = ureg_DECL_fs_input(shader, TGSI_SEMANTIC_GENERIC, i + 1, TGSI_INTERPOLATE_LINEAR);
+      sampler[i] = ureg_DECL_sampler(shader, i);
    }
+   texel = ureg_DECL_temporary(shader);
+   ref = ureg_DECL_temporary(shader);
+   fragment = ureg_DECL_output(shader, TGSI_SEMANTIC_COLOR, 0);
 
    /*
-    * tex2d t1, i0, s0             ; Read texel from luma texture
-    * mov t0.x, t1.x               ; Move luma sample into .x component
-    * tex2d t1, i1, s1             ; Read texel from chroma Cb texture
-    * mov t0.y, t1.x               ; Move Cb sample into .y component
-    * tex2d t1, i2, s2             ; Read texel from chroma Cr texture
-    * mov t0.z, t1.x               ; Move Cr sample into .z component
+    * texel.r = tex(tc[0], sampler[0])
+    * texel.g = tex(tc[1], sampler[1])
+    * texel.b = tex(tc[2], sampler[2])
+    * ref = tex(tc[3], sampler[3])
+    * fragment = texel * scale + ref
     */
-   for (unsigned i = 0; i < 3; ++i)
-   {
-      inst = vl_tex(TGSI_TEXTURE_2D, TGSI_FILE_TEMPORARY, 1, TGSI_FILE_INPUT, i, TGSI_FILE_SAMPLER, i);
-      ti += tgsi_build_full_instruction(&inst, &tokens[ti], header, max_tokens - ti);
-
-      inst = vl_inst2(TGSI_OPCODE_MOV, TGSI_FILE_TEMPORARY, 0, TGSI_FILE_TEMPORARY, 1);
-      inst.FullSrcRegisters[0].SrcRegister.SwizzleX = TGSI_SWIZZLE_X;
-      inst.FullSrcRegisters[0].SrcRegister.SwizzleY = TGSI_SWIZZLE_X;
-      inst.FullSrcRegisters[0].SrcRegister.SwizzleZ = TGSI_SWIZZLE_X;
-      inst.FullDstRegisters[0].DstRegister.WriteMask = TGSI_WRITEMASK_X << i;
-      ti += tgsi_build_full_instruction(&inst, &tokens[ti], header, max_tokens - ti);
+   for (i = 0; i < 3; ++i) {
+      /* Nouveau can't writemask tex dst regs (yet?), do in two steps */
+      ureg_TEX(shader, ref, TGSI_TEXTURE_2D, tc[i], sampler[i]);
+      ureg_MOV(shader, ureg_writemask(texel, TGSI_WRITEMASK_X << i), ureg_scalar(ureg_src(ref), TGSI_SWIZZLE_X));
    }
+   ureg_TEX(shader, ref, TGSI_TEXTURE_2D, tc[3], sampler[3]);
+   ureg_MAD(shader, fragment, ureg_src(texel), ureg_scalar(ureg_imm1f(shader, SCALE_FACTOR_16_TO_9), TGSI_SWIZZLE_X), ureg_src(ref));
 
-   /* mul t0, t0, c0               ; Rescale texel to correct range */
-   inst = vl_inst3(TGSI_OPCODE_MUL, TGSI_FILE_TEMPORARY, 0, TGSI_FILE_TEMPORARY, 0, TGSI_FILE_CONSTANT, 0);
-   ti += tgsi_build_full_instruction(&inst, &tokens[ti], header, max_tokens - ti);
-
-   /* tex2d t1, i3, s3             ; Read texel from ref macroblock */
-   inst = vl_tex(TGSI_TEXTURE_2D, TGSI_FILE_TEMPORARY, 1, TGSI_FILE_INPUT, 3, TGSI_FILE_SAMPLER, 3);
-   ti += tgsi_build_full_instruction(&inst, &tokens[ti], header, max_tokens - ti);
+   ureg_release_temporary(shader, texel);
+   ureg_release_temporary(shader, ref);
+   ureg_END(shader);
 
-   /* add o0, t0, t1               ; Add ref and differential to form final output */
-   inst = vl_inst3(TGSI_OPCODE_ADD, TGSI_FILE_OUTPUT, 0, TGSI_FILE_TEMPORARY, 0, TGSI_FILE_TEMPORARY, 1);
-   ti += tgsi_build_full_instruction(&inst, &tokens[ti], header, max_tokens - ti);
-
-   /* end */
-   inst = vl_end();
-   ti += tgsi_build_full_instruction(&inst, &tokens[ti], header, max_tokens - ti);
-
-   assert(ti <= max_tokens);
+   r->p_fs[0] = ureg_create_shader_and_destroy(shader, r->pipe);
+   if (!r->p_fs[0])
+      return false;
 
-   fs.tokens = tokens;
-   r->p_fs[0] = r->pipe->create_fs_state(r->pipe, &fs);
-   free(tokens);
+   return true;
 }
 
+#if 0
 static void
 create_field_pred_frag_shader(struct vl_mpeg12_mc_renderer *r)
 {
    assert(false);
 }
+#endif
 
-static void
+static bool
 create_frame_bi_pred_vert_shader(struct vl_mpeg12_mc_renderer *r)
 {
-   const unsigned max_tokens = 100;
-
-   struct pipe_shader_state vs;
-   struct tgsi_token *tokens;
-   struct tgsi_header *header;
+   struct ureg_program *shader;
+   struct ureg_src vpos, vtex[5];
+   struct ureg_dst o_vpos, o_vtex[5];
+   unsigned i;
 
-   struct tgsi_full_declaration decl;
-   struct tgsi_full_instruction inst;
-
-   unsigned ti;
-
-   assert(r);
-
-   tokens = (struct tgsi_token *) malloc(max_tokens * sizeof(struct tgsi_token));
-   *(struct tgsi_version *) &tokens[0] = tgsi_build_version();
-   header = (struct tgsi_header *) &tokens[1];
-   *header = tgsi_build_header();
-   *(struct tgsi_processor *) &tokens[2] = tgsi_build_processor(TGSI_PROCESSOR_VERTEX, header);
-
-   ti = 3;
-
-   /*
-    * decl i0              ; Vertex pos
-    * decl i1              ; Luma texcoords
-    * decl i2              ; Chroma Cb texcoords
-    * decl i3              ; Chroma Cr texcoords
-    * decl i4              ; First ref macroblock top field texcoords
-    * decl i5              ; First ref macroblock bottom field texcoords (unused, packed in the same stream)
-    * decl i6              ; Second ref macroblock top field texcoords
-    * decl i7              ; Second ref macroblock bottom field texcoords (unused, packed in the same stream)
-    */
-   for (unsigned i = 0; i < 8; i++)
-   {
-      decl = vl_decl_input(i == 0 ? TGSI_SEMANTIC_POSITION : TGSI_SEMANTIC_GENERIC, i, i, i);
-      ti += tgsi_build_full_declaration(&decl, &tokens[ti], header, max_tokens - ti);
-   }
-
-   /*
-    * decl o0              ; Vertex pos
-    * decl o1              ; Luma texcoords
-    * decl o2              ; Chroma Cb texcoords
-    * decl o3              ; Chroma Cr texcoords
-    * decl o4              ; First ref macroblock texcoords
-    * decl o5              ; Second ref macroblock texcoords
-    */
-   for (unsigned i = 0; i < 6; i++)
-   {
-      decl = vl_decl_output(i == 0 ? TGSI_SEMANTIC_POSITION : TGSI_SEMANTIC_GENERIC, i, i, i);
-      ti += tgsi_build_full_declaration(&decl, &tokens[ti], header, max_tokens - ti);
-   }
+   shader = ureg_create(TGSI_PROCESSOR_VERTEX);
+   if (!shader)
+      return false;
 
-   /*
-    * mov o0, i0           ; Move input vertex pos to output
-    * mov o1, i1           ; Move input luma texcoords to output
-    * mov o2, i2           ; Move input chroma Cb texcoords to output
-    * mov o3, i3           ; Move input chroma Cr texcoords to output
-    */
-   for (unsigned i = 0; i < 4; ++i)
-   {
-      inst = vl_inst2(TGSI_OPCODE_MOV, TGSI_FILE_OUTPUT, i, TGSI_FILE_INPUT, i);
-      ti += tgsi_build_full_instruction(&inst, &tokens[ti], header, max_tokens - ti);
-   }
+   vpos = ureg_DECL_vs_input(shader, 0);
+   for (i = 0; i < 4; ++i)
+      vtex[i] = ureg_DECL_vs_input(shader, i + 1);
+   /* Skip input 5 */
+   vtex[4] = ureg_DECL_vs_input(shader, 6);
+   o_vpos = ureg_DECL_output(shader, TGSI_SEMANTIC_POSITION, 0);
+   for (i = 0; i < 5; ++i)
+      o_vtex[i] = ureg_DECL_output(shader, TGSI_SEMANTIC_GENERIC, i + 1);
 
    /*
-    * add o4, i0, i4       ; Translate vertex pos by motion vec to form first ref macroblock texcoords
-    * add o5, i0, i6       ; Translate vertex pos by motion vec to form second ref macroblock texcoords
+    * o_vpos = vpos
+    * o_vtex[0..2] = vtex[0..2]
+    * o_vtex[3..4] = vpos + vtex[3..4] // Apply motion vector
     */
-   for (unsigned i = 0; i < 2; ++i)
-   {
-      inst = vl_inst3(TGSI_OPCODE_ADD, TGSI_FILE_OUTPUT, i + 4, TGSI_FILE_INPUT, 0, TGSI_FILE_INPUT, (i + 2) * 2);
-      ti += tgsi_build_full_instruction(&inst, &tokens[ti], header, max_tokens - ti);
-   }
+   ureg_MOV(shader, o_vpos, vpos);
+   for (i = 0; i < 3; ++i)
+      ureg_MOV(shader, o_vtex[i], vtex[i]);
+   for (i = 3; i < 5; ++i)
+      ureg_ADD(shader, o_vtex[i], vpos, vtex[i]);
 
-   /* end */
-   inst = vl_end();
-   ti += tgsi_build_full_instruction(&inst, &tokens[ti], header, max_tokens - ti);
+   ureg_END(shader);
 
-   assert(ti <= max_tokens);
+   r->b_vs[0] = ureg_create_shader_and_destroy(shader, r->pipe);
+   if (!r->b_vs[0])
+      return false;
 
-   vs.tokens = tokens;
-   r->b_vs[0] = r->pipe->create_vs_state(r->pipe, &vs);
-   free(tokens);
+   return true;
 }
 
+#if 0
 static void
 create_field_bi_pred_vert_shader(struct vl_mpeg12_mc_renderer *r)
 {
    assert(false);
 }
+#endif
 
-static void
+static bool
 create_frame_bi_pred_frag_shader(struct vl_mpeg12_mc_renderer *r)
 {
-   const unsigned max_tokens = 100;
-
-   struct pipe_shader_state fs;
-   struct tgsi_token *tokens;
-   struct tgsi_header *header;
-
-   struct tgsi_full_declaration decl;
-   struct tgsi_full_instruction inst;
-
-   unsigned ti;
-
-   assert(r);
-
-   tokens = (struct tgsi_token *) malloc(max_tokens * sizeof(struct tgsi_token));
-   *(struct tgsi_version *) &tokens[0] = tgsi_build_version();
-   header = (struct tgsi_header *) &tokens[1];
-   *header = tgsi_build_header();
-   *(struct tgsi_processor *) &tokens[2] = tgsi_build_processor(TGSI_PROCESSOR_FRAGMENT, header);
-
-   ti = 3;
-
-   /*
-    * decl i0                      ; Luma texcoords
-    * decl i1                      ; Chroma Cb texcoords
-    * decl i2                      ; Chroma Cr texcoords
-    * decl i3                      ; First ref macroblock texcoords
-    * decl i4                      ; Second ref macroblock texcoords
-    */
-   for (unsigned i = 0; i < 5; ++i)
-   {
-      decl = vl_decl_interpolated_input(TGSI_SEMANTIC_GENERIC, i + 1, i, i, TGSI_INTERPOLATE_LINEAR);
-      ti += tgsi_build_full_declaration(&decl, &tokens[ti], header, max_tokens - ti);
-   }
-
-   /*
-    * decl c0                      ; Scaling factor, rescales 16-bit snorm to 9-bit snorm
-    * decl c1                      ; Constant 1/2 in .x channel to use as weight to blend past and future texels
-    */
-   decl = vl_decl_constants(TGSI_SEMANTIC_GENERIC, 0, 0, 1);
-   ti += tgsi_build_full_declaration(&decl, &tokens[ti], header, max_tokens - ti);
-
-   /* decl o0                      ; Fragment color */
-   decl = vl_decl_output(TGSI_SEMANTIC_COLOR, 0, 0, 0);
-   ti += tgsi_build_full_declaration(&decl, &tokens[ti], header, max_tokens - ti);
-
-   /* decl t0-t2 */
-   decl = vl_decl_temps(0, 2);
-   ti += tgsi_build_full_declaration(&decl, &tokens[ti], header, max_tokens - ti);
+   struct ureg_program *shader;
+   struct ureg_src tc[5];
+   struct ureg_src sampler[5];
+   struct ureg_dst texel, ref[2];
+   struct ureg_dst fragment;
+   unsigned i;
+
+   shader = ureg_create(TGSI_PROCESSOR_FRAGMENT);
+   if (!shader)
+      return false;
 
-   /*
-    * decl s0                      ; Sampler for luma texture
-    * decl s1                      ; Sampler for chroma Cb texture
-    * decl s2                      ; Sampler for chroma Cr texture
-    * decl s3                      ; Sampler for first ref surface texture
-    * decl s4                      ; Sampler for second ref surface texture
-    */
-   for (unsigned i = 0; i < 5; ++i)
-   {
-      decl = vl_decl_samplers(i, i);
-      ti += tgsi_build_full_declaration(&decl, &tokens[ti], header, max_tokens - ti);
+   for (i = 0; i < 5; ++i)  {
+      tc[i] = ureg_DECL_fs_input(shader, TGSI_SEMANTIC_GENERIC, i + 1, TGSI_INTERPOLATE_LINEAR);
+      sampler[i] = ureg_DECL_sampler(shader, i);
    }
+   texel = ureg_DECL_temporary(shader);
+   ref[0] = ureg_DECL_temporary(shader);
+   ref[1] = ureg_DECL_temporary(shader);
+   fragment = ureg_DECL_output(shader, TGSI_SEMANTIC_COLOR, 0);
 
    /*
-    * tex2d t1, i0, s0             ; Read texel from luma texture
-    * mov t0.x, t1.x               ; Move luma sample into .x component
-    * tex2d t1, i1, s1             ; Read texel from chroma Cb texture
-    * mov t0.y, t1.x               ; Move Cb sample into .y component
-    * tex2d t1, i2, s2             ; Read texel from chroma Cr texture
-    * mov t0.z, t1.x               ; Move Cr sample into .z component
+    * texel.r = tex(tc[0], sampler[0])
+    * texel.g = tex(tc[1], sampler[1])
+    * texel.b = tex(tc[2], sampler[2])
+    * ref[0..1 = tex(tc[3..4], sampler[3..4])
+    * ref[0] = lerp(ref[0], ref[1], 0.5)
+    * fragment = texel * scale + ref[0]
     */
-   for (unsigned i = 0; i < 3; ++i)
-   {
-      inst = vl_tex(TGSI_TEXTURE_2D, TGSI_FILE_TEMPORARY, 1, TGSI_FILE_INPUT, i, TGSI_FILE_SAMPLER, i);
-      ti += tgsi_build_full_instruction(&inst, &tokens[ti], header, max_tokens - ti);
-
-      inst = vl_inst2(TGSI_OPCODE_MOV, TGSI_FILE_TEMPORARY, 0, TGSI_FILE_TEMPORARY, 1);
-      inst.FullSrcRegisters[0].SrcRegister.SwizzleX = TGSI_SWIZZLE_X;
-      inst.FullSrcRegisters[0].SrcRegister.SwizzleY = TGSI_SWIZZLE_X;
-      inst.FullSrcRegisters[0].SrcRegister.SwizzleZ = TGSI_SWIZZLE_X;
-      inst.FullDstRegisters[0].DstRegister.WriteMask = TGSI_WRITEMASK_X << i;
-      ti += tgsi_build_full_instruction(&inst, &tokens[ti], header, max_tokens - ti);
+   for (i = 0; i < 3; ++i) {
+      /* Nouveau can't writemask tex dst regs (yet?), do in two steps */
+      ureg_TEX(shader, ref[0], TGSI_TEXTURE_2D, tc[i], sampler[i]);
+      ureg_MOV(shader, ureg_writemask(texel, TGSI_WRITEMASK_X << i), ureg_scalar(ureg_src(ref[0]), TGSI_SWIZZLE_X));
    }
+   ureg_TEX(shader, ref[0], TGSI_TEXTURE_2D, tc[3], sampler[3]);
+   ureg_TEX(shader, ref[1], TGSI_TEXTURE_2D, tc[4], sampler[4]);
+   ureg_LRP(shader, ref[0], ureg_scalar(ureg_imm1f(shader, 0.5f), TGSI_SWIZZLE_X), ureg_src(ref[0]), ureg_src(ref[1]));
 
-   /* mul t0, t0, c0               ; Rescale texel to correct range */
-   inst = vl_inst3(TGSI_OPCODE_MUL, TGSI_FILE_TEMPORARY, 0, TGSI_FILE_TEMPORARY, 0, TGSI_FILE_CONSTANT, 0);
-   ti += tgsi_build_full_instruction(&inst, &tokens[ti], header, max_tokens - ti);
+   ureg_MAD(shader, fragment, ureg_src(texel), ureg_scalar(ureg_imm1f(shader, SCALE_FACTOR_16_TO_9), TGSI_SWIZZLE_X), ureg_src(ref[0]));
 
-   /*
-    * tex2d t1, i3, s3             ; Read texel from first ref macroblock
-    * tex2d t2, i4, s4             ; Read texel from second ref macroblock
-    */
-   for (unsigned i = 0; i < 2; ++i)
-   {
-      inst = vl_tex(TGSI_TEXTURE_2D, TGSI_FILE_TEMPORARY, i + 1, TGSI_FILE_INPUT, i + 3, TGSI_FILE_SAMPLER, i + 3);
-      ti += tgsi_build_full_instruction(&inst, &tokens[ti], header, max_tokens - ti);
-   }
-
-   /* lerp t1, c1.x, t1, t2        ; Blend past and future texels */
-   inst = vl_inst4(TGSI_OPCODE_LRP, TGSI_FILE_TEMPORARY, 1, TGSI_FILE_CONSTANT, 1, TGSI_FILE_TEMPORARY, 1, TGSI_FILE_TEMPORARY, 2);
-   inst.FullSrcRegisters[0].SrcRegister.SwizzleX = TGSI_SWIZZLE_X;
-   inst.FullSrcRegisters[0].SrcRegister.SwizzleY = TGSI_SWIZZLE_X;
-   inst.FullSrcRegisters[0].SrcRegister.SwizzleZ = TGSI_SWIZZLE_X;
-   inst.FullSrcRegisters[0].SrcRegister.SwizzleW = TGSI_SWIZZLE_X;
-   ti += tgsi_build_full_instruction(&inst, &tokens[ti], header, max_tokens - ti);
-
-   /* add o0, t0, t1               ; Add past/future ref and differential to form final output */
-   inst = vl_inst3(TGSI_OPCODE_ADD, TGSI_FILE_OUTPUT, 0, TGSI_FILE_TEMPORARY, 0, TGSI_FILE_TEMPORARY, 1);
-   ti += tgsi_build_full_instruction(&inst, &tokens[ti], header, max_tokens - ti);
+   ureg_release_temporary(shader, texel);
+   ureg_release_temporary(shader, ref[0]);
+   ureg_release_temporary(shader, ref[1]);
+   ureg_END(shader);
 
-   /* end */
-   inst = vl_end();
-   ti += tgsi_build_full_instruction(&inst, &tokens[ti], header, max_tokens - ti);
-
-   assert(ti <= max_tokens);
+   r->b_fs[0] = ureg_create_shader_and_destroy(shader, r->pipe);
+   if (!r->b_fs[0])
+      return false;
 
-   fs.tokens = tokens;
-   r->b_fs[0] = r->pipe->create_fs_state(r->pipe, &fs);
-   free(tokens);
+   return true;
 }
 
+#if 0
 static void
 create_field_bi_pred_frag_shader(struct vl_mpeg12_mc_renderer *r)
 {
    assert(false);
 }
+#endif
 
 static void
 xfer_buffers_map(struct vl_mpeg12_mc_renderer *r)
 {
+   unsigned i;
+
    assert(r);
 
-   for (unsigned i = 0; i < 3; ++i)
-   {
+   for (i = 0; i < 3; ++i) {
       r->tex_transfer[i] = r->pipe->screen->get_tex_transfer
       (
          r->pipe->screen, r->textures.all[i],
          0, 0, 0, PIPE_TRANSFER_WRITE, 0, 0,
-         r->textures.all[i]->width[0], r->textures.all[i]->height[0]
+         r->textures.all[i]->width0, r->textures.all[i]->height0
       );
 
       r->texels[i] = r->pipe->screen->transfer_map(r->pipe->screen, r->tex_transfer[i]);
@@ -671,10 +392,11 @@ xfer_buffers_map(struct vl_mpeg12_mc_renderer *r)
 static void
 xfer_buffers_unmap(struct vl_mpeg12_mc_renderer *r)
 {
+   unsigned i;
+
    assert(r);
 
-   for (unsigned i = 0; i < 3; ++i)
-   {
+   for (i = 0; i < 3; ++i) {
       r->pipe->screen->transfer_unmap(r->pipe->screen, r->tex_transfer[i]);
       r->pipe->screen->tex_transfer_destroy(r->tex_transfer[i]);
    }
@@ -685,6 +407,7 @@ init_pipe_state(struct vl_mpeg12_mc_renderer *r)
 {
    struct pipe_sampler_state sampler;
    unsigned filters[5];
+   unsigned i;
 
    assert(r);
 
@@ -710,13 +433,11 @@ init_pipe_state(struct vl_mpeg12_mc_renderer *r)
    filters[0] = PIPE_TEX_FILTER_NEAREST;
    /* Chroma filters */
    if (r->chroma_format == PIPE_VIDEO_CHROMA_FORMAT_444 ||
-       r->eb_handling == VL_MPEG12_MC_RENDERER_EMPTY_BLOCK_XFER_ONE)
-   {
+       r->eb_handling == VL_MPEG12_MC_RENDERER_EMPTY_BLOCK_XFER_ONE) {
       filters[1] = PIPE_TEX_FILTER_NEAREST;
       filters[2] = PIPE_TEX_FILTER_NEAREST;
    }
-   else
-   {
+   else {
       filters[1] = PIPE_TEX_FILTER_LINEAR;
       filters[2] = PIPE_TEX_FILTER_LINEAR;
    }
@@ -724,8 +445,7 @@ init_pipe_state(struct vl_mpeg12_mc_renderer *r)
    filters[3] = PIPE_TEX_FILTER_LINEAR;
    filters[4] = PIPE_TEX_FILTER_LINEAR;
 
-   for (unsigned i = 0; i < 5; ++i)
-   {
+   for (i = 0; i < 5; ++i) {
       sampler.wrap_s = PIPE_TEX_WRAP_CLAMP_TO_EDGE;
       sampler.wrap_t = PIPE_TEX_WRAP_CLAMP_TO_EDGE;
       sampler.wrap_r = PIPE_TEX_WRAP_CLAMP_TO_EDGE;
@@ -735,7 +455,6 @@ init_pipe_state(struct vl_mpeg12_mc_renderer *r)
       sampler.compare_mode = PIPE_TEX_COMPARE_NONE;
       sampler.compare_func = PIPE_FUNC_ALWAYS;
       sampler.normalized_coords = 1;
-      /*sampler.prefilter = ; */
       /*sampler.shadow_ambient = ; */
       /*sampler.lod_bias = ; */
       sampler.min_lod = 0;
@@ -751,9 +470,11 @@ init_pipe_state(struct vl_mpeg12_mc_renderer *r)
 static void
 cleanup_pipe_state(struct vl_mpeg12_mc_renderer *r)
 {
+   unsigned i;
+
    assert(r);
 
-   for (unsigned i = 0; i < 5; ++i)
+   for (i = 0; i < 5; ++i)
       r->pipe->delete_sampler_state(r->pipe, r->samplers.all[i]);
 }
 
@@ -795,6 +516,8 @@ init_buffers(struct vl_mpeg12_mc_renderer *r)
    const unsigned mbh =
       align(r->picture_height, MACROBLOCK_HEIGHT) / MACROBLOCK_HEIGHT;
 
+   unsigned i;
+
    assert(r);
 
    r->macroblocks_per_batch =
@@ -807,27 +530,25 @@ init_buffers(struct vl_mpeg12_mc_renderer *r)
    /* TODO: Accomodate HW that can't do this and also for cases when this isn't precise enough */
    template.format = PIPE_FORMAT_R16_SNORM;
    template.last_level = 0;
-   template.width[0] = r->pot_buffers ?
+   template.width0 = r->pot_buffers ?
       util_next_power_of_two(r->picture_width) : r->picture_width;
-   template.height[0] = r->pot_buffers ?
+   template.height0 = r->pot_buffers ?
       util_next_power_of_two(r->picture_height) : r->picture_height;
-   template.depth[0] = 1;
-   pf_get_block(template.format, &template.block);
+   template.depth0 = 1;
    template.tex_usage = PIPE_TEXTURE_USAGE_SAMPLER | PIPE_TEXTURE_USAGE_DYNAMIC;
 
    r->textures.individual.y = r->pipe->screen->texture_create(r->pipe->screen, &template);
 
-   if (r->chroma_format == PIPE_VIDEO_CHROMA_FORMAT_420)
-   {
-      template.width[0] = r->pot_buffers ?
+   if (r->chroma_format == PIPE_VIDEO_CHROMA_FORMAT_420) {
+      template.width0 = r->pot_buffers ?
          util_next_power_of_two(r->picture_width / 2) :
          r->picture_width / 2;
-      template.height[0] = r->pot_buffers ?
+      template.height0 = r->pot_buffers ?
          util_next_power_of_two(r->picture_height / 2) :
          r->picture_height / 2;
    }
    else if (r->chroma_format == PIPE_VIDEO_CHROMA_FORMAT_422)
-      template.height[0] = r->pot_buffers ?
+      template.height0 = r->pot_buffers ?
          util_next_power_of_two(r->picture_height / 2) :
          r->picture_height / 2;
 
@@ -847,8 +568,7 @@ init_buffers(struct vl_mpeg12_mc_renderer *r)
       sizeof(struct vertex2f) * 4 * 24 * r->macroblocks_per_batch
    );
 
-   for (unsigned i = 1; i < 3; ++i)
-   {
+   for (i = 1; i < 3; ++i) {
       r->vertex_bufs.all[i].stride = sizeof(struct vertex2f) * 2;
       r->vertex_bufs.all[i].max_index = 24 * r->macroblocks_per_batch - 1;
       r->vertex_bufs.all[i].buffer_offset = 0;
@@ -863,53 +583,61 @@ init_buffers(struct vl_mpeg12_mc_renderer *r)
 
    /* Position element */
    r->vertex_elems[0].src_offset = 0;
+   r->vertex_elems[0].instance_divisor = 0;
    r->vertex_elems[0].vertex_buffer_index = 0;
    r->vertex_elems[0].nr_components = 2;
    r->vertex_elems[0].src_format = PIPE_FORMAT_R32G32_FLOAT;
 
    /* Luma, texcoord element */
    r->vertex_elems[1].src_offset = sizeof(struct vertex2f);
+   r->vertex_elems[1].instance_divisor = 0;
    r->vertex_elems[1].vertex_buffer_index = 0;
    r->vertex_elems[1].nr_components = 2;
    r->vertex_elems[1].src_format = PIPE_FORMAT_R32G32_FLOAT;
 
    /* Chroma Cr texcoord element */
    r->vertex_elems[2].src_offset = sizeof(struct vertex2f) * 2;
+   r->vertex_elems[2].instance_divisor = 0;
    r->vertex_elems[2].vertex_buffer_index = 0;
    r->vertex_elems[2].nr_components = 2;
    r->vertex_elems[2].src_format = PIPE_FORMAT_R32G32_FLOAT;
 
    /* Chroma Cb texcoord element */
    r->vertex_elems[3].src_offset = sizeof(struct vertex2f) * 3;
+   r->vertex_elems[3].instance_divisor = 0;
    r->vertex_elems[3].vertex_buffer_index = 0;
    r->vertex_elems[3].nr_components = 2;
    r->vertex_elems[3].src_format = PIPE_FORMAT_R32G32_FLOAT;
 
    /* First ref surface top field texcoord element */
    r->vertex_elems[4].src_offset = 0;
+   r->vertex_elems[4].instance_divisor = 0;
    r->vertex_elems[4].vertex_buffer_index = 1;
    r->vertex_elems[4].nr_components = 2;
    r->vertex_elems[4].src_format = PIPE_FORMAT_R32G32_FLOAT;
 
    /* First ref surface bottom field texcoord element */
    r->vertex_elems[5].src_offset = sizeof(struct vertex2f);
+   r->vertex_elems[5].instance_divisor = 0;
    r->vertex_elems[5].vertex_buffer_index = 1;
    r->vertex_elems[5].nr_components = 2;
    r->vertex_elems[5].src_format = PIPE_FORMAT_R32G32_FLOAT;
 
    /* Second ref surface top field texcoord element */
    r->vertex_elems[6].src_offset = 0;
+   r->vertex_elems[6].instance_divisor = 0;
    r->vertex_elems[6].vertex_buffer_index = 2;
    r->vertex_elems[6].nr_components = 2;
    r->vertex_elems[6].src_format = PIPE_FORMAT_R32G32_FLOAT;
 
    /* Second ref surface bottom field texcoord element */
    r->vertex_elems[7].src_offset = sizeof(struct vertex2f);
+   r->vertex_elems[7].instance_divisor = 0;
    r->vertex_elems[7].vertex_buffer_index = 2;
    r->vertex_elems[7].nr_components = 2;
    r->vertex_elems[7].src_format = PIPE_FORMAT_R32G32_FLOAT;
 
-   r->vs_const_buf.buffer = pipe_buffer_create
+   r->vs_const_buf = pipe_buffer_create
    (
       r->pipe->screen,
       DEFAULT_BUF_ALIGNMENT,
@@ -917,36 +645,22 @@ init_buffers(struct vl_mpeg12_mc_renderer *r)
       sizeof(struct vertex_shader_consts)
    );
 
-   r->fs_const_buf.buffer = pipe_buffer_create
-   (
-      r->pipe->screen,
-      DEFAULT_BUF_ALIGNMENT,
-      PIPE_BUFFER_USAGE_CONSTANT, sizeof(struct fragment_shader_consts)
-   );
-
-   memcpy
-   (
-      pipe_buffer_map(r->pipe->screen, r->fs_const_buf.buffer, PIPE_BUFFER_USAGE_CPU_WRITE),
-      &fs_consts, sizeof(struct fragment_shader_consts)
-   );
-
-   pipe_buffer_unmap(r->pipe->screen, r->fs_const_buf.buffer);
-
    return true;
 }
 
 static void
 cleanup_buffers(struct vl_mpeg12_mc_renderer *r)
 {
+   unsigned i;
+
    assert(r);
 
-   pipe_buffer_reference(&r->vs_const_buf.buffer, NULL);
-   pipe_buffer_reference(&r->fs_const_buf.buffer, NULL);
+   pipe_buffer_reference(&r->vs_const_buf, NULL);
 
-   for (unsigned i = 0; i < 3; ++i)
+   for (i = 0; i < 3; ++i)
       pipe_buffer_reference(&r->vertex_bufs.all[i].buffer, NULL);
 
-   for (unsigned i = 0; i < 3; ++i)
+   for (i = 0; i < 3; ++i)
       pipe_texture_reference(&r->textures.all[i], NULL);
 
    FREE(r->macroblock_buf);
@@ -957,8 +671,7 @@ get_macroblock_type(struct pipe_mpeg12_macroblock *mb)
 {
    assert(mb);
 
-   switch (mb->mb_type)
-   {
+   switch (mb->mb_type) {
       case PIPE_MPEG12_MACROBLOCK_TYPE_INTRA:
          return MACROBLOCK_TYPE_INTRA;
       case PIPE_MPEG12_MACROBLOCK_TYPE_FWD:
@@ -978,73 +691,105 @@ get_macroblock_type(struct pipe_mpeg12_macroblock *mb)
    return -1;
 }
 
-/* XXX: One of these days this will have to be killed with fire */
-#define SET_BLOCK(vb, cbp, mbx, mby, unitx, unity, ofsx, ofsy, hx, hy, lm, cbm, crm, use_zb, zb)                               \
-       do {                                                                                                                    \
-       (vb)[0].pos.x = (mbx) * (unitx) + (ofsx);               (vb)[0].pos.y = (mby) * (unity) + (ofsy);                       \
-       (vb)[1].pos.x = (mbx) * (unitx) + (ofsx);               (vb)[1].pos.y = (mby) * (unity) + (ofsy) + (hy);                \
-       (vb)[2].pos.x = (mbx) * (unitx) + (ofsx) + (hx);        (vb)[2].pos.y = (mby) * (unity) + (ofsy);                       \
-       (vb)[3].pos.x = (mbx) * (unitx) + (ofsx) + (hx);        (vb)[3].pos.y = (mby) * (unity) + (ofsy);                       \
-       (vb)[4].pos.x = (mbx) * (unitx) + (ofsx);               (vb)[4].pos.y = (mby) * (unity) + (ofsy) + (hy);                \
-       (vb)[5].pos.x = (mbx) * (unitx) + (ofsx) + (hx);        (vb)[5].pos.y = (mby) * (unity) + (ofsy) + (hy);                \
-                                                                                                                               \
-       if (!use_zb || (cbp) & (lm))                                                                                            \
-       {                                                                                                                       \
-               (vb)[0].luma_tc.x = (mbx) * (unitx) + (ofsx);           (vb)[0].luma_tc.y = (mby) * (unity) + (ofsy);           \
-               (vb)[1].luma_tc.x = (mbx) * (unitx) + (ofsx);           (vb)[1].luma_tc.y = (mby) * (unity) + (ofsy) + (hy);    \
-               (vb)[2].luma_tc.x = (mbx) * (unitx) + (ofsx) + (hx);    (vb)[2].luma_tc.y = (mby) * (unity) + (ofsy);           \
-               (vb)[3].luma_tc.x = (mbx) * (unitx) + (ofsx) + (hx);    (vb)[3].luma_tc.y = (mby) * (unity) + (ofsy);           \
-               (vb)[4].luma_tc.x = (mbx) * (unitx) + (ofsx);           (vb)[4].luma_tc.y = (mby) * (unity) + (ofsy) + (hy);    \
-               (vb)[5].luma_tc.x = (mbx) * (unitx) + (ofsx) + (hx);    (vb)[5].luma_tc.y = (mby) * (unity) + (ofsy) + (hy);    \
-       }                                                                                                                       \
-       else                                                                                                                    \
-       {                                                                                                                       \
-               (vb)[0].luma_tc.x = (zb)[0].x;          (vb)[0].luma_tc.y = (zb)[0].y;                                          \
-               (vb)[1].luma_tc.x = (zb)[0].x;          (vb)[1].luma_tc.y = (zb)[0].y + (hy);                                   \
-               (vb)[2].luma_tc.x = (zb)[0].x + (hx);   (vb)[2].luma_tc.y = (zb)[0].y;                                          \
-               (vb)[3].luma_tc.x = (zb)[0].x + (hx);   (vb)[3].luma_tc.y = (zb)[0].y;                                          \
-               (vb)[4].luma_tc.x = (zb)[0].x;          (vb)[4].luma_tc.y = (zb)[0].y + (hy);                                   \
-               (vb)[5].luma_tc.x = (zb)[0].x + (hx);   (vb)[5].luma_tc.y = (zb)[0].y + (hy);                                   \
-       }                                                                                                                       \
-                                                                                                                               \
-       if (!use_zb || (cbp) & (cbm))                                                                                           \
-       {                                                                                                                       \
-               (vb)[0].cb_tc.x = (mbx) * (unitx) + (ofsx);             (vb)[0].cb_tc.y = (mby) * (unity) + (ofsy);             \
-               (vb)[1].cb_tc.x = (mbx) * (unitx) + (ofsx);             (vb)[1].cb_tc.y = (mby) * (unity) + (ofsy) + (hy);      \
-               (vb)[2].cb_tc.x = (mbx) * (unitx) + (ofsx) + (hx);      (vb)[2].cb_tc.y = (mby) * (unity) + (ofsy);             \
-               (vb)[3].cb_tc.x = (mbx) * (unitx) + (ofsx) + (hx);      (vb)[3].cb_tc.y = (mby) * (unity) + (ofsy);             \
-               (vb)[4].cb_tc.x = (mbx) * (unitx) + (ofsx);             (vb)[4].cb_tc.y = (mby) * (unity) + (ofsy) + (hy);      \
-               (vb)[5].cb_tc.x = (mbx) * (unitx) + (ofsx) + (hx);      (vb)[5].cb_tc.y = (mby) * (unity) + (ofsy) + (hy);      \
-       }                                                                                                                       \
-       else                                                                                                                    \
-       {                                                                                                                       \
-               (vb)[0].cb_tc.x = (zb)[1].x;            (vb)[0].cb_tc.y = (zb)[1].y;                                            \
-               (vb)[1].cb_tc.x = (zb)[1].x;            (vb)[1].cb_tc.y = (zb)[1].y + (hy);                                     \
-               (vb)[2].cb_tc.x = (zb)[1].x + (hx);     (vb)[2].cb_tc.y = (zb)[1].y;                                            \
-               (vb)[3].cb_tc.x = (zb)[1].x + (hx);     (vb)[3].cb_tc.y = (zb)[1].y;                                            \
-               (vb)[4].cb_tc.x = (zb)[1].x;            (vb)[4].cb_tc.y = (zb)[1].y + (hy);                                     \
-               (vb)[5].cb_tc.x = (zb)[1].x + (hx);     (vb)[5].cb_tc.y = (zb)[1].y + (hy);                                     \
-       }                                                                                                                       \
-                                                                                                                               \
-       if (!use_zb || (cbp) & (crm))                                                                                           \
-       {                                                                                                                       \
-               (vb)[0].cr_tc.x = (mbx) * (unitx) + (ofsx);             (vb)[0].cr_tc.y = (mby) * (unity) + (ofsy);             \
-               (vb)[1].cr_tc.x = (mbx) * (unitx) + (ofsx);             (vb)[1].cr_tc.y = (mby) * (unity) + (ofsy) + (hy);      \
-               (vb)[2].cr_tc.x = (mbx) * (unitx) + (ofsx) + (hx);      (vb)[2].cr_tc.y = (mby) * (unity) + (ofsy);             \
-               (vb)[3].cr_tc.x = (mbx) * (unitx) + (ofsx) + (hx);      (vb)[3].cr_tc.y = (mby) * (unity) + (ofsy);             \
-               (vb)[4].cr_tc.x = (mbx) * (unitx) + (ofsx);             (vb)[4].cr_tc.y = (mby) * (unity) + (ofsy) + (hy);      \
-               (vb)[5].cr_tc.x = (mbx) * (unitx) + (ofsx) + (hx);      (vb)[5].cr_tc.y = (mby) * (unity) + (ofsy) + (hy);      \
-       }                                                                                                                       \
-       else                                                                                                                    \
-       {                                                                                                                       \
-               (vb)[0].cr_tc.x = (zb)[2].x;            (vb)[0].cr_tc.y = (zb)[2].y;                                            \
-               (vb)[1].cr_tc.x = (zb)[2].x;            (vb)[1].cr_tc.y = (zb)[2].y + (hy);                                     \
-               (vb)[2].cr_tc.x = (zb)[2].x + (hx);     (vb)[2].cr_tc.y = (zb)[2].y;                                            \
-               (vb)[3].cr_tc.x = (zb)[2].x + (hx);     (vb)[3].cr_tc.y = (zb)[2].y;                                            \
-               (vb)[4].cr_tc.x = (zb)[2].x;            (vb)[4].cr_tc.y = (zb)[2].y + (hy);                                     \
-               (vb)[5].cr_tc.x = (zb)[2].x + (hx);     (vb)[5].cr_tc.y = (zb)[2].y + (hy);                                     \
-       }                                                                                                                       \
-       } while (0)
+static void
+gen_block_verts(struct vert_stream_0 *vb, unsigned cbp, unsigned mbx, unsigned mby,
+                const struct vertex2f *unit, const struct vertex2f *half, const struct vertex2f *offset,
+                unsigned luma_mask, unsigned cb_mask, unsigned cr_mask,
+                bool use_zeroblocks, struct vertex2f *zero_blocks)
+{
+   struct vertex2f v;
+
+   assert(vb);
+   assert(unit && half && offset);
+   assert(zero_blocks || !use_zeroblocks);
+
+   /* Generate vertices for two triangles covering a block */
+   v.x = mbx * unit->x + offset->x;
+   v.y = mby * unit->y + offset->y;
+
+   vb[0].pos.x = v.x;
+   vb[0].pos.y = v.y;
+   vb[1].pos.x = v.x;
+   vb[1].pos.y = v.y + half->y;
+   vb[2].pos.x = v.x + half->x;
+   vb[2].pos.y = v.y;
+   vb[3].pos.x = v.x + half->x;
+   vb[3].pos.y = v.y;
+   vb[4].pos.x = v.x;
+   vb[4].pos.y = v.y + half->y;
+   vb[5].pos.x = v.x + half->x;
+   vb[5].pos.y = v.y + half->y;
+
+   /* Generate texcoords for the triangles, either pointing to the correct area on the luma/chroma texture
+      or if zero blocks are being used, to the zero block if the appropriate CBP bits aren't set (i.e. no data
+      for this channel is defined for this block) */
+
+   if (!use_zeroblocks || cbp & luma_mask) {
+      v.x = mbx * unit->x + offset->x;
+      v.y = mby * unit->y + offset->y;
+   }
+   else {
+      v.x = zero_blocks[0].x;
+      v.y = zero_blocks[0].y;
+   }
+
+   vb[0].luma_tc.x = v.x;
+   vb[0].luma_tc.y = v.y;
+   vb[1].luma_tc.x = v.x;
+   vb[1].luma_tc.y = v.y + half->y;
+   vb[2].luma_tc.x = v.x + half->x;
+   vb[2].luma_tc.y = v.y;
+   vb[3].luma_tc.x = v.x + half->x;
+   vb[3].luma_tc.y = v.y;
+   vb[4].luma_tc.x = v.x;
+   vb[4].luma_tc.y = v.y + half->y;
+   vb[5].luma_tc.x = v.x + half->x;
+   vb[5].luma_tc.y = v.y + half->y;
+
+   if (!use_zeroblocks || cbp & cb_mask) {
+      v.x = mbx * unit->x + offset->x;
+      v.y = mby * unit->y + offset->y;
+   }
+   else {
+      v.x = zero_blocks[1].x;
+      v.y = zero_blocks[1].y;
+   }
+
+   vb[0].cb_tc.x = v.x;
+   vb[0].cb_tc.y = v.y;
+   vb[1].cb_tc.x = v.x;
+   vb[1].cb_tc.y = v.y + half->y;
+   vb[2].cb_tc.x = v.x + half->x;
+   vb[2].cb_tc.y = v.y;
+   vb[3].cb_tc.x = v.x + half->x;
+   vb[3].cb_tc.y = v.y;
+   vb[4].cb_tc.x = v.x;
+   vb[4].cb_tc.y = v.y + half->y;
+   vb[5].cb_tc.x = v.x + half->x;
+   vb[5].cb_tc.y = v.y + half->y;
+
+   if (!use_zeroblocks || cbp & cr_mask) {
+      v.x = mbx * unit->x + offset->x;
+      v.y = mby * unit->y + offset->y;
+   }
+   else {
+      v.x = zero_blocks[2].x;
+      v.y = zero_blocks[2].y;
+   }
+
+   vb[0].cr_tc.x = v.x;
+   vb[0].cr_tc.y = v.y;
+   vb[1].cr_tc.x = v.x;
+   vb[1].cr_tc.y = v.y + half->y;
+   vb[2].cr_tc.x = v.x + half->x;
+   vb[2].cr_tc.y = v.y;
+   vb[3].cr_tc.x = v.x + half->x;
+   vb[3].cr_tc.y = v.y;
+   vb[4].cr_tc.x = v.x;
+   vb[4].cr_tc.y = v.y + half->y;
+   vb[5].cr_tc.x = v.x + half->x;
+   vb[5].cr_tc.y = v.y + half->y;
+}
 
 static void
 gen_macroblock_verts(struct vl_mpeg12_mc_renderer *r,
@@ -1053,13 +798,17 @@ gen_macroblock_verts(struct vl_mpeg12_mc_renderer *r,
 {
    struct vertex2f mo_vec[2];
 
+   unsigned i;
+
    assert(r);
    assert(mb);
    assert(ycbcr_vb);
    assert(pos < r->macroblocks_per_batch);
 
-   switch (mb->mb_type)
-   {
+   mo_vec[1].x = 0;
+   mo_vec[1].y = 0;
+
+   switch (mb->mb_type) {
       case PIPE_MPEG12_MACROBLOCK_TYPE_BI:
       {
          struct vertex2f *vb;
@@ -1071,21 +820,17 @@ gen_macroblock_verts(struct vl_mpeg12_mc_renderer *r,
          mo_vec[0].x = mb->pmv[0][1][0] * 0.5f * r->surface_tex_inv_size.x;
          mo_vec[0].y = mb->pmv[0][1][1] * 0.5f * r->surface_tex_inv_size.y;
 
-         if (mb->mo_type == PIPE_MPEG12_MOTION_TYPE_FRAME)
-         {
-            for (unsigned i = 0; i < 24 * 2; i += 2)
-            {
+         if (mb->mo_type == PIPE_MPEG12_MOTION_TYPE_FRAME) {
+            for (i = 0; i < 24 * 2; i += 2) {
                vb[i].x = mo_vec[0].x;
                vb[i].y = mo_vec[0].y;
             }
          }
-         else
-         {
+         else {
             mo_vec[1].x = mb->pmv[1][1][0] * 0.5f * r->surface_tex_inv_size.x;
             mo_vec[1].y = mb->pmv[1][1][1] * 0.5f * r->surface_tex_inv_size.y;
 
-            for (unsigned i = 0; i < 24 * 2; i += 2)
-            {
+            for (i = 0; i < 24 * 2; i += 2) {
                vb[i].x = mo_vec[0].x;
                vb[i].y = mo_vec[0].y;
                vb[i + 1].x = mo_vec[1].x;
@@ -1104,41 +849,33 @@ gen_macroblock_verts(struct vl_mpeg12_mc_renderer *r,
 
          vb = ref_vb[0] + pos * 2 * 24;
 
-         if (mb->mb_type == PIPE_MPEG12_MACROBLOCK_TYPE_BKWD)
-         {
+         if (mb->mb_type == PIPE_MPEG12_MACROBLOCK_TYPE_BKWD) {
              mo_vec[0].x = mb->pmv[0][1][0] * 0.5f * r->surface_tex_inv_size.x;
              mo_vec[0].y = mb->pmv[0][1][1] * 0.5f * r->surface_tex_inv_size.y;
 
-             if (mb->mo_type == PIPE_MPEG12_MOTION_TYPE_FIELD)
-             {
+             if (mb->mo_type == PIPE_MPEG12_MOTION_TYPE_FIELD) {
                 mo_vec[1].x = mb->pmv[1][1][0] * 0.5f * r->surface_tex_inv_size.x;
                 mo_vec[1].y = mb->pmv[1][1][1] * 0.5f * r->surface_tex_inv_size.y;
              }
          }
-         else
-         {
+         else {
             mo_vec[0].x = mb->pmv[0][0][0] * 0.5f * r->surface_tex_inv_size.x;
             mo_vec[0].y = mb->pmv[0][0][1] * 0.5f * r->surface_tex_inv_size.y;
 
-            if (mb->mo_type == PIPE_MPEG12_MOTION_TYPE_FIELD)
-            {
+            if (mb->mo_type == PIPE_MPEG12_MOTION_TYPE_FIELD) {
                mo_vec[1].x = mb->pmv[1][0][0] * 0.5f * r->surface_tex_inv_size.x;
                mo_vec[1].y = mb->pmv[1][0][1] * 0.5f * r->surface_tex_inv_size.y;
             }
          }
 
-         if (mb->mb_type == PIPE_MPEG12_MOTION_TYPE_FRAME)
-         {
-            for (unsigned i = 0; i < 24 * 2; i += 2)
-            {
+         if (mb->mb_type == PIPE_MPEG12_MOTION_TYPE_FRAME) {
+            for (i = 0; i < 24 * 2; i += 2) {
                vb[i].x = mo_vec[0].x;
                vb[i].y = mo_vec[0].y;
             }
          }
-         else
-         {
-            for (unsigned i = 0; i < 24 * 2; i += 2)
-            {
+         else {
+            for (i = 0; i < 24 * 2; i += 2) {
                vb[i].x = mo_vec[0].x;
                vb[i].y = mo_vec[0].y;
                vb[i + 1].x = mo_vec[1].x;
@@ -1160,25 +897,34 @@ gen_macroblock_verts(struct vl_mpeg12_mc_renderer *r,
             r->surface_tex_inv_size.x * (MACROBLOCK_WIDTH / 2),
             r->surface_tex_inv_size.y * (MACROBLOCK_HEIGHT / 2)
          };
+         const struct vertex2f offsets[2][2] =
+         {
+            {
+               {0, 0}, {0, half.y}
+            },
+            {
+               {half.x, 0}, {half.x, half.y}
+            }
+         };
          const bool use_zb = r->eb_handling == VL_MPEG12_MC_RENDERER_EMPTY_BLOCK_XFER_ONE;
 
          struct vert_stream_0 *vb = ycbcr_vb + pos * 24;
 
-         SET_BLOCK(vb, mb->cbp, mb->mbx, mb->mby,
-                   unit.x, unit.y, 0, 0, half.x, half.y,
-                   32, 2, 1, use_zb, r->zero_block);
+         gen_block_verts(vb, mb->cbp, mb->mbx, mb->mby,
+                         &unit, &half, &offsets[0][0],
+                         32, 2, 1, use_zb, r->zero_block);
 
-         SET_BLOCK(vb + 6, mb->cbp, mb->mbx, mb->mby,
-                   unit.x, unit.y, half.x, 0, half.x, half.y,
-                   16, 2, 1, use_zb, r->zero_block);
+         gen_block_verts(vb + 6, mb->cbp, mb->mbx, mb->mby,
+                         &unit, &half, &offsets[1][0],
+                         16, 2, 1, use_zb, r->zero_block);
 
-         SET_BLOCK(vb + 12, mb->cbp, mb->mbx, mb->mby,
-                   unit.x, unit.y, 0, half.y, half.x, half.y,
-                   8, 2, 1, use_zb, r->zero_block);
+         gen_block_verts(vb + 12, mb->cbp, mb->mbx, mb->mby,
+                         &unit, &half, &offsets[0][1],
+                         8, 2, 1, use_zb, r->zero_block);
 
-         SET_BLOCK(vb + 18, mb->cbp, mb->mbx, mb->mby,
-                   unit.x, unit.y, half.x, half.y, half.x, half.y,
-                   4, 2, 1, use_zb, r->zero_block);
+         gen_block_verts(vb + 18, mb->cbp, mb->mbx, mb->mby,
+                         &unit, &half, &offsets[1][1],
+                         4, 2, 1, use_zb, r->zero_block);
 
          break;
       }
@@ -1194,19 +940,19 @@ gen_macroblock_stream(struct vl_mpeg12_mc_renderer *r,
    unsigned offset[NUM_MACROBLOCK_TYPES];
    struct vert_stream_0 *ycbcr_vb;
    struct vertex2f *ref_vb[2];
+   unsigned i;
 
    assert(r);
    assert(num_macroblocks);
 
-   for (unsigned i = 0; i < r->num_macroblocks; ++i)
-   {
+   for (i = 0; i < r->num_macroblocks; ++i) {
       enum MACROBLOCK_TYPE mb_type = get_macroblock_type(&r->macroblock_buf[i]);
       ++num_macroblocks[mb_type];
    }
 
    offset[0] = 0;
 
-   for (unsigned i = 1; i < NUM_MACROBLOCK_TYPES; ++i)
+   for (i = 1; i < NUM_MACROBLOCK_TYPES; ++i)
       offset[i] = offset[i - 1] + num_macroblocks[i - 1];
 
    ycbcr_vb = (struct vert_stream_0 *)pipe_buffer_map
@@ -1216,7 +962,7 @@ gen_macroblock_stream(struct vl_mpeg12_mc_renderer *r,
       PIPE_BUFFER_USAGE_CPU_WRITE | PIPE_BUFFER_USAGE_DISCARD
    );
 
-   for (unsigned i = 0; i < 2; ++i)
+   for (i = 0; i < 2; ++i)
       ref_vb[i] = (struct vertex2f *)pipe_buffer_map
       (
          r->pipe->screen,
@@ -1224,8 +970,7 @@ gen_macroblock_stream(struct vl_mpeg12_mc_renderer *r,
          PIPE_BUFFER_USAGE_CPU_WRITE | PIPE_BUFFER_USAGE_DISCARD
       );
 
-   for (unsigned i = 0; i < r->num_macroblocks; ++i)
-   {
+   for (i = 0; i < r->num_macroblocks; ++i) {
       enum MACROBLOCK_TYPE mb_type = get_macroblock_type(&r->macroblock_buf[i]);
 
       gen_macroblock_verts(r, &r->macroblock_buf[i], offset[mb_type],
@@ -1235,7 +980,7 @@ gen_macroblock_stream(struct vl_mpeg12_mc_renderer *r,
    }
 
    pipe_buffer_unmap(r->pipe->screen, r->vertex_bufs.individual.ycbcr.buffer);
-   for (unsigned i = 0; i < 2; ++i)
+   for (i = 0; i < 2; ++i)
       pipe_buffer_unmap(r->pipe->screen, r->vertex_bufs.individual.ref[i].buffer);
 }
 
@@ -1245,6 +990,7 @@ flush(struct vl_mpeg12_mc_renderer *r)
    unsigned num_macroblocks[NUM_MACROBLOCK_TYPES] = { 0 };
    unsigned vb_start = 0;
    struct vertex_shader_consts *vs_consts;
+   unsigned i;
 
    assert(r);
    assert(r->num_macroblocks == r->macroblocks_per_batch);
@@ -1262,26 +1008,23 @@ flush(struct vl_mpeg12_mc_renderer *r)
 
    vs_consts = pipe_buffer_map
    (
-      r->pipe->screen, r->vs_const_buf.buffer,
+      r->pipe->screen, r->vs_const_buf,
       PIPE_BUFFER_USAGE_CPU_WRITE | PIPE_BUFFER_USAGE_DISCARD
    );
 
-   vs_consts->denorm.x = r->surface->width[0];
-   vs_consts->denorm.y = r->surface->height[0];
+   vs_consts->denorm.x = r->surface->width0;
+   vs_consts->denorm.y = r->surface->height0;
 
-   pipe_buffer_unmap(r->pipe->screen, r->vs_const_buf.buffer);
+   pipe_buffer_unmap(r->pipe->screen, r->vs_const_buf);
 
    r->pipe->set_constant_buffer(r->pipe, PIPE_SHADER_VERTEX, 0,
-                                &r->vs_const_buf);
-   r->pipe->set_constant_buffer(r->pipe, PIPE_SHADER_FRAGMENT, 0,
-                                &r->fs_const_buf);
+                                r->vs_const_buf);
 
-   if (num_macroblocks[MACROBLOCK_TYPE_INTRA] > 0)
-   {
+   if (num_macroblocks[MACROBLOCK_TYPE_INTRA] > 0) {
       r->pipe->set_vertex_buffers(r->pipe, 1, r->vertex_bufs.all);
       r->pipe->set_vertex_elements(r->pipe, 4, r->vertex_elems);
-      r->pipe->set_sampler_textures(r->pipe, 3, r->textures.all);
-      r->pipe->bind_sampler_states(r->pipe, 3, r->samplers.all);
+      r->pipe->set_fragment_sampler_textures(r->pipe, 3, r->textures.all);
+      r->pipe->bind_fragment_sampler_states(r->pipe, 3, r->samplers.all);
       r->pipe->bind_vs_state(r->pipe, r->i_vs);
       r->pipe->bind_fs_state(r->pipe, r->i_fs);
 
@@ -1290,13 +1033,12 @@ flush(struct vl_mpeg12_mc_renderer *r)
       vb_start += num_macroblocks[MACROBLOCK_TYPE_INTRA] * 24;
    }
 
-   if (num_macroblocks[MACROBLOCK_TYPE_FWD_FRAME_PRED] > 0)
-   {
+   if (num_macroblocks[MACROBLOCK_TYPE_FWD_FRAME_PRED] > 0) {
       r->pipe->set_vertex_buffers(r->pipe, 2, r->vertex_bufs.all);
       r->pipe->set_vertex_elements(r->pipe, 6, r->vertex_elems);
       r->textures.individual.ref[0] = r->past;
-      r->pipe->set_sampler_textures(r->pipe, 4, r->textures.all);
-      r->pipe->bind_sampler_states(r->pipe, 4, r->samplers.all);
+      r->pipe->set_fragment_sampler_textures(r->pipe, 4, r->textures.all);
+      r->pipe->bind_fragment_sampler_states(r->pipe, 4, r->samplers.all);
       r->pipe->bind_vs_state(r->pipe, r->p_vs[0]);
       r->pipe->bind_fs_state(r->pipe, r->p_fs[0]);
 
@@ -1305,13 +1047,12 @@ flush(struct vl_mpeg12_mc_renderer *r)
       vb_start += num_macroblocks[MACROBLOCK_TYPE_FWD_FRAME_PRED] * 24;
    }
 
-   if (false /*num_macroblocks[MACROBLOCK_TYPE_FWD_FIELD_PRED] > 0 */ )
-   {
+   if (false /*num_macroblocks[MACROBLOCK_TYPE_FWD_FIELD_PRED] > 0 */ ) {
       r->pipe->set_vertex_buffers(r->pipe, 2, r->vertex_bufs.all);
       r->pipe->set_vertex_elements(r->pipe, 6, r->vertex_elems);
       r->textures.individual.ref[0] = r->past;
-      r->pipe->set_sampler_textures(r->pipe, 4, r->textures.all);
-      r->pipe->bind_sampler_states(r->pipe, 4, r->samplers.all);
+      r->pipe->set_fragment_sampler_textures(r->pipe, 4, r->textures.all);
+      r->pipe->bind_fragment_sampler_states(r->pipe, 4, r->samplers.all);
       r->pipe->bind_vs_state(r->pipe, r->p_vs[1]);
       r->pipe->bind_fs_state(r->pipe, r->p_fs[1]);
 
@@ -1320,13 +1061,12 @@ flush(struct vl_mpeg12_mc_renderer *r)
       vb_start += num_macroblocks[MACROBLOCK_TYPE_FWD_FIELD_PRED] * 24;
    }
 
-   if (num_macroblocks[MACROBLOCK_TYPE_BKWD_FRAME_PRED] > 0)
-   {
+   if (num_macroblocks[MACROBLOCK_TYPE_BKWD_FRAME_PRED] > 0) {
       r->pipe->set_vertex_buffers(r->pipe, 2, r->vertex_bufs.all);
       r->pipe->set_vertex_elements(r->pipe, 6, r->vertex_elems);
       r->textures.individual.ref[0] = r->future;
-      r->pipe->set_sampler_textures(r->pipe, 4, r->textures.all);
-      r->pipe->bind_sampler_states(r->pipe, 4, r->samplers.all);
+      r->pipe->set_fragment_sampler_textures(r->pipe, 4, r->textures.all);
+      r->pipe->bind_fragment_sampler_states(r->pipe, 4, r->samplers.all);
       r->pipe->bind_vs_state(r->pipe, r->p_vs[0]);
       r->pipe->bind_fs_state(r->pipe, r->p_fs[0]);
 
@@ -1335,13 +1075,12 @@ flush(struct vl_mpeg12_mc_renderer *r)
       vb_start += num_macroblocks[MACROBLOCK_TYPE_BKWD_FRAME_PRED] * 24;
    }
 
-   if (false /*num_macroblocks[MACROBLOCK_TYPE_BKWD_FIELD_PRED] > 0 */ )
-   {
+   if (false /*num_macroblocks[MACROBLOCK_TYPE_BKWD_FIELD_PRED] > 0 */ ) {
       r->pipe->set_vertex_buffers(r->pipe, 2, r->vertex_bufs.all);
       r->pipe->set_vertex_elements(r->pipe, 6, r->vertex_elems);
       r->textures.individual.ref[0] = r->future;
-      r->pipe->set_sampler_textures(r->pipe, 4, r->textures.all);
-      r->pipe->bind_sampler_states(r->pipe, 4, r->samplers.all);
+      r->pipe->set_fragment_sampler_textures(r->pipe, 4, r->textures.all);
+      r->pipe->bind_fragment_sampler_states(r->pipe, 4, r->samplers.all);
       r->pipe->bind_vs_state(r->pipe, r->p_vs[1]);
       r->pipe->bind_fs_state(r->pipe, r->p_fs[1]);
 
@@ -1350,14 +1089,13 @@ flush(struct vl_mpeg12_mc_renderer *r)
       vb_start += num_macroblocks[MACROBLOCK_TYPE_BKWD_FIELD_PRED] * 24;
    }
 
-   if (num_macroblocks[MACROBLOCK_TYPE_BI_FRAME_PRED] > 0)
-   {
+   if (num_macroblocks[MACROBLOCK_TYPE_BI_FRAME_PRED] > 0) {
       r->pipe->set_vertex_buffers(r->pipe, 3, r->vertex_bufs.all);
       r->pipe->set_vertex_elements(r->pipe, 8, r->vertex_elems);
       r->textures.individual.ref[0] = r->past;
       r->textures.individual.ref[1] = r->future;
-      r->pipe->set_sampler_textures(r->pipe, 5, r->textures.all);
-      r->pipe->bind_sampler_states(r->pipe, 5, r->samplers.all);
+      r->pipe->set_fragment_sampler_textures(r->pipe, 5, r->textures.all);
+      r->pipe->bind_fragment_sampler_states(r->pipe, 5, r->samplers.all);
       r->pipe->bind_vs_state(r->pipe, r->b_vs[0]);
       r->pipe->bind_fs_state(r->pipe, r->b_fs[0]);
 
@@ -1366,14 +1104,13 @@ flush(struct vl_mpeg12_mc_renderer *r)
       vb_start += num_macroblocks[MACROBLOCK_TYPE_BI_FRAME_PRED] * 24;
    }
 
-   if (false /*num_macroblocks[MACROBLOCK_TYPE_BI_FIELD_PRED] > 0 */ )
-   {
+   if (false /*num_macroblocks[MACROBLOCK_TYPE_BI_FIELD_PRED] > 0 */ ) {
       r->pipe->set_vertex_buffers(r->pipe, 3, r->vertex_bufs.all);
       r->pipe->set_vertex_elements(r->pipe, 8, r->vertex_elems);
       r->textures.individual.ref[0] = r->past;
       r->textures.individual.ref[1] = r->future;
-      r->pipe->set_sampler_textures(r->pipe, 5, r->textures.all);
-      r->pipe->bind_sampler_states(r->pipe, 5, r->samplers.all);
+      r->pipe->set_fragment_sampler_textures(r->pipe, 5, r->textures.all);
+      r->pipe->bind_fragment_sampler_states(r->pipe, 5, r->samplers.all);
       r->pipe->bind_vs_state(r->pipe, r->b_vs[1]);
       r->pipe->bind_fs_state(r->pipe, r->b_fs[1]);
 
@@ -1386,7 +1123,7 @@ flush(struct vl_mpeg12_mc_renderer *r)
    pipe_surface_reference(&r->fb_state.cbufs[0], NULL);
 
    if (r->eb_handling == VL_MPEG12_MC_RENDERER_EMPTY_BLOCK_XFER_ONE)
-      for (unsigned i = 0; i < 3; ++i)
+      for (i = 0; i < 3; ++i)
          r->zero_block[i].x = ZERO_BLOCK_NIL;
 
    r->num_macroblocks = 0;
@@ -1395,29 +1132,35 @@ flush(struct vl_mpeg12_mc_renderer *r)
 static void
 grab_frame_coded_block(short *src, short *dst, unsigned dst_pitch)
 {
+   unsigned y;
+
    assert(src);
    assert(dst);
 
-   for (unsigned y = 0; y < BLOCK_HEIGHT; ++y)
+   for (y = 0; y < BLOCK_HEIGHT; ++y)
       memcpy(dst + y * dst_pitch, src + y * BLOCK_WIDTH, BLOCK_WIDTH * 2);
 }
 
 static void
 grab_field_coded_block(short *src, short *dst, unsigned dst_pitch)
 {
+   unsigned y;
+
    assert(src);
    assert(dst);
 
-   for (unsigned y = 0; y < BLOCK_HEIGHT; ++y)
+   for (y = 0; y < BLOCK_HEIGHT; ++y)
       memcpy(dst + y * dst_pitch * 2, src + y * BLOCK_WIDTH, BLOCK_WIDTH * 2);
 }
 
 static void
 fill_zero_block(short *dst, unsigned dst_pitch)
 {
+   unsigned y;
+
    assert(dst);
 
-   for (unsigned y = 0; y < BLOCK_HEIGHT; ++y)
+   for (y = 0; y < BLOCK_HEIGHT; ++y)
       memset(dst + y * dst_pitch, 0, BLOCK_WIDTH * 2);
 }
 
@@ -1429,27 +1172,23 @@ grab_blocks(struct vl_mpeg12_mc_renderer *r, unsigned mbx, unsigned mby,
    short *texels;
    unsigned tb = 0, sb = 0;
    unsigned mbpx = mbx * MACROBLOCK_WIDTH, mbpy = mby * MACROBLOCK_HEIGHT;
+   unsigned x, y;
 
    assert(r);
    assert(blocks);
 
-   tex_pitch = r->tex_transfer[0]->stride / r->tex_transfer[0]->block.size;
+   tex_pitch = r->tex_transfer[0]->stride / util_format_get_blocksize(r->tex_transfer[0]->texture->format);
    texels = r->texels[0] + mbpy * tex_pitch + mbpx;
 
-   for (unsigned y = 0; y < 2; ++y)
-   {
-      for (unsigned x = 0; x < 2; ++x, ++tb)
-      {
-         if ((cbp >> (5 - tb)) & 1)
-         {
-            if (dct_type == PIPE_MPEG12_DCT_TYPE_FRAME)
-            {
+   for (y = 0; y < 2; ++y) {
+      for (x = 0; x < 2; ++x, ++tb) {
+         if ((cbp >> (5 - tb)) & 1) {
+            if (dct_type == PIPE_MPEG12_DCT_TYPE_FRAME) {
                grab_frame_coded_block(blocks + sb * BLOCK_WIDTH * BLOCK_HEIGHT,
                                       texels + y * tex_pitch * BLOCK_WIDTH +
                                       x * BLOCK_WIDTH, tex_pitch);
             }
-            else
-            {
+            else {
                grab_field_coded_block(blocks + sb * BLOCK_WIDTH * BLOCK_HEIGHT,
                                       texels + y * tex_pitch + x * BLOCK_WIDTH,
                                       tex_pitch);
@@ -1457,14 +1196,11 @@ grab_blocks(struct vl_mpeg12_mc_renderer *r, unsigned mbx, unsigned mby,
 
             ++sb;
          }
-         else if (r->eb_handling != VL_MPEG12_MC_RENDERER_EMPTY_BLOCK_XFER_NONE)
-         {
+         else if (r->eb_handling != VL_MPEG12_MC_RENDERER_EMPTY_BLOCK_XFER_NONE) {
             if (r->eb_handling == VL_MPEG12_MC_RENDERER_EMPTY_BLOCK_XFER_ALL ||
-                ZERO_BLOCK_IS_NIL(r->zero_block[0]))
-            {
+                ZERO_BLOCK_IS_NIL(r->zero_block[0])) {
                fill_zero_block(texels + y * tex_pitch * BLOCK_WIDTH + x * BLOCK_WIDTH, tex_pitch);
-               if (r->eb_handling == VL_MPEG12_MC_RENDERER_EMPTY_BLOCK_XFER_ONE)
-               {
+               if (r->eb_handling == VL_MPEG12_MC_RENDERER_EMPTY_BLOCK_XFER_ONE) {
                   r->zero_block[0].x = (mbpx + x * 8) * r->surface_tex_inv_size.x;
                   r->zero_block[0].y = (mbpy + y * 8) * r->surface_tex_inv_size.y;
                }
@@ -1479,24 +1215,19 @@ grab_blocks(struct vl_mpeg12_mc_renderer *r, unsigned mbx, unsigned mby,
    mbpx /= 2;
    mbpy /= 2;
 
-   for (tb = 0; tb < 2; ++tb)
-   {
-      tex_pitch = r->tex_transfer[tb + 1]->stride / r->tex_transfer[tb + 1]->block.size;
+   for (tb = 0; tb < 2; ++tb) {
+      tex_pitch = r->tex_transfer[tb + 1]->stride / util_format_get_blocksize(r->tex_transfer[tb + 1]->texture->format);
       texels = r->texels[tb + 1] + mbpy * tex_pitch + mbpx;
 
-      if ((cbp >> (1 - tb)) & 1)
-      {
+      if ((cbp >> (1 - tb)) & 1) {
          grab_frame_coded_block(blocks + sb * BLOCK_WIDTH * BLOCK_HEIGHT, texels, tex_pitch);
          ++sb;
       }
-      else if (r->eb_handling != VL_MPEG12_MC_RENDERER_EMPTY_BLOCK_XFER_NONE)
-      {
+      else if (r->eb_handling != VL_MPEG12_MC_RENDERER_EMPTY_BLOCK_XFER_NONE) {
          if (r->eb_handling == VL_MPEG12_MC_RENDERER_EMPTY_BLOCK_XFER_ALL ||
-             ZERO_BLOCK_IS_NIL(r->zero_block[tb + 1]))
-         {
+             ZERO_BLOCK_IS_NIL(r->zero_block[tb + 1])) {
             fill_zero_block(texels, tex_pitch);
-            if (r->eb_handling == VL_MPEG12_MC_RENDERER_EMPTY_BLOCK_XFER_ONE)
-            {
+            if (r->eb_handling == VL_MPEG12_MC_RENDERER_EMPTY_BLOCK_XFER_ONE) {
                r->zero_block[tb + 1].x = (mbpx << 1) * r->surface_tex_inv_size.x;
                r->zero_block[tb + 1].y = (mbpy << 1) * r->surface_tex_inv_size.y;
             }
@@ -1509,6 +1240,8 @@ static void
 grab_macroblock(struct vl_mpeg12_mc_renderer *r,
                 struct pipe_mpeg12_macroblock *mb)
 {
+   void *blocks;
+
    assert(r);
    assert(mb);
    assert(r->num_macroblocks < r->macroblocks_per_batch);
@@ -1516,7 +1249,10 @@ grab_macroblock(struct vl_mpeg12_mc_renderer *r,
    memcpy(&r->macroblock_buf[r->num_macroblocks], mb,
           sizeof(struct pipe_mpeg12_macroblock));
 
-   grab_blocks(r, mb->mbx, mb->mby, mb->dct_type, mb->cbp, mb->blocks);
+   blocks = pipe_buffer_map(r->pipe->screen, mb->blocks,
+                            PIPE_BUFFER_USAGE_CPU_READ);
+   grab_blocks(r, mb->mbx, mb->mby, mb->dct_type, mb->cbp, blocks);
+   pipe_buffer_unmap(r->pipe->screen, mb->blocks);
 
    ++r->num_macroblocks;
 }
@@ -1531,6 +1267,8 @@ vl_mpeg12_mc_renderer_init(struct vl_mpeg12_mc_renderer *renderer,
                            enum VL_MPEG12_MC_RENDERER_EMPTY_BLOCK eb_handling,
                            bool pot_buffers)
 {
+   unsigned i;
+
    assert(renderer);
    assert(pipe);
    /* TODO: Implement other policies */
@@ -1553,13 +1291,11 @@ vl_mpeg12_mc_renderer_init(struct vl_mpeg12_mc_renderer *renderer,
 
    if (!init_pipe_state(renderer))
       return false;
-   if (!init_shaders(renderer))
-   {
+   if (!init_shaders(renderer)) {
       cleanup_pipe_state(renderer);
       return false;
    }
-   if (!init_buffers(renderer))
-   {
+   if (!init_buffers(renderer)) {
       cleanup_shaders(renderer);
       cleanup_pipe_state(renderer);
       return false;
@@ -1568,7 +1304,7 @@ vl_mpeg12_mc_renderer_init(struct vl_mpeg12_mc_renderer *renderer,
    renderer->surface = NULL;
    renderer->past = NULL;
    renderer->future = NULL;
-   for (unsigned i = 0; i < 3; ++i)
+   for (i = 0; i < 3; ++i)
       renderer->zero_block[i].x = ZERO_BLOCK_NIL;
    renderer->num_macroblocks = 0;
 
@@ -1607,16 +1343,13 @@ vl_mpeg12_mc_renderer_render_macroblocks(struct vl_mpeg12_mc_renderer
    assert(num_macroblocks);
    assert(mpeg12_macroblocks);
 
-   if (renderer->surface)
-   {
-      if (surface != renderer->surface)
-      {
-         if (renderer->num_macroblocks > 0)
-         {
+   if (renderer->surface) {
+      if (surface != renderer->surface) {
+         if (renderer->num_macroblocks > 0) {
             xfer_buffers_unmap(renderer);
             flush(renderer);
          }
-         
+
          new_surface = true;
       }
 
@@ -1627,31 +1360,28 @@ vl_mpeg12_mc_renderer_render_macroblocks(struct vl_mpeg12_mc_renderer
    else
       new_surface = true;
 
-   if (new_surface)
-   {
+   if (new_surface) {
       renderer->surface = surface;
       renderer->past = past;
       renderer->future = future;
       renderer->fence = fence;
-      renderer->surface_tex_inv_size.x = 1.0f / surface->width[0];
-      renderer->surface_tex_inv_size.y = 1.0f / surface->height[0];
+      renderer->surface_tex_inv_size.x = 1.0f / surface->width0;
+      renderer->surface_tex_inv_size.y = 1.0f / surface->height0;
    }
 
-   while (num_macroblocks)
-   {
+   while (num_macroblocks) {
       unsigned left_in_batch = renderer->macroblocks_per_batch - renderer->num_macroblocks;
       unsigned num_to_submit = MIN2(num_macroblocks, left_in_batch);
+      unsigned i;
 
-      for (unsigned i = 0; i < num_to_submit; ++i)
-      {
+      for (i = 0; i < num_to_submit; ++i) {
          assert(mpeg12_macroblocks[i].base.codec == PIPE_VIDEO_CODEC_MPEG12);
          grab_macroblock(renderer, &mpeg12_macroblocks[i]);
       }
 
       num_macroblocks -= num_to_submit;
 
-      if (renderer->num_macroblocks == renderer->macroblocks_per_batch)
-      {
+      if (renderer->num_macroblocks == renderer->macroblocks_per_batch) {
          xfer_buffers_unmap(renderer);
          flush(renderer);
          xfer_buffers_map(renderer);