[Mesa-dev] [PATCH 10/25] st/vdpau: avoid an unnessasary copy

Christian König deathsimple at vodafone.de
Mon Feb 27 08:25:38 PST 2012


Delay the actual mixer rendering until we really
know which surface is the real destination.

Signed-off-by: Christian König <deathsimple at vodafone.de>
---
 src/gallium/state_trackers/vdpau/device.c        |   52 ++++++++++++++++++++++
 src/gallium/state_trackers/vdpau/mixer.c         |   33 +++++++++-----
 src/gallium/state_trackers/vdpau/output.c        |    6 +++
 src/gallium/state_trackers/vdpau/presentation.c  |   33 ++++++++++----
 src/gallium/state_trackers/vdpau/vdpau_private.h |    9 ++++
 5 files changed, 112 insertions(+), 21 deletions(-)

diff --git a/src/gallium/state_trackers/vdpau/device.c b/src/gallium/state_trackers/vdpau/device.c
index f4a3dc0..482b71e 100644
--- a/src/gallium/state_trackers/vdpau/device.c
+++ b/src/gallium/state_trackers/vdpau/device.c
@@ -29,6 +29,7 @@
 
 #include "util/u_memory.h"
 #include "util/u_debug.h"
+#include "util/u_sampler.h"
 
 #include "vl_winsys.h"
 
@@ -237,3 +238,54 @@ vlVdpGetErrorString (VdpStatus status)
    default: return "Unknown Error";
    }
 }
+
+void
+vlVdpResolveDelayedRendering(vlVdpDevice *dev, struct pipe_surface *surface, struct u_rect *dirty_area)
+{
+   struct vl_compositor_state *cstate;
+   vlVdpOutputSurface *vlsurface;
+
+   assert(dev);
+
+   cstate = dev->delayed_rendering.cstate;
+   if (!cstate)
+      return;
+
+   vlsurface = vlGetDataHTAB(dev->delayed_rendering.surface);
+   if (!vlsurface)
+      return;
+
+   if (!surface) {
+      surface = vlsurface->surface;
+      dirty_area = &vlsurface->dirty_area;
+   }
+
+   vl_compositor_render(cstate, &dev->compositor, surface, dirty_area);
+
+   dev->delayed_rendering.surface = VDP_INVALID_HANDLE;
+   dev->delayed_rendering.cstate = NULL;
+
+   /* test if we need to create a new sampler for the just filled texture */
+   if (surface->texture != vlsurface->sampler_view->texture) {
+      struct pipe_resource *res = surface->texture;
+      struct pipe_sampler_view sv_templ;
+
+      memset(&sv_templ, 0, sizeof(sv_templ));
+      u_sampler_view_default_template(&sv_templ, res, res->format);
+      pipe_sampler_view_reference(&vlsurface->sampler_view,
+         dev->context->create_sampler_view(dev->context, res, &sv_templ));
+   }
+
+   return;
+}
+
+void
+vlVdpSave4DelayedRendering(vlVdpDevice *dev, VdpOutputSurface surface, struct vl_compositor_state *cstate)
+{
+   assert(dev);
+
+   vlVdpResolveDelayedRendering(dev, NULL, NULL);
+
+   dev->delayed_rendering.surface = surface;
+   dev->delayed_rendering.cstate = cstate;
+}
diff --git a/src/gallium/state_trackers/vdpau/mixer.c b/src/gallium/state_trackers/vdpau/mixer.c
index ead9323..4ded2a0 100644
--- a/src/gallium/state_trackers/vdpau/mixer.c
+++ b/src/gallium/state_trackers/vdpau/mixer.c
@@ -166,6 +166,9 @@ vlVdpVideoMixerDestroy(VdpVideoMixer mixer)
    vmixer = vlGetDataHTAB(mixer);
    if (!vmixer)
       return VDP_STATUS_INVALID_HANDLE;
+
+   vlVdpResolveDelayedRendering(vmixer->device, NULL, NULL);
+
    vlRemoveDataHTAB(mixer);
 
    vl_compositor_cleanup_state(&vmixer->cstate);
@@ -218,6 +221,8 @@ VdpStatus vlVdpVideoMixerRender(VdpVideoMixer mixer,
    if (!vmixer)
       return VDP_STATUS_INVALID_HANDLE;
 
+   vlVdpResolveDelayedRendering(vmixer->device, NULL, NULL);
+
    compositor = &vmixer->device->compositor;
 
    surf = vlGetDataHTAB(video_surface_current);
@@ -269,18 +274,22 @@ VdpStatus vlVdpVideoMixerRender(VdpVideoMixer mixer,
                                   RectToPipe(video_source_rect, &src_rect), NULL, deinterlace);
    vl_compositor_set_dst_area(&vmixer->cstate, RectToPipe(destination_video_rect, &dst_rect));
    vl_compositor_set_dst_clip(&vmixer->cstate, RectToPipe(destination_rect, &dst_clip));
-   vl_compositor_render(&vmixer->cstate, compositor, dst->surface, &dst->dirty_area);
-
-   /* 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);
-
-   if (vmixer->sharpness.filter)
-      vl_matrix_filter_render(vmixer->sharpness.filter,
-                              dst->sampler_view, dst->surface);
+   if (!vmixer->noise_reduction.filter && !vmixer->sharpness.filter)
+      vlVdpSave4DelayedRendering(vmixer->device, destination_surface, &vmixer->cstate);
+   else {
+      vl_compositor_render(&vmixer->cstate, compositor, dst->surface, &dst->dirty_area);
+
+      /* 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);
+
+      if (vmixer->sharpness.filter)
+         vl_matrix_filter_render(vmixer->sharpness.filter,
+                                 dst->sampler_view, dst->surface);
+   }
 
    return VDP_STATUS_OK;
 }
diff --git a/src/gallium/state_trackers/vdpau/output.c b/src/gallium/state_trackers/vdpau/output.c
index 0ea5029..887ca2a 100644
--- a/src/gallium/state_trackers/vdpau/output.c
+++ b/src/gallium/state_trackers/vdpau/output.c
@@ -131,6 +131,8 @@ vlVdpOutputSurfaceDestroy(VdpOutputSurface surface)
    if (!vlsurface)
       return VDP_STATUS_INVALID_HANDLE;
 
+   vlVdpResolveDelayedRendering(vlsurface->device, NULL, NULL);
+
    pipe_surface_reference(&vlsurface->surface, NULL);
    pipe_sampler_view_reference(&vlsurface->sampler_view, NULL);
    vl_compositor_cleanup_state(&vlsurface->cstate);
@@ -220,6 +222,8 @@ vlVdpOutputSurfacePutBitsIndexed(VdpOutputSurface surface,
    if (!vlsurface)
       return VDP_STATUS_INVALID_HANDLE;
 
+   vlVdpResolveDelayedRendering(vlsurface->device, NULL, NULL);
+
    context = vlsurface->device->context;
    compositor = &vlsurface->device->compositor;
    cstate = &vlsurface->cstate;
@@ -463,6 +467,8 @@ vlVdpOutputSurfaceRenderOutputSurface(VdpOutputSurface destination_surface,
    if (dst_vlsurface->device != src_vlsurface->device)
       return VDP_STATUS_HANDLE_DEVICE_MISMATCH;
 
+   vlVdpResolveDelayedRendering(dst_vlsurface->device, NULL, NULL);
+
    context = dst_vlsurface->device->context;
    compositor = &dst_vlsurface->device->compositor;
    cstate = &dst_vlsurface->cstate;
diff --git a/src/gallium/state_trackers/vdpau/presentation.c b/src/gallium/state_trackers/vdpau/presentation.c
index 4d12bb3..cc20a96 100644
--- a/src/gallium/state_trackers/vdpau/presentation.c
+++ b/src/gallium/state_trackers/vdpau/presentation.c
@@ -205,13 +205,16 @@ vlVdpPresentationQueueDisplay(VdpPresentationQueue presentation_queue,
    struct u_rect src_rect, dst_clip, *dirty_area;
 
    struct vl_compositor *compositor;
+   struct vl_compositor_state *cstate;
 
    pq = vlGetDataHTAB(presentation_queue);
    if (!pq)
       return VDP_STATUS_INVALID_HANDLE;
 
+
    pipe = pq->device->context;
    compositor = &pq->device->compositor;
+   cstate = &pq->cstate;
 
    tex = vl_screen_texture_from_drawable(pq->device->vscreen, pq->drawable);
    if (!tex)
@@ -230,20 +233,32 @@ vlVdpPresentationQueueDisplay(VdpPresentationQueue presentation_queue,
 
    surf->timestamp = (vlVdpTime)earliest_presentation_time;
 
-   src_rect.x0 = 0;
-   src_rect.y0 = 0;
-   src_rect.x1 = surf_draw->width;
-   src_rect.y1 = surf_draw->height;
-
    dst_clip.x0 = 0;
    dst_clip.y0 = 0;
    dst_clip.x1 = clip_width ? clip_width : surf_draw->width;
    dst_clip.y1 = clip_height ? clip_height : surf_draw->height;
 
-   vl_compositor_clear_layers(&pq->cstate);
-   vl_compositor_set_rgba_layer(&pq->cstate, compositor, 0, surf->sampler_view, &src_rect, NULL);
-   vl_compositor_set_dst_clip(&pq->cstate, &dst_clip);
-   vl_compositor_render(&pq->cstate, compositor, surf_draw, dirty_area);
+   if (pq->device->delayed_rendering.surface == surface &&
+       dst_clip.x1 == surf_draw->width && dst_clip.y1 == surf_draw->height) {
+
+      // TODO: we correctly support the clipping here, but not the pq background color in the clipped area....
+      cstate = pq->device->delayed_rendering.cstate;
+      vl_compositor_set_dst_clip(cstate, &dst_clip);
+      vlVdpResolveDelayedRendering(pq->device, surf_draw, dirty_area);
+
+   } else {
+      vlVdpResolveDelayedRendering(pq->device, NULL, NULL);
+
+      src_rect.x0 = 0;
+      src_rect.y0 = 0;
+      src_rect.x1 = surf_draw->width;
+      src_rect.y1 = surf_draw->height;
+
+      vl_compositor_clear_layers(cstate);
+      vl_compositor_set_rgba_layer(cstate, compositor, 0, surf->sampler_view, &src_rect, NULL);
+      vl_compositor_set_dst_clip(cstate, &dst_clip);
+      vl_compositor_render(cstate, compositor, surf_draw, dirty_area);
+   }
 
    pipe->screen->flush_frontbuffer
    (
diff --git a/src/gallium/state_trackers/vdpau/vdpau_private.h b/src/gallium/state_trackers/vdpau/vdpau_private.h
index 1b61784..b7035f3 100644
--- a/src/gallium/state_trackers/vdpau/vdpau_private.h
+++ b/src/gallium/state_trackers/vdpau/vdpau_private.h
@@ -288,6 +288,11 @@ typedef struct
    struct vl_screen *vscreen;
    struct pipe_context *context;
    struct vl_compositor compositor;
+
+   struct {
+      struct vl_compositor_state *cstate;
+      VdpOutputSurface surface;
+   } delayed_rendering;
 } vlVdpDevice;
 
 typedef struct
@@ -366,6 +371,10 @@ boolean vlGetFuncFTAB(VdpFuncId function_id, void **func);
 VdpDeviceCreateX11 vdp_imp_device_create_x11;
 VdpPresentationQueueTargetCreateX11 vlVdpPresentationQueueTargetCreateX11;
 
+/* Delayed rendering funtionality */
+void vlVdpResolveDelayedRendering(vlVdpDevice *dev, struct pipe_surface *surface, struct u_rect *dirty_area);
+void vlVdpSave4DelayedRendering(vlVdpDevice *dev, VdpOutputSurface surface, struct vl_compositor_state *cstate);
+
 /* Internal function pointers */
 VdpGetErrorString vlVdpGetErrorString;
 VdpDeviceDestroy vlVdpDeviceDestroy;
-- 
1.7.5.4



More information about the mesa-dev mailing list