st/vdpau: avoid an unnessasary copy
Delay the actual mixer rendering until we really know which surface is the real destination. Signed-off-by: Christian König <deathsimple@vodafone.de>
This commit is contained in:
@@ -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;
|
||||
}
|
||||
|
||||
@@ -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);
|
||||
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);
|
||||
/* 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->sharpness.filter)
|
||||
vl_matrix_filter_render(vmixer->sharpness.filter,
|
||||
dst->sampler_view, dst->surface);
|
||||
}
|
||||
|
||||
return VDP_STATUS_OK;
|
||||
}
|
||||
|
||||
@@ -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;
|
||||
|
||||
@@ -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
|
||||
(
|
||||
|
||||
@@ -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;
|
||||
|
||||
Reference in New Issue
Block a user