From d9777cee3bd82e3451e0e9a6a422612c62adf967 Mon Sep 17 00:00:00 2001
From: Brendan King <Brendan.King@imgtec.com>
Date: Thu, 18 Aug 2022 19:14:29 +0100
Subject: [PATCH] gallium/pvr: support DRI Image extension v21

IMG NOTE: This patch should be merged into the "Add PVR Gallium
driver" patch the next time the Mesa version is upgraded in the
IMG DDK.

---
 src/gallium/frontends/pvr/dri_support.h    | 46 +++++++++++
 src/gallium/frontends/pvr/pvrcompat.c      | 74 +++++++++++++++++
 src/gallium/frontends/pvr/pvrdri_support.h | 27 +++++++
 src/gallium/frontends/pvr/pvrext.c         | 94 +++++++++++++++++++++-
 4 files changed, 240 insertions(+), 1 deletion(-)

diff --git a/src/gallium/frontends/pvr/dri_support.h b/src/gallium/frontends/pvr/dri_support.h
index b0b3106..3cc8f29 100644
--- a/src/gallium/frontends/pvr/dri_support.h
+++ b/src/gallium/frontends/pvr/dri_support.h
@@ -489,6 +489,52 @@ struct  PVRDRISupportInterfaceV2
 	struct {
 		bool (*HaveGetFenceFromCLEvent)(void);
 	} v4;
+	/* The v5 interface is an extension of v4, so v4 is required as well */
+	struct {
+		__DRIimage *(*CreateImageFromDMABufs3)
+			(struct DRISUPScreen *psDRISUPScreen,
+			 int iWidth,
+			 int iHeight,
+			 int iFourCC,
+			 uint64_t uModifier,
+			 int *piFDs,
+			 int iNumFDs,
+			 int *piStrides,
+			 int *piOffsets,
+			 unsigned int uColorSpace,
+			 unsigned int uSampleRange,
+			 unsigned int uHorizSiting,
+			 unsigned int uVertSiting,
+			 uint32_t uFlags,
+			 unsigned int *puError,
+			 void *pvLoaderPrivate);
+
+		__DRIimage *(*CreateImageWithModifiers2)
+			(struct DRISUPScreen *psDRISUPScreen,
+			 int iWidth,
+			 int iHeight,
+			 int iFourCC,
+			 const uint64_t *puModifiers,
+			 const unsigned int uModifierCount,
+			 unsigned int uUsage,
+			 void *pvLoaderPrivate);
+
+		__DRIimage *(*CreateImageFromFDs2)
+			(struct DRISUPScreen *psDRISUPcreen,
+			 int iWidth,
+			 int iHeight,
+			 int iFourCC,
+			 int *piFDs,
+			 int iNumFDs,
+			 uint32_t uFlags,
+			 int *piStrides,
+			 int *piOffsets,
+			 void *pvLoaderPrivate);
+
+		void (*SetInFenceFD)
+			(__DRIimage *psImage,
+			 int iFD);
+	} v5;
 };
 
 struct PVRDRIImageList {
diff --git a/src/gallium/frontends/pvr/pvrcompat.c b/src/gallium/frontends/pvr/pvrcompat.c
index 23a57dd..782c900 100644
--- a/src/gallium/frontends/pvr/pvrcompat.c
+++ b/src/gallium/frontends/pvr/pvrcompat.c
@@ -55,6 +55,10 @@ static pthread_mutex_t gsCompatLock = PTHREAD_MUTEX_INITIALIZER;
       ptr = dlsym(gpvSupLib, MAKESTRING(func)); \
    } while(0)
 
