diff options
-rw-r--r-- | src/gallium/state_trackers/va/buffer.c | 43 | ||||
-rw-r--r-- | src/gallium/state_trackers/va/image.c | 95 | ||||
-rw-r--r-- | src/gallium/state_trackers/va/va_private.h | 5 |
3 files changed, 138 insertions, 5 deletions
diff --git a/src/gallium/state_trackers/va/buffer.c b/src/gallium/state_trackers/va/buffer.c index f5b9e814c3a..d3a7c5d6dc4 100644 --- a/src/gallium/state_trackers/va/buffer.c +++ b/src/gallium/state_trackers/va/buffer.c @@ -26,8 +26,11 @@ * **************************************************************************/ +#include "pipe/p_screen.h" #include "util/u_memory.h" #include "util/u_handle_table.h" +#include "util/u_transfer.h" +#include "vl/vl_winsys.h" #include "va_private.h" @@ -76,6 +79,9 @@ vlVaBufferSetNumElements(VADriverContextP ctx, VABufferID buf_id, if (!buf) return VA_STATUS_ERROR_INVALID_BUFFER; + if (buf->derived_surface.resource) + return VA_STATUS_ERROR_INVALID_BUFFER; + buf->data = REALLOC(buf->data, buf->size * buf->num_elements, buf->size * num_elements); buf->num_elements = num_elements; @@ -89,19 +95,34 @@ vlVaBufferSetNumElements(VADriverContextP ctx, VABufferID buf_id, VAStatus vlVaMapBuffer(VADriverContextP ctx, VABufferID buf_id, void **pbuff) { + vlVaDriver *drv; vlVaBuffer *buf; if (!ctx) return VA_STATUS_ERROR_INVALID_CONTEXT; + drv = VL_VA_DRIVER(ctx); + if (!drv) + return VA_STATUS_ERROR_INVALID_CONTEXT; + if (!pbuff) return VA_STATUS_ERROR_INVALID_PARAMETER; - buf = handle_table_get(VL_VA_DRIVER(ctx)->htab, buf_id); + buf = handle_table_get(drv->htab, buf_id); if (!buf) return VA_STATUS_ERROR_INVALID_BUFFER; - *pbuff = buf->data; + if (buf->derived_surface.resource) { + *pbuff = pipe_buffer_map(drv->pipe, buf->derived_surface.resource, + PIPE_TRANSFER_WRITE, + &buf->derived_surface.transfer); + + if (!buf->derived_surface.transfer || !*pbuff) + return VA_STATUS_ERROR_INVALID_BUFFER; + + } else { + *pbuff = buf->data; + } return VA_STATUS_SUCCESS; } @@ -109,16 +130,27 @@ vlVaMapBuffer(VADriverContextP ctx, VABufferID buf_id, void **pbuff) VAStatus vlVaUnmapBuffer(VADriverContextP ctx, VABufferID buf_id) { + vlVaDriver *drv; vlVaBuffer *buf; if (!ctx) return VA_STATUS_ERROR_INVALID_CONTEXT; - buf = handle_table_get(VL_VA_DRIVER(ctx)->htab, buf_id); + drv = VL_VA_DRIVER(ctx); + if (!drv) + return VA_STATUS_ERROR_INVALID_CONTEXT; + + buf = handle_table_get(drv->htab, buf_id); if (!buf) return VA_STATUS_ERROR_INVALID_BUFFER; - /* Nothing to do here */ + if (buf->derived_surface.resource) { + if (!buf->derived_surface.transfer) + return VA_STATUS_ERROR_INVALID_BUFFER; + + pipe_buffer_unmap(drv->pipe, buf->derived_surface.transfer); + buf->derived_surface.transfer = NULL; + } return VA_STATUS_SUCCESS; } @@ -135,6 +167,9 @@ vlVaDestroyBuffer(VADriverContextP ctx, VABufferID buf_id) if (!buf) return VA_STATUS_ERROR_INVALID_BUFFER; + if (buf->derived_surface.resource) + pipe_resource_reference(&buf->derived_surface.resource, NULL); + FREE(buf->data); FREE(buf); handle_table_remove(VL_VA_DRIVER(ctx)->htab, buf_id); diff --git a/src/gallium/state_trackers/va/image.c b/src/gallium/state_trackers/va/image.c index b0c720de107..c6d0c5abf65 100644 --- a/src/gallium/state_trackers/va/image.c +++ b/src/gallium/state_trackers/va/image.c @@ -184,10 +184,97 @@ vlVaCreateImage(VADriverContextP ctx, VAImageFormat *format, int width, int heig VAStatus vlVaDeriveImage(VADriverContextP ctx, VASurfaceID surface, VAImage *image) { + vlVaDriver *drv; + vlVaSurface *surf; + vlVaBuffer *img_buf; + VAImage *img; + struct pipe_surface **surfaces; + int w; + int h; + int i; + if (!ctx) return VA_STATUS_ERROR_INVALID_CONTEXT; - return VA_STATUS_ERROR_UNIMPLEMENTED; + drv = VL_VA_DRIVER(ctx); + + if (!drv) + return VA_STATUS_ERROR_INVALID_CONTEXT; + + surf = handle_table_get(drv->htab, surface); + + if (!surf || !surf->buffer || surf->buffer->interlaced) + return VA_STATUS_ERROR_INVALID_SURFACE; + + surfaces = surf->buffer->get_surfaces(surf->buffer); + if (!surfaces || !surfaces[0]->texture) + return VA_STATUS_ERROR_ALLOCATION_FAILED; + + img = CALLOC(1, sizeof(VAImage)); + if (!img) + return VA_STATUS_ERROR_ALLOCATION_FAILED; + + img->format.fourcc = PipeFormatToVaFourcc(surf->buffer->buffer_format); + img->buf = VA_INVALID_ID; + img->width = surf->buffer->width; + img->height = surf->buffer->height; + img->num_palette_entries = 0; + img->entry_bytes = 0; + w = align(surf->buffer->width, 2); + h = align(surf->buffer->height, 2); + + for (i = 0; i < ARRAY_SIZE(formats); ++i) { + if (img->format.fourcc == formats[i].fourcc) { + img->format = formats[i]; + break; + } + } + + switch (img->format.fourcc) { + case VA_FOURCC('U','Y','V','Y'): + case VA_FOURCC('Y','U','Y','V'): + img->num_planes = 1; + img->pitches[0] = w * 2; + img->offsets[0] = 0; + img->data_size = w * h * 2; + break; + + case VA_FOURCC('B','G','R','A'): + case VA_FOURCC('R','G','B','A'): + case VA_FOURCC('B','G','R','X'): + case VA_FOURCC('R','G','B','X'): + img->num_planes = 1; + img->pitches[0] = w * 4; + img->offsets[0] = 0; + img->data_size = w * h * 4; + break; + + default: + /* VaDeriveImage is designed for contiguous planes. */ + FREE(img); + return VA_STATUS_ERROR_INVALID_IMAGE_FORMAT; + } + + img_buf = CALLOC(1, sizeof(vlVaBuffer)); + if (!img_buf) { + FREE(img); + return VA_STATUS_ERROR_ALLOCATION_FAILED; + } + + img->image_id = handle_table_add(drv->htab, img); + + img_buf->type = VAImageBufferType; + img_buf->size = image->data_size; + img_buf->num_elements = 1; + img_buf->derived_surface.fence = surf->fence; + + pipe_resource_reference(&img_buf->derived_surface.resource, surfaces[0]->texture); + + img->buf = handle_table_add(VL_VA_DRIVER(ctx)->htab, img_buf); + + *image = *img; + + return VA_STATUS_SUCCESS; } VAStatus @@ -342,7 +429,13 @@ vlVaPutImage(VADriverContextP ctx, VASurfaceID surface, VAImageID image, if (!img_buf) return VA_STATUS_ERROR_INVALID_BUFFER; + if (img_buf->derived_surface.resource) { + /* Attempting to transfer derived image to surface */ + return VA_STATUS_ERROR_UNIMPLEMENTED; + } + format = VaFourccToPipeFormat(vaimage->format.fourcc); + if (format == PIPE_FORMAT_NONE) return VA_STATUS_ERROR_OPERATION_FAILED; diff --git a/src/gallium/state_trackers/va/va_private.h b/src/gallium/state_trackers/va/va_private.h index 60e966965e2..3ae51a766a0 100644 --- a/src/gallium/state_trackers/va/va_private.h +++ b/src/gallium/state_trackers/va/va_private.h @@ -233,6 +233,11 @@ typedef struct { unsigned int size; unsigned int num_elements; void *data; + struct { + struct pipe_resource *resource; + struct pipe_transfer *transfer; + struct pipe_fence_handle *fence; + } derived_surface; } vlVaBuffer; typedef struct { |