diff options
Diffstat (limited to 'src/gallium/state_trackers/va/image.c')
-rw-r--r-- | src/gallium/state_trackers/va/image.c | 138 |
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); |