summaryrefslogtreecommitdiffstats
path: root/src/gallium/state_trackers/va/image.c
diff options
context:
space:
mode:
Diffstat (limited to 'src/gallium/state_trackers/va/image.c')
-rw-r--r--src/gallium/state_trackers/va/image.c138
1 files changed, 125 insertions, 13 deletions
diff --git a/src/gallium/state_trackers/va/image.c b/src/gallium/state_trackers/va/image.c
index b37a9714437..c6d0c5abf65 100644
--- a/src/gallium/state_trackers/va/image.c
+++ b/src/gallium/state_trackers/va/image.c
@@ -37,14 +37,21 @@
#include "va_private.h"
-static const VAImageFormat formats[VL_VA_MAX_IMAGE_FORMATS] =
+static const VAImageFormat formats[] =
{
{VA_FOURCC('N','V','1','2')},
{VA_FOURCC('I','4','2','0')},
{VA_FOURCC('Y','V','1','2')},
{VA_FOURCC('Y','U','Y','V')},
{VA_FOURCC('U','Y','V','Y')},
- {VA_FOURCC('B','G','R','A')}
+ {.fourcc = VA_FOURCC('B','G','R','A'), .byte_order = VA_LSB_FIRST, 32, 32,
+ 0x00ff0000, 0x0000ff00, 0x000000ff, 0xff000000},
+ {.fourcc = VA_FOURCC('R','G','B','A'), .byte_order = VA_LSB_FIRST, 32, 32,
+ 0x000000ff, 0x0000ff00, 0x00ff0000, 0xff000000},
+ {.fourcc = VA_FOURCC('B','G','R','X'), .byte_order = VA_LSB_FIRST, 32, 24,
+ 0x00ff0000, 0x0000ff00, 0x000000ff, 0x00000000},
+ {.fourcc = VA_FOURCC('R','G','B','X'), .byte_order = VA_LSB_FIRST, 32, 24,
+ 0x000000ff, 0x0000ff00, 0x00ff0000, 0x00000000}
};
static void
@@ -72,6 +79,8 @@ vlVaQueryImageFormats(VADriverContextP ctx, VAImageFormat *format_list, int *num
enum pipe_format format;
int i;
+ STATIC_ASSERT(ARRAY_SIZE(formats) == VL_VA_MAX_IMAGE_FORMATS);
+
if (!ctx)
return VA_STATUS_ERROR_INVALID_CONTEXT;
@@ -80,8 +89,8 @@ vlVaQueryImageFormats(VADriverContextP ctx, VAImageFormat *format_list, int *num
*num_formats = 0;
pscreen = VL_VA_PSCREEN(ctx);
- for (i = 0; i < VL_VA_MAX_IMAGE_FORMATS; ++i) {
- format = YCbCrToPipe(formats[i].fourcc);
+ for (i = 0; i < ARRAY_SIZE(formats); ++i) {
+ format = VaFourccToPipeFormat(formats[i].fourcc);
if (pscreen->is_video_format_supported(pscreen, format,
PIPE_VIDEO_PROFILE_UNKNOWN,
PIPE_VIDEO_ENTRYPOINT_BITSTREAM))
@@ -149,6 +158,9 @@ vlVaCreateImage(VADriverContextP ctx, VAImageFormat *format, int width, int heig
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;
@@ -172,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
@@ -235,7 +334,7 @@ vlVaGetImage(VADriverContextP ctx, VASurfaceID surface, int x, int y,
if (!img_buf)
return VA_STATUS_ERROR_INVALID_BUFFER;
- format = YCbCrToPipe(vaimage->format.fourcc);
+ format = VaFourccToPipeFormat(vaimage->format.fourcc);
if (format == PIPE_FORMAT_NONE)
return VA_STATUS_ERROR_OPERATION_FAILED;
@@ -330,17 +429,30 @@ vlVaPutImage(VADriverContextP ctx, VASurfaceID surface, VAImageID image,
if (!img_buf)
return VA_STATUS_ERROR_INVALID_BUFFER;
- format = YCbCrToPipe(vaimage->format.fourcc);
+ 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;
- if (surf->buffer == NULL || format != surf->buffer->buffer_format) {
- if (surf->buffer)
- surf->buffer->destroy(surf->buffer);
+ if (format != surf->buffer->buffer_format) {
+ struct pipe_video_buffer *tmp_buf;
+ enum pipe_format old_surf_format = surf->templat.buffer_format;
+
surf->templat.buffer_format = format;
- surf->buffer = drv->pipe->create_video_buffer(drv->pipe, &surf->templat);
- if (!surf->buffer)
- return VA_STATUS_ERROR_ALLOCATION_FAILED;
+ tmp_buf = drv->pipe->create_video_buffer(drv->pipe, &surf->templat);
+
+ if (!tmp_buf) {
+ surf->templat.buffer_format = old_surf_format;
+ return VA_STATUS_ERROR_ALLOCATION_FAILED;
+ }
+
+ surf->buffer->destroy(surf->buffer);
+ surf->buffer = tmp_buf;
}
views = surf->buffer->get_sampler_view_planes(surf->buffer);