/*
* Copyright (c) 2009-2020, Intel Corporation
*
* Permission is hereby granted, free of charge, to any person obtaining a
* copy of this software and associated documentation files (the "Software"),
* to deal in the Software without restriction, including without limitation
* the rights to use, copy, modify, merge, publish, distribute, sublicense,
* and/or sell copies of the Software, and to permit persons to whom the
* Software is furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included
* in all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
* OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
* THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR
* OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
* ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
* OTHER DEALINGS IN THE SOFTWARE.
*/
//!
//! \file     mos_os.h
//! \brief    Common interface and structure used in MOS OS
//!

#ifndef __MOS_OS_H__
#define __MOS_OS_H__

#include "mos_defs.h"
#include "media_skuwa_specific.h"
#include "mos_utilities.h"
#include "mos_utilities_next.h"
#include "mos_util_debug_next.h"
#include "mos_os_hw.h"         //!< HW specific details that flow through OS pathes
#include "mos_os_cp_interface_specific.h"         //!< CP specific OS functionality 
#if (_RELEASE_INTERNAL || _DEBUG)
#if defined(CM_DIRECT_GUC_SUPPORT)
#include "work_queue_mngr.h"
#include "KmGucClientInterface.h"
#endif
#endif

#include "media_user_setting.h"
#include "null_hardware.h"
extern PerfUtility *g_perfutility;

#define PERF_DECODE "DECODE"
#define PERF_ENCODE "ENCODE"
#define PERF_VP "VP"
#define PERF_CP "CP"
#define PERF_MOS "MOS"

#define PERF_LEVEL_DDI "DDI"
#define PERF_LEVEL_HAL "HAL"

#define DECODE_DDI (1)
#define DECODE_HAL (1 << 1)
#define ENCODE_DDI (1 << 4)
#define ENCODE_HAL (1 << 5)
#define VP_DDI     (1 << 8)
#define VP_HAL     (1 << 9)
#define CP_DDI     (1 << 12)
#define CP_HAL     (1 << 13)
#define MOS_DDI    (1 << 16)
#define MOS_HAL    (1 << 17)

#define PERFUTILITY_IS_ENABLED(sCOMP,sLEVEL)                                                              \
    (((sCOMP == "DECODE" && sLEVEL == "DDI") && (g_perfutility->dwPerfUtilityIsEnabled & DECODE_DDI)) ||  \
     ((sCOMP == "DECODE" && sLEVEL == "HAL") && (g_perfutility->dwPerfUtilityIsEnabled & DECODE_HAL)) ||  \
     ((sCOMP == "ENCODE" && sLEVEL == "DDI") && (g_perfutility->dwPerfUtilityIsEnabled & ENCODE_DDI)) ||  \
     ((sCOMP == "ENCODE" && sLEVEL == "HAL") && (g_perfutility->dwPerfUtilityIsEnabled & ENCODE_HAL)) ||  \
     ((sCOMP == "VP" && sLEVEL == "DDI") && (g_perfutility->dwPerfUtilityIsEnabled & VP_DDI)) ||          \
     ((sCOMP == "VP" && sLEVEL == "HAL") && (g_perfutility->dwPerfUtilityIsEnabled & VP_HAL)) ||          \
     ((sCOMP == "CP" && sLEVEL == "DDI") && (g_perfutility->dwPerfUtilityIsEnabled & CP_DDI)) ||          \
     ((sCOMP == "CP" && sLEVEL == "HAL") && (g_perfutility->dwPerfUtilityIsEnabled & CP_HAL)) ||          \
     ((sCOMP == "MOS" && sLEVEL == "DDI") && (g_perfutility->dwPerfUtilityIsEnabled & MOS_DDI)) ||        \
     ((sCOMP == "MOS" && sLEVEL == "HAL") && (g_perfutility->dwPerfUtilityIsEnabled & MOS_HAL)))

#define PERF_UTILITY_START(TAG,COMP,LEVEL)                                 \
    do                                                                     \
    {                                                                      \
        if (PERFUTILITY_IS_ENABLED((std::string)COMP,(std::string)LEVEL))  \
        {                                                                  \
            g_perfutility->startTick(TAG);                                 \
        }                                                                  \
    } while(0)

#define PERF_UTILITY_STOP(TAG, COMP, LEVEL)                                \
    do                                                                     \
    {                                                                      \
        if (PERFUTILITY_IS_ENABLED((std::string)COMP,(std::string)LEVEL))  \
        {                                                                  \
            g_perfutility->stopTick(TAG);                                  \
        }                                                                  \
    } while (0)

static int perf_count_start = 0;
static int perf_count_stop = 0;

#define PERF_UTILITY_START_ONCE(TAG, COMP,LEVEL)                           \
    do                                                                     \
    {                                                                      \
        if (perf_count_start == 0                                          \
            && PERFUTILITY_IS_ENABLED((std::string)COMP,(std::string)LEVEL))  \
        {                                                                  \
                g_perfutility->startTick(TAG);                             \
        }                                                                  \
        perf_count_start++;                                                \
    } while(0)

#define PERF_UTILITY_STOP_ONCE(TAG, COMP, LEVEL)                           \
    do                                                                     \
    {                                                                      \
        if (perf_count_stop == 0                                           \
            && PERFUTILITY_IS_ENABLED((std::string)COMP,(std::string)LEVEL))  \
        {                                                                  \
            g_perfutility->stopTick(TAG);                                  \
        }                                                                  \
        perf_count_stop++;                                                 \
    } while (0)

#define PERF_UTILITY_AUTO(TAG,COMP,LEVEL) AutoPerfUtility apu(TAG,COMP,LEVEL)

#define PERF_UTILITY_PRINT                         \
    do                                             \
    {                                              \
        if (g_perfutility->dwPerfUtilityIsEnabled && MosUtilities::MosIsProfilerDumpEnabled()) \
        {                                          \
            g_perfutility->savePerfData();         \
        }                                          \
    } while(0)

class AutoPerfUtility
{
public:
    AutoPerfUtility(std::string tag, std::string comp, std::string level);
    ~AutoPerfUtility();

private:
    bool bEnable = false;
    std::string autotag ="intialized";
};

//!
//! \brief OS specific includes and definitions
//!
#include "mos_os_specific.h"
#include "mos_os_virtualengine_specific.h"

#include "mos_oca_interface.h"

#define MOS_NAL_UNIT_LENGTH                 4
#define MOS_NAL_UNIT_STARTCODE_LENGTH       3
#define MOS_MAX_PATH_LENGTH                 256

#define MOS_MAX_SEMAPHORE_COUNT             3
#define MOS_MAX_OBJECT_SIGNALED             32

#define MOS_INVALID_APPID                   0xFFFFFFFF

#define MOS_GPU_CONTEXT_CREATE_DEFAULT      1
#define MOS_GPU_CONTEXT_CREATE_CM_DEFAULT   15

#define MOS_VCS_ENGINE_USED(GpuContext) (              \
    ((GpuContext) == MOS_GPU_CONTEXT_VIDEO)         || \
    ((GpuContext) == MOS_GPU_CONTEXT_VIDEO2)        || \
    ((GpuContext) == MOS_GPU_CONTEXT_VIDEO3)        || \
    ((GpuContext) == MOS_GPU_CONTEXT_VIDEO4)        || \
    ((GpuContext) == MOS_GPU_CONTEXT_VDBOX2_VIDEO)  || \
    ((GpuContext) == MOS_GPU_CONTEXT_VDBOX2_VIDEO2) || \
    ((GpuContext) == MOS_GPU_CONTEXT_VDBOX2_VIDEO3) || \
    ((GpuContext) == MOS_GPU_CONTEXT_VIDEO5)        || \
    ((GpuContext) == MOS_GPU_CONTEXT_VIDEO6)        || \
    ((GpuContext) == MOS_GPU_CONTEXT_VIDEO7)           \
)

#define MOS_RCS_ENGINE_USED(GpuContext) (                 \
    ((GpuContext) == MOS_GPU_CONTEXT_RENDER)           || \
    ((GpuContext) == MOS_GPU_CONTEXT_RENDER2)          || \
    ((GpuContext) == MOS_GPU_CONTEXT_RENDER3)          || \
    ((GpuContext) == MOS_GPU_CONTEXT_RENDER4)          || \
    ((GpuContext) == MOS_GPU_CONTEXT_COMPUTE)          || \
    ((GpuContext) == MOS_GPU_CONTEXT_CM_COMPUTE)       || \
    ((GpuContext) == MOS_GPU_CONTEXT_COMPUTE_RA)       || \
    ((GpuContext) == MOS_GPU_CONTEXT_RENDER_RA)           \
)

#define MOS_BCS_ENGINE_USED(GpuContext) (             \
    ((GpuContext) == MOS_GPU_CONTEXT_BLT))

#if MOS_MEDIASOLO_SUPPORTED
#define MOS_VECS_ENGINE_USED(GpuContext) (             \
    ((GpuContext) == MOS_GPU_CONTEXT_VEBOX)         || \
    ((GpuContext) == MOS_GPU_CONTEXT_VEBOX2))
