frontends/va: Implement format conversions in PutImage/GetImage

Reviewed-by: Thong Thai <thong.thai@amd.com>
Part-of: <https://gitlab.freedesktop.org/mesa/mesa/-/merge_requests/32919>
This commit is contained in:
David Rosca
2025-01-13 10:15:16 +01:00
committed by Marge Bot
parent b3e666248b
commit 762a86c937
+112 -31
View File
@@ -468,7 +468,7 @@ vlVaGetImage(VADriverContextP ctx, VASurfaceID surface, int x, int y,
unsigned int width, unsigned int height, VAImageID image)
{
vlVaDriver *drv;
vlVaSurface *surf;
vlVaSurface *surf, tmp_surf = {0};
vlVaBuffer *img_buf;
VAImage *vaimage;
struct pipe_resource *view_resources[VL_NUM_COMPONENTS];
@@ -519,9 +519,43 @@ vlVaGetImage(VADriverContextP ctx, VASurfaceID surface, int x, int y,
}
format = VaFourccToPipeFormat(vaimage->format.fourcc);
if (format != surf->buffer->buffer_format) {
if (format == PIPE_FORMAT_NONE) {
mtx_unlock(&drv->mutex);
return VA_STATUS_ERROR_INVALID_IMAGE_FORMAT;
return VA_STATUS_ERROR_UNSUPPORTED_RT_FORMAT;
}
if (format != surf->buffer->buffer_format) {
tmp_surf.templat.buffer_format = format;
tmp_surf.templat.width = vaimage->width;
tmp_surf.templat.height = vaimage->height;
VAStatus ret =
vlVaHandleSurfaceAllocate(drv, &tmp_surf, &tmp_surf.templat, NULL, 0);
if (ret != VA_STATUS_SUCCESS) {
mtx_unlock(&drv->mutex);
return VA_STATUS_ERROR_ALLOCATION_FAILED;
}
VARectangle src_rect = {
.x = x,
.y = y,
.width = width,
.height = height,
};
VARectangle dst_rect = {
.x = 0,
.y = 0,
.width = vaimage->width,
.height = vaimage->height,
};
VAProcPipelineParameterBuffer proc = {0};
ret = vlVaPostProcCompositor(drv, &src_rect, &dst_rect,
surf->buffer, tmp_surf.buffer,
VL_COMPOSITOR_NONE, &proc);
if (ret != VA_STATUS_SUCCESS) {
tmp_surf.buffer->destroy(tmp_surf.buffer);
mtx_unlock(&drv->mutex);
return ret;
}
surf = &tmp_surf;
}
memset(view_resources, 0, sizeof(view_resources));
@@ -562,11 +596,46 @@ vlVaGetImage(VADriverContextP ctx, VASurfaceID surface, int x, int y,
pipe_texture_unmap(drv->pipe, transfer);
}
}
if (tmp_surf.buffer)
tmp_surf.buffer->destroy(tmp_surf.buffer);
mtx_unlock(&drv->mutex);
return VA_STATUS_SUCCESS;
}
static void
vlVaUploadImage(vlVaDriver *drv, vlVaSurface *surf, vlVaBuffer *buf, VAImage *image)
{
uint8_t *data[3];
unsigned pitches[3];
struct pipe_resource *view_resources[VL_NUM_COMPONENTS] = {0};
surf->buffer->get_resources(surf->buffer, view_resources);
for (unsigned i = 0; i < MIN2(image->num_planes, 3); i++) {
data[i] = ((uint8_t*)buf->data) + image->offsets[i];
pitches[i] = image->pitches[i];
}
for (unsigned i = 0; i < image->num_planes; ++i) {
unsigned width, height;
struct pipe_resource *tex;
if (!view_resources[i]) continue;
tex = view_resources[i];
vlVaVideoSurfaceSize(surf, i, &width, &height);
for (unsigned j = 0; j < tex->array_size; ++j) {
struct pipe_box dst_box;
u_box_3d(0, 0, j, width, height, 1, &dst_box);
drv->pipe->texture_subdata(drv->pipe, tex, 0,
PIPE_MAP_WRITE, &dst_box,
data[i] + pitches[i] * j,
pitches[i] * view_resources[i]->array_size, 0);
}
}
}
VAStatus
vlVaPutImage(VADriverContextP ctx, VASurfaceID surface, VAImageID image,
int src_x, int src_y, unsigned int src_width, unsigned int src_height,
@@ -576,10 +645,7 @@ vlVaPutImage(VADriverContextP ctx, VASurfaceID surface, VAImageID image,
vlVaSurface *surf;
vlVaBuffer *img_buf;
VAImage *vaimage;
struct pipe_resource *view_resources[VL_NUM_COMPONENTS];
enum pipe_format format;
uint8_t *data[3];
unsigned pitches[3], i, j;
if (!ctx)
return VA_STATUS_ERROR_INVALID_CONTEXT;
@@ -613,36 +679,51 @@ vlVaPutImage(VADriverContextP ctx, VASurfaceID surface, VAImageID image,
}
format = VaFourccToPipeFormat(vaimage->format.fourcc);
if (format != surf->buffer->buffer_format) {
if (format == PIPE_FORMAT_NONE) {
mtx_unlock(&drv->mutex);
return VA_STATUS_ERROR_INVALID_IMAGE_FORMAT;
return VA_STATUS_ERROR_UNSUPPORTED_RT_FORMAT;
}
memset(view_resources, 0, sizeof(view_resources));
surf->buffer->get_resources(surf->buffer, view_resources);
for (i = 0; i < MIN2(vaimage->num_planes, 3); i++) {
data[i] = ((uint8_t*)img_buf->data) + vaimage->offsets[i];
pitches[i] = vaimage->pitches[i];
}
for (i = 0; i < vaimage->num_planes; ++i) {
unsigned width, height;
struct pipe_resource *tex;
if (!view_resources[i]) continue;
tex = view_resources[i];
vlVaVideoSurfaceSize(surf, i, &width, &height);
for (j = 0; j < tex->array_size; ++j) {
struct pipe_box dst_box;
u_box_3d(0, 0, j, width, height, 1, &dst_box);
drv->pipe->texture_subdata(drv->pipe, tex, 0,
PIPE_MAP_WRITE, &dst_box,
data[i] + pitches[i] * j,
pitches[i] * view_resources[i]->array_size, 0);
if (format != surf->buffer->buffer_format ||
dest_width != src_width || dest_height != src_height ||
src_x != 0 || dest_x != 0 || src_y != 0 || dest_y != 0) {
struct vlVaSurface tmp_surf = {
.templat = {
.buffer_format = format,
.width = vaimage->width,
.height = vaimage->height,
},
};
VAStatus ret =
vlVaHandleSurfaceAllocate(drv, &tmp_surf, &tmp_surf.templat, NULL, 0);
if (ret != VA_STATUS_SUCCESS) {
mtx_unlock(&drv->mutex);
return VA_STATUS_ERROR_ALLOCATION_FAILED;
}
vlVaUploadImage(drv, &tmp_surf, img_buf, vaimage);
VARectangle src_rect = {
.x = src_x,
.y = src_y,
.width = src_width,
.height = src_height,
};
VARectangle dst_rect = {
.x = dest_x,
.y = dest_y,
.width = dest_width,
.height = dest_height,
};
VAProcPipelineParameterBuffer proc = {0};
ret = vlVaPostProcCompositor(drv, &src_rect, &dst_rect,
tmp_surf.buffer, surf->buffer,
VL_COMPOSITOR_NONE, &proc);
tmp_surf.buffer->destroy(tmp_surf.buffer);
mtx_unlock(&drv->mutex);
return ret;
}
vlVaUploadImage(drv, surf, img_buf, vaimage);
drv->pipe->flush(drv->pipe, NULL, 0);
mtx_unlock(&drv->mutex);