gallium/va: Add support for PRIME_2 import.
That way we can actually import surfaces with modifiers & metadata planes. Tested with patches for ffmpeg to use this with kmsgrab & modifiers. For AMD & multiplanar formats we always have 1 format plane = 1 memory plane, even with modifiers. Intel (non Gallium) does have 1 format plane is 2 memory planes for some modifiers with NV12. Currently with Gallium we don't really have info about layer/plane ordering so this manually orders things so that they align with Intel. This shouldn't impact other drivers as without modifiers with metadata planes this should give equivalent behavior to the old import path. Reviewed-and-Tested-by: Leo Liu <leo.liu@amd.com> Part-of: <https://gitlab.freedesktop.org/mesa/mesa/-/merge_requests/10815>
This commit is contained in:

committed by
Marge Bot

parent
243475b96c
commit
fbf6511e35
@@ -503,7 +503,8 @@ vlVaQuerySurfaceAttributes(VADriverContextP ctx, VAConfigID config_id,
|
||||
attribs[i].value.type = VAGenericValueTypeInteger;
|
||||
attribs[i].flags = VA_SURFACE_ATTRIB_GETTABLE | VA_SURFACE_ATTRIB_SETTABLE;
|
||||
attribs[i].value.value.i = VA_SURFACE_ATTRIB_MEM_TYPE_VA |
|
||||
VA_SURFACE_ATTRIB_MEM_TYPE_DRM_PRIME;
|
||||
VA_SURFACE_ATTRIB_MEM_TYPE_DRM_PRIME |
|
||||
VA_SURFACE_ATTRIB_MEM_TYPE_DRM_PRIME_2;
|
||||
i++;
|
||||
|
||||
attribs[i].type = VASurfaceAttribExternalBufferDescriptor;
|
||||
@@ -655,6 +656,127 @@ fail:
|
||||
return result;
|
||||
}
|
||||
|
||||
static VAStatus
|
||||
surface_from_prime_2(VADriverContextP ctx, vlVaSurface *surface,
|
||||
VADRMPRIMESurfaceDescriptor *desc,
|
||||
struct pipe_video_buffer *templat)
|
||||
{
|
||||
vlVaDriver *drv;
|
||||
struct pipe_screen *pscreen;
|
||||
struct pipe_resource res_templ;
|
||||
struct winsys_handle whandle;
|
||||
struct pipe_resource *resources[VL_NUM_COMPONENTS];
|
||||
enum pipe_format resource_formats[VL_NUM_COMPONENTS];
|
||||
unsigned num_format_planes, expected_planes, input_planes, plane;
|
||||
VAStatus result;
|
||||
|
||||
num_format_planes = util_format_get_num_planes(templat->buffer_format);
|
||||
pscreen = VL_VA_PSCREEN(ctx);
|
||||
drv = VL_VA_DRIVER(ctx);
|
||||
|
||||
if (!desc || desc->num_layers >= 4 ||desc->num_objects == 0)
|
||||
return VA_STATUS_ERROR_INVALID_PARAMETER;
|
||||
|
||||
if (surface->templat.width != desc->width ||
|
||||
surface->templat.height != desc->height ||
|
||||
desc->num_layers < 1)
|
||||
return VA_STATUS_ERROR_INVALID_PARAMETER;
|
||||
|
||||
if (desc->num_layers != num_format_planes)
|
||||
return VA_STATUS_ERROR_INVALID_PARAMETER;
|
||||
|
||||
input_planes = 0;
|
||||
for (unsigned i = 0; i < desc->num_layers; ++i) {
|
||||
if (desc->layers[i].num_planes == 0 || desc->layers[i].num_planes > 4)
|
||||
return VA_STATUS_ERROR_INVALID_PARAMETER;
|
||||
|
||||
for (unsigned j = 0; j < desc->layers[i].num_planes; ++j)
|
||||
if (desc->layers[i].object_index[j] >= desc->num_objects)
|
||||
return VA_STATUS_ERROR_INVALID_PARAMETER;
|
||||
|
||||
input_planes += desc->layers[i].num_planes;
|
||||
}
|
||||
|
||||
expected_planes = num_format_planes;
|
||||
if (desc->objects[0].drm_format_modifier != DRM_FORMAT_MOD_INVALID &&
|
||||
pscreen->is_dmabuf_modifier_supported &&
|
||||
pscreen->is_dmabuf_modifier_supported(pscreen, desc->objects[0].drm_format_modifier,
|
||||
templat->buffer_format, NULL) &&
|
||||
pscreen->get_dmabuf_modifier_planes)
|
||||
expected_planes = pscreen->get_dmabuf_modifier_planes(pscreen, desc->objects[0].drm_format_modifier,
|
||||
templat->buffer_format);
|
||||
|
||||
if (input_planes != expected_planes)
|
||||
return VA_STATUS_ERROR_INVALID_PARAMETER;
|
||||
|
||||
vl_get_video_buffer_formats(pscreen, templat->buffer_format, resource_formats);
|
||||
|
||||
memset(&res_templ, 0, sizeof(res_templ));
|
||||
res_templ.target = PIPE_TEXTURE_2D;
|
||||
res_templ.last_level = 0;
|
||||
res_templ.depth0 = 1;
|
||||
res_templ.array_size = 1;
|
||||
res_templ.width0 = desc->width;
|
||||
res_templ.height0 = desc->height;
|
||||
res_templ.bind = PIPE_BIND_SAMPLER_VIEW;
|
||||
res_templ.usage = PIPE_USAGE_DEFAULT;
|
||||
res_templ.format = templat->buffer_format;
|
||||
|
||||
memset(&whandle, 0, sizeof(struct winsys_handle));
|
||||
whandle.type = WINSYS_HANDLE_TYPE_FD;
|
||||
whandle.format = templat->buffer_format;
|
||||
whandle.modifier = desc->objects[0].drm_format_modifier;
|
||||
|
||||
// Create a resource for each plane.
|
||||
memset(resources, 0, sizeof resources);
|
||||
|
||||
/* This does a backwards walk to set the next pointers. It interleaves so
|
||||
* that the main planes always come first and then the first compression metadata
|
||||
* plane of each main plane etc. */
|
||||
plane = input_planes - 1;
|
||||
for (int layer_plane = 3; layer_plane >= 0; --layer_plane) {
|
||||
for (int layer = desc->num_layers - 1; layer >= 0; --layer) {
|
||||
if (layer_plane >= desc->layers[layer].num_planes)
|
||||
continue;
|
||||
|
||||
if (plane < num_format_planes)
|
||||
res_templ.format = resource_formats[plane];
|
||||
|
||||
whandle.stride = desc->layers[layer].pitch[layer_plane];
|
||||
whandle.offset = desc->layers[layer].offset[layer_plane];
|
||||
whandle.handle = desc->objects[desc->layers[layer].object_index[layer_plane]].fd;
|
||||
whandle.plane = plane;
|
||||
|
||||
resources[plane] = pscreen->resource_from_handle(pscreen, &res_templ, &whandle,
|
||||
PIPE_HANDLE_USAGE_FRAMEBUFFER_WRITE);
|
||||
if (!resources[plane]) {
|
||||
result = VA_STATUS_ERROR_ALLOCATION_FAILED;
|
||||
goto fail;
|
||||
}
|
||||
|
||||
/* After the resource gets created the resource now owns the next reference. */
|
||||
res_templ.next = NULL;
|
||||
|
||||
if (plane)
|
||||
pipe_resource_reference(&res_templ.next, resources[plane]);
|
||||
--plane;
|
||||
}
|
||||
}
|
||||
|
||||
surface->buffer = vl_video_buffer_create_ex2(drv->pipe, templat, resources);
|
||||
if (!surface->buffer) {
|
||||
result = VA_STATUS_ERROR_ALLOCATION_FAILED;
|
||||
goto fail;
|
||||
}
|
||||
return VA_STATUS_SUCCESS;
|
||||
|
||||
fail:
|
||||
pipe_resource_reference(&res_templ.next, NULL);
|
||||
for (int i = 0; i < VL_NUM_COMPONENTS; i++)
|
||||
pipe_resource_reference(&resources[i], NULL);
|
||||
return result;
|
||||
}
|
||||
|
||||
VAStatus
|
||||
vlVaHandleSurfaceAllocate(vlVaDriver *drv, vlVaSurface *surface,
|
||||
struct pipe_video_buffer *templat,
|
||||
@@ -704,6 +826,7 @@ vlVaCreateSurfaces2(VADriverContextP ctx, unsigned int format,
|
||||
{
|
||||
vlVaDriver *drv;
|
||||
VASurfaceAttribExternalBuffers *memory_attribute;
|
||||
VADRMPRIMESurfaceDescriptor *prime_desc;
|
||||
#ifdef HAVE_VA_SURFACE_ATTRIB_DRM_FORMAT_MODIFIERS
|
||||
const VADRMFormatModifierList *modifier_list;
|
||||
#endif
|
||||
@@ -736,6 +859,7 @@ vlVaCreateSurfaces2(VADriverContextP ctx, unsigned int format,
|
||||
|
||||
/* Default. */
|
||||
memory_attribute = NULL;
|
||||
prime_desc = NULL;
|
||||
memory_type = VA_SURFACE_ATTRIB_MEM_TYPE_VA;
|
||||
expected_fourcc = 0;
|
||||
modifiers = NULL;
|
||||
@@ -758,6 +882,7 @@ vlVaCreateSurfaces2(VADriverContextP ctx, unsigned int format,
|
||||
switch (attrib_list[i].value.value.i) {
|
||||
case VA_SURFACE_ATTRIB_MEM_TYPE_VA:
|
||||
case VA_SURFACE_ATTRIB_MEM_TYPE_DRM_PRIME:
|
||||
case VA_SURFACE_ATTRIB_MEM_TYPE_DRM_PRIME_2:
|
||||
memory_type = attrib_list[i].value.value.i;
|
||||
break;
|
||||
default:
|
||||
@@ -767,7 +892,10 @@ vlVaCreateSurfaces2(VADriverContextP ctx, unsigned int format,
|
||||
case VASurfaceAttribExternalBufferDescriptor:
|
||||
if (attrib_list[i].value.type != VAGenericValueTypePointer)
|
||||
return VA_STATUS_ERROR_INVALID_PARAMETER;
|
||||
memory_attribute = (VASurfaceAttribExternalBuffers *)attrib_list[i].value.value.p;
|
||||
if (memory_type == VA_SURFACE_ATTRIB_MEM_TYPE_DRM_PRIME_2)
|
||||
prime_desc = (VADRMPRIMESurfaceDescriptor *)attrib_list[i].value.value.p;
|
||||
else
|
||||
memory_attribute = (VASurfaceAttribExternalBuffers *)attrib_list[i].value.value.p;
|
||||
break;
|
||||
#ifdef HAVE_VA_SURFACE_ATTRIB_DRM_FORMAT_MODIFIERS
|
||||
case VASurfaceAttribDRMFormatModifiers:
|
||||
@@ -809,6 +937,12 @@ vlVaCreateSurfaces2(VADriverContextP ctx, unsigned int format,
|
||||
|
||||
expected_fourcc = memory_attribute->pixel_format;
|
||||
break;
|
||||
case VA_SURFACE_ATTRIB_MEM_TYPE_DRM_PRIME_2:
|
||||
if (!prime_desc)
|
||||
return VA_STATUS_ERROR_INVALID_PARAMETER;
|
||||
|
||||
expected_fourcc = prime_desc->fourcc;
|
||||
break;
|
||||
default:
|
||||
assert(0);
|
||||
}
|
||||
@@ -878,6 +1012,11 @@ vlVaCreateSurfaces2(VADriverContextP ctx, unsigned int format,
|
||||
goto free_surf;
|
||||
break;
|
||||
|
||||
case VA_SURFACE_ATTRIB_MEM_TYPE_DRM_PRIME_2:
|
||||
vaStatus = surface_from_prime_2(ctx, surf, prime_desc, &templat);
|
||||
if (vaStatus != VA_STATUS_SUCCESS)
|
||||
goto free_surf;
|
||||
break;
|
||||
default:
|
||||
assert(0);
|
||||
}
|
||||
|
Reference in New Issue
Block a user