st/vdpau: use bicubic filter for scaling(v6.1)
authorNayan Deshmukh <nayan26deshmukh@gmail.com>
Wed, 29 Jun 2016 13:24:01 +0000 (18:54 +0530)
committerChristian König <christian.koenig@amd.com>
Fri, 1 Jul 2016 10:54:58 +0000 (12:54 +0200)
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 <nayan26deshmukh@gmail.com>
Reviewed-by: Christian König <christian.koenig@amd.com>
src/gallium/state_trackers/vdpau/mixer.c
src/gallium/state_trackers/vdpau/query.c
src/gallium/state_trackers/vdpau/vdpau_private.h

index 65c3ce2b9e1b7e0bbce0eefae420c9e819abe367..cb0ef03972238618f052fa3c632b150fd629d360 100644 (file)
@@ -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 = &rect;
    }
    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);
 
@@ -460,6 +513,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.
  */
@@ -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;
       }
index c3decc0405f92b5f61ed0848a6e1a163019b42df..e69c9b11f55bb0ea071781afd51652409522af00 100644 (file)
@@ -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:
index 8673c6ac9320b409a3f97e2ff395a47a90bb6772..bcd4bb181c7a72fc7aba279599cb97186cf1d322 100644 (file)
@@ -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"
@@ -372,6 +373,11 @@ typedef struct
          struct vl_deint_filter *filter;
    } deint;
 
+   struct {
+         bool supported, enabled;
+         struct vl_bicubic_filter *filter;
+   } bicubic;
+
    struct {
       bool supported, enabled;
       unsigned level;