#else
#define MOS_VECS_ENGINE_USED(GpuContext) (             \
    ((GpuContext) == MOS_GPU_CONTEXT_VEBOX))
#endif

#define MOS_GCS_ENGINE_USED(GpuContext) (             \
    ((GpuContext) == MOS_GPU_CONTEXT_TEE))

#if MOS_COMMAND_BUFFER_DUMP_SUPPORTED
#define MOS_COMMAND_BUFFER_OUT_FILE        "Command_buffer_output"
#define MOS_COMMAND_BUFFER_OUT_DIR         "Command_buffer_dumps"
#define MOS_COMMAND_BUFFER_RENDER_ENGINE   "CS"
#define MOS_COMMAND_BUFFER_VIDEO_ENGINE    "VCS"
#define MOS_COMMAND_BUFFER_VEBOX_ENGINE    "VECS"
#define MOS_COMMAND_BUFFER_TEE_ENGINE      "TEE"
#define MOS_COMMAND_BUFFER_PLATFORM_LEN    4
#endif // MOS_COMMAND_BUFFER_DUMP_SUPPORTED

#ifndef E_NOTIMPL
#define E_NOTIMPL       0x80004001L
#endif // E_NOTIMPL

#ifndef E_UNEXPECTED
#define E_UNEXPECTED    0x8000FFFFL
#endif // E_UNEXPECTED

//!
//! \brief Enum for OS component
//!
enum MOS_COMPONENT
{
    COMPONENT_UNKNOWN = 0,
    COMPONENT_LibVA,
    COMPONENT_EMULATION,
    COMPONENT_CM,
    COMPONENT_Encode,
    COMPONENT_Decode,
    COMPONENT_VPCommon,
    COMPONENT_VPreP,
    COMPONENT_CP,
    COMPONENT_MEMDECOMP,
    COMPONENT_MCPY,
};
C_ASSERT(COMPONENT_MCPY == 10); // When adding, update assert

//!
//! \brief Structure to OS sync parameters
//!
typedef struct _MOS_SYNC_PARAMS
{
    MOS_GPU_CONTEXT        GpuContext;          //!< GPU context you would like to signal on or wait in
    PMOS_RESOURCE          presSyncResource;    //!< Has 2 meanings:
    //!< 1) a resource that requires sync, like a destination surface
    //!< 2) a resource used by HW/OS to sync between engines, like for MI_SEMAPHORE_MBOX
    uint32_t                uiSemaphoreCount;
    uint32_t                uiSemaphoreValue;           //!< Tag value in the case of resource tagging
    uint32_t                uiSemaphoreOffset;          //!< Offset into the sync resource for value read/write
    int32_t                 bReadOnly;                  //!< Marks the resource as read or write for future waits
    int32_t                 bDisableDecodeSyncLock;     //!< Disable the lock function for decode.
    int32_t                 bDisableLockForTranscode;   //!< Disable the lock function for transcode perf.
} MOS_SYNC_PARAMS, *PMOS_SYNC_PARAMS;

typedef enum _MOS_SCALABILITY_ENABLE_MODE
{
    MOS_SCALABILITY_ENABLE_MODE_FALSE      = 0,
    MOS_SCALABILITY_ENABLE_MODE_DEFAULT    = 0x0001,
    MOS_SCALABILITY_ENABLE_MODE_USER_FORCE = 0x0010
} MOS_SCALABILITY_ENABLE_MODE;

#if (_DEBUG || _RELEASE_INTERNAL)
//!
//! \brief for forcing VDBOX
//!

#define    MOS_FORCE_VDBOX_NONE     0
#define    MOS_FORCE_VDBOX_1        0x0001
#define    MOS_FORCE_VDBOX_2        0x0002
//below is for scalability case,
//format is FE vdbox is specified as lowest 4 bits; BE0 is 2nd low 4 bits; BE1 is 3rd low 4bits.
#define    MOS_FORCE_VDBOX_1_1_2    0x0211
//FE-VDBOX2, BE0-VDBOX1, BE2-VDBOX2
#define    MOS_FORCE_VDBOX_2_1_2    0x0212

//!
//! \brief Enum for forcing VEBOX
//!
typedef enum _MOS_FORCE_VEBOX
{
    MOS_FORCE_VEBOX_NONE    = 0,
    MOS_FORCE_VEBOX_1       = 0x0001,
    MOS_FORCE_VEBOX_2       = 0x0002,
    MOS_FORCE_VEBOX_3       = 0x0003,
    MOS_FORCE_VEBOX_4       = 0x0004,
    // For scalability case
    MOS_FORCE_VEBOX_1_2     = 0x0012,
    MOS_FORCE_VEBOX_1_2_3   = 0x0123,
    MOS_FORCE_VEBOX_1_2_3_4 = 0x1234
} MOS_FORCE_VEBOX;

#define MOS_FORCEVEBOX_VEBOXID_BITSNUM              4 //each VEBOX ID occupies 4 bits see defintion MOS_FORCE_VEBOX
#define MOS_FORCEVEBOX_MASK                         0xf


#define MOS_FORCEVDBOX_VDBOXID_BITSNUM              4 //each VDBOX ID occupies 4 bits see defintion MOS_FORCE_VDBOX
#define MOS_FORCEVDBOX_MASK                         0xF

#define MOS_FORCEENGINE_MASK                         0xf
#define MOS_FORCEENGINE_ENGINEID_BITSNUM             4 //each VDBOX ID occupies 4 bits see defintion MOS_FORCE_VDBOX
#define MOS_INVALID_FORCEENGINE_VALUE                0xffffffff
#endif

typedef struct _MOS_VIRTUALENGINE_INTERFACE *PMOS_VIRTUALENGINE_INTERFACE;
typedef struct _MOS_CMD_BUF_ATTRI_VE MOS_CMD_BUF_ATTRI_VE, *PMOS_CMD_BUF_ATTRI_VE;


typedef struct _MOS_COMMAND_BUFFER_ATTRIBUTES
{
    int32_t                     bTurboMode;
    int32_t                     bIsMdfLoad;
    int32_t                     bMediaPreemptionEnabled;
    uint32_t                    dwNumRequestedEUSlices;
    uint32_t                    dwNumRequestedSubSlices;
    uint32_t                    dwNumRequestedEUs;
    int32_t                     bValidPowerGatingRequest;
    int32_t                     bEnableMediaFrameTracking;
    uint32_t                    dwMediaFrameTrackingTag;
    uint32_t                    dwMediaFrameTrackingAddrOffset;
    PMOS_RESOURCE               resMediaFrameTrackingSurface;
    int32_t                     bUmdSSEUEnable;
    int32_t                     bFrequencyBoost;
    void*                       pAttriVe;
} MOS_COMMAND_BUFFER_ATTRIBUTES, *PMOS_COMMAND_BUFFER_ATTRIBUTES;

//!
//! \brief VDBOX indices
//!
typedef enum _MOS_VDBOX_NODE_IND
{
    MOS_VDBOX_NODE_INVALID     = -1,
    MOS_VDBOX_NODE_1           = 0x0,
    MOS_VDBOX_NODE_2           = 0x1
} MOS_VDBOX_NODE_IND;

//!
//! \brief VEBOX indices
//!
typedef enum _MOS_VEBOX_NODE_IND
{
    MOS_VEBOX_NODE_INVALID     = -1,
    MOS_VEBOX_NODE_1           = 0x0,
    MOS_VEBOX_NODE_2           = 0x1,
    MOS_VEBOX_NODE_3           = 0x2,
    MOS_VEBOX_NODE_4           = 0x3
} MOS_VEBOX_NODE_IND;

#define SUBMISSION_TYPE_SINGLE_PIPE                     (1 << 0)
#define SUBMISSION_TYPE_SINGLE_PIPE_MASK                (0xff)
#define SUBMISSION_TYPE_MULTI_PIPE_SHIFT                8
#define SUBMISSION_TYPE_MULTI_PIPE_ALONE                (1 << SUBMISSION_TYPE_MULTI_PIPE_SHIFT)
#define SUBMISSION_TYPE_MULTI_PIPE_MASTER               (1 << (SUBMISSION_TYPE_MULTI_PIPE_SHIFT+1))
#define SUBMISSION_TYPE_MULTI_PIPE_SLAVE                (1 << (SUBMISSION_TYPE_MULTI_PIPE_SHIFT+2))
#define SUBMISSION_TYPE_MULTI_PIPE_MASK                 (0xff << SUBMISSION_TYPE_MULTI_PIPE_SHIFT)
#define SUBMISSION_TYPE_MULTI_PIPE_SLAVE_INDEX_SHIFT    16
#define SUBMISSION_TYPE_MULTI_PIPE_SLAVE_INDEX_MASK     (0xff << SUBMISSION_TYPE_MULTI_PIPE_SLAVE_INDEX_SHIFT)
#define SUBMISSION_TYPE_MULTI_PIPE_FLAGS_SHIFT          24
#define SUBMISSION_TYPE_MULTI_PIPE_FLAGS_MASK           (0xff << SUBMISSION_TYPE_MULTI_PIPE_FLAGS_SHIFT)
#define SUBMISSION_TYPE_MULTI_PIPE_FLAGS_LAST_PIPE      (1 << SUBMISSION_TYPE_MULTI_PIPE_FLAGS_SHIFT)
typedef int32_t MOS_SUBMISSION_TYPE;

