From b12448838a3f2edb759443295dfbfbf77c8e68a5 Mon Sep 17 00:00:00 2001
From: "Xu, Zhengguo" <zhengguo.xu@intel.com>
Date: Tue, 21 May 2024 13:42:31 +0800
Subject: [PATCH 1/6] [Decode] Add ddi implement for vaEndPicture2

Signed-off-by: Xu, Zhengguo <zhengguo.xu@intel.com>
---
 media_driver/linux/common/ddi/media_libva.cpp | 51 +++++++++++++++++++
 media_driver/linux/common/ddi/media_libva.h   |  9 ++++
 2 files changed, 60 insertions(+)

diff --git a/media_driver/linux/common/ddi/media_libva.cpp b/media_driver/linux/common/ddi/media_libva.cpp
index f52c6e65c2c..4758587aa30 100755
--- a/media_driver/linux/common/ddi/media_libva.cpp
+++ b/media_driver/linux/common/ddi/media_libva.cpp
@@ -2137,6 +2137,9 @@ VAStatus DdiMedia_LoadFuncion (VADriverContextP ctx)
     pVTable->vaBeginPicture                  = DdiMedia_BeginPicture;
     pVTable->vaRenderPicture                 = DdiMedia_RenderPicture;
     pVTable->vaEndPicture                    = DdiMedia_EndPicture;
+//todo: #if VA_CHECK_VERSION(1, 9, 0)
+    pVTable->vaEndPicture2                   = DdiMedia_EndPicture2;
+//#endif
     pVTable->vaSyncSurface                   = DdiMedia_SyncSurface;
 #if VA_CHECK_VERSION(1, 9, 0)
     pVTable->vaSyncSurface2                  = DdiMedia_SyncSurface2;
@@ -4056,6 +4059,54 @@ VAStatus DdiMedia_EndPicture (
     return vaStatus;
 }
 
