diff options
author | Jonathan Gray <jsg@cvs.openbsd.org> | 2016-12-11 08:40:05 +0000 |
---|---|---|
committer | Jonathan Gray <jsg@cvs.openbsd.org> | 2016-12-11 08:40:05 +0000 |
commit | 21ab4c9f31674b113c24177398ed39f29b7cd8e6 (patch) | |
tree | 8be392d7a792d9663c2586396be77bfd506f5164 /lib/mesa/src/gallium/auxiliary/vl | |
parent | a8f0a7916e26e550dd2a26e7188835c481978004 (diff) |
Import Mesa 13.0.2
Diffstat (limited to 'lib/mesa/src/gallium/auxiliary/vl')
19 files changed, 1576 insertions, 152 deletions
diff --git a/lib/mesa/src/gallium/auxiliary/vl/vl_bicubic_filter.c b/lib/mesa/src/gallium/auxiliary/vl/vl_bicubic_filter.c new file mode 100644 index 000000000..0364d4326 --- /dev/null +++ b/lib/mesa/src/gallium/auxiliary/vl/vl_bicubic_filter.c @@ -0,0 +1,459 @@ +/************************************************************************** + * + * Copyright 2016 Nayan Deshmukh. + * 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 VMWARE 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 <stdio.h> + +#include "pipe/p_context.h" + +#include "tgsi/tgsi_ureg.h" + +#include "util/u_draw.h" +#include "util/u_memory.h" +#include "util/u_math.h" +#include "util/u_rect.h" + +#include "vl_types.h" +#include "vl_vertex_buffers.h" +#include "vl_bicubic_filter.h" + +enum VS_OUTPUT +{ + VS_O_VPOS = 0, + VS_O_VTEX = 0 +}; + +static void * +create_vert_shader(struct vl_bicubic_filter *filter) +{ + struct ureg_program *shader; + struct ureg_src i_vpos; + struct ureg_dst o_vpos, o_vtex; + + shader = ureg_create(PIPE_SHADER_VERTEX); + if (!shader) + return NULL; + + i_vpos = ureg_DECL_vs_input(shader, 0); + o_vpos = ureg_DECL_output(shader, TGSI_SEMANTIC_POSITION, VS_O_VPOS); + o_vtex = ureg_DECL_output(shader, TGSI_SEMANTIC_GENERIC, VS_O_VTEX); + + ureg_MOV(shader, o_vpos, i_vpos); + ureg_MOV(shader, o_vtex, i_vpos); + + ureg_END(shader); + + return ureg_create_shader_and_destroy(shader, filter->pipe); +} + +static void +create_frag_shader_cubic_interpolater(struct ureg_program *shader, struct ureg_src tex_a, + struct ureg_src tex_b, struct ureg_src tex_c, + struct ureg_src tex_d, struct ureg_src t, + struct ureg_dst o_fragment) +{ + struct ureg_dst temp[11]; + struct ureg_dst t_2; + unsigned i; + + for(i = 0; i < 11; ++i) + temp[i] = ureg_DECL_temporary(shader); + t_2 = ureg_DECL_temporary(shader); + + /* + * |temp[0]| | 0 2 0 0 | |tex_a| + * |temp[1]| = | -1 0 1 0 |* |tex_b| + * |temp[2]| | 2 -5 4 -1 | |tex_c| + * |temp[3]| | -1 3 -3 1 | |tex_d| + */ + ureg_MUL(shader, temp[0], tex_b, ureg_imm1f(shader, 2.0f)); + + ureg_MUL(shader, temp[1], tex_a, ureg_imm1f(shader, -1.0f)); + ureg_MAD(shader, temp[1], tex_c, ureg_imm1f(shader, 1.0f), + ureg_src(temp[1])); + + ureg_MUL(shader, temp[2], tex_a, ureg_imm1f(shader, 2.0f)); + ureg_MAD(shader, temp[2], tex_b, ureg_imm1f(shader, -5.0f), + ureg_src(temp[2])); + ureg_MAD(shader, temp[2], tex_c, ureg_imm1f(shader, 4.0f), + ureg_src(temp[2])); + ureg_MAD(shader, temp[2], tex_d, ureg_imm1f(shader, -1.0f), + ureg_src(temp[2])); + + ureg_MUL(shader, temp[3], tex_a, ureg_imm1f(shader, -1.0f)); + ureg_MAD(shader, temp[3], tex_b, ureg_imm1f(shader, 3.0f), + ureg_src(temp[3])); + ureg_MAD(shader, temp[3], tex_c, ureg_imm1f(shader, -3.0f), + ureg_src(temp[3])); + ureg_MAD(shader, temp[3], tex_d, ureg_imm1f(shader, 1.0f), + ureg_src(temp[3])); + + /* + * t_2 = t*t + * o_fragment = 0.5*|1 t t^2 t^3|*|temp[0]| + * |temp[1]| + * |temp[2]| + * |temp[3]| + */ + + ureg_MUL(shader, t_2, t, t); + ureg_MUL(shader, temp[4], ureg_src(t_2), t); + + ureg_MUL(shader, temp[4], ureg_src(temp[4]), + ureg_src(temp[3])); + ureg_MUL(shader, temp[5], ureg_src(t_2), + ureg_src(temp[2])); + ureg_MUL(shader, temp[6], t, + ureg_src(temp[1])); + ureg_MUL(shader, temp[7], ureg_imm1f(shader, 1.0f), + ureg_src(temp[0])); + ureg_ADD(shader, temp[8], ureg_src(temp[4]), + ureg_src(temp[5])); + ureg_ADD(shader, temp[9], ureg_src(temp[6]), + ureg_src(temp[7])); + + ureg_ADD(shader, temp[10], ureg_src(temp[8]), + ureg_src(temp[9])); + ureg_MUL(shader, o_fragment, ureg_src(temp[10]), + ureg_imm1f(shader, 0.5f)); + + + for(i = 0; i < 11; ++i) + ureg_release_temporary(shader, temp[i]); + ureg_release_temporary(shader, t_2); +} + +static void * +create_frag_shader(struct vl_bicubic_filter *filter, unsigned video_width, + unsigned video_height, struct vertex2f *offsets) +{ + struct pipe_screen *screen = filter->pipe->screen; + struct ureg_program *shader; + struct ureg_src i_vtex, vtex; + struct ureg_src sampler; + struct ureg_src half_pixel; + struct ureg_dst t_array[23]; + struct ureg_dst o_fragment; + struct ureg_dst t; + unsigned i; + + if (screen->get_shader_param( + screen, PIPE_SHADER_FRAGMENT, PIPE_SHADER_CAP_MAX_TEMPS) < 23) { + + return NULL; + } + + shader = ureg_create(PIPE_SHADER_FRAGMENT); + if (!shader) { + return NULL; + } + + i_vtex = ureg_DECL_fs_input(shader, TGSI_SEMANTIC_GENERIC, VS_O_VTEX, TGSI_INTERPOLATE_LINEAR); + sampler = ureg_DECL_sampler(shader, 0); + + for (i = 0; i < 23; ++i) + t_array[i] = ureg_DECL_temporary(shader); + t = ureg_DECL_temporary(shader); + + half_pixel = ureg_DECL_constant(shader, 0); + o_fragment = ureg_DECL_output(shader, TGSI_SEMANTIC_COLOR, 0); + + /* + * temp = (i_vtex - (0.5/dst_size)) * i_size) + * t = frac(temp) + * vtex = floor(i_vtex)/i_size + */ + ureg_SUB(shader, ureg_writemask(t_array[21], TGSI_WRITEMASK_XY), + i_vtex, half_pixel); + ureg_MUL(shader, ureg_writemask(t_array[22], TGSI_WRITEMASK_XY), + ureg_src(t_array[21]), ureg_imm2f(shader, video_width, video_height)); + ureg_FRC(shader, ureg_writemask(t, TGSI_WRITEMASK_XY), + ureg_src(t_array[22])); + + ureg_FLR(shader, ureg_writemask(t_array[22], TGSI_WRITEMASK_XY), + ureg_src(t_array[22])); + ureg_DIV(shader, ureg_writemask(t_array[22], TGSI_WRITEMASK_XY), + ureg_src(t_array[22]), ureg_imm2f(shader, video_width, video_height)); + ureg_ADD(shader, ureg_writemask(t_array[22], TGSI_WRITEMASK_XY), + ureg_src(t_array[22]), half_pixel); + + /* + * t_array[0..*] = vtex + offset[0..*] + * t_array[0..*] = tex(t_array[0..*], sampler) + * t_array[16+i] = cubic_interpolate(t_array[4*i..4*i+3], t_x) + * o_fragment = cubic_interpolate(t_array[16..19], t_y) + */ + vtex = ureg_src(t_array[22]); + for (i = 0; i < 16; ++i) { + ureg_ADD(shader, ureg_writemask(t_array[i], TGSI_WRITEMASK_XY), + vtex, ureg_imm2f(shader, offsets[i].x, offsets[i].y)); + ureg_MOV(shader, ureg_writemask(t_array[i], TGSI_WRITEMASK_ZW), + ureg_imm1f(shader, 0.0f)); + } + + for (i = 0; i < 16; ++i) { + ureg_TEX(shader, t_array[i], TGSI_TEXTURE_2D, ureg_src(t_array[i]), sampler); + } + + for(i = 0; i < 4; ++i) + create_frag_shader_cubic_interpolater(shader, ureg_src(t_array[4*i]), + ureg_src(t_array[4*i+1]), ureg_src(t_array[4*i+2]), ureg_src(t_array[4*i+3]), + ureg_scalar(ureg_src(t), TGSI_SWIZZLE_X), t_array[16+i]); + + create_frag_shader_cubic_interpolater(shader, ureg_src(t_array[16]), + ureg_src(t_array[17]), ureg_src(t_array[18]), ureg_src(t_array[19]), + ureg_scalar(ureg_src(t), TGSI_SWIZZLE_Y), o_fragment); + + for(i = 0; i < 23; ++i) + ureg_release_temporary(shader, t_array[i]); + ureg_release_temporary(shader, t); + + ureg_END(shader); + + return ureg_create_shader_and_destroy(shader, filter->pipe); +} + +bool +vl_bicubic_filter_init(struct vl_bicubic_filter *filter, struct pipe_context *pipe, + unsigned width, unsigned height) +{ + struct pipe_rasterizer_state rs_state; + struct pipe_blend_state blend; + struct vertex2f offsets[16]; + struct pipe_sampler_state sampler; + struct pipe_vertex_element ve; + unsigned i; + + assert(filter && pipe); + assert(width && height); + + memset(filter, 0, sizeof(*filter)); + filter->pipe = pipe; + + memset(&rs_state, 0, sizeof(rs_state)); + rs_state.half_pixel_center = true; + rs_state.bottom_edge_rule = true; + rs_state.depth_clip = 1; + filter->rs_state = pipe->create_rasterizer_state(pipe, &rs_state); + if (!filter->rs_state) + goto error_rs_state; + + memset(&blend, 0, sizeof blend); + blend.rt[0].rgb_func = PIPE_BLEND_ADD; + blend.rt[0].rgb_src_factor = PIPE_BLENDFACTOR_ONE; + blend.rt[0].rgb_dst_factor = PIPE_BLENDFACTOR_ONE; + blend.rt[0].alpha_func = PIPE_BLEND_ADD; + blend.rt[0].alpha_src_factor = PIPE_BLENDFACTOR_ONE; + blend.rt[0].alpha_dst_factor = PIPE_BLENDFACTOR_ONE; + blend.logicop_func = PIPE_LOGICOP_CLEAR; + blend.rt[0].colormask = PIPE_MASK_RGBA; + filter->blend = pipe->create_blend_state(pipe, &blend); + if (!filter->blend) + goto error_blend; + + 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.min_img_filter = PIPE_TEX_FILTER_NEAREST; + sampler.min_mip_filter = PIPE_TEX_MIPFILTER_NONE; + sampler.mag_img_filter = PIPE_TEX_FILTER_NEAREST; + sampler.compare_mode = PIPE_TEX_COMPARE_NONE; + sampler.compare_func = PIPE_FUNC_ALWAYS; + sampler.normalized_coords = 1; + filter->sampler = pipe->create_sampler_state(pipe, &sampler); + if (!filter->sampler) + goto error_sampler; + + filter->quad = vl_vb_upload_quads(pipe); + if(!filter->quad.buffer) + goto error_quad; + + memset(&ve, 0, sizeof(ve)); + ve.src_offset = 0; + ve.instance_divisor = 0; + ve.vertex_buffer_index = 0; + ve.src_format = PIPE_FORMAT_R32G32_FLOAT; + filter->ves = pipe->create_vertex_elements_state(pipe, 1, &ve); + if (!filter->ves) + goto error_ves; + + offsets[0].x = -1.0f; offsets[0].y = -1.0f; + offsets[1].x = 0.0f; offsets[1].y = -1.0f; + offsets[2].x = 1.0f; offsets[2].y = -1.0f; + offsets[3].x = 2.0f; offsets[3].y = -1.0f; + + offsets[4].x = -1.0f; offsets[4].y = 0.0f; + offsets[5].x = 0.0f; offsets[5].y = 0.0f; + offsets[6].x = 1.0f; offsets[6].y = 0.0f; + offsets[7].x = 2.0f; offsets[7].y = 0.0f; + + offsets[8].x = -1.0f; offsets[8].y = 1.0f; + offsets[9].x = 0.0f; offsets[9].y = 1.0f; + offsets[10].x = 1.0f; offsets[10].y = 1.0f; + offsets[11].x = 2.0f; offsets[11].y = 1.0f; + + offsets[12].x = -1.0f; offsets[12].y = 2.0f; + offsets[13].x = 0.0f; offsets[13].y = 2.0f; + offsets[14].x = 1.0f; offsets[14].y = 2.0f; + offsets[15].x = 2.0f; offsets[15].y = 2.0f; + + for (i = 0; i < 16; ++i) { + offsets[i].x /= width; + offsets[i].y /= height; + } + + filter->vs = create_vert_shader(filter); + if (!filter->vs) + goto error_vs; + + filter->fs = create_frag_shader(filter, width, height, offsets); + if (!filter->fs) + goto error_fs; + + return true; + +error_fs: + pipe->delete_vs_state(pipe, filter->vs); + +error_vs: + pipe->delete_vertex_elements_state(pipe, filter->ves); + +error_ves: + pipe_resource_reference(&filter->quad.buffer, NULL); + +error_quad: + pipe->delete_sampler_state(pipe, filter->sampler); + +error_sampler: + pipe->delete_blend_state(pipe, filter->blend); + +error_blend: + pipe->delete_rasterizer_state(pipe, filter->rs_state); + +error_rs_state: + return false; +} + +void +vl_bicubic_filter_cleanup(struct vl_bicubic_filter *filter) +{ + assert(filter); + + filter->pipe->delete_sampler_state(filter->pipe, filter->sampler); + filter->pipe->delete_blend_state(filter->pipe, filter->blend); + filter->pipe->delete_rasterizer_state(filter->pipe, filter->rs_state); + filter->pipe->delete_vertex_elements_state(filter->pipe, filter->ves); + pipe_resource_reference(&filter->quad.buffer, NULL); + + filter->pipe->delete_vs_state(filter->pipe, filter->vs); + filter->pipe->delete_fs_state(filter->pipe, filter->fs); +} + +void +vl_bicubic_filter_render(struct vl_bicubic_filter *filter, + struct pipe_sampler_view *src, + struct pipe_surface *dst, + struct u_rect *dst_area, + struct u_rect *dst_clip) +{ + struct pipe_viewport_state viewport; + struct pipe_framebuffer_state fb_state; + struct pipe_scissor_state scissor; + union pipe_color_union clear_color; + struct pipe_transfer *buf_transfer; + struct pipe_resource *surface_size; + assert(filter && src && dst); + + if (dst_clip) { + scissor.minx = dst_clip->x0; + scissor.miny = dst_clip->y0; + scissor.maxx = dst_clip->x1; + scissor.maxy = dst_clip->y1; + } else { + scissor.minx = 0; + scissor.miny = 0; + scissor.maxx = dst->width; + scissor.maxy = dst->height; + } + + clear_color.f[0] = clear_color.f[1] = 0.0f; + clear_color.f[2] = clear_color.f[3] = 0.0f; + surface_size = pipe_buffer_create + ( + filter->pipe->screen, + PIPE_BIND_CONSTANT_BUFFER, + PIPE_USAGE_DEFAULT, + 2*sizeof(float) + ); + + + memset(&viewport, 0, sizeof(viewport)); + if(dst_area){ + viewport.scale[0] = dst_area->x1 - dst_area->x0; + viewport.scale[1] = dst_area->y1 - dst_area->y0; + viewport.translate[0] = dst_area->x0; + viewport.translate[1] = dst_area->y0; + } else { + viewport.scale[0] = dst->width; + viewport.scale[1] = dst->height; + } + viewport.scale[2] = 1; + + float *ptr = pipe_buffer_map(filter->pipe, surface_size, + PIPE_TRANSFER_WRITE | PIPE_TRANSFER_DISCARD_RANGE, + &buf_transfer); + + ptr[0] = 0.5f/viewport.scale[0]; + ptr[1] = 0.5f/viewport.scale[1]; + + pipe_buffer_unmap(filter->pipe, buf_transfer); + + memset(&fb_state, 0, sizeof(fb_state)); + fb_state.width = dst->width; + fb_state.height = dst->height; + fb_state.nr_cbufs = 1; + fb_state.cbufs[0] = dst; + + filter->pipe->set_scissor_states(filter->pipe, 0, 1, &scissor); + filter->pipe->clear_render_target(filter->pipe, dst, &clear_color, + 0, 0, dst->width, dst->height, false); + pipe_set_constant_buffer(filter->pipe, PIPE_SHADER_FRAGMENT, 0, surface_size); + filter->pipe->bind_rasterizer_state(filter->pipe, filter->rs_state); + filter->pipe->bind_blend_state(filter->pipe, filter->blend); + filter->pipe->bind_sampler_states(filter->pipe, PIPE_SHADER_FRAGMENT, + 0, 1, &filter->sampler); + filter->pipe->set_sampler_views(filter->pipe, PIPE_SHADER_FRAGMENT, + 0, 1, &src); + filter->pipe->bind_vs_state(filter->pipe, filter->vs); + filter->pipe->bind_fs_state(filter->pipe, filter->fs); + filter->pipe->set_framebuffer_state(filter->pipe, &fb_state); + filter->pipe->set_viewport_states(filter->pipe, 0, 1, &viewport); + filter->pipe->set_vertex_buffers(filter->pipe, 0, 1, &filter->quad); + filter->pipe->bind_vertex_elements_state(filter->pipe, filter->ves); + + util_draw_arrays(filter->pipe, PIPE_PRIM_QUADS, 0, 4); +} diff --git a/lib/mesa/src/gallium/auxiliary/vl/vl_bicubic_filter.h b/lib/mesa/src/gallium/auxiliary/vl/vl_bicubic_filter.h new file mode 100644 index 000000000..e5bef474e --- /dev/null +++ b/lib/mesa/src/gallium/auxiliary/vl/vl_bicubic_filter.h @@ -0,0 +1,63 @@ +/************************************************************************** + * + * Copyright 2016 Nayan Deshmukh. + * 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 VMWARE 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. + * + **************************************************************************/ + +/* implementation of bicubic interpolation filters */ + +#ifndef vl_bicubic_filter_h +#define vl_bicubic_filter_h + +#include "pipe/p_state.h" + +struct vl_bicubic_filter +{ + struct pipe_context *pipe; + struct pipe_vertex_buffer quad; + + void *rs_state; + void *blend; + void *sampler; + void *ves; + void *vs, *fs; +}; + +bool +vl_bicubic_filter_init(struct vl_bicubic_filter *filter, struct pipe_context *pipe, + unsigned width, unsigned height); + +void +vl_bicubic_filter_cleanup(struct vl_bicubic_filter *filter); + + +void +vl_bicubic_filter_render(struct vl_bicubic_filter *filter, + struct pipe_sampler_view *src, + struct pipe_surface *dst, + struct u_rect *dst_area, + struct u_rect *dst_clip); + + +#endif /* vl_bicubic_filter_h */ diff --git a/lib/mesa/src/gallium/auxiliary/vl/vl_compositor.c b/lib/mesa/src/gallium/auxiliary/vl/vl_compositor.c index 77688f0f9..03a0a6453 100644 --- a/lib/mesa/src/gallium/auxiliary/vl/vl_compositor.c +++ b/lib/mesa/src/gallium/auxiliary/vl/vl_compositor.c @@ -62,7 +62,7 @@ create_vert_shader(struct vl_compositor *c) struct ureg_dst o_vpos, o_vtex, o_color; struct ureg_dst o_vtop, o_vbottom; - shader = ureg_create(TGSI_PROCESSOR_VERTEX); + shader = ureg_create(PIPE_SHADER_VERTEX); if (!shader) return false; @@ -125,78 +125,25 @@ create_vert_shader(struct vl_compositor *c) return ureg_create_shader_and_destroy(shader, c->pipe); } -static void * -create_frag_shader_video_buffer(struct vl_compositor *c) -{ - struct ureg_program *shader; - struct ureg_src tc; - struct ureg_src csc[3]; - struct ureg_src sampler[3]; - struct ureg_dst texel; - struct ureg_dst fragment; - unsigned i; - - shader = ureg_create(TGSI_PROCESSOR_FRAGMENT); - if (!shader) - return false; - - tc = ureg_DECL_fs_input(shader, TGSI_SEMANTIC_GENERIC, VS_O_VTEX, 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); - - /* - * 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_MOV(shader, ureg_writemask(texel, TGSI_WRITEMASK_W), ureg_imm1f(shader, 1.0f)); - - for (i = 0; i < 3; ++i) - ureg_DP4(shader, ureg_writemask(fragment, TGSI_WRITEMASK_X << i), csc[i], ureg_src(texel)); - - ureg_MOV(shader, ureg_writemask(fragment, TGSI_WRITEMASK_W), ureg_imm1f(shader, 1.0f)); - - ureg_release_temporary(shader, texel); - ureg_END(shader); - - return ureg_create_shader_and_destroy(shader, c->pipe); -} - -static void * -create_frag_shader_weave(struct vl_compositor *c) +static void +create_frag_shader_weave(struct ureg_program *shader, struct ureg_dst fragment) { - struct ureg_program *shader; 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_texel[2]; - struct ureg_dst o_fragment; unsigned i, j; - shader = ureg_create(TGSI_PROCESSOR_FRAGMENT); - if (!shader) - return false; - 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); - for (i = 0; i < 3; ++i) { - csc[i] = ureg_DECL_constant(shader, i); + for (i = 0; i < 3; ++i) sampler[i] = ureg_DECL_sampler(shader, i); - } for (i = 0; i < 2; ++i) { t_tc[i] = ureg_DECL_temporary(shader); t_texel[i] = ureg_DECL_temporary(shader); } - o_fragment = ureg_DECL_output(shader, TGSI_SEMANTIC_COLOR, 0); /* calculate the texture offsets * t_tc.x = i_tc.x @@ -239,23 +186,135 @@ create_frag_shader_weave(struct vl_compositor *c) ureg_src(t_tc[0]), ureg_negate(i_tc[0])); ureg_MUL(shader, ureg_writemask(t_tc[0], TGSI_WRITEMASK_YZ), ureg_abs(ureg_src(t_tc[0])), ureg_imm1f(shader, 2.0f)); - ureg_LRP(shader, t_texel[0], ureg_swizzle(ureg_src(t_tc[0]), + ureg_LRP(shader, fragment, ureg_swizzle(ureg_src(t_tc[0]), TGSI_SWIZZLE_Y, TGSI_SWIZZLE_Z, TGSI_SWIZZLE_Z, TGSI_SWIZZLE_Z), ureg_src(t_texel[0]), ureg_src(t_texel[1])); - /* and finally do colour space transformation + for (i = 0; i < 2; ++i) { + ureg_release_temporary(shader, t_texel[i]); + ureg_release_temporary(shader, t_tc[i]); + } +} + +static void +create_frag_shader_csc(struct ureg_program *shader, struct ureg_dst texel, + struct ureg_dst fragment) +{ + struct ureg_src csc[3]; + struct ureg_src lumakey; + struct ureg_dst temp[2]; + unsigned i; + + for (i = 0; i < 3; ++i) + csc[i] = ureg_DECL_constant(shader, i); + + lumakey = ureg_DECL_constant(shader, 3); + + for (i = 0; i < 2; ++i) + temp[i] = ureg_DECL_temporary(shader); + + ureg_MOV(shader, ureg_writemask(texel, TGSI_WRITEMASK_W), + ureg_imm1f(shader, 1.0f)); + + for (i = 0; i < 3; ++i) + ureg_DP4(shader, ureg_writemask(fragment, TGSI_WRITEMASK_X << i), csc[i], + ureg_src(texel)); + + ureg_MOV(shader, ureg_writemask(temp[0], TGSI_WRITEMASK_W), + ureg_scalar(ureg_src(texel), TGSI_SWIZZLE_Z)); + ureg_SLE(shader, ureg_writemask(temp[1],TGSI_WRITEMASK_W), + ureg_src(temp[0]), ureg_scalar(lumakey, TGSI_SWIZZLE_X)); + ureg_SGT(shader, ureg_writemask(temp[0],TGSI_WRITEMASK_W), + ureg_src(temp[0]), ureg_scalar(lumakey, TGSI_SWIZZLE_Y)); + ureg_MAX(shader, ureg_writemask(fragment, TGSI_WRITEMASK_W), + ureg_src(temp[0]), ureg_src(temp[1])); + + for (i = 0; i < 2; ++i) + ureg_release_temporary(shader, temp[i]); +} + +static void * +create_frag_shader_video_buffer(struct vl_compositor *c) +{ + struct ureg_program *shader; + struct ureg_src tc; + struct ureg_src sampler[3]; + struct ureg_dst texel; + struct ureg_dst fragment; + unsigned i; + + shader = ureg_create(PIPE_SHADER_FRAGMENT); + if (!shader) + return false; + + tc = ureg_DECL_fs_input(shader, TGSI_SEMANTIC_GENERIC, VS_O_VTEX, TGSI_INTERPOLATE_LINEAR); + for (i = 0; i < 3; ++i) + sampler[i] = ureg_DECL_sampler(shader, i); + + texel = ureg_DECL_temporary(shader); + fragment = ureg_DECL_output(shader, TGSI_SEMANTIC_COLOR, 0); + + /* + * texel.xyz = tex(tc, sampler[i]) * fragment = csc * texel */ - ureg_MOV(shader, ureg_writemask(t_texel[0], TGSI_WRITEMASK_W), ureg_imm1f(shader, 1.0f)); for (i = 0; i < 3; ++i) - ureg_DP4(shader, ureg_writemask(o_fragment, TGSI_WRITEMASK_X << i), csc[i], ureg_src(t_texel[0])); + ureg_TEX(shader, ureg_writemask(texel, TGSI_WRITEMASK_X << i), TGSI_TEXTURE_2D_ARRAY, tc, sampler[i]); - ureg_MOV(shader, ureg_writemask(o_fragment, TGSI_WRITEMASK_W), ureg_imm1f(shader, 1.0f)); + create_frag_shader_csc(shader, texel, fragment); - for (i = 0; i < 2; ++i) { - ureg_release_temporary(shader, t_texel[i]); - ureg_release_temporary(shader, t_tc[i]); - } + ureg_release_temporary(shader, texel); + ureg_END(shader); + + return ureg_create_shader_and_destroy(shader, c->pipe); +} + +static void * +create_frag_shader_weave_rgb(struct vl_compositor *c) +{ + struct ureg_program *shader; + struct ureg_dst texel, fragment; + + shader = ureg_create(PIPE_SHADER_FRAGMENT); + if (!shader) + return false; + + texel = ureg_DECL_temporary(shader); + fragment = ureg_DECL_output(shader, TGSI_SEMANTIC_COLOR, 0); + + create_frag_shader_weave(shader, texel); + create_frag_shader_csc(shader, texel, fragment); + + ureg_release_temporary(shader, texel); + + ureg_END(shader); + + return ureg_create_shader_and_destroy(shader, c->pipe); +} + +static void * +create_frag_shader_weave_yuv(struct vl_compositor *c, bool y) +{ + struct ureg_program *shader; + struct ureg_dst texel, fragment; + + shader = ureg_create(PIPE_SHADER_FRAGMENT); + if (!shader) + return false; + + texel = ureg_DECL_temporary(shader); + fragment = ureg_DECL_output(shader, TGSI_SEMANTIC_COLOR, 0); + + create_frag_shader_weave(shader, texel); + + if (y) + ureg_MOV(shader, ureg_writemask(fragment, TGSI_WRITEMASK_X), ureg_src(texel)); + else + ureg_MOV(shader, ureg_writemask(fragment, TGSI_WRITEMASK_XY), + ureg_swizzle(ureg_src(texel), TGSI_SWIZZLE_Y, + TGSI_SWIZZLE_Z, TGSI_SWIZZLE_W, TGSI_SWIZZLE_W)); + + ureg_release_temporary(shader, texel); ureg_END(shader); @@ -274,7 +333,7 @@ create_frag_shader_palette(struct vl_compositor *c, bool include_cc) struct ureg_dst fragment; unsigned i; - shader = ureg_create(TGSI_PROCESSOR_FRAGMENT); + shader = ureg_create(PIPE_SHADER_FRAGMENT); if (!shader) return false; @@ -318,7 +377,7 @@ create_frag_shader_rgba(struct vl_compositor *c) struct ureg_src tc, color, sampler; struct ureg_dst texel, fragment; - shader = ureg_create(TGSI_PROCESSOR_FRAGMENT); + shader = ureg_create(PIPE_SHADER_FRAGMENT); if (!shader) return false; @@ -355,12 +414,19 @@ init_shaders(struct vl_compositor *c) return false; } - c->fs_weave = create_frag_shader_weave(c); - if (!c->fs_weave) { + c->fs_weave_rgb = create_frag_shader_weave_rgb(c); + if (!c->fs_weave_rgb) { debug_printf("Unable to create YCbCr-to-RGB weave fragment shader.\n"); return false; } + c->fs_weave_yuv.y = create_frag_shader_weave_yuv(c, true); + c->fs_weave_yuv.uv = create_frag_shader_weave_yuv(c, false); + if (!c->fs_weave_yuv.y || !c->fs_weave_yuv.uv) { + debug_printf("Unable to create YCbCr i-to-YCbCr p weave fragment shader.\n"); + return false; + } + c->fs_palette.yuv = create_frag_shader_palette(c, true); if (!c->fs_palette.yuv) { debug_printf("Unable to create YUV-Palette-to-RGB fragment shader.\n"); @@ -388,7 +454,9 @@ static void cleanup_shaders(struct vl_compositor *c) c->pipe->delete_vs_state(c->pipe, c->vs); c->pipe->delete_fs_state(c->pipe, c->fs_video_buffer); - c->pipe->delete_fs_state(c->pipe, c->fs_weave); + c->pipe->delete_fs_state(c->pipe, c->fs_weave_rgb); + c->pipe->delete_fs_state(c->pipe, c->fs_weave_yuv.y); + c->pipe->delete_fs_state(c->pipe, c->fs_weave_yuv.uv); c->pipe->delete_fs_state(c->pipe, c->fs_palette.yuv); c->pipe->delete_fs_state(c->pipe, c->fs_palette.rgb); c->pipe->delete_fs_state(c->pipe, c->fs_rgba); @@ -852,20 +920,23 @@ vl_compositor_cleanup(struct vl_compositor *c) } void -vl_compositor_set_csc_matrix(struct vl_compositor_state *s, vl_csc_matrix const *matrix) +vl_compositor_set_csc_matrix(struct vl_compositor_state *s, + vl_csc_matrix const *matrix, + float luma_min, float luma_max) { struct pipe_transfer *buf_transfer; assert(s); - memcpy - ( - pipe_buffer_map(s->pipe, s->csc_matrix, - PIPE_TRANSFER_WRITE | PIPE_TRANSFER_DISCARD_RANGE, - &buf_transfer), - matrix, - sizeof(vl_csc_matrix) - ); + float *ptr = pipe_buffer_map(s->pipe, s->csc_matrix, + PIPE_TRANSFER_WRITE | PIPE_TRANSFER_DISCARD_RANGE, + &buf_transfer); + + memcpy(ptr, matrix, sizeof(vl_csc_matrix)); + + ptr += sizeof(vl_csc_matrix)/sizeof(float); + ptr[0] = luma_min; + ptr[1] = luma_max; pipe_buffer_unmap(s->pipe, buf_transfer); } @@ -945,7 +1016,7 @@ vl_compositor_set_buffer_layer(struct vl_compositor_state *s, float half_a_line = 0.5f / s->layers[layer].zw.y; switch(deinterlace) { case VL_COMPOSITOR_WEAVE: - s->layers[layer].fs = c->fs_weave; + s->layers[layer].fs = c->fs_weave_rgb; break; case VL_COMPOSITOR_BOB_TOP: @@ -1040,6 +1111,36 @@ vl_compositor_set_layer_rotation(struct vl_compositor_state *s, } void +vl_compositor_set_yuv_layer(struct vl_compositor_state *s, + struct vl_compositor *c, + unsigned layer, + struct pipe_video_buffer *buffer, + struct u_rect *src_rect, + struct u_rect *dst_rect, + bool y) +{ + struct pipe_sampler_view **sampler_views; + unsigned i; + + assert(s && c && buffer); + + assert(layer < VL_COMPOSITOR_MAX_LAYERS); + + s->used_layers |= 1 << layer; + sampler_views = buffer->get_sampler_view_components(buffer); + for (i = 0; i < 3; ++i) { + s->layers[layer].samplers[i] = c->sampler_linear; + pipe_sampler_view_reference(&s->layers[layer].sampler_views[i], sampler_views[i]); + } + + calc_src_and_dst(&s->layers[layer], buffer->width, buffer->height, + src_rect ? *src_rect : default_rect(&s->layers[layer]), + dst_rect ? *dst_rect : default_rect(&s->layers[layer])); + + s->layers[layer].fs = (y) ? c->fs_weave_yuv.y : c->fs_weave_yuv.uv; +} + +void vl_compositor_render(struct vl_compositor_state *s, struct vl_compositor *c, struct pipe_surface *dst_surface, @@ -1067,7 +1168,7 @@ vl_compositor_render(struct vl_compositor_state *s, (dirty_area->x0 < dirty_area->x1 || dirty_area->y0 < dirty_area->y1)) { c->pipe->clear_render_target(c->pipe, dst_surface, &s->clear_color, - 0, 0, dst_surface->width, dst_surface->height); + 0, 0, dst_surface->width, dst_surface->height, false); dirty_area->x0 = dirty_area->y0 = MAX_DIRTY; dirty_area->x1 = dirty_area->y1 = MIN_DIRTY; } @@ -1142,13 +1243,13 @@ vl_compositor_init_state(struct vl_compositor_state *s, struct pipe_context *pip pipe->screen, PIPE_BIND_CONSTANT_BUFFER, PIPE_USAGE_DEFAULT, - sizeof(csc_matrix) + sizeof(csc_matrix) + 2*sizeof(float) ); vl_compositor_clear_layers(s); vl_csc_get_matrix(VL_CSC_COLOR_STANDARD_IDENTITY, NULL, true, &csc_matrix); - vl_compositor_set_csc_matrix(s, (const vl_csc_matrix *)&csc_matrix); + vl_compositor_set_csc_matrix(s, (const vl_csc_matrix *)&csc_matrix, 1.0f, 0.0f); return true; } diff --git a/lib/mesa/src/gallium/auxiliary/vl/vl_compositor.h b/lib/mesa/src/gallium/auxiliary/vl/vl_compositor.h index 934b634b3..ceab5e004 100644 --- a/lib/mesa/src/gallium/auxiliary/vl/vl_compositor.h +++ b/lib/mesa/src/gallium/auxiliary/vl/vl_compositor.h @@ -113,10 +113,15 @@ struct vl_compositor void *vs; void *fs_video_buffer; - void *fs_weave; + void *fs_weave_rgb; void *fs_rgba; struct { + void *y; + void *uv; + } fs_weave_yuv; + + struct { void *rgb; void *yuv; } fs_palette; @@ -138,7 +143,9 @@ vl_compositor_init_state(struct vl_compositor_state *state, struct pipe_context * set yuv -> rgba conversion matrix */ void -vl_compositor_set_csc_matrix(struct vl_compositor_state *settings, const vl_csc_matrix *matrix); +vl_compositor_set_csc_matrix(struct vl_compositor_state *settings, + const vl_csc_matrix *matrix, + float luma_min, float luma_max); /** * reset dirty area, so it's cleared with the clear colour @@ -234,6 +241,18 @@ vl_compositor_set_layer_rotation(struct vl_compositor_state *state, unsigned layer, enum vl_compositor_rotation rotate); +/** + * set a layer of y or uv to render + */ +void +vl_compositor_set_yuv_layer(struct vl_compositor_state *s, + struct vl_compositor *c, + unsigned layer, + struct pipe_video_buffer *buffer, + struct u_rect *src_rect, + struct u_rect *dst_rect, + bool y); + /*@}*/ /** diff --git a/lib/mesa/src/gallium/auxiliary/vl/vl_deint_filter.c b/lib/mesa/src/gallium/auxiliary/vl/vl_deint_filter.c index 9e782e531..3ca3b4954 100644 --- a/lib/mesa/src/gallium/auxiliary/vl/vl_deint_filter.c +++ b/lib/mesa/src/gallium/auxiliary/vl/vl_deint_filter.c @@ -67,7 +67,7 @@ create_vert_shader(struct vl_deint_filter *filter) struct ureg_src i_vpos; struct ureg_dst o_vpos, o_vtex; - shader = ureg_create(TGSI_PROCESSOR_VERTEX); + shader = ureg_create(PIPE_SHADER_VERTEX); if (!shader) return NULL; @@ -92,7 +92,7 @@ create_copy_frag_shader(struct vl_deint_filter *filter, unsigned field) struct ureg_dst o_fragment; struct ureg_dst t_tex; - shader = ureg_create(TGSI_PROCESSOR_FRAGMENT); + shader = ureg_create(PIPE_SHADER_FRAGMENT); if (!shader) { return NULL; } @@ -136,7 +136,7 @@ create_deint_frag_shader(struct vl_deint_filter *filter, unsigned field, struct ureg_dst t_a, t_b; struct ureg_dst t_weave, t_linear; - shader = ureg_create(TGSI_PROCESSOR_FRAGMENT); + shader = ureg_create(PIPE_SHADER_FRAGMENT); if (!shader) { return NULL; } @@ -447,7 +447,8 @@ vl_deint_filter_render(struct vl_deint_filter *filter, struct pipe_sampler_view *sampler_views[4]; struct pipe_surface **dst_surfaces; const unsigned *plane_order; - int i, j; + int i; + unsigned j; assert(filter && prevprev && prev && cur && next && field <= 1); diff --git a/lib/mesa/src/gallium/auxiliary/vl/vl_idct.c b/lib/mesa/src/gallium/auxiliary/vl/vl_idct.c index 948a5a403..3e6f58124 100644 --- a/lib/mesa/src/gallium/auxiliary/vl/vl_idct.c +++ b/lib/mesa/src/gallium/auxiliary/vl/vl_idct.c @@ -148,7 +148,7 @@ create_mismatch_vert_shader(struct vl_idct *idct) struct ureg_dst t_tex; struct ureg_dst o_vpos, o_addr[2]; - shader = ureg_create(TGSI_PROCESSOR_VERTEX); + shader = ureg_create(PIPE_SHADER_VERTEX); if (!shader) return NULL; @@ -200,7 +200,7 @@ create_mismatch_frag_shader(struct vl_idct *idct) unsigned i; - shader = ureg_create(TGSI_PROCESSOR_FRAGMENT); + shader = ureg_create(PIPE_SHADER_FRAGMENT); if (!shader) return NULL; @@ -264,7 +264,7 @@ create_stage1_vert_shader(struct vl_idct *idct) struct ureg_dst t_tex, t_start; struct ureg_dst o_vpos, o_l_addr[2], o_r_addr[2]; - shader = ureg_create(TGSI_PROCESSOR_VERTEX); + shader = ureg_create(PIPE_SHADER_VERTEX); if (!shader) return NULL; @@ -321,15 +321,13 @@ static void * create_stage1_frag_shader(struct vl_idct *idct) { struct ureg_program *shader; - struct ureg_src l_addr[2], r_addr[2]; - struct ureg_dst l[4][2], r[2]; struct ureg_dst *fragment; + unsigned i; + int j; - int i, j; - - shader = ureg_create(TGSI_PROCESSOR_FRAGMENT); + shader = ureg_create(PIPE_SHADER_FRAGMENT); if (!shader) return NULL; diff --git a/lib/mesa/src/gallium/auxiliary/vl/vl_matrix_filter.c b/lib/mesa/src/gallium/auxiliary/vl/vl_matrix_filter.c index 52ce45401..e331cb758 100644 --- a/lib/mesa/src/gallium/auxiliary/vl/vl_matrix_filter.c +++ b/lib/mesa/src/gallium/auxiliary/vl/vl_matrix_filter.c @@ -52,7 +52,7 @@ create_vert_shader(struct vl_matrix_filter *filter) struct ureg_src i_vpos; struct ureg_dst o_vpos, o_vtex; - shader = ureg_create(TGSI_PROCESSOR_VERTEX); + shader = ureg_create(PIPE_SHADER_VERTEX); if (!shader) return NULL; @@ -85,9 +85,9 @@ create_frag_shader(struct vl_matrix_filter *filter, unsigned num_offsets, struct ureg_dst t_sum; struct ureg_dst o_fragment; bool first; - int i; + unsigned i; - shader = ureg_create(TGSI_PROCESSOR_FRAGMENT); + shader = ureg_create(PIPE_SHADER_FRAGMENT); if (!shader) { FREE(t_array); return NULL; diff --git a/lib/mesa/src/gallium/auxiliary/vl/vl_mc.c b/lib/mesa/src/gallium/auxiliary/vl/vl_mc.c index eb703a904..a202fac54 100644 --- a/lib/mesa/src/gallium/auxiliary/vl/vl_mc.c +++ b/lib/mesa/src/gallium/auxiliary/vl/vl_mc.c @@ -112,7 +112,7 @@ create_ref_vert_shader(struct vl_mc *r) struct ureg_dst o_vmv[2]; unsigned i; - shader = ureg_create(TGSI_PROCESSOR_VERTEX); + shader = ureg_create(PIPE_SHADER_VERTEX); if (!shader) return NULL; @@ -169,7 +169,7 @@ create_ref_frag_shader(struct vl_mc *r) struct ureg_dst fragment; unsigned label; - shader = ureg_create(TGSI_PROCESSOR_FRAGMENT); + shader = ureg_create(PIPE_SHADER_FRAGMENT); if (!shader) return NULL; @@ -241,7 +241,7 @@ create_ycbcr_vert_shader(struct vl_mc *r, vl_mc_ycbcr_vert_shader vs_callback, v unsigned label; - shader = ureg_create(TGSI_PROCESSOR_VERTEX); + shader = ureg_create(PIPE_SHADER_VERTEX); if (!shader) return NULL; @@ -320,7 +320,7 @@ create_ycbcr_frag_shader(struct vl_mc *r, float scale, bool invert, struct ureg_dst fragment; unsigned label; - shader = ureg_create(TGSI_PROCESSOR_FRAGMENT); + shader = ureg_create(PIPE_SHADER_FRAGMENT); if (!shader) return NULL; diff --git a/lib/mesa/src/gallium/auxiliary/vl/vl_median_filter.c b/lib/mesa/src/gallium/auxiliary/vl/vl_median_filter.c index aa9a6b264..f7477b757 100644 --- a/lib/mesa/src/gallium/auxiliary/vl/vl_median_filter.c +++ b/lib/mesa/src/gallium/auxiliary/vl/vl_median_filter.c @@ -50,7 +50,7 @@ create_vert_shader(struct vl_median_filter *filter) struct ureg_src i_vpos; struct ureg_dst o_vpos, o_vtex; - shader = ureg_create(TGSI_PROCESSOR_VERTEX); + shader = ureg_create(PIPE_SHADER_VERTEX); if (!shader) return NULL; @@ -84,7 +84,7 @@ create_frag_shader(struct vl_median_filter *filter, struct ureg_dst *t_array = MALLOC(sizeof(struct ureg_dst) * num_offsets); struct ureg_dst o_fragment; const unsigned median = num_offsets >> 1; - int i, j; + unsigned i, j; assert(num_offsets & 1); /* we need an odd number of offsets */ if (!(num_offsets & 1)) { /* yeah, we REALLY need an odd number of offsets!!! */ @@ -93,13 +93,13 @@ create_frag_shader(struct vl_median_filter *filter, } if (num_offsets > screen->get_shader_param( - screen, TGSI_PROCESSOR_FRAGMENT, PIPE_SHADER_CAP_MAX_TEMPS)) { + screen, PIPE_SHADER_FRAGMENT, PIPE_SHADER_CAP_MAX_TEMPS)) { FREE(t_array); return NULL; } - shader = ureg_create(TGSI_PROCESSOR_FRAGMENT); + shader = ureg_create(PIPE_SHADER_FRAGMENT); if (!shader) { FREE(t_array); return NULL; @@ -158,7 +158,8 @@ static void generate_offsets(enum vl_median_filter_shape shape, unsigned size, struct vertex2f **offsets, unsigned *num_offsets) { - int i = 0, half_size; + unsigned i = 0; + int half_size; struct vertex2f v; assert(offsets && num_offsets); diff --git a/lib/mesa/src/gallium/auxiliary/vl/vl_mpeg12_bitstream.c b/lib/mesa/src/gallium/auxiliary/vl/vl_mpeg12_bitstream.c index 52ce6c416..0e99d830d 100644 --- a/lib/mesa/src/gallium/auxiliary/vl/vl_mpeg12_bitstream.c +++ b/lib/mesa/src/gallium/auxiliary/vl/vl_mpeg12_bitstream.c @@ -583,12 +583,12 @@ init_dct_coeff_table(struct dct_coeff *dst, const struct dct_coeff_compressed *s break; } - for(i=0; i<(1 << (17 - coeff.length)); ++i) + for(i = 0; i < (1u << (17 - coeff.length)); ++i) dst[src->bitcode << 1 | i] = coeff; if (has_sign) { coeff.level = -coeff.level; - for(; i<(1 << (18 - coeff.length)); ++i) + for(; i < (1u << (18 - coeff.length)); ++i) dst[src->bitcode << 1 | i] = coeff; } } @@ -597,18 +597,18 @@ init_dct_coeff_table(struct dct_coeff *dst, const struct dct_coeff_compressed *s static inline void init_tables() { - vl_vlc_init_table(tbl_B1, Elements(tbl_B1), macroblock_address_increment, Elements(macroblock_address_increment)); - vl_vlc_init_table(tbl_B2, Elements(tbl_B2), macroblock_type_i, Elements(macroblock_type_i)); - vl_vlc_init_table(tbl_B3, Elements(tbl_B3), macroblock_type_p, Elements(macroblock_type_p)); - vl_vlc_init_table(tbl_B4, Elements(tbl_B4), macroblock_type_b, Elements(macroblock_type_b)); - vl_vlc_init_table(tbl_B9, Elements(tbl_B9), coded_block_pattern, Elements(coded_block_pattern)); - vl_vlc_init_table(tbl_B10, Elements(tbl_B10), motion_code, Elements(motion_code)); - vl_vlc_init_table(tbl_B11, Elements(tbl_B11), dmvector, Elements(dmvector)); - vl_vlc_init_table(tbl_B12, Elements(tbl_B12), dct_dc_size_luminance, Elements(dct_dc_size_luminance)); - vl_vlc_init_table(tbl_B13, Elements(tbl_B13), dct_dc_size_chrominance, Elements(dct_dc_size_chrominance)); - init_dct_coeff_table(tbl_B14_DC, dct_coeff_tbl_zero, Elements(dct_coeff_tbl_zero), true); - init_dct_coeff_table(tbl_B14_AC, dct_coeff_tbl_zero, Elements(dct_coeff_tbl_zero), false); - init_dct_coeff_table(tbl_B15, dct_coeff_tbl_one, Elements(dct_coeff_tbl_one), false); + vl_vlc_init_table(tbl_B1, ARRAY_SIZE(tbl_B1), macroblock_address_increment, ARRAY_SIZE(macroblock_address_increment)); + vl_vlc_init_table(tbl_B2, ARRAY_SIZE(tbl_B2), macroblock_type_i, ARRAY_SIZE(macroblock_type_i)); + vl_vlc_init_table(tbl_B3, ARRAY_SIZE(tbl_B3), macroblock_type_p, ARRAY_SIZE(macroblock_type_p)); + vl_vlc_init_table(tbl_B4, ARRAY_SIZE(tbl_B4), macroblock_type_b, ARRAY_SIZE(macroblock_type_b)); + vl_vlc_init_table(tbl_B9, ARRAY_SIZE(tbl_B9), coded_block_pattern, ARRAY_SIZE(coded_block_pattern)); + vl_vlc_init_table(tbl_B10, ARRAY_SIZE(tbl_B10), motion_code, ARRAY_SIZE(motion_code)); + vl_vlc_init_table(tbl_B11, ARRAY_SIZE(tbl_B11), dmvector, ARRAY_SIZE(dmvector)); + vl_vlc_init_table(tbl_B12, ARRAY_SIZE(tbl_B12), dct_dc_size_luminance, ARRAY_SIZE(dct_dc_size_luminance)); + vl_vlc_init_table(tbl_B13, ARRAY_SIZE(tbl_B13), dct_dc_size_chrominance, ARRAY_SIZE(dct_dc_size_chrominance)); + init_dct_coeff_table(tbl_B14_DC, dct_coeff_tbl_zero, ARRAY_SIZE(dct_coeff_tbl_zero), true); + init_dct_coeff_table(tbl_B14_AC, dct_coeff_tbl_zero, ARRAY_SIZE(dct_coeff_tbl_zero), false); + init_dct_coeff_table(tbl_B15, dct_coeff_tbl_one, ARRAY_SIZE(dct_coeff_tbl_one), false); } static inline int diff --git a/lib/mesa/src/gallium/auxiliary/vl/vl_mpeg12_decoder.c b/lib/mesa/src/gallium/auxiliary/vl/vl_mpeg12_decoder.c index b5c70451c..db62b44f5 100644 --- a/lib/mesa/src/gallium/auxiliary/vl/vl_mpeg12_decoder.c +++ b/lib/mesa/src/gallium/auxiliary/vl/vl_mpeg12_decoder.c @@ -189,7 +189,7 @@ init_zscan_buffer(struct vl_mpeg12_decoder *dec, struct vl_mpeg12_buffer *buffer memset(&sv_tmpl, 0, sizeof(sv_tmpl)); u_sampler_view_default_template(&sv_tmpl, res, res->format); - sv_tmpl.swizzle_r = sv_tmpl.swizzle_g = sv_tmpl.swizzle_b = sv_tmpl.swizzle_a = PIPE_SWIZZLE_RED; + sv_tmpl.swizzle_r = sv_tmpl.swizzle_g = sv_tmpl.swizzle_b = sv_tmpl.swizzle_a = PIPE_SWIZZLE_X; buffer->zscan_source = dec->context->create_sampler_view(dec->context, res, &sv_tmpl); pipe_resource_reference(&res, NULL); if (!buffer->zscan_source) diff --git a/lib/mesa/src/gallium/auxiliary/vl/vl_rbsp.h b/lib/mesa/src/gallium/auxiliary/vl/vl_rbsp.h index 7867238c4..4d90c2de0 100644 --- a/lib/mesa/src/gallium/auxiliary/vl/vl_rbsp.h +++ b/lib/mesa/src/gallium/auxiliary/vl/vl_rbsp.h @@ -50,22 +50,34 @@ struct vl_rbsp { */ static inline void vl_rbsp_init(struct vl_rbsp *rbsp, struct vl_vlc *nal, unsigned num_bits) { - unsigned bits_left = vl_vlc_bits_left(nal); + unsigned valid, bits_left = vl_vlc_bits_left(nal); + int i; /* copy the position */ rbsp->nal = *nal; - rbsp->escaped = 0; - /* search for the end of the NAL unit */ while (vl_vlc_search_byte(nal, num_bits, 0x00)) { if (vl_vlc_peekbits(nal, 24) == 0x000001 || vl_vlc_peekbits(nal, 32) == 0x00000001) { vl_vlc_limit(&rbsp->nal, bits_left - vl_vlc_bits_left(nal)); - return; + break; } vl_vlc_eatbits(nal, 8); } + + valid = vl_vlc_valid_bits(&rbsp->nal); + /* search for the emulation prevention three byte */ + for (i = 24; i <= valid; i += 8) { + if ((vl_vlc_peekbits(&rbsp->nal, i) & 0xffffff) == 0x3) { + vl_vlc_removebits(&rbsp->nal, i - 8, 8); + i += 8; + } + } + + valid = vl_vlc_valid_bits(&rbsp->nal); + + rbsp->escaped = (valid >= 16) ? 16 : ((valid >= 8) ? 8 : 0); } /** diff --git a/lib/mesa/src/gallium/auxiliary/vl/vl_video_buffer.c b/lib/mesa/src/gallium/auxiliary/vl/vl_video_buffer.c index 462fdcb08..fdc9598f8 100644 --- a/lib/mesa/src/gallium/auxiliary/vl/vl_video_buffer.c +++ b/lib/mesa/src/gallium/auxiliary/vl/vl_video_buffer.c @@ -250,7 +250,7 @@ vl_video_buffer_template(struct pipe_resource *templ, templ->height0 = tmpl->height; templ->depth0 = depth; templ->array_size = array_size; - templ->bind = PIPE_BIND_SAMPLER_VIEW | PIPE_BIND_RENDER_TARGET; + templ->bind = PIPE_BIND_SAMPLER_VIEW | PIPE_BIND_RENDER_TARGET | tmpl->bind; templ->usage = usage; vl_video_buffer_adjust_size(&templ->width0, &templ->height0, plane, @@ -297,7 +297,7 @@ vl_video_buffer_sampler_view_planes(struct pipe_video_buffer *buffer) u_sampler_view_default_template(&sv_templ, buf->resources[i], buf->resources[i]->format); if (util_format_get_nr_components(buf->resources[i]->format) == 1) - sv_templ.swizzle_r = sv_templ.swizzle_g = sv_templ.swizzle_b = sv_templ.swizzle_a = PIPE_SWIZZLE_RED; + sv_templ.swizzle_r = sv_templ.swizzle_g = sv_templ.swizzle_b = sv_templ.swizzle_a = PIPE_SWIZZLE_X; buf->sampler_view_planes[i] = pipe->create_sampler_view(pipe, buf->resources[i], &sv_templ); if (!buf->sampler_view_planes[i]) @@ -344,8 +344,8 @@ vl_video_buffer_sampler_view_components(struct pipe_video_buffer *buffer) memset(&sv_templ, 0, sizeof(sv_templ)); u_sampler_view_default_template(&sv_templ, res, sampler_format[plane_order[i]]); - sv_templ.swizzle_r = sv_templ.swizzle_g = sv_templ.swizzle_b = PIPE_SWIZZLE_RED + j; - sv_templ.swizzle_a = PIPE_SWIZZLE_ONE; + sv_templ.swizzle_r = sv_templ.swizzle_g = sv_templ.swizzle_b = PIPE_SWIZZLE_X + j; + sv_templ.swizzle_a = PIPE_SWIZZLE_1; buf->sampler_view_components[component] = pipe->create_sampler_view(pipe, res, &sv_templ); if (!buf->sampler_view_components[component]) goto error; diff --git a/lib/mesa/src/gallium/auxiliary/vl/vl_vlc.h b/lib/mesa/src/gallium/auxiliary/vl/vl_vlc.h index 7821b8be0..dd7b0918a 100644 --- a/lib/mesa/src/gallium/auxiliary/vl/vl_vlc.h +++ b/lib/mesa/src/gallium/auxiliary/vl/vl_vlc.h @@ -79,7 +79,7 @@ vl_vlc_init_table(struct vl_vlc_entry *dst, unsigned dst_size, const struct vl_v } for(; src_size > 0; --src_size, ++src) { - for(i=0; i<(1 << (bits - src->entry.length)); ++i) + for(i = 0; i < (1u << (bits - src->entry.length)); ++i) dst[src->bitcode >> (16 - bits) | i] = src->entry; } } @@ -293,7 +293,7 @@ vl_vlc_search_byte(struct vl_vlc *vlc, unsigned num_bits, uint8_t value) { /* make sure we are on a byte boundary */ assert((vl_vlc_valid_bits(vlc) % 8) == 0); - assert(num_bits == ~0 || (num_bits % 8) == 0); + assert(num_bits == ~0u || (num_bits % 8) == 0); /* deplete the bit buffer */ while (vl_vlc_valid_bits(vlc) > 0) { @@ -305,7 +305,7 @@ vl_vlc_search_byte(struct vl_vlc *vlc, unsigned num_bits, uint8_t value) vl_vlc_eatbits(vlc, 8); - if (num_bits != ~0) { + if (num_bits != ~0u) { num_bits -= 8; if (num_bits == 0) return FALSE; @@ -332,7 +332,7 @@ vl_vlc_search_byte(struct vl_vlc *vlc, unsigned num_bits, uint8_t value) } ++vlc->data; - if (num_bits != ~0) { + if (num_bits != ~0u) { num_bits -= 8; if (num_bits == 0) { vl_vlc_align_data_ptr(vlc); diff --git a/lib/mesa/src/gallium/auxiliary/vl/vl_winsys.h b/lib/mesa/src/gallium/auxiliary/vl/vl_winsys.h index 1af7653d6..26db9f263 100644 --- a/lib/mesa/src/gallium/auxiliary/vl/vl_winsys.h +++ b/lib/mesa/src/gallium/auxiliary/vl/vl_winsys.h @@ -69,4 +69,9 @@ vl_dri2_screen_create(Display *display, int screen); struct vl_screen * vl_drm_screen_create(int fd); +#if defined(HAVE_DRI3) +struct vl_screen * +vl_dri3_screen_create(Display *display, int screen); +#endif + #endif diff --git a/lib/mesa/src/gallium/auxiliary/vl/vl_winsys_dri.c b/lib/mesa/src/gallium/auxiliary/vl/vl_winsys_dri.c index 758f50d7c..9ecc216b9 100644 --- a/lib/mesa/src/gallium/auxiliary/vl/vl_winsys_dri.c +++ b/lib/mesa/src/gallium/auxiliary/vl/vl_winsys_dri.c @@ -248,7 +248,8 @@ vl_dri2_screen_texture_from_drawable(struct vl_screen *vscreen, void *drawable) template.flags = 0; tex = scrn->base.pscreen->resource_from_handle(scrn->base.pscreen, &template, - &dri2_handle); + &dri2_handle, + PIPE_HANDLE_USAGE_READ_WRITE); free(reply); return tex; @@ -426,13 +427,15 @@ vl_dri2_screen_create(Display *display, int screen) return &scrn->base; release_pipe: - if (scrn->base.dev) + if (scrn->base.dev) { pipe_loader_release(&scrn->base.dev, 1); - fd = -1; + fd = -1; + } free_authenticate: free(authenticate); close_fd: - close(fd); + if (fd != -1) + close(fd); free_connect: free(connect); free_query: diff --git a/lib/mesa/src/gallium/auxiliary/vl/vl_winsys_dri3.c b/lib/mesa/src/gallium/auxiliary/vl/vl_winsys_dri3.c new file mode 100644 index 000000000..29299289f --- /dev/null +++ b/lib/mesa/src/gallium/auxiliary/vl/vl_winsys_dri3.c @@ -0,0 +1,763 @@ +/************************************************************************** + * + * Copyright 2016 Advanced Micro Devices, Inc. + * 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 VMWARE 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 <fcntl.h> + +#include <X11/Xlib-xcb.h> +#include <X11/xshmfence.h> +#include <xcb/dri3.h> +#include <xcb/present.h> + +#include "loader.h" + +#include "pipe/p_screen.h" +#include "pipe/p_state.h" +#include "pipe-loader/pipe_loader.h" + +#include "util/u_memory.h" +#include "util/u_inlines.h" + +#include "vl/vl_compositor.h" +#include "vl/vl_winsys.h" + +#define BACK_BUFFER_NUM 3 + +struct vl_dri3_buffer +{ + struct pipe_resource *texture; + struct pipe_resource *linear_texture; + + uint32_t pixmap; + uint32_t sync_fence; + struct xshmfence *shm_fence; + + bool busy; + uint32_t width, height, pitch; +}; + +struct vl_dri3_screen +{ + struct vl_screen base; + xcb_connection_t *conn; + xcb_drawable_t drawable; + + uint32_t width, height, depth; + + xcb_present_event_t eid; + xcb_special_event_t *special_event; + + struct pipe_context *pipe; + + struct vl_dri3_buffer *back_buffers[BACK_BUFFER_NUM]; + int cur_back; + + struct u_rect dirty_areas[BACK_BUFFER_NUM]; + + struct vl_dri3_buffer *front_buffer; + bool is_pixmap; + + uint32_t send_msc_serial, recv_msc_serial; + uint64_t send_sbc, recv_sbc; + int64_t last_ust, ns_frame, last_msc, next_msc; + + bool flushed; + int is_different_gpu; +}; + +static void +dri3_free_front_buffer(struct vl_dri3_screen *scrn, + struct vl_dri3_buffer *buffer) +{ + xcb_sync_destroy_fence(scrn->conn, buffer->sync_fence); + xshmfence_unmap_shm(buffer->shm_fence); + pipe_resource_reference(&buffer->texture, NULL); + FREE(buffer); +} + +static void +dri3_free_back_buffer(struct vl_dri3_screen *scrn, + struct vl_dri3_buffer *buffer) +{ + xcb_free_pixmap(scrn->conn, buffer->pixmap); + xcb_sync_destroy_fence(scrn->conn, buffer->sync_fence); + xshmfence_unmap_shm(buffer->shm_fence); + pipe_resource_reference(&buffer->texture, NULL); + if (buffer->linear_texture) + pipe_resource_reference(&buffer->linear_texture, NULL); + FREE(buffer); +} + +static void +dri3_handle_stamps(struct vl_dri3_screen *scrn, uint64_t ust, uint64_t msc) +{ + int64_t ust_ns = ust * 1000; + + if (scrn->last_ust && (ust_ns > scrn->last_ust) && + scrn->last_msc && (msc > scrn->last_msc)) + scrn->ns_frame = (ust_ns - scrn->last_ust) / (msc - scrn->last_msc); + + scrn->last_ust = ust_ns; + scrn->last_msc = msc; +} + +static void +dri3_handle_present_event(struct vl_dri3_screen *scrn, + xcb_present_generic_event_t *ge) +{ + switch (ge->evtype) { + case XCB_PRESENT_CONFIGURE_NOTIFY: { + xcb_present_configure_notify_event_t *ce = (void *) ge; + scrn->width = ce->width; + scrn->height = ce->height; + break; + } + case XCB_PRESENT_COMPLETE_NOTIFY: { + xcb_present_complete_notify_event_t *ce = (void *) ge; + if (ce->kind == XCB_PRESENT_COMPLETE_KIND_PIXMAP) { + scrn->recv_sbc = (scrn->send_sbc & 0xffffffff00000000LL) | ce->serial; + if (scrn->recv_sbc > scrn->send_sbc) + scrn->recv_sbc -= 0x100000000; + dri3_handle_stamps(scrn, ce->ust, ce->msc); + } else if (ce->kind == XCB_PRESENT_COMPLETE_KIND_NOTIFY_MSC) { + scrn->recv_msc_serial = ce->serial; + dri3_handle_stamps(scrn, ce->ust, ce->msc); + } + break; + } + case XCB_PRESENT_EVENT_IDLE_NOTIFY: { + xcb_present_idle_notify_event_t *ie = (void *) ge; + int b; + for (b = 0; b < BACK_BUFFER_NUM; b++) { + struct vl_dri3_buffer *buf = scrn->back_buffers[b]; + if (buf && buf->pixmap == ie->pixmap) { + buf->busy = false; + break; + } + } + break; + } + } + free(ge); +} + +static void +dri3_flush_present_events(struct vl_dri3_screen *scrn) +{ + if (scrn->special_event) { + xcb_generic_event_t *ev; + while ((ev = xcb_poll_for_special_event( + scrn->conn, scrn->special_event)) != NULL) + dri3_handle_present_event(scrn, (xcb_present_generic_event_t *)ev); + } +} + +static bool +dri3_wait_present_events(struct vl_dri3_screen *scrn) +{ + if (scrn->special_event) { + xcb_generic_event_t *ev; + ev = xcb_wait_for_special_event(scrn->conn, scrn->special_event); + if (!ev) + return false; + dri3_handle_present_event(scrn, (xcb_present_generic_event_t *)ev); + return true; + } + return false; +} + +static int +dri3_find_back(struct vl_dri3_screen *scrn) +{ + int b; + + for (;;) { + for (b = 0; b < BACK_BUFFER_NUM; b++) { + int id = (b + scrn->cur_back) % BACK_BUFFER_NUM; + struct vl_dri3_buffer *buffer = scrn->back_buffers[id]; + if (!buffer || !buffer->busy) + return id; + } + xcb_flush(scrn->conn); + if (!dri3_wait_present_events(scrn)) + return -1; + } +} + +static struct vl_dri3_buffer * +dri3_alloc_back_buffer(struct vl_dri3_screen *scrn) +{ + struct vl_dri3_buffer *buffer; + xcb_pixmap_t pixmap; + xcb_sync_fence_t sync_fence; + struct xshmfence *shm_fence; + int buffer_fd, fence_fd; + struct pipe_resource templ, *pixmap_buffer_texture; + struct winsys_handle whandle; + unsigned usage; + + buffer = CALLOC_STRUCT(vl_dri3_buffer); + if (!buffer) + return NULL; + + fence_fd = xshmfence_alloc_shm(); + if (fence_fd < 0) + goto free_buffer; + + shm_fence = xshmfence_map_shm(fence_fd); + if (!shm_fence) + goto close_fd; + + memset(&templ, 0, sizeof(templ)); + templ.bind = PIPE_BIND_RENDER_TARGET | PIPE_BIND_SAMPLER_VIEW; + templ.format = PIPE_FORMAT_B8G8R8X8_UNORM; + templ.target = PIPE_TEXTURE_2D; + templ.last_level = 0; + templ.width0 = scrn->width; + templ.height0 = scrn->height; + templ.depth0 = 1; + templ.array_size = 1; + + if (scrn->is_different_gpu) { + buffer->texture = scrn->base.pscreen->resource_create(scrn->base.pscreen, + &templ); + if (!buffer->texture) + goto unmap_shm; + + templ.bind |= PIPE_BIND_SCANOUT | PIPE_BIND_SHARED | + PIPE_BIND_LINEAR; + buffer->linear_texture = scrn->base.pscreen->resource_create(scrn->base.pscreen, + &templ); + pixmap_buffer_texture = buffer->linear_texture; + + if (!buffer->linear_texture) + goto no_linear_texture; + } else { + templ.bind |= PIPE_BIND_SCANOUT | PIPE_BIND_SHARED; + buffer->texture = scrn->base.pscreen->resource_create(scrn->base.pscreen, + &templ); + if (!buffer->texture) + goto unmap_shm; + pixmap_buffer_texture = buffer->texture; + } + memset(&whandle, 0, sizeof(whandle)); + whandle.type= DRM_API_HANDLE_TYPE_FD; + usage = PIPE_HANDLE_USAGE_EXPLICIT_FLUSH | PIPE_HANDLE_USAGE_READ; + scrn->base.pscreen->resource_get_handle(scrn->base.pscreen, NULL, + pixmap_buffer_texture, &whandle, + usage); + buffer_fd = whandle.handle; + buffer->pitch = whandle.stride; + xcb_dri3_pixmap_from_buffer(scrn->conn, + (pixmap = xcb_generate_id(scrn->conn)), + scrn->drawable, + 0, + scrn->width, scrn->height, buffer->pitch, + scrn->depth, 32, + buffer_fd); + xcb_dri3_fence_from_fd(scrn->conn, + pixmap, + (sync_fence = xcb_generate_id(scrn->conn)), + false, + fence_fd); + + buffer->pixmap = pixmap; + buffer->sync_fence = sync_fence; + buffer->shm_fence = shm_fence; + buffer->width = scrn->width; + buffer->height = scrn->height; + + xshmfence_trigger(buffer->shm_fence); + + return buffer; + +no_linear_texture: + pipe_resource_reference(&buffer->texture, NULL); +unmap_shm: + xshmfence_unmap_shm(shm_fence); +close_fd: + close(fence_fd); +free_buffer: + FREE(buffer); + return NULL; +} + +static struct vl_dri3_buffer * +dri3_get_back_buffer(struct vl_dri3_screen *scrn) +{ + struct vl_dri3_buffer *buffer; + struct pipe_resource *texture = NULL; + + assert(scrn); + + scrn->cur_back = dri3_find_back(scrn); + if (scrn->cur_back < 0) + return NULL; + buffer = scrn->back_buffers[scrn->cur_back]; + + if (!buffer || buffer->width != scrn->width || + buffer->height != scrn->height) { + struct vl_dri3_buffer *new_buffer; + + new_buffer = dri3_alloc_back_buffer(scrn); + if (!new_buffer) + return NULL; + + if (buffer) + dri3_free_back_buffer(scrn, buffer); + + vl_compositor_reset_dirty_area(&scrn->dirty_areas[scrn->cur_back]); + buffer = new_buffer; + scrn->back_buffers[scrn->cur_back] = buffer; + } + + pipe_resource_reference(&texture, buffer->texture); + xcb_flush(scrn->conn); + xshmfence_await(buffer->shm_fence); + + return buffer; +} + +static bool +dri3_set_drawable(struct vl_dri3_screen *scrn, Drawable drawable) +{ + xcb_get_geometry_cookie_t geom_cookie; + xcb_get_geometry_reply_t *geom_reply; + xcb_void_cookie_t cookie; + xcb_generic_error_t *error; + bool ret = true; + + assert(drawable); + + if (scrn->drawable == drawable) + return true; + + scrn->drawable = drawable; + + geom_cookie = xcb_get_geometry(scrn->conn, scrn->drawable); + geom_reply = xcb_get_geometry_reply(scrn->conn, geom_cookie, NULL); + if (!geom_reply) + return false; + + scrn->width = geom_reply->width; + scrn->height = geom_reply->height; + scrn->depth = geom_reply->depth; + free(geom_reply); + + if (scrn->special_event) { + xcb_unregister_for_special_event(scrn->conn, scrn->special_event); + scrn->special_event = NULL; + cookie = xcb_present_select_input_checked(scrn->conn, scrn->eid, + scrn->drawable, + XCB_PRESENT_EVENT_MASK_NO_EVENT); + xcb_discard_reply(scrn->conn, cookie.sequence); + } + + scrn->is_pixmap = false; + scrn->eid = xcb_generate_id(scrn->conn); + cookie = + xcb_present_select_input_checked(scrn->conn, scrn->eid, scrn->drawable, + XCB_PRESENT_EVENT_MASK_CONFIGURE_NOTIFY | + XCB_PRESENT_EVENT_MASK_COMPLETE_NOTIFY | + XCB_PRESENT_EVENT_MASK_IDLE_NOTIFY); + + error = xcb_request_check(scrn->conn, cookie); + if (error) { + if (error->error_code != BadWindow) + ret = false; + else { + scrn->is_pixmap = true; + if (scrn->front_buffer) { + dri3_free_front_buffer(scrn, scrn->front_buffer); + scrn->front_buffer = NULL; + } + } + free(error); + } else + scrn->special_event = + xcb_register_for_special_xge(scrn->conn, &xcb_present_id, scrn->eid, 0); + + dri3_flush_present_events(scrn); + + return ret; +} + +static struct vl_dri3_buffer * +dri3_get_front_buffer(struct vl_dri3_screen *scrn) +{ + xcb_dri3_buffer_from_pixmap_cookie_t bp_cookie; + xcb_dri3_buffer_from_pixmap_reply_t *bp_reply; + xcb_sync_fence_t sync_fence; + struct xshmfence *shm_fence; + int fence_fd, *fds; + struct winsys_handle whandle; + struct pipe_resource templ, *texture = NULL; + + if (scrn->front_buffer) { + pipe_resource_reference(&texture, scrn->front_buffer->texture); + return scrn->front_buffer; + } + + scrn->front_buffer = CALLOC_STRUCT(vl_dri3_buffer); + if (!scrn->front_buffer) + return NULL; + + fence_fd = xshmfence_alloc_shm(); + if (fence_fd < 0) + goto free_buffer; + + shm_fence = xshmfence_map_shm(fence_fd); + if (!shm_fence) + goto close_fd; + + bp_cookie = xcb_dri3_buffer_from_pixmap(scrn->conn, scrn->drawable); + bp_reply = xcb_dri3_buffer_from_pixmap_reply(scrn->conn, bp_cookie, NULL); + if (!bp_reply) + goto unmap_shm; + + fds = xcb_dri3_buffer_from_pixmap_reply_fds(scrn->conn, bp_reply); + if (fds[0] < 0) + goto free_reply; + + memset(&whandle, 0, sizeof(whandle)); + whandle.type = DRM_API_HANDLE_TYPE_FD; + whandle.handle = (unsigned)fds[0]; + whandle.stride = bp_reply->stride; + memset(&templ, 0, sizeof(templ)); + templ.bind = PIPE_BIND_RENDER_TARGET | PIPE_BIND_SAMPLER_VIEW; + templ.format = PIPE_FORMAT_B8G8R8X8_UNORM; + templ.target = PIPE_TEXTURE_2D; + templ.last_level = 0; + templ.width0 = bp_reply->width; + templ.height0 = bp_reply->height; + templ.depth0 = 1; + templ.array_size = 1; + scrn->front_buffer->texture = + scrn->base.pscreen->resource_from_handle(scrn->base.pscreen, + &templ, &whandle, + PIPE_HANDLE_USAGE_READ_WRITE); + close(fds[0]); + if (!scrn->front_buffer->texture) + goto free_reply; + + xcb_dri3_fence_from_fd(scrn->conn, + scrn->drawable, + (sync_fence = xcb_generate_id(scrn->conn)), + false, + fence_fd); + + pipe_resource_reference(&texture, scrn->front_buffer->texture); + scrn->front_buffer->pixmap = scrn->drawable; + scrn->front_buffer->width = bp_reply->width; + scrn->front_buffer->height = bp_reply->height; + scrn->front_buffer->shm_fence = shm_fence; + scrn->front_buffer->sync_fence = sync_fence; + free(bp_reply); + + return scrn->front_buffer; + +free_reply: + free(bp_reply); +unmap_shm: + xshmfence_unmap_shm(shm_fence); +close_fd: + close(fence_fd); +free_buffer: + FREE(scrn->front_buffer); + return NULL; +} + +static void +vl_dri3_flush_frontbuffer(struct pipe_screen *screen, + struct pipe_resource *resource, + unsigned level, unsigned layer, + void *context_private, struct pipe_box *sub_box) +{ + struct vl_dri3_screen *scrn = (struct vl_dri3_screen *)context_private; + uint32_t options = XCB_PRESENT_OPTION_NONE; + struct vl_dri3_buffer *back; + struct pipe_box src_box; + + back = scrn->back_buffers[scrn->cur_back]; + if (!back) + return; + + if (scrn->flushed) { + while (scrn->special_event && scrn->recv_sbc < scrn->send_sbc) + if (!dri3_wait_present_events(scrn)) + return; + } + + if (scrn->is_different_gpu) { + u_box_origin_2d(scrn->width, scrn->height, &src_box); + scrn->pipe->resource_copy_region(scrn->pipe, + back->linear_texture, + 0, 0, 0, 0, + back->texture, + 0, &src_box); + + scrn->pipe->flush(scrn->pipe, NULL, 0); + } + xshmfence_reset(back->shm_fence); + back->busy = true; + + xcb_present_pixmap(scrn->conn, + scrn->drawable, + back->pixmap, + (uint32_t)(++scrn->send_sbc), + 0, 0, 0, 0, + None, None, + back->sync_fence, + options, + scrn->next_msc, + 0, 0, 0, NULL); + + xcb_flush(scrn->conn); + + scrn->flushed = true; + + return; +} + +static struct pipe_resource * +vl_dri3_screen_texture_from_drawable(struct vl_screen *vscreen, void *drawable) +{ + struct vl_dri3_screen *scrn = (struct vl_dri3_screen *)vscreen; + struct vl_dri3_buffer *buffer; + + assert(scrn); + + if (!dri3_set_drawable(scrn, (Drawable)drawable)) + return NULL; + + if (scrn->flushed) { + while (scrn->special_event && scrn->recv_sbc < scrn->send_sbc) + if (!dri3_wait_present_events(scrn)) + return NULL; + } + scrn->flushed = false; + + buffer = (scrn->is_pixmap) ? + dri3_get_front_buffer(scrn) : + dri3_get_back_buffer(scrn); + if (!buffer) + return NULL; + + return buffer->texture; +} + +static struct u_rect * +vl_dri3_screen_get_dirty_area(struct vl_screen *vscreen) +{ + struct vl_dri3_screen *scrn = (struct vl_dri3_screen *)vscreen; + + assert(scrn); + + return &scrn->dirty_areas[scrn->cur_back]; +} + +static uint64_t +vl_dri3_screen_get_timestamp(struct vl_screen *vscreen, void *drawable) +{ + struct vl_dri3_screen *scrn = (struct vl_dri3_screen *)vscreen; + + assert(scrn); + + if (!dri3_set_drawable(scrn, (Drawable)drawable)) + return 0; + + if (!scrn->last_ust) { + xcb_present_notify_msc(scrn->conn, + scrn->drawable, + ++scrn->send_msc_serial, + 0, 0, 0); + xcb_flush(scrn->conn); + + while (scrn->special_event && + scrn->send_msc_serial > scrn->recv_msc_serial) { + if (!dri3_wait_present_events(scrn)) + return 0; + } + } + + return scrn->last_ust; +} + +static void +vl_dri3_screen_set_next_timestamp(struct vl_screen *vscreen, uint64_t stamp) +{ + struct vl_dri3_screen *scrn = (struct vl_dri3_screen *)vscreen; + + assert(scrn); + + if (stamp && scrn->last_ust && scrn->ns_frame && scrn->last_msc) + scrn->next_msc = ((int64_t)stamp - scrn->last_ust + scrn->ns_frame/2) / + scrn->ns_frame + scrn->last_msc; + else + scrn->next_msc = 0; +} + +static void * +vl_dri3_screen_get_private(struct vl_screen *vscreen) +{ + return vscreen; +} + +static void +vl_dri3_screen_destroy(struct vl_screen *vscreen) +{ + struct vl_dri3_screen *scrn = (struct vl_dri3_screen *)vscreen; + int i; + + assert(vscreen); + + dri3_flush_present_events(scrn); + + if (scrn->front_buffer) { + dri3_free_front_buffer(scrn, scrn->front_buffer); + scrn->front_buffer = NULL; + return; + } + + for (i = 0; i < BACK_BUFFER_NUM; ++i) { + if (scrn->back_buffers[i]) { + dri3_free_back_buffer(scrn, scrn->back_buffers[i]); + scrn->back_buffers[i] = NULL; + } + } + + if (scrn->special_event) { + xcb_void_cookie_t cookie = + xcb_present_select_input_checked(scrn->conn, scrn->eid, + scrn->drawable, + XCB_PRESENT_EVENT_MASK_NO_EVENT); + + xcb_discard_reply(scrn->conn, cookie.sequence); + xcb_unregister_for_special_event(scrn->conn, scrn->special_event); + } + scrn->pipe->destroy(scrn->pipe); + scrn->base.pscreen->destroy(scrn->base.pscreen); + pipe_loader_release(&scrn->base.dev, 1); + FREE(scrn); + + return; +} + +struct vl_screen * +vl_dri3_screen_create(Display *display, int screen) +{ + struct vl_dri3_screen *scrn; + const xcb_query_extension_reply_t *extension; + xcb_dri3_open_cookie_t open_cookie; + xcb_dri3_open_reply_t *open_reply; + xcb_get_geometry_cookie_t geom_cookie; + xcb_get_geometry_reply_t *geom_reply; + int fd; + + assert(display); + + scrn = CALLOC_STRUCT(vl_dri3_screen); + if (!scrn) + return NULL; + + scrn->conn = XGetXCBConnection(display); + if (!scrn->conn) + goto free_screen; + + xcb_prefetch_extension_data(scrn->conn , &xcb_dri3_id); + xcb_prefetch_extension_data(scrn->conn, &xcb_present_id); + extension = xcb_get_extension_data(scrn->conn, &xcb_dri3_id); + if (!(extension && extension->present)) + goto free_screen; + extension = xcb_get_extension_data(scrn->conn, &xcb_present_id); + if (!(extension && extension->present)) + goto free_screen; + + open_cookie = xcb_dri3_open(scrn->conn, RootWindow(display, screen), None); + open_reply = xcb_dri3_open_reply(scrn->conn, open_cookie, NULL); + if (!open_reply) + goto free_screen; + if (open_reply->nfd != 1) { + free(open_reply); + goto free_screen; + } + + fd = xcb_dri3_open_reply_fds(scrn->conn, open_reply)[0]; + if (fd < 0) { + free(open_reply); + goto free_screen; + } + fcntl(fd, F_SETFD, FD_CLOEXEC); + free(open_reply); + + fd = loader_get_user_preferred_fd(fd, &scrn->is_different_gpu); + + geom_cookie = xcb_get_geometry(scrn->conn, RootWindow(display, screen)); + geom_reply = xcb_get_geometry_reply(scrn->conn, geom_cookie, NULL); + if (!geom_reply) + goto close_fd; + /* TODO support depth other than 24 */ + if (geom_reply->depth != 24) { + free(geom_reply); + goto close_fd; + } + free(geom_reply); + + if (pipe_loader_drm_probe_fd(&scrn->base.dev, fd)) + scrn->base.pscreen = pipe_loader_create_screen(scrn->base.dev); + + if (!scrn->base.pscreen) + goto release_pipe; + + scrn->pipe = scrn->base.pscreen->context_create(scrn->base.pscreen, + &scrn->base, 0); + if (!scrn->pipe) + goto no_context; + + scrn->base.destroy = vl_dri3_screen_destroy; + scrn->base.texture_from_drawable = vl_dri3_screen_texture_from_drawable; + scrn->base.get_dirty_area = vl_dri3_screen_get_dirty_area; + scrn->base.get_timestamp = vl_dri3_screen_get_timestamp; + scrn->base.set_next_timestamp = vl_dri3_screen_set_next_timestamp; + scrn->base.get_private = vl_dri3_screen_get_private; + scrn->base.pscreen->flush_frontbuffer = vl_dri3_flush_frontbuffer; + + return &scrn->base; + +no_context: + scrn->base.pscreen->destroy(scrn->base.pscreen); +release_pipe: + if (scrn->base.dev) { + pipe_loader_release(&scrn->base.dev, 1); + fd = -1; + } +close_fd: + if (fd != -1) + close(fd); +free_screen: + FREE(scrn); + return NULL; +} diff --git a/lib/mesa/src/gallium/auxiliary/vl/vl_winsys_drm.c b/lib/mesa/src/gallium/auxiliary/vl/vl_winsys_drm.c index 6d9d94758..df8809c50 100644 --- a/lib/mesa/src/gallium/auxiliary/vl/vl_winsys_drm.c +++ b/lib/mesa/src/gallium/auxiliary/vl/vl_winsys_drm.c @@ -26,6 +26,7 @@ **************************************************************************/ #include <assert.h> +#include <fcntl.h> #include "pipe/p_screen.h" #include "pipe-loader/pipe_loader.h" @@ -41,20 +42,20 @@ struct vl_screen * vl_drm_screen_create(int fd) { struct vl_screen *vscreen; - int new_fd = -1; + int new_fd; vscreen = CALLOC_STRUCT(vl_screen); if (!vscreen) return NULL; - if (fd < 0 || (new_fd = dup(fd)) < 0) - goto error; + if (fd < 0 || (new_fd = fcntl(fd, F_DUPFD_CLOEXEC, 3)) < 0) + goto free_screen; if (pipe_loader_drm_probe_fd(&vscreen->dev, new_fd)) vscreen->pscreen = pipe_loader_create_screen(vscreen->dev); if (!vscreen->pscreen) - goto error; + goto release_pipe; vscreen->destroy = vl_drm_screen_destroy; vscreen->texture_from_drawable = NULL; @@ -64,12 +65,13 @@ vl_drm_screen_create(int fd) vscreen->get_private = NULL; return vscreen; -error: +release_pipe: if (vscreen->dev) pipe_loader_release(&vscreen->dev, 1); else close(new_fd); +free_screen: FREE(vscreen); return NULL; } diff --git a/lib/mesa/src/gallium/auxiliary/vl/vl_zscan.c b/lib/mesa/src/gallium/auxiliary/vl/vl_zscan.c index 5241471f5..ef05af463 100644 --- a/lib/mesa/src/gallium/auxiliary/vl/vl_zscan.c +++ b/lib/mesa/src/gallium/auxiliary/vl/vl_zscan.c @@ -99,17 +99,14 @@ static void * create_vert_shader(struct vl_zscan *zscan) { struct ureg_program *shader; - struct ureg_src scale; struct ureg_src vrect, vpos, block_num; - struct ureg_dst tmp; struct ureg_dst o_vpos; struct ureg_dst *o_vtex; + unsigned i; - signed i; - - shader = ureg_create(TGSI_PROCESSOR_VERTEX); + shader = ureg_create(PIPE_SHADER_VERTEX); if (!shader) return NULL; @@ -186,7 +183,7 @@ create_frag_shader(struct vl_zscan *zscan) unsigned i; - shader = ureg_create(TGSI_PROCESSOR_FRAGMENT); + shader = ureg_create(PIPE_SHADER_FRAGMENT); if (!shader) return NULL; |