A new Linux interface for media sharing to exchange format info

vaExportSurfaceHandle() with DRM_PRIME_2 uses VADRMPRIMESurfaceDescriptor,
where the drm_format_modifier can help passing tiling/compression info.

Related-To: NEO-4452

Change-Id: I1c25df53a6fd185c949156ea099abc7c0b3e11d6
Signed-off-by: Slawomir Milczarek <slawomir.milczarek@intel.com>
This commit is contained in:
Slawomir Milczarek
2020-05-04 21:37:54 +02:00
committed by sys_ocldev
parent 35d9b4365b
commit a5793fc654
6 changed files with 144 additions and 10 deletions

View File

@ -14,6 +14,7 @@ typedef int (*VADisplayIsValidPFN)(VADisplay vaDisplay);
typedef VAStatus (*VADeriveImagePFN)(VADisplay vaDisplay, VASurfaceID vaSurface, VAImage *vaImage);
typedef VAStatus (*VADestroyImagePFN)(VADisplay vaDisplay, VAImageID vaImageId);
typedef VAStatus (*VAExtGetSurfaceHandlePFN)(VADisplay vaDisplay, VASurfaceID *vaSurface, unsigned int *handleId);
typedef VAStatus (*VAExportSurfaceHandlePFN)(VADisplay vaDisplay, VASurfaceID vaSurface, uint32_t memType, uint32_t flags, void *descriptor);
typedef VAStatus (*VASyncSurfacePFN)(VADisplay vaDisplay, VASurfaceID vaSurface);
typedef void *(*VAGetLibFuncPFN)(VADisplay vaDisplay, const char *func);
typedef VAStatus (*VAQueryImageFormatsPFN)(VADisplay vaDisplay, VAImageFormat *formatList, int *numFormats);

View File