#define EXTRA_PADDING_NEEDED                            4096

//!
//! \brief Structure to command buffer
//!
typedef struct _MOS_COMMAND_BUFFER
{
    MOS_RESOURCE        OsResource;                 //!< OS Resource

    // Common fields
    uint32_t            *pCmdBase;                   //!< Base    address (CPU)
    uint32_t            *pCmdPtr;                    //!< Current address (CPU)
    int32_t             iOffset;                     //!< Current offset in bytes
    int32_t             iRemaining;                  //!< Remaining size
    int32_t             iTokenOffsetInCmdBuf;        //!< Pointer to (Un)Secure token's next field Offset
    int32_t             iCmdIndex;                   //!< command buffer's index
    MOS_VDBOX_NODE_IND  iVdboxNodeIndex;             //!< Which VDBOX buffer is binded to
    MOS_VEBOX_NODE_IND  iVeboxNodeIndex;             //!< Which VEBOX buffer is binded to
    int32_t             iSubmissionType;
    bool                is1stLvlBB;                  //!< indicate it's a first level BB or not
    struct _MOS_COMMAND_BUFFER   *cmdBuf1stLvl;      //!< Pointer to 1st level command buffer.
    MOS_COMMAND_BUFFER_ATTRIBUTES Attributes;        //!< Attributes for the command buffer to be provided to KMD at submission
} MOS_COMMAND_BUFFER;

//!
//! \brief Structure to Lock params
//!
typedef struct _MOS_LOCK_PARAMS
{
    union
    {
        struct
        {
            uint32_t ReadOnly            : 1;                                    //!< Lock only for reading.
            uint32_t WriteOnly           : 1;                                    //!< Lock only for writing.
            uint32_t TiledAsTiled        : 1;                                    //!< Means that you want to lock a tiled surface as tiled, not linear.
            uint32_t NoOverWrite         : 1;                                    //!< No Over write for async locks
            uint32_t NoDecompress        : 1;                                    //!< No decompression for memory compressed surface
            uint32_t Uncached            : 1;                                    //!< Use uncached lock
            uint32_t ForceCached         : 1;                                    //!< Prefer normal map to global GTT map(Uncached) if both can work
            uint32_t DumpBeforeSubmit    : 1;                                    //!< Lock only for dump before submit
            uint32_t DumpAfterSubmit     : 1;                                    //!< Lock only for dump after submit
            uint32_t Reserved            : 23;                                   //!< Reserved for expansion.
        };
        uint32_t    Value;
    };
} MOS_LOCK_PARAMS, *PMOS_LOCK_PARAMS;

//!
//! \brief flags for GFX allocation destroy
//!
typedef struct _MOS_GFXRES_FREE_FLAGS
{
    union
    {
        struct
        {
            uint32_t AssumeNotInUse : 1;
            uint32_t SynchronousDestroy : 1;
            uint32_t Reserved : 30;
        };
        uint32_t Value;
    };
} MOS_GFXRES_FREE_FLAGS;

//!
//! \brief Structure to Resource Flags
//!
typedef struct _MOS_GFXRES_FLAGS
{
    int32_t         bNotLockable;                                               //!< [in] true: Resource will not be CPU accessible. false: Resource can be CPU accessed.
    int32_t         bOverlay;
    int32_t         bFlipChain;
    int32_t         bSVM;
    int32_t         bCacheable;
} MOS_GFXRES_FLAGS, *PMOS_GFXRES_FLAGS;

//!
//! \brief Structure to Resource allocation parameters
//!
typedef struct _MOS_ALLOC_GFXRES_PARAMS
{
    MOS_GFXRES_TYPE     Type;                                                   //!< [in] Basic resource geometry
    MOS_GFXRES_FLAGS    Flags;                                                  //!< [in] Flags to describe attributes
    union
    {
        uint32_t        dwWidth;                                                //!< [in] Type == 2D || VOLUME, width in pixels.
        uint32_t        dwBytes;                                                //!< [in] Type == BUFFER, # of bytes
    };
    uint32_t            dwHeight;                                               //!< [in] Type == 2D || VOLUME, height in rows. Type == BUFFER, n/a
    uint32_t            dwDepth;                                                //!< [in] 0: Implies 2D resource. >=1: volume resource
    uint32_t            dwArraySize;                                            //!< [in] 0,1: 1 element. >1: N elements
    MOS_TILE_TYPE       TileType;                                               //!< [in] Defines the layout of a physical page. Optimal choice depends on usage model.
    MOS_TILE_MODE_GMM   m_tileModeByForce;                                      //!< [in] Indicates a tile Encoding (aligned w/ GMM defination) needs set by force
    MOS_FORMAT          Format;                                                 //!< [in] Pixel format
    void                *pSystemMemory;                                         //!< [in] Optional parameter. If non null, TileType must be set to linear.
    const char          *pBufName;                                              //!< [in] Optional parameter. A string indicates the buffer name and is used for debugging. nullptr is OK.
    int32_t             bIsCompressible;                                        //!< [in] Resource is compressible or not.
    MOS_RESOURCE_MMC_MODE   CompressionMode;                                    //!< [in] Compression mode.
    int32_t             bIsPersistent;                                          //!< [in] Optional parameter. Used to indicate that resource can not be evicted
    int32_t             bBypassMODImpl;
    int32_t             dwMemType;                                              //!< [in] Optional paramerter. Prefer memory type
    MOS_HW_RESOURCE_DEF ResUsageType;                                           //!< [in] the resource usage type to determine the cache policy
} MOS_ALLOC_GFXRES_PARAMS, *PMOS_ALLOC_GFXRES_PARAMS;

//!
//! \brief Enum for MOS patch type
//!
typedef enum _MOS_PATCH_TYPE
{
    MOS_PATCH_TYPE_BASE_ADDRESS = 0,
    MOS_PATCH_TYPE_PITCH,
    MOS_PATCH_TYPE_UV_Y_OFFSET,
    MOS_PATCH_TYPE_BIND_ONLY,
    MOS_PATCH_TYPE_UV_BASE_ADDRESS,
    MOS_PATCH_TYPE_V_BASE_ADDRESS,
    MOS_PATCH_TYPE_V_Y_OFFSET
} MOS_PATCH_TYPE;

//!
//! \brief Structure to OS sync parameters
//!
typedef struct _MOS_PATCH_ENTRY_PARAMS
{
    PMOS_RESOURCE presResource;      //!< resource to be patched
    uint32_t      uiAllocationIndex;
    uint32_t      uiResourceOffset;  //!< resource offset
    uint32_t      uiPatchOffset;     //!< patch offset
    uint32_t      bWrite;            //!< is write operation
    int32_t       bUpperBoundPatch;  //!< is upper bound patch
    MOS_HW_COMMAND              HwCommandType;     //!< hw cmd type
    uint32_t                    forceDwordOffset;  //!< force dword offset
    uint8_t                     *cmdBufBase; //!< cmd buffer base address
    uint32_t                    offsetInSSH; //!< patch offset in SSH
    uint32_t                    shiftAmount; //!< shift amount for patch
    uint32_t                    shiftDirection; //!< shift direction for patch
    MOS_PATCH_TYPE              patchType;   //!< patch type
    MOS_COMMAND_BUFFER          *cmdBuffer;  //!< command buffer
} MOS_PATCH_ENTRY_PARAMS, *PMOS_PATCH_ENTRY_PARAMS;

typedef struct _MOS_GPUCTX_CREATOPTIONS MOS_GPUCTX_CREATOPTIONS, *PMOS_GPUCTX_CREATOPTIONS;
struct _MOS_GPUCTX_CREATOPTIONS
{
    uint32_t CmdBufferNumScale;
    uint32_t RAMode;
    uint32_t ProtectMode;
    uint32_t gpuNode;
    //For slice shutdown
    union
    {
        struct
        {
            uint8_t SliceCount;
            uint8_t SubSliceCount;  //Subslice count per slice
            uint8_t MaxEUcountPerSubSlice;
            uint8_t MinEUcountPerSubSlice;
        } packed;

        uint32_t SSEUValue;
    };

    _MOS_GPUCTX_CREATOPTIONS() : CmdBufferNumScale(MOS_GPU_CONTEXT_CREATE_DEFAULT),
        RAMode(0),
        ProtectMode(0),
        gpuNode(0),
        SSEUValue(0){}

    virtual ~_MOS_GPUCTX_CREATOPTIONS(){}
};

class OsContext;

#if MOS_COMMAND_RESINFO_DUMP_SUPPORTED
//!
//! \brief Class to Dump GPU Command Info
//!
class GpuCmdResInfoDump
{
public:

    static const GpuCmdResInfoDump *GetInstance(PMOS_CONTEXT mosCtx);
    GpuCmdResInfoDump(PMOS_CONTEXT mosCtx);

