From de772bc060fb401e30cfbfa4ae3973fb025865e5 Mon Sep 17 00:00:00 2001 From: Nayan Deshmukh Date: Wed, 29 Jun 2016 18:54:01 +0530 Subject: st/vdpau: use bicubic filter for scaling(v6.1) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit use bicubic filtering as high quality scaling L1. v2: fix a typo and add a newline to code v3: -render the unscaled image on a temporary surface (Christian) -apply noise reduction and sharpness filter on unscaled surface -render the final scaled surface using bicubic interpolation v4: support high quality scaling v5: set dst_area and dst_clip in bicubic filter v6: set buffer layer before setting dst_area v6.1: add PIPE_BIND_LINEAR when creating resource Signed-off-by: Nayan Deshmukh Reviewed-by: Christian König --- src/gallium/state_trackers/vdpau/mixer.c | 113 ++++++++++++++++++++--- src/gallium/state_trackers/vdpau/query.c | 1 + src/gallium/state_trackers/vdpau/vdpau_private.h | 6 ++ 3 files changed, 106 insertions(+), 14 deletions(-) (limited to 'src/gallium/state_trackers/vdpau') diff --git a/src/gallium/state_trackers/vdpau/mixer.c b/src/gallium/state_trackers/vdpau/mixer.c index 65c3ce2..cb0ef03 100644 --- a/src/gallium/state_trackers/vdpau/mixer.c +++ b/src/gallium/state_trackers/vdpau/mixer.c @@ -82,7 +82,6 @@ vlVdpVideoMixerCreate(VdpDevice device, switch (features[i]) { /* they are valid, but we doesn't support them */ case VDP_VIDEO_MIXER_FEATURE_DEINTERLACE_TEMPORAL_SPATIAL: - case VDP_VIDEO_MIXER_FEATURE_HIGH_QUALITY_SCALING_L1: case VDP_VIDEO_MIXER_FEATURE_HIGH_QUALITY_SCALING_L2: case VDP_VIDEO_MIXER_FEATURE_HIGH_QUALITY_SCALING_L3: case VDP_VIDEO_MIXER_FEATURE_HIGH_QUALITY_SCALING_L4: @@ -110,6 +109,9 @@ vlVdpVideoMixerCreate(VdpDevice device, vmixer->luma_key.supported = true; break; + case VDP_VIDEO_MIXER_FEATURE_HIGH_QUALITY_SCALING_L1: + vmixer->bicubic.supported = true; + break; default: goto no_params; } } @@ -202,6 +204,11 @@ vlVdpVideoMixerDestroy(VdpVideoMixer mixer) vl_matrix_filter_cleanup(vmixer->sharpness.filter); FREE(vmixer->sharpness.filter); } + + if (vmixer->bicubic.filter) { + vl_bicubic_filter_cleanup(vmixer->bicubic.filter); + FREE(vmixer->bicubic.filter); + } pipe_mutex_unlock(vmixer->device->mutex); DeviceReference(&vmixer->device, NULL); @@ -230,9 +237,11 @@ VdpStatus vlVdpVideoMixerRender(VdpVideoMixer mixer, VdpLayer const *layers) { enum vl_compositor_deinterlace deinterlace; - struct u_rect rect, clip, *prect; + struct u_rect rect, clip, *prect, dirty_area; unsigned i, layer = 0; struct pipe_video_buffer *video_buffer; + struct pipe_sampler_view *sampler_view; + struct pipe_surface *surface; vlVdpVideoMixer *vmixer; vlVdpSurface *surf; @@ -325,7 +334,44 @@ VdpStatus vlVdpVideoMixerRender(VdpVideoMixer mixer, prect = ▭ } vl_compositor_set_buffer_layer(&vmixer->cstate, compositor, layer, video_buffer, prect, NULL, deinterlace); - vl_compositor_set_layer_dst_area(&vmixer->cstate, layer++, RectToPipe(destination_video_rect, &rect)); + + if(vmixer->bicubic.filter) { + struct pipe_context *pipe; + struct pipe_resource res_tmpl, *res; + struct pipe_sampler_view sv_templ; + struct pipe_surface surf_templ; + + pipe = vmixer->device->context; + memset(&res_tmpl, 0, sizeof(res_tmpl)); + + res_tmpl.target = PIPE_TEXTURE_2D; + res_tmpl.width0 = surf->templat.width; + res_tmpl.height0 = surf->templat.height; + res_tmpl.format = dst->sampler_view->format; + res_tmpl.depth0 = 1; + res_tmpl.array_size = 1; + res_tmpl.bind = PIPE_BIND_SAMPLER_VIEW | PIPE_BIND_RENDER_TARGET | + PIPE_BIND_LINEAR; + res_tmpl.usage = PIPE_USAGE_DEFAULT; + + res = pipe->screen->resource_create(pipe->screen, &res_tmpl); + + vlVdpDefaultSamplerViewTemplate(&sv_templ, res); + sampler_view = pipe->create_sampler_view(pipe, res, &sv_templ); + + memset(&surf_templ, 0, sizeof(surf_templ)); + surf_templ.format = res->format; + surface = pipe->create_surface(pipe, res, &surf_templ); + + vl_compositor_reset_dirty_area(&dirty_area); + pipe_resource_reference(&res, NULL); + } else { + surface = dst->surface; + sampler_view = dst->sampler_view; + dirty_area = dst->dirty_area; + vl_compositor_set_layer_dst_area(&vmixer->cstate, layer++, RectToPipe(destination_video_rect, &rect)); + vl_compositor_set_dst_clip(&vmixer->cstate, RectToPipe(destination_rect, &clip)); + } for (i = 0; i < layer_count; ++i) { vlVdpOutputSurface *src = vlGetDataHTAB(layers->source_surface); @@ -343,22 +389,29 @@ VdpStatus vlVdpVideoMixerRender(VdpVideoMixer mixer, ++layers; } - vl_compositor_set_dst_clip(&vmixer->cstate, RectToPipe(destination_rect, &clip)); - if (!vmixer->noise_reduction.filter && !vmixer->sharpness.filter) + if (!vmixer->noise_reduction.filter && !vmixer->sharpness.filter && !vmixer->bicubic.filter) vlVdpSave4DelayedRendering(vmixer->device, destination_surface, &vmixer->cstate); else { - vl_compositor_render(&vmixer->cstate, compositor, dst->surface, &dst->dirty_area, true); + vl_compositor_render(&vmixer->cstate, compositor, surface, &dirty_area, true); - /* applying the noise reduction after scaling is actually not very - clever, but currently we should avoid to copy around the image - data once more. */ if (vmixer->noise_reduction.filter) vl_median_filter_render(vmixer->noise_reduction.filter, - dst->sampler_view, dst->surface); + sampler_view, surface); if (vmixer->sharpness.filter) vl_matrix_filter_render(vmixer->sharpness.filter, - dst->sampler_view, dst->surface); + sampler_view, surface); + + if (vmixer->bicubic.filter) + vl_bicubic_filter_render(vmixer->bicubic.filter, + sampler_view, dst->surface, + RectToPipe(destination_video_rect, &rect), + RectToPipe(destination_rect, &clip)); + + if(surface != dst->surface) { + pipe_sampler_view_reference(&sampler_view, NULL); + pipe_surface_reference(&surface, NULL); + } } pipe_mutex_unlock(vmixer->device->mutex); @@ -461,6 +514,28 @@ vlVdpVideoMixerUpdateSharpnessFilter(vlVdpVideoMixer *vmixer) } /** + * Update the bicubic filter + */ +static void +vlVdpVideoMixerUpdateBicubicFilter(vlVdpVideoMixer *vmixer) +{ + assert(vmixer); + + /* if present remove the old filter first */ + if (vmixer->bicubic.filter) { + vl_bicubic_filter_cleanup(vmixer->bicubic.filter); + FREE(vmixer->bicubic.filter); + vmixer->bicubic.filter = NULL; + } + /* and create a new filter as needed */ + if (vmixer->bicubic.enabled) { + vmixer->bicubic.filter = MALLOC(sizeof(struct vl_bicubic_filter)); + vl_bicubic_filter_init(vmixer->bicubic.filter, vmixer->device->context, + vmixer->video_width, vmixer->video_height); + } +} + +/** * Retrieve whether features were requested at creation time. */ VdpStatus @@ -483,7 +558,6 @@ vlVdpVideoMixerGetFeatureSupport(VdpVideoMixer mixer, switch (features[i]) { /* they are valid, but we doesn't support them */ case VDP_VIDEO_MIXER_FEATURE_DEINTERLACE_TEMPORAL_SPATIAL: - case VDP_VIDEO_MIXER_FEATURE_HIGH_QUALITY_SCALING_L1: case VDP_VIDEO_MIXER_FEATURE_HIGH_QUALITY_SCALING_L2: case VDP_VIDEO_MIXER_FEATURE_HIGH_QUALITY_SCALING_L3: case VDP_VIDEO_MIXER_FEATURE_HIGH_QUALITY_SCALING_L4: @@ -512,6 +586,10 @@ vlVdpVideoMixerGetFeatureSupport(VdpVideoMixer mixer, feature_supports[i] = vmixer->luma_key.supported; break; + case VDP_VIDEO_MIXER_FEATURE_HIGH_QUALITY_SCALING_L1: + feature_supports[i] = vmixer->bicubic.supported; + break; + default: return VDP_STATUS_INVALID_VIDEO_MIXER_FEATURE; } @@ -544,7 +622,6 @@ vlVdpVideoMixerSetFeatureEnables(VdpVideoMixer mixer, switch (features[i]) { /* they are valid, but we doesn't support them */ case VDP_VIDEO_MIXER_FEATURE_DEINTERLACE_TEMPORAL_SPATIAL: - case VDP_VIDEO_MIXER_FEATURE_HIGH_QUALITY_SCALING_L1: case VDP_VIDEO_MIXER_FEATURE_HIGH_QUALITY_SCALING_L2: case VDP_VIDEO_MIXER_FEATURE_HIGH_QUALITY_SCALING_L3: case VDP_VIDEO_MIXER_FEATURE_HIGH_QUALITY_SCALING_L4: @@ -578,6 +655,11 @@ vlVdpVideoMixerSetFeatureEnables(VdpVideoMixer mixer, vmixer->luma_key.luma_min, vmixer->luma_key.luma_max); break; + case VDP_VIDEO_MIXER_FEATURE_HIGH_QUALITY_SCALING_L1: + vmixer->bicubic.enabled = feature_enables[i]; + vlVdpVideoMixerUpdateBicubicFilter(vmixer); + break; + default: pipe_mutex_unlock(vmixer->device->mutex); return VDP_STATUS_INVALID_VIDEO_MIXER_FEATURE; @@ -612,7 +694,6 @@ vlVdpVideoMixerGetFeatureEnables(VdpVideoMixer mixer, /* they are valid, but we doesn't support them */ case VDP_VIDEO_MIXER_FEATURE_DEINTERLACE_TEMPORAL: case VDP_VIDEO_MIXER_FEATURE_DEINTERLACE_TEMPORAL_SPATIAL: - case VDP_VIDEO_MIXER_FEATURE_HIGH_QUALITY_SCALING_L1: case VDP_VIDEO_MIXER_FEATURE_HIGH_QUALITY_SCALING_L2: case VDP_VIDEO_MIXER_FEATURE_HIGH_QUALITY_SCALING_L3: case VDP_VIDEO_MIXER_FEATURE_HIGH_QUALITY_SCALING_L4: @@ -636,6 +717,10 @@ vlVdpVideoMixerGetFeatureEnables(VdpVideoMixer mixer, feature_enables[i] = vmixer->luma_key.enabled; break; + case VDP_VIDEO_MIXER_FEATURE_HIGH_QUALITY_SCALING_L1: + feature_enables[i] = vmixer->bicubic.enabled; + break; + default: return VDP_STATUS_INVALID_VIDEO_MIXER_FEATURE; } diff --git a/src/gallium/state_trackers/vdpau/query.c b/src/gallium/state_trackers/vdpau/query.c index c3decc0..e69c9b1 100644 --- a/src/gallium/state_trackers/vdpau/query.c +++ b/src/gallium/state_trackers/vdpau/query.c @@ -471,6 +471,7 @@ vlVdpVideoMixerQueryFeatureSupport(VdpDevice device, VdpVideoMixerFeature featur case VDP_VIDEO_MIXER_FEATURE_NOISE_REDUCTION: case VDP_VIDEO_MIXER_FEATURE_DEINTERLACE_TEMPORAL: case VDP_VIDEO_MIXER_FEATURE_LUMA_KEY: + case VDP_VIDEO_MIXER_FEATURE_HIGH_QUALITY_SCALING_L1: *is_supported = VDP_TRUE; break; default: diff --git a/src/gallium/state_trackers/vdpau/vdpau_private.h b/src/gallium/state_trackers/vdpau/vdpau_private.h index 8673c6a..bcd4bb1 100644 --- a/src/gallium/state_trackers/vdpau/vdpau_private.h +++ b/src/gallium/state_trackers/vdpau/vdpau_private.h @@ -45,6 +45,7 @@ #include "os/os_thread.h" #include "vl/vl_video_buffer.h" +#include "vl/vl_bicubic_filter.h" #include "vl/vl_compositor.h" #include "vl/vl_csc.h" #include "vl/vl_deint_filter.h" @@ -373,6 +374,11 @@ typedef struct } deint; struct { + bool supported, enabled; + struct vl_bicubic_filter *filter; + } bicubic; + + struct { bool supported, enabled; unsigned level; struct vl_median_filter *filter; -- cgit v1.1