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:
@@ -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);
|
||||
|
||||
|
||||
Reference in New Issue
Block a user