    void Dump(PMOS_INTERFACE pOsInterface) const;

    void StoreCmdResPtr(PMOS_INTERFACE pOsInterface, const void *pRes) const;

    void ClearCmdResPtrs(PMOS_INTERFACE pOsInterface) const;

private:

    struct GpuCmdResInfo;

    void Dump(const void *pRes, std::ofstream &outputFile) const;

    const std::vector<const void *> &GetCmdResPtrs(PMOS_INTERFACE pOsInterface) const;

    const char *GetResType(MOS_GFXRES_TYPE resType) const;

    const char *GetTileType(MOS_TILE_TYPE tileType) const;

private:

    static std::shared_ptr<GpuCmdResInfoDump> m_instance;
    mutable uint32_t         m_cnt         = 0;
    bool                     m_dumpEnabled = false;
    std::string              m_path;
};
#endif // MOS_COMMAND_RESINFO_DUMP_SUPPORTED

class OsContextNext;
typedef void *      OS_PER_STREAM_PARAMETERS;
typedef void *      EXTRA_PARAMS;
typedef OsContextNext OsDeviceContext;
typedef _MOS_GPUCTX_CREATOPTIONS GpuContextCreateOption;
struct _MOS_INTERFACE;
class MosVeInterface;
class CommandList;
class CmdBufMgrNext;

struct MosStreamState
{
    OsDeviceContext   *osDeviceContext = nullptr;
    GPU_CONTEXT_HANDLE currentGpuContextHandle = MOS_GPU_CONTEXT_INVALID_HANDLE;
    MOS_COMPONENT      component;

    CommandList        *currentCmdList      = nullptr;  //<! Command list used in async mode
    CmdBufMgrNext      *currentCmdBufMgr    = nullptr;  //<! Cmd buffer manager used in async mode
    bool                postponedExecution  = false;    //!< Indicate if the stream is work in postponed execution mode. This flag is only used in aync mode.

    bool supportVirtualEngine = false; //!< Flag to indicate using virtual engine interface
    MosVeInterface *virtualEngineInterface = nullptr; //!< Interface to virtual engine state
    bool useHwSemaForResSyncInVe = false; //!< Flag to indicate if UMD need to send HW sema cmd under this OS when there is a resource sync need with Virtual Engine interface
    bool veEnable = false;                //!< Flag to indicate virtual engine enabled (Can enable VE without using virtual engine interface)
    bool phasedSubmission = false;        //!< Flag to indicate if secondary command buffers are submitted together or separately due to different OS
    bool frameSplit = true;               //!< Flag to indicate if frame split is enabled (only active when phasedSubmission is true)
    int32_t hcpDecScalabilityMode = 0;   //!< Hcp scalability mode
    int32_t veboxScalabilityMode  = 0;    //!< Vebox scalability mode

    bool ctxBasedScheduling = false;  //!< Indicate if context based scheduling is enabled in this stream
    bool multiNodeScaling = false;    //!< Flag to indicate if multi-node scaling is enabled for virtual engine (only active when ctxBasedScheduling is true)

    int32_t ctxPriority = 0;
    bool softReset = false;  //!< trigger soft reset

    MosCpInterface *osCpInterface = nullptr; //!< CP interface

    bool mediaReset    = false;  //!< Flag to indicate media reset is enabled

    bool simIsActive = false;  //!< Flag to indicate if Simulation is enabled
    MOS_NULL_RENDERING_FLAGS nullHwAccelerationEnable = {};     //!< To indicate which components to enable Null HW support

    bool usesPatchList = false;               //!< Uses patch list instead of graphic address directly
    bool usesGfxAddress = false;              //!< Uses graphic address directly instead of patch list
    bool enableKmdMediaFrameTracking = false; //!< Enable KMD Media frame tracking
    bool usesCmdBufHeaderInResize = false;    //!< Use cmd buffer header in resize
    bool usesCmdBufHeader = false;            //!< Use cmd buffer header

    // GPU Reset Statistics
    uint32_t gpuResetCount      = 0;
    uint32_t gpuActiveBatch     = 0;
    uint32_t gpuPendingBatch    = 0;

#if MOS_COMMAND_BUFFER_DUMP_SUPPORTED
    // Command buffer dump
    bool  dumpCommandBuffer = false;                      //!< Flag to indicate if Dump command buffer is enabled
    bool  dumpCommandBufferToFile = false;                //!< Indicates that the command buffer should be dumped to a file
    bool  dumpCommandBufferAsMessages = false;            //!< Indicates that the command buffer should be dumped via MOS normal messages
    char  sDirName[MOS_MAX_HLT_FILENAME_LEN] = {0};       //!< Dump Directory name - maximum 260 bytes length
#endif // MOS_COMMAND_BUFFER_DUMP_SUPPORTED

#if _DEBUG || _RELEASE_INTERNAL
    bool  enableDbgOvrdInVirtualEngine = false; //!< enable debug override in virtual engine

    int32_t eForceVdbox = 0;  //!< Force select Vdbox
    int32_t eForceVebox = 0;  //!< Force select Vebox
#endif // _DEBUG || _RELEASE_INTERNAL

    bool  bGucSubmission     = false;  //!< Flag to indicate if guc submission is enabled
    OS_PER_STREAM_PARAMETERS  perStreamParameters = nullptr; //!< Parameters of OS specific per stream
};

// OS agnostic MOS objects
typedef OsDeviceContext *MOS_DEVICE_HANDLE;
typedef MosStreamState  *MOS_STREAM_HANDLE;
//typedef uint32_t             GPU_CONTEXT_HANDLE;
typedef MOS_COMMAND_BUFFER *COMMAND_BUFFER_HANDLE;
typedef MOS_RESOURCE       *MOS_RESOURCE_HANDLE;
typedef MosVeInterface     *MOS_VE_HANDLE;

// OS specific MOS objects
typedef void *              OsSpecificRes;       //!< stand for different os specific resource structure (or info)
typedef void *              OS_HANDLE;           //!< stand for different os handles
typedef MOS_SURFACE         MosResourceInfo;
typedef void *              DDI_DEVICE_CONTEXT;  //!< stand for different os specific device context
typedef void *              MOS_INTERFACE_HANDLE;

