#define MACROBLOCK_HEIGHT 16
#define BLOCK_WIDTH 8
#define BLOCK_HEIGHT 8
-#define ZERO_BLOCK_NIL -1.0f
-#define ZERO_BLOCK_IS_NIL(zb) ((zb).x < 0.0f)
-#define SCALE_FACTOR_16_TO_9 (32767.0f / 255.0f)
-struct vertex_shader_consts
+struct vertex_stream
{
- struct vertex4f denorm;
+ struct vertex2s pos;
+ struct vertex2s mv[4];
+ struct {
+ int8_t y;
+ int8_t cr;
+ int8_t cb;
+ int8_t flag;
+ } eb[2][2];
};
-struct fragment_shader_consts
+enum VS_INPUT
{
- struct vertex4f multiplier;
- struct vertex4f div;
+ VS_I_RECT,
+ VS_I_VPOS,
+ VS_I_MV0,
+ VS_I_MV1,
+ VS_I_MV2,
+ VS_I_MV3,
+ VS_I_EB_0_0,
+ VS_I_EB_0_1,
+ VS_I_EB_1_0,
+ VS_I_EB_1_1,
+
+ NUM_VS_INPUTS
};
-struct vert_stream_0
+enum VS_OUTPUT
{
- struct vertex2f pos;
- struct vertex2f luma_tc;
- struct vertex2f cb_tc;
- struct vertex2f cr_tc;
+ VS_O_VPOS,
+ VS_O_LINE,
+ VS_O_TEX0,
+ VS_O_TEX1,
+ VS_O_TEX2,
+ VS_O_EB_0,
+ VS_O_EB_1,
+ VS_O_INFO,
+ VS_O_MV0,
+ VS_O_MV1,
+ VS_O_MV2,
+ VS_O_MV3
};
-enum MACROBLOCK_TYPE
-{
- MACROBLOCK_TYPE_INTRA,
- MACROBLOCK_TYPE_FWD_FRAME_PRED,
- MACROBLOCK_TYPE_FWD_FIELD_PRED,
- MACROBLOCK_TYPE_BKWD_FRAME_PRED,
- MACROBLOCK_TYPE_BKWD_FIELD_PRED,
- MACROBLOCK_TYPE_BI_FRAME_PRED,
- MACROBLOCK_TYPE_BI_FIELD_PRED,
-
- NUM_MACROBLOCK_TYPES
+static const unsigned const_empty_block_mask_420[3][2][2] = {
+ { { 0x20, 0x10 }, { 0x08, 0x04 } },
+ { { 0x02, 0x02 }, { 0x02, 0x02 } },
+ { { 0x01, 0x01 }, { 0x01, 0x01 } }
};
-static bool
-create_intra_vert_shader(struct vl_mpeg12_mc_renderer *r)
+static void *
+create_vert_shader(struct vl_mpeg12_mc_renderer *r)
{
struct ureg_program *shader;
- struct ureg_src vpos, vtex[3];
- struct ureg_dst o_vpos, o_vtex[3];
- unsigned i;
+ struct ureg_src block_scale, mv_scale;
+ struct ureg_src vrect, vpos, eb[2][2], vmv[4];
+ struct ureg_dst t_vpos, t_vtex, t_vmv;
+ struct ureg_dst o_vpos, o_line, o_vtex[3], o_eb[2], o_vmv[4], o_info;
+ unsigned i, label;
shader = ureg_create(TGSI_PROCESSOR_VERTEX);
if (!shader)
- return false;
-
- 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);
-
- /*
- * o_vpos = vpos
- * o_vtex[0..2] = vtex[0..2]
- */
- ureg_MOV(shader, o_vpos, vpos);
- for (i = 0; i < 3; ++i)
- ureg_MOV(shader, o_vtex[i], vtex[i]);
-
- ureg_END(shader);
-
- r->i_vs = ureg_create_shader_and_destroy(shader, r->pipe);
- if (!r->i_vs)
- return false;
-
- return true;
-}
-
-static bool
-create_intra_frag_shader(struct vl_mpeg12_mc_renderer *r)
-{
- 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;
-
- 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);
+ return NULL;
+
+ t_vpos = ureg_DECL_temporary(shader);
+ t_vtex = ureg_DECL_temporary(shader);
+ t_vmv = ureg_DECL_temporary(shader);
+
+ vrect = ureg_DECL_vs_input(shader, VS_I_RECT);
+ vpos = ureg_DECL_vs_input(shader, VS_I_VPOS);
+ eb[0][0] = ureg_DECL_vs_input(shader, VS_I_EB_0_0);
+ eb[1][0] = ureg_DECL_vs_input(shader, VS_I_EB_1_0);
+ eb[0][1] = ureg_DECL_vs_input(shader, VS_I_EB_0_1);
+ eb[1][1] = ureg_DECL_vs_input(shader, VS_I_EB_1_1);
+
+ o_vpos = ureg_DECL_output(shader, TGSI_SEMANTIC_POSITION, VS_O_VPOS);
+ o_line = ureg_DECL_output(shader, TGSI_SEMANTIC_GENERIC, VS_O_LINE);
+ o_vtex[0] = ureg_DECL_output(shader, TGSI_SEMANTIC_GENERIC, VS_O_TEX0);
+ o_vtex[1] = ureg_DECL_output(shader, TGSI_SEMANTIC_GENERIC, VS_O_TEX1);
+ o_vtex[2] = ureg_DECL_output(shader, TGSI_SEMANTIC_GENERIC, VS_O_TEX2);
+ o_eb[0] = ureg_DECL_output(shader, TGSI_SEMANTIC_GENERIC, VS_O_EB_0);
+ o_eb[1] = ureg_DECL_output(shader, TGSI_SEMANTIC_GENERIC, VS_O_EB_1);
+ o_info = ureg_DECL_output(shader, TGSI_SEMANTIC_GENERIC, VS_O_INFO);
+
+ for (i = 0; i < 4; ++i) {
+ vmv[i] = ureg_DECL_vs_input(shader, VS_I_MV0 + i);
+ o_vmv[i] = ureg_DECL_output(shader, TGSI_SEMANTIC_GENERIC, VS_O_MV0 + i);
}
- texel = ureg_DECL_temporary(shader);
- temp = ureg_DECL_temporary(shader);
- fragment = ureg_DECL_output(shader, TGSI_SEMANTIC_COLOR, 0);
/*
- * texel.r = tex(tc[0], sampler[0])
- * texel.g = tex(tc[1], sampler[1])
- * texel.b = tex(tc[2], sampler[2])
- * fragment = texel * scale
+ * block_scale = (MACROBLOCK_WIDTH, MACROBLOCK_HEIGHT) / (dst.width, dst.height)
+ * mv_scale = 0.5 / (dst.width, dst.height);
+ *
+ * t_vpos = (vpos + vrect) * block_scale
+ * o_vpos.xy = t_vpos
+ * o_vpos.zw = vpos
+ *
+ * o_eb[0..1] = vrect.x ? eb[0..1][1] : eb[0..1][0]
+ *
+ * o_frame_pred = frame_pred
+ * o_info.x = ref_frames
+ * o_info.y = ref_frames > 0
+ * o_info.z = bkwd_pred
+ *
+ * // Apply motion vectors
+ * o_vmv[0..count] = t_vpos + vmv[0..count] * mv_scale
+ *
+ * o_line.xy = vrect * 8
+ * o_line.z = interlaced
+ *
+ * if(eb[0][0].w) { //interlaced
+ * t_vtex.x = vrect.x
+ * t_vtex.y = vrect.y * 0.5
+ * t_vtex += vpos
+ *
+ * o_vtex[0].xy = t_vtex * block_scale
+ *
+ * t_vtex.y += 0.5
+ * o_vtex[1].xy = t_vtex * block_scale
+ * } else {
+ * o_vtex[0..1].xy = t_vpos
+ * }
+ * o_vtex[2].xy = t_vpos
+ *
*/
- 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));
+ block_scale = ureg_imm2f(shader,
+ (float)MACROBLOCK_WIDTH / r->buffer_width,
+ (float)MACROBLOCK_HEIGHT / r->buffer_height);
+
+ mv_scale = ureg_imm2f(shader,
+ 0.5f / r->buffer_width,
+ 0.5f / r->buffer_height);
+
+ ureg_ADD(shader, ureg_writemask(t_vpos, TGSI_WRITEMASK_XY), vpos, vrect);
+ ureg_MUL(shader, ureg_writemask(t_vpos, TGSI_WRITEMASK_XY), ureg_src(t_vpos), block_scale);
+ ureg_MOV(shader, ureg_writemask(o_vpos, TGSI_WRITEMASK_XY), ureg_src(t_vpos));
+ ureg_MOV(shader, ureg_writemask(o_vpos, TGSI_WRITEMASK_ZW), vpos);
+
+ ureg_CMP(shader, ureg_writemask(o_eb[0], TGSI_WRITEMASK_XYZ),
+ ureg_negate(ureg_scalar(vrect, TGSI_SWIZZLE_X)),
+ eb[0][1], eb[0][0]);
+ ureg_CMP(shader, ureg_writemask(o_eb[1], TGSI_WRITEMASK_XYZ),
+ ureg_negate(ureg_scalar(vrect, TGSI_SWIZZLE_X)),
+ eb[1][1], eb[1][0]);
+
+ ureg_MOV(shader, ureg_writemask(o_info, TGSI_WRITEMASK_X),
+ ureg_scalar(eb[1][1], TGSI_SWIZZLE_W));
+ ureg_SGE(shader, ureg_writemask(o_info, TGSI_WRITEMASK_Y),
+ ureg_scalar(eb[1][1], TGSI_SWIZZLE_W), ureg_imm1f(shader, 0.0f));
+ ureg_MOV(shader, ureg_writemask(o_info, TGSI_WRITEMASK_Z),
+ ureg_scalar(eb[1][0], TGSI_SWIZZLE_W));
+
+ ureg_MAD(shader, ureg_writemask(o_vmv[0], TGSI_WRITEMASK_XY), mv_scale, vmv[0], ureg_src(t_vpos));
+ ureg_MAD(shader, ureg_writemask(o_vmv[2], TGSI_WRITEMASK_XY), mv_scale, vmv[2], ureg_src(t_vpos));
+
+ ureg_CMP(shader, ureg_writemask(t_vmv, TGSI_WRITEMASK_XY),
+ ureg_negate(ureg_scalar(eb[0][1], TGSI_SWIZZLE_W)),
+ vmv[0], vmv[1]);
+ ureg_MAD(shader, ureg_writemask(o_vmv[1], TGSI_WRITEMASK_XY), mv_scale, ureg_src(t_vmv), ureg_src(t_vpos));
+
+ ureg_CMP(shader, ureg_writemask(t_vmv, TGSI_WRITEMASK_XY),
+ ureg_negate(ureg_scalar(eb[0][1], TGSI_SWIZZLE_W)),
+ vmv[2], vmv[3]);
+ ureg_MAD(shader, ureg_writemask(o_vmv[3], TGSI_WRITEMASK_XY), mv_scale, ureg_src(t_vmv), ureg_src(t_vpos));
+
+ ureg_MOV(shader, ureg_writemask(o_vtex[0], TGSI_WRITEMASK_XY), ureg_src(t_vpos));
+ ureg_MOV(shader, ureg_writemask(o_vtex[1], TGSI_WRITEMASK_XY), ureg_src(t_vpos));
+ ureg_MOV(shader, ureg_writemask(o_vtex[2], TGSI_WRITEMASK_XY), ureg_src(t_vpos));
+
+ ureg_MOV(shader, ureg_writemask(o_line, TGSI_WRITEMASK_X), ureg_scalar(vrect, TGSI_SWIZZLE_Y));
+ ureg_MUL(shader, ureg_writemask(o_line, TGSI_WRITEMASK_Y),
+ vrect, ureg_imm1f(shader, MACROBLOCK_HEIGHT / 2));
+
+ ureg_IF(shader, ureg_scalar(eb[0][0], TGSI_SWIZZLE_W), &label);
+
+ ureg_MOV(shader, ureg_writemask(t_vtex, TGSI_WRITEMASK_X), vrect);
+ ureg_MUL(shader, ureg_writemask(t_vtex, TGSI_WRITEMASK_Y), vrect, ureg_imm1f(shader, 0.5f));
+ ureg_ADD(shader, ureg_writemask(t_vtex, TGSI_WRITEMASK_XY), vpos, ureg_src(t_vtex));
+ ureg_MUL(shader, ureg_writemask(o_vtex[0], TGSI_WRITEMASK_XY), ureg_src(t_vtex), block_scale);
+ ureg_ADD(shader, ureg_writemask(t_vtex, TGSI_WRITEMASK_Y), ureg_src(t_vtex), ureg_imm1f(shader, 0.5f));
+ ureg_MUL(shader, ureg_writemask(o_vtex[1], TGSI_WRITEMASK_XY), ureg_src(t_vtex), block_scale);
+
+ ureg_MUL(shader, ureg_writemask(o_line, TGSI_WRITEMASK_X),
+ ureg_scalar(vrect, TGSI_SWIZZLE_Y),
+ ureg_imm1f(shader, MACROBLOCK_HEIGHT / 2));
+
+ ureg_fixup_label(shader, label, ureg_get_instruction_number(shader));
+ ureg_ENDIF(shader);
+
+ ureg_release_temporary(shader, t_vtex);
+ ureg_release_temporary(shader, t_vpos);
+ ureg_release_temporary(shader, t_vmv);
- ureg_release_temporary(shader, texel);
- ureg_release_temporary(shader, temp);
ureg_END(shader);
- r->i_fs = ureg_create_shader_and_destroy(shader, r->pipe);
- if (!r->i_fs)
- return false;
-
- return true;
+ return ureg_create_shader_and_destroy(shader, r->pipe);
}
-static bool
-create_frame_pred_vert_shader(struct vl_mpeg12_mc_renderer *r)
+static struct ureg_dst
+calc_field(struct ureg_program *shader)
{
- struct ureg_program *shader;
- struct ureg_src vpos, vtex[4];
- struct ureg_dst o_vpos, o_vtex[4];
- unsigned i;
+ struct ureg_dst tmp;
+ struct ureg_src line;
- shader = ureg_create(TGSI_PROCESSOR_VERTEX);
- if (!shader)
- return false;
+ tmp = ureg_DECL_temporary(shader);
- 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);
+ line = ureg_DECL_fs_input(shader, TGSI_SEMANTIC_GENERIC, VS_O_LINE, TGSI_INTERPOLATE_LINEAR);
/*
- * o_vpos = vpos
- * o_vtex[0..2] = vtex[0..2]
- * o_vtex[3] = vpos + vtex[3] // Apply motion vector
+ * line.x going from 0 to 1 if not interlaced
+ * line.x going from 0 to 8 in steps of 0.5 if interlaced
+ * line.y going from 0 to 8 in steps of 0.5
+ *
+ * tmp.xy = fraction(line)
+ * tmp.xy = tmp.xy >= 0.5 ? 1 : 0
*/
- 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]);
-
- ureg_END(shader);
+ ureg_FRC(shader, ureg_writemask(tmp, TGSI_WRITEMASK_XY), line);
+ ureg_SGE(shader, ureg_writemask(tmp, TGSI_WRITEMASK_XY), ureg_src(tmp), ureg_imm1f(shader, 0.5f));
- r->p_vs[0] = ureg_create_shader_and_destroy(shader, r->pipe);
- if (!r->p_vs[0])
- return false;
-
- return true;
+ return tmp;
}
-#if 0
-static void
-create_field_pred_vert_shader(struct vl_mpeg12_mc_renderer *r)
+static struct ureg_dst
+fetch_ycbcr(struct vl_mpeg12_mc_renderer *r, struct ureg_program *shader, struct ureg_dst field)
{
- assert(false);
-}
-#endif
+ struct ureg_src tc[3], sampler[3], eb[2];
+ struct ureg_dst texel, t_tc, t_eb_info;
+ unsigned i, label;
-static bool
-create_frame_pred_frag_shader(struct vl_mpeg12_mc_renderer *r)
-{
- 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;
+ texel = ureg_DECL_temporary(shader);
+ t_tc = ureg_DECL_temporary(shader);
+ t_eb_info = ureg_DECL_temporary(shader);
- shader = ureg_create(TGSI_PROCESSOR_FRAGMENT);
- if (!shader)
- return false;
+ tc[0] = ureg_DECL_fs_input(shader, TGSI_SEMANTIC_GENERIC, VS_O_TEX0, TGSI_INTERPOLATE_LINEAR);
+ tc[1] = ureg_DECL_fs_input(shader, TGSI_SEMANTIC_GENERIC, VS_O_TEX1, TGSI_INTERPOLATE_LINEAR);
+ tc[2] = ureg_DECL_fs_input(shader, TGSI_SEMANTIC_GENERIC, VS_O_TEX2, TGSI_INTERPOLATE_LINEAR);
+
+ eb[0] = ureg_DECL_fs_input(shader, TGSI_SEMANTIC_GENERIC, VS_O_EB_0, TGSI_INTERPOLATE_CONSTANT);
+ eb[1] = ureg_DECL_fs_input(shader, TGSI_SEMANTIC_GENERIC, VS_O_EB_1, TGSI_INTERPOLATE_CONSTANT);
- for (i = 0; i < 4; ++i) {
- tc[i] = ureg_DECL_fs_input(shader, TGSI_SEMANTIC_GENERIC, i + 1, TGSI_INTERPOLATE_LINEAR);
+ for (i = 0; i < 3; ++i) {
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);
/*
- * 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
+ * texel.y = tex(field.y ? tc[1] : tc[0], sampler[0])
+ * texel.cb = tex(tc[2], sampler[1])
+ * texel.cr = tex(tc[2], sampler[2])
*/
+
+ ureg_CMP(shader, ureg_writemask(t_tc, TGSI_WRITEMASK_XY),
+ ureg_negate(ureg_scalar(ureg_src(field), TGSI_SWIZZLE_X)),
+ tc[1], tc[0]);
+
+ ureg_CMP(shader, ureg_writemask(t_eb_info, TGSI_WRITEMASK_XYZ),
+ ureg_negate(ureg_scalar(ureg_src(field), TGSI_SWIZZLE_X)),
+ eb[1], eb[0]);
+
+ /* r600g is ignoring TGSI_INTERPOLATE_CONSTANT, just workaround this */
+ ureg_SLT(shader, ureg_writemask(t_eb_info, TGSI_WRITEMASK_XYZ), ureg_src(t_eb_info), ureg_imm1f(shader, 0.5f));
+
+ ureg_MOV(shader, ureg_writemask(texel, TGSI_WRITEMASK_XYZ), ureg_imm1f(shader, 0.0f));
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));
+ ureg_IF(shader, ureg_scalar(ureg_src(t_eb_info), TGSI_SWIZZLE_X + i), &label);
- ureg_release_temporary(shader, texel);
- ureg_release_temporary(shader, ref);
- ureg_END(shader);
+ /* Nouveau can't writemask tex dst regs (yet?), so this won't work anymore on nvidia hardware */
+ if(i==0 || r->chroma_format == PIPE_VIDEO_CHROMA_FORMAT_444) {
+ ureg_TEX(shader, ureg_writemask(texel, TGSI_WRITEMASK_X << i), TGSI_TEXTURE_3D, ureg_src(t_tc), sampler[i]);
+ } else {
+ ureg_TEX(shader, ureg_writemask(texel, TGSI_WRITEMASK_X << i), TGSI_TEXTURE_3D, tc[2], sampler[i]);
+ }
- r->p_fs[0] = ureg_create_shader_and_destroy(shader, r->pipe);
- if (!r->p_fs[0])
- return false;
+ ureg_fixup_label(shader, label, ureg_get_instruction_number(shader));
+ ureg_ENDIF(shader);
+ }
- return true;
-}
+ ureg_release_temporary(shader, t_tc);
+ ureg_release_temporary(shader, t_eb_info);
-#if 0
-static void
-create_field_pred_frag_shader(struct vl_mpeg12_mc_renderer *r)
-{
- assert(false);
+ return texel;
}
-#endif
-static bool
-create_frame_bi_pred_vert_shader(struct vl_mpeg12_mc_renderer *r)
+static struct ureg_dst
+fetch_ref(struct ureg_program *shader, struct ureg_dst field)
{
- struct ureg_program *shader;
- struct ureg_src vpos, vtex[5];
- struct ureg_dst o_vpos, o_vtex[5];
- unsigned i;
+ struct ureg_src info;
+ struct ureg_src tc[4], sampler[2];
+ struct ureg_dst ref[2], result;
+ unsigned i, intra_label, bi_label, label;
- shader = ureg_create(TGSI_PROCESSOR_VERTEX);
- if (!shader)
- return false;
+ info = ureg_DECL_fs_input(shader, TGSI_SEMANTIC_GENERIC, VS_O_INFO, TGSI_INTERPOLATE_CONSTANT);
- 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 */
- ureg_DECL_vs_input(shader, 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);
+ tc[i] = ureg_DECL_fs_input(shader, TGSI_SEMANTIC_GENERIC, VS_O_MV0 + i, TGSI_INTERPOLATE_LINEAR);
- /*
- * o_vpos = vpos
- * o_vtex[0..2] = vtex[0..2]
- * o_vtex[3..4] = vpos + vtex[3..4] // Apply motion vector
- */
- 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]);
+ for (i = 0; i < 2; ++i) {
+ sampler[i] = ureg_DECL_sampler(shader, i + 3);
+ ref[i] = ureg_DECL_temporary(shader);
+ }
- ureg_END(shader);
+ result = ureg_DECL_temporary(shader);
+
+ ureg_MOV(shader, ureg_writemask(result, TGSI_WRITEMASK_XYZ), ureg_imm1f(shader, 0.5f));
+
+ ureg_IF(shader, ureg_scalar(info, TGSI_SWIZZLE_Y), &intra_label);
+ ureg_CMP(shader, ureg_writemask(ref[0], TGSI_WRITEMASK_XY),
+ ureg_negate(ureg_scalar(ureg_src(field), TGSI_SWIZZLE_Y)),
+ tc[1], tc[0]);
+
+ ureg_IF(shader, ureg_scalar(info, TGSI_SWIZZLE_X), &bi_label);
+
+ /*
+ * result = tex(field.z ? tc[1] : tc[0], sampler[bkwd_pred ? 1 : 0])
+ */
+ ureg_IF(shader, ureg_scalar(info, TGSI_SWIZZLE_Z), &label);
+ ureg_TEX(shader, result, TGSI_TEXTURE_2D, ureg_src(ref[0]), sampler[1]);
+ ureg_fixup_label(shader, label, ureg_get_instruction_number(shader));
+ ureg_ELSE(shader, &label);
+ ureg_TEX(shader, result, TGSI_TEXTURE_2D, ureg_src(ref[0]), sampler[0]);
+ ureg_fixup_label(shader, label, ureg_get_instruction_number(shader));
+ ureg_ENDIF(shader);
+
+ ureg_fixup_label(shader, bi_label, ureg_get_instruction_number(shader));
+ ureg_ELSE(shader, &bi_label);
+
+ /*
+ * if (field.z)
+ * ref[0..1] = tex(tc[0..1], sampler[0..1])
+ * else
+ * ref[0..1] = tex(tc[2..3], sampler[0..1])
+ */
+ ureg_CMP(shader, ureg_writemask(ref[1], TGSI_WRITEMASK_XY),
+ ureg_negate(ureg_scalar(ureg_src(field), TGSI_SWIZZLE_Y)),
+ tc[3], tc[2]);
+ ureg_TEX(shader, ref[0], TGSI_TEXTURE_2D, ureg_src(ref[0]), sampler[0]);
+ ureg_TEX(shader, ref[1], TGSI_TEXTURE_2D, ureg_src(ref[1]), sampler[1]);
+
+ ureg_LRP(shader, ureg_writemask(result, TGSI_WRITEMASK_XYZ), ureg_imm1f(shader, 0.5f),
+ ureg_src(ref[0]), ureg_src(ref[1]));
+
+ ureg_fixup_label(shader, bi_label, ureg_get_instruction_number(shader));
+ ureg_ENDIF(shader);
+ ureg_fixup_label(shader, intra_label, ureg_get_instruction_number(shader));
+ ureg_ENDIF(shader);
- r->b_vs[0] = ureg_create_shader_and_destroy(shader, r->pipe);
- if (!r->b_vs[0])
- return false;
-
- return true;
-}
+ for (i = 0; i < 2; ++i)
+ ureg_release_temporary(shader, ref[i]);
-#if 0
-static void
-create_field_bi_pred_vert_shader(struct vl_mpeg12_mc_renderer *r)
-{
- assert(false);
+ return result;
}
-#endif
-static bool
-create_frame_bi_pred_frag_shader(struct vl_mpeg12_mc_renderer *r)
+static void *
+create_frag_shader(struct vl_mpeg12_mc_renderer *r)
{
struct ureg_program *shader;
- struct ureg_src tc[5];
- struct ureg_src sampler[5];
- struct ureg_dst texel, ref[2];
+ struct ureg_dst result;
+ struct ureg_dst field, texel;
struct ureg_dst fragment;
- unsigned i;
shader = ureg_create(TGSI_PROCESSOR_FRAGMENT);
if (!shader)
- return false;
+ return NULL;
- 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);
- /*
- * 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 (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]));
+ field = calc_field(shader);
+ texel = fetch_ycbcr(r, shader, field);
+
+ result = fetch_ref(shader, field);
- ureg_MAD(shader, fragment, ureg_src(texel), ureg_scalar(ureg_imm1f(shader, SCALE_FACTOR_16_TO_9), TGSI_SWIZZLE_X), ureg_src(ref[0]));
+ ureg_ADD(shader, ureg_writemask(fragment, TGSI_WRITEMASK_XYZ), ureg_src(texel), ureg_src(result));
+ ureg_release_temporary(shader, field);
ureg_release_temporary(shader, texel);
- ureg_release_temporary(shader, ref[0]);
- ureg_release_temporary(shader, ref[1]);
+ ureg_release_temporary(shader, result);
ureg_END(shader);
- r->b_fs[0] = ureg_create_shader_and_destroy(shader, r->pipe);
- if (!r->b_fs[0])
- return false;
-
- 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 (i = 0; i < 3; ++i) {
- struct pipe_box rect =
- {
- 0, 0, 0,
- r->textures.all[i]->width0,
- r->textures.all[i]->height0,
- 1
- };
-
- r->tex_transfer[i] = r->pipe->get_transfer
- (
- r->pipe, r->textures.all[i],
- u_subresource(0, 0),
- PIPE_TRANSFER_WRITE | PIPE_TRANSFER_DISCARD,
- &rect
- );
-
- r->texels[i] = r->pipe->transfer_map(r->pipe, r->tex_transfer[i]);
- }
-}
-
-static void
-xfer_buffers_unmap(struct vl_mpeg12_mc_renderer *r)
-{
- unsigned i;
-
- assert(r);
-
- for (i = 0; i < 3; ++i) {
- r->pipe->transfer_unmap(r->pipe, r->tex_transfer[i]);
- r->pipe->transfer_destroy(r->pipe, r->tex_transfer[i]);
- }
+ return ureg_create_shader_and_destroy(shader, r->pipe);
}
static bool
init_pipe_state(struct vl_mpeg12_mc_renderer *r)
{
struct pipe_sampler_state sampler;
+ struct pipe_rasterizer_state rs_state;
unsigned filters[5];
unsigned i;
assert(r);
- r->viewport.scale[0] = r->pot_buffers ?
- util_next_power_of_two(r->picture_width) : r->picture_width;
- r->viewport.scale[1] = r->pot_buffers ?
- util_next_power_of_two(r->picture_height) : r->picture_height;
+ r->viewport.scale[0] = r->buffer_width;
+ r->viewport.scale[1] = r->buffer_height;
r->viewport.scale[2] = 1;
r->viewport.scale[3] = 1;
r->viewport.translate[0] = 0;
r->viewport.translate[2] = 0;
r->viewport.translate[3] = 0;
- r->fb_state.width = r->pot_buffers ?
- util_next_power_of_two(r->picture_width) : r->picture_width;
- r->fb_state.height = r->pot_buffers ?
- util_next_power_of_two(r->picture_height) : r->picture_height;
+ r->fb_state.width = r->buffer_width;
+ r->fb_state.height = r->buffer_height;
r->fb_state.nr_cbufs = 1;
r->fb_state.zsbuf = NULL;
/* Luma filter */
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) {
+ if (r->chroma_format == PIPE_VIDEO_CHROMA_FORMAT_444 || true) { //TODO
filters[1] = PIPE_TEX_FILTER_NEAREST;
filters[2] = PIPE_TEX_FILTER_NEAREST;
}
memset(&sampler, 0, sizeof(sampler));
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;
+ sampler.wrap_r = PIPE_TEX_WRAP_CLAMP_TO_BORDER;
sampler.min_img_filter = filters[i];
sampler.min_mip_filter = PIPE_TEX_MIPFILTER_NONE;
sampler.mag_img_filter = filters[i];
/*sampler.lod_bias = ; */
sampler.min_lod = 0;
/*sampler.max_lod = ; */
- /*sampler.border_color[i] = ; */
+ sampler.border_color[0] = 0.0f;
+ sampler.border_color[1] = 0.0f;
+ sampler.border_color[2] = 0.0f;
+ sampler.border_color[3] = 0.0f;
/*sampler.max_anisotropy = ; */
r->samplers.all[i] = r->pipe->create_sampler_state(r->pipe, &sampler);
}
+ memset(&rs_state, 0, sizeof(rs_state));
+ /*rs_state.sprite_coord_enable */
+ rs_state.sprite_coord_mode = PIPE_SPRITE_COORD_UPPER_LEFT;
+ rs_state.point_quad_rasterization = true;
+ rs_state.point_size = BLOCK_WIDTH;
+ rs_state.gl_rasterization_rules = true;
+ r->rs_state = r->pipe->create_rasterizer_state(r->pipe, &rs_state);
+
return true;
}
for (i = 0; i < 5; ++i)
r->pipe->delete_sampler_state(r->pipe, r->samplers.all[i]);
-}
-static bool
-init_shaders(struct vl_mpeg12_mc_renderer *r)
-{
- assert(r);
-
- create_intra_vert_shader(r);
- create_intra_frag_shader(r);
- create_frame_pred_vert_shader(r);
- create_frame_pred_frag_shader(r);
- create_frame_bi_pred_vert_shader(r);
- create_frame_bi_pred_frag_shader(r);
-
- return true;
-}
-
-static void
-cleanup_shaders(struct vl_mpeg12_mc_renderer *r)
-{
- assert(r);
-
- r->pipe->delete_vs_state(r->pipe, r->i_vs);
- r->pipe->delete_fs_state(r->pipe, r->i_fs);
- r->pipe->delete_vs_state(r->pipe, r->p_vs[0]);
- r->pipe->delete_fs_state(r->pipe, r->p_fs[0]);
- r->pipe->delete_vs_state(r->pipe, r->b_vs[0]);
- r->pipe->delete_fs_state(r->pipe, r->b_fs[0]);
+ r->pipe->delete_rasterizer_state(r->pipe, r->rs_state);
}
static bool
init_buffers(struct vl_mpeg12_mc_renderer *r)
{
- struct pipe_resource template;
- struct pipe_vertex_element vertex_elems[8];
- struct pipe_sampler_view sampler_view;
+ struct pipe_resource *idct_matrix;
+ struct pipe_vertex_element vertex_elems[NUM_VS_INPUTS];
const unsigned mbw =
- align(r->picture_width, MACROBLOCK_WIDTH) / MACROBLOCK_WIDTH;
+ align(r->buffer_width, MACROBLOCK_WIDTH) / MACROBLOCK_WIDTH;
const unsigned mbh =
- align(r->picture_height, MACROBLOCK_HEIGHT) / MACROBLOCK_HEIGHT;
+ align(r->buffer_height, MACROBLOCK_HEIGHT) / MACROBLOCK_HEIGHT;
- unsigned i;
+ unsigned i, chroma_width, chroma_height;
assert(r);
r->macroblocks_per_batch =
mbw * (r->bufmode == VL_MPEG12_MC_RENDERER_BUFFER_PICTURE ? mbh : 1);
- r->num_macroblocks = 0;
- r->macroblock_buf = MALLOC(r->macroblocks_per_batch * sizeof(struct pipe_mpeg12_macroblock));
- memset(&template, 0, sizeof(struct pipe_resource));
- template.target = PIPE_TEXTURE_2D;
- /* 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.width0 = r->pot_buffers ?
- util_next_power_of_two(r->picture_width) : r->picture_width;
- template.height0 = r->pot_buffers ?
- util_next_power_of_two(r->picture_height) : r->picture_height;
- template.depth0 = 1;
- template.usage = PIPE_USAGE_DYNAMIC;
- template.bind = PIPE_BIND_SAMPLER_VIEW;
- template.flags = 0;
+ if (!(idct_matrix = vl_idct_upload_matrix(r->pipe)))
+ return false;
- r->textures.individual.y = r->pipe->screen->resource_create(r->pipe->screen, &template);
+ if (!vl_idct_init(&r->idct_luma, r->pipe, r->buffer_width, r->buffer_height, idct_matrix))
+ return false;
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.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.height0 = r->pot_buffers ?
- util_next_power_of_two(r->picture_height / 2) :
- r->picture_height / 2;
-
- r->textures.individual.cb =
- r->pipe->screen->resource_create(r->pipe->screen, &template);
- r->textures.individual.cr =
- r->pipe->screen->resource_create(r->pipe->screen, &template);
-
- for (i = 0; i < 3; ++i) {
- u_sampler_view_default_template(&sampler_view,
- r->textures.all[i],
- r->textures.all[i]->format);
- r->sampler_views.all[i] = r->pipe->create_sampler_view(r->pipe, r->textures.all[i], &sampler_view);
+ chroma_width = r->buffer_width / 2;
+ chroma_height = r->buffer_height / 2;
+ } else if (r->chroma_format == PIPE_VIDEO_CHROMA_FORMAT_422) {
+ chroma_width = r->buffer_width;
+ chroma_height = r->buffer_height / 2;
+ } else {
+ chroma_width = r->buffer_width;
+ chroma_height = r->buffer_height;
}
- r->vertex_bufs.individual.ycbcr.stride = sizeof(struct vertex2f) * 4;
- r->vertex_bufs.individual.ycbcr.max_index = 24 * r->macroblocks_per_batch - 1;
- r->vertex_bufs.individual.ycbcr.buffer_offset = 0;
- /* XXX: Create with usage DYNAMIC or STREAM */
- r->vertex_bufs.individual.ycbcr.buffer = pipe_buffer_create
- (
- r->pipe->screen,
- PIPE_BIND_VERTEX_BUFFER,
- sizeof(struct vertex2f) * 4 * 24 * r->macroblocks_per_batch
- );
-
- 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;
- /* XXX: Create with usage DYNAMIC or STREAM */
- r->vertex_bufs.all[i].buffer = pipe_buffer_create
- (
- r->pipe->screen,
- PIPE_BIND_VERTEX_BUFFER,
- sizeof(struct vertex2f) * 2 * 24 * r->macroblocks_per_batch
- );
- }
+ if(!vl_idct_init(&r->idct_chroma, r->pipe, chroma_width, chroma_height, idct_matrix))
+ return false;
memset(&vertex_elems, 0, sizeof(vertex_elems));
- /* Position element */
- vertex_elems[0].src_offset = 0;
- vertex_elems[0].instance_divisor = 0;
- vertex_elems[0].vertex_buffer_index = 0;
- vertex_elems[0].src_format = PIPE_FORMAT_R32G32_FLOAT;
-
- /* Luma, texcoord element */
- vertex_elems[1].src_offset = sizeof(struct vertex2f);
- vertex_elems[1].instance_divisor = 0;
- vertex_elems[1].vertex_buffer_index = 0;
- vertex_elems[1].src_format = PIPE_FORMAT_R32G32_FLOAT;
-
- /* Chroma Cr texcoord element */
- vertex_elems[2].src_offset = sizeof(struct vertex2f) * 2;
- vertex_elems[2].instance_divisor = 0;
- vertex_elems[2].vertex_buffer_index = 0;
- vertex_elems[2].src_format = PIPE_FORMAT_R32G32_FLOAT;
-
- /* Chroma Cb texcoord element */
- vertex_elems[3].src_offset = sizeof(struct vertex2f) * 3;
- vertex_elems[3].instance_divisor = 0;
- vertex_elems[3].vertex_buffer_index = 0;
- vertex_elems[3].src_format = PIPE_FORMAT_R32G32_FLOAT;
-
- /* First ref surface top field texcoord element */
- vertex_elems[4].src_offset = 0;
- vertex_elems[4].instance_divisor = 0;
- vertex_elems[4].vertex_buffer_index = 1;
- vertex_elems[4].src_format = PIPE_FORMAT_R32G32_FLOAT;
-
- /* First ref surface bottom field texcoord element */
- vertex_elems[5].src_offset = sizeof(struct vertex2f);
- vertex_elems[5].instance_divisor = 0;
- vertex_elems[5].vertex_buffer_index = 1;
- vertex_elems[5].src_format = PIPE_FORMAT_R32G32_FLOAT;
-
- /* Second ref surface top field texcoord element */
- vertex_elems[6].src_offset = 0;
- vertex_elems[6].instance_divisor = 0;
- vertex_elems[6].vertex_buffer_index = 2;
- vertex_elems[6].src_format = PIPE_FORMAT_R32G32_FLOAT;
-
- /* Second ref surface bottom field texcoord element */
- vertex_elems[7].src_offset = sizeof(struct vertex2f);
- vertex_elems[7].instance_divisor = 0;
- vertex_elems[7].vertex_buffer_index = 2;
- vertex_elems[7].src_format = PIPE_FORMAT_R32G32_FLOAT;
-
- r->vertex_elems_state.individual.i = r->pipe->create_vertex_elements_state(r->pipe, 4, vertex_elems);
- r->vertex_elems_state.individual.p = r->pipe->create_vertex_elements_state(r->pipe, 6, vertex_elems);
- r->vertex_elems_state.individual.b = r->pipe->create_vertex_elements_state(r->pipe, 8, vertex_elems);
-
- r->vs_const_buf = pipe_buffer_create
- (
- r->pipe->screen,
- PIPE_BIND_CONSTANT_BUFFER,
- sizeof(struct vertex_shader_consts)
- );
-
- return true;
-}
-
-static void
-cleanup_buffers(struct vl_mpeg12_mc_renderer *r)
-{
- unsigned i;
-
- assert(r);
-
- pipe_resource_reference(&r->vs_const_buf, NULL);
-
- for (i = 0; i < 3; ++i) {
- pipe_sampler_view_reference(&r->sampler_views.all[i], NULL);
- r->pipe->delete_vertex_elements_state(r->pipe, r->vertex_elems_state.all[i]);
- pipe_resource_reference(&r->vertex_bufs.all[i].buffer, NULL);
- pipe_resource_reference(&r->textures.all[i], NULL);
- }
-
- FREE(r->macroblock_buf);
-}
-
-static enum MACROBLOCK_TYPE
-get_macroblock_type(struct pipe_mpeg12_macroblock *mb)
-{
- assert(mb);
-
- switch (mb->mb_type) {
- case PIPE_MPEG12_MACROBLOCK_TYPE_INTRA:
- return MACROBLOCK_TYPE_INTRA;
- case PIPE_MPEG12_MACROBLOCK_TYPE_FWD:
- return mb->mo_type == PIPE_MPEG12_MOTION_TYPE_FRAME ?
- MACROBLOCK_TYPE_FWD_FRAME_PRED : MACROBLOCK_TYPE_FWD_FIELD_PRED;
- case PIPE_MPEG12_MACROBLOCK_TYPE_BKWD:
- return mb->mo_type == PIPE_MPEG12_MOTION_TYPE_FRAME ?
- MACROBLOCK_TYPE_BKWD_FRAME_PRED : MACROBLOCK_TYPE_BKWD_FIELD_PRED;
- case PIPE_MPEG12_MACROBLOCK_TYPE_BI:
- return mb->mo_type == PIPE_MPEG12_MOTION_TYPE_FRAME ?
- MACROBLOCK_TYPE_BI_FRAME_PRED : MACROBLOCK_TYPE_BI_FIELD_PRED;
- default:
- assert(0);
- }
-
- /* Unreachable */
- return -1;
-}
-
-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,
- struct pipe_mpeg12_macroblock *mb, unsigned pos,
- struct vert_stream_0 *ycbcr_vb, struct vertex2f **ref_vb)
-{
- struct vertex2f mo_vec[2];
-
- unsigned i;
-
- assert(r);
- assert(mb);
- assert(ycbcr_vb);
- assert(pos < r->macroblocks_per_batch);
-
- mo_vec[1].x = 0;
- mo_vec[1].y = 0;
-
- switch (mb->mb_type) {
- case PIPE_MPEG12_MACROBLOCK_TYPE_BI:
- {
- struct vertex2f *vb;
-
- assert(ref_vb && ref_vb[1]);
-
- vb = ref_vb[1] + pos * 2 * 24;
+ vertex_elems[VS_I_RECT] = vl_vb_get_quad_vertex_element();
+ r->quad = vl_vb_upload_quads(r->pipe, r->macroblocks_per_batch);
- 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 (i = 0; i < 24 * 2; i += 2) {
- vb[i].x = mo_vec[0].x;
- vb[i].y = mo_vec[0].y;
- }
- }
- 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 (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;
- vb[i + 1].y = mo_vec[1].y;
- }
- }
+ /* Position element */
+ vertex_elems[VS_I_VPOS].src_format = PIPE_FORMAT_R16G16_SSCALED;
- /* fall-through */
- }
- case PIPE_MPEG12_MACROBLOCK_TYPE_FWD:
- case PIPE_MPEG12_MACROBLOCK_TYPE_BKWD:
- {
- struct vertex2f *vb;
+ for (i = 0; i < 4; ++i)
+ /* motion vector 0..4 element */
+ vertex_elems[VS_I_MV0 + i].src_format = PIPE_FORMAT_R16G16_SSCALED;
- assert(ref_vb && ref_vb[0]);
+ /* y, cr, cb empty block element top left block */
+ vertex_elems[VS_I_EB_0_0].src_format = PIPE_FORMAT_R8G8B8A8_SSCALED;
- vb = ref_vb[0] + pos * 2 * 24;
+ /* y, cr, cb empty block element top right block */
+ vertex_elems[VS_I_EB_0_1].src_format = PIPE_FORMAT_R8G8B8A8_SSCALED;
- 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;
+ /* y, cr, cb empty block element bottom left block */
+ vertex_elems[VS_I_EB_1_0].src_format = PIPE_FORMAT_R8G8B8A8_SSCALED;
- 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 {
- 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;
+ /* y, cr, cb empty block element bottom right block */
+ vertex_elems[VS_I_EB_1_1].src_format = PIPE_FORMAT_R8G8B8A8_SSCALED;
- 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;
- }
- }
+ r->vertex_stream_stride = vl_vb_element_helper(&vertex_elems[VS_I_VPOS], 9, 1);
- 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 {
- 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;
- vb[i + 1].y = mo_vec[1].y;
- }
- }
+ r->vertex_elems_state = r->pipe->create_vertex_elements_state(
+ r->pipe, NUM_VS_INPUTS, vertex_elems);
- /* fall-through */
- }
- case PIPE_MPEG12_MACROBLOCK_TYPE_INTRA:
- {
- const struct vertex2f unit =
- {
- r->surface_tex_inv_size.x * MACROBLOCK_WIDTH,
- r->surface_tex_inv_size.y * MACROBLOCK_HEIGHT
- };
- const struct vertex2f half =
- {
- 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;
-
- gen_block_verts(vb, mb->cbp, mb->mbx, mb->mby,
- &unit, &half, &offsets[0][0],
- 32, 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);
+ if (r->vertex_elems_state == NULL)
+ return false;
- gen_block_verts(vb + 12, mb->cbp, mb->mbx, mb->mby,
- &unit, &half, &offsets[0][1],
- 8, 2, 1, use_zb, r->zero_block);
+ r->vs = create_vert_shader(r);
+ r->fs = create_frag_shader(r);
- gen_block_verts(vb + 18, mb->cbp, mb->mbx, mb->mby,
- &unit, &half, &offsets[1][1],
- 4, 2, 1, use_zb, r->zero_block);
+ if (r->vs == NULL || r->fs == NULL)
+ return false;
- break;
- }
- default:
- assert(0);
- }
+ return true;
}
static void
-gen_macroblock_stream(struct vl_mpeg12_mc_renderer *r,
- unsigned *num_macroblocks)
+cleanup_buffers(struct vl_mpeg12_mc_renderer *r)
{
- unsigned offset[NUM_MACROBLOCK_TYPES];
- struct vert_stream_0 *ycbcr_vb;
- struct vertex2f *ref_vb[2];
- struct pipe_transfer *buf_transfer[3];
- unsigned i;
-
assert(r);
- assert(num_macroblocks);
-
- 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 (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
- (
- r->pipe,
- r->vertex_bufs.individual.ycbcr.buffer,
- PIPE_TRANSFER_WRITE | PIPE_TRANSFER_DISCARD,
- &buf_transfer[0]
- );
+ r->pipe->delete_vs_state(r->pipe, r->vs);
+ r->pipe->delete_fs_state(r->pipe, r->fs);
- for (i = 0; i < 2; ++i)
- ref_vb[i] = (struct vertex2f *)pipe_buffer_map
- (
- r->pipe,
- r->vertex_bufs.individual.ref[i].buffer,
- PIPE_TRANSFER_WRITE | PIPE_TRANSFER_DISCARD,
- &buf_transfer[i + 1]
- );
-
- for (i = 0; i < r->num_macroblocks; ++i) {
- enum MACROBLOCK_TYPE mb_type = get_macroblock_type(&r->macroblock_buf[i]);
+ vl_idct_cleanup(&r->idct_luma);
+ vl_idct_cleanup(&r->idct_chroma);
- gen_macroblock_verts(r, &r->macroblock_buf[i], offset[mb_type],
- ycbcr_vb, ref_vb);
-
- ++offset[mb_type];
- }
-
- pipe_buffer_unmap(r->pipe, r->vertex_bufs.individual.ycbcr.buffer, buf_transfer[0]);
- for (i = 0; i < 2; ++i)
- pipe_buffer_unmap(r->pipe, r->vertex_bufs.individual.ref[i].buffer, buf_transfer[i + 1]);
+ r->pipe->delete_vertex_elements_state(r->pipe, r->vertex_elems_state);
}
static struct pipe_sampler_view
}
static void
-flush(struct vl_mpeg12_mc_renderer *r)
+get_motion_vectors(struct pipe_mpeg12_macroblock *mb, struct vertex2s mv[4])
{
- unsigned num_macroblocks[NUM_MACROBLOCK_TYPES] = { 0 };
- unsigned vb_start = 0;
- struct vertex_shader_consts *vs_consts;
- struct pipe_transfer *buf_transfer;
-
- unsigned i;
-
- assert(r);
- assert(r->num_macroblocks == r->macroblocks_per_batch);
-
- gen_macroblock_stream(r, num_macroblocks);
-
- r->fb_state.cbufs[0] = r->surface;
-
- r->pipe->set_framebuffer_state(r->pipe, &r->fb_state);
- r->pipe->set_viewport_state(r->pipe, &r->viewport);
-
- vs_consts = pipe_buffer_map
- (
- r->pipe, r->vs_const_buf,
- PIPE_TRANSFER_WRITE | PIPE_TRANSFER_DISCARD,
- &buf_transfer
- );
-
- vs_consts->denorm.x = r->surface->width;
- vs_consts->denorm.y = r->surface->height;
-
- pipe_buffer_unmap(r->pipe, r->vs_const_buf, buf_transfer);
-
- r->pipe->set_constant_buffer(r->pipe, PIPE_SHADER_VERTEX, 0,
- r->vs_const_buf);
-
-
- if (num_macroblocks[MACROBLOCK_TYPE_INTRA] > 0) {
- r->pipe->set_vertex_buffers(r->pipe, 1, r->vertex_bufs.all);
- r->pipe->bind_vertex_elements_state(r->pipe, r->vertex_elems_state.individual.i);
- r->pipe->set_fragment_sampler_views(r->pipe, 3, r->sampler_views.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);
-
- util_draw_arrays(r->pipe,PIPE_PRIM_TRIANGLES,vb_start,num_macroblocks[MACROBLOCK_TYPE_INTRA] * 24);
-
- vb_start += num_macroblocks[MACROBLOCK_TYPE_INTRA] * 24;
- }
-
- if (num_macroblocks[MACROBLOCK_TYPE_FWD_FRAME_PRED] > 0) {
- r->pipe->set_vertex_buffers(r->pipe, 2, r->vertex_bufs.all);
- r->pipe->bind_vertex_elements_state(r->pipe, r->vertex_elems_state.individual.p);
- r->textures.individual.ref[0] = r->past->texture;
- r->sampler_views.individual.ref[0] = find_or_create_sampler_view(r, r->past);
- r->pipe->set_fragment_sampler_views(r->pipe, 4, r->sampler_views.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]);
-
- util_draw_arrays(r->pipe,PIPE_PRIM_TRIANGLES,vb_start,num_macroblocks[MACROBLOCK_TYPE_FWD_FRAME_PRED] * 24);
-
-
- vb_start += num_macroblocks[MACROBLOCK_TYPE_FWD_FRAME_PRED] * 24;
- }
-
- if (false /*num_macroblocks[MACROBLOCK_TYPE_FWD_FIELD_PRED] > 0 */ ) {
- r->pipe->set_vertex_buffers(r->pipe, 2, r->vertex_bufs.all);
- r->pipe->bind_vertex_elements_state(r->pipe, r->vertex_elems_state.individual.p);
- r->textures.individual.ref[0] = r->past->texture;
- r->sampler_views.individual.ref[0] = find_or_create_sampler_view(r, r->past);
- r->pipe->set_fragment_sampler_views(r->pipe, 4, r->sampler_views.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]);
-
- util_draw_arrays(r->pipe,PIPE_PRIM_TRIANGLES,vb_start,num_macroblocks[MACROBLOCK_TYPE_FWD_FIELD_PRED] * 24);
+ switch (mb->mb_type) {
+ case PIPE_MPEG12_MACROBLOCK_TYPE_BI:
+ {
+ if (mb->mo_type == PIPE_MPEG12_MOTION_TYPE_FRAME) {
+ mv[2].x = mb->pmv[0][1][0];
+ mv[2].y = mb->pmv[0][1][1];
+ } else {
+ mv[2].x = mb->pmv[0][1][0];
+ mv[2].y = mb->pmv[0][1][1] - (mb->pmv[0][1][1] % 4);
- vb_start += num_macroblocks[MACROBLOCK_TYPE_FWD_FIELD_PRED] * 24;
- }
+ mv[3].x = mb->pmv[1][1][0];
+ mv[3].y = mb->pmv[1][1][1] - (mb->pmv[1][1][1] % 4);
- if (num_macroblocks[MACROBLOCK_TYPE_BKWD_FRAME_PRED] > 0) {
- r->pipe->set_vertex_buffers(r->pipe, 2, r->vertex_bufs.all);
- r->pipe->bind_vertex_elements_state(r->pipe, r->vertex_elems_state.individual.p);
- r->textures.individual.ref[0] = r->future->texture;
- r->sampler_views.individual.ref[0] = find_or_create_sampler_view(r, r->future);
- r->pipe->set_fragment_sampler_views(r->pipe, 4, r->sampler_views.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]);
+ if(mb->mvfs[0][1]) mv[2].y += 2;
+ if(!mb->mvfs[1][1]) mv[3].y -= 2;
+ }
- util_draw_arrays(r->pipe,PIPE_PRIM_TRIANGLES,vb_start,num_macroblocks[MACROBLOCK_TYPE_BKWD_FRAME_PRED] * 24);
+ /* fall-through */
+ }
+ case PIPE_MPEG12_MACROBLOCK_TYPE_FWD:
+ case PIPE_MPEG12_MACROBLOCK_TYPE_BKWD:
+ {
+ if (mb->mb_type == PIPE_MPEG12_MACROBLOCK_TYPE_BKWD) {
- vb_start += num_macroblocks[MACROBLOCK_TYPE_BKWD_FRAME_PRED] * 24;
- }
+ if (mb->mo_type == PIPE_MPEG12_MOTION_TYPE_FRAME) {
+ mv[0].x = mb->pmv[0][1][0];
+ mv[0].y = mb->pmv[0][1][1];
- if (false /*num_macroblocks[MACROBLOCK_TYPE_BKWD_FIELD_PRED] > 0*/ ) {
- r->pipe->set_vertex_buffers(r->pipe, 2, r->vertex_bufs.all);
- r->pipe->bind_vertex_elements_state(r->pipe, r->vertex_elems_state.individual.p);
- r->textures.individual.ref[0] = r->future->texture;
- r->sampler_views.individual.ref[0] = find_or_create_sampler_view(r, r->future);
- r->pipe->set_fragment_sampler_views(r->pipe, 4, r->sampler_views.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]);
+ } else {
+ mv[0].x = mb->pmv[0][1][0];
+ mv[0].y = mb->pmv[0][1][1] - (mb->pmv[0][1][1] % 4);
- util_draw_arrays(r->pipe,PIPE_PRIM_TRIANGLES,vb_start,num_macroblocks[MACROBLOCK_TYPE_BKWD_FIELD_PRED] * 24);
+ mv[1].x = mb->pmv[1][1][0];
+ mv[1].y = mb->pmv[1][1][1] - (mb->pmv[1][1][1] % 4);
- vb_start += num_macroblocks[MACROBLOCK_TYPE_BKWD_FIELD_PRED] * 24;
- }
+ if(mb->mvfs[0][1]) mv[0].y += 2;
+ if(!mb->mvfs[1][1]) mv[1].y -= 2;
+ }
- if (num_macroblocks[MACROBLOCK_TYPE_BI_FRAME_PRED] > 0) {
- r->pipe->set_vertex_buffers(r->pipe, 3, r->vertex_bufs.all);
- r->pipe->bind_vertex_elements_state(r->pipe, r->vertex_elems_state.individual.b);
- r->textures.individual.ref[0] = r->past->texture;
- r->textures.individual.ref[1] = r->future->texture;
- r->sampler_views.individual.ref[0] = find_or_create_sampler_view(r, r->past);
- r->sampler_views.individual.ref[1] = find_or_create_sampler_view(r, r->future);
- r->pipe->set_fragment_sampler_views(r->pipe, 5, r->sampler_views.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]);
+ } else {
+ if (mb->mo_type == PIPE_MPEG12_MOTION_TYPE_FRAME) {
+ mv[0].x = mb->pmv[0][0][0];
+ mv[0].y = mb->pmv[0][0][1];
- util_draw_arrays(r->pipe,PIPE_PRIM_TRIANGLES,vb_start,num_macroblocks[MACROBLOCK_TYPE_BI_FRAME_PRED] * 24);
+ } else {
+ mv[0].x = mb->pmv[0][0][0];
+ mv[0].y = mb->pmv[0][0][1] - (mb->pmv[0][0][1] % 4);
- vb_start += num_macroblocks[MACROBLOCK_TYPE_BI_FRAME_PRED] * 24;
- }
+ mv[1].x = mb->pmv[1][0][0];
+ mv[1].y = mb->pmv[1][0][1] - (mb->pmv[1][0][1] % 4);
- if (false /*num_macroblocks[MACROBLOCK_TYPE_BI_FIELD_PRED] > 0 */ ) {
- r->pipe->set_vertex_buffers(r->pipe, 3, r->vertex_bufs.all);
- r->pipe->bind_vertex_elements_state(r->pipe, r->vertex_elems_state.individual.b);
- r->textures.individual.ref[0] = r->past->texture;
- r->textures.individual.ref[1] = r->future->texture;
- r->sampler_views.individual.ref[0] = find_or_create_sampler_view(r, r->past);
- r->sampler_views.individual.ref[1] = find_or_create_sampler_view(r, r->future);
- r->pipe->set_fragment_sampler_views(r->pipe, 5, r->sampler_views.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]);
-
- util_draw_arrays(r->pipe,PIPE_PRIM_TRIANGLES,vb_start,num_macroblocks[MACROBLOCK_TYPE_BI_FIELD_PRED] * 24);
-
- vb_start += num_macroblocks[MACROBLOCK_TYPE_BI_FIELD_PRED] * 24;
+ if(mb->mvfs[0][0]) mv[0].y += 2;
+ if(!mb->mvfs[1][0]) mv[1].y -= 2;
+ }
+ }
+ }
+ default:
+ break;
}
-
- r->pipe->flush(r->pipe, PIPE_FLUSH_RENDER_CACHE, r->fence);
-
- if (r->eb_handling == VL_MPEG12_MC_RENDERER_EMPTY_BLOCK_XFER_ONE)
- for (i = 0; i < 3; ++i)
- r->zero_block[i].x = ZERO_BLOCK_NIL;
-
- r->num_macroblocks = 0;
}
static void
-grab_frame_coded_block(short *src, short *dst, unsigned dst_pitch)
+grab_vectors(struct vl_mpeg12_mc_renderer *r,
+ struct vl_mpeg12_mc_buffer *buffer,
+ struct pipe_mpeg12_macroblock *mb)
{
- unsigned y;
-
- assert(src);
- assert(dst);
+ struct vertex_stream stream;
- for (y = 0; y < BLOCK_HEIGHT; ++y)
- memcpy(dst + y * dst_pitch, src + y * BLOCK_WIDTH, BLOCK_WIDTH * 2);
-}
+ unsigned i, j;
-static void
-grab_field_coded_block(short *src, short *dst, unsigned dst_pitch)
-{
- unsigned y;
+ assert(r);
+ assert(mb);
- assert(src);
- assert(dst);
+ stream.pos.x = mb->mbx;
+ stream.pos.y = mb->mby;
+ for ( i = 0; i < 2; ++i) {
+ for ( j = 0; j < 2; ++j) {
+ stream.eb[i][j].y = !(mb->cbp & (*r->empty_block_mask)[0][i][j]);
+ stream.eb[i][j].cr = !(mb->cbp & (*r->empty_block_mask)[1][i][j]);
+ stream.eb[i][j].cb = !(mb->cbp & (*r->empty_block_mask)[2][i][j]);
+ }
+ }
+ stream.eb[0][0].flag = mb->dct_type == PIPE_MPEG12_DCT_TYPE_FIELD;
+ stream.eb[0][1].flag = mb->mo_type == PIPE_MPEG12_MOTION_TYPE_FRAME;
+ stream.eb[1][0].flag = mb->mb_type == PIPE_MPEG12_MACROBLOCK_TYPE_BKWD;
+ switch (mb->mb_type) {
+ case PIPE_MPEG12_MACROBLOCK_TYPE_INTRA:
+ stream.eb[1][1].flag = -1;
+ break;
- for (y = 0; y < BLOCK_HEIGHT; ++y)
- memcpy(dst + y * dst_pitch * 2, src + y * BLOCK_WIDTH, BLOCK_WIDTH * 2);
-}
+ case PIPE_MPEG12_MACROBLOCK_TYPE_FWD:
+ case PIPE_MPEG12_MACROBLOCK_TYPE_BKWD:
+ stream.eb[1][1].flag = 1;
+ break;
-static void
-fill_zero_block(short *dst, unsigned dst_pitch)
-{
- unsigned y;
+ case PIPE_MPEG12_MACROBLOCK_TYPE_BI:
+ stream.eb[1][1].flag = 0;
+ break;
- assert(dst);
+ default:
+ assert(0);
+ }
- for (y = 0; y < BLOCK_HEIGHT; ++y)
- memset(dst + y * dst_pitch, 0, BLOCK_WIDTH * 2);
+ get_motion_vectors(mb, stream.mv);
+ vl_vb_add_block(&buffer->vertex_stream, &stream);
}
static void
-grab_blocks(struct vl_mpeg12_mc_renderer *r, unsigned mbx, unsigned mby,
- enum pipe_mpeg12_dct_type dct_type, unsigned cbp, short *blocks)
+grab_blocks(struct vl_mpeg12_mc_renderer *r,
+ struct vl_mpeg12_mc_buffer *buffer,
+ unsigned mbx, unsigned mby,
+ unsigned cbp, short *blocks)
{
- unsigned tex_pitch;
- short *texels;
- unsigned tb = 0, sb = 0;
- unsigned mbpx = mbx * MACROBLOCK_WIDTH, mbpy = mby * MACROBLOCK_HEIGHT;
+ unsigned tb = 0;
unsigned x, y;
assert(r);
assert(blocks);
- tex_pitch = r->tex_transfer[0]->stride / util_format_get_blocksize(r->tex_transfer[0]->resource->format);
- texels = r->texels[0] + mbpy * tex_pitch + mbpx;
-
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 {
- grab_field_coded_block(blocks + sb * BLOCK_WIDTH * BLOCK_HEIGHT,
- texels + y * tex_pitch + x * BLOCK_WIDTH,
- tex_pitch);
- }
-
- ++sb;
- }
- 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])) {
- 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) {
- 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;
- }
- }
+ if (cbp & (*r->empty_block_mask)[0][y][x]) {
+ vl_idct_add_block(&buffer->idct_y, mbx * 2 + x, mby * 2 + y, blocks);
+ blocks += BLOCK_WIDTH * BLOCK_HEIGHT;
}
}
}
/* TODO: Implement 422, 444 */
assert(r->chroma_format == PIPE_VIDEO_CHROMA_FORMAT_420);
- mbpx /= 2;
- mbpy /= 2;
-
- for (tb = 0; tb < 2; ++tb) {
- tex_pitch = r->tex_transfer[tb + 1]->stride / util_format_get_blocksize(r->tex_transfer[tb + 1]->resource->format);
- texels = r->texels[tb + 1] + mbpy * tex_pitch + mbpx;
-
- 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) {
- if (r->eb_handling == VL_MPEG12_MC_RENDERER_EMPTY_BLOCK_XFER_ALL ||
- 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) {
- 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;
- }
- }
+ for (tb = 1; tb < 3; ++tb) {
+ if (cbp & (*r->empty_block_mask)[tb][0][0]) {
+ if(tb == 1)
+ vl_idct_add_block(&buffer->idct_cb, mbx, mby, blocks);
+ else
+ vl_idct_add_block(&buffer->idct_cr, mbx, mby, blocks);
+ blocks += BLOCK_WIDTH * BLOCK_HEIGHT;
}
}
}
static void
grab_macroblock(struct vl_mpeg12_mc_renderer *r,
+ struct vl_mpeg12_mc_buffer *buffer,
struct pipe_mpeg12_macroblock *mb)
{
assert(r);
assert(mb);
assert(mb->blocks);
- assert(r->num_macroblocks < r->macroblocks_per_batch);
-
- memcpy(&r->macroblock_buf[r->num_macroblocks], mb,
- sizeof(struct pipe_mpeg12_macroblock));
+ assert(buffer->num_macroblocks < r->macroblocks_per_batch);
- grab_blocks(r, mb->mbx, mb->mby, mb->dct_type, mb->cbp, mb->blocks);
+ grab_vectors(r, buffer, mb);
+ grab_blocks(r, buffer, mb->mbx, mb->mby, mb->cbp, mb->blocks);
- ++r->num_macroblocks;
+ ++buffer->num_macroblocks;
}
static void
bool
vl_mpeg12_mc_renderer_init(struct vl_mpeg12_mc_renderer *renderer,
struct pipe_context *pipe,
- unsigned picture_width,
- unsigned picture_height,
+ unsigned buffer_width,
+ unsigned buffer_height,
enum pipe_video_chroma_format chroma_format,
- enum VL_MPEG12_MC_RENDERER_BUFFER_MODE bufmode,
- enum VL_MPEG12_MC_RENDERER_EMPTY_BLOCK eb_handling,
- bool pot_buffers)
+ enum VL_MPEG12_MC_RENDERER_BUFFER_MODE bufmode)
{
- unsigned i;
-
assert(renderer);
assert(pipe);
+
/* TODO: Implement other policies */
assert(bufmode == VL_MPEG12_MC_RENDERER_BUFFER_PICTURE);
- /* TODO: Implement this */
- /* XXX: XFER_ALL sampling issue at block edges when using bilinear filtering */
- assert(eb_handling != VL_MPEG12_MC_RENDERER_EMPTY_BLOCK_XFER_NONE);
- /* TODO: Non-pot buffers untested, probably doesn't work without changes to texcoord generation, vert shader, etc */
- assert(pot_buffers);
memset(renderer, 0, sizeof(struct vl_mpeg12_mc_renderer));
renderer->pipe = pipe;
- renderer->picture_width = picture_width;
- renderer->picture_height = picture_height;
+ renderer->buffer_width = buffer_width;
+ renderer->buffer_height = buffer_height;
renderer->chroma_format = chroma_format;
renderer->bufmode = bufmode;
- renderer->eb_handling = eb_handling;
- renderer->pot_buffers = pot_buffers;
+
+ /* TODO: Implement 422, 444 */
+ assert(chroma_format == PIPE_VIDEO_CHROMA_FORMAT_420);
+ renderer->empty_block_mask = &const_empty_block_mask_420;
renderer->texview_map = util_new_keymap(sizeof(struct pipe_surface*), -1,
texview_map_delete);
if (!renderer->texview_map)
return false;
- if (!init_pipe_state(renderer)) {
- util_delete_keymap(renderer->texview_map, renderer->pipe);
+ if (!init_pipe_state(renderer))
+ goto error_pipe_state;
+
+ if (!init_buffers(renderer))
+ goto error_buffers;
+
+ return true;
+
+error_buffers:
+ cleanup_pipe_state(renderer);
+
+error_pipe_state:
+ util_delete_keymap(renderer->texview_map, renderer->pipe);
+ return false;
+}
+
+void
+vl_mpeg12_mc_renderer_cleanup(struct vl_mpeg12_mc_renderer *renderer)
+{
+ assert(renderer);
+
+ util_delete_keymap(renderer->texview_map, renderer->pipe);
+ cleanup_pipe_state(renderer);
+ cleanup_buffers(renderer);
+}
+
+bool
+vl_mpeg12_mc_init_buffer(struct vl_mpeg12_mc_renderer *renderer, struct vl_mpeg12_mc_buffer *buffer)
+{
+ struct pipe_resource template;
+ struct pipe_sampler_view sampler_view;
+
+ unsigned i;
+
+ assert(renderer && buffer);
+
+ buffer->surface = NULL;
+ buffer->past = NULL;
+ buffer->future = NULL;
+ buffer->num_macroblocks = 0;
+
+ memset(&template, 0, sizeof(struct pipe_resource));
+ template.target = PIPE_TEXTURE_2D;
+ /* 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.width0 = renderer->buffer_width;
+ template.height0 = renderer->buffer_height;
+ template.depth0 = 1;
+ template.usage = PIPE_USAGE_STATIC;
+ template.bind = PIPE_BIND_SAMPLER_VIEW;
+ template.flags = 0;
+
+ buffer->textures.individual.y = renderer->pipe->screen->resource_create(renderer->pipe->screen, &template);
+
+ if (!vl_idct_init_buffer(&renderer->idct_luma, &buffer->idct_y, buffer->textures.individual.y))
return false;
+
+ if (renderer->chroma_format == PIPE_VIDEO_CHROMA_FORMAT_420) {
+ template.width0 = renderer->buffer_width / 2;
+ template.height0 = renderer->buffer_height / 2;
}
- if (!init_shaders(renderer)) {
- util_delete_keymap(renderer->texview_map, renderer->pipe);
- cleanup_pipe_state(renderer);
+ else if (renderer->chroma_format == PIPE_VIDEO_CHROMA_FORMAT_422)
+ template.height0 = renderer->buffer_height / 2;
+
+ buffer->textures.individual.cb =
+ renderer->pipe->screen->resource_create(renderer->pipe->screen, &template);
+ buffer->textures.individual.cr =
+ renderer->pipe->screen->resource_create(renderer->pipe->screen, &template);
+
+ if (!vl_idct_init_buffer(&renderer->idct_chroma, &buffer->idct_cb, buffer->textures.individual.cb))
return false;
- }
- if (!init_buffers(renderer)) {
- util_delete_keymap(renderer->texview_map, renderer->pipe);
- cleanup_shaders(renderer);
- cleanup_pipe_state(renderer);
+
+ if (!vl_idct_init_buffer(&renderer->idct_chroma, &buffer->idct_cr, buffer->textures.individual.cr))
return false;
+
+ for (i = 0; i < 3; ++i) {
+ u_sampler_view_default_template(&sampler_view,
+ buffer->textures.all[i],
+ buffer->textures.all[i]->format);
+ sampler_view.swizzle_r = i == 0 ? PIPE_SWIZZLE_RED : PIPE_SWIZZLE_ZERO;
+ sampler_view.swizzle_g = i == 1 ? PIPE_SWIZZLE_RED : PIPE_SWIZZLE_ZERO;
+ sampler_view.swizzle_b = i == 2 ? PIPE_SWIZZLE_RED : PIPE_SWIZZLE_ZERO;
+ sampler_view.swizzle_a = PIPE_SWIZZLE_ONE;
+ buffer->sampler_views.all[i] = renderer->pipe->create_sampler_view(
+ renderer->pipe, buffer->textures.all[i], &sampler_view);
}
- renderer->surface = NULL;
- renderer->past = NULL;
- renderer->future = NULL;
- for (i = 0; i < 3; ++i)
- renderer->zero_block[i].x = ZERO_BLOCK_NIL;
- renderer->num_macroblocks = 0;
+ buffer->vertex_bufs.individual.quad.stride = renderer->quad.stride;
+ buffer->vertex_bufs.individual.quad.max_index = renderer->quad.max_index;
+ buffer->vertex_bufs.individual.quad.buffer_offset = renderer->quad.buffer_offset;
+ pipe_resource_reference(&buffer->vertex_bufs.individual.quad.buffer, renderer->quad.buffer);
- xfer_buffers_map(renderer);
+ buffer->vertex_bufs.individual.stream = vl_vb_init(
+ &buffer->vertex_stream, renderer->pipe, renderer->macroblocks_per_batch,
+ renderer->vertex_stream_stride);
return true;
}
void
-vl_mpeg12_mc_renderer_cleanup(struct vl_mpeg12_mc_renderer *renderer)
+vl_mpeg12_mc_cleanup_buffer(struct vl_mpeg12_mc_renderer *renderer, struct vl_mpeg12_mc_buffer *buffer)
{
- assert(renderer);
+ unsigned i;
- xfer_buffers_unmap(renderer);
+ assert(renderer && buffer);
- util_delete_keymap(renderer->texview_map, renderer->pipe);
- cleanup_pipe_state(renderer);
- cleanup_shaders(renderer);
- cleanup_buffers(renderer);
+ for (i = 0; i < 3; ++i) {
+ pipe_sampler_view_reference(&buffer->sampler_views.all[i], NULL);
+ pipe_resource_reference(&buffer->vertex_bufs.all[i].buffer, NULL);
+ pipe_resource_reference(&buffer->textures.all[i], NULL);
+ }
+
+ pipe_resource_reference(&buffer->vertex_bufs.individual.quad.buffer, NULL);
+ vl_vb_cleanup(&buffer->vertex_stream);
+
+ vl_idct_cleanup_buffer(&renderer->idct_luma, &buffer->idct_y);
+ vl_idct_cleanup_buffer(&renderer->idct_chroma, &buffer->idct_cb);
+ vl_idct_cleanup_buffer(&renderer->idct_chroma, &buffer->idct_cr);
+
+ pipe_surface_reference(&buffer->surface, NULL);
+ pipe_surface_reference(&buffer->past, NULL);
+ pipe_surface_reference(&buffer->future, NULL);
+}
+
+void
+vl_mpeg12_mc_map_buffer(struct vl_mpeg12_mc_renderer *renderer, struct vl_mpeg12_mc_buffer *buffer)
+{
+ assert(renderer && buffer);
- pipe_surface_reference(&renderer->surface, NULL);
- pipe_surface_reference(&renderer->past, NULL);
- pipe_surface_reference(&renderer->future, NULL);
+ vl_idct_map_buffers(&renderer->idct_luma, &buffer->idct_y);
+ vl_idct_map_buffers(&renderer->idct_chroma, &buffer->idct_cr);
+ vl_idct_map_buffers(&renderer->idct_chroma, &buffer->idct_cb);
+
+ vl_vb_map(&buffer->vertex_stream, renderer->pipe);
}
void
-vl_mpeg12_mc_renderer_render_macroblocks(struct vl_mpeg12_mc_renderer
- *renderer,
+vl_mpeg12_mc_renderer_render_macroblocks(struct vl_mpeg12_mc_renderer *renderer,
+ struct vl_mpeg12_mc_buffer *buffer,
struct pipe_surface *surface,
struct pipe_surface *past,
struct pipe_surface *future,
unsigned num_macroblocks,
- struct pipe_mpeg12_macroblock
- *mpeg12_macroblocks,
+ struct pipe_mpeg12_macroblock *mpeg12_macroblocks,
struct pipe_fence_handle **fence)
{
- bool new_surface = false;
-
- assert(renderer);
+ assert(renderer && buffer);
assert(surface);
assert(num_macroblocks);
assert(mpeg12_macroblocks);
- if (renderer->surface) {
- if (surface != renderer->surface) {
- if (renderer->num_macroblocks > 0) {
- xfer_buffers_unmap(renderer);
- flush(renderer);
- }
-
- new_surface = true;
- }
-
+ if (surface != buffer->surface) {
+ pipe_surface_reference(&buffer->surface, surface);
+ pipe_surface_reference(&buffer->past, past);
+ pipe_surface_reference(&buffer->future, future);
+ buffer->fence = fence;
+ } else {
/* If the surface we're rendering hasn't changed the ref frames shouldn't change. */
- assert(surface != renderer->surface || renderer->past == past);
- assert(surface != renderer->surface || renderer->future == future);
- }
- else
- new_surface = true;
-
- if (new_surface) {
- pipe_surface_reference(&renderer->surface, surface);
- pipe_surface_reference(&renderer->past, past);
- pipe_surface_reference(&renderer->future, future);
- renderer->fence = fence;
- renderer->surface_tex_inv_size.x = 1.0f / surface->width;
- renderer->surface_tex_inv_size.y = 1.0f / surface->height;
+ assert(buffer->past == past);
+ assert(buffer->future == future);
}
while (num_macroblocks) {
- unsigned left_in_batch = renderer->macroblocks_per_batch - renderer->num_macroblocks;
+ unsigned left_in_batch = renderer->macroblocks_per_batch - buffer->num_macroblocks;
unsigned num_to_submit = MIN2(num_macroblocks, left_in_batch);
unsigned 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]);
+ grab_macroblock(renderer, buffer, &mpeg12_macroblocks[i]);
}
num_macroblocks -= num_to_submit;
- if (renderer->num_macroblocks == renderer->macroblocks_per_batch) {
- xfer_buffers_unmap(renderer);
- flush(renderer);
- xfer_buffers_map(renderer);
- /* Next time we get this surface it may have new ref frames */
- pipe_surface_reference(&renderer->surface, NULL);
- pipe_surface_reference(&renderer->past, NULL);
- pipe_surface_reference(&renderer->future, NULL);
+ if (buffer->num_macroblocks == renderer->macroblocks_per_batch) {
+ vl_mpeg12_mc_unmap_buffer(renderer, buffer);
+ vl_mpeg12_mc_renderer_flush(renderer, buffer);
+ pipe_surface_reference(&buffer->surface, surface);
+ pipe_surface_reference(&buffer->past, past);
+ pipe_surface_reference(&buffer->future, future);
+ vl_mpeg12_mc_map_buffer(renderer, buffer);
}
}
}
+
+void
+vl_mpeg12_mc_unmap_buffer(struct vl_mpeg12_mc_renderer *renderer, struct vl_mpeg12_mc_buffer *buffer)
+{
+ assert(renderer && buffer);
+
+ vl_idct_unmap_buffers(&renderer->idct_luma, &buffer->idct_y);
+ vl_idct_unmap_buffers(&renderer->idct_chroma, &buffer->idct_cr);
+ vl_idct_unmap_buffers(&renderer->idct_chroma, &buffer->idct_cb);
+
+ vl_vb_unmap(&buffer->vertex_stream, renderer->pipe);
+}
+
+void
+vl_mpeg12_mc_renderer_flush(struct vl_mpeg12_mc_renderer *renderer, struct vl_mpeg12_mc_buffer *buffer)
+{
+ assert(renderer && buffer);
+ assert(buffer->num_macroblocks <= renderer->macroblocks_per_batch);
+
+ if (buffer->num_macroblocks == 0)
+ return;
+
+ vl_idct_flush(&renderer->idct_luma, &buffer->idct_y);
+ vl_idct_flush(&renderer->idct_chroma, &buffer->idct_cr);
+ vl_idct_flush(&renderer->idct_chroma, &buffer->idct_cb);
+
+ vl_vb_restart(&buffer->vertex_stream);
+
+ renderer->fb_state.cbufs[0] = buffer->surface;
+ renderer->pipe->bind_rasterizer_state(renderer->pipe, renderer->rs_state);
+ renderer->pipe->set_framebuffer_state(renderer->pipe, &renderer->fb_state);
+ renderer->pipe->set_viewport_state(renderer->pipe, &renderer->viewport);
+ renderer->pipe->set_vertex_buffers(renderer->pipe, 2, buffer->vertex_bufs.all);
+ renderer->pipe->bind_vertex_elements_state(renderer->pipe, renderer->vertex_elems_state);
+
+ if (buffer->past) {
+ buffer->textures.individual.ref[0] = buffer->past->texture;
+ buffer->sampler_views.individual.ref[0] = find_or_create_sampler_view(renderer, buffer->past);
+ } else {
+ buffer->textures.individual.ref[0] = buffer->surface->texture;
+ buffer->sampler_views.individual.ref[0] = find_or_create_sampler_view(renderer, buffer->surface);
+ }
+
+ if (buffer->future) {
+ buffer->textures.individual.ref[1] = buffer->future->texture;
+ buffer->sampler_views.individual.ref[1] = find_or_create_sampler_view(renderer, buffer->future);
+ } else {
+ buffer->textures.individual.ref[1] = buffer->surface->texture;
+ buffer->sampler_views.individual.ref[1] = find_or_create_sampler_view(renderer, buffer->surface);
+ }
+
+ renderer->pipe->set_fragment_sampler_views(renderer->pipe, 5, buffer->sampler_views.all);
+ renderer->pipe->bind_fragment_sampler_states(renderer->pipe, 5, renderer->samplers.all);
+
+ renderer->pipe->bind_vs_state(renderer->pipe, renderer->vs);
+ renderer->pipe->bind_fs_state(renderer->pipe, renderer->fs);
+ util_draw_arrays(renderer->pipe, PIPE_PRIM_QUADS, 0, buffer->num_macroblocks * 4);
+
+ renderer->pipe->flush(renderer->pipe, PIPE_FLUSH_RENDER_CACHE, buffer->fence);
+
+ /* Next time we get this surface it may have new ref frames */
+ pipe_surface_reference(&buffer->surface, NULL);
+ pipe_surface_reference(&buffer->past, NULL);
+ pipe_surface_reference(&buffer->future, NULL);
+
+ buffer->num_macroblocks = 0;
+}