+//#if VA_CHECK_VERSION(1, 9, 0) //todo: check correct version
+VAStatus DdiMedia_EndPicture2 (
+    VADriverContextP    ctx,
+    VAContextID         context,
+    int32_t            *fences,
+    int32_t            count
+)
+{
+    DDI_FUNCTION_ENTER();
+
+    DDI_CHK_NULL(ctx, "nullptr ctx", VA_STATUS_ERROR_INVALID_CONTEXT);
+    DDI_CHK_NULL(fences, "nullptr fences", VA_STATUS_ERROR_INVALID_PARAMETER);
+
+    uint32_t ctxType = DDI_MEDIA_CONTEXT_TYPE_NONE;
+    void     *ctxPtr = DdiMedia_GetContextFromContextID(ctx, context, &ctxType);
+    VAStatus  vaStatus = VA_STATUS_SUCCESS;
+
+    //todo: DdiMediaUtil_LockMutex(mediaCtx->SyncFenceMutex);
+    //todo: vaStatus  = DdiMedia_SetSyncFences(ctx, context, fences, count);
+    //todo: add fences[1...count] into bufmgr->fences[...]
+
+    switch (ctxType)
+    {
+        case DDI_MEDIA_CONTEXT_TYPE_DECODER:
+            vaStatus = DdiDecode_EndPicture(ctx, context);
+            break;
+        case DDI_MEDIA_CONTEXT_TYPE_ENCODER:
+            vaStatus = DdiEncode_EndPicture(ctx, context);
+            break;
+        case DDI_MEDIA_CONTEXT_TYPE_VP:
+            vaStatus = DdiVp_EndPicture(ctx, context);
+            break;
+        default:
+            DDI_ASSERTMESSAGE("DDI: unsupported context in DdiCodec_EndPicture.");
+            vaStatus = VA_STATUS_ERROR_INVALID_CONTEXT;
+    }
+
+    //todo: vaStatus  = DdiMedia_GetSyncFenceOut(ctx, context, &fences[0]);
+    //todo: get fence out from bufmgr->fence[0]
+    //todo: DdiMediaUtil_UnLockMutex(mediaCtx->SyncFenceMutex);
+
+    MOS_TraceEventExt(EVENT_VA_PICTURE, EVENT_TYPE_END, &context, sizeof(context), &vaStatus, sizeof(vaStatus));
+    PERF_UTILITY_STOP_ONCE("First Frame Time", PERF_MOS, PERF_LEVEL_DDI);
+
+    return vaStatus;
+}
+//#endif
+
 static VAStatus DdiMedia_StatusCheck (
     PDDI_MEDIA_CONTEXT mediaCtx,
     DDI_MEDIA_SURFACE  *surface,
diff --git a/media_driver/linux/common/ddi/media_libva.h b/media_driver/linux/common/ddi/media_libva.h
index 8842188d678..a1bb721c497 100755
--- a/media_driver/linux/common/ddi/media_libva.h
+++ b/media_driver/linux/common/ddi/media_libva.h
@@ -639,6 +639,15 @@ VAStatus DdiMedia_EndPicture (
     VAContextID       context
 );
 
+//#if VA_CHECK_VERSION(1, 9, 0) //todo: check correct version
+VAStatus DdiMedia_EndPicture2 (
+    VADriverContextP    ctx,
+    VAContextID         context,
+    int32_t            *fences,
+    int32_t            count
+);
+//#endif
+
 //!
 //! \brief  Sync surface
 //! \details    This function blocks until all pending operations on the render target

From 13ec4547440975c6bb52fe10ad64347cd792f5d6 Mon Sep 17 00:00:00 2001
From: "Xu, Zhengguo" <zhengguo.xu@intel.com>
Date: Wed, 22 May 2024 11:22:28 +0800
Subject: [PATCH 2/6] [Decode] Add sync fence mutex for vaEndPicure2

Signed-off-by: Xu, Zhengguo <zhengguo.xu@intel.com>
---
 media_driver/linux/common/ddi/ddi_media_context.h |  3 +++
 media_driver/linux/common/ddi/media_libva.cpp     | 14 ++++++++++++--
 2 files changed, 15 insertions(+), 2 deletions(-)

diff --git a/media_driver/linux/common/ddi/ddi_media_context.h b/media_driver/linux/common/ddi/ddi_media_context.h
index 53c1bcceffe..8ddef68c501 100644
--- a/media_driver/linux/common/ddi/ddi_media_context.h
+++ b/media_driver/linux/common/ddi/ddi_media_context.h
@@ -100,6 +100,9 @@ struct DDI_MEDIA_CONTEXT
     MEDIA_MUTEX_T       ProtMutex      = {};
     MEDIA_MUTEX_T       CmMutex        = {};
     MEDIA_MUTEX_T       MfeMutex       = {};
+//todo: #if VA_CHECK_VERSION(1, 9, 0)
+    MEDIA_MUTEX_T       SyncFenceMutex = {};
+//#endif
 
     // GT system Info
     MEDIA_SYSTEM_INFO  *pGtSystemInfo           = nullptr;
diff --git a/media_driver/linux/common/ddi/media_libva.cpp b/media_driver/linux/common/ddi/media_libva.cpp
index 4758587aa30..ee67f59347c 100755
--- a/media_driver/linux/common/ddi/media_libva.cpp
+++ b/media_driver/linux/common/ddi/media_libva.cpp
@@ -1427,6 +1427,9 @@ static VAStatus DdiMedia_HeapInitialize(
     DdiMediaUtil_InitMutex(&mediaCtx->ProtMutex);
     DdiMediaUtil_InitMutex(&mediaCtx->CmMutex);
     DdiMediaUtil_InitMutex(&mediaCtx->MfeMutex);
+//todo: #if VA_CHECK_VERSION(1, 9, 0)
+    DdiMediaUtil_InitMutex(&mediaCtx->SyncFenceMutex);
+//#endif
 
     return VA_STATUS_SUCCESS;
 }
@@ -1481,6 +1484,9 @@ static VAStatus DdiMedia_HeapDestroy(
     DdiMediaUtil_DestroyMutex(&mediaCtx->ProtMutex);
     DdiMediaUtil_DestroyMutex(&mediaCtx->CmMutex);
     DdiMediaUtil_DestroyMutex(&mediaCtx->MfeMutex);
+//todo: #if VA_CHECK_VERSION(1, 9, 0)
+    DdiMediaUtil_DestroyMutex(&mediaCtx->SyncFenceMutex);
+//#endif
 
     //resource checking
     if (mediaCtx->uiNumSurfaces != 0)
@@ -1558,6 +1564,9 @@ void DestroyMediaContextMutex(PDDI_MEDIA_CONTEXT mediaCtx)
     DdiMediaUtil_DestroyMutex(&mediaCtx->VpMutex);
     DdiMediaUtil_DestroyMutex(&mediaCtx->CmMutex);
     DdiMediaUtil_DestroyMutex(&mediaCtx->MfeMutex);
+//todo: #if VA_CHECK_VERSION(1, 9, 0)
+    DdiMediaUtil_DestroyMutex(&mediaCtx->SyncFenceMutex);
+//#endif
 #if !defined(ANDROID) && defined(X11_FOUND)
     DdiMediaUtil_DestroyMutex(&mediaCtx->PutSurfaceRenderMutex);
     DdiMediaUtil_DestroyMutex(&mediaCtx->PutSurfaceSwapBufferMutex);
@@ -4074,9 +4083,10 @@ VAStatus DdiMedia_EndPicture2 (
 
     uint32_t ctxType = DDI_MEDIA_CONTEXT_TYPE_NONE;
     void     *ctxPtr = DdiMedia_GetContextFromContextID(ctx, context, &ctxType);
+    PDDI_MEDIA_CONTEXT mediaCtx  = DdiMedia_GetMediaContext(ctx);
     VAStatus  vaStatus = VA_STATUS_SUCCESS;
 
-    //todo: DdiMediaUtil_LockMutex(mediaCtx->SyncFenceMutex);
+    DdiMediaUtil_LockMutex(&mediaCtx->SyncFenceMutex);
     //todo: vaStatus  = DdiMedia_SetSyncFences(ctx, context, fences, count);
     //todo: add fences[1...count] into bufmgr->fences[...]
 
@@ -4098,7 +4108,7 @@ VAStatus DdiMedia_EndPicture2 (
 
     //todo: vaStatus  = DdiMedia_GetSyncFenceOut(ctx, context, &fences[0]);
     //todo: get fence out from bufmgr->fence[0]
-    //todo: DdiMediaUtil_UnLockMutex(mediaCtx->SyncFenceMutex);
+    DdiMediaUtil_UnLockMutex(&mediaCtx->SyncFenceMutex);
 
     MOS_TraceEventExt(EVENT_VA_PICTURE, EVENT_TYPE_END, &context, sizeof(context), &vaStatus, sizeof(vaStatus));
     PERF_UTILITY_STOP_ONCE("First Frame Time", PERF_MOS, PERF_LEVEL_DDI);

From f93d2b8c915b55cbd311402207e14cf0552aa33f Mon Sep 17 00:00:00 2001
From: "Xu, Zhengguo" <zhengguo.xu@intel.com>
Date: Wed, 22 May 2024 13:25:39 +0800
Subject: [PATCH 3/6] [Decode] Add media common function to set and get fences

Signed-off-by: Xu, Zhengguo <zhengguo.xu@intel.com>
---
 media_driver/linux/common/ddi/media_libva.cpp  |  4 ++--
 .../linux/common/ddi/media_libva_common.cpp    | 18 ++++++++++++++++++
 .../linux/common/ddi/media_libva_common.h      | 10 ++++++++++
 3 files changed, 30 insertions(+), 2 deletions(-)

diff --git a/media_driver/linux/common/ddi/media_libva.cpp b/media_driver/linux/common/ddi/media_libva.cpp
index ee67f59347c..1f0310f8523 100755
--- a/media_driver/linux/common/ddi/media_libva.cpp
+++ b/media_driver/linux/common/ddi/media_libva.cpp
@@ -4087,7 +4087,7 @@ VAStatus DdiMedia_EndPicture2 (
     VAStatus  vaStatus = VA_STATUS_SUCCESS;
 
     DdiMediaUtil_LockMutex(&mediaCtx->SyncFenceMutex);
-    //todo: vaStatus  = DdiMedia_SetSyncFences(ctx, context, fences, count);
+    vaStatus  = DdiMedia_SetSyncFences(ctx, context, fences, count);
     //todo: add fences[1...count] into bufmgr->fences[...]
 
     switch (ctxType)
@@ -4106,7 +4106,7 @@ VAStatus DdiMedia_EndPicture2 (
             vaStatus = VA_STATUS_ERROR_INVALID_CONTEXT;
     }
 
-    //todo: vaStatus  = DdiMedia_GetSyncFenceOut(ctx, context, &fences[0]);
+    vaStatus  = DdiMedia_GetSyncFenceOut(ctx, context, &fences[0]);
     //todo: get fence out from bufmgr->fence[0]
     DdiMediaUtil_UnLockMutex(&mediaCtx->SyncFenceMutex);
 
diff --git a/media_driver/linux/common/ddi/media_libva_common.cpp b/media_driver/linux/common/ddi/media_libva_common.cpp
index bea8b673e83..f41aa3b9185 100644
--- a/media_driver/linux/common/ddi/media_libva_common.cpp
+++ b/media_driver/linux/common/ddi/media_libva_common.cpp
@@ -475,3 +475,21 @@ void MovePriorityBufferIdToEnd (VABufferID *buffers, int32_t priorityIndexInBuf,
     }
 }
 
+VAStatus DdiMedia_SetSyncFences(VADriverContextP ctx, VAContextID context, int32_t *fences, int32_t count)
+{
+    VAStatus vaStatus = VA_STATUS_SUCCESS;
+    //todo: get bufmgr
+    //todo: struct mos_exec_fences exec_fences = {.fences = fences, .count = count};
+    //todo: int ret = mos_bufmgr_set_fences(bufmgr, &exec_fences);
+
+    return vaStatus;
+}
+
+VAStatus DdiMedia_GetSyncFenceOut(VADriverContextP ctx, VAContextID context, int32_t *fence_out)
+{
+    VAStatus vaStatus = VA_STATUS_SUCCESS;
+    //todo: get bufmgr
+    //todo: int ret = mos_bufmgr_get_fence(bufmgr, fence_out);
+
+    return vaStatus;
+}
diff --git a/media_driver/linux/common/ddi/media_libva_common.h b/media_driver/linux/common/ddi/media_libva_common.h
index 4a9b653b1a4..b24033e6f8c 100644
--- a/media_driver/linux/common/ddi/media_libva_common.h
+++ b/media_driver/linux/common/ddi/media_libva_common.h
@@ -273,4 +273,14 @@ int32_t DdiMedia_GetGpuPriority (VADriverContextP ctx, VABufferID *buffers, int3
 //!
 void MovePriorityBufferIdToEnd (VABufferID *buffers, int32_t priorityIndexInBuf, int32_t numBuffers);
 
+//!
+//! \brief  Add fence fds into bufmgr for execution sync
+//!
+VAStatus DdiMedia_SetSyncFences(VADriverContextP ctx, VAContextID context, int32_t *fences, int32_t count);
+
+//!
+//! \brief  Get fence out from current execution submission
+//!
+VAStatus DdiMedia_GetSyncFenceOut(VADriverContextP ctx, VAContextID context, int32_t *fence_out);
+
 #endif

From 3962c1832fae1beb9eeb7df99f3d5f95bb06fe64 Mon Sep 17 00:00:00 2001
From: "Xu, Zhengguo" <zhengguo.xu@intel.com>
Date: Wed, 22 May 2024 13:42:07 +0800
Subject: [PATCH 4/6] [Decode] Add mos bufmgr api to set and get fences

Signed-off-by: Xu, Zhengguo <zhengguo.xu@intel.com>
---
 .../linux/common/ddi/media_libva_common.cpp   | 23 +++++++---
 .../common/os/i915/include/mos_bufmgr_api.h   |  9 ++++
 .../linux/common/os/i915/mos_bufmgr_api.c     | 44 +++++++++++++++++++
 3 files changed, 71 insertions(+), 5 deletions(-)

diff --git a/media_driver/linux/common/ddi/media_libva_common.cpp b/media_driver/linux/common/ddi/media_libva_common.cpp
index f41aa3b9185..dab26bbfbee 100644
--- a/media_driver/linux/common/ddi/media_libva_common.cpp
+++ b/media_driver/linux/common/ddi/media_libva_common.cpp
@@ -478,9 +478,16 @@ void MovePriorityBufferIdToEnd (VABufferID *buffers, int32_t priorityIndexInBuf,
 VAStatus DdiMedia_SetSyncFences(VADriverContextP ctx, VAContextID context, int32_t *fences, int32_t count)
 {
     VAStatus vaStatus = VA_STATUS_SUCCESS;
-    //todo: get bufmgr
-    //todo: struct mos_exec_fences exec_fences = {.fences = fences, .count = count};
-    //todo: int ret = mos_bufmgr_set_fences(bufmgr, &exec_fences);
+    PDDI_MEDIA_CONTEXT mediaCtx  = DdiMedia_GetMediaContext(ctx);
+    struct mos_exec_fences exec_fences;
+    exec_fences.fences = fences;
+    exec_fences.count = count;
+    int ret = mos_set_fences(mediaCtx->pDrmBufMgr, &exec_fences);
+
+    if (ret)
+    {
+        vaStatus = VA_STATUS_ERROR_OPERATION_FAILED;
+    }
 
     return vaStatus;
 }
@@ -488,8 +495,14 @@ VAStatus DdiMedia_SetSyncFences(VADriverContextP ctx, VAContextID context, int32
 VAStatus DdiMedia_GetSyncFenceOut(VADriverContextP ctx, VAContextID context, int32_t *fence_out)
 {
     VAStatus vaStatus = VA_STATUS_SUCCESS;
-    //todo: get bufmgr
-    //todo: int ret = mos_bufmgr_get_fence(bufmgr, fence_out);
+    PDDI_MEDIA_CONTEXT mediaCtx  = DdiMedia_GetMediaContext(ctx);
+    int ret = mos_get_fence(mediaCtx->pDrmBufMgr, fence_out);
+
+    if (ret)
+    {
+        vaStatus = VA_STATUS_ERROR_OPERATION_FAILED;
+        *fence_out = 0;
+    }
 
     return vaStatus;
 }
diff --git a/media_softlet/linux/common/os/i915/include/mos_bufmgr_api.h b/media_softlet/linux/common/os/i915/include/mos_bufmgr_api.h
index 9e86adc293f..b57c8c211ad 100644
--- a/media_softlet/linux/common/os/i915/include/mos_bufmgr_api.h
+++ b/media_softlet/linux/common/os/i915/include/mos_bufmgr_api.h
@@ -252,6 +252,12 @@ struct mos_drm_uc_version {
     uint32_t minor_version;
 };
 
+struct mos_exec_fences
+{
+    int32_t *fences;
+    int32_t count;
+};
+
 struct mos_linux_bo *mos_bo_alloc(struct mos_bufmgr *bufmgr,
                                 struct mos_drm_bo_alloc *alloc);
 struct mos_linux_bo *mos_bo_alloc_userptr(struct mos_bufmgr *bufmgr,
@@ -312,6 +318,9 @@ int mos_bufmgr_get_memory_info(struct mos_bufmgr *bufmgr, char *info, uint32_t l
 int mos_bufmgr_get_devid(struct mos_bufmgr *bufmgr);
 void mos_bufmgr_realloc_cache(struct mos_bufmgr *bufmgr, uint8_t alloc_mode);
 
+int mos_set_fences(struct mos_bufmgr *bufmgr, struct mos_exec_fences *exec_fences);
+int mos_get_fence(struct mos_bufmgr *bufmgr, int32_t *fence_out);
+
 int mos_bo_map_unsynchronized(struct mos_linux_bo *bo);
 int mos_bo_map_gtt(struct mos_linux_bo *bo);
 int mos_bo_unmap_gtt(struct mos_linux_bo *bo);
diff --git a/media_softlet/linux/common/os/i915/mos_bufmgr_api.c b/media_softlet/linux/common/os/i915/mos_bufmgr_api.c
index 6a9f5f6642a..0485bf29765 100644
--- a/media_softlet/linux/common/os/i915/mos_bufmgr_api.c
+++ b/media_softlet/linux/common/os/i915/mos_bufmgr_api.c
@@ -1223,6 +1223,50 @@ mos_bufmgr_realloc_cache(struct mos_bufmgr *bufmgr, uint8_t alloc_mode)
     }
 }
 
+int
+mos_set_fences(struct mos_bufmgr *bufmgr, struct mos_exec_fences *exec_fences)
+{
+    if(!bufmgr)
+    {
+        MOS_OS_CRITICALMESSAGE("Input null ptr\n");
+        return -EINVAL;
+    }
+
+    return 0;
+    //todo: add func pointer to bufmgr
+    //if (bufmgr->set_fences)
+    //{
+    //    return bufmgr->set_fences(bufmgr, exec_fences);
+    //}
+    //else
+    //{
+    //    MOS_OS_CRITICALMESSAGE("Unsupported\n");
+    //}
+
+}
+
+int
+mos_get_fence(struct mos_bufmgr *bufmgr, int32_t *fence_out)
+{
+    if(!bufmgr)
+    {
+        MOS_OS_CRITICALMESSAGE("Input null ptr\n");
+        return -EINVAL;
+    }
+
+    return 0;
+    //todo: add func pointer to bufmgr
+    //if (bufmgr->get_fence)
+    //{
+    //    return bufmgr->get_fence(bufmgr, fence_out);
+    //}
+    //else
+    //{
+    //    MOS_OS_CRITICALMESSAGE("Unsupported\n");
+    //}
+
+}
+
 int
 mos_query_engines_count(struct mos_bufmgr *bufmgr,
                       unsigned int *nengine)

From d1e964ad92eb57030deb8346a901fe3128f07319 Mon Sep 17 00:00:00 2001
From: "Xu, Zhengguo" <zhengguo.xu@intel.com>
Date: Mon, 27 May 2024 11:05:19 +0800
Subject: [PATCH 5/6] [Decode] Add set fences and get fence implement in i915
 drm

Signed-off-by: Xu, Zhengguo <zhengguo.xu@intel.com>
---
 .../common/os/i915/include/mos_bufmgr_api.h   |  1 +
 .../common/os/i915/include/mos_bufmgr_priv.h  |  3 +
 .../linux/common/os/i915/mos_bufmgr.c         | 59 +++++++++++++++++++
 .../linux/common/os/i915/mos_bufmgr_api.c     | 38 ++++++------
 .../os/i915_production/mos_bufmgr_priv.h      |  3 +
 5 files changed, 84 insertions(+), 20 deletions(-)

diff --git a/media_softlet/linux/common/os/i915/include/mos_bufmgr_api.h b/media_softlet/linux/common/os/i915/include/mos_bufmgr_api.h
index b57c8c211ad..b8a9137b12c 100644
--- a/media_softlet/linux/common/os/i915/include/mos_bufmgr_api.h
+++ b/media_softlet/linux/common/os/i915/include/mos_bufmgr_api.h
@@ -254,6 +254,7 @@ struct mos_drm_uc_version {
 
 struct mos_exec_fences
 {
+#define FENCES_MAX  10
     int32_t *fences;
     int32_t count;
 };
diff --git a/media_softlet/linux/common/os/i915/include/mos_bufmgr_priv.h b/media_softlet/linux/common/os/i915/include/mos_bufmgr_priv.h
index 04f543946b6..25f4788c050 100644
--- a/media_softlet/linux/common/os/i915/include/mos_bufmgr_priv.h
+++ b/media_softlet/linux/common/os/i915/include/mos_bufmgr_priv.h
@@ -418,6 +418,9 @@ struct mos_bufmgr {
     uint8_t (*switch_off_n_bits)(struct mos_linux_context *ctx, uint8_t in_mask, int n) = nullptr;
     unsigned int (*hweight8)(struct mos_linux_context *ctx, uint8_t w) = nullptr;
 
+    int (*set_fences)(struct mos_bufmgr *bufmgr, struct mos_exec_fences *exec_fences) = nullptr;
+    int (*get_fence)(struct mos_bufmgr *bufmgr, int32_t *fence_out) = nullptr;
+
     /**< Enables verbose debugging printouts */
     int debug = 0;
     uint32_t *get_reserved = nullptr;
diff --git a/media_softlet/linux/common/os/i915/mos_bufmgr.c b/media_softlet/linux/common/os/i915/mos_bufmgr.c
index 75f1df4feb8..0c97ab5f3a0 100644
--- a/media_softlet/linux/common/os/i915/mos_bufmgr.c
+++ b/media_softlet/linux/common/os/i915/mos_bufmgr.c
@@ -140,6 +140,8 @@ struct mos_bufmgr_gem {
     int exec_size;
     int exec_count;
 
+    struct mos_exec_fences exec_fences;
+
     /** Array of lists of cached gem objects of power-of-two sizes */
     struct mos_gem_bo_bucket cache_bucket[64];
     int num_buckets;
@@ -5221,6 +5223,61 @@ mos_bufmgr_enable_turbo_boost(struct mos_bufmgr *bufmgr)
                       DRM_IOCTL_I915_GEM_CONTEXT_SETPARAM, &ctxParam );
 }
 
+int
+mos_bufmgr_set_fences(struct mos_bufmgr *bufmgr, struct mos_exec_fences *exec_fences)
+{
+    if (!bufmgr || !exec_fences || exec_fences->count > FENCES_MAX)
+    {
+        return -EINVAL;
+    }
+
+    struct mos_bufmgr_gem *bufmgr_gem = (struct mos_bufmgr_gem *)bufmgr;
+
+    if (bufmgr_gem->exec_fences.fences == nullptr)
+    {
+        //fences[0] reserved for fence out
+        bufmgr_gem->exec_fences.fences = (int32_t *)malloc((FENCES_MAX + 1) * sizeof(int32_t));
+
+        if (bufmgr_gem->exec_fences.fences == nullptr)
+        {
+            return -ENOMEM;
+        }
+
+        bufmgr_gem->exec_fences.count = 0;
+    }
+
+    if (exec_fences->count > 0)
+    {
+        memcpy(bufmgr_gem->exec_fences.fences, exec_fences->fences, (exec_fences->count + 1) * sizeof(int32_t));
+        bufmgr_gem->exec_fences.fences[0] = 0;
+        bufmgr_gem->exec_fences.count = exec_fences->count;
+    }
+
+    return 0;
+}
+
+int
+mos_bufmgr_get_fence(struct mos_bufmgr *bufmgr, int32_t *fence_out)
+{
+    if (!bufmgr || !fence_out)
+    {
+        return -EINVAL;
+    }
+
+    struct mos_bufmgr_gem *bufmgr_gem = (struct mos_bufmgr_gem *)bufmgr;
+
+    if (bufmgr_gem->exec_fences.fences)
+    {
+        *fence_out = bufmgr_gem->exec_fences.fences[0];
+    }
+    else
+    {
+        *fence_out = 0;
+    }
+
+    return 0;
+}
+
 /**
  * Initializes the GEM buffer manager, which uses the kernel to allocate, map,
  * and manage map buffer objections.
@@ -5333,6 +5390,8 @@ mos_bufmgr_gem_init_i915(int fd, int batch_size)
     bufmgr_gem->bufmgr.get_ts_frequency = mos_bufmgr_get_ts_frequency;
     bufmgr_gem->bufmgr.has_bsd2 = mos_bufmgr_has_bsd2;
     bufmgr_gem->bufmgr.enable_turbo_boost = mos_bufmgr_enable_turbo_boost;
+    bufmgr_gem->bufmgr.set_fences = mos_bufmgr_set_fences;
+    bufmgr_gem->bufmgr.get_fence = mos_bufmgr_get_fence;
 
     bufmgr_gem->mem_profiler_path = getenv("MEDIA_MEMORY_PROFILER_LOG");
     if (bufmgr_gem->mem_profiler_path != nullptr)
diff --git a/media_softlet/linux/common/os/i915/mos_bufmgr_api.c b/media_softlet/linux/common/os/i915/mos_bufmgr_api.c
index 0485bf29765..bc086729c9c 100644
--- a/media_softlet/linux/common/os/i915/mos_bufmgr_api.c
+++ b/media_softlet/linux/common/os/i915/mos_bufmgr_api.c
@@ -1232,16 +1232,15 @@ mos_set_fences(struct mos_bufmgr *bufmgr, struct mos_exec_fences *exec_fences)
         return -EINVAL;
     }
 
-    return 0;
-    //todo: add func pointer to bufmgr
-    //if (bufmgr->set_fences)
-    //{
-    //    return bufmgr->set_fences(bufmgr, exec_fences);
-    //}
-    //else
-    //{
-    //    MOS_OS_CRITICALMESSAGE("Unsupported\n");
-    //}
+    if (bufmgr->set_fences)
+    {
+        return bufmgr->set_fences(bufmgr, exec_fences);
+    }
+    else
+    {
+        MOS_OS_CRITICALMESSAGE("Unsupported\n");
+        return -EPERM;
+    }
 
 }
 
@@ -1254,16 +1253,15 @@ mos_get_fence(struct mos_bufmgr *bufmgr, int32_t *fence_out)
         return -EINVAL;
     }
 
-    return 0;
-    //todo: add func pointer to bufmgr
-    //if (bufmgr->get_fence)
-    //{
-    //    return bufmgr->get_fence(bufmgr, fence_out);
-    //}
-    //else
-    //{
-    //    MOS_OS_CRITICALMESSAGE("Unsupported\n");
-    //}
+    if (bufmgr->get_fence)
+    {
+        return bufmgr->get_fence(bufmgr, fence_out);
+    }
+    else
+    {
+        MOS_OS_CRITICALMESSAGE("Unsupported\n");
+        return -EPERM;
+    }
 
 }
 
diff --git a/media_softlet/linux/common/os/i915_production/mos_bufmgr_priv.h b/media_softlet/linux/common/os/i915_production/mos_bufmgr_priv.h
index 951a640ef59..9cc5c8a3163 100644
--- a/media_softlet/linux/common/os/i915_production/mos_bufmgr_priv.h
+++ b/media_softlet/linux/common/os/i915_production/mos_bufmgr_priv.h
@@ -419,6 +419,9 @@ struct mos_bufmgr {
     uint8_t (*switch_off_n_bits)(struct mos_linux_context *ctx, uint8_t in_mask, int n) = nullptr;
     unsigned int (*hweight8)(struct mos_linux_context *ctx, uint8_t w) = nullptr;
 
+    int (*set_fences)(struct mos_bufmgr *bufmgr, struct mos_exec_fences *exec_fences) = nullptr;
+    int (*get_fence)(struct mos_bufmgr *bufmgr, int32_t *fence_out) = nullptr;
+
     /**< Enables verbose debugging printouts */
     int debug = 0;
     /** used for reserved info*/

From 1487558ed4499eeb142b06dbfae25c8c486887b4 Mon Sep 17 00:00:00 2001
From: "Xu, Zhengguo" <zhengguo.xu@intel.com>
Date: Mon, 27 May 2024 14:58:53 +0800
Subject: [PATCH 6/6] [Decode] add fence array into execbuffer in i915 drm

Signed-off-by: Xu, Zhengguo <zhengguo.xu@intel.com>
---
 .../linux/common/os/i915/mos_bufmgr.c         | 84 ++++++++++++++++++-
 .../os/xe/include/mos_synchronization_xe.h    |  1 +
 2 files changed, 82 insertions(+), 3 deletions(-)

diff --git a/media_softlet/linux/common/os/i915/mos_bufmgr.c b/media_softlet/linux/common/os/i915/mos_bufmgr.c
index 0c97ab5f3a0..b4859ab4812 100644
--- a/media_softlet/linux/common/os/i915/mos_bufmgr.c
+++ b/media_softlet/linux/common/os/i915/mos_bufmgr.c
@@ -2461,9 +2461,10 @@ mos_bufmgr_gem_destroy(struct mos_bufmgr *bufmgr)
     struct drm_gem_close close_bo;
     int ret;
 
-    free(bufmgr_gem->exec2_objects);
-    free(bufmgr_gem->exec_objects);
-    free(bufmgr_gem->exec_bos);
+    mos_safe_free(bufmgr_gem->exec2_objects);
+    mos_safe_free(bufmgr_gem->exec_objects);
+    mos_safe_free(bufmgr_gem->exec_bos);
+    mos_safe_free(bufmgr_gem->exec_fences.fences);
     pthread_mutex_destroy(&bufmgr_gem->lock);
 
     /* Free any cached buffer objects we were going to reuse */
@@ -2964,6 +2965,79 @@ mos_update_buffer_offsets2 (struct mos_bufmgr_gem *bufmgr_gem, mos_linux_context
     }
 }
 
+//todo: to move synchronization_xe.h to os common instead of xe specific
+#include "mos_synchronization_xe.h"
+
+int
+__add_eb_fence_array(struct mos_bufmgr_gem *bufmgr_gem,
+            struct drm_i915_gem_execbuffer2 *eb,
+            unsigned int flags)
+{
+#define SCALABILITY_ON (I915_EXEC_FENCE_OUT | I915_EXEC_FENCE_IN | I915_EXEC_FENCE_SUBMIT)
+
+    //Ignore multi batch submission for scalability to simplify logic
+    //todo: check has_fence_array from params
+    if (!(flags & SCALABILITY_ON)
+                && bufmgr_gem->exec_fences.fences)
+    {
+        int32_t fence_count = bufmgr_gem->exec_fences.count;
+        int32_t *exec_fences = bufmgr_gem->exec_fences.fences;
+
+        if (fence_count > 0)
+        {
+            struct drm_i915_gem_exec_fence *fences
+                = (struct drm_i915_gem_exec_fence *)malloc(fence_count * sizeof(struct drm_i915_gem_exec_fence));
+            if (fences == nullptr)
+            {
+                return -ENOMEM;
+            }
+            for (int32_t i = 0; i < fence_count; i++)
+            {
+                fences[i].handle = mos_sync_syncfile_fd_to_syncobj_handle(bufmgr_gem->fd, exec_fences[i + 1]);
+                fences[i].flags = I915_EXEC_FENCE_WAIT;
+            }
+
+            eb->num_cliprects = fence_count;
+            eb->cliprects_ptr = (uintptr_t)fences;
+            eb->flags |= I915_EXEC_FENCE_ARRAY;
+        }
+
+        eb->rsvd2 = -1;
+        eb->flags |= I915_EXEC_FENCE_OUT; //todo: to verify rsvd2 >> 32 still has fence out
+        return 0;
+    }
+    else
+    {
+        return 0;
+    }
+}
+
+void
+__clear_eb_fence_array(struct mos_bufmgr_gem *bufmgr_gem,
+            struct drm_i915_gem_execbuffer2 *eb)
+{
+    if (eb->cliprects_ptr
+                && eb->flags & I915_EXEC_FENCE_ARRAY)
+    {
+        struct drm_i915_gem_exec_fence *fences = (drm_i915_gem_exec_fence *)eb->cliprects_ptr;
+
+        for (int32_t i = 0; i < eb->num_cliprects; i++)
+        {
+            mos_sync_syncobj_destroy(bufmgr_gem->fd, fences[i].handle);
+        }
+
+        mos_safe_free(fences);
+        eb->cliprects_ptr = (uintptr_t)nullptr;
+    }
+
+    if (bufmgr_gem->exec_fences.fences
+                && eb->flags & I915_EXEC_FENCE_OUT)
+    {
+        bufmgr_gem->exec_fences.fences[0] = eb->rsvd2 >> 32;
+    }
+
+}
+
 drm_export int
 do_exec2(struct mos_linux_bo *bo, int used, struct mos_linux_context *ctx,
      drm_clip_rect_t *cliprects, int num_cliprects, int DR4,
@@ -3035,6 +3109,8 @@ do_exec2(struct mos_linux_bo *bo, int used, struct mos_linux_context *ctx,
     if (bufmgr_gem->no_exec)
         goto skip_execution;
 
+    __add_eb_fence_array(bufmgr_gem, &execbuf, flags);
+
     ret = drmIoctl(bufmgr_gem->fd,
                DRM_IOCTL_I915_GEM_EXECBUFFER2_WR,
                &execbuf);
@@ -3061,6 +3137,8 @@ do_exec2(struct mos_linux_bo *bo, int used, struct mos_linux_context *ctx,
         *fence = execbuf.rsvd2 >> 32;
     }
 
+    __clear_eb_fence_array(bufmgr_gem, &execbuf);
+
 skip_execution:
     if (bufmgr_gem->bufmgr.debug)
         mos_gem_dump_validation_list(bufmgr_gem);
diff --git a/media_softlet/linux/common/os/xe/include/mos_synchronization_xe.h b/media_softlet/linux/common/os/xe/include/mos_synchronization_xe.h
index 70f9eea57d5..a7c5511d43d 100644
--- a/media_softlet/linux/common/os/xe/include/mos_synchronization_xe.h
+++ b/media_softlet/linux/common/os/xe/include/mos_synchronization_xe.h
@@ -74,6 +74,7 @@ int mos_sync_syncobj_timeline_wait(int fd, uint32_t *handles, uint64_t *points,
             uint32_t *first_signaled);
 
 int mos_sync_syncobj_handle_to_syncfile_fd(int fd, int syncobj_handle);
+int mos_sync_syncfile_fd_to_syncobj_handle(int fd, int syncfile_fd);
 int mos_sync_import_syncfile_to_external_bo(int fd, int prime_fd, int syncfile_fd);
 int mos_sync_syncobj_timeline_to_binary(int fd, uint32_t binary_handle,
         uint32_t timeline_handle,