class GpuContextMgr;
//!
//! \brief Structure to Unified HAL OS resources
//!
typedef struct _MOS_INTERFACE
{
    //APO WRAPPER
    MOS_STREAM_HANDLE osStreamState = MOS_INVALID_HANDLE; 

    // Saved OS context
    PMOS_CONTEXT                    pOsContext;
    MOS_GPU_CONTEXT                 CurrentGpuContextOrdinal;
    //!< An internal handle that indexes into the list of GPU Context object
    uint32_t                        CurrentGpuContextHandle;
    //!< A handle to the graphics context device that can be used to calls back
    //!< into the kernel subsystem
    HANDLE                          CurrentGpuContextRuntimeHandle;

    //!< Only used in async mode for backward compatiable
    GPU_CONTEXT_HANDLE              m_GpuContextHandleMap[MOS_GPU_CONTEXT_MAX] = {0};

    // OS dependent settings, flags, limits
    int32_t                         b64bit;
    int32_t                         bDeallocateOnExit;
    MOS_USER_FEATURE_INTERFACE      UserFeatureInterface;
    MosCpInterface                  *osCpInterface;

    int32_t                         bUsesCmdBufHeader;
    int32_t                         bUsesCmdBufHeaderInResize;
    int32_t                         bEnableKmdMediaFrameTracking;
    int32_t                         bNoParsingAssistanceInKmd;
    bool                            bPitchAndUVPatchingNeeded = false;
    uint32_t                        dwCommandBufferReservedSpace;
    uint32_t                        dwNumNalUnitBytesIncluded;

    // GPU Reset Statistics
    uint32_t                        dwGPUResetCount;
    uint32_t                        dwGPUActiveBatch;
    uint32_t                        dwGPUPendingBatch;

    // Resource addressing
    int32_t                         bUsesPatchList;
    int32_t                         bUsesGfxAddress;
    int32_t                         bMapOnCreate;                           // For limited GPU VA resource can not be mapped during creation
    int32_t                         bInlineCodecStatusUpdate;               // check whether use inline codec status update or seperate BB
    int32_t                         bAllowExtraPatchToSameLoc;              // patch another resource to same location in cmdbuffer

    // Component info
    MOS_COMPONENT                   Component;

    // Stream info
    uint32_t                        streamIndex = 0;

    // Synchronization
    int32_t                         bTagEngineSync;
    int32_t                         bTagResourceSync;
    int32_t                         bOsEngineSync;
    int32_t                         bOsResourceSync;

    // Simulation (HAS) related
    int32_t                         bSimIsActive;                                   //!< Flag to indicate if HAS is enabled

    MOS_NULL_RENDERING_FLAGS        NullHWAccelerationEnable;                    //!< To indicate which components to enable Null HW support

    // for MODS Wrapper
    int32_t                         modulizedMosEnabled;
    int32_t                         modularizedGpuCtxEnabled;
    OsContext*                      osContextPtr;

    // used for media reset enabling/disabling in UMD
    // pls remove it after hw scheduling
    int32_t                         bMediaReset;

    bool                            umdMediaResetEnable;

#if MOS_MEDIASOLO_SUPPORTED
    // MediaSolo related
    int32_t                         bSoloInUse;                                   //!< Flag to indicate if MediaSolo is enabled
    static void                    *pvSoloContext;                                //!< pointer to MediaSolo context
    static uint32_t                 soloRefCnt;
    uint32_t                        dwEnableMediaSoloFrameNum;                    //!< The frame number at which MediaSolo will be enabled, 0 is not valid.
#endif // MOS_MEDIASOLO_SUPPORTED

#if MOS_COMMAND_BUFFER_DUMP_SUPPORTED
    // Command buffer dump
    int32_t                         bDumpCommandBuffer;                                //!< Flag to indicate if Dump command buffer is enabled
    int32_t                         bDumpCommandBufferToFile;                          //!< Indicates that the command buffer should be dumped to a file
    int32_t                         bDumpCommandBufferAsMessages;                      //!< Indicates that the command buffer should be dumped via MOS normal messages
    char                            sPlatformName[MOS_COMMAND_BUFFER_PLATFORM_LEN];    //!< Platform name - maximum 4 bytes length
    char                            sDirName[MOS_MAX_HLT_FILENAME_LEN];                //!< Dump Directory name - maximum 260 bytes length
#endif // MOS_COMMAND_BUFFER_DUMP_SUPPORTED

#if (_RELEASE_INTERNAL||_DEBUG)
#if defined(CM_DIRECT_GUC_SUPPORT)
    CMRTWorkQueueMngr          *m_pWorkQueueMngr;
    CMRT_WORK_QUEUE_INFO       m_WorkQueueInfo[5];  //IGFX_ABSOLUTE_MAX_ENGINES
#endif
#endif

    bool                            bEnableVdboxBalancing;                            //!< Enable per BB VDBox balancing

#if (_DEBUG || _RELEASE_INTERNAL)
    int                             eForceVdbox;                                  //!< Force select Vdbox
    uint32_t                        dwForceTileYfYs;                              // force to allocate Yf (=1) or Ys (=2), remove after full validation
    int32_t                         bTriggerCodecHang;                            // trigger GPU HANG in codec
    int32_t                         bTriggerVPHang;                               //!< trigger GPU HANG in VP
#endif // (_DEBUG || _RELEASE_INTERNAL)

    bool                            apoMosEnabled;                                //!< apo mos or not

    MEMORY_OBJECT_CONTROL_STATE (* pfnCachePolicyGetMemoryObject) (
        MOS_HW_RESOURCE_DEF         Usage,
        GMM_CLIENT_CONTEXT          *pGmmClientContext);

    uint8_t (* pfnCachePolicyGetL1Config) (
            MOS_HW_RESOURCE_DEF         Usage,
            GMM_CLIENT_CONTEXT          *pGmmClientContext);

    MOS_STATUS (* pfnCreateGpuContext) (
        PMOS_INTERFACE              pOsInterface,
        MOS_GPU_CONTEXT             GpuContext,
        MOS_GPU_NODE                GpuNode,
        PMOS_GPUCTX_CREATOPTIONS    createOption);

    GPU_CONTEXT_HANDLE (*pfnCreateGpuComputeContext) (
        PMOS_INTERFACE          osInterface,
        MOS_GPU_CONTEXT         gpuContext,
        MOS_GPUCTX_CREATOPTIONS *createOption);

    MOS_STATUS (* pfnDestroyGpuContext) (
        PMOS_INTERFACE              pOsInterface,
        MOS_GPU_CONTEXT             GpuContext);

    MOS_STATUS (* pfnDestroyGpuComputeContext) (
        PMOS_INTERFACE              osInterface,
        GPU_CONTEXT_HANDLE          gpuContextHandle);

    MOS_STATUS (* pfnSetGpuContext) (
        PMOS_INTERFACE              pOsInterface,
        MOS_GPU_CONTEXT             GpuContext);

    MOS_STATUS (*pfnSetGpuContextFromHandle)(PMOS_INTERFACE osInterface,
                                             MOS_GPU_CONTEXT contextName,
                                             GPU_CONTEXT_HANDLE contextHandle);

    MOS_STATUS (*pfnSetGpuContextHandle) (
        PMOS_INTERFACE     pOsInterface,
        GPU_CONTEXT_HANDLE gpuContextHandle,
        MOS_GPU_CONTEXT    GpuContext);

    GpuContextMgr* (*pfnGetGpuContextMgr) (
        PMOS_INTERFACE     pOsInterface);

#if (_RELEASE_INTERNAL || _DEBUG)
#if defined(CM_DIRECT_GUC_SUPPORT)
    MOS_STATUS(*pfnDestroyGuC) (
        PMOS_INTERFACE              pOsInterface);
    MOS_STATUS(*pfnInitGuC) (
        PMOS_INTERFACE              pOsInterface,
        MOS_GPU_NODE                 Engine);
    MOS_STATUS(*pfnSubmitWorkQueue) (
        PMOS_INTERFACE pOsInterface,
        MOS_GPU_NODE Engine,
        uint64_t BatchBufferAddress);
#endif
#endif

    MOS_GPU_CONTEXT (* pfnGetGpuContext) (
        PMOS_INTERFACE              pOsInterface);

    void* (*pfnGetGpuContextbyHandle)(
        PMOS_INTERFACE              pOsInterface,
        const GPU_CONTEXT_HANDLE    gpuContextHandle);

    GMM_CLIENT_CONTEXT* (* pfnGetGmmClientContext) (
        PMOS_INTERFACE              pOsInterface);

    MOS_STATUS (* pfnIsGpuContextValid) (
        PMOS_INTERFACE              pOsInterface,
        MOS_GPU_CONTEXT             GpuContext);

    void (* pfnSetEncodeEncContext) (
        PMOS_INTERFACE              pOsInterface,
        MOS_GPU_CONTEXT             GpuContext);

    void (* pfnSetEncodePakContext) (
        PMOS_INTERFACE              pOsInterface,
        MOS_GPU_CONTEXT             GpuContext);

    void (* pfnSyncOnResource) (
        PMOS_INTERFACE              pOsInterface,
        PMOS_RESOURCE               pOsResource,
        MOS_GPU_CONTEXT             requestorGPUCtx,
        int32_t                     bWriteOperation);

    void (* pfnSyncOnOverlayResource) (
        PMOS_INTERFACE              pOsInterface,
        PMOS_RESOURCE               pOsResource,
        MOS_GPU_CONTEXT             requestorGPUCtx);

    void (* pfnSetResourceSyncTag) (
        PMOS_INTERFACE              pOsInterface,
        PMOS_SYNC_PARAMS            pParams);

    MOS_STATUS (* pfnPerformOverlaySync) (
        PMOS_INTERFACE              pOsInterface,
        PMOS_SYNC_PARAMS            pParams);

    MOS_STATUS (* pfnResourceSignal) (
        PMOS_INTERFACE              pOsInterface,
        PMOS_SYNC_PARAMS            pParams);

    MOS_STATUS (* pfnResourceWait) (
        PMOS_INTERFACE              pOsInterface,
        PMOS_SYNC_PARAMS            pParams);

    MOS_STATUS (* pfnEngineSignal) (
        PMOS_INTERFACE              pOsInterface,
        PMOS_SYNC_PARAMS            pParams);

    MOS_STATUS (* pfnEngineWait) (
        PMOS_INTERFACE              pOsInterface,
        PMOS_SYNC_PARAMS            pParams);

    MOS_STATUS (* pfnWaitAllCmdCompletion) (
        PMOS_INTERFACE              pOsInterface);

    MOS_STATUS (* pfnCreateSyncResource) (
        PMOS_INTERFACE              pOsInterface,
        PMOS_RESOURCE               pOsResource);

    MOS_STATUS (* pfnDestroySyncResource) (
        PMOS_INTERFACE              pOsInterface,
        PMOS_RESOURCE               pOsResource);

    void (* pfnSyncGpuContext) (
        PMOS_INTERFACE              pOsInterface,
        MOS_GPU_CONTEXT             busyGPUCtx,
        MOS_GPU_CONTEXT             requestorGPUCtx);

    void(* pfnSyncWith3DContext)(
        PMOS_INTERFACE              pOsInterface,
        PMOS_SYNC_PARAMS            pParams);

    MOS_STATUS (* pfnRegisterBBCompleteNotifyEvent) (
        PMOS_INTERFACE              pOsInterface,
        MOS_GPU_CONTEXT             GpuContext);

    MOS_STATUS (* pfnWaitForBBCompleteNotifyEvent) (
        PMOS_INTERFACE              pOsInterface,
        MOS_GPU_CONTEXT             GpuContext,
        uint32_t                    uiTimeOut);

    void (* pfnDestroy) (
        PMOS_INTERFACE              pOsInterface,
        int32_t                     bDestroyVscVppDeviceTag);

    void (* pfnGetPlatform) (
        PMOS_INTERFACE              pOsInterface,
        PLATFORM                    *pPlatform);

    MEDIA_FEATURE_TABLE *(* pfnGetSkuTable) (
        PMOS_INTERFACE              pOsInterface);

    MEDIA_WA_TABLE *(* pfnGetWaTable) (
        PMOS_INTERFACE              pOsInterface);

    MEDIA_SYSTEM_INFO *(* pfnGetGtSystemInfo)(
        PMOS_INTERFACE     pOsInterface);

    MOS_STATUS (*pfnGetMediaEngineInfo)(
        PMOS_INTERFACE     pOsInterface, MEDIA_ENGINE_INFO &info);

    void (* pfnResetOsStates) (
        PMOS_INTERFACE              pOsInterface);

    MOS_STATUS(* pfnInitializeMultiThreadingSyncTags) (
        PMOS_INTERFACE              pOsInterface,
        PMOS_RESOURCE               pOsResource,
        uint8_t                     ucRenderTargetIndex,
        PMOS_SEMAPHORE              *pCurFrmSem,
        PMOS_SEMAPHORE              *pRefFrmSem,
        PMOS_MUTEX                  *pFrmMutex);

    MOS_STATUS (* pfnMultiThreadingWaitCurrentFrame) (
        PMOS_RESOURCE               pOsResource);

    MOS_STATUS (* pfnMultiThreadingPostCurrentFrame) (
        PMOS_RESOURCE               pOsResource);

    MOS_STATUS (* pfnMultiThreadResourceSync) (
        PMOS_INTERFACE              pOsInterface,
        PMOS_RESOURCE               pOsResource);

    MOS_STATUS(*pfnSetHybridDecoderRunningFlag) (
        PMOS_INTERFACE              pOsInterface,
        int32_t                     bFlag);

    MOS_STATUS(*pfnGetHybridDecoderRunningFlag) (
        PMOS_INTERFACE              pOsInterface,
        int32_t                     *pFlag);

#if MOS_MESSAGES_ENABLED

    #define pfnAllocateResource(pOsInterface, pParams, pOsResource) \
       pfnAllocateResource(pOsInterface, pParams, __FUNCTION__, __FILE__, __LINE__, pOsResource)

    MOS_STATUS (* pfnAllocateResource) (
        PMOS_INTERFACE              pOsInterface,
        PMOS_ALLOC_GFXRES_PARAMS    pParams,
        const char                  *functionName,
        const char                  *filename,
        int32_t                     line,
        PMOS_RESOURCE               pOsResource);

    MOS_STATUS (* pfnDumpCommandBuffer) (
        PMOS_INTERFACE              pOsInterface,
        PMOS_COMMAND_BUFFER         pCmdBuffer);

    #define pfnFreeResource(pOsInterface, pResource) \
       pfnFreeResource(pOsInterface, __FUNCTION__, __FILE__, __LINE__, pResource)

    void (* pfnFreeResource) (
        PMOS_INTERFACE              pOsInterface,
        const char                  *functionName,
        const char                  *filename,
        int32_t                     line,
        PMOS_RESOURCE               pResource);
    
    #define pfnFreeResourceWithFlag(pOsInterface, pResource, uiFlag) \
       pfnFreeResourceWithFlag(pOsInterface, pResource, __FUNCTION__, __FILE__, __LINE__, uiFlag)

    void (* pfnFreeResourceWithFlag) (
        PMOS_INTERFACE              pOsInterface,
        PMOS_RESOURCE               pResource,
        const char                  *functionName,
        const char                  *filename,
        int32_t                     line,
        uint32_t                    uiFlag);

#else

    MOS_STATUS (* pfnAllocateResource) (
        PMOS_INTERFACE              pOsInterface,
        PMOS_ALLOC_GFXRES_PARAMS    pParams,
        PMOS_RESOURCE               pOsResource);

    void (* pfnFreeResource) (
        PMOS_INTERFACE              pOsInterface,
        PMOS_RESOURCE               pResource);

    void (* pfnFreeResourceWithFlag) (
        PMOS_INTERFACE              pOsInterface,
        PMOS_RESOURCE               pResource,
        uint32_t                    uiFlag);

#endif // MOS_MESSAGES_ENABLED

    MOS_STATUS (* pfnGetResourceInfo) (
        PMOS_INTERFACE              pOsInterface,
        PMOS_RESOURCE               pOsResource,
        PMOS_SURFACE                pDetails);

    MOS_STATUS (* pfnLockSyncRequest) (
        PMOS_INTERFACE              pOsInterface,
        PMOS_RESOURCE               pResource,
        PMOS_LOCK_PARAMS            pFlags);

    void  *(* pfnLockResource) (
        PMOS_INTERFACE              pOsInterface,
        PMOS_RESOURCE               pResource,
        PMOS_LOCK_PARAMS            pFlags);

    MOS_STATUS (* pfnUnlockResource) (
        PMOS_INTERFACE              pOsInterface,
        PMOS_RESOURCE               pResource);

    MOS_STATUS (* pfnDecompResource) (
        PMOS_INTERFACE              pOsInterface,
        PMOS_RESOURCE               pResource);

    MOS_STATUS(*pfnDoubleBufferCopyResource) (
        PMOS_INTERFACE        pOsInterface,
        PMOS_RESOURCE         pInputOsResource,
        PMOS_RESOURCE         pOutputOsResource,
        bool                  bOutputCompressed);

    MOS_STATUS(*pfnMediaCopyResource2D) (
        PMOS_INTERFACE        pOsInterface,
        PMOS_RESOURCE         pInputOsResource,
        PMOS_RESOURCE         pOutputOsResource,
        uint32_t              copyWidth,
        uint32_t              copyHeight,
        uint32_t              copyInputOffset,
        uint32_t              copyOutputOffset,
        uint32_t              bpp,
        bool                  bOutputCompressed);

    MOS_STATUS(*pfnGetMosContext) (
        PMOS_INTERFACE        pOsInterface,
        PMOS_CONTEXT*         mosContext);

    MOS_STATUS (* pfnFillResource) (
        PMOS_INTERFACE              pOsInterface,
        PMOS_RESOURCE               pResource,
        uint32_t                    dwSize,
        uint8_t                     iValue);

    MOS_STATUS (*pfnUpdateResourceUsageType) (
        PMOS_RESOURCE           pOsResource,
        MOS_HW_RESOURCE_DEF     resUsageType);

    MOS_STATUS (* pfnRegisterResource) (
        PMOS_INTERFACE              pOsInterface,
        PMOS_RESOURCE               pResource,
        int32_t                     bWrite,
        int32_t                     bWritebSetResourceSyncTag);

    void (* pfnResetResourceAllocationIndex) (
        PMOS_INTERFACE              pOsInterface,
        PMOS_RESOURCE               pResource);

    int32_t (* pfnGetResourceAllocationIndex) (
        PMOS_INTERFACE              pOsInterface,
        PMOS_RESOURCE               pResource);

    uint64_t (* pfnGetResourceGfxAddress) (
        PMOS_INTERFACE              pOsInterface,
        PMOS_RESOURCE               pResource);

    MOS_STATUS (* pfnSetPatchEntry) (
        PMOS_INTERFACE              pOsInterface,
        PMOS_PATCH_ENTRY_PARAMS     pParams);

#if MOS_MEDIASOLO_SUPPORTED
    MOS_STATUS (* pfnInitializeMediaSolo) (
        PMOS_INTERFACE              pOsInterface);
#endif // MOS_MEDIASOLO_SUPPORTED

    MOS_STATUS (* pfnWaitOnResource) (
        PMOS_INTERFACE              pOsInterface,
        PMOS_RESOURCE               pResource);

    uint32_t (* pfnGetGpuStatusTag) (
        PMOS_INTERFACE              pOsInterface,
        MOS_GPU_CONTEXT             GpuContext);

    void (* pfnIncrementGpuStatusTag) (
        PMOS_INTERFACE              pOsInterface,
        MOS_GPU_CONTEXT             GpuContext);

    uint32_t (* pfnGetGpuStatusTagOffset) (
        PMOS_INTERFACE              pOsInterface,
        MOS_GPU_CONTEXT             GpuContext);

    uint32_t (* pfnGetGpuStatusSyncTag) (
        PMOS_INTERFACE              pOsInterface,
        MOS_GPU_CONTEXT             GpuContext);

    MOS_STATUS (* pfnVerifyCommandBufferSize) (
        PMOS_INTERFACE              pOsInterface,
        uint32_t                    dwRequestedSize,
        uint32_t                    dwFlags);

    MOS_STATUS (* pfnResizeCommandBufferAndPatchList) (
        PMOS_INTERFACE              pOsInterface,
        uint32_t                    dwRequestedCommandBufferSize,
        uint32_t                    dwRequestedPatchListSize,
        uint32_t                    dwFlags);

    MOS_STATUS (* pfnGetCommandBuffer) (
        PMOS_INTERFACE              pOsInterface,
        PMOS_COMMAND_BUFFER         pCmdBuffer,
        uint32_t                    dwFlags);

    MOS_STATUS (* pfnSetIndirectStateSize) (
        PMOS_INTERFACE              pOsInterface,
        uint32_t                    uSize);

    MOS_STATUS (* pfnGetIndirectState) (
        PMOS_INTERFACE              pOsInterface,
        uint32_t                    *puOffset,
        uint32_t                    *puSize);

    MOS_STATUS (* pfnGetIndirectStatePointer) (
        PMOS_INTERFACE              pOsInterface,
        uint8_t                     **pIndirectState);

    void (* pfnReturnCommandBuffer) (
        PMOS_INTERFACE              pOsInterface,
        PMOS_COMMAND_BUFFER         pCmdBuffer,
        uint32_t                    dwFlags);

    MOS_STATUS (* pfnSubmitCommandBuffer) (
        PMOS_INTERFACE              pOsInterface,
        PMOS_COMMAND_BUFFER         pCmdBuffer,
        int32_t                     bNullRendering);

    MOS_STATUS (* pfnWaitAndReleaseCmdBuffer) (
        PMOS_INTERFACE              pOsInterface,
        PMOS_COMMAND_BUFFER         pCmdBuffer);

    MOS_FORMAT (* pfnFmt_OsToMos) (
        MOS_OS_FORMAT               format);

    MOS_OS_FORMAT (* pfnFmt_MosToOs) (
        MOS_FORMAT                  format);

    GMM_RESOURCE_FORMAT (* pfnFmt_MosToGmm) (
        MOS_FORMAT                  format);

    void (* pfnSetPerfTag) (
        PMOS_INTERFACE              pOsInterface,
        uint32_t                    PerfTag);

    uint32_t(* pfnGetPerfTag) (
        PMOS_INTERFACE              pOsInterface);

    void (* pfnResetPerfBufferID) (
        PMOS_INTERFACE              pOsInterface);

    void (* pfnIncPerfFrameID) (
        PMOS_INTERFACE              pOsInterface);

    void (* pfnIncPerfBufferID) (
        PMOS_INTERFACE              pOsInterface);

    void (* pfnSetPerfHybridKernelID) (
        PMOS_INTERFACE              pOsInterface,
        uint32_t                    KernelID);

    int32_t (* pfnIsPerfTagSet) (
        PMOS_INTERFACE              pOsInterface);

    MOS_STATUS (* pfnGetBitsPerPixel) (
        PMOS_INTERFACE              pOsInterface,
        MOS_FORMAT                  Format,
        uint32_t                    *piBpp);

    MOS_STATUS (*pfnLoadLibrary) (
        PMOS_INTERFACE              pOsInterface,
        const char                  *pFileName,
        PHMODULE                    phModule);

    MOS_STATUS (*pfnFreeLibrary) (
        HINSTANCE                   hInstance);

    void (*pfnLogData)(
        char                        *pData);

    MOS_NULL_RENDERING_FLAGS  (* pfnGetNullHWRenderFlags) (
        PMOS_INTERFACE              pOsInterface);

    MOS_STATUS (* pfnSetCmdBufferDebugInfo) (
        PMOS_INTERFACE              pOsInterface,
        int32_t                     bSamplerState,
        int32_t                     bSurfaceState,
        uint32_t                    dwStateIndex,
        uint32_t                    dwType);

    uint32_t (* pfnGetCmdBufferDebugInfo) (
        PMOS_INTERFACE              pOsInterface,
        int32_t                     bSamplerState,
        int32_t                     bSurfaceState,
        uint32_t                    dwStateIndex);

    MOS_STATUS (*pfnGetGpuStatusBufferResource) (
        PMOS_INTERFACE              pOsInterface,
        PMOS_RESOURCE               &pOsResource);

    MOS_STATUS (* pfnVerifyPatchListSize) (
        PMOS_INTERFACE              pOsInterface,
        uint32_t                    dwRequestedSize);

    MOS_STATUS (* pfnResetCommandBuffer) (
        PMOS_INTERFACE              pOsInterface,
        PMOS_COMMAND_BUFFER         pCmdBuffer);

    MOS_STATUS (* pfnGetMemoryCompressionMode) (
        PMOS_INTERFACE              pOsInterface,
        PMOS_RESOURCE               pOsResource,
        PMOS_MEMCOMP_STATE          pResMmcMode);

    MOS_STATUS (* pfnSetMemoryCompressionMode) (
        PMOS_INTERFACE              pOsInterface,
        PMOS_RESOURCE               pOsResource,
        MOS_MEMCOMP_STATE           ResMmcMode);

    MOS_STATUS (* pfnSetMemoryCompressionHint) (
        PMOS_INTERFACE              pOsInterface,
        PMOS_RESOURCE               pOsResource,
        int32_t                     bHintOn);

    MOS_STATUS (* pfnGetMemoryCompressionFormat) (
        PMOS_INTERFACE              pOsInterface,
        PMOS_RESOURCE               pOsResource,
        uint32_t                    *pResMmcFormat);

    MOS_STATUS (* pfnCreateVideoNodeAssociation)(
        PMOS_INTERFACE              pOsInterface,
        int32_t                     bSetVideoNode,
        MOS_GPU_NODE                *pVideoNodeOrdinal);

    MOS_VDBOX_NODE_IND (* pfnGetVdboxNodeId)(
        PMOS_INTERFACE              pOsInterface,
        PMOS_COMMAND_BUFFER         pCmdBuffer);

    MOS_STATUS (* pfnDestroyVideoNodeAssociation)(
        PMOS_INTERFACE              pOsInterface,
        MOS_GPU_NODE                VideoNodeOrdinal);

    int32_t (*pfnSetCpuCacheability)(
        PMOS_INTERFACE              pOsInterface,
        PMOS_ALLOC_GFXRES_PARAMS    pParams);

    MOS_STATUS(*pfnSkipResourceSync)(
        PMOS_RESOURCE               pOsResource);

    MOS_STATUS(*pfnSetObjectCapture)(
        PMOS_RESOURCE               pOsResource);

    MOS_STATUS(*pfnSkipResourceSyncDynamic)(
        PMOS_RESOURCE               pOsResource);

    MOS_STATUS(*pfnEnableResourceSyncDynamic)(
        PMOS_RESOURCE               pOsResource);

    bool(*pfnIsValidStreamID)(
        PMOS_RESOURCE               pOsResource);

    void(*pfnInvalidateStreamID)(
        PMOS_RESOURCE               pOsResource);

    MOS_STATUS(*pfnSetStreamID)(
        PMOS_RESOURCE               pOsResource,
        PMOS_INTERFACE              pOsInterface,
        uint8_t                     streamID);

    uint8_t(*pfnGetStreamID)(
        PMOS_RESOURCE               pOsResource);

    int32_t (*pfnIsGPUHung)(
        PMOS_INTERFACE              pOsInterface);

    //!
    //! \brief    Get Aux Table base address
    //!
    //! \param    [in] pOsInterface
    //!             MOS_INTERFACE pointer
    //! \return   uint64_t 
    //!           return Aux Table base address
    //!
    uint64_t(*pfnGetAuxTableBaseAddr)(
        PMOS_INTERFACE              pOsInterface);

    //!
    //! \brief    Get Gpu Priority
    //! \param    [in] pOsInterface
    //!           pointer to the current gpu context.
    //! \param    [out] pPriority
    //!           pointer to the priority get from gpu context.
    //!
    void (*pfnGetGpuPriority)(
        PMOS_INTERFACE              pOsInterface,
        int32_t                     *pPriority);

    //!
    //! \brief    Set Gpu Priority
    //!
    //! \param    [in] pOsInterface
    //!           pointer to the current gpu context
    //! \param    [in] priority
    //!           pointer to the priority set to gpu context
    //!
    void (*pfnSetGpuPriority)(
        PMOS_INTERFACE              pOsInterface,
        int32_t                     priority);

    //!
    //! \brief  Set slice count to shared memory and KMD
    //! \param  [in] pOsInterface
    //!         pointer to the requested slice count for current context
    //! \param  [out] pSliceCount
    //!         pointer to the ruling slice count shared by all contexts
    void (*pfnSetSliceCount)(
        PMOS_INTERFACE              pOsInterface,
        uint32_t *pSliceCount);

    //!
    //! \brief  Get resource index
    //! \param  [in] osResource
    //!         pointer to the resource
    //! \return uint32_t 
    //!         return resource index
    uint32_t(*pfnGetResourceIndex)(
        PMOS_RESOURCE           osResource);

    //!
    //! \brief    Get SetMarker enabled flag
    //! \details  Get SetMarker enabled flag from OsInterface
    //! \param    PMOS_INTERFACE pOsInterface
    //!           [in] OS Interface
    //! \return   bool
    //!           SetMarker enabled flag
    //!
    bool (*pfnIsSetMarkerEnabled)(
        PMOS_INTERFACE              pOsInterface);

    //!
    //! \brief    Get SetMarker resource address
    //! \details  Get SetMarker resource address from OsInterface
    //! \param    PMOS_INTERFACE pOsInterface
    //!           [in] OS Interface
    //! \return   PMOS_RESOURCE
    //!           SetMarker resource address
    //!
    PMOS_RESOURCE (*pfnGetMarkerResource)(
        PMOS_INTERFACE              pOsInterface);

    //!
    //! \brief    Notify shared Stream index
    //!
    //! \param    PMOS_INTERFACE pOsInterface
    //!           [in] OS Interface
    //! \return   void
    //!
    void (*pfnNotifyStreamIndexSharing)(
        PMOS_INTERFACE              pOsInterface);

    // Virtual Engine related
    int32_t                         bSupportVirtualEngine;                        //!< Enable virtual engine flag
    int32_t                         bUseHwSemaForResSyncInVE;                     //!< Flag to indicate if UMD need to send HW sema cmd under this OS when there is a resource sync need with Virtual Engine interface 
    PMOS_VIRTUALENGINE_INTERFACE    pVEInterf;
    bool                            ctxBasedScheduling;                           //!< Flag to indicate if context based scheduling enabled for virtual engine, that is VE2.0.
    bool                            multiNodeScaling;                             //!< Flag to indicate if multi-node scaling is enabled for virtual engine, that is VE3.0.
    bool                            veDefaultEnable = true;                       //!< Flag to indicate if virtual engine is enabled by default
    bool                            phasedSubmission = false;                     //!< Flag to indicate if secondary command buffers are submitted together (Win) or separately (Linux)
    bool                            frameSplit = true;                            //!< Flag to indicate if frame split is enabled
    bool                            bSetHandleInvalid = false;
    bool                            bGucSubmission = false;                       //!< Flag to indicate if guc submission is enabled
    MOS_CMD_BUF_ATTRI_VE            bufAttriVe[MOS_GPU_CONTEXT_MAX];

    MOS_STATUS (*pfnCheckVirtualEngineSupported)(
        PMOS_INTERFACE              pOsInterface);

#if MOS_MEDIASOLO_SUPPORTED
    int32_t                         bSupportMediaSoloVirtualEngine;               //!< Flag to indicate if MediaSolo uses VE solution in cmdbuffer submission.
#endif // MOS_MEDIASOLO_SUPPORTED
    bool                            VEEnable;
    bool                            bCanEnableSecureRt;

    int32_t                         bHcpDecScalabilityMode;                       //!< enable scalability decode {mode: default, user force, false}
#if (_DEBUG || _RELEASE_INTERNAL)
    MOS_FORCE_VEBOX                 eForceVebox;                                  //!< Force select Vebox
    int32_t                         bEnableDbgOvrdInVE;                           //!< It is for all scalable engines: used together with KMD VE for UMD to specify an engine directly
    int32_t                         bSoftReset;                                   //!< trigger soft reset
#endif // (_DEBUG || _RELEASE_INTERNAL)
    bool streamStateIniter = false;

    int32_t                         bVeboxScalabilityMode;                        //!< Enable scalability vebox

    bool                            bOptimizeCpuTiming;                           //!< Optimize Cpu Timing

    //!< os interface extension
    void                            *pOsExt;
} MOS_INTERFACE;

