Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions NEWS
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@ Copyright (C) 2009-2023 Intel Corporation

Version 2.4.6 - XX.XX.XXXX (IRQL fork)

* Add support for VA_SURFACE_ATTRIB_MEM_TYPE_DRM_PRIME_2 in vaCreateSurfaces.
* Remove support for VA_SURFACE_ATTRIB_MEM_TYPE_DRM_PRIME_3 in vaExportSurfaceHandle.

It was using an ugly memory hack to work and there isn't much support or use case for this variant.
Expand Down
295 changes: 291 additions & 4 deletions src/i965_drv_video.c
Original file line number Diff line number Diff line change
Expand Up @@ -2047,6 +2047,266 @@ i965_surface_external_memory(VADriverContextP ctx,
return VA_STATUS_SUCCESS;
}

static VAStatus
i965_surface_external_memory2(VADriverContextP ctx,
struct object_surface *obj_surface,
int external_memory_type,
VADRMPRIMESurfaceDescriptor *memory_attribute,
int index)
{
assert(external_memory_type != I965_SURFACE_MEM_DRM_PRIME_2);

struct i965_driver_data *i965 = i965_driver_data(ctx);
unsigned int tiling, swizzle;

if (!memory_attribute ||
!memory_attribute->num_objects ||
index >= memory_attribute->num_objects)
return VA_STATUS_ERROR_INVALID_PARAMETER;

if (memory_attribute->num_objects > 1)
{
i965_log_error(ctx, "i965_surface_external_memory2: Driver does not support more than one object.");
return VA_STATUS_ERROR_INVALID_PARAMETER;
}

obj_surface->size = memory_attribute->objects[0].size;
obj_surface->bo = drm_intel_bo_gem_create_from_prime(i965->intel.bufmgr,
memory_attribute->objects[0].fd,
obj_surface->size);

if (!obj_surface->bo)
return VA_STATUS_ERROR_INVALID_PARAMETER;

dri_bo_get_tiling(obj_surface->bo, &tiling, &swizzle);

ASSERT_RET(obj_surface->orig_width == memory_attribute->width, VA_STATUS_ERROR_INVALID_PARAMETER);
ASSERT_RET(obj_surface->orig_height == memory_attribute->height, VA_STATUS_ERROR_INVALID_PARAMETER);

obj_surface->fourcc = memory_attribute->fourcc;
obj_surface->width = memory_attribute->width;

int bpp_1stplane = bpp_1stplane_by_fourcc(obj_surface->fourcc);
ASSERT_RET(IS_ALIGNED(obj_surface->width, 16), VA_STATUS_ERROR_INVALID_PARAMETER);
ASSERT_RET(obj_surface->width >= obj_surface->orig_width * bpp_1stplane, VA_STATUS_ERROR_INVALID_PARAMETER);

if (memory_attribute->num_layers == 1)
obj_surface->height = memory_attribute->objects[0].size / obj_surface->width;
else
obj_surface->height = memory_attribute->layers[1].offset[0] / obj_surface->width;

if (memory_attribute->num_layers > 1) {
ASSERT_RET(obj_surface->height >= obj_surface->orig_height, VA_STATUS_ERROR_INVALID_PARAMETER);
}

if (tiling) {
ASSERT_RET(IS_ALIGNED(obj_surface->width, 128), VA_STATUS_ERROR_INVALID_PARAMETER);

if (memory_attribute->num_layers > 1)
ASSERT_RET(IS_ALIGNED(obj_surface->height, 32), VA_STATUS_ERROR_INVALID_PARAMETER);
} else {
ASSERT_RET(IS_ALIGNED(obj_surface->width, i965->codec_info->min_linear_wpitch), VA_STATUS_ERROR_INVALID_PARAMETER);

if (memory_attribute->num_layers > 1)
ASSERT_RET(IS_ALIGNED(obj_surface->height, i965->codec_info->min_linear_hpitch), VA_STATUS_ERROR_INVALID_PARAMETER);
}

obj_surface->x_cb_offset = 0; /* X offset is always 0 */
obj_surface->x_cr_offset = 0;
if ((obj_surface->fourcc == VA_FOURCC_I420 ||
obj_surface->fourcc == VA_FOURCC_IYUV ||
obj_surface->fourcc == VA_FOURCC_I010 ||
obj_surface->fourcc == VA_FOURCC_YV12 ||
obj_surface->fourcc == VA_FOURCC_YV16) && tiling)
return VA_STATUS_ERROR_INVALID_PARAMETER;

switch (obj_surface->fourcc) {
case VA_FOURCC_NV12:
case VA_FOURCC_P010:
ASSERT_RET(memory_attribute->num_layers == 2, VA_STATUS_ERROR_INVALID_PARAMETER);
ASSERT_RET(memory_attribute->layers[0].pitch[0] == memory_attribute->layers[1].pitch[0], VA_STATUS_ERROR_INVALID_PARAMETER);

obj_surface->subsampling = SUBSAMPLE_YUV420;
obj_surface->y_cb_offset = obj_surface->height;
obj_surface->y_cr_offset = obj_surface->height;
obj_surface->cb_cr_width = ALIGN(obj_surface->orig_width, 2) / 2;
obj_surface->cb_cr_height = ALIGN(obj_surface->orig_height, 2) / 2;
obj_surface->cb_cr_pitch = memory_attribute->layers[1].pitch[0];
if (tiling)
ASSERT_RET(IS_ALIGNED(obj_surface->cb_cr_pitch, 128), VA_STATUS_ERROR_INVALID_PARAMETER);
else
ASSERT_RET(IS_ALIGNED(obj_surface->cb_cr_pitch, i965->codec_info->min_linear_wpitch), VA_STATUS_ERROR_INVALID_PARAMETER);

break;

case VA_FOURCC_YV12:
case VA_FOURCC_IMC1:
ASSERT_RET(memory_attribute->num_layers == 3, VA_STATUS_ERROR_INVALID_PARAMETER);
ASSERT_RET(memory_attribute->layers[1].pitch[0] == memory_attribute->layers[2].pitch[0], VA_STATUS_ERROR_INVALID_PARAMETER);

obj_surface->subsampling = SUBSAMPLE_YUV420;
obj_surface->y_cr_offset = obj_surface->height;
obj_surface->y_cb_offset = memory_attribute->layers[2].offset[0] / obj_surface->width;
obj_surface->cb_cr_width = ALIGN(obj_surface->orig_width, 2) / 2;
obj_surface->cb_cr_height = ALIGN(obj_surface->orig_height, 2) / 2;
obj_surface->cb_cr_pitch = memory_attribute->layers[1].pitch[0];

if (tiling)
ASSERT_RET(IS_ALIGNED(obj_surface->cb_cr_pitch, 128), VA_STATUS_ERROR_INVALID_PARAMETER);
else
ASSERT_RET(IS_ALIGNED(obj_surface->cb_cr_pitch, i965->codec_info->min_linear_wpitch), VA_STATUS_ERROR_INVALID_PARAMETER);

break;

case VA_FOURCC_I420:
case VA_FOURCC_IYUV:
case VA_FOURCC_IMC3:
case VA_FOURCC_I010:
ASSERT_RET(memory_attribute->num_layers == 3, VA_STATUS_ERROR_INVALID_PARAMETER);
ASSERT_RET(memory_attribute->layers[1].pitch[0] == memory_attribute->layers[2].pitch[0], VA_STATUS_ERROR_INVALID_PARAMETER);

obj_surface->subsampling = SUBSAMPLE_YUV420;
obj_surface->y_cb_offset = obj_surface->height;
obj_surface->y_cr_offset = memory_attribute->layers[2].offset[0] / obj_surface->width;
obj_surface->cb_cr_width = ALIGN(obj_surface->orig_width, 2) / 2;
obj_surface->cb_cr_height = ALIGN(obj_surface->orig_height, 2) / 2;
obj_surface->cb_cr_pitch = memory_attribute->layers[1].pitch[0];
if (tiling)
ASSERT_RET(IS_ALIGNED(obj_surface->cb_cr_pitch, 128), VA_STATUS_ERROR_INVALID_PARAMETER);
else
ASSERT_RET(IS_ALIGNED(obj_surface->cb_cr_pitch, i965->codec_info->min_linear_wpitch), VA_STATUS_ERROR_INVALID_PARAMETER);

break;

case VA_FOURCC_YUY2:
case VA_FOURCC_UYVY:
ASSERT_RET(memory_attribute->num_layers == 1, VA_STATUS_ERROR_INVALID_PARAMETER);

obj_surface->subsampling = SUBSAMPLE_YUV422H;
obj_surface->y_cb_offset = 0;
obj_surface->y_cr_offset = 0;
obj_surface->cb_cr_width = obj_surface->orig_width / 2;
obj_surface->cb_cr_height = obj_surface->orig_height;
obj_surface->cb_cr_pitch = memory_attribute->layers[0].pitch[0];

break;

case VA_FOURCC_RGBA:
case VA_FOURCC_RGBX:
case VA_FOURCC_BGRA:
case VA_FOURCC_BGRX:
case VA_FOURCC_ARGB:
ASSERT_RET(memory_attribute->num_layers == 1, VA_STATUS_ERROR_INVALID_PARAMETER);

obj_surface->subsampling = SUBSAMPLE_RGBX;
obj_surface->y_cb_offset = 0;
obj_surface->y_cr_offset = 0;
obj_surface->cb_cr_width = 0;
obj_surface->cb_cr_height = 0;
obj_surface->cb_cr_pitch = 0;

break;

case VA_FOURCC_Y800: /* monochrome surface */
ASSERT_RET(memory_attribute->num_layers == 1, VA_STATUS_ERROR_INVALID_PARAMETER);

obj_surface->subsampling = SUBSAMPLE_YUV400;
obj_surface->y_cb_offset = 0;
obj_surface->y_cr_offset = 0;
obj_surface->cb_cr_width = 0;
obj_surface->cb_cr_height = 0;
obj_surface->cb_cr_pitch = 0;

break;

case VA_FOURCC_411P:
ASSERT_RET(memory_attribute->num_layers == 3, VA_STATUS_ERROR_INVALID_PARAMETER);
ASSERT_RET(memory_attribute->layers[1].pitch[0] == memory_attribute->layers[2].pitch[0], VA_STATUS_ERROR_INVALID_PARAMETER);

obj_surface->subsampling = SUBSAMPLE_YUV411;
obj_surface->y_cb_offset = obj_surface->height;
obj_surface->y_cr_offset = memory_attribute->layers[2].offset[0] / obj_surface->width;
obj_surface->cb_cr_width = obj_surface->orig_width / 4;
obj_surface->cb_cr_height = obj_surface->orig_height;
obj_surface->cb_cr_pitch = memory_attribute->layers[1].pitch[0];
if (tiling)
ASSERT_RET(IS_ALIGNED(obj_surface->cb_cr_pitch, 128), VA_STATUS_ERROR_INVALID_PARAMETER);
else
ASSERT_RET(IS_ALIGNED(obj_surface->cb_cr_pitch, i965->codec_info->min_linear_wpitch), VA_STATUS_ERROR_INVALID_PARAMETER);
break;

case VA_FOURCC_422H:
ASSERT_RET(memory_attribute->num_layers == 3, VA_STATUS_ERROR_INVALID_PARAMETER);
ASSERT_RET(memory_attribute->layers[1].pitch[0] == memory_attribute->layers[2].pitch[0], VA_STATUS_ERROR_INVALID_PARAMETER);

obj_surface->subsampling = SUBSAMPLE_YUV422H;
obj_surface->y_cb_offset = obj_surface->height;
obj_surface->y_cr_offset = memory_attribute->layers[2].offset[0] / obj_surface->width;
obj_surface->cb_cr_width = ALIGN(obj_surface->orig_width, 2) / 2;
obj_surface->cb_cr_height = obj_surface->orig_height;
obj_surface->cb_cr_pitch = memory_attribute->layers[1].pitch[0];
if (tiling)
ASSERT_RET(IS_ALIGNED(obj_surface->cb_cr_pitch, 128), VA_STATUS_ERROR_INVALID_PARAMETER);
else
ASSERT_RET(IS_ALIGNED(obj_surface->cb_cr_pitch, i965->codec_info->min_linear_wpitch), VA_STATUS_ERROR_INVALID_PARAMETER);

break;

case VA_FOURCC_YV16:
ASSERT_RET(memory_attribute->num_layers == 3, VA_STATUS_ERROR_INVALID_PARAMETER);
ASSERT_RET(memory_attribute->layers[1].pitch[0] == memory_attribute->layers[2].pitch[0], VA_STATUS_ERROR_INVALID_PARAMETER);

obj_surface->subsampling = SUBSAMPLE_YUV422H;
obj_surface->y_cr_offset = memory_attribute->layers[1].offset[0] / obj_surface->width;
obj_surface->y_cb_offset = memory_attribute->layers[2].offset[0] / obj_surface->width;
obj_surface->cb_cr_width = ALIGN(obj_surface->orig_width, 2) / 2;
obj_surface->cb_cr_height = obj_surface->orig_height;
obj_surface->cb_cr_pitch = memory_attribute->layers[1].pitch[0];
ASSERT_RET(IS_ALIGNED(obj_surface->cb_cr_pitch, i965->codec_info->min_linear_wpitch), VA_STATUS_ERROR_INVALID_PARAMETER);

break;

case VA_FOURCC_422V:
ASSERT_RET(memory_attribute->num_layers == 3, VA_STATUS_ERROR_INVALID_PARAMETER);
ASSERT_RET(memory_attribute->layers[1].pitch[0] == memory_attribute->layers[2].pitch[0], VA_STATUS_ERROR_INVALID_PARAMETER);

obj_surface->subsampling = SUBSAMPLE_YUV422H;
obj_surface->y_cb_offset = obj_surface->height;
obj_surface->y_cr_offset = memory_attribute->layers[2].offset[0] / obj_surface->width;
obj_surface->cb_cr_width = obj_surface->orig_width;
obj_surface->cb_cr_height = ALIGN(obj_surface->orig_height, 2) / 2;
obj_surface->cb_cr_pitch = memory_attribute->layers[1].pitch[0];
if (tiling)
ASSERT_RET(IS_ALIGNED(obj_surface->cb_cr_pitch, 128), VA_STATUS_ERROR_INVALID_PARAMETER);
else
ASSERT_RET(IS_ALIGNED(obj_surface->cb_cr_pitch, i965->codec_info->min_linear_wpitch), VA_STATUS_ERROR_INVALID_PARAMETER);

break;

case VA_FOURCC_444P:
ASSERT_RET(memory_attribute->num_layers == 3, VA_STATUS_ERROR_INVALID_PARAMETER);
ASSERT_RET(memory_attribute->layers[1].pitch[0] == memory_attribute->layers[2].pitch[0], VA_STATUS_ERROR_INVALID_PARAMETER);

obj_surface->subsampling = SUBSAMPLE_YUV444;
obj_surface->y_cb_offset = obj_surface->height;
obj_surface->y_cr_offset = memory_attribute->layers[2].offset[0] / obj_surface->width;
obj_surface->cb_cr_width = obj_surface->orig_width;
obj_surface->cb_cr_height = obj_surface->orig_height;
obj_surface->cb_cr_pitch = memory_attribute->layers[1].pitch[0];
if (tiling)
ASSERT_RET(IS_ALIGNED(obj_surface->cb_cr_pitch, 128), VA_STATUS_ERROR_INVALID_PARAMETER);
else
ASSERT_RET(IS_ALIGNED(obj_surface->cb_cr_pitch, i965->codec_info->min_linear_wpitch), VA_STATUS_ERROR_INVALID_PARAMETER);

break;

default:
return VA_STATUS_ERROR_INVALID_PARAMETER;
}

return VA_STATUS_SUCCESS;
}

