summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorGrigori Goronzy <greg@chown.ath.cx>2014-08-29 20:09:00 +0200
committerGrigori Goronzy <greg@chown.ath.cx>2015-04-26 12:11:30 +0200
commitedb31ddef5eb3ba5f6cb08ec54c10bbab8234836 (patch)
treeec8e4efc717227aac14c348f32536a86ab0a8d48
parenta7c79eaa15cc64a779677db84b9b50deefaaa094 (diff)
st/vl: use MPEG-2 chroma cositingvdpau-422
MPEG-2 and later video standards align the chroma sample position horizontally with the leftmost luma sample position. Add a half-texel offset to the chroma texture sampling coordinate to sample at the this position instead of sampling in the center between the luma texels. This avoids minor color smearing and blurriness with most video content. v2: use extra vertex attribute instead of abusing zw
-rw-r--r--src/gallium/auxiliary/vl/vl_compositor.c123
-rw-r--r--src/gallium/auxiliary/vl/vl_compositor.h1
2 files changed, 78 insertions, 46 deletions
diff --git a/src/gallium/auxiliary/vl/vl_compositor.c b/src/gallium/auxiliary/vl/vl_compositor.c
index 69839e6138..2f08c1540a 100644
--- a/src/gallium/auxiliary/vl/vl_compositor.c
+++ b/src/gallium/auxiliary/vl/vl_compositor.c
@@ -51,16 +51,17 @@ enum VS_OUTPUT
VS_O_VTEX = 0,
VS_O_VTOP,
VS_O_VBOTTOM,
+ VS_O_SIZE,
};
static void *
create_vert_shader(struct vl_compositor *c)
{
struct ureg_program *shader;
- struct ureg_src vpos, vtex, color;
+ struct ureg_src vpos, vtex, color, size;
struct ureg_dst tmp;
struct ureg_dst o_vpos, o_vtex, o_color;
- struct ureg_dst o_vtop, o_vbottom;
+ struct ureg_dst o_vtop, o_vbottom, o_size;
shader = ureg_create(TGSI_PROCESSOR_VERTEX);
if (!shader)
@@ -69,25 +70,29 @@ create_vert_shader(struct vl_compositor *c)
vpos = ureg_DECL_vs_input(shader, 0);
vtex = ureg_DECL_vs_input(shader, 1);
color = ureg_DECL_vs_input(shader, 2);
+ size = ureg_DECL_vs_input(shader, 3);
tmp = ureg_DECL_temporary(shader);
o_vpos = ureg_DECL_output(shader, TGSI_SEMANTIC_POSITION, VS_O_VPOS);
o_color = ureg_DECL_output(shader, TGSI_SEMANTIC_COLOR, VS_O_COLOR);
o_vtex = ureg_DECL_output(shader, TGSI_SEMANTIC_GENERIC, VS_O_VTEX);
o_vtop = ureg_DECL_output(shader, TGSI_SEMANTIC_GENERIC, VS_O_VTOP);
o_vbottom = ureg_DECL_output(shader, TGSI_SEMANTIC_GENERIC, VS_O_VBOTTOM);
+ o_size = ureg_DECL_output(shader, TGSI_SEMANTIC_GENERIC, VS_O_SIZE);
/*
* o_vpos = vpos
* o_vtex = vtex
* o_color = color
+ * o_size = size
*/
ureg_MOV(shader, o_vpos, vpos);
ureg_MOV(shader, o_vtex, vtex);
ureg_MOV(shader, o_color, color);
+ ureg_MOV(shader, o_size, size);
/*
- * tmp.x = vtex.w / 2
- * tmp.y = vtex.w / 4
+ * tmp.x = size.y / 2
+ * tmp.y = size.y / 4
*
* o_vtop.x = vtex.x
* o_vtop.y = vtex.y * tmp.x + 0.25f
@@ -100,9 +105,9 @@ create_vert_shader(struct vl_compositor *c)
* o_vbottom.w = 1 / tmp.y
*/
ureg_MUL(shader, ureg_writemask(tmp, TGSI_WRITEMASK_X),
- ureg_scalar(vtex, TGSI_SWIZZLE_W), ureg_imm1f(shader, 0.5f));
+ ureg_scalar(size, TGSI_SWIZZLE_Y), ureg_imm1f(shader, 0.5f));
ureg_MUL(shader, ureg_writemask(tmp, TGSI_WRITEMASK_Y),
- ureg_scalar(vtex, TGSI_SWIZZLE_W), ureg_imm1f(shader, 0.25f));
+ ureg_scalar(size, TGSI_SWIZZLE_Y), ureg_imm1f(shader, 0.25f));
ureg_MOV(shader, ureg_writemask(o_vtop, TGSI_WRITEMASK_X), vtex);
ureg_MAD(shader, ureg_writemask(o_vtop, TGSI_WRITEMASK_Y), ureg_scalar(vtex, TGSI_SWIZZLE_Y),
@@ -129,7 +134,8 @@ static void *
create_frag_shader_video_buffer(struct vl_compositor *c)
{
struct ureg_program *shader;
- struct ureg_src tc;
+ struct ureg_src tc, size;
+ struct ureg_dst tc_chroma;
struct ureg_src csc[3];
struct ureg_src sampler[3];
struct ureg_dst texel;
@@ -141,19 +147,27 @@ create_frag_shader_video_buffer(struct vl_compositor *c)
return false;
tc = ureg_DECL_fs_input(shader, TGSI_SEMANTIC_GENERIC, VS_O_VTEX, TGSI_INTERPOLATE_LINEAR);
+ size = ureg_DECL_fs_input(shader, TGSI_SEMANTIC_GENERIC, VS_O_SIZE, TGSI_INTERPOLATE_LINEAR);
for (i = 0; i < 3; ++i) {
csc[i] = ureg_DECL_constant(shader, i);
sampler[i] = ureg_DECL_sampler(shader, i);
}
texel = ureg_DECL_temporary(shader);
fragment = ureg_DECL_output(shader, TGSI_SEMANTIC_COLOR, 0);
+ tc_chroma = ureg_DECL_temporary(shader);
+
+ /* chroma offset */
+ ureg_MOV(shader, ureg_writemask(tc_chroma, TGSI_WRITEMASK_XYZW), tc);
+ ureg_ADD(shader, ureg_writemask(tc_chroma, TGSI_WRITEMASK_X), ureg_src(tc_chroma),
+ ureg_scalar(size, TGSI_SWIZZLE_X));
/*
* texel.xyz = tex(tc, sampler[i])
* fragment = csc * texel
*/
for (i = 0; i < 3; ++i)
- ureg_TEX(shader, ureg_writemask(texel, TGSI_WRITEMASK_X << i), TGSI_TEXTURE_2D_ARRAY, tc, sampler[i]);
+ ureg_TEX(shader, ureg_writemask(texel, TGSI_WRITEMASK_X << i), TGSI_TEXTURE_2D_ARRAY,
+ i ? ureg_src(tc_chroma) : tc, sampler[i]);
ureg_MOV(shader, ureg_writemask(texel, TGSI_WRITEMASK_W), ureg_imm1f(shader, 1.0f));
@@ -172,10 +186,12 @@ static void *
create_frag_shader_weave(struct vl_compositor *c)
{
struct ureg_program *shader;
+ struct ureg_src size;
struct ureg_src i_tc[2];
struct ureg_src csc[3];
struct ureg_src sampler[3];
struct ureg_dst t_tc[2];
+ struct ureg_dst t_tc_chroma[2];
struct ureg_dst t_texel[2];
struct ureg_dst o_fragment;
unsigned i, j;
@@ -184,6 +200,7 @@ create_frag_shader_weave(struct vl_compositor *c)
if (!shader)
return false;
+ size = ureg_DECL_fs_input(shader, TGSI_SEMANTIC_GENERIC, VS_O_SIZE, TGSI_INTERPOLATE_LINEAR);
i_tc[0] = ureg_DECL_fs_input(shader, TGSI_SEMANTIC_GENERIC, VS_O_VTOP, TGSI_INTERPOLATE_LINEAR);
i_tc[1] = ureg_DECL_fs_input(shader, TGSI_SEMANTIC_GENERIC, VS_O_VBOTTOM, TGSI_INTERPOLATE_LINEAR);
@@ -195,6 +212,7 @@ create_frag_shader_weave(struct vl_compositor *c)
for (i = 0; i < 2; ++i) {
t_tc[i] = ureg_DECL_temporary(shader);
t_texel[i] = ureg_DECL_temporary(shader);
+ t_tc_chroma[i] = ureg_DECL_temporary(shader);
}
o_fragment = ureg_DECL_output(shader, TGSI_SEMANTIC_COLOR, 0);
@@ -215,6 +233,9 @@ create_frag_shader_weave(struct vl_compositor *c)
ureg_src(t_tc[i]), ureg_scalar(i_tc[0], TGSI_SWIZZLE_W));
ureg_MUL(shader, ureg_writemask(t_tc[i], TGSI_WRITEMASK_Z),
ureg_src(t_tc[i]), ureg_scalar(i_tc[1], TGSI_SWIZZLE_W));
+ ureg_MOV(shader, ureg_writemask(t_tc_chroma[i], TGSI_WRITEMASK_XYZW), ureg_src(t_tc[i]));
+ ureg_ADD(shader, ureg_writemask(t_tc_chroma[i], TGSI_WRITEMASK_X), ureg_src(t_tc_chroma[i]),
+ ureg_scalar(size, TGSI_SWIZZLE_X));
}
/* fetch the texels
@@ -224,7 +245,7 @@ create_frag_shader_weave(struct vl_compositor *c)
*/
for (i = 0; i < 2; ++i)
for (j = 0; j < 3; ++j) {
- struct ureg_src src = ureg_swizzle(ureg_src(t_tc[i]),
+ struct ureg_src src = ureg_swizzle(j ? ureg_src(t_tc_chroma[i]) : ureg_src(t_tc[i]),
TGSI_SWIZZLE_X, j ? TGSI_SWIZZLE_Z : TGSI_SWIZZLE_Y, TGSI_SWIZZLE_W, TGSI_SWIZZLE_W);
ureg_TEX(shader, ureg_writemask(t_texel[i], TGSI_WRITEMASK_X << j),
@@ -501,14 +522,14 @@ static void cleanup_pipe_state(struct vl_compositor *c)
static bool
init_buffers(struct vl_compositor *c)
{
- struct pipe_vertex_element vertex_elems[3];
+ struct pipe_vertex_element vertex_elems[4];
assert(c);
/*
* Create our vertex buffer and vertex buffer elements
*/
- c->vertex_buf.stride = sizeof(struct vertex2f) + sizeof(struct vertex4f) * 2;
+ c->vertex_buf.stride = 2 * sizeof(struct vertex2f) + sizeof(struct vertex4f) * 2;
c->vertex_buf.buffer_offset = 0;
c->vertex_buf.buffer = NULL;
@@ -524,7 +545,11 @@ init_buffers(struct vl_compositor *c)
vertex_elems[2].instance_divisor = 0;
vertex_elems[2].vertex_buffer_index = 0;
vertex_elems[2].src_format = PIPE_FORMAT_R32G32B32A32_FLOAT;
- c->vertex_elems_state = c->pipe->create_vertex_elements_state(c->pipe, 3, vertex_elems);
+ vertex_elems[3].src_offset = sizeof(struct vertex2f) + 2 * sizeof(struct vertex4f);
+ vertex_elems[3].instance_divisor = 0;
+ vertex_elems[3].vertex_buffer_index = 0;
+ vertex_elems[3].src_format = PIPE_FORMAT_R32G32_FLOAT;
+ c->vertex_elems_state = c->pipe->create_vertex_elements_state(c->pipe, 4, vertex_elems);
return true;
}
@@ -570,8 +595,10 @@ calc_src_and_dst(struct vl_compositor_layer *layer, unsigned width, unsigned hei
layer->src.br = calc_bottomright(size, src);
layer->dst.tl = calc_topleft(size, dst);
layer->dst.br = calc_bottomright(size, dst);
- layer->zw.x = 0.0f;
- layer->zw.y = size.y;
+ layer->zw.x = 0.0f;
+ layer->zw.y = 0.0f;
+ layer->size.x = 0.5f / size.x; /* half a texel */
+ layer->size.y = size.y;
}
static void
@@ -626,36 +653,40 @@ gen_rect_verts(struct vertex2f *vb, struct vl_compositor_layer *layer)
vb[ 3].y = layer->colors[0].y;
vb[ 4].x = layer->colors[0].z;
vb[ 4].y = layer->colors[0].w;
-
- vb[ 5].x = tr.x;
- vb[ 5].y = tr.y;
- vb[ 6].x = layer->src.br.x;
- vb[ 6].y = layer->src.tl.y;
- vb[ 7] = layer->zw;
- vb[ 8].x = layer->colors[1].x;
- vb[ 8].y = layer->colors[1].y;
- vb[ 9].x = layer->colors[1].z;
- vb[ 9].y = layer->colors[1].w;
-
- vb[10].x = br.x;
- vb[10].y = br.y;
- vb[11].x = layer->src.br.x;
- vb[11].y = layer->src.br.y;
- vb[12] = layer->zw;
- vb[13].x = layer->colors[2].x;
- vb[13].y = layer->colors[2].y;
- vb[14].x = layer->colors[2].z;
- vb[14].y = layer->colors[2].w;
-
- vb[15].x = bl.x;
- vb[15].y = bl.y;
- vb[16].x = layer->src.tl.x;
- vb[16].y = layer->src.br.y;
- vb[17] = layer->zw;
- vb[18].x = layer->colors[3].x;
- vb[18].y = layer->colors[3].y;
- vb[19].x = layer->colors[3].z;
- vb[19].y = layer->colors[3].w;
+ vb[ 5] = layer->size;
+
+ vb[ 6].x = tr.x;
+ vb[ 6].y = tr.y;
+ vb[ 7].x = layer->src.br.x;
+ vb[ 7].y = layer->src.tl.y;
+ vb[ 8] = layer->zw;
+ vb[ 9].x = layer->colors[1].x;
+ vb[ 9].y = layer->colors[1].y;
+ vb[10].x = layer->colors[1].z;
+ vb[10].y = layer->colors[1].w;
+ vb[11] = layer->size;
+
+ vb[12].x = br.x;
+ vb[12].y = br.y;
+ vb[13].x = layer->src.br.x;
+ vb[13].y = layer->src.br.y;
+ vb[14] = layer->zw;
+ vb[15].x = layer->colors[2].x;
+ vb[15].y = layer->colors[2].y;
+ vb[16].x = layer->colors[2].z;
+ vb[16].y = layer->colors[2].w;
+ vb[17] = layer->size;
+
+ vb[18].x = bl.x;
+ vb[18].y = bl.y;
+ vb[19].x = layer->src.tl.x;
+ vb[19].y = layer->src.br.y;
+ vb[20] = layer->zw;
+ vb[21].x = layer->colors[3].x;
+ vb[21].y = layer->colors[3].y;
+ vb[22].x = layer->colors[3].z;
+ vb[22].y = layer->colors[3].w;
+ vb[23] = layer->size;
}
static INLINE struct u_rect
@@ -723,7 +754,7 @@ gen_vertex_data(struct vl_compositor *c, struct vl_compositor_state *s, struct u
if (s->used_layers & (1 << i)) {
struct vl_compositor_layer *layer = &s->layers[i];
gen_rect_verts(vb, layer);
- vb += 20;
+ vb += 24;
if (!layer->viewport_valid) {
layer->viewport.scale[0] = c->fb_state.width;
@@ -941,7 +972,7 @@ vl_compositor_set_buffer_layer(struct vl_compositor_state *s,
dst_rect ? *dst_rect : default_rect(&s->layers[layer]));
if (buffer->interlaced) {
- float half_a_line = 0.5f / s->layers[layer].zw.y;
+ float half_a_line = 0.5f / s->layers[layer].size.y;
switch(deinterlace) {
case VL_COMPOSITOR_WEAVE:
s->layers[layer].fs = c->fs_weave;
diff --git a/src/gallium/auxiliary/vl/vl_compositor.h b/src/gallium/auxiliary/vl/vl_compositor.h
index 934b634b39..75c6beb9ee 100644
--- a/src/gallium/auxiliary/vl/vl_compositor.h
+++ b/src/gallium/auxiliary/vl/vl_compositor.h
@@ -77,6 +77,7 @@ struct vl_compositor_layer
struct {
struct vertex2f tl, br;
} src, dst;
+ struct vertex2f size;
struct vertex2f zw;
struct vertex4f colors[4];
enum vl_compositor_rotation rotate;