blob: 27a5674874114f713d769e34c1508a229cb4ee06 [file] [log] [blame]
/*
* Copyright (c) 2009-2021, 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_specific.c
//! \brief Common interface used in MOS LINUX OS
//! \details Common interface used in MOS LINUX OS
//!
#include "mos_os.h"
#include "mos_util_debug.h"
#include "mos_resource_defs.h"
#include <unistd.h>
#include <dlfcn.h>
#include "hwinfo_linux.h"
#include "media_fourcc.h"
#include <stdlib.h>
#include "mos_graphicsresource.h"
#include "mos_context_specific.h"
#include "mos_gpucontext_specific.h"
#include "mos_gpucontextmgr.h"
#include "mos_graphicsresource_next.h"
#include "mos_context_specific_next.h"
#include "mos_gpucontext_specific_next.h"
#include "mos_gpucontextmgr_next.h"
#include "mos_interface.h"
#if MOS_MEDIASOLO_SUPPORTED
#include "mos_os_solo.h"
#endif // MOS_MEDIASOLO_SUPPORTED
#include "mos_solo_generic.h"
#ifndef ANDROID
#include <sys/ipc.h>
#include <sys/shm.h>
#include <sys/sem.h>
#include <sys/types.h>
#endif
#include "mos_os_virtualengine.h"
#include "mos_util_user_interface.h"
#include "mos_os_virtualengine_singlepipe_next.h"
#include "mos_os_virtualengine_scalability_next.h"
#include "memory_policy_manager.h"
#if defined(USE_MAGMA)
#include "magma_fd.h"
#endif
//!
//! \brief DRM VMAP patch
//!
#define Y_TILE_WIDTH 128
#define Y_TILE_HEIGHT 32
#define X_TILE_WIDTH 512
#define X_TILE_HEIGHT 8
#define MI_BATCHBUFFER_END 0x05000000
//!
//! \brief Two VDBOX shared memory key
//!
#define DUAL_VDBOX_KEY ('D'<<24|'V'<<8|'X'<<0)
//============= PRIVATE FUNCTIONS <BEGIN>=========================================
bool SetupApoMosSwitch(int32_t fd)
{
if (fd < 0)
{
return false;
}
//Read user feature to determine if apg mos is enabled.
uint32_t userfeatureValue = 0;
MOS_STATUS estatus = MosUtilities::MosReadApoMosEnabledUserFeature(userfeatureValue);
if(estatus == MOS_STATUS_SUCCESS)
{
return (userfeatureValue != 0);
}
PRODUCT_FAMILY eProductFamily = IGFX_UNKNOWN;
HWInfo_GetGfxProductFamily(fd, eProductFamily);
if (eProductFamily >= IGFX_TIGERLAKE_LP)
{
return true;
}
return false;
}
//!
//! \brief Clear Gpu Context
//! \details OS GPU context clear
//! \param PMOS_RESOURCE pContext
//! [in] Pointer to OS context
//! \return void
//! Return NONE
//!
void Mos_Specific_ClearGpuContext(MOS_CONTEXT *pContext)
{
int32_t iLoop = 0;
MOS_OS_FUNCTION_ENTER;
if (nullptr == pContext)
{
MOS_OS_ASSERTMESSAGE("Input mos context is null");
return;
}
for (iLoop = 0; iLoop < MOS_GPU_CONTEXT_MAX; iLoop++)
{
if (pContext->OsGpuContext[iLoop].pCB != nullptr)
{
MOS_FreeMemory(pContext->OsGpuContext[iLoop].pCB);
pContext->OsGpuContext[iLoop].pCB = nullptr;
}
if (pContext->OsGpuContext[iLoop].pAllocationList != nullptr)
{
MOS_FreeMemory(pContext->OsGpuContext[iLoop].pAllocationList);
pContext->OsGpuContext[iLoop].pAllocationList = nullptr;
}
if (pContext->OsGpuContext[iLoop].pPatchLocationList)
{
MOS_FreeMemory(pContext->OsGpuContext[iLoop].pPatchLocationList);
pContext->OsGpuContext[iLoop].pPatchLocationList = nullptr;
}
if (pContext->OsGpuContext[iLoop].pResources != nullptr)
{
MOS_FreeMemory(pContext->OsGpuContext[iLoop].pResources);
pContext->OsGpuContext[iLoop].pResources = nullptr;
}
if (pContext->OsGpuContext[iLoop].pbWriteMode != nullptr)
{
MOS_FreeMemory(pContext->OsGpuContext[iLoop].pbWriteMode);
pContext->OsGpuContext[iLoop].pbWriteMode = nullptr;
}
pContext->OsGpuContext[iLoop].uiMaxNumAllocations = 0;
pContext->OsGpuContext[iLoop].uiMaxPatchLocationsize = 0;
}
}
//!
//! \brief Unified OS get command buffer
//! \details Return the pointer to the next available space in Cmd Buffer
//! \param PMOS_CONTEXT pOsContext
//! [in] Pointer to OS Context
//! \param PMOS_COMMAND_BUFFER pCmdBuffer
//! [out] Pointer to Command Buffer
//! \param int32_t iSize
//! [out] Size of command in bytes
//! \return int32_t
//! Return true is there is space
//!
int32_t Linux_GetCommandBuffer(
PMOS_CONTEXT pOsContext,
PMOS_COMMAND_BUFFER pCmdBuffer,
int32_t iSize)
{
int32_t bResult = false;
MOS_LINUX_BO *cmd_bo = nullptr;
if ( pOsContext == nullptr ||
pCmdBuffer == nullptr)
{
bResult = false;
MOS_OS_ASSERTMESSAGE("Linux_GetCommandBuffer:pOsContext == nullptr || pCmdBuffer == NULL");
goto finish;
}
// Allocate the command buffer from GEM
cmd_bo = mos_bo_alloc(pOsContext->bufmgr,"MOS CmdBuf",iSize,4096, MOS_MEMPOOL_SYSTEMMEMORY); // Align to page boundary
if (cmd_bo == nullptr)
{
MOS_OS_ASSERTMESSAGE("Allocation of command buffer failed.");
bResult = false;
goto finish;
}
//MOS_OS_NORMALMESSAGE("alloc CMB, bo is 0x%x.", cmd_bo);
// Map command buffer to user virtual address
if (mos_bo_map(cmd_bo,1) != 0) // Write enable set
{
MOS_OS_ASSERTMESSAGE("Mapping of command buffer failed.");
bResult = false;
goto finish;
}
Mos_ResetResource(&pCmdBuffer->OsResource);
// Fill in resource information
pCmdBuffer->OsResource.Format = Format_Buffer;
pCmdBuffer->OsResource.iWidth = cmd_bo->size;
pCmdBuffer->OsResource.iHeight = 1;
pCmdBuffer->OsResource.iPitch = cmd_bo->size;
pCmdBuffer->OsResource.iSize = pCmdBuffer->OsResource.iPitch * pCmdBuffer->OsResource.iHeight;
pCmdBuffer->OsResource.iCount = 1;
pCmdBuffer->OsResource.pData = (uint8_t*)cmd_bo->virt;
pCmdBuffer->OsResource.TileType = MOS_TILE_LINEAR;
pCmdBuffer->OsResource.bo = cmd_bo;
pCmdBuffer->OsResource.bMapped = true;
// for MOS wrapper to avoid memory leak
pCmdBuffer->OsResource.bConvertedFromDDIResource = true;
pCmdBuffer->pCmdBase = (uint32_t*)cmd_bo->virt;
pCmdBuffer->pCmdPtr = (uint32_t*)cmd_bo->virt;
pCmdBuffer->iOffset = 0;
pCmdBuffer->iRemaining = cmd_bo->size;
pCmdBuffer->iCmdIndex = -1;
pCmdBuffer->iVdboxNodeIndex = MOS_VDBOX_NODE_INVALID;
pCmdBuffer->iVeboxNodeIndex = MOS_VEBOX_NODE_INVALID;
pCmdBuffer->is1stLvlBB = true;
MOS_ZeroMemory(pCmdBuffer->pCmdBase, cmd_bo->size);
pCmdBuffer->iSubmissionType = SUBMISSION_TYPE_SINGLE_PIPE;
MOS_ZeroMemory(&pCmdBuffer->Attributes, sizeof(pCmdBuffer->Attributes));
bResult = true;
finish:
if ((false == bResult)&&(nullptr != cmd_bo)){
//need to unreference command buffer allocated.
mos_bo_unreference(cmd_bo);
}
return bResult;
}
//!
//! \brief Get unused command buffer space
//! \details Return unused command buffer space
//! \param PMOS_CONTEXT pOsContext
//! [in] Pointer to OS Context
//! \param MOS_GPU_CONTEXT GpuContext
//! [in] GPU context
//! \param PMOS_COMMAND_BUFFER pCmdBuffer
//! [out] Pointer to Command buffer
//! \return void
//!
void Linux_ReturnCommandBuffer(
PMOS_CONTEXT pOsContext,
MOS_GPU_CONTEXT GpuContext,
PMOS_COMMAND_BUFFER pCmdBuffer)
{
MOS_OS_GPU_CONTEXT *pOsGpuContext;
if (pOsContext == nullptr || pCmdBuffer == nullptr ||
Mos_ResourceIsNull(&(pCmdBuffer->OsResource)))
{
MOS_OS_ASSERTMESSAGE("Invalid input parameter pOsContext or pCmdBuffer.");
goto finish;
}
if (GpuContext == MOS_GPU_CONTEXT_INVALID_HANDLE)
{
MOS_OS_ASSERTMESSAGE("Invalid input parameter GpuContext.");
goto finish;
}
pOsGpuContext = &pOsContext->OsGpuContext[GpuContext];
if (pOsContext == nullptr)
{
MOS_OS_ASSERTMESSAGE("Os gpucontext is null.");
goto finish;
}
pOsGpuContext->pCB->iOffset = pCmdBuffer->iOffset ;
pOsGpuContext->pCB->iRemaining = pCmdBuffer->iRemaining;
pOsGpuContext->pCB->pCmdPtr = pCmdBuffer->pCmdPtr;
pOsGpuContext->pCB->iVdboxNodeIndex = pCmdBuffer->iVdboxNodeIndex;
pOsGpuContext->pCB->iVeboxNodeIndex = pCmdBuffer->iVeboxNodeIndex;
pOsGpuContext->pCB->is1stLvlBB = pCmdBuffer->is1stLvlBB;
finish:
return;
}
//!
//! \brief Flush Command Buffer
//! \details Flush Command Buffer space
//! \param PMOS_CONTEXT pOsContext
//! [in] Pointer to OS Context
//! \param MOS_GPU_CONTEXT GpuContext
//! [in] GPU context
//! \return int32_t
//! true if succeeded, false if failed or invalid parameters
//!
int32_t Linux_FlushCommandBuffer(
PMOS_CONTEXT pOsContext,
MOS_GPU_CONTEXT GpuContext)
{
PCOMMAND_BUFFER pCurrCB;
int32_t bResult = false;
PMOS_OS_GPU_CONTEXT pOsGpuContext;
if (pOsContext == nullptr)
{
MOS_OS_ASSERTMESSAGE("Invalid input parameter pOsContext.")
goto finish;
}
if (GpuContext == MOS_GPU_CONTEXT_INVALID_HANDLE)
{
MOS_OS_ASSERTMESSAGE("Invalid input parameter GpuContext.");
goto finish;
}
pOsGpuContext = &pOsContext->OsGpuContext[GpuContext];
if (pOsGpuContext == nullptr)
{
MOS_OS_ASSERTMESSAGE("Invalid OsGpuContext");
goto finish;
}
// Refresh command buffer usage
pOsContext->pfnRefresh(pOsContext);
pOsGpuContext->uiCurrentNumPatchLocations = 0;
// CB already active
pCurrCB = pOsGpuContext->pCurrentCB;
if (pCurrCB == nullptr)
{
MOS_OS_ASSERTMESSAGE("Invalid current CB in OsGpuContext.");
goto finish;
}
if (pCurrCB->bActive)
{
goto finish;
}
pCurrCB->bActive = true;
bResult = true;
finish:
return bResult;
}
//!
//! \brief Init command buffer pool
//! \details Initilize the command buffer pool
//! \param PMOS_CONTEXT pOsContext
//! [in] Pointer to OS Context
//! \return void
//!
void Linux_InitCmdBufferPool(
PMOS_CONTEXT pOsContext)
{
MOS_OS_FUNCTION_ENTER;
MOS_ZeroMemory(&pOsContext->CmdBufferPool, sizeof(CMD_BUFFER_BO_POOL));
pOsContext->CmdBufferPool.iFetch = 0;
}
//!
//! \brief Wait and release command buffer
//! \details Command buffer Wait and release
//! \param PMOS_CONTEXT pOsContext
//! [in] Pointer to OS context structure
//! \param int32_t index
//! [in] Command buffer's index in Command buffer pool
//! \return MOS_STATUS
//! Return MOS_STATUS_SUCCESS if successful, otherwise failed
//!
MOS_STATUS Linux_WaitAndReleaseCmdBuffer(
PMOS_CONTEXT pOsContext,
int32_t index)
{
MOS_LINUX_BO *cmd_bo;
MOS_STATUS eStatus;
MOS_OS_FUNCTION_ENTER;
eStatus = MOS_STATUS_SUCCESS;
MOS_OS_CHK_NULL(pOsContext);
if (index < 0 || index >= MAX_CMD_BUF_NUM)
{
eStatus = MOS_STATUS_INVALID_PARAMETER;
goto finish;
}
// According to the logic of CmdBufferPool now, the command buffer is used in a circular way.
// The input index always points to the next(oldest) buffer after the latest(newest) buffer.
// If the next buffer is not empty (!= nullptr), all the buffers in the pool will also be not empty.
// So it's not necessary to check all buffers to see whether there's empty buffer.
cmd_bo = pOsContext->CmdBufferPool.pCmd_bo[index];
if (cmd_bo != nullptr)
{
mos_bo_wait_rendering(cmd_bo);
mos_bo_unreference(cmd_bo);
pOsContext->CmdBufferPool.pCmd_bo[index] = nullptr;
}
finish:
return eStatus;
}
//!
//! \brief Release command buffer pool
//! \details Release command buffer pool until all of commands are finished.
//! \param PMOS_CONTEXT pOsContext
//! [in] Pointer to OS context structure
//! \return MOS_STATUS
//! Return MOS_STATUS_SUCCESS if successful, otherwise failed
//!
MOS_STATUS Linux_ReleaseCmdBufferPool(PMOS_CONTEXT pOsContext)
{
int32_t i;
MOS_STATUS eStatus;
MOS_OS_FUNCTION_ENTER;
eStatus = MOS_STATUS_SUCCESS;
MOS_OS_CHK_NULL(pOsContext);
for (i = 0; i < MAX_CMD_BUF_NUM; i++)
{
MOS_OS_CHK_STATUS(Linux_WaitAndReleaseCmdBuffer(pOsContext, i));
}
finish:
return eStatus;
}
//!
//! \brief Wait for the fetch command
//! \details Wait for the fetch command bo until it is available
//! \param PMOS_CONTEXT pOsContext
//! [in] Pointer to OS context structure
//! \return MOS_STATUS
//! Return MOS_STATUS_SUCCESS if successful, otherwise failed
//!
MOS_STATUS Linux_WaitForAvailableCmdBo(
PMOS_CONTEXT pOsContext)
{
int32_t index;
MOS_STATUS eStatus;
MOS_OS_FUNCTION_ENTER;
eStatus = MOS_STATUS_SUCCESS;
MOS_OS_CHK_NULL(pOsContext);
index = pOsContext->CmdBufferPool.iFetch;
MOS_OS_CHK_STATUS(Linux_WaitAndReleaseCmdBuffer(pOsContext, index));
finish:
return eStatus;
}
//!
//! \brief Insert command buffer
//! \details Insert command buffer into pool
//! \param PMOS_CONTEXT pOsContext
//! [in] Pointer to OS context structure
//! \param PMOS_COMMAND_BUFFER pCmdBuffer
//! [in] Pointer to command buffer struct
//! \return MOS_STATUS
//! Return MOS_STATUS_SUCCESS if successful, otherwise failed
//!
MOS_STATUS Linux_InsertCmdBufferToPool(
PMOS_CONTEXT pOsContext,
PMOS_COMMAND_BUFFER pCmdBuffer)
{
int32_t index = 0;
MOS_STATUS eStatus;
MOS_OS_FUNCTION_ENTER;
eStatus = MOS_STATUS_SUCCESS;
MOS_OS_CHK_NULL(pOsContext);
MOS_OS_CHK_NULL(pCmdBuffer);
MOS_OS_CHK_STATUS(Linux_WaitForAvailableCmdBo(pOsContext));
index = pOsContext->CmdBufferPool.iFetch;
pOsContext->CmdBufferPool.pCmd_bo[index] = pCmdBuffer->OsResource.bo;
pCmdBuffer->iCmdIndex = index;
pOsContext->CmdBufferPool.iFetch++;
if (pOsContext->CmdBufferPool.iFetch >= MAX_CMD_BUF_NUM)
{
pOsContext->CmdBufferPool.iFetch = 0;
}
finish:
return eStatus;
}
//!
//! \brief Linux Refresh
//! \details Linux Refresh
//! \param MOS_CONTEXT * pOsContext
//! [in] Pointer to OS context structure
//! \return int32_t
//! true always
//!
int32_t Linux_Refresh(MOS_CONTEXT *pOsContext)
{
MOS_UNUSED(pOsContext);
return true;
}
#ifndef ANDROID
#define MOS_LINUX_IPC_INVALID_ID -1
#define MOS_LINUX_SHM_INVALID (void *)-1
#define MOS_LINUX_SEM_MAX_TRIES 10
#if !defined(__Fuchsia__)
static MOS_STATUS DetachDestroyShm(int32_t shmid, void *pShm)
{
struct shmid_ds buf;
MOS_ZeroMemory(&buf, sizeof(buf));
if (shmid < 0)
{
return MOS_STATUS_UNKNOWN;
}
if ((pShm != MOS_LINUX_SHM_INVALID) && (pShm != nullptr) && shmdt(pShm) < 0)
{
return MOS_STATUS_UNKNOWN;
}
if (shmctl(shmid, IPC_STAT, &buf) < 0)
{
return MOS_STATUS_UNKNOWN;
}
if (buf.shm_nattch == 0)
{
if (shmctl(shmid, IPC_RMID, nullptr) < 0)
{
return MOS_STATUS_UNKNOWN;
}
}
return MOS_STATUS_SUCCESS;
}
static MOS_STATUS ConnectCreateShm(long key, uint32_t size, int32_t *pShmid, void **ppShm)
{
MOS_STATUS eStatus = MOS_STATUS_SUCCESS;
MOS_OS_CHK_NULL_RETURN(pShmid);
MOS_OS_CHK_NULL_RETURN(ppShm);
struct shmid_ds buf;
int32_t shmid = -1;
key_t key_value = (key_t)key;
void * shmptr = nullptr;
MOS_ZeroMemory(&buf, sizeof(buf));
shmid = shmget(key_value, size, IPC_CREAT | 0666);
if (shmid < 0)
{
return MOS_STATUS_UNKNOWN;
}
shmptr = shmat(shmid, 0, 0);
if (shmptr == MOS_LINUX_SHM_INVALID)
{
DetachDestroyShm(shmid, shmptr);
return MOS_STATUS_UNKNOWN;
}
if (shmctl(shmid, IPC_STAT, &buf) < 0)
{
// can't get any status info
DetachDestroyShm(shmid, shmptr);
return MOS_STATUS_UNKNOWN;
}
*ppShm = shmptr;
*pShmid = shmid;
return MOS_STATUS_SUCCESS;
}
static MOS_STATUS ConnectCreateSemaphore(long key, int32_t *pSemid)
{
MOS_STATUS eStatus = MOS_STATUS_SUCCESS;
MOS_OS_CHK_NULL_RETURN(pSemid);
int32_t semid = -1;
struct sembuf sop;
struct semid_ds buf;
uint32_t i = 0;
key_t key_value = (key_t)key;
int32_t val = 0;
MOS_ZeroMemory(&sop, sizeof(sop));
MOS_ZeroMemory(&buf, sizeof(buf));
semid = semget(key, 1, IPC_CREAT | IPC_EXCL | 0666);
if (semid != MOS_LINUX_IPC_INVALID_ID)
{
// initialize it to 0
if (semctl(semid, 0, SETVAL, val) == -1)
{
return MOS_STATUS_UNKNOWN;
}
// Perform a "no-op" semaphore operation - changes sem_otime
// so other processes can see we've initialized the set.
sop.sem_num = 0;
sop.sem_op = 0; //Wait for value to equal 0
sop.sem_flg = 0;
if (semop(semid, &sop, 1) == -1)
{
return MOS_STATUS_UNKNOWN;
}
}
else
{
// errno EEXIST
semid = semget(key, 1, 0666);
if (semid == MOS_LINUX_IPC_INVALID_ID)
{
return MOS_STATUS_UNKNOWN;
}
}
*pSemid = semid;
return MOS_STATUS_SUCCESS;
}
static MOS_STATUS DestroySemaphore(int32_t semid)
{
int32_t nwait = -1;
if (semid < 0)
{
return MOS_STATUS_UNKNOWN;
}
nwait = semctl(semid, 0, GETZCNT, 0);
if (nwait > 0)
{
return MOS_STATUS_SUCCESS;
}
if (semctl(semid, 0, IPC_RMID, nullptr) < 0)
{
return MOS_STATUS_UNKNOWN;
}
return MOS_STATUS_SUCCESS;
}
static int16_t ShmAttachedNumber(int32_t shmid)
{
struct shmid_ds buf;
MOS_ZeroMemory(&buf, sizeof(buf));
if (shmctl(shmid, IPC_STAT, &buf) < 0)
{
return -1;
}
return buf.shm_nattch;
}
#endif
static MOS_STATUS LockSemaphore(int32_t semid)
{
struct sembuf op[2];
op[0].sem_num = 0; // wait for [0] to be 0
op[0].sem_op = 0;
op[0].sem_flg = 0;
op[1].sem_num = 0;
op[1].sem_op = 1; // increment
op[1].sem_flg = SEM_UNDO;
if (semid < 0)
{
return MOS_STATUS_UNKNOWN;
}
if (semop(semid, op, 2) < 0)
{
return MOS_STATUS_UNKNOWN;
}
return MOS_STATUS_SUCCESS;
}
static MOS_STATUS UnLockSemaphore(int32_t semid)
{
struct sembuf op;
op.sem_num = 0;
op.sem_op = -1; // decrement back to 0
op.sem_flg = SEM_UNDO;
if (semid < 0)
{
return MOS_STATUS_UNKNOWN;
}
if (semop(semid, &op, 1) < 0)
{
return MOS_STATUS_UNKNOWN;
}
return MOS_STATUS_SUCCESS;
}
#if !defined(__Fuchsia__)
void DestroyIPC(PMOS_CONTEXT pOsContext)
{
if (MOS_LINUX_IPC_INVALID_ID != pOsContext->semid)
{
int16_t iAttachedNum = 0;
if (MOS_LINUX_IPC_INVALID_ID != pOsContext->shmid)
{
LockSemaphore(pOsContext->semid);
iAttachedNum = ShmAttachedNumber(pOsContext->shmid);
DetachDestroyShm(pOsContext->shmid, pOsContext->pShm);
pOsContext->shmid = MOS_LINUX_IPC_INVALID_ID;
pOsContext->pShm = MOS_LINUX_SHM_INVALID;
if (iAttachedNum) --iAttachedNum;
UnLockSemaphore(pOsContext->semid);
}
}
}
MOS_STATUS CreateIPC(PMOS_CONTEXT pOsContext)
{
MOS_STATUS eStatus;
MOS_OS_CHK_NULL(pOsContext);
pOsContext->semid = MOS_LINUX_IPC_INVALID_ID;
pOsContext->shmid = MOS_LINUX_IPC_INVALID_ID;
pOsContext->pShm = MOS_LINUX_SHM_INVALID;
struct semid_ds buf;
MOS_ZeroMemory(&buf, sizeof(buf));
//wait and retry untill to get a valid semaphore
for (int i = 0; i < MOS_LINUX_SEM_MAX_TRIES; i ++)
{
ConnectCreateSemaphore(DUAL_VDBOX_KEY, &pOsContext->semid);
//check whether the semid is initialized or not
if (semctl(pOsContext->semid, 0, IPC_STAT, &buf) == -1)
{
return MOS_STATUS_UNKNOWN;
}
if (buf.sem_otime != 0)
{
break;
}
MOS_Sleep(1); //wait and retry
}
LockSemaphore(pOsContext->semid);
eStatus = ConnectCreateShm(DUAL_VDBOX_KEY, sizeof(VDBOX_WORKLOAD), &pOsContext->shmid, &pOsContext->pShm);
UnLockSemaphore(pOsContext->semid);
MOS_CHK_STATUS_SAFE(eStatus);
finish:
return eStatus;
}
#endif
#endif
GpuContextSpecific* Linux_GetGpuContext(PMOS_INTERFACE pOsInterface, uint32_t gpuContextHandle)
{
MOS_OS_FUNCTION_ENTER;
if (pOsInterface == nullptr || pOsInterface->osContextPtr == nullptr)
{
MOS_OS_ASSERTMESSAGE("invalid input parameters!");
return nullptr;
}
auto osCxtSpecific = static_cast<OsContextSpecific*>(pOsInterface->osContextPtr);
auto gpuContextMgr = osCxtSpecific->GetGpuContextMgr();
if (gpuContextMgr == nullptr)
{
MOS_OS_ASSERTMESSAGE("m_gpuContextMgr cannot be nullptr");
return nullptr;
}
auto gpuContext = gpuContextMgr->GetGpuContext(gpuContextHandle);
if (gpuContext == nullptr)
{
MOS_OS_ASSERTMESSAGE("cannot find the gpuContext corresponding to the active gpuContextHandle");
return nullptr;
}
auto gpuContextSpecific = static_cast<GpuContextSpecific *>(gpuContext);
return gpuContextSpecific;
}
//!
//! \brief Initialize the GPU Status Buffer
//! \details Initialize the GPU Status Buffer
//! \param MOS_CONTEXT * pOsContext
//! [in, out] Pointer to OS context structure
//! \return MOS_STATUS
//! Return MOS_STATUS_SUCCESS if successful, otherwise failed
//!
MOS_STATUS Linux_InitGPUStatus(
PMOS_CONTEXT pOsContext)
{
MOS_LINUX_BO *bo = nullptr;
MOS_STATUS eStatus = MOS_STATUS_SUCCESS;
if (pOsContext == nullptr)
{
MOS_OS_ASSERTMESSAGE("Linux_InitGPUStatus:pOsContext == NULL");
eStatus = MOS_STATUS_NULL_POINTER;
goto finish;
}
pOsContext->pGPUStatusBuffer =
(MOS_RESOURCE*)MOS_AllocAndZeroMemory(sizeof(MOS_RESOURCE) * MOS_GPU_CONTEXT_MAX);
if (nullptr == pOsContext->pGPUStatusBuffer)
{
MOS_OS_ASSERTMESSAGE("pContext->pGPUStatusBuffer malloc failed.");
eStatus = MOS_STATUS_NO_SPACE;
goto finish;
}
// Allocate the command buffer from GEM
bo = mos_bo_alloc(pOsContext->bufmgr,"GPU Status Buffer", sizeof(MOS_GPU_STATUS_DATA) * MOS_GPU_CONTEXT_MAX, 4096, MOS_MEMPOOL_SYSTEMMEMORY); // Align to page boundary
if (bo == nullptr)
{
MOS_OS_ASSERTMESSAGE("Allocation of GPU Status Buffer failed.");
eStatus = MOS_STATUS_NO_SPACE;
goto finish;
}
// Map command buffer to user virtual address
if (mos_bo_map(bo, 1) != 0) // Write enable set
{
MOS_OS_ASSERTMESSAGE("Mapping of GPU Status Buffer failed.");
eStatus = MOS_STATUS_INVALID_HANDLE;
goto finish;
}
Mos_ResetResource(pOsContext->pGPUStatusBuffer);
// Fill in resource information
pOsContext->pGPUStatusBuffer->Format = Format_Buffer;
pOsContext->pGPUStatusBuffer->iWidth = bo->size;
pOsContext->pGPUStatusBuffer->iHeight = 1;
pOsContext->pGPUStatusBuffer->iPitch = bo->size;
pOsContext->pGPUStatusBuffer->iCount = 1;
pOsContext->pGPUStatusBuffer->pData = (uint8_t*)bo->virt;
pOsContext->pGPUStatusBuffer->TileType = MOS_TILE_LINEAR;
pOsContext->pGPUStatusBuffer->bo = bo;
pOsContext->pGPUStatusBuffer->bMapped = true;
MOS_ZeroMemory(pOsContext->pGPUStatusBuffer->pData, bo->size);
finish:
return eStatus;
}
//!
//! \brief Release the GPU Status Buffer
//! \details Release the GPU Status Buffer
//! \param MOS_CONTEXT * pOsContext
//! [in, out] Pointer to OS context structure
//! \return void
//!
void Linux_ReleaseGPUStatus(
PMOS_CONTEXT pOsContext)
{
MOS_LINUX_BO *bo = nullptr;
if ( pOsContext == nullptr || pOsContext->pGPUStatusBuffer == nullptr)
{
return;
}
bo = pOsContext->pGPUStatusBuffer->bo;
if (bo != nullptr)
{
mos_bo_unmap(bo);
mos_bo_wait_rendering(bo);
mos_bo_unreference(bo);
}
pOsContext->pGPUStatusBuffer->bo = nullptr;
MOS_FreeMemAndSetNull(pOsContext->pGPUStatusBuffer);
}
//!
//! \brief Get GPU status tag for the given GPU context
//! \details Get GPU status tag for the given GPU context
//! \param MOS_CONTEXT * pOsContext
//! [in] Pointer to OS context structure
//! \param MOS_GPU_CONTEXT GpuContext
//! [in, out] GPU Context
//! \return uint32_t
//! GPU status tag
//!
uint32_t Linux_GetGpuCtxBufferTag(
PMOS_CONTEXT pOsContext,
MOS_GPU_CONTEXT GpuContext)
{
if ( pOsContext == nullptr)
{
MOS_OS_ASSERTMESSAGE("Invalid pOsContext.");
return 0;
}
if (GpuContext == MOS_GPU_CONTEXT_INVALID_HANDLE)
{
MOS_OS_ASSERTMESSAGE("Invalid input parameter GpuContext.");
return 0;
}
return pOsContext->OsGpuContext[GpuContext].uiGPUStatusTag;
}
//!
//! \brief Increment GPU status tag for the given GPU context
//! \details Increment GPU status tag for the given GPU context
//! \param MOS_CONTEXT * pOsContext
//! [in] Pointer to OS context structure
//! \param MOS_GPU_CONTEXT GpuContext
//! [in] GPU Context
//! \return void
//!
void Linux_IncGpuCtxBufferTag(
PMOS_CONTEXT pOsContext,
MOS_GPU_CONTEXT GpuContext)
{
uint32_t uiGPUStatusTag;
if ( pOsContext == nullptr)
{
MOS_OS_ASSERTMESSAGE("Invalid pOsContext.");
return;
}
if (GpuContext == MOS_GPU_CONTEXT_INVALID_HANDLE)
{
MOS_OS_ASSERTMESSAGE("Invalid input parameter GpuContext.");
return;
}
uiGPUStatusTag = pOsContext->OsGpuContext[GpuContext].uiGPUStatusTag;
pOsContext->OsGpuContext[GpuContext].uiGPUStatusTag = uiGPUStatusTag % UINT_MAX + 1;
if(pOsContext->OsGpuContext[GpuContext].uiGPUStatusTag == 0)
{
pOsContext->OsGpuContext[GpuContext].uiGPUStatusTag = 1;
}
}
GMM_CLIENT_CONTEXT* Linux_GetGmmClientContext(PMOS_CONTEXT pOsContext)
{
if (pOsContext == nullptr)
{
return nullptr;
}
return pOsContext->pGmmClientContext;
}
MosOcaInterface* Linux_GetOcaInterface()
{
return nullptr;
}
//!
//! \brief Get GPU tag for the given GPU context from the status buffer
//! \details Get GPU tag for the given GPU context from the status buffer
//! \param MOS_CONTEXT * pOsContext
//! [in] Pointer to OS context structure
//! \param MOS_GPU_CONTEXT GpuContext
//! [in] GPU Context
//! \return uint32_t
//! GPU tag
//!
uint32_t Linux_GetGPUTag(
PMOS_INTERFACE pOsInterface,
MOS_GPU_CONTEXT mosGpuCtx)
{
MOS_OS_FUNCTION_ENTER;
if (pOsInterface == nullptr)
{
MOS_OS_ASSERTMESSAGE("invalid input parameters!");
return 0;
}
if (mosGpuCtx == MOS_GPU_CONTEXT_INVALID_HANDLE)
{
MOS_OS_ASSERTMESSAGE("Invalid input parameter GpuContext.");
return 0;
}
if (pOsInterface->modularizedGpuCtxEnabled && !Mos_Solo_IsEnabled(nullptr))
{
if (pOsInterface->osContextPtr == nullptr)
{
MOS_OS_ASSERTMESSAGE("invalid input parameters!");
return 0;
}
auto osCxtSpecific = static_cast<OsContextSpecific*>(pOsInterface->osContextPtr);
auto handle = osCxtSpecific->GetGpuContextHandle(mosGpuCtx);
if (pOsInterface->apoMosEnabled)
{
PMOS_RESOURCE gpuStatusResource = nullptr;
MOS_OS_CHK_STATUS_RETURN(MosInterface::GetGpuStatusBufferResource(pOsInterface->osStreamState, gpuStatusResource, handle));
MOS_OS_CHK_NULL_RETURN(gpuStatusResource);
auto gpuStatusData = (MOS_GPU_STATUS_DATA *)gpuStatusResource->pData;
if (gpuStatusData == nullptr)
{
MOS_OS_ASSERTMESSAGE("cannot find ");
return 0;
}
return gpuStatusData->GPUTag;
}
auto gpuContext = Linux_GetGpuContext(pOsInterface, handle);
if (gpuContext == nullptr)
{
MOS_OS_ASSERTMESSAGE("cannot get corresponding gpu context!");
return 0;
}
auto resource = gpuContext->GetStatusBufferResource();
if (resource == nullptr)
{
MOS_OS_ASSERTMESSAGE("cannot find the gpuContext corresponding to the active resource.");
return 0;
}
MOS_RESOURCE gpuStatusResource;
MOS_OS_CHK_STATUS_RETURN(resource->ConvertToMosResource(&gpuStatusResource));
auto gpuStatusData = (MOS_GPU_STATUS_DATA *)gpuStatusResource.pData;
if (gpuStatusData == nullptr)
{
MOS_OS_ASSERTMESSAGE("cannot find ");
return 0;
}
return gpuStatusData->GPUTag;
}
MOS_GPU_STATUS_DATA *pGPUStatusData = nullptr;
if ( pOsInterface->pOsContext == nullptr ||
pOsInterface->pOsContext->pGPUStatusBuffer == nullptr ||
pOsInterface->pOsContext->pGPUStatusBuffer->pData == nullptr)
{
return 0;
}
pGPUStatusData = (MOS_GPU_STATUS_DATA *)(pOsInterface->pOsContext->pGPUStatusBuffer->pData + (sizeof(MOS_GPU_STATUS_DATA) * mosGpuCtx));
if (pGPUStatusData == nullptr)
{
MOS_OS_ASSERTMESSAGE("cannot find the gpuContext corresponding to the active resource");
return 0;
}
return pGPUStatusData->GPUTag;
}
//!
//! \brief Destroy Linux context
//! \details Destroy Linux context
//! \param PMOS_CONTEXT pOsContext
//! [in] Pointer to OS context structure
//! \return void
//!
void Linux_Destroy(
PMOS_CONTEXT pOsContext,
int32_t MODSEnabled,
int32_t modularizedGpuCtxEnabled)
{
PCOMMAND_BUFFER pCurrCB = nullptr;
PCOMMAND_BUFFER pNextCB = nullptr;
int32_t iSize = 0;
int i = 0;
if (pOsContext == nullptr)
{
MOS_OS_ASSERTMESSAGE("OsContext is null.");
return;
}
#ifndef ANDROID
#if !defined(__Fuchsia__)
if (pOsContext->bKMDHasVCS2)
{
DestroyIPC(pOsContext);
}
#endif
#endif
if (!modularizedGpuCtxEnabled)
{
Linux_ReleaseCmdBufferPool(pOsContext);
for (i = 0; i < MOS_GPU_CONTEXT_MAX; i++)
{
MOS_FreeMemAndSetNull(pOsContext->OsGpuContext[i].pCB);
pCurrCB = pOsContext->OsGpuContext[i].pStartCB;
for (; (pCurrCB); pCurrCB = pNextCB)
{
pNextCB = pCurrCB->pNext;
MOS_FreeMemAndSetNull(pCurrCB);
}
}
Linux_ReleaseGPUStatus(pOsContext);
}
if (pOsContext->contextOffsetList.size())
{
pOsContext->contextOffsetList.clear();
pOsContext->contextOffsetList.shrink_to_fit();
}
if (!MODSEnabled && (pOsContext->intel_context))
{
if (pOsContext->intel_context->vm)
{
mos_gem_vm_destroy(pOsContext->intel_context->bufmgr,pOsContext->intel_context->vm);
pOsContext->intel_context->vm = nullptr;
}
mos_gem_context_destroy(pOsContext->intel_context);
}
pOsContext->GmmFuncs.pfnDeleteClientContext(pOsContext->pGmmClientContext);
MOS_FreeMemAndSetNull(pOsContext);
}
//!
//! \brief Get DMA Buffer ID
//! \details Get the DMA perf Buffer ID
//! \param PMOS_CONTEXT pOsContext
//! [in] Pointer to OS context structure
//! \return uint32_t
//! Return the buffer ID
//!
uint32_t Linux_GetDmaBufID (PMOS_CONTEXT pOsContext )
{
if (pOsContext == nullptr)
{
MOS_OS_ASSERTMESSAGE("OsContext is null.");
return 0;
}
uint32_t dmaBufID = 0;
if (pOsContext->pPerfData != nullptr)
{
dmaBufID = pOsContext->pPerfData->dmaBufID;
}
return dmaBufID;
}
//!
//! \brief Get Buffer Type
//! \details Returns the type of buffer, 1D, 2D or volume
//! \param PMOS_RESOURCE pOsResource
//! [in] Pointer to OS Resource
//! \return GFX resource Type
//!
MOS_GFXRES_TYPE GetResType(PMOS_RESOURCE pOsResource)
{
GMM_RESOURCE_INFO *pGmmResourceInfo = nullptr;
MOS_GFXRES_TYPE ResType = MOS_GFXRES_INVALID;
GMM_RESOURCE_TYPE GMMResType = RESOURCE_INVALID;
if (pOsResource == nullptr)
{
MOS_OS_ASSERTMESSAGE("OsContext is null.");
return MOS_GFXRES_INVALID;
}
pGmmResourceInfo = (GMM_RESOURCE_INFO *)pOsResource->pGmmResInfo;
GMMResType = pGmmResourceInfo->GetResourceType();
switch (GMMResType)
{
case RESOURCE_BUFFER:
ResType = MOS_GFXRES_BUFFER;
break;
case RESOURCE_3D:
ResType = MOS_GFXRES_VOLUME;
break;
case RESOURCE_2D:
ResType = MOS_GFXRES_2D;
break;
default:
break;
}
return ResType;
}
//!
//! \brief Set the DMA Buffer ID
//! \details Sets the buffer ID in perf data
//! \param PMOS_CONTEXT pOsContext
//! [in] Pointer to OS context structure
//! \param uint32_t dwDmaBufID
//! [in] Buffer ID to be set
//! \return void
//!
void Linux_SetDmaBufID ( PMOS_CONTEXT pOsContext, uint32_t dwDmaBufID )
{
if (pOsContext == nullptr)
{
MOS_OS_ASSERTMESSAGE("OsContext is null.");
return;
}
if (pOsContext->pPerfData != nullptr)
{
pOsContext->pPerfData->dmaBufID = dwDmaBufID;
}
}
//!
//! \brief Set the DMA Kernel ID
//! \details Sets the Kernel ID in perf data
//! \param PMOS_CONTEXT pOsContext
//! [in] Pointer to OS context structure
//! \param uint32_t KernelID
//! [in] Buffer ID to be set
//! \return void
//!
void Linux_SetPerfHybridKernelID ( PMOS_CONTEXT pOsContext, uint32_t KernelID)
{
if (pOsContext == nullptr)
{
MOS_OS_ASSERTMESSAGE("OsContext is null.");
return;
}
if (pOsContext->pPerfData != nullptr)
{
pOsContext->pPerfData->dmaBufID = (pOsContext->pPerfData->dmaBufID & 0xF0FF) | ((KernelID <<8) & 0x0F00);
}
}
//!
//! \brief Init Linux context
//! \details Initialize the linux context
//! \param MOS_OS_CONTEXT * pContext
//! [in] Pointer to OS context structure
//! \param PMOS_CONTEXT pOsDriverContext
//! [in] Pointer to OS Driver context
//! \return MOS_STATUS
//! Return MOS_STATUS_SUCCESS if successful, otherwise failed
//!
MOS_STATUS Linux_InitContext(
MOS_OS_CONTEXT *pContext,
PMOS_CONTEXT pOsDriverContext,
int32_t MODSEnabled,
int32_t modularizedGpuCtxEnabled)
{
int32_t iDeviceId = -1;
MOS_STATUS eStatus;
int32_t i = -1;
MOS_OS_FUNCTION_ENTER;
eStatus = MOS_STATUS_SUCCESS;
if (nullptr == pContext ||
nullptr == pOsDriverContext ||
nullptr == pOsDriverContext->bufmgr ||
(nullptr == pOsDriverContext->m_gpuContextMgr && modularizedGpuCtxEnabled && !pOsDriverContext->m_apoMosEnabled) ||
(nullptr == pOsDriverContext->m_cmdBufMgr && modularizedGpuCtxEnabled && !pOsDriverContext->m_apoMosEnabled) ||
0 >= pOsDriverContext->fd)
{
MOS_OS_ASSERT(false);
return MOS_STATUS_INVALID_HANDLE;
}
pContext->bufmgr = pOsDriverContext->bufmgr;
pContext->m_gpuContextMgr = pOsDriverContext->m_gpuContextMgr;
pContext->m_cmdBufMgr = pOsDriverContext->m_cmdBufMgr;
pContext->fd = pOsDriverContext->fd;
pContext->pPerfData = pOsDriverContext->pPerfData;
pContext->m_auxTableMgr = pOsDriverContext->m_auxTableMgr;
mos_bufmgr_gem_enable_reuse(pOsDriverContext->bufmgr);
// DDI layer can pass over the DeviceID.
iDeviceId = pOsDriverContext->iDeviceId;
if (0 == iDeviceId)
{
//Such as CP, it calls InitMosInterface() dretly without creating MediaContext.
iDeviceId = mos_bufmgr_gem_get_devid(pOsDriverContext->bufmgr);
pOsDriverContext->iDeviceId = iDeviceId;
MOS_OS_CHK_STATUS_MESSAGE(
HWInfo_GetGfxInfo(pOsDriverContext->fd, pOsDriverContext->bufmgr, &pContext->platform, &pContext->SkuTable, &pContext->WaTable, &pContext->gtSystemInfo),
"Fatal error - unsuccesfull Sku/Wa/GtSystemInfo initialization");
pOsDriverContext->SkuTable = pContext->SkuTable;
pOsDriverContext->WaTable = pContext->WaTable;
pOsDriverContext->gtSystemInfo = pContext->gtSystemInfo;
pOsDriverContext->platform = pContext->platform;
MOS_OS_NORMALMESSAGE("DeviceID was created DeviceID = %d, platform product %d", iDeviceId, pContext->platform.eProductFamily);
}
else
{
// pOsDriverContext's parameters were passed by CmCreateDevice.
// Get SkuTable/WaTable/systemInfo/platform from OSDriver directly.
pContext->SkuTable = pOsDriverContext->SkuTable;
pContext->WaTable = pOsDriverContext->WaTable;
pContext->gtSystemInfo = pOsDriverContext->gtSystemInfo;
pContext->platform = pOsDriverContext->platform;
}
pContext->bUse64BitRelocs = true;
pContext->bUseSwSwizzling = pContext->bSimIsActive || MEDIA_IS_SKU(&pContext->SkuTable, FtrUseSwSwizzling);
pContext->bTileYFlag = MEDIA_IS_SKU(&pContext->SkuTable, FtrTileY);
// when MODS enabled, intel_context will be created by pOsContextSpecific, should not recreate it here, or will cause memory leak.
if (!MODSEnabled)
{
pContext->intel_context = mos_gem_context_create_ext(pOsDriverContext->bufmgr,0);
if (!Mos_Solo_IsEnabled(nullptr) && pContext->intel_context)
{
pContext->intel_context->vm = mos_gem_vm_create(pOsDriverContext->bufmgr);
if (pContext->intel_context->vm == nullptr)
{
MOS_OS_ASSERTMESSAGE("Failed to create vm.\n");
return MOS_STATUS_UNKNOWN;
}
}
else //try legacy context create ioctl if DRM_IOCTL_I915_GEM_CONTEXT_CREATE_EXT is not supported
{
pContext->intel_context = mos_gem_context_create(pOsDriverContext->bufmgr);
if (pContext->intel_context)
{
pContext->intel_context->vm = nullptr;
}
}
if (pContext->intel_context == nullptr)
{
MOS_OS_ASSERTMESSAGE("Failed to create drm intel context");
return MOS_STATUS_UNKNOWN;
}
}
pContext->intel_context->pOsContext = pContext;
pContext->bIsAtomSOC = IS_ATOMSOC(iDeviceId);
if(!modularizedGpuCtxEnabled)
{
Linux_InitCmdBufferPool(pContext);
// Initialize GPU Status Buffer
eStatus = Linux_InitGPUStatus(pContext);
if (MOS_STATUS_SUCCESS != eStatus)
{
goto finish;
}
for (i = 0; i < MOS_GPU_CONTEXT_MAX; i++)
{
pContext->OsGpuContext[i].pStartCB = nullptr;
pContext->OsGpuContext[i].pCurrentCB = nullptr;
pContext->OsGpuContext[i].bCBFlushed = true;
pContext->OsGpuContext[i].uiCommandBufferSize = COMMAND_BUFFER_SIZE;
pContext->OsGpuContext[i].pCB =
(PMOS_COMMAND_BUFFER)MOS_AllocAndZeroMemory(sizeof(MOS_COMMAND_BUFFER));
if (nullptr == pContext->OsGpuContext[i].pCB)
{
MOS_OS_ASSERTMESSAGE("No More Avaliable Memory");
eStatus = MOS_STATUS_NO_SPACE;
goto finish;
}
// each thread has its own GPU context, so do not need any lock as guarder here
pContext->OsGpuContext[i].pAllocationList =
(ALLOCATION_LIST*)MOS_AllocAndZeroMemory(sizeof(ALLOCATION_LIST) * ALLOCATIONLIST_SIZE);
if (nullptr == pContext->OsGpuContext[i].pAllocationList)
{
MOS_OS_ASSERTMESSAGE("pContext->OsGpuContext[%d].pAllocationList malloc failed.", i);
eStatus = MOS_STATUS_NO_SPACE;
goto finish;
}
pContext->OsGpuContext[i].uiMaxNumAllocations = ALLOCATIONLIST_SIZE;
pContext->OsGpuContext[i].pPatchLocationList =
(PATCHLOCATIONLIST*)MOS_AllocAndZeroMemory(sizeof(PATCHLOCATIONLIST) * PATCHLOCATIONLIST_SIZE);
if (nullptr == pContext->OsGpuContext[i].pPatchLocationList)
{
MOS_OS_ASSERTMESSAGE("pContext->OsGpuContext[%d].pPatchLocationList malloc failed.", i);
eStatus = MOS_STATUS_NO_SPACE;
goto finish;
}
pContext->OsGpuContext[i].uiMaxPatchLocationsize = PATCHLOCATIONLIST_SIZE;
pContext->OsGpuContext[i].pResources =
(PMOS_RESOURCE)MOS_AllocAndZeroMemory(sizeof(MOS_RESOURCE) * ALLOCATIONLIST_SIZE);
if (nullptr == pContext->OsGpuContext[i].pResources)
{
MOS_OS_ASSERTMESSAGE("pContext->OsGpuContext[%d].pResources malloc failed.", i);
eStatus = MOS_STATUS_NO_SPACE;
goto finish;
}
pContext->OsGpuContext[i].pbWriteMode =
(int32_t*)MOS_AllocAndZeroMemory(sizeof(int32_t) * ALLOCATIONLIST_SIZE);
if (nullptr == pContext->OsGpuContext[i].pbWriteMode)
{
MOS_OS_ASSERTMESSAGE("pContext->OsGpuContext[%d].pbWriteMode malloc failed.", i);
eStatus = MOS_STATUS_NO_SPACE;
goto finish;
}
pContext->OsGpuContext[i].uiGPUStatusTag = 1;
}
}
#if !defined(ANDROID)
{
drm_i915_getparam_t gp;
int32_t ret = -1;
int32_t value = 0;
//KMD support VCS2?
gp.value = &value;
gp.param = I915_PARAM_HAS_BSD2;
if (pContext->fd < 0)
{
MOS_OS_ASSERTMESSAGE("pContext->fd is not valid.");
eStatus = MOS_STATUS_INVALID_PARAMETER;
goto finish;
}
#if defined(USE_MAGMA)
{
uint32_t unsigned_value;
if (query_magma_fd(pContext->fd, gp.param, &unsigned_value)) {
ret = 0;
value = unsigned_value;
}
}
#else
ret = drmIoctl(pContext->fd, DRM_IOCTL_I915_GETPARAM, &gp);
#endif
if (ret == 0 && value != 0)
{
pContext->bKMDHasVCS2 = true;
}
else
{
pContext->bKMDHasVCS2 = false;
}
}
#if !defined(__Fuchsia__)
if (pContext->bKMDHasVCS2)
{
eStatus = CreateIPC(pContext);
MOS_CHK_STATUS_SAFE(eStatus);
}
#endif
#endif
pContext->pTranscryptedKernels = nullptr;
pContext->uiTranscryptedKernelsSize = 0;
// For Media Memory compression
pContext->ppMediaMemDecompState = pOsDriverContext->ppMediaMemDecompState;
pContext->pfnMemoryDecompress = pOsDriverContext->pfnMemoryDecompress;
pContext->pfnMediaMemoryCopy = pOsDriverContext->pfnMediaMemoryCopy;
pContext->pfnMediaMemoryCopy2D = pOsDriverContext->pfnMediaMemoryCopy2D;
// Set interface functions
pContext->pfnDestroy = Linux_Destroy;
pContext->pfnGetCommandBuffer = Linux_GetCommandBuffer;
pContext->pfnReturnCommandBuffer = Linux_ReturnCommandBuffer;
pContext->pfnFlushCommandBuffer = Linux_FlushCommandBuffer;
pContext->pfnInsertCmdBufferToPool = Linux_InsertCmdBufferToPool;
pContext->pfnWaitAndReleaseCmdBuffer = Linux_WaitAndReleaseCmdBuffer;
pContext->pfnRefresh = Linux_Refresh;
pContext->GetDmaBufID = Linux_GetDmaBufID;
pContext->SetDmaBufID = Linux_SetDmaBufID;
pContext->SetPerfHybridKernelID = Linux_SetPerfHybridKernelID;
pContext->pfnGetGpuCtxBufferTag = Linux_GetGpuCtxBufferTag;
pContext->pfnIncGpuCtxBufferTag = Linux_IncGpuCtxBufferTag;
pContext->GetGPUTag = Linux_GetGPUTag;
pContext->GetGmmClientContext = Linux_GetGmmClientContext;
pContext->GetOcaInterface = Linux_GetOcaInterface;
finish:
if (!modularizedGpuCtxEnabled)
{
// init context failed, roll back
if (eStatus != MOS_STATUS_SUCCESS)
Mos_Specific_ClearGpuContext(pContext);
}
return eStatus;
}
//============= PRIVATE FUNCTIONS <END>=========================================
//!
//! \brief Set GPU context
//! \details Set GPU context for the following rendering operations
//! \param MOS_OS_CONTEXT * pContext
//! [in] Pointer to OS context structure
//! \param MOS_GPU_CONTEXT GpuContext
//! [in] GPU Context
//! \return MOS_STATUS
//! Return MOS_STATUS_SUCCESS if successful, otherwise failed
//!
MOS_STATUS Mos_Specific_SetGpuContext(
PMOS_INTERFACE pOsInterface,
MOS_GPU_CONTEXT GpuContext)
{
MOS_OS_FUNCTION_ENTER;
MOS_OS_CHK_NULL_RETURN(pOsInterface);
if (GpuContext == MOS_GPU_CONTEXT_INVALID_HANDLE)
{
MOS_OS_ASSERTMESSAGE("Invalid input parameter GpuContext.");
return MOS_STATUS_INVALID_PARAMETER;
}
// Set GPU context handle
pOsInterface->CurrentGpuContextOrdinal = GpuContext;
if (pOsInterface->modularizedGpuCtxEnabled && !Mos_Solo_IsEnabled(nullptr))
{
MOS_OS_CHK_NULL_RETURN(pOsInterface->osContextPtr);
auto pOsContextSpecific = static_cast<OsContextSpecific*>(pOsInterface->osContextPtr);
MOS_OS_CHK_NULL_RETURN(pOsContextSpecific);
// Set GPU context handle
pOsInterface->CurrentGpuContextHandle = pOsContextSpecific->GetGpuContextHandle(GpuContext);
if (pOsInterface->apoMosEnabled)
{
MOS_OS_CHK_STATUS_RETURN(MosInterface::SetGpuContext(
pOsInterface->osStreamState,
pOsContextSpecific->GetGpuContextHandle(GpuContext)));
}
}
return MOS_STATUS_SUCCESS;
}
MOS_STATUS Mos_Specific_SetGpuContextFromHandle(MOS_INTERFACE *osInterface,
MOS_GPU_CONTEXT contextName,
GPU_CONTEXT_HANDLE contextHandle)
{
MOS_OS_FUNCTION_ENTER;
MOS_OS_CHK_NULL_RETURN(osInterface);
if (MOS_GPU_CONTEXT_INVALID_HANDLE == contextName)
{
MOS_OS_ASSERTMESSAGE("Invalid input parameter contextName.");
return MOS_STATUS_INVALID_PARAMETER;
}
// Set GPU context handle
osInterface->CurrentGpuContextOrdinal = contextName;
if (osInterface->modularizedGpuCtxEnabled && !Mos_Solo_IsEnabled(nullptr))
{
MOS_OS_CHK_NULL_RETURN(osInterface->osContextPtr);
auto os_context_specific
= static_cast<OsContextSpecific*>(osInterface->osContextPtr);
MOS_OS_CHK_NULL_RETURN(os_context_specific);
// Set GPU context handle
osInterface->CurrentGpuContextHandle = contextHandle;
if (osInterface->apoMosEnabled)
{
MOS_OS_CHK_STATUS_RETURN(
MosInterface::SetGpuContext(osInterface->osStreamState,
contextHandle));
}
}
return MOS_STATUS_SUCCESS;
}
//!
//! \brief Get current GPU context
//! \details Get current GPU context for the following rendering operations
//! \param PMOS_INTERFACE pOsInterface
//! [in] Pointer to OS Interface
//! \return MOS_GPU_CONTEXT
//! Return current GPU context
//!
MOS_GPU_CONTEXT Mos_Specific_GetGpuContext(
PMOS_INTERFACE pOsInterface)
{
if (pOsInterface == nullptr)
{
MOS_OS_ASSERTMESSAGE("OsInterface is null.");
return MOS_GPU_CONTEXT_INVALID_HANDLE;
}
return pOsInterface->CurrentGpuContextOrdinal;
}
//!
//! \brief Set GPU context Handle
//! \details Set GPU context handle for the following rendering operations
//! \param PMOS_INTERFACE pOsInterface
//! [in] Pointer to OS Interface
//! \param GPU_CONTEXT_HANDLE gpuContextHandle
//! [in] GPU Context Handle
//! \param MOS_GPU_CONTEXT GpuContext
//! [in] GPU Context
//! \return MOS_STATUS
//! Return MOS_STATUS_SUCCESS if successful, otherwise failed
//!
MOS_STATUS Mos_Specific_SetGpuContextHandle(
PMOS_INTERFACE pOsInterface,
GPU_CONTEXT_HANDLE gpuContextHandle,
MOS_GPU_CONTEXT GpuContext)
{
MOS_OS_FUNCTION_ENTER;
MOS_OS_CHK_NULL_RETURN(pOsInterface);
MOS_OS_CHK_NULL_RETURN(pOsInterface->osContextPtr);
auto pOsContextSpecific = static_cast<OsContextSpecific*>(pOsInterface->osContextPtr);
MOS_OS_CHK_NULL_RETURN(pOsContextSpecific);
pOsContextSpecific->SetGpuContextHandle(GpuContext, gpuContextHandle);
return MOS_STATUS_SUCCESS;
}
//!
//! \brief Get GPU context pointer
//! \details Get GPU context pointer
//! \param PMOS_INTERFACE pOsInterface
//! [in] Pointer to OS Interface
//! \param GPU_CONTEXT_HANDLE gpuContextHandle
//! [in] GPU Context Handle
//! \return void *
//! a pointer to a gpu context
//!
void *Mos_Specific_GetGpuContextbyHandle(
PMOS_INTERFACE pOsInterface,
GPU_CONTEXT_HANDLE gpuContextHandle)
{
MOS_OS_FUNCTION_ENTER;
if (!pOsInterface)
{
MOS_OS_ASSERTMESSAGE("Invalid nullptr");
return nullptr;
}
if (pOsInterface->apoMosEnabled)
{
return MosInterface::GetGpuContextbyHandle(pOsInterface->osStreamState, gpuContextHandle);
}
OsContextSpecific *pOsContextSpecific = static_cast<OsContextSpecific *>(pOsInterface->osContextPtr);
if(!pOsContextSpecific)
{
MOS_OS_ASSERTMESSAGE("Invalid nullptr");
return nullptr;
}
GpuContextMgr *gpuContextMgr = pOsContextSpecific->GetGpuContextMgr();
if (!gpuContextMgr)
{
MOS_OS_ASSERTMESSAGE("Invalid nullptr");
return nullptr;
}
GpuContext *gpuContext = gpuContextMgr->GetGpuContext(gpuContextHandle);
if (!gpuContext)
{
MOS_OS_ASSERTMESSAGE("Invalid nullptr");
return nullptr;
}
return (void *)gpuContext;
}
//!
//! \brief Get GPU context Manager
//! \param PMOS_INTERFACE pOsInterface
//! [in] Pointer to OS Interface
//! \return GpuContextMgr
//! GPU context Manager got from Os interface
//!
GpuContextMgr* Mos_Specific_GetGpuContextMgr(
PMOS_INTERFACE pOsInterface)
{
MOS_OS_FUNCTION_ENTER;
if (pOsInterface && pOsInterface->osContextPtr)
{
auto pOsContextSpecific = static_cast<OsContextSpecific*>(pOsInterface->osContextPtr);
return pOsContextSpecific->GetGpuContextMgr();
}
else
{
return nullptr;
}
}
//!
//! \brief Get current GMM client context
//! \details Get current GMM client context
//! \param PMOS_INTERFACE pOsInterface
//! [in] Pointer to OS Interface
//! \return GMM_CLIENT_CONTEXT
//! Return current GMM client context
//!
GMM_CLIENT_CONTEXT *Mos_Specific_GetGmmClientContext(
PMOS_INTERFACE pOsInterface)
{
if (pOsInterface == nullptr)
{
MOS_OS_ASSERTMESSAGE("OsInterface is null.");
return nullptr;
}
if (pOsInterface->apoMosEnabled)
{
return MosInterface::GetGmmClientContext(pOsInterface->osStreamState);
}
if (pOsInterface->modulizedMosEnabled && !Mos_Solo_IsEnabled(nullptr))
{
OsContextSpecific *pOsContextSpecific = static_cast<OsContextSpecific *>(pOsInterface->osContextPtr);
if (pOsContextSpecific)
{
return pOsContextSpecific->GetGmmClientContext();
}
}
else
{
if (pOsInterface->pOsContext)
{
return pOsInterface->pOsContext->GetGmmClientContext(pOsInterface->pOsContext);
}
}
return nullptr;
}
//!
//! \brief Get Platform
//! \details Get platform info
//! \param PMOS_INTERFACE pOsInterface
//! [in] Pointer to OS Interface
//! \param PLATFORM pPlatform
//! [out] Pointer to platform
//! \return MOS_STATUS
//! Return MOS_STATUS_SUCCESS if successful, otherwise failed
//!
void Mos_Specific_GetPlatform(
PMOS_INTERFACE pOsInterface,
PLATFORM *pPlatform)
{
MOS_STATUS eStatus;
eStatus = MOS_STATUS_SUCCESS;
MOS_OS_CHK_NULL(pOsInterface);
MOS_OS_CHK_NULL(pOsInterface->pOsContext);
MOS_OS_CHK_NULL(pPlatform);
if (pOsInterface->apoMosEnabled)
{
// apo wrapper
auto platform = MosInterface::GetPlatform(pOsInterface->osStreamState);
if (platform)
{
*pPlatform = *platform;
}
return;
}
*pPlatform = pOsInterface->pOsContext->platform;
finish:
return;
}
MOS_STATUS Mos_DestroyInterface(PMOS_INTERFACE pOsInterface)
{
MOS_OS_CHK_NULL_RETURN(pOsInterface);
MOS_STREAM_HANDLE streamState = pOsInterface->osStreamState;
MOS_OS_CHK_NULL_RETURN(streamState);
auto deviceContext = streamState->osDeviceContext;
MOS_OS_CHK_NULL_RETURN(deviceContext);
if (!Mos_Solo_IsEnabled((PMOS_CONTEXT)streamState->perStreamParameters))
{
OsContext *pOsContext = pOsInterface->osContextPtr;
MOS_OS_CHK_NULL_RETURN(pOsContext);
// APO MOS destory GPU contexts here instead of inside osContextPtr
OsContextSpecific *pOsContextSpecific = static_cast<OsContextSpecific *>(pOsContext);
auto gpuContextMgr = deviceContext->GetGpuContextMgr();
for (uint32_t i = 0; i < MOS_GPU_CONTEXT_MAX; i++)
{
if (pOsContextSpecific->GetGpuContextHandleByIndex(i) != MOS_GPU_CONTEXT_INVALID_HANDLE)
{
if (gpuContextMgr == nullptr)
{
MOS_OS_ASSERTMESSAGE("GpuContextMgr is null when destroy GpuContext");
break;
}
auto gpuContext = gpuContextMgr->GetGpuContext(pOsContextSpecific->GetGpuContextHandleByIndex(i));
if (gpuContext == nullptr)
{
MOS_OS_ASSERTMESSAGE("cannot find the gpuContext corresponding to the active gpuContextHandle");
continue;
}
gpuContextMgr->DestroyGpuContext(gpuContext);
pOsContextSpecific->SetGpuContextHandleByIndex(i, MOS_GPU_CONTEXT_INVALID_HANDLE);
}
}
pOsContext->CleanUp();
MOS_Delete(pOsContext);
pOsInterface->osContextPtr = nullptr;
}
if (pOsInterface->osCpInterface)
{
Delete_MosCpInterface(pOsInterface->osCpInterface);
pOsInterface->osCpInterface = NULL;
}
PMOS_CONTEXT perStreamParameters = (PMOS_CONTEXT)streamState->perStreamParameters;
if (perStreamParameters && perStreamParameters->bFreeContext)
{
perStreamParameters->SkuTable.reset();
perStreamParameters->WaTable.reset();
Mos_Specific_ClearGpuContext(perStreamParameters);
if (perStreamParameters->contextOffsetList.size())
{
perStreamParameters->contextOffsetList.clear();
perStreamParameters->contextOffsetList.shrink_to_fit();
}
if(Mos_Solo_IsEnabled(perStreamParameters))
{
Linux_ReleaseCmdBufferPool(perStreamParameters);
PCOMMAND_BUFFER pCurrCB = nullptr;
PCOMMAND_BUFFER pNextCB = nullptr;
for (uint32_t i = 0; i < MOS_GPU_CONTEXT_MAX; i++)
{
MOS_FreeMemAndSetNull(perStreamParameters->OsGpuContext[i].pCB);
pCurrCB = perStreamParameters->OsGpuContext[i].pStartCB;
for (; (pCurrCB); pCurrCB = pNextCB)
{
pNextCB = pCurrCB->pNext;
MOS_FreeMemAndSetNull(pCurrCB);
}
}
Linux_ReleaseGPUStatus(perStreamParameters);
}
if (perStreamParameters->intel_context)
{
if (perStreamParameters->intel_context->vm)
{
mos_gem_vm_destroy(perStreamParameters->intel_context->bufmgr, perStreamParameters->intel_context->vm);
perStreamParameters->intel_context->vm = nullptr;
}
mos_gem_context_destroy(perStreamParameters->intel_context);
perStreamParameters->intel_context = nullptr;
}
perStreamParameters->GmmFuncs.pfnDeleteClientContext(perStreamParameters->pGmmClientContext);
MOS_FreeMemAndSetNull(perStreamParameters);
streamState->perStreamParameters = nullptr;
}
MosInterface::DestroyVirtualEngineState(streamState);
MOS_FreeMemAndSetNull(pOsInterface->pVEInterf);
MOS_OS_CHK_STATUS_RETURN(MosInterface::DestroyOsStreamState(streamState));
pOsInterface->osStreamState = nullptr;
return MOS_STATUS_SUCCESS;
}
//!
//! \brief Destroys OS specific allocations
//! \details Destroys OS specific allocations including destroying OS context
//! \param PMOS_INTERFACE pOsInterface
//! [in] Pointer to OS Interface
//! \param int32_t bDestroyVscVppDeviceTag
//! [in] Destroy VscVppDeviceTagId Flag, no use in Linux
//! \return void
//!
void Mos_Specific_Destroy(
PMOS_INTERFACE pOsInterface,
int32_t bDestroyVscVppDeviceTag)
{
MOS_UNUSED(bDestroyVscVppDeviceTag);
if (nullptr == pOsInterface)
{
MOS_OS_ASSERTMESSAGE("input parameter, pOsInterface is NULL.");
return;
}
if (pOsInterface->apoMosEnabled)
{
MOS_STATUS status = Mos_DestroyInterface(pOsInterface);
if (status != MOS_STATUS_SUCCESS)
{
MOS_OS_ASSERTMESSAGE("Mos Destroy Interface failed.");
}
return;
}
if (pOsInterface->modulizedMosEnabled && !Mos_Solo_IsEnabled(nullptr))
{
OsContext* pOsContext = pOsInterface->osContextPtr;
if (pOsContext == nullptr)
{
MOS_OS_ASSERTMESSAGE("Unable to get the active OS context.");
return;
}
// APO MOS destory GPU contexts here instead of inside osContextPtr
if (pOsInterface->apoMosEnabled)
{
OsContextSpecific* pOsContextSpecific = static_cast<OsContextSpecific*>(pOsContext);
if (pOsInterface->osStreamState == nullptr)
{
MOS_OS_ASSERTMESSAGE("osStreamState is null when destroy GpuContext");
return;
}
if (pOsInterface->osStreamState->osDeviceContext == nullptr)
{
MOS_OS_ASSERTMESSAGE("osDeviceContext is null when destroy GpuContext");
return;
}
auto gpuContextMgr = pOsInterface->osStreamState->osDeviceContext->GetGpuContextMgr();
for (uint32_t i = 0; i < MOS_GPU_CONTEXT_MAX; i++)
{
if (pOsContextSpecific->GetGpuContextHandleByIndex(i) != MOS_GPU_CONTEXT_INVALID_HANDLE)
{
if (gpuContextMgr == nullptr)
{
MOS_OS_ASSERTMESSAGE("GpuContextMgr is null when destroy GpuContext");
break;
}
auto gpuContext = gpuContextMgr->GetGpuContext(pOsContextSpecific->GetGpuContextHandleByIndex(i));
if (gpuContext == nullptr)
{
MOS_OS_ASSERTMESSAGE("cannot find the gpuContext corresponding to the active gpuContextHandle");
continue;
}
gpuContextMgr->DestroyGpuContext(gpuContext);
pOsContextSpecific->SetGpuContextHandleByIndex(i, MOS_GPU_CONTEXT_INVALID_HANDLE);
}
}
}
pOsContext->CleanUp();
MOS_Delete(pOsContext);
pOsInterface->osContextPtr = nullptr;
}
if (pOsInterface->osCpInterface)
{
Delete_MosCpInterface(pOsInterface->osCpInterface);
pOsInterface->osCpInterface = NULL;
}
if (pOsInterface &&
pOsInterface->pOsContext &&
pOsInterface->pOsContext->bFreeContext)
{
pOsInterface->pOsContext->SkuTable.reset();
pOsInterface->pOsContext->WaTable.reset();
Mos_Specific_ClearGpuContext(pOsInterface->pOsContext);
bool modularizedGpuCtxEnabled = pOsInterface->modularizedGpuCtxEnabled && !Mos_Solo_IsEnabled(nullptr);
pOsInterface->pOsContext->pfnDestroy(pOsInterface->pOsContext, pOsInterface->modulizedMosEnabled, modularizedGpuCtxEnabled);
pOsInterface->pOsContext = nullptr;
}
if (pOsInterface->pVEInterf)
{
if (pOsInterface->apoMosEnabled && pOsInterface->pVEInterf->veInterface)
{
pOsInterface->pVEInterf->veInterface->Destroy();
MOS_Delete(pOsInterface->pVEInterf->veInterface);
}
MOS_FreeMemAndSetNull(pOsInterface->pVEInterf);
}
if (pOsInterface->apoMosEnabled)
{
auto status = MosInterface::DestroyOsStreamState(pOsInterface->osStreamState);
if (status != MOS_STATUS_SUCCESS)
{
MOS_OS_ASSERTMESSAGE("Failed to destroy stream state.");
return;
}
}
}
//!
//! \brief Gets the SKU table
//! \details Gets the SKU table for the platform
//! \param PMOS_INTERFACE pOsInterface
//! [in] Pointer to OS Interface
//! \return MEDIA_FEATURE_TABLE *
//! Returns the pointer to sku table
//!
MEDIA_FEATURE_TABLE *Mos_Specific_GetSkuTable(
PMOS_INTERFACE pOsInterface)
{
if (pOsInterface && pOsInterface->apoMosEnabled)
{
// apo wrapper
return MosInterface::GetSkuTable(pOsInterface->osStreamState);
}
if (pOsInterface && pOsInterface->pOsContext)
{
return &pOsInterface->pOsContext->SkuTable;
}
return nullptr;
}
//!
//! \brief Gets the WA table
//! \details Gets the WA table for the platform
//! \param PMOS_INTERFACE pOsInterface
//! [in] Pointer to OS Interface
//! \return MEDIA_WA_TABLE *
//! Returns the pointer to WA table
//!
MEDIA_WA_TABLE *Mos_Specific_GetWaTable(
PMOS_INTERFACE pOsInterface)
{
if (pOsInterface && pOsInterface->apoMosEnabled)
{
// apo wrapper
return MosInterface::GetWaTable(pOsInterface->osStreamState);
}
if (pOsInterface && pOsInterface->pOsContext)
{
return &pOsInterface->pOsContext->WaTable;
}
return nullptr;
}
//!
//! \brief Gets the GT System Info
//! \details Gets the GT System Info
//! \param PMOS_INTERFACE pOsInterface
//! [in] OS Interface
//! \return MEDIA_SYSTEM_INFO *
//! pointer to the GT System Info
//!
MEDIA_SYSTEM_INFO *Mos_Specific_GetGtSystemInfo(
PMOS_INTERFACE pOsInterface)
{
if( nullptr == pOsInterface)
{
MOS_OS_ASSERTMESSAGE("input parameter pOsInterface is NULL.");
return nullptr;
}
if (pOsInterface->apoMosEnabled)
{
// apo wrapper
return MosInterface::GetGtSystemInfo(pOsInterface->osStreamState);
}
if( nullptr == pOsInterface->pOsContext)
{
MOS_OS_ASSERTMESSAGE("pOsContext is NULL.");
return nullptr;
}
return &pOsInterface->pOsContext->gtSystemInfo;
}
MOS_STATUS Mos_Specific_GetMediaEngineInfo(
PMOS_INTERFACE pOsInterface, MEDIA_ENGINE_INFO &info)
{
if (pOsInterface == nullptr)
{
MOS_OS_ASSERTMESSAGE("Invalid pointer!");
return MOS_STATUS_INVALID_PARAMETER;
}
if (pOsInterface->apoMosEnabled)
{
// apo wrapper
MOS_OS_CHK_STATUS_RETURN(MosInterface::GetMediaEngineInfo(pOsInterface->osStreamState, info));
return MOS_STATUS_SUCCESS;
}
auto systemInfo = pOsInterface->pfnGetGtSystemInfo(pOsInterface);
MOS_OS_CHK_NULL_RETURN(systemInfo);
MosUtilities::MosZeroMemory(&info, sizeof(info));
info.VDBoxInfo = systemInfo->VDBoxInfo;
info.VEBoxInfo = systemInfo->VEBoxInfo;
return MOS_STATUS_SUCCESS;
}
//!
//! \brief Resets OS States
//! \details Resets OS States for linux
//! \param PMOS_INTERFACE pOsInterface
//! [in] Pointer to OS Interface
//! \return void
//!
void Mos_Specific_ResetOsStates(
PMOS_INTERFACE pOsInterface) // [in] OS Interface
{
MOS_OS_FUNCTION_ENTER;
PMOS_OS_CONTEXT pOsContext;
PMOS_OS_GPU_CONTEXT pOsGpuContext;
if (pOsInterface == nullptr ||
pOsInterface->pOsContext == nullptr)
{
return;
}
if (pOsInterface->apoMosEnabled)
{
auto status = MosInterface::ResetCommandBuffer(pOsInterface->osStreamState, 0);
if (MOS_FAILED(status))
{
MOS_OS_ASSERTMESSAGE("ResetCommandBuffer failed.");
}
return;
}
if (pOsInterface->modularizedGpuCtxEnabled && !Mos_Solo_IsEnabled(nullptr))
{
auto gpuContext = Linux_GetGpuContext(pOsInterface, pOsInterface->CurrentGpuContextHandle);
if (gpuContext == nullptr)
{
MOS_OS_ASSERTMESSAGE("GPU Context pointer is nullptr!");
return;
}
gpuContext->ResetGpuContextStatus();
return;
}
pOsContext = pOsInterface->pOsContext;
pOsGpuContext = &pOsContext->OsGpuContext[pOsInterface->CurrentGpuContextOrdinal];
// Reset resource allocation
pOsGpuContext->uiNumAllocations = 0;
MOS_ZeroMemory(pOsGpuContext->pAllocationList, sizeof(ALLOCATION_LIST) * pOsGpuContext->uiMaxNumAllocations);
pOsGpuContext->uiCurrentNumPatchLocations = 0;
MOS_ZeroMemory(pOsGpuContext->pPatchLocationList, sizeof(PATCHLOCATIONLIST) * pOsGpuContext->uiMaxPatchLocationsize);
pOsGpuContext->uiResCount = 0;
MOS_ZeroMemory(pOsGpuContext->pResources, sizeof(MOS_RESOURCE) * pOsGpuContext->uiMaxNumAllocations);
MOS_ZeroMemory(pOsGpuContext->pbWriteMode, sizeof(int32_t) * pOsGpuContext->uiMaxNumAllocations);
if((pOsGpuContext->bCBFlushed == true) && pOsGpuContext->pCB->OsResource.bo)
{
pOsGpuContext->pCB->OsResource.bo = nullptr;
}
}
//!
//! \brief Convert MOS format to gmm format
//! \details convert MOS format to gmm format
//! \param MOS_FORMAT format
//! [in] Surface
//! \return MEDIA_WA_TABLE *
//! Returns the pointer to WA table
//!
GMM_RESOURCE_FORMAT Mos_Specific_ConvertMosFmtToGmmFmt(
MOS_FORMAT format)
{
switch (format)
{
case Format_Buffer : return GMM_FORMAT_GENERIC_8BIT;
case Format_Buffer_2D : return GMM_FORMAT_GENERIC_8BIT; // matching size as format
case Format_L8 : return GMM_FORMAT_GENERIC_8BIT; // matching size as format
case Format_L16 : return GMM_FORMAT_L16_UNORM_TYPE;
case Format_STMM : return GMM_FORMAT_R8_UNORM_TYPE; // matching size as format
case Format_AI44 : return GMM_FORMAT_GENERIC_8BIT; // matching size as format
case Format_IA44 : return GMM_FORMAT_GENERIC_8BIT; // matching size as format
case Format_R5G6B5 : return GMM_FORMAT_B5G6R5_UNORM_TYPE;
case Format_R8G8B8 : return GMM_FORMAT_R8G8B8_UNORM;
case Format_X8R8G8B8 : return GMM_FORMAT_B8G8R8X8_UNORM_TYPE;
case Format_A8R8G8B8 : return GMM_FORMAT_B8G8R8A8_UNORM_TYPE;
case Format_X8B8G8R8 : return GMM_FORMAT_R8G8B8X8_UNORM_TYPE;
case Format_A8B8G8R8 : return GMM_FORMAT_R8G8B8A8_UNORM_TYPE;
case Format_R32F : return GMM_FORMAT_R32_FLOAT_TYPE;
case Format_V8U8 : return GMM_FORMAT_GENERIC_16BIT; // matching size as format
case Format_YUY2 : return GMM_FORMAT_YUY2;
case Format_UYVY : return GMM_FORMAT_UYVY;
case Format_P8 : return GMM_FORMAT_RENDER_8BIT_TYPE; // matching size as format
case Format_A8 : return GMM_FORMAT_A8_UNORM_TYPE;
case Format_AYUV : return GMM_FORMAT_R8G8B8A8_UINT_TYPE;
case Format_NV12 : return GMM_FORMAT_NV12_TYPE;
case Format_NV21 : return GMM_FORMAT_NV21_TYPE;
case Format_YV12 : return GMM_FORMAT_YV12_TYPE;
case Format_R32U : return GMM_FORMAT_R32_UINT_TYPE;
case Format_R32S : return GMM_FORMAT_R32_SINT_TYPE;
case Format_RAW : return GMM_FORMAT_GENERIC_8BIT;
case Format_444P : return GMM_FORMAT_MFX_JPEG_YUV444_TYPE;
case Format_422H : return GMM_FORMAT_MFX_JPEG_YUV422H_TYPE;
case Format_422V : return GMM_FORMAT_MFX_JPEG_YUV422V_TYPE;
case Format_IMC3 : return GMM_FORMAT_IMC3_TYPE;
case Format_411P : return GMM_FORMAT_MFX_JPEG_YUV411_TYPE;
case Format_411R : return GMM_FORMAT_MFX_JPEG_YUV411R_TYPE;
case Format_RGBP : return GMM_FORMAT_RGBP_TYPE;
case Format_BGRP : return GMM_FORMAT_BGRP_TYPE;
case Format_R8U : return GMM_FORMAT_R8_UINT_TYPE;
case Format_R8UN : return GMM_FORMAT_R8_UNORM;
case Format_R16U : return GMM_FORMAT_R16_UINT_TYPE;
case Format_R16F : return GMM_FORMAT_R16_FLOAT_TYPE;
case Format_P010 : return GMM_FORMAT_P010_TYPE;
case Format_P016 : return GMM_FORMAT_P016_TYPE;
case Format_Y216 : return GMM_FORMAT_Y216_TYPE;
case Format_Y416 : return GMM_FORMAT_Y416_TYPE;
case Format_P208 : return GMM_FORMAT_P208_TYPE;
case Format_Y210 : return GMM_FORMAT_Y210_TYPE;
case Format_Y410 : return GMM_FORMAT_Y410_TYPE;
default : return GMM_FORMAT_INVALID;
}
}
//!
//! \brief Allocate resource
//! \details To Allocate Buffer, pass Format as Format_Buffer and set the iWidth as size of the buffer.
//! \param PMOS_INTERFACE pOsInterface
//! [in] Pointer to OS Interface
//! \param PMOS_ALLOC_GFXRES_PARAMS pParams
//! [in] Pointer to resource params
//! \param PMOS_RESOURCE pOsResource
//! [in/out] Pointer to OS resource
//! \return MOS_STATUS
//! Return MOS_STATUS_SUCCESS if successful, otherwise failed
//!
MOS_STATUS Mos_Specific_AllocateResource(
PMOS_INTERFACE pOsInterface,
PMOS_ALLOC_GFXRES_PARAMS pParams,
#if MOS_MESSAGES_ENABLED
PCCHAR functionName,
PCCHAR filename,
int32_t line,
#endif // MOS_MESSAGES_ENABLED
PMOS_RESOURCE pOsResource)
{
void * caller = nullptr;
const char * bufname;
void * ptr;
int32_t iSize = 0;
int32_t iPitch = 0;
unsigned long ulPitch = 0;
MOS_STATUS eStatus;
MOS_LINUX_BO * bo = nullptr;
MOS_TILE_TYPE tileformat;
uint32_t tileformat_linux = 0;
int32_t iHeight = 0;
int32_t iAlignedHeight = 0;
GMM_RESCREATE_PARAMS GmmParams;
GMM_RESOURCE_INFO * pGmmResourceInfo = nullptr;
GMM_RESOURCE_TYPE resourceType = RESOURCE_INVALID;
int mem_type = MOS_MEMPOOL_VIDEOMEMORY;
MOS_OS_FUNCTION_ENTER;
MOS_ZeroMemory(&GmmParams, sizeof(GmmParams));
if( nullptr == pOsResource)
{
MOS_OS_ASSERTMESSAGE("input parameter pOSResource is NULL.");
return MOS_STATUS_INVALID_PARAMETER;
}
if( nullptr == pOsInterface)
{
MOS_OS_ASSERTMESSAGE("input parameter pOsInterface is NULL.");
return MOS_STATUS_INVALID_PARAMETER;
}
bufname = pParams->pBufName;
pOsResource->bConvertedFromDDIResource = false;
bool osContextValid = false;
if (pOsInterface->osContextPtr != nullptr)
{
if (pOsInterface->osContextPtr->GetOsContextValid() == true)
{
osContextValid = true;
}
}
if (pOsInterface->apoMosEnabled)
{
pParams->bBypassMODImpl = !((pOsInterface->modulizedMosEnabled) && (!Mos_Solo_IsEnabled(nullptr)) && (osContextValid == true));
MOS_OS_CHK_NULL_RETURN(pOsInterface->osStreamState);
pOsInterface->osStreamState->component = pOsInterface->Component;
eStatus = MosInterface::AllocateResource(
pOsInterface->osStreamState,
pParams,
pOsResource
#if MOS_MESSAGES_ENABLED
,
functionName,
filename,
line
#endif // MOS_MESSAGES_ENABLED
);
return eStatus;
}
if ((pOsInterface->modulizedMosEnabled) && (!Mos_Solo_IsEnabled(nullptr)) && (osContextValid == true))
{
pOsResource->pGfxResource = GraphicsResource::CreateGraphicResource(GraphicsResource::osSpecificResource);
if (pOsResource->pGfxResource == nullptr)
{
MOS_OS_ASSERTMESSAGE("input nullptr returned by GraphicsResource::CreateGraphicResource.");
return MOS_STATUS_INVALID_HANDLE;
}
if (pOsInterface->osContextPtr == nullptr)
{
MOS_OS_ASSERTMESSAGE("invalid osContextPtr.");
return MOS_STATUS_INVALID_HANDLE;
}
GraphicsResource::SetMemAllocCounterGfx(MosUtilities::m_mosMemAllocCounterGfx);
GraphicsResource::CreateParams params(pParams);
eStatus = pOsResource->pGfxResource->Allocate(pOsInterface->osContextPtr, params);
if (eStatus != MOS_STATUS_SUCCESS)
{
MOS_OS_ASSERTMESSAGE("Allocate graphic resource failed");
return MOS_STATUS_INVALID_HANDLE;
}
eStatus = pOsResource->pGfxResource->ConvertToMosResource(pOsResource);
if (eStatus != MOS_STATUS_SUCCESS)
{
MOS_OS_ASSERTMESSAGE("Convert graphic resource failed");
return MOS_STATUS_INVALID_HANDLE;
}
MosUtilities::m_mosMemAllocCounterGfx = GraphicsResource::GetMemAllocCounterGfx();
MOS_OS_CHK_NULL(pOsResource->pGmmResInfo);
MOS_MEMNINJA_GFX_ALLOC_MESSAGE(pOsResource->pGmmResInfo, bufname, pOsInterface->Component,
(uint32_t)pOsResource->pGmmResInfo->GetSizeSurface(), pParams->dwArraySize, functionName, filename, line);
return eStatus;
}
caller = nullptr;
tileformat_linux = I915_TILING_NONE;
iAlignedHeight = iHeight = pParams->dwHeight;
eStatus = MOS_STATUS_SUCCESS;
resourceType = RESOURCE_2D;
tileformat = pParams->TileType;
MOS_ZeroMemory(&GmmParams, sizeof(GmmParams));
if( nullptr == pOsInterface->pOsContext )
{
MOS_OS_ASSERTMESSAGE("input parameter pOsInterface is NULL.");
return MOS_STATUS_INVALID_PARAMETER;
}
switch (pParams->Format)
{
case Format_Buffer:
case Format_RAW:
resourceType = RESOURCE_BUFFER;
iAlignedHeight = 1;
//indicate buffer Restriction is Vertex.
GmmParams.Flags.Gpu.State = true;
break;
case Format_L8:
case Format_L16:
case Format_STMM:
case Format_AI44:
case Format_IA44:
case Format_R5G6B5:
case Format_R8G8B8:
case Format_X8R8G8B8:
case Format_A8R8G8B8:
case Format_X8B8G8R8:
case Format_A8B8G8R8:
case Format_R32S:
case Format_R32F:
case Format_V8U8:
case Format_YUY2:
case Format_UYVY:
case Format_P8:
case Format_A8:
case Format_AYUV:
case Format_NV12:
case Format_NV21:
case Format_YV12:
case Format_Buffer_2D:
case Format_R32U:
case Format_444P:
case Format_422H:
case Format_422V:
case Format_IMC3:
case Format_411P:
case Format_411R:
case Format_RGBP:
case Format_BGRP:
case Format_R16U:
case Format_R8U:
case Format_R8UN:
case Format_P010:
case Format_P016:
case Format_Y216:
case Format_Y416:
case Format_P208:
case Format_Y210:
case Format_Y410:
case Format_R16F:
resourceType = RESOURCE_2D;
//indicate buffer Restriction is Planar surface restrictions.
GmmParams.Flags.Gpu.Video = true;
break;
default:
MOS_OS_ASSERTMESSAGE("Unsupported format");
eStatus = MOS_STATUS_UNIMPLEMENTED;
goto finish;
}
// Create GmmResourceInfo
GmmParams.BaseWidth = pParams->dwWidth;
GmmParams.BaseHeight = iAlignedHeight;
GmmParams.ArraySize = 1;
GmmParams.Type = resourceType;
GmmParams.Format = Mos_Specific_ConvertMosFmtToGmmFmt(pParams->Format);
MOS_OS_CHECK_CONDITION(GmmParams.Format == GMM_FORMAT_INVALID,
"Unsupported format",
MOS_STATUS_UNKNOWN);
switch(tileformat)
{
case MOS_TILE_Y:
tileformat_linux = I915_TILING_Y;
if (pParams->bIsCompressible && MEDIA_IS_SKU(&pOsInterface->pOsContext->SkuTable, FtrE2ECompression))
{
GmmParams.Flags.Gpu.MMC = true;
GmmParams.Flags.Info.MediaCompressed = 1;
GmmParams.Flags.Gpu.CCS = 1;
GmmParams.Flags.Gpu.RenderTarget = 1;
GmmParams.Flags.Gpu.UnifiedAuxSurface = 1;
if(MEDIA_IS_SKU(&pOsInterface->pOsContext->SkuTable, FtrFlatPhysCCS))
{
GmmParams.Flags.Gpu.UnifiedAuxSurface = 0;
}
}
break;
case MOS_TILE_X:
GmmParams.Flags.Info.TiledX = true;
tileformat_linux = I915_TILING_X;
break;
default:
GmmParams.Flags.Info.Linear = true;
tileformat_linux = I915_TILING_NONE;
}
GmmParams.Flags.Info.LocalOnly = MEDIA_IS_SKU(&pOsInterface->pOsContext->SkuTable, FtrLocalMemory);
pOsResource->pGmmResInfo = pGmmResourceInfo = pOsInterface->pOsContext->pGmmClientContext->CreateResInfoObject(&GmmParams);
MOS_OS_CHK_NULL(pGmmResourceInfo);
switch (pGmmResourceInfo->GetTileType())
{
case GMM_TILED_X:
tileformat = MOS_TILE_X;
tileformat_linux = I915_TILING_X;
break;
case GMM_TILED_Y:
tileformat = MOS_TILE_Y;
tileformat_linux = I915_TILING_Y;
break;
case GMM_NOT_TILED:
tileformat = MOS_TILE_LINEAR;
tileformat_linux = I915_TILING_NONE;
break;
default:
tileformat = MOS_TILE_Y;
tileformat_linux = I915_TILING_Y;
break;
}
if (pParams->TileType == MOS_TILE_Y)
{
pGmmResourceInfo->SetMmcMode((GMM_RESOURCE_MMC_INFO)pParams->CompressionMode, 0);
}
iPitch = GFX_ULONG_CAST(pGmmResourceInfo->GetRenderPitch());
iSize = GFX_ULONG_CAST(pGmmResourceInfo->GetSizeSurface());
iHeight = pGmmResourceInfo->GetBaseHeight();
MemoryPolicyParameter memPolicyPar;
MOS_ZeroMemory(&memPolicyPar, sizeof(MemoryPolicyParameter));
memPolicyPar.skuTable = &pOsInterface->pOsContext->SkuTable;
memPolicyPar.waTable = &pOsInterface->pOsContext->WaTable;
memPolicyPar.resInfo = pGmmResourceInfo;
memPolicyPar.resName = pParams->pBufName;
memPolicyPar.preferredMemType = pParams->dwMemType;
mem_type = MemoryPolicyManager::UpdateMemoryPolicy(&memPolicyPar);
// Only Linear and Y TILE supported
if( tileformat_linux == I915_TILING_NONE )
{
bo = mos_bo_alloc(pOsInterface->pOsContext->bufmgr, bufname, iSize, 4096, mem_type);
}
else
{
bo = mos_bo_alloc_tiled(pOsInterface->pOsContext->bufmgr, bufname, iPitch, iSize/iPitch, 1, &tileformat_linux, &ulPitch, 0, mem_type);
iPitch = (int32_t)ulPitch;
}
pOsResource->bMapped = false;
if (bo)
{
pOsResource->Format = pParams->Format;
pOsResource->iWidth = pParams->dwWidth;
pOsResource->iHeight = iHeight;
pOsResource->iPitch = iPitch;
pOsResource->iCount = 0;
pOsResource->bufname = bufname;
pOsResource->bo = bo;
pOsResource->TileType = tileformat;
pOsResource->TileModeGMM = (MOS_TILE_MODE_GMM)pGmmResourceInfo->GetTileModeSurfaceState();
pOsResource->bGMMTileEnabled = true;
pOsResource->pData = (uint8_t*) bo->virt; //It is useful for batch buffer to fill commands
MOS_OS_VERBOSEMESSAGE("Alloc %7d bytes (%d x %d resource).",iSize, pParams->dwWidth, iHeight);
}
else
{
MOS_OS_ASSERTMESSAGE("Fail to Alloc %7d bytes (%d x %d resource).",iSize, pParams->dwWidth, pParams->dwHeight);
eStatus = MOS_STATUS_NO_SPACE;
}
MosUtilities::m_mosMemAllocCounterGfx++;
MOS_MEMNINJA_GFX_ALLOC_MESSAGE(pOsResource->pGmmResInfo, bufname, pOsInterface->Component,
(uint32_t)pOsResource->pGmmResInfo->GetSizeSurface(), pParams->dwArraySize, functionName, filename, line);
finish:
return eStatus;
}
//!
//! \brief Get Resource Information
//! \details Linux get resource info
//! \param PMOS_INTERFACE pOsInterface
//! [in] Pointer to OS interface structure
//! \param PMOS_RESOURCE pOsResource
//! [in] Pointer to input OS resource
//! \param PMOS_SURFACE pResDetails
//! [out] Pointer to output resource information details
//! \return MOS_STATUS
//! Return MOS_STATUS_SUCCESS if successful, otherwise failed
//!
MOS_STATUS Mos_Specific_GetResourceInfo(
PMOS_INTERFACE pOsInterface,
PMOS_RESOURCE pOsResource,
PMOS_SURFACE pResDetails)
{
GMM_RESOURCE_INFO * pGmmResourceInfo = nullptr;
GMM_DISPLAY_FRAME gmmChannel = GMM_DISPLAY_FRAME_MAX;
GMM_REQ_OFFSET_INFO reqInfo[3] = {};
GMM_RESOURCE_FLAG GmmFlags = {};
MOS_STATUS eStatus;
MOS_OS_FUNCTION_ENTER;
eStatus = MOS_STATUS_SUCCESS;
MOS_OS_CHK_NULL(pOsInterface);
MOS_OS_CHK_NULL(pOsResource);
MOS_OS_CHK_NULL(pResDetails);
if (pOsInterface->apoMosEnabled)
{
return MosInterface::GetResourceInfo(pOsInterface->osStreamState, pOsResource, *pResDetails);
}
// Get Gmm resource info
pGmmResourceInfo = (GMM_RESOURCE_INFO*)pOsResource->pGmmResInfo;
MOS_OS_CHK_NULL(pGmmResourceInfo);
GmmFlags = pGmmResourceInfo->GetResFlags();
pResDetails->dwWidth = GFX_ULONG_CAST(pGmmResourceInfo->GetBaseWidth());
pResDetails->dwHeight = pGmmResourceInfo->GetBaseHeight();
pResDetails->dwPitch = GFX_ULONG_CAST(pGmmResourceInfo->GetRenderPitch());
pResDetails->dwSize = GFX_ULONG_CAST(pGmmResourceInfo->GetSizeSurface());
pResDetails->dwDepth = MOS_MAX(1, pGmmResourceInfo->GetBaseDepth());
pResDetails->dwLockPitch = GFX_ULONG_CAST(pGmmResourceInfo->GetRenderPitch());
if (GFX_GET_CURRENT_RENDERCORE(pOsInterface->pfnGetGmmClientContext(pOsInterface)->GetPlatformInfo().Platform) < IGFX_GEN8_CORE)
{
pResDetails->bArraySpacing = pGmmResourceInfo->IsArraySpacingSingleLod();
}
if (GFX_GET_CURRENT_RENDERCORE(pOsInterface->pfnGetGmmClientContext(pOsInterface)->GetPlatformInfo().Platform) >= IGFX_GEN9_CORE)
{
pResDetails->dwQPitch = pGmmResourceInfo->GetQPitch();
}
pResDetails->bCompressible = GmmFlags.Gpu.MMC ?
(pGmmResourceInfo->GetMmcHint(0) == GMM_MMC_HINT_ON) : false;
pResDetails->bIsCompressed = pGmmResourceInfo->IsMediaMemoryCompressed(0);
pResDetails->CompressionMode = (MOS_RESOURCE_MMC_MODE)pGmmResourceInfo->GetMmcMode(0);
if (0 == pResDetails->dwPitch)
{
MOS_OS_ASSERTMESSAGE("Pitch from GmmResource is 0, unexpected.");
return MOS_STATUS_INVALID_PARAMETER;
}
// check resource's tile type
pResDetails->TileModeGMM = (MOS_TILE_MODE_GMM)pGmmResourceInfo->GetTileModeSurfaceState();
pResDetails->bGMMTileEnabled = true;
switch (pGmmResourceInfo->GetTileType())
{
case GMM_TILED_Y:
if (GmmFlags.Info.TiledYf)
{
pResDetails->TileType = MOS_TILE_YF;
}
else if (GmmFlags.Info.TiledYs)
{
pResDetails->TileType = MOS_TILE_YS;
}
else
{
pResDetails->TileType = MOS_TILE_Y;
}
break;
case GMM_TILED_X:
pResDetails->TileType = MOS_TILE_X;
break;
case GMM_NOT_TILED:
pResDetails->TileType = MOS_TILE_LINEAR;
break;
default:
pResDetails->TileType = MOS_TILE_Y;
break;
}
pResDetails->Format = pOsResource->Format;
MOS_ZeroMemory(reqInfo, sizeof(reqInfo));
gmmChannel = GMM_DISPLAY_BASE;
// Get the base offset of the surface (plane Y)
reqInfo[2].ReqRender = true;
reqInfo[2].Plane = GMM_PLANE_Y;
reqInfo[2].Frame = gmmChannel;
reqInfo[2].CubeFace = __GMM_NO_CUBE_MAP;
reqInfo[2].ArrayIndex = 0;
pGmmResourceInfo->GetOffset(reqInfo[2]);
pResDetails->RenderOffset.YUV.Y.BaseOffset = reqInfo[2].Render.Offset;
// Get U/UV plane information (plane offset, X/Y offset)
reqInfo[0].ReqRender = true;
reqInfo[0].Plane = GMM_PLANE_U;
reqInfo[0].Frame = gmmChannel;
reqInfo[0].CubeFace = __GMM_NO_CUBE_MAP;
reqInfo[0].ArrayIndex = 0;
pGmmResourceInfo->GetOffset(reqInfo[0]);
pResDetails->RenderOffset.YUV.U.BaseOffset = reqInfo[0].Render.Offset;
pResDetails->RenderOffset.YUV.U.XOffset = reqInfo[0].Render.XOffset;
pResDetails->RenderOffset.YUV.U.YOffset = reqInfo[0].Render.YOffset;
// Get V plane information (plane offset, X/Y offset)
reqInfo[1].ReqRender = true;
reqInfo[1].Plane = GMM_PLANE_V;
reqInfo[1].Frame = gmmChannel;
reqInfo[1].CubeFace = __GMM_NO_CUBE_MAP;
reqInfo[1].ArrayIndex = 0;
pGmmResourceInfo->GetOffset(reqInfo[1]);
pResDetails->RenderOffset.YUV.V.BaseOffset = reqInfo[1].Render.Offset;
pResDetails->RenderOffset.YUV.V.XOffset = reqInfo[1].Render.XOffset;
pResDetails->RenderOffset.YUV.V.YOffset = reqInfo[1].Render.YOffset;
finish:
return eStatus;
}
//!
//! \brief Free the resource
//! \details Free the allocated resource
//! \param PMOS_INTERFACE pOsInterface
//! [in] Pointer to OS interface structure
//! \param PMOS_RESOURCE pOsResource
//! [in] Pointer to input OS resource
//! \return void
//!
void Mos_Specific_FreeResource(
PMOS_INTERFACE pOsInterface,
#if MOS_MESSAGES_ENABLED
PCCHAR functionName,
PCCHAR filename,
int32_t line,
#endif // MOS_MESSAGES_ENABLED
PMOS_RESOURCE pOsResource)
{
MOS_OS_FUNCTION_ENTER;
if( nullptr == pOsInterface )
{
MOS_OS_ASSERTMESSAGE("input parameter pOsInterface is NULL.");
return;
}
if( nullptr == pOsResource )
{
MOS_OS_ASSERTMESSAGE("input parameter pOsResource is NULL.");
return;
}
bool osContextValid = false;
if (pOsInterface->osContextPtr != nullptr)
{
if (pOsInterface->osContextPtr->GetOsContextValid() == true)
{
osContextValid = true;
}
}
if (pOsInterface->apoMosEnabled)
{
MosInterface::FreeResource(
pOsInterface->osStreamState,
pOsResource,
0
#if MOS_MESSAGES_ENABLED
,
functionName,
filename,
line
#endif
);
return;
}
if ((pOsInterface->modulizedMosEnabled)
&& (!pOsResource->bConvertedFromDDIResource)
&& (osContextValid == true)
&& (!Mos_Solo_IsEnabled(nullptr))
&& (pOsResource->pGfxResource))
{
if (pOsInterface->osContextPtr == nullptr)
{
MOS_OS_ASSERTMESSAGE("invalid osContextPtr.");
return;
}
GraphicsResource::SetMemAllocCounterGfx(MosUtilities::m_mosMemAllocCounterGfx);
if (pOsResource && pOsResource->pGfxResource)
{
pOsResource->pGfxResource->Free(pOsInterface->osContextPtr);
}
else
{
MOS_OS_VERBOSEMESSAGE("Received an empty Graphics Resource, skip free");
}
MOS_Delete(pOsResource->pGfxResource);
pOsResource->pGfxResource = nullptr;
MosUtilities::m_mosMemAllocCounterGfx = GraphicsResource::GetMemAllocCounterGfx();
MOS_MEMNINJA_GFX_FREE_MESSAGE(pOsResource->pGmmResInfo, functionName, filename, line);
MOS_ZeroMemory(pOsResource, sizeof(*pOsResource));
return;
}
if (pOsResource && pOsResource->bo)
{
OsContextSpecific *osCtx = static_cast<OsContextSpecific *>(pOsInterface->osContextPtr);
if(osCtx == nullptr)
{
MOS_OS_ASSERTMESSAGE("osCtx is nullptr!");
return;
}
else
{
AuxTableMgr *auxTableMgr = osCtx->GetAuxTableMgr();
// Unmap Resource from Aux Table
if (auxTableMgr)
{
auxTableMgr->UnmapResource(pOsResource->pGmmResInfo, pOsResource->bo);
}
}
mos_bo_unreference((MOS_LINUX_BO *)(pOsResource->bo));
if ( pOsInterface->pOsContext != nullptr && pOsInterface->pOsContext->contextOffsetList.size())
{
MOS_CONTEXT *pOsCtx = pOsInterface->pOsContext;
auto item_ctx = pOsCtx->contextOffsetList.begin();
for (;item_ctx != pOsCtx->contextOffsetList.end();)
{
if (item_ctx->target_bo == pOsResource->bo)
{
item_ctx = pOsCtx->contextOffsetList.erase(item_ctx);
}
else
{
item_ctx++;
}
}
}
pOsResource->bo = nullptr;
if (pOsResource->pGmmResInfo != nullptr &&
pOsInterface->pOsContext != nullptr &&
pOsInterface->pOsContext->pGmmClientContext != nullptr)
{
MosUtilities::m_mosMemAllocCounterGfx--;
MOS_MEMNINJA_GFX_FREE_MESSAGE(pOsResource->pGmmResInfo, functionName, filename, line);
pOsInterface->pOsContext->pGmmClientContext->DestroyResInfoObject(pOsResource->pGmmResInfo);
pOsResource->pGmmResInfo = nullptr;
}
}
}
//!
//! \brief Free OS resource
//! \details Free OS resource
//! \param PMOS_INTERFACE pOsInterface
//! [in] OS Interface
//! \param PMOS_RESOURCE pOsResource
//! [in/out] OS Resource to be freed
//! \param uint32_t uiFlag
//! [in] Flag to free resources. This one is useless on Linux, just for compatibility.
//! \return void
//!
void Mos_Specific_FreeResourceWithFlag(
PMOS_INTERFACE pOsInterface,
PMOS_RESOURCE pOsResource,
#if MOS_MESSAGES_ENABLED
PCCHAR functionName,
PCCHAR filename,
int32_t line,
#endif // MOS_MESSAGES_ENABLED
uint32_t uiFlag)
{
MOS_UNUSED(uiFlag);
if (pOsInterface == nullptr ||
pOsResource == nullptr)
{
return;
}
#if MOS_MESSAGES_ENABLED
Mos_Specific_FreeResource(pOsInterface, functionName, filename, line, pOsResource);
#else
Mos_Specific_FreeResource(pOsInterface, pOsResource);
#endif // MOS_MESSAGES_ENABLED
}
//!
//! \brief Locks Resource request
//! \details Locks Resource request
//! \param PMOS_INTERFACE pOsInterface
//! [in] pointer to OS Interface structure
//! \param PMOS_RESOURCE pOsResource
//! [in/out] Resource object
//! \param PMOS_LOCK_PARAMS pLockFlags
//! [in] Lock Flags
//! \return MOS_STATUS
//! MOS_STATUS_SUCCESS if successful
//!
MOS_STATUS Mos_Specific_LockSyncRequest(
PMOS_INTERFACE pOsInterface,
PMOS_RESOURCE pOsResource,
PMOS_LOCK_PARAMS pLockFlags)
{
MOS_UNUSED(pOsInterface);
MOS_UNUSED(pOsInterface);
MOS_UNUSED(pOsInterface);
return MOS_STATUS_SUCCESS;
}
//!
//! \brief Lock resource
//! \details Lock allocated resource
//! \param PMOS_INTERFACE pOsInterface
//! [in] Pointer to OS interface structure
//! \param PMOS_RESOURCE pOsResource
//! [in] Pointer to input OS resource
//! \param PMOS_LOCK_PARAMS pLockFlags
//! [in] Lock Flags - MOS_LOCKFLAG_* flags
//! \return void *
//!
void *Mos_Specific_LockResource(
PMOS_INTERFACE pOsInterface,
PMOS_RESOURCE pOsResource,
PMOS_LOCK_PARAMS pLockFlags)
{
void *pData = nullptr;
MOS_OS_CONTEXT *pContext = nullptr;
MOS_OS_FUNCTION_ENTER;
MOS_OS_ASSERT(pOsInterface);
MOS_OS_ASSERT(pOsResource);
MOS_OS_ASSERT(pOsInterface->pOsContext);
if( nullptr == pOsInterface )
{
MOS_OS_ASSERTMESSAGE("input parameter pOsInterface is NULL.");
return nullptr;
}
if( nullptr == pOsResource)
{
MOS_OS_ASSERTMESSAGE("input parameter pOsInterface is NULL.");
return nullptr;
}
bool osContextValid = false;
if (pOsInterface->osContextPtr != nullptr)
{
if (pOsInterface->osContextPtr->GetOsContextValid() == true)
{
osContextValid = true;
}
}
if (pOsInterface->apoMosEnabled)
{
return MosInterface::LockMosResource(pOsInterface->osStreamState, pOsResource, pLockFlags);
}
if ((pOsInterface->modulizedMosEnabled)
&& (!pOsResource->bConvertedFromDDIResource)
&& (osContextValid == true)
&& (!Mos_Solo_IsEnabled(nullptr))
&& (pOsResource->pGfxResource))
{
if (nullptr == pOsInterface->osContextPtr)
{
MOS_OS_ASSERTMESSAGE("invalid osContextPtr, skip lock");
}
if (pOsResource->pGfxResource)
{
GraphicsResource::LockParams params(pLockFlags);
pData = pOsResource->pGfxResource->Lock(pOsInterface->osContextPtr, params);
}
else
{
MOS_OS_ASSERTMESSAGE("Received an empty Graphics Resource, skip lock");
}
return pData;
}
pContext = pOsInterface->pOsContext;
if (pOsResource && pOsResource->bo && pOsResource->pGmmResInfo)
{
MOS_LINUX_BO *bo = pOsResource->bo;
GMM_RESOURCE_FLAG GmmFlags;
MOS_ZeroMemory(&GmmFlags, sizeof(GmmFlags));
GmmFlags = pOsResource->pGmmResInfo->GetResFlags();
// Do decompression for a compressed surface before lock
if (!pLockFlags->NoDecompress &&
(((GmmFlags.Gpu.MMC || GmmFlags.Gpu.CCS) && GmmFlags.Gpu.UnifiedAuxSurface)||
pOsResource->pGmmResInfo->IsMediaMemoryCompressed(0)))
{
PMOS_CONTEXT pOsContext = pOsInterface->pOsContext;
MOS_OS_ASSERT(pOsContext);
MOS_OS_ASSERT(pOsContext->ppMediaMemDecompState);
MOS_OS_ASSERT(pOsContext->pfnMemoryDecompress);
pOsContext->pfnMemoryDecompress(pOsContext, pOsResource);
}
if(false == pOsResource->bMapped)
{
if (pContext->bIsAtomSOC)
{
mos_gem_bo_map_gtt(bo);
}
else
{
if (pOsResource->TileType != MOS_TILE_LINEAR && !pLockFlags->TiledAsTiled)
{
if (pContext->bUseSwSwizzling)
{
mos_bo_map(bo, (OSKM_LOCKFLAG_WRITEONLY&pLockFlags->WriteOnly));
pOsResource->MmapOperation = MOS_MMAP_OPERATION_MMAP;
if (pOsResource->pSystemShadow == nullptr)
{
pOsResource->pSystemShadow = (uint8_t *)MOS_AllocMemory(bo->size);
MOS_OS_CHECK_CONDITION((pOsResource->pSystemShadow == nullptr), "Failed to allocate shadow surface", nullptr);
}
if (pOsResource->pSystemShadow)
{
int32_t flags = pContext->bTileYFlag ? 0 : 1;
MOS_OS_CHECK_CONDITION((pOsResource->TileType != MOS_TILE_Y), "Unsupported tile type", nullptr);
MOS_OS_CHECK_CONDITION((bo->size <= 0 || pOsResource->iPitch <= 0), "Invalid BO size or pitch", nullptr);
Mos_SwizzleData((uint8_t*)bo->virt, pOsResource->pSystemShadow,
MOS_TILE_Y, MOS_TILE_LINEAR, bo->size / pOsResource->iPitch, pOsResource->iPitch, flags);
}
}
else
{
mos_gem_bo_map_gtt(bo);
pOsResource->MmapOperation = MOS_MMAP_OPERATION_MMAP_GTT;
}
}
else if (pLockFlags->Uncached)
{
mos_gem_bo_map_wc(bo);
pOsResource->MmapOperation = MOS_MMAP_OPERATION_MMAP_WC;
}
else
{
mos_bo_map(bo, (OSKM_LOCKFLAG_WRITEONLY&pLockFlags->WriteOnly));
pOsResource->MmapOperation = MOS_MMAP_OPERATION_MMAP;
}
}
pOsResource->pData = pOsResource->pSystemShadow ? pOsResource->pSystemShadow : (uint8_t*)bo->virt;
pOsResource->bMapped = true;
}
pData = pOsResource->pData;
}
finish:
MOS_OS_ASSERT(pData);
return pData;
}
//!
//! \brief Unlock resource
//! \details Unlock the locked resource
//! \param PMOS_INTERFACE pOsInterface
//! [in] Pointer to OS interface structure
//! \param PMOS_RESOURCE pOsResource
//! [in] Pointer to input OS resource
//! \return MOS_STATUS
//! Return MOS_STATUS_SUCCESS if successful, otherwise failed
//!
MOS_STATUS Mos_Specific_UnlockResource(
PMOS_INTERFACE pOsInterface,
PMOS_RESOURCE pOsResource)
{
MOS_STATUS eStatus;
eStatus = MOS_STATUS_SUCCESS;
MOS_OS_CONTEXT *pContext = nullptr;
MOS_OS_FUNCTION_ENTER;
MOS_OS_CHK_NULL(pOsInterface);
MOS_OS_CHK_NULL(pOsResource);
MOS_OS_CHK_NULL(pOsInterface->pOsContext);
if (pOsInterface->apoMosEnabled)
{
return MosInterface::UnlockMosResource(pOsInterface->osStreamState, pOsResource);
}
bool osContextValid;
osContextValid = false;
if (pOsInterface->osContextPtr != nullptr)
{
if (pOsInterface->osContextPtr->GetOsContextValid() == true)
{
osContextValid = true;
}
}
if ((pOsInterface->modulizedMosEnabled)
&& (!pOsResource->bConvertedFromDDIResource)
&& (osContextValid == true)
&& (!Mos_Solo_IsEnabled(nullptr))
&& (pOsResource->pGfxResource))
{
if (nullptr == pOsInterface->osContextPtr)
{
MOS_OS_ASSERTMESSAGE("invalid osContextPtr, skip lock");
}
if (pOsResource->pGfxResource)
{
eStatus = pOsResource->pGfxResource->Unlock(pOsInterface->osContextPtr);
}
else
{
MOS_OS_VERBOSEMESSAGE("Received an empty Graphics Resource, skip unlock");
}
return eStatus;
}
pContext = pOsInterface->pOsContext;
if(pOsResource->bo)
{
if(true == pOsResource->bMapped)
{
if (pContext->bIsAtomSOC)
{
mos_gem_bo_unmap_gtt(pOsResource->bo);
}
else
{
if (pOsResource->pSystemShadow)
{
int32_t flags = pContext->bTileYFlag ? 0 : 1;
Mos_SwizzleData(pOsResource->pSystemShadow, (uint8_t*)pOsResource->bo->virt,
MOS_TILE_LINEAR, MOS_TILE_Y, pOsResource->bo->size / pOsResource->iPitch, pOsResource->iPitch, flags);
MOS_FreeMemory(pOsResource->pSystemShadow);
pOsResource->pSystemShadow = nullptr;
}
switch(pOsResource->MmapOperation)
{
case MOS_MMAP_OPERATION_MMAP_GTT:
mos_gem_bo_unmap_gtt(pOsResource->bo);
break;
case MOS_MMAP_OPERATION_MMAP_WC:
mos_gem_bo_unmap_wc(pOsResource->bo);
break;
case MOS_MMAP_OPERATION_MMAP:
mos_bo_unmap(pOsResource->bo);
break;