diff options
author | Grigori Goronzy <greg@chown.ath.cx> | 2014-08-29 20:09:00 +0200 |
---|---|---|
committer | Grigori Goronzy <greg@chown.ath.cx> | 2015-04-26 12:11:30 +0200 |
commit | edb31ddef5eb3ba5f6cb08ec54c10bbab8234836 (patch) | |
tree | ec8e4efc717227aac14c348f32536a86ab0a8d48 | |
parent | a7c79eaa15cc64a779677db84b9b50deefaaa094 (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.c | 123 | ||||
-rw-r--r-- | src/gallium/auxiliary/vl/vl_compositor.h | 1 |
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; |