*
**************************************************************************/
+#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"
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;
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;
}
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;
}
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);
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
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;