diff options
Diffstat (limited to 'src/gallium/state_trackers/va/surface.c')
-rw-r--r-- | src/gallium/state_trackers/va/surface.c | 130 |
1 files changed, 124 insertions, 6 deletions
diff --git a/src/gallium/state_trackers/va/surface.c b/src/gallium/state_trackers/va/surface.c index 58cd8ad772e..6f1ddf9a248 100644 --- a/src/gallium/state_trackers/va/surface.c +++ b/src/gallium/state_trackers/va/surface.c @@ -26,28 +26,92 @@ * **************************************************************************/ +#include "pipe/p_screen.h" + +#include "util/u_memory.h" +#include "util/u_handle_table.h" +#include "util/u_rect.h" + +#include "vl/vl_compositor.h" +#include "vl/vl_winsys.h" + #include "va_private.h" VAStatus vlVaCreateSurfaces(VADriverContextP ctx, int width, int height, int format, int num_surfaces, VASurfaceID *surfaces) { + struct pipe_video_buffer templat = {}; + struct pipe_screen *pscreen; + vlVaDriver *drv; + int i; + if (!ctx) return VA_STATUS_ERROR_INVALID_CONTEXT; if (!(width && height)) return VA_STATUS_ERROR_INVALID_IMAGE_FORMAT; - return VA_STATUS_ERROR_UNIMPLEMENTED; + drv = VL_VA_DRIVER(ctx); + pscreen = VL_VA_PSCREEN(ctx); + + templat.buffer_format = pscreen->get_video_param + ( + pscreen, + PIPE_VIDEO_PROFILE_UNKNOWN, + PIPE_VIDEO_ENTRYPOINT_BITSTREAM, + PIPE_VIDEO_CAP_PREFERED_FORMAT + ); + templat.chroma_format = ChromaToPipe(format); + templat.width = width; + templat.height = height; + templat.interlaced = pscreen->get_video_param + ( + pscreen, + PIPE_VIDEO_PROFILE_UNKNOWN, + PIPE_VIDEO_ENTRYPOINT_BITSTREAM, + PIPE_VIDEO_CAP_PREFERS_INTERLACED + ); + + for (i = 0; i < num_surfaces; ++i) { + vlVaSurface *surf = CALLOC(1, sizeof(vlVaSurface)); + if (!surf) + goto no_res; + + surf->templat = templat; + surfaces[i] = handle_table_add(drv->htab, surf); + } + + return VA_STATUS_SUCCESS; + +no_res: + if (i) + vlVaDestroySurfaces(ctx, surfaces, i); + + return VA_STATUS_ERROR_ALLOCATION_FAILED; } VAStatus vlVaDestroySurfaces(VADriverContextP ctx, VASurfaceID *surface_list, int num_surfaces) { + vlVaDriver *drv; + int i; + if (!ctx) return VA_STATUS_ERROR_INVALID_CONTEXT; - return VA_STATUS_ERROR_UNIMPLEMENTED; + drv = VL_VA_DRIVER(ctx); + for (i = 0; i < num_surfaces; ++i) { + vlVaSurface *surf = handle_table_get(drv->htab, surface_list[i]); + if (surf->buffer) + surf->buffer->destroy(surf->buffer); + if(surf->fence) + drv->pipe->screen->fence_reference(drv->pipe->screen, &surf->fence, NULL); + FREE(surf); + handle_table_remove(drv->htab, surface_list[i]); + } + + return VA_STATUS_SUCCESS; } VAStatus @@ -56,7 +120,7 @@ vlVaSyncSurface(VADriverContextP ctx, VASurfaceID render_target) if (!ctx) return VA_STATUS_ERROR_INVALID_CONTEXT; - return VA_STATUS_ERROR_UNIMPLEMENTED; + return VA_STATUS_SUCCESS; } VAStatus @@ -65,7 +129,7 @@ vlVaQuerySurfaceStatus(VADriverContextP ctx, VASurfaceID render_target, VASurfac if (!ctx) return VA_STATUS_ERROR_INVALID_CONTEXT; - return VA_STATUS_ERROR_UNIMPLEMENTED; + return VA_STATUS_SUCCESS; } VAStatus @@ -78,15 +142,69 @@ vlVaQuerySurfaceError(VADriverContextP ctx, VASurfaceID render_target, VAStatus } VAStatus -vlVaPutSurface(VADriverContextP ctx, VASurfaceID surface, void* draw, short srcx, short srcy, +vlVaPutSurface(VADriverContextP ctx, VASurfaceID surface_id, void* draw, short srcx, short srcy, unsigned short srcw, unsigned short srch, short destx, short desty, unsigned short destw, unsigned short desth, VARectangle *cliprects, unsigned int number_cliprects, unsigned int flags) { + vlVaDriver *drv; + vlVaSurface *surf; + struct pipe_screen *screen; + struct pipe_resource *tex; + struct pipe_surface surf_templ, *surf_draw; + struct u_rect src_rect, *dirty_area; + if (!ctx) return VA_STATUS_ERROR_INVALID_CONTEXT; - return VA_STATUS_ERROR_UNIMPLEMENTED; + drv = VL_VA_DRIVER(ctx); + surf = handle_table_get(drv->htab, surface_id); + if (!surf) + return VA_STATUS_ERROR_INVALID_SURFACE; + + screen = drv->pipe->screen; + + if(surf->fence) { + screen->fence_finish(screen, surf->fence, PIPE_TIMEOUT_INFINITE); + screen->fence_reference(screen, &surf->fence, NULL); + } + + tex = vl_screen_texture_from_drawable(drv->vscreen, (Drawable)draw); + if (!tex) + return VA_STATUS_ERROR_INVALID_DISPLAY; + + dirty_area = vl_screen_get_dirty_area(drv->vscreen); + + memset(&surf_templ, 0, sizeof(surf_templ)); + surf_templ.format = tex->format; + surf_draw = drv->pipe->create_surface(drv->pipe, tex, &surf_templ); + if (!surf_draw) { + pipe_resource_reference(&tex, NULL); + return VA_STATUS_ERROR_INVALID_DISPLAY; + } + + src_rect.x0 = srcx; + src_rect.y0 = srcy; + src_rect.x1 = srcw + srcx; + src_rect.y1 = srch + srcy; + + vl_compositor_clear_layers(&drv->cstate); + vl_compositor_set_buffer_layer(&drv->cstate, &drv->compositor, 0, surf->buffer, &src_rect, NULL, VL_COMPOSITOR_WEAVE); + vl_compositor_render(&drv->cstate, &drv->compositor, surf_draw, dirty_area, true); + + screen->flush_frontbuffer + ( + screen, tex, 0, 0, + vl_screen_get_private(drv->vscreen), NULL + ); + + screen->fence_reference(screen, &surf->fence, NULL); + drv->pipe->flush(drv->pipe, &surf->fence, 0); + + pipe_resource_reference(&tex, NULL); + pipe_surface_reference(&surf_draw, NULL); + + return VA_STATUS_SUCCESS; } VAStatus |