﻿/*
* Copyright (c) 2019, 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_gpucontextmgr_next.cpp
//! \brief   Container class for the basic gpu context manager
//!

#include "mos_gpucontextmgr_next.h"
#include "mos_gpucontext_specific_next.h"
#include "mos_graphicsresource_specific_next.h"

GpuContextMgrNext::GpuContextMgrNext(GT_SYSTEM_INFO *gtSystemInfo, OsContextNext *osContext)
{
    MOS_OS_FUNCTION_ENTER;
    m_initialized = false;

    if (gtSystemInfo)
    {
        MosUtilities::MosSecureMemcpy(&m_gtSystemInfo, sizeof(GT_SYSTEM_INFO), gtSystemInfo, sizeof(GT_SYSTEM_INFO));
    }
    else
    {
        MOS_OS_ASSERTMESSAGE("Input GTSystemInfo cannot be nullptr");
        return;
    }

    if (osContext)
    {
        m_osContext = osContext;
    }
    else
    {
        MOS_OS_ASSERTMESSAGE("Input osContext cannot be nullptr");
        return;
    }
}

GpuContextMgrNext::~GpuContextMgrNext()
{
    MOS_OS_FUNCTION_ENTER;

    if (m_gpuContextArrayMutex)
    {
        MosUtilities::MosDestroyMutex(m_gpuContextArrayMutex);
        m_gpuContextArrayMutex = nullptr;
    }
}

MOS_STATUS GpuContextMgrNext::Initialize()
{
    MOS_STATUS status = MOS_STATUS_SUCCESS;
    m_gpuContextArrayMutex = MosUtilities::MosCreateMutex();
    MOS_OS_CHK_NULL_RETURN(m_gpuContextArrayMutex);

    MosUtilities::MosLockMutex(m_gpuContextArrayMutex);
    m_gpuContextArray.clear();
    MosUtilities::MosUnlockMutex(m_gpuContextArrayMutex);

    m_initialized = true;
    return status;
}


GpuContextMgrNext *GpuContextMgrNext::GetObject(
    GT_SYSTEM_INFO *gtSystemInfo,
    OsContextNext     *osContext)
{
    MOS_OS_FUNCTION_ENTER;
    if (gtSystemInfo == nullptr || osContext == nullptr)
    {
        MOS_OS_ASSERTMESSAGE("Invalid input parameters!");
        return nullptr;
    }

    MOS_STATUS status = MOS_STATUS_SUCCESS;
    GpuContextMgrNext* pGpuContext = MOS_New(GpuContextMgrNext, gtSystemInfo, osContext);
    if (!pGpuContext)
    {
        return nullptr;
    }
    status = pGpuContext->Initialize();
    if (MOS_FAILED(status))
    {
        MOS_Delete(pGpuContext);
        return nullptr;
    }
    return pGpuContext;
}

void GpuContextMgrNext::CleanUp()
{
    MOS_OS_FUNCTION_ENTER;

    if (m_initialized)
    {
        DestroyAllGpuContexts();

        MosUtilities::MosLockMutex(m_gpuContextArrayMutex);
        m_gpuContextArray.clear();
        MosUtilities::MosUnlockMutex(m_gpuContextArrayMutex);

        m_initialized = false;
    }

    return;
}

bool GpuContextMgrNext::ContextReuseNeeded()
{
    MOS_OS_FUNCTION_ENTER;

    // to be added after scalable design is nailed down
    return false;
}

GpuContextNext *GpuContextMgrNext::SelectContextToReuse()
{
    MOS_OS_FUNCTION_ENTER;

    // to be added after scalable design is nailed down
    return nullptr;
}

GpuContextNext *GpuContextMgrNext::CreateGpuContext(
    const MOS_GPU_NODE gpuNode,
    CmdBufMgrNext *    cmdBufMgr)
{
    MOS_OS_FUNCTION_ENTER;

    if (cmdBufMgr == nullptr && !m_osContext->IsAynchronous())
    {
        MOS_OS_ASSERTMESSAGE("nullptr of cmdbufmgr in normal mode. nullptr can only be applied in Async mode");
        return nullptr;
    }

    GpuContextNext *reusedContext = nullptr;
    if (ContextReuseNeeded())
    {
        reusedContext = SelectContextToReuse();
    }

    GpuContextNext *gpuContext = GpuContextNext::Create(gpuNode, cmdBufMgr, reusedContext);
    if (gpuContext == nullptr)
    {
        MOS_OS_ASSERTMESSAGE("nullptr returned by GpuContext::Create.");
        return nullptr;
    }

    MosUtilities::MosLockMutex(m_gpuContextArrayMutex);

    GPU_CONTEXT_HANDLE gpuContextHandle = 0;

    if (m_noCycledGpuCxtMgmt)
    {
        // new created context at the end of m_gpuContextArray.
        gpuContextHandle = m_gpuContextArray.size() ? m_gpuContextArray.size() : 0;
    }
    else
    {
        // Directly replace nullptr with new created context in m_gpuContextArray.
        GpuContextNext *curGpuContext = nullptr;
        int         index         = 0;
        for (auto &curGpuContext : m_gpuContextArray)
        {
            if (curGpuContext == nullptr)
            {
                break;
            }
            index++;
        }
        gpuContextHandle = m_gpuContextArray.size() ? index : 0;
    }
    gpuContext->SetGpuContextHandle(gpuContextHandle);

    if (gpuContextHandle == m_gpuContextArray.size())
    {
        m_gpuContextArray.push_back(gpuContext);
    }
    else
    {
        m_gpuContextArray[gpuContextHandle] = gpuContext;
    }
    m_gpuContextCount++;

    MosUtilities::MosUnlockMutex(m_gpuContextArrayMutex);

    return gpuContext;
}

GpuContextNext *GpuContextMgrNext::GetGpuContext(GPU_CONTEXT_HANDLE gpuContextHandle)
{
    MOS_OS_FUNCTION_ENTER;

    if (gpuContextHandle == MOS_GPU_CONTEXT_INVALID_HANDLE)
    {
        MOS_OS_ASSERTMESSAGE("Input gpucontext handle cannot be MOS_GPU_CONTEXT_INVALID_HANDLE!");
        return nullptr;
    }

    if (!m_gpuContextArray.empty() && gpuContextHandle < m_gpuContextArray.size())
    {
        return m_gpuContextArray.at(gpuContextHandle);
    }
    else
    {
        MOS_OS_ASSERTMESSAGE("GPU context array is empty or got invalid index, something must be wrong!");
        return nullptr;
    }
}

void GpuContextMgrNext::DestroyGpuContext(GpuContextNext *gpuContext)
{
    MOS_OS_FUNCTION_ENTER;
    MOS_OS_CHK_NULL_NO_STATUS_RETURN(gpuContext);

    GpuContextNext *curGpuContext = nullptr;
    bool        found         = false;

    MosUtilities::MosLockMutex(m_gpuContextArrayMutex);
    for (auto &curGpuContext : m_gpuContextArray)
    {
        if (curGpuContext == gpuContext)
        {
            found = true;
            // to keep original order, here should not erase gpucontext, replace with nullptr in array.
            MOS_Delete(curGpuContext);  // delete gpu context.
            m_gpuContextCount--;
            break;
        }
    }

    if (m_gpuContextCount == 0 && !m_noCycledGpuCxtMgmt)
    {
        m_gpuContextArray.clear();  // clear whole array
    }

    MosUtilities::MosUnlockMutex(m_gpuContextArrayMutex);

    if (!found)
    {
        MOS_OS_ASSERTMESSAGE("cannot find specified gpuContext in the gpucontext pool, something must be wrong");
    }
}

void GpuContextMgrNext::DestroyAllGpuContexts()
{
    MOS_OS_FUNCTION_ENTER;

    GpuContextNext *curGpuContext = nullptr;

    MosUtilities::MosLockMutex(m_gpuContextArrayMutex);

    // delete each instance in m_gpuContextArray
    for (auto &curGpuContext : m_gpuContextArray)
    {
        MOS_Delete(curGpuContext);
    }

    m_gpuContextArray.clear();  // clear whole array

    MosUtilities::MosUnlockMutex(m_gpuContextArrayMutex);
}
