aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorJulien Isorce <[email protected]>2015-10-30 11:42:52 +0000
committerChristian König <[email protected]>2015-10-30 13:21:11 +0100
commit802ba6f8655bf967299b027204ecdd5855050609 (patch)
treee79cde893485075a1720a75010a39b5dba42dfa5
parent5e763aaa21654d0591b7da14c573fc03d4a60205 (diff)
st/va: implement VaDeriveImage
And apply relatives change to: vlVaBufferSetNumElements vlVaCreateBuffer vlVaMapBuffer vlVaUnmapBuffer vlVaDestroyBuffer vlVaPutImage It is unfortunate that there is no proper va buffer type and struct for this. Only possible to use VAImageBufferType which is normally used for normal user data array. On of the consequences is that it is only possible VaDeriveImage is only useful on surfaces backed with contiguous planes. Implementation inspired from cgit.freedesktop.org/vaapi/intel-driver Signed-off-by: Julien Isorce <[email protected]> Reviewed-by: Emil Velikov <[email protected]> Reviewed-by: Christian König <[email protected]>
-rw-r--r--src/gallium/state_trackers/va/buffer.c43
-rw-r--r--src/gallium/state_trackers/va/image.c95
-rw-r--r--src/gallium/state_trackers/va/va_private.h5
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 {