mirror of
https://github.com/intel/compute-runtime.git
synced 2025-09-15 13:01:45 +08:00
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:

committed by
sys_ocldev

parent
35d9b4365b
commit
a5793fc654
@ -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);
|
||||
|
@ -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;
|
||||
}
|
||||
|
@ -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;
|
||||
|
@ -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;
|
||||
|
||||
sharingFunctions->deriveImage(*surface, &vaImage);
|
||||
uint32_t imageFourcc = 0;
|
||||
size_t imageOffset = 0;
|
||||
size_t imagePitch = 0;
|
||||
|
||||
imageId = vaImage.image_id;
|
||||
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_width = vaImage.width;
|
||||
imgDesc.image_height = vaImage.height;
|
||||
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());
|
||||
|
||||
|
@ -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;
|
||||
|
@ -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);
|
||||
|
Reference in New Issue
Block a user