#ifdef __cplusplus
extern "C" {
#endif

//! \brief    Unified OS Initializes OS Interface
//! \details  OS Interface initilization
//! \param    PMOS_INTERFACE pOsInterface
//!           [in/out] Pointer to OS Interface
//! \param    PMOS_CONTEXT pOsDriverContext
//!           [in] Pointer to Driver context
//! \return   MOS_STATUS
//!           Return MOS_STATUS_SUCCESS if successful, otherwise failed
//!
MOS_STATUS Mos_InitInterface(
    PMOS_INTERFACE      pOsInterface,
    PMOS_CONTEXT        pOsDriverContext,
    MOS_COMPONENT       component);

//! \brief    Destroy the mos interface
//! \details  MOS Interface release
//! \param    PMOS_INTERFACE pOsInterface
//!           [in/out] Pointer to OS Interface
//! \return   MOS_STATUS
//!           Return MOS_STATUS_SUCCESS if successful, otherwise failed
//!
MOS_STATUS Mos_DestroyInterface(PMOS_INTERFACE pOsInterface);

//! \brief    Unified OS add command to command buffer
//! \details  Offset returned is dword aligned but size requested can be byte aligned
//! \param    PMOS_COMMAND_BUFFER pCmdBuffer
//!           [in/out] Pointer to Command Buffer
//! \param    void  *pCmd
//!           [in] Command Pointer
//! \param    uint32_t dwCmdSize
//!           [in] Size of command in bytes
//! \return   MOS_STATUS
//!           Return MOS_STATUS_SUCCESS if successful, otherwise failed
//!
MOS_STATUS Mos_AddCommand(
    PMOS_COMMAND_BUFFER pCmdBuffer,
    const void          *pCmd,
    uint32_t            dwCmdSize);

//! \brief    Unified OS get uf path info
//! \details  return a pointer to the user feature key path info
//! \param    PMOS_CONTEXT mosContext
//!           [in/out] Pointer to mosContext
//! \return   MOS_USER_FEATURE_KEY_PATH_INFO*
//!           Return a poniter to user feature path info
//!
MOS_USER_FEATURE_KEY_PATH_INFO *Mos_GetDeviceUfPathInfo(
    PMOS_CONTEXT mosContext);


#if !EMUL
//!
//! \brief    Get memory object based on resource usage
//! \details  Get memory object based on resource usage
//! \param    MOS_HW_RESOURCE_DEF MosUsage
//!           [in] Current usage for resource
//!           [in] Gmm client context
//! \return   MEMORY_OBJECT_CONTROL_STATE
//!           Populated memory object
//!
MEMORY_OBJECT_CONTROL_STATE Mos_CachePolicyGetMemoryObject(
    MOS_HW_RESOURCE_DEF MosUsage,
    GMM_CLIENT_CONTEXT  *pGmmClientContext);

#endif

#ifdef __cplusplus
}
#endif