@ -52,6 +52,7 @@ void VASharingFunctions::initFunctions() {
vaSyncSurfacePFN = reinterpret_cast<VASyncSurfacePFN>(fdlsym(libHandle, "vaSyncSurface"));
vaGetLibFuncPFN = reinterpret_cast<VAGetLibFuncPFN>(fdlsym(libHandle, "vaGetLibFunc"));
vaExtGetSurfaceHandlePFN = reinterpret_cast<VAExtGetSurfaceHandlePFN>(getLibFunc("DdiMedia_ExtGetSurfaceHandle"));
vaExportSurfaceHandlePFN = reinterpret_cast<VAExportSurfaceHandlePFN>(fdlsym(libHandle, "vaExportSurfaceHandle"));
vaQueryImageFormatsPFN = reinterpret_cast<VAQueryImageFormatsPFN>(fdlsym(libHandle, "vaQueryImageFormats"));
vaMaxNumImageFormatsPFN = reinterpret_cast<VAMaxNumImageFormatsPFN>(fdlsym(libHandle, "vaMaxNumImageFormats"));
@ -62,6 +63,7 @@ void VASharingFunctions::initFunctions() {
vaSyncSurfacePFN = nullptr;
vaGetLibFuncPFN = nullptr;
vaExtGetSurfaceHandlePFN = nullptr;
vaExportSurfaceHandlePFN = nullptr;
vaQueryImageFormatsPFN = nullptr;
vaMaxNumImageFormatsPFN = nullptr;
}

View File

@ -40,6 +40,10 @@ class VASharingFunctions : public SharingFunctions {
return vaExtGetSurfaceHandlePFN(vaDisplay, vaSurface, handleId);
}
MOCKABLE_VIRTUAL VAStatus exportSurfaceHandle(VASurfaceID vaSurface, uint32_t memType, uint32_t flags, void *descriptor) {
return vaExportSurfaceHandlePFN(vaDisplay, vaSurface, memType, flags, descriptor);
}
MOCKABLE_VIRTUAL VAStatus syncSurface(VASurfaceID vaSurface) {
return vaSyncSurfacePFN(vaDisplay, vaSurface);
}
@ -85,6 +89,7 @@ class VASharingFunctions : public SharingFunctions {
VADestroyImagePFN vaDestroyImagePFN;
VASyncSurfacePFN vaSyncSurfacePFN;
VAExtGetSurfaceHandlePFN vaExtGetSurfaceHandlePFN;
VAExportSurfaceHandlePFN vaExportSurfaceHandlePFN;
VAGetLibFuncPFN vaGetLibFuncPFN;
VAQueryImageFormatsPFN vaQueryImageFormatsPFN;
VAMaxNumImageFormatsPFN vaMaxNumImageFormatsPFN;

View File

@ -15,6 +15,9 @@
#include "opencl/source/context/context.h"
#include "opencl/source/mem_obj/image.h"
#include <drm/drm_fourcc.h>
#include <va/va_drmcommon.h>
namespace NEO {
Image *VASurface::createSharedVaSurface(Context *context, VASharingFunctions *sharingFunctions,
cl_mem_flags flags, cl_mem_flags_intel flagsIntel, VASurfaceID *surface,
@ -23,6 +26,7 @@ Image *VASurface::createSharedVaSurface(Context *context, VASharingFunctions *sh
auto memoryManager = context->getMemoryManager();
unsigned int sharedHandle = 0;
VADRMPRIMESurfaceDescriptor vaDrmPrimeSurfaceDesc = {};
VAImage vaImage = {};
cl_image_desc imgDesc = {};
cl_image_format gmmImgFormat = {CL_NV12_INTEL, CL_UNORM_INT8};
@ -31,13 +35,41 @@ Image *VASurface::createSharedVaSurface(Context *context, VASharingFunctions *sh
ImageInfo imgInfo = {};
VAImageID imageId = 0;
McsSurfaceInfo mcsSurfaceInfo = {};
VAStatus vaStatus;
uint32_t imageFourcc = 0;
size_t imageOffset = 0;
size_t imagePitch = 0;
vaStatus = sharingFunctions->exportSurfaceHandle(*surface,
VA_SURFACE_ATTRIB_MEM_TYPE_DRM_PRIME_2,
VA_EXPORT_SURFACE_READ_WRITE | VA_EXPORT_SURFACE_SEPARATE_LAYERS,
&vaDrmPrimeSurfaceDesc);
if (VA_STATUS_SUCCESS == vaStatus) {
imageId = VA_INVALID_ID;
imgDesc.image_width = vaDrmPrimeSurfaceDesc.width;
imgDesc.image_height = vaDrmPrimeSurfaceDesc.height;
imageFourcc = vaDrmPrimeSurfaceDesc.fourcc;
if (plane == 1) {
imageOffset = vaDrmPrimeSurfaceDesc.layers[1].offset[0];
imagePitch = vaDrmPrimeSurfaceDesc.layers[1].pitch[0];
}
imgInfo.linearStorage = DRM_FORMAT_MOD_LINEAR == vaDrmPrimeSurfaceDesc.objects[0].drm_format_modifier;
sharedHandle = vaDrmPrimeSurfaceDesc.objects[0].fd;
} else {
sharingFunctions->deriveImage(*surface, &vaImage);
imageId = vaImage.image_id;
imgDesc.image_width = vaImage.width;
imgDesc.image_height = vaImage.height;
imageFourcc = vaImage.format.fourcc;
if (plane == 1) {
imageOffset = vaImage.offsets[1];
imagePitch = vaImage.pitches[0];
}
imgInfo.linearStorage = false;
sharingFunctions->extGetSurfaceHandle(surface, &sharedHandle);
}
imgDesc.image_type = CL_MEM_OBJECT_IMAGE2D;
imgInfo.imgDesc = Image::convertDescriptor(imgDesc);
@ -53,16 +85,15 @@ Image *VASurface::createSharedVaSurface(Context *context, VASharingFunctions *sh
auto gmmSurfaceFormat = Image::getSurfaceFormatFromTable(flags, &gmmImgFormat, context->getDevice(0)->getHardwareInfo().capabilityTable.supportsOcl21Features); //vaImage.format.fourcc == VA_FOURCC_NV12
if (DebugManager.flags.EnableExtendedVaFormats.get() && vaImage.format.fourcc == VA_FOURCC_P010) {
if (DebugManager.flags.EnableExtendedVaFormats.get() && imageFourcc == VA_FOURCC_P010) {
channelType = CL_UNORM_INT16;
gmmSurfaceFormat = getExtendedSurfaceFormatInfo(vaImage.format.fourcc);
gmmSurfaceFormat = getExtendedSurfaceFormatInfo(imageFourcc);
}
imgInfo.surfaceFormat = &gmmSurfaceFormat->surfaceFormat;
cl_image_format imgFormat = {channelOrder, channelType};
auto imgSurfaceFormat = Image::getSurfaceFormatFromTable(flags, &imgFormat, context->getDevice(0)->getHardwareInfo().capabilityTable.supportsOcl21Features);
sharingFunctions->extGetSurfaceHandle(surface, &sharedHandle);
AllocationProperties properties(context->getDevice(0)->getRootDeviceIndex(),
false, // allocateMemory
imgInfo, GraphicsAllocation::AllocationType::SHARED_IMAGE,
@ -77,13 +108,15 @@ Image *VASurface::createSharedVaSurface(Context *context, VASharingFunctions *sh
if (plane == 1) {
imgDesc.image_width /= 2;
imgDesc.image_height /= 2;
imgInfo.offset = vaImage.offsets[1];
imgInfo.offset = imageOffset;
imgInfo.yOffset = 0;
imgInfo.xOffset = 0;
imgInfo.yOffsetForUVPlane = static_cast<uint32_t>(imgInfo.offset / vaImage.pitches[0]);
imgInfo.yOffsetForUVPlane = static_cast<uint32_t>(imageOffset / imagePitch);
}
imgInfo.imgDesc = Image::convertDescriptor(imgDesc);
sharingFunctions->destroyImage(vaImage.image_id);
if (VA_INVALID_ID != imageId) {
sharingFunctions->destroyImage(imageId);
}
auto vaSurface = new VASurface(sharingFunctions, imageId, plane, surface, context->getInteropUserSyncEnabled());

View File

@ -10,6 +10,9 @@
#include "opencl/source/sharings/va/va_sharing.h"
#include <drm/drm_fourcc.h>
#include <va/va_drmcommon.h>
namespace NEO {
class VASharingFunctionsMock : public VASharingFunctions {
@ -28,9 +31,29 @@ class VASharingFunctionsMock : public VASharingFunctions {
bool destroyImageCalled = false;
bool syncSurfaceCalled = false;
bool extGetSurfaceHandleCalled = false;
bool exportSurfaceHandleCalled = false;
osHandle acquiredVaHandle = 0;
bool haveExportSurfaceHandle = false;
uint32_t receivedSurfaceMemType = 0;
uint32_t receivedSurfaceFlags = 0;
VADRMPRIMESurfaceDescriptor mockVaSurfaceDesc{
VA_FOURCC_NV12,
256,
256,
1,
{{8, 98304, I915_FORMAT_MOD_Y_TILED}, {}, {}, {}},
2,
{
{DRM_FORMAT_R8, 1, {}, {0, 0, 0, 0}, {256, 0, 0, 0}},
{DRM_FORMAT_GR88, 1, {}, {65536, 0, 0, 0}, {256, 0, 0, 0}},
{0, 0, {}, {0, 0, 0, 0}, {0, 0, 0, 0}},
{0, 0, {}, {0, 0, 0, 0}, {0, 0, 0, 0}},
}};
VASharingFunctionsMock(VADisplay vaDisplay) : VASharingFunctions(vaDisplay) {}
VASharingFunctionsMock() : VASharingFunctionsMock(nullptr){};
@ -68,6 +91,20 @@ class VASharingFunctionsMock : public VASharingFunctions {
return VA_STATUS_SUCCESS;
}
VAStatus exportSurfaceHandle(VASurfaceID vaSurface, uint32_t memType, uint32_t flags, void *descriptor) override {
exportSurfaceHandleCalled = true;
receivedSurfaceMemType = memType;
receivedSurfaceFlags = flags;
if (haveExportSurfaceHandle) {
if (memType != VA_SURFACE_ATTRIB_MEM_TYPE_DRM_PRIME_2) {
return VA_STATUS_ERROR_UNSUPPORTED_MEMORY_TYPE;
}
*(static_cast<VADRMPRIMESurfaceDescriptor *>(descriptor)) = mockVaSurfaceDesc;
return VA_STATUS_SUCCESS;
}
return VA_STATUS_ERROR_UNIMPLEMENTED;
}
VAStatus syncSurface(VASurfaceID vaSurface) override {
syncSurfaceCalled = true;
return VA_STATUS_SUCCESS;

View File

@ -75,6 +75,7 @@ TEST(VaSharingTest, givenVASharingFunctionsObjectWhenFunctionsAreCalledThenCalls
unsigned int handle = 0u;
VASurfaceID vaSurfaceId = 0u;
VAImage vaImage = {};
VADRMPRIMESurfaceDescriptor vaDrmPrimeSurfaceDesc = {};
class VASharingFunctionsGlobalFunctionPointersMock : public VASharingFunctions {
public:
@ -88,6 +89,7 @@ TEST(VaSharingTest, givenVASharingFunctionsObjectWhenFunctionsAreCalledThenCalls
bool vaSyncSurfaceCalled = false;
bool vaGetLibFuncCalled = false;
bool vaExtGetSurfaceHandleCalled = false;
bool vaExportSurfaceHandleCalled = false;
bool vaQueryImageFormatsCalled = false;
bool vaMaxNumImageFormatsCalled = false;
@ -98,6 +100,7 @@ TEST(VaSharingTest, givenVASharingFunctionsObjectWhenFunctionsAreCalledThenCalls
vaSyncSurfacePFN = mockVaSyncSurface;
vaGetLibFuncPFN = mockVaGetLibFunc;
vaExtGetSurfaceHandlePFN = mockExtGetSurfaceHandle;
vaExportSurfaceHandlePFN = mockExportSurfaceHandle;
vaQueryImageFormatsPFN = mockVaQueryImageFormats;
vaMaxNumImageFormatsPFN = mockVaMaxNumImageFormats;
}
@ -143,6 +146,11 @@ TEST(VaSharingTest, givenVASharingFunctionsObjectWhenFunctionsAreCalledThenCalls
return VA_STATUS_SUCCESS;
};
static VAStatus mockExportSurfaceHandle(VADisplay vaDisplay, VASurfaceID vaSurface, uint32_t memType, uint32_t flags, void *descriptor) {
getInstance(false)->vaExportSurfaceHandleCalled = true;
return VA_STATUS_SUCCESS;
};
static VAStatus mockVaQueryImageFormats(VADisplay vaDisplay, VAImageFormat *formatList, int *numFormats) {
getInstance(false)->vaQueryImageFormatsCalled = true;
return VA_STATUS_SUCCESS;
@ -160,6 +168,7 @@ TEST(VaSharingTest, givenVASharingFunctionsObjectWhenFunctionsAreCalledThenCalls
EXPECT_EQ(0, vaSharingFunctions->syncSurface(vaSurfaceId));
EXPECT_TRUE(nullptr == vaSharingFunctions->getLibFunc("funcName"));
EXPECT_EQ(0, vaSharingFunctions->extGetSurfaceHandle(&vaSurfaceId, &handle));
EXPECT_EQ(0, vaSharingFunctions->exportSurfaceHandle(vaSurfaceId, VA_SURFACE_ATTRIB_MEM_TYPE_DRM_PRIME_2, 0, &vaDrmPrimeSurfaceDesc));
int numFormats = 0;
EXPECT_EQ(0, vaSharingFunctions->queryImageFormats(VADisplay(1), nullptr, &numFormats));
EXPECT_EQ(0, vaSharingFunctions->maxNumImageFormats(VADisplay(1)));
@ -172,12 +181,59 @@ TEST(VaSharingTest, givenVASharingFunctionsObjectWhenFunctionsAreCalledThenCalls
EXPECT_TRUE(VASharingFunctionsGlobalFunctionPointersMock::getInstance(false)->vaSyncSurfaceCalled);
EXPECT_TRUE(VASharingFunctionsGlobalFunctionPointersMock::getInstance(false)->vaGetLibFuncCalled);
EXPECT_TRUE(VASharingFunctionsGlobalFunctionPointersMock::getInstance(false)->vaExtGetSurfaceHandleCalled);
EXPECT_TRUE(VASharingFunctionsGlobalFunctionPointersMock::getInstance(false)->vaExportSurfaceHandleCalled);
EXPECT_TRUE(VASharingFunctionsGlobalFunctionPointersMock::getInstance(false)->vaQueryImageFormatsCalled);
EXPECT_TRUE(VASharingFunctionsGlobalFunctionPointersMock::getInstance(false)->vaMaxNumImageFormatsCalled);
VASharingFunctionsGlobalFunctionPointersMock::getInstance(true);
}
TEST_F(VaSharingTests, givenMockVaWithExportSurfaceHandlerWhenVaSurfaceIsCreatedThenCallHandlerWithDrmPrime2ToGetSurfaceFormatsInDescriptor) {
vaSharing->sharingFunctions.haveExportSurfaceHandle = true;
for (int plane = 0; plane < 2; plane++) {
auto vaSurface = std::unique_ptr<Image>(VASurface::createSharedVaSurface(
&context, &vaSharing->sharingFunctions, CL_MEM_READ_WRITE, 0, &vaSurfaceId, plane, &errCode));
ASSERT_NE(nullptr, vaSurface);
auto handler = vaSurface->peekSharingHandler();
ASSERT_NE(nullptr, handler);
auto vaHandler = static_cast<VASharing *>(handler);
EXPECT_EQ(vaHandler->peekFunctionsHandler(), &vaSharing->sharingFunctions);
auto sharingFunctions = vaSharing->sharingFunctions;
EXPECT_FALSE(sharingFunctions.deriveImageCalled);
EXPECT_FALSE(sharingFunctions.destroyImageCalled);
EXPECT_TRUE(sharingFunctions.exportSurfaceHandleCalled);
EXPECT_EQ(static_cast<uint32_t>(VA_SURFACE_ATTRIB_MEM_TYPE_DRM_PRIME_2), sharingFunctions.receivedSurfaceMemType);
EXPECT_EQ(static_cast<uint32_t>(VA_EXPORT_SURFACE_READ_WRITE | VA_EXPORT_SURFACE_SEPARATE_LAYERS), sharingFunctions.receivedSurfaceFlags);
if (plane == 0) {
EXPECT_EQ(256u, vaSurface->getImageDesc().image_width);
EXPECT_EQ(256u, vaSurface->getImageDesc().image_height);
}
if (plane == 1) {
EXPECT_EQ(128u, vaSurface->getImageDesc().image_width);
EXPECT_EQ(128u, vaSurface->getImageDesc().image_height);
SurfaceOffsets surfaceOffsets;
vaSurface->getSurfaceOffsets(surfaceOffsets);
auto vaSurfaceDesc = sharingFunctions.mockVaSurfaceDesc;
EXPECT_EQ(vaSurfaceDesc.layers[1].offset[0], surfaceOffsets.offset);
EXPECT_EQ(0u, surfaceOffsets.xOffset);
EXPECT_EQ(0u, surfaceOffsets.yOffset);
EXPECT_EQ(vaSurfaceDesc.layers[1].offset[0] / vaSurfaceDesc.layers[1].pitch[0], surfaceOffsets.yOffsetForUVplane);
}
EXPECT_TRUE(vaSurface->isTiledAllocation());
EXPECT_EQ(8u, vaSurface->getGraphicsAllocation()->peekSharedHandle());
}
}
TEST_F(VaSharingTests, givenMockVaWhenVaSurfaceIsCreatedThenMemObjectHasVaHandler) {
auto vaSurface = VASurface::createSharedVaSurface(&context, &vaSharing->sharingFunctions,
CL_MEM_READ_WRITE, 0, &vaSurfaceId, 0, &errCode);