static VAStatus
i965_CreateSurfaces2(
VADriverContextP ctx,
Expand All @@ -2071,6 +2331,7 @@ i965_CreateSurfaces2(
int memory_type = I965_SURFACE_MEM_NATIVE; /* native */
int surface_usage_hint = VA_SURFACE_ATTRIB_USAGE_HINT_GENERIC;
VASurfaceAttribExternalBuffers *memory_attribute = NULL;
VADRMPRIMESurfaceDescriptor *prime_descriptor = NULL;

for (i = 0; i < num_attribs && attrib_list; i++) {
if ((attrib_list[i].type == VASurfaceAttribPixelFormat) &&
Expand All @@ -2096,7 +2357,11 @@ i965_CreateSurfaces2(
}
else if (attrib_list[i].value.value.i == VA_SURFACE_ATTRIB_MEM_TYPE_DRM_PRIME)
{
memory_type = I965_SURFACE_MEM_DRM_PRIME; /* drm prime fd */
memory_type = I965_SURFACE_MEM_DRM_PRIME; /* VASurfaceAttribExternalBuffers (using DRM PRIME fd) */
}
else if (attrib_list[i].value.value.i == VA_SURFACE_ATTRIB_MEM_TYPE_DRM_PRIME_2)
{
memory_type = I965_SURFACE_MEM_DRM_PRIME_2; /* VADRMPRIMESurfaceDescriptor (using DRM PRIME fd) */
}
else if (attrib_list[i].value.value.i == VA_SURFACE_ATTRIB_MEM_TYPE_VA)
{
Expand All @@ -2108,14 +2373,27 @@ i965_CreateSurfaces2(
}
else
{
i965_log_debug(ctx, "i965_CreateSurfaces2: Unknown VA_SURFACE_TYPE: %i\n", attrib_list[i].value.value.i);
if (attrib_list[i].value.value.i != VA_SURFACE_ATTRIB_MEM_TYPE_USER_PTR)
{
i965_log_debug(ctx, "i965_CreateSurfaces2: Unknown VA_SURFACE_TYPE: %i\n", attrib_list[i].value.value.i);
}

return VA_STATUS_ERROR_INVALID_PARAMETER;
}
}

if ((attrib_list[i].type == VASurfaceAttribExternalBufferDescriptor) &&
(attrib_list[i].flags == VA_SURFACE_ATTRIB_SETTABLE)) {
ASSERT_RET(attrib_list[i].value.type == VAGenericValueTypePointer, VA_STATUS_ERROR_INVALID_PARAMETER);
memory_attribute = (VASurfaceAttribExternalBuffers *)attrib_list[i].value.value.p;

if (memory_type == I965_SURFACE_MEM_DRM_PRIME_2)
{
prime_descriptor = (VADRMPRIMESurfaceDescriptor *)attrib_list[i].value.value.p;
}
else
{
memory_attribute = (VASurfaceAttribExternalBuffers *)attrib_list[i].value.value.p;
}
}
}

Expand Down Expand Up @@ -2247,6 +2525,14 @@ i965_CreateSurfaces2(
i);
break;

case I965_SURFACE_MEM_DRM_PRIME_2:
vaStatus = i965_surface_external_memory2(ctx,
obj_surface,
memory_type,
prime_descriptor,
i);
break;

default:
i965_log_debug(ctx, "i965_CreateSurfaces2: Unknown memory type %d, expect explosion?\n", memory_type);
break;
Expand Down Expand Up @@ -6448,7 +6734,8 @@ i965_QuerySurfaceAttributes(VADriverContextP ctx,
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_KERNEL_DRM |
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;
Expand Down
1 change: 1 addition & 0 deletions src/i965_drv_video.h
Original file line number Diff line number Diff line change
Expand Up @@ -676,6 +676,7 @@ extern VAStatus i965_CreateSurfaces(VADriverContextP ctx,
#define I965_SURFACE_MEM_NATIVE 0
#define I965_SURFACE_MEM_GEM_FLINK 1
#define I965_SURFACE_MEM_DRM_PRIME 2
#define I965_SURFACE_MEM_DRM_PRIME_2 3

void
i965_destroy_surface_storage(struct object_surface *obj_surface);
Expand Down