typedef struct _MOS_GPUCTX_CREATOPTIONS_ENHANCED MOS_GPUCTX_CREATOPTIONS_ENHANCED, *PMOS_GPUCTX_CREATOPTIONS_ENHANCED;
struct _MOS_GPUCTX_CREATOPTIONS_ENHANCED : public _MOS_GPUCTX_CREATOPTIONS
{
    union
    {
        struct
        {
            uint32_t    UsingSFC : 1;
            uint32_t    Reserved1 : 1; // remove HWRestrictedEngine
#if (_DEBUG || _RELEASE_INTERNAL)
            uint32_t    Reserved : 29;
            uint32_t    DebugOverride : 1; // Debug & validation usage only
#else
            uint32_t    Reserved : 30;
#endif
        };
        uint32_t    Flags;
    };

    uint32_t    LRCACount;

#if (_DEBUG || _RELEASE_INTERNAL)
    // Logical engine instances used by this context; valid only if flag DebugOverride is set.
    uint8_t    EngineInstance[MOS_MAX_ENGINE_INSTANCE_PER_CLASS];
#endif

    _MOS_GPUCTX_CREATOPTIONS_ENHANCED()
        : Flags(0),
        LRCACount(0)
    {
#if (_DEBUG || _RELEASE_INTERNAL)
        for (auto i = 0; i < MOS_MAX_ENGINE_INSTANCE_PER_CLASS; i++)
        {
            EngineInstance[i] = 0xff;
        }
#endif
    }
};

