[Mesa-dev] [PATCH 2/2] st/vdpau: use bicubic filter for scaling(v6.1)

Christian König deathsimple at vodafone.de
Wed Jun 29 13:34:33 UTC 2016


Am 29.06.2016 um 15:24 schrieb Nayan Deshmukh:
> 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

Ah, crap yeah. The filters only work correctly on AMD hardware because 
of the linear bind.

I should have probably used a temporary texture for this as well.

Anyway I will commit this patch now and fix the fallout later on.

Regards,
Christian.

>
> Signed-off-by: Nayan Deshmukh <nayan26deshmukh at gmail.com>
> ---
>   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(-)
>
> 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;



More information about the mesa-dev mailing list