From f8ac7e034803a1c873bf156c012fede6d2640097 Mon Sep 17 00:00:00 2001 From: =?utf8?q?Christian=20K=C3=B6nig?= Date: Sat, 25 Feb 2012 23:34:31 +0100 Subject: [PATCH] st/vdpau: avoid an unnessasary copy MIME-Version: 1.0 Content-Type: text/plain; charset=utf8 Content-Transfer-Encoding: 8bit Delay the actual mixer rendering until we really know which surface is the real destination. Signed-off-by: Christian König --- 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 d3b8946..d376817 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_layer_dst_area(&vmixer->cstate, layer++, 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 b2c8962..512ee94 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 55437d7..397bd37 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, 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, 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 1d776ab..1f896cd 100644 --- a/src/gallium/state_trackers/vdpau/vdpau_private.h +++ b/src/gallium/state_trackers/vdpau/vdpau_private.h @@ -290,6 +290,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 @@ -370,6 +375,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; -- 2.7.4