#define MOS_VE_SUPPORTED(pOsInterface) \
    (pOsInterface ? pOsInterface->bSupportVirtualEngine : false)

#define MOS_VE_CTXBASEDSCHEDULING_SUPPORTED(pOsInterface) \
    (pOsInterface ? pOsInterface->ctxBasedScheduling : false)

#define MOS_VE_MULTINODESCALING_SUPPORTED(pOsInterface) \
    (pOsInterface ? pOsInterface->multiNodeScaling : false)

#if MOS_MEDIASOLO_SUPPORTED
#define MOS_MEDIASOLO_VE_SUPPORTED(pOsInterface) \
    (pOsInterface ? pOsInterface->bSupportMediaSoloVirtualEngine : false)
#endif

__inline void Mos_SetVirtualEngineSupported(PMOS_INTERFACE pOsInterface, bool bEnabled)
{
    if (pOsInterface && pOsInterface->veDefaultEnable)
    {
        pOsInterface->bSupportVirtualEngine = bEnabled;
    }
}

//!
//! \brief    Check virtual engine is supported
//! \details  Check virtual engine is supported
//! \param    PMOS_INTERFACE pOsInterface
//!           [in] OS Interface
//! \return   MOS_STATUS
//!           MOS_STATUS_SUCCESS if succeeded, otherwise error code
//!
MOS_STATUS Mos_CheckVirtualEngineSupported(
    PMOS_INTERFACE osInterface,
    bool           isDecode,
    bool           veDefaultEnable);

struct ContextRequirement
{
    bool IsEnc               = false;
    bool IsPak               = false;
    bool IsContextSwitchBack = false;
};

#endif  // __MOS_OS_H__