+/* Check if a function exists in the DRI Support interface structure */
+#define HaveFuncV2(field)                       \
+      ((gsSupV2.field) != NULL)                 \
+
 /* Call a function via the DRI Support interface structure */
 #define CallFuncV2(field, ...)                  \
    do {                                         \
@@ -238,6 +242,7 @@ MODSUPRegisterSupportInterfaceV2(const void *pvInterface,
    case 2:
    case 3:
    case 4:
+   case 5:
       /* These versions require version 0 */
       return false;
    default:
@@ -247,6 +252,13 @@ MODSUPRegisterSupportInterfaceV2(const void *pvInterface,
    /* The "default" case should be associated with the latest version */
    switch (uVersion) {
    default:
+   case 5:
+      /* This version is an extension of versions 0 to 4 */
+      if (uMinVersion > 0)
+         return false;
+
+      uEnd = PVRDRIInterfaceV2End(v5);
+      break;
    case 4:
       /* This version is an extension of versions 0 to 3 */
       if (uMinVersion > 0)
@@ -836,3 +848,65 @@ DRISUPHaveGetFenceFromCLEvent(void)
 
    return true;
 }
+
+__DRIimage *
+DRISUPCreateImageFromDMABufs3(struct DRISUPScreen *psDRISUPScreen,
+                              int iWidth, int iHeight, int iFourCC,
+                              uint64_t uModifier, int *piFDs, int iNumFDs,
+                              int *piStrides, int *piOffsets,
+                              unsigned int uColorSpace,
+                              unsigned int uSampleRange,
+                              unsigned int uHorizSiting,
+                              unsigned int uVertSiting,
+                              uint32_t uFlags,
+                              unsigned int *puError, void *pvLoaderPrivate)
+{
+   CallFuncV2(v5.CreateImageFromDMABufs3,
+              psDRISUPScreen, iWidth, iHeight, iFourCC, uModifier,
+              piFDs, iNumFDs, piStrides, piOffsets, uColorSpace, uSampleRange,
+              uHorizSiting, uVertSiting, uFlags, puError, pvLoaderPrivate);
+
+   return NULL;
+}
+
+__DRIimage *
+DRISUPCreateImageWithModifiers2(struct DRISUPScreen *psDRISUPScreen,
+                                int iWidth, int iHeight, int iFourCC,
+                                const uint64_t *puModifiers,
+                                const unsigned int uModifierCount,
+                                unsigned int uUse,
+                                void *pvLoaderPrivate)
+{
+   CallFuncV2(v5.CreateImageWithModifiers2,
+              psDRISUPScreen, iWidth, iHeight, iFourCC, puModifiers,
+              uModifierCount, uUse, pvLoaderPrivate);
+
+   return NULL;
+}
+
+__DRIimage *
+DRISUPCreateImageFromFDs2(struct DRISUPScreen *psDRISUPcreen,
+                          int iWidth, int iHeight, int iFourCC,
+                          int *piFDs, int iNumFDs, uint32_t uFlags,
+                          int *piStrides, int *piOffsets,
+                          void *pvLoaderPrivate)
+{
+   CallFuncV2(v5.CreateImageFromFDs2,
+              psDRISUPcreen, iWidth, iHeight, iFourCC, piFDs, iNumFDs,
+              uFlags, piStrides, piOffsets, pvLoaderPrivate);
+
+   return NULL;
+}
+
+bool
+DRISUPHaveSetInFenceFd(void)
+{
+	return HaveFuncV2(v5.SetInFenceFD);
+}
+
+void
+DRISUPSetInFenceFd(__DRIimage *psImage, int iFd)
+{
+   CallFuncV2(v5.SetInFenceFD,
+              psImage, iFd);
+}
diff --git a/src/gallium/frontends/pvr/pvrdri_support.h b/src/gallium/frontends/pvr/pvrdri_support.h
index 58ea350..f735354 100644
--- a/src/gallium/frontends/pvr/pvrdri_support.h
+++ b/src/gallium/frontends/pvr/pvrdri_support.h
@@ -203,4 +203,31 @@ void DRISUPSetDamageRegion(struct DRISUPDrawable *psDRISUPDrawable,
 
 bool DRISUPHaveGetFenceFromCLEvent(void);
 
+__DRIimage *DRISUPCreateImageFromDMABufs3(struct DRISUPScreen *psDRISUPScreen,
+                                          int iWidth, int iHeight,
+                                          int iFourCC, uint64_t uModifier,
+                                          int *piFDs, int iNumFDs,
+                                          int *piStrides, int *piOffsets,
+                                          unsigned int uColorSpace,
+                                          unsigned int uSampleRange,
+                                          unsigned int uHorizSiting,
+                                          unsigned int uVertSiting,
+                                          uint32_t uFlags,
+                                          unsigned int *puError,
+                                          void *pvLoaderPrivate);
+__DRIimage *DRISUPCreateImageWithModifiers2(struct DRISUPScreen *psDRISUPScreen,
+                                            int iWidth, int iHeight,
+                                            int iFourCC,
+                                            const uint64_t *puModifiers,
+                                            const unsigned int uModifierCount,
+                                            unsigned int uUse,
+                                            void *pvLoaderPrivate);
+__DRIimage *DRISUPCreateImageFromFDs2(struct DRISUPScreen *psDRISUPcreen,
+                                      int iWidth, int iHeight, int iFourCC,
+                                      int *piFDs, int iNumFDs, uint32_t uFlags,
+                                      int *piStrides, int *piOffsets,
+                                      void *pvLoaderPrivate);
+
+bool DRISUPHaveSetInFenceFd(void);
+void DRISUPSetInFenceFd(__DRIimage *psImage, int iFd);
 #endif /* defined(__PVRDRI_SUPPORT_H__) */
diff --git a/src/gallium/frontends/pvr/pvrext.c b/src/gallium/frontends/pvr/pvrext.c
index 4783996..826e84f 100644
--- a/src/gallium/frontends/pvr/pvrext.c
+++ b/src/gallium/frontends/pvr/pvrext.c
@@ -71,7 +71,7 @@
 /* Maximum version numbers for each supported extension */
 #define PVR_DRI_TEX_BUFFER_VERSION      3
 #define PVR_DRI2_FLUSH_VERSION          4
-#define PVR_DRI_IMAGE_VERSION           17
+#define PVR_DRI_IMAGE_VERSION           21
 #define PVR_DRI2_ROBUSTNESS_VERSION     1
 #define PVR_DRI2_FENCE_VERSION          2
 #define PVR_DRI2_RENDERER_QUERY_VERSION 1
@@ -445,6 +445,68 @@ PVRDRICreateImageFromRenderbuffer2(__DRIcontext *psDRIContext,
                                              pvLoaderPrivate, puError);
 }
 
+static __DRIimage *
+PVRDRICreateImageFromDmaBufs3(__DRIscreen *psDRIScreen,
+                              int iWidth, int iHeight,
+                              int iFourCC, uint64_t uModifier,
+                              int *piFDs, int iNumFDs,
+                              int *piStrides, int *piOffsets,
+                              enum __DRIYUVColorSpace eColorSpace,
+                              enum __DRISampleRange eSampleRange,
+                              enum __DRIChromaSiting eHorizSiting,
+                              enum __DRIChromaSiting eVertSiting,
+                              uint32_t uFlags, unsigned int *puError,
+                              void *pvLoaderPrivate)
+{
+   PVRDRIScreen *psPVRScreen = psDRIScreen->driverPrivate;
+
+   return DRISUPCreateImageFromDMABufs3(psPVRScreen->psDRISUPScreen,
+                                        iWidth, iHeight, iFourCC, uModifier,
+                                        piFDs, iNumFDs, piStrides, piOffsets,
+                                        (unsigned int) eColorSpace,
+                                        (unsigned int) eSampleRange,
+                                        (unsigned int) eHorizSiting,
+                                        (unsigned int) eVertSiting,
+                                        uFlags, puError, pvLoaderPrivate);
+}
+
+static __DRIimage *
+PVRDRICreateImageWithModifiers2(__DRIscreen *psDRIScreen,
+                                int iWidth, int iHeight, int iFormat,
+                                const uint64_t *puModifiers,
+                                const unsigned int uModifierCount,
+                                unsigned int uUse,
+                                void *pvLoaderPrivate)
+{
+   PVRDRIScreen *psPVRScreen = psDRIScreen->driverPrivate;
+   int iFourCC = PVRDRIFormatToFourCC(iFormat);
+
+   return DRISUPCreateImageWithModifiers2(psPVRScreen->psDRISUPScreen,
+                                          iWidth, iHeight, iFourCC,
+                                          puModifiers, uModifierCount,
+                                          uUse, pvLoaderPrivate);
+}
+
+static __DRIimage *
+PVRDRICreateImageFromFds2(__DRIscreen *psDRIScreen, int iWidth, int iHeight,
+                          int iFourCC, int *piFDs, int iNumFDs,
+                          uint32_t uFlags, int *piStrides, int *piOffsets,
+                          void *pvLoaderPrivate)
+{
+   PVRDRIScreen *psPVRScreen = psDRIScreen->driverPrivate;
+
+   return DRISUPCreateImageFromFDs2(psPVRScreen->psDRISUPScreen,
+                                    iWidth, iHeight, iFourCC, piFDs, iNumFDs,
+                                    uFlags, piStrides, piOffsets,
+                                    pvLoaderPrivate);
+}
+
+static void
+PVRDRISetInFenceFd(__DRIimage *psImage, int iFd)
+{
+   return DRISUPSetInFenceFd(psImage, iFd);
+}
+
 #if defined(EGL_IMG_cl_image)
 static __DRIimage *
 PVRDRICreateImageFromBuffer(__DRIcontext *psDRIContext, int iTarget,
@@ -486,6 +548,10 @@ static __DRIimageExtension pvrDRIImage = {
    .queryDmaBufFormatModifierAttribs =
    PVRDRIQueryDmaBufFormatModifierAttribs,
    .createImageFromRenderbuffer2 = PVRDRICreateImageFromRenderbuffer2,
+   .createImageFromDmaBufs3 = PVRDRICreateImageFromDmaBufs3,
+   .createImageWithModifiers2 = PVRDRICreateImageWithModifiers2,
+   .createImageFromFds2 = PVRDRICreateImageFromFds2,
+   .setInFenceFd = PVRDRISetInFenceFd,
 #if defined(EGL_IMG_cl_image)
    .createImageFromBuffer = PVRDRICreateImageFromBuffer,
 #endif
@@ -684,8 +750,10 @@ PVRDRIScreenExtensionVersionInfo(void)
 void
 PVRDRIAdjustExtensions(unsigned int uVersion, unsigned int uMinVersion)
 {
+   /* __DRI2fenceExtension adjustment */
    switch (uVersion) {
    default:
+   case 5:
    case 4:
       /* Is the KHR_cl_event2 EGL extension supported? */
       if (!DRISUPHaveGetFenceFromCLEvent())
@@ -701,4 +769,28 @@ PVRDRIAdjustExtensions(unsigned int uVersion, unsigned int uMinVersion)
       pvrDRIFenceExtension.get_fence_from_cl_event = NULL;
       break;
    }
+
+   /* __DRIimageExtension adjustment */
+   switch (uVersion) {
+   default:
+   case 5:
+      if (!DRISUPHaveSetInFenceFd())
+         pvrDRIImage.setInFenceFd = NULL;
+
+      break;
+   case 4:
+   case 3:
+   case 2:
+   case 1:
+   case 0:
+      /*
+       * The following are not supported:
+       *    createImageFromDmaBufs3
+       *    createImageWithModifiers2
+       *    createImageFromFds2
+       *    setInFenceFd
+       */
+      pvrDRIImage.base.version = 17;
+      break;
+   }
 }