| /* |
| * Copyright (c) 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 media_copy.cpp |
| //! \brief Common interface and structure used in media copy |
| //! \details Common interface and structure used in media copy which are platform independent |
| //! |
| |
| #include "media_copy.h" |
| |
| MediaCopyBaseState::MediaCopyBaseState(): |
| m_osInterface(nullptr) |
| { |
| |
| } |
| |
| MediaCopyBaseState::~MediaCopyBaseState() |
| { |
| MOS_STATUS eStatus; |
| |
| if (m_mhwInterfaces) |
| { |
| if (m_mhwInterfaces->m_cpInterface) |
| { |
| Delete_MhwCpInterface(m_mhwInterfaces->m_cpInterface); |
| m_mhwInterfaces->m_cpInterface = nullptr; |
| } |
| MOS_Delete(m_mhwInterfaces->m_miInterface); |
| MOS_Delete(m_mhwInterfaces->m_veboxInterface); |
| MOS_Delete(m_mhwInterfaces->m_bltInterface); |
| MOS_Delete(m_mhwInterfaces->m_renderInterface); |
| MOS_Delete(m_mhwInterfaces); |
| m_mhwInterfaces = nullptr; |
| } |
| |
| if (m_osInterface) |
| { |
| m_osInterface->pfnDestroy(m_osInterface, false); |
| MOS_FreeMemory(m_osInterface); |
| m_osInterface = nullptr; |
| } |
| |
| if (m_inUseGPUMutex) |
| { |
| MosUtilities::MosDestroyMutex(m_inUseGPUMutex); |
| m_inUseGPUMutex = nullptr; |
| } |
| } |
| |
| //! |
| //! \brief init Media copy |
| //! \details init func. |
| //! \param none |
| //! \return MOS_STATUS |
| //! Return MOS_STATUS_SUCCESS if success, otherwise return failed. |
| //! |
| MOS_STATUS MediaCopyBaseState::Initialize(PMOS_INTERFACE osInterface, MhwInterfaces *mhwInterfaces) |
| { |
| m_inUseGPUMutex = MosUtilities::MosCreateMutex(); |
| MCPY_CHK_NULL_RETURN(m_inUseGPUMutex); |
| return MOS_STATUS_SUCCESS; |
| } |
| |
| //! |
| //! \brief check copy capability. |
| //! \details to determine surface copy is supported or not. |
| //! \param none |
| //! \return MOS_STATUS |
| //! Return MOS_STATUS_SUCCESS if support, otherwise return unspoort. |
| //! |
| MOS_STATUS MediaCopyBaseState::CapabilityCheck() |
| { |
| // init hw enigne caps. |
| m_mcpyEngineCaps.engineVebox = 1; |
| m_mcpyEngineCaps.engineBlt = 1; |
| m_mcpyEngineCaps.engineRender = 1; |
| |
| // common policy check |
| // legal check |
| // Blt engine does not support protection, allow the copy if dst is staging buffer in system mem |
| if (m_mcpySrc.CpMode == MCPY_CPMODE_CP && m_mcpyDst.CpMode == MCPY_CPMODE_CLEAR && !m_allowBltCopy) |
| { |
| MCPY_ASSERTMESSAGE("illegal usage"); |
| return MOS_STATUS_INVALID_PARAMETER; |
| } |
| |
| // vebox cap check. |
| if (!IsVeboxCopySupported(m_mcpySrc.OsRes, m_mcpyDst.OsRes) || // format check, implemented on Gen derivate class. |
| (m_mcpyDst.CompressionMode == MOS_MMC_RC) || // compression check |
| m_mcpySrc.bAuxSuface) |
| { |
| m_mcpyEngineCaps.engineVebox = false; |
| } |
| |
| // Eu cap check. |
| if (!RenderFormatSupportCheck(m_mcpySrc.OsRes, m_mcpyDst.OsRes) || // format check, implemented on Gen derivate class. |
| (m_mcpyDst.CompressionMode == MOS_MMC_MC) || |
| m_mcpySrc.bAuxSuface) |
| { |
| m_mcpyEngineCaps.engineRender = false; |
| } |
| |
| // blt check. |
| if ((m_mcpySrc.CompressionMode != MOS_MMC_DISABLED) || |
| (m_mcpyDst.CompressionMode != MOS_MMC_DISABLED) || |
| (m_mcpySrc.TileMode != m_mcpyDst.TileMode)) |
| { |
| m_mcpyEngineCaps.engineBlt = false; |
| } |
| |
| // derivate class specific check. include HW engine avaliable check. |
| FeatureSupport(m_mcpySrc.OsRes, m_mcpyDst.OsRes, m_mcpySrc, m_mcpyDst, m_mcpyEngineCaps); |
| |
| if (!m_mcpyEngineCaps.engineVebox && !m_mcpyEngineCaps.engineBlt && !m_mcpyEngineCaps.engineRender) |
| { |
| return MOS_STATUS_INVALID_PARAMETER; // unsupport copy on each hw engine. |
| } |
| |
| return MOS_STATUS_SUCCESS; |
| } |
| |
| //! |
| //! \brief surface copy pre process. |
| //! \details pre process before doing surface copy. |
| //! \param none |
| //! \return MOS_STATUS |
| //! Return MOS_STATUS_SUCCESS if support, otherwise return unspoort. |
| //! |
| MOS_STATUS MediaCopyBaseState::PreProcess(MCPY_METHOD preferMethod) |
| { |
| return MOS_STATUS_SUCCESS; |
| } |
| |
| //! |
| //! \brief dispatch copy task if support. |
| //! \details dispatch copy task to HW engine (vebox, EU, Blt) based on customer and default. |
| //! \param src |
| //! [in] Pointer to source surface |
| //! \param dst |
| //! [in] Pointer to destination surface |
| //! \return MOS_STATUS |
| //! Return MOS_STATUS_SUCCESS if support, otherwise return unspoort. |
| //! |
| MOS_STATUS MediaCopyBaseState::CopyEnigneSelect(MCPY_METHOD preferMethod) |
| { |
| // assume perf render > vebox > blt. blt data should be measured. |
| // driver should make sure there is at least one he can process copy even customer choice doesn't match caps. |
| switch (preferMethod) |
| { |
| case MCPY_METHOD_PERFORMANCE: |
| m_mcpyEngine = m_mcpyEngineCaps.engineRender?MCPY_ENGINE_RENDER:(m_mcpyEngineCaps.engineVebox?MCPY_ENGINE_VEBOX:MCPY_ENGINE_BLT); |
| break; |
| case MCPY_METHOD_BALANCE: |
| m_mcpyEngine = m_mcpyEngineCaps.engineVebox?MCPY_ENGINE_VEBOX:(m_mcpyEngineCaps.engineBlt?MCPY_ENGINE_BLT:MCPY_ENGINE_RENDER); |
| break; |
| case MCPY_METHOD_POWERSAVING: |
| m_mcpyEngine = m_mcpyEngineCaps.engineBlt?MCPY_ENGINE_BLT:(m_mcpyEngineCaps.engineVebox?MCPY_ENGINE_VEBOX:MCPY_ENGINE_RENDER); |
| break; |
| default: |
| break; |
| } |
| |
| return MOS_STATUS_SUCCESS; |
| } |
| |
| //! |
| //! \brief surface copy func. |
| //! \details copy surface. |
| //! \param src |
| //! [in] Pointer to source surface |
| //! \param dst |
| //! [in] Pointer to destination surface |
| //! \return MOS_STATUS |
| //! Return MOS_STATUS_SUCCESS if support, otherwise return unspoort. |
| //! |
| MOS_STATUS MediaCopyBaseState::SurfaceCopy(PMOS_RESOURCE src, PMOS_RESOURCE dst, MCPY_METHOD preferMethod) |
| { |
| MOS_STATUS eStatus = MOS_STATUS_SUCCESS; |
| |
| MOS_SURFACE ResDetails; |
| MOS_ZeroMemory(&ResDetails, sizeof(MOS_SURFACE)); |
| MCPY_CHK_STATUS_RETURN(m_osInterface->pfnGetResourceInfo(m_osInterface, src, &ResDetails)); |
| m_mcpySrc.CompressionMode = ResDetails.CompressionMode; |
| m_mcpySrc.CpMode = src->pGmmResInfo->GetSetCpSurfTag(false, 0)?MCPY_CPMODE_CP:MCPY_CPMODE_CLEAR; |
| m_mcpySrc.TileMode = ResDetails.TileType; |
| m_mcpySrc.OsRes = src; |
| |
| MOS_ZeroMemory(&ResDetails, sizeof(MOS_SURFACE)); |
| MCPY_CHK_STATUS_RETURN(m_osInterface->pfnGetResourceInfo(m_osInterface, dst, &ResDetails)); |
| m_mcpyDst.CompressionMode = ResDetails.CompressionMode; |
| m_mcpyDst.CpMode = dst->pGmmResInfo->GetSetCpSurfTag(false, 0)?MCPY_CPMODE_CP:MCPY_CPMODE_CLEAR; |
| m_mcpyDst.TileMode = ResDetails.TileType; |
| m_mcpyDst.OsRes = dst; |
| |
| MCPY_CHK_STATUS_RETURN(PreProcess(preferMethod)); |
| |
| MCPY_CHK_STATUS_RETURN(CapabilityCheck()); |
| |
| CopyEnigneSelect(preferMethod); |
| |
| MCPY_CHK_STATUS_RETURN(TaskDispatch()); |
| |
| return eStatus; |
| } |
| |
| MOS_STATUS MediaCopyBaseState::TaskDispatch() |
| { |
| MOS_STATUS eStatus = MOS_STATUS_SUCCESS; |
| MosUtilities::MosLockMutex(m_inUseGPUMutex); |
| switch(m_mcpyEngine) |
| { |
| case MCPY_ENGINE_VEBOX: |
| eStatus = MediaVeboxCopy(m_mcpySrc.OsRes, m_mcpyDst.OsRes); |
| break; |
| case MCPY_ENGINE_BLT: |
| eStatus = MediaBltCopy(m_mcpySrc.OsRes, m_mcpyDst.OsRes); |
| break; |
| case MCPY_ENGINE_RENDER: |
| eStatus = MediaRenderCopy(m_mcpySrc.OsRes, m_mcpyDst.OsRes); |
| break; |
| default: |
| break; |
| } |
| MosUtilities::MosUnlockMutex(m_inUseGPUMutex); |
| |
| #if (_DEBUG || _RELEASE_INTERNAL) |
| char *CopyEngine = (char *)(m_mcpyEngine?(m_mcpyEngine == MCPY_ENGINE_BLT?"BLT":"Render"):"VeBox"); |
| WriteUserFeatureString(__MEDIA_USER_FEATURE_MCPY_MODE_ID, CopyEngine, strlen(CopyEngine), nullptr); |
| #endif |
| MCPY_NORMALMESSAGE("Media Copy works on %s Engine", m_mcpyEngine?(m_mcpyEngine == MCPY_ENGINE_BLT?"BLT":"Render"):"VeBox"); |
| |
| return eStatus; |
| } |
| |
| //! |
| //! \brief aux surface copy. |
| //! \details copy surface. |
| //! \param src |
| //! [in] Pointer to source surface |
| //! \param dst |
| //! [in] Pointer to destination surface |
| //! \return MOS_STATUS |
| //! Return MOS_STATUS_SUCCESS if support, otherwise return unspoort. |
| //! |
| MOS_STATUS MediaCopyBaseState::AuxCopy(PMOS_RESOURCE src, PMOS_RESOURCE dst) |
| { |
| // only support form Gen12+, will implement on deriavete class. |
| MCPY_ASSERTMESSAGE("doesn't support"); |
| return MOS_STATUS_INVALID_HANDLE; |
| } |
| |