/* * Copyright (c) 2018, 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_allocator.cpp //! \brief Defines the common interface for media resource manage //! \details Media allocator will allocate and destory buffers, the caller //! can use directly //! #include #include "media_allocator.h" Allocator::Allocator(PMOS_INTERFACE osInterface) : m_osInterface(osInterface) { } Allocator::~Allocator() { DestroyAllResources(); } MOS_STATUS Allocator::DestroyAllResources() { #if (_DEBUG || _RELEASE_INTERNAL) for (auto it : m_resourcePool) { MOS_RESOURCE *resource = const_cast(it.first); m_osInterface->pfnFreeResource(m_osInterface, resource); MOS_Delete(resource); MOS_Delete(it.second); } m_resourcePool.clear(); for (auto it : m_surfacePool) { MOS_SURFACE *surface = const_cast(it.first); if (surface) { m_osInterface->pfnFreeResource(m_osInterface, &(surface->OsResource)); } MOS_Delete(surface); MOS_Delete(it.second); } m_surfacePool.clear(); #else for (auto it : m_resourcePool) { m_osInterface->pfnFreeResource(m_osInterface, it); MOS_Delete(it); } m_resourcePool.clear(); for (auto it : m_surfacePool) { m_osInterface->pfnFreeResource(m_osInterface, &it->OsResource); MOS_Delete(it); } m_surfacePool.clear(); #endif return MOS_STATUS_SUCCESS; } MOS_RESOURCE *Allocator::AllocateResource(MOS_ALLOC_GFXRES_PARAMS ¶m, bool zeroOnAllocate, MOS_COMPONENT component) { if (nullptr == m_osInterface) { return nullptr; } MOS_RESOURCE *resource = MOS_New(MOS_RESOURCE); memset(resource, 0, sizeof(MOS_RESOURCE)); MOS_STATUS status = m_osInterface->pfnAllocateResource(m_osInterface, ¶m, resource); if (status != MOS_STATUS_SUCCESS) { MOS_Delete(resource); return nullptr; } #if (_DEBUG || _RELEASE_INTERNAL) TraceInfo *info = MOS_New(TraceInfo); if (nullptr == info) { FreeResource(resource); MOS_Delete(resource); return nullptr; } info->component = component; //Note, param.pBufName cannot be null. //This assignment statement will calcualte the string length and copy param.pBufName to info->name. //If param.pBufName is null, exception happens when to calculate the string length. MOS_OS_ASSERT(param.pBufName != nullptr); info->name = param.pBufName; m_resourcePool.insert(std::make_pair(resource, info)); #else m_resourcePool.push_back(resource); #endif if (zeroOnAllocate) { ClearResource(resource, param); } return resource; } PMOS_BUFFER Allocator::AllocateBuffer(MOS_ALLOC_GFXRES_PARAMS ¶m, bool zeroOnAllocate, MOS_COMPONENT component) { if (nullptr == m_osInterface) { return nullptr; } MOS_BUFFER *buffer = MOS_New(MOS_BUFFER); if (nullptr == buffer) { return nullptr; } memset(buffer, 0, sizeof(MOS_BUFFER)); MOS_STATUS status = m_osInterface->pfnAllocateResource(m_osInterface, ¶m, &buffer->OsResource); if (status != MOS_STATUS_SUCCESS) { MOS_Delete(buffer); return nullptr; } #if (_DEBUG || _RELEASE_INTERNAL) TraceInfo *info = MOS_New(TraceInfo); if (nullptr == info) { FreeResource(&buffer->OsResource); MOS_Delete(buffer); return nullptr; } info->component = component; //Note, param.pBufName cannot be null. //This assignment statement will calcualte the string length and copy param.pBufName to info->name. //If param.pBufName is null, exception happens when to calculate the string length. MOS_OS_ASSERT(param.pBufName != nullptr); info->name = param.pBufName; m_resourcePool.insert(std::make_pair(&buffer->OsResource, info)); #else m_resourcePool.push_back(&buffer->OsResource); #endif if (zeroOnAllocate) { ClearResource(&buffer->OsResource, param); } return buffer; } MOS_SURFACE *Allocator::AllocateSurface(MOS_ALLOC_GFXRES_PARAMS ¶m, bool zeroOnAllocate, MOS_COMPONENT component) { MOS_SURFACE *surface = MOS_New(MOS_SURFACE); if (nullptr == surface) { return nullptr; } MOS_STATUS status = m_osInterface->pfnAllocateResource(m_osInterface, ¶m, &surface->OsResource); m_osInterface->pfnGetResourceInfo(m_osInterface, &surface->OsResource, surface); #if (_DEBUG || _RELEASE_INTERNAL) TraceInfo *info = MOS_New(TraceInfo); if (nullptr == info) { FreeResource(&surface->OsResource); MOS_Delete(surface); return nullptr; } info->component = component; MOS_OS_ASSERT(param.pBufName != nullptr); info->name = param.pBufName; m_surfacePool.insert(std::make_pair(surface, info)); #else m_surfacePool.push_back(surface); #endif if (zeroOnAllocate) { ClearResource(&surface->OsResource, param); } return surface; } MOS_STATUS Allocator::DestroyResource(MOS_RESOURCE *resource) { if (nullptr == resource) { return MOS_STATUS_NULL_POINTER; } #if (_DEBUG || _RELEASE_INTERNAL) auto it = m_resourcePool.find(resource); if (it == m_resourcePool.end()) { return MOS_STATUS_SUCCESS; } MOS_Delete(it->second); #else auto it = std::find(m_resourcePool.begin(), m_resourcePool.end(), resource); if (it == m_resourcePool.end()) { return MOS_STATUS_SUCCESS; } #endif m_resourcePool.erase(it); m_osInterface->pfnFreeResource(m_osInterface, resource); MOS_Delete(resource); return MOS_STATUS_SUCCESS; } MOS_STATUS Allocator::DestroyBuffer(MOS_BUFFER *buffer) { if (nullptr == buffer) { return MOS_STATUS_NULL_POINTER; } #if (_DEBUG || _RELEASE_INTERNAL) auto it = m_resourcePool.find(&buffer->OsResource); if (it == m_resourcePool.end()) { return MOS_STATUS_SUCCESS; } MOS_Delete(it->second); #else auto it = std::find(m_resourcePool.begin(), m_resourcePool.end(), &buffer->OsResource); if (it == m_resourcePool.end()) { return MOS_STATUS_SUCCESS; } #endif m_resourcePool.erase(it); m_osInterface->pfnFreeResource(m_osInterface, &buffer->OsResource); MOS_Delete(buffer); return MOS_STATUS_SUCCESS; } MOS_STATUS Allocator::DestroySurface(MOS_SURFACE *surface, MOS_GFXRES_FREE_FLAGS flags) { if (nullptr == surface) { return MOS_STATUS_NULL_POINTER; } #if (_DEBUG || _RELEASE_INTERNAL) auto it = m_surfacePool.find(surface); if (it == m_surfacePool.end()) { return MOS_STATUS_SUCCESS; } MOS_Delete(it->second); #else auto it = std::find(m_surfacePool.begin(), m_surfacePool.end(), surface); if (it == m_surfacePool.end()) { return MOS_STATUS_SUCCESS; } #endif m_surfacePool.erase(it); m_osInterface->pfnFreeResourceWithFlag(m_osInterface, &surface->OsResource, flags.Value); MOS_Delete(surface); return MOS_STATUS_SUCCESS; } MOS_STATUS Allocator::AllocateResource(MOS_RESOURCE *res, MOS_ALLOC_GFXRES_PARAMS ¶m) { if (nullptr == m_osInterface || nullptr == res) { return MOS_STATUS_NULL_POINTER; } memset(res, 0, sizeof(MOS_RESOURCE)); MOS_STATUS status = m_osInterface->pfnAllocateResource(m_osInterface, ¶m, res); return status; } MOS_STATUS Allocator::FreeResource(MOS_RESOURCE *res) { if (nullptr == m_osInterface) { return MOS_STATUS_NULL_POINTER; } m_osInterface->pfnFreeResource(m_osInterface, res); return MOS_STATUS_SUCCESS; } MOS_STATUS Allocator::ClearResource(MOS_RESOURCE *resource, MOS_ALLOC_GFXRES_PARAMS ¶m) { MOS_LOCK_PARAMS lockFlag; memset(&lockFlag, 0, sizeof(lockFlag)); lockFlag.WriteOnly = true; uint8_t *data = (uint8_t *)m_osInterface->pfnLockResource(m_osInterface, resource, &lockFlag); if (data == 0) { return MOS_STATUS_NULL_POINTER; } if (param.Format == Format_Buffer) { memset(data, 0, param.dwBytes); } else if (param.Format == Format_Buffer_2D) { memset(data, 0, param.dwHeight * param.dwWidth); } else if (param.Format == Format_NV12) { memset(data, 0, param.dwHeight * param.dwWidth); } else { m_osInterface->pfnUnlockResource(m_osInterface, resource); return MOS_STATUS_INVALID_PARAMETER; } m_osInterface->pfnUnlockResource(m_osInterface, resource); return MOS_STATUS_SUCCESS; } void* Allocator::Lock(MOS_RESOURCE* resource, MOS_LOCK_PARAMS* lockFlag) { if (nullptr == resource || nullptr == lockFlag) { return nullptr; } return (m_osInterface->pfnLockResource(m_osInterface, resource, lockFlag)); } MOS_STATUS Allocator::UnLock(MOS_RESOURCE* resource) { if (nullptr == resource) { return MOS_STATUS_INVALID_PARAMETER; } return (m_osInterface->pfnUnlockResource(m_osInterface, resource)); } MOS_STATUS Allocator::SkipResourceSync(MOS_RESOURCE* resource) { if (nullptr == resource) { return MOS_STATUS_INVALID_PARAMETER; } return (m_osInterface->pfnSkipResourceSync(resource)); } MOS_STATUS Allocator::GetSurfaceInfo(PMOS_RESOURCE osResource, PMOS_SURFACE resDetails) { return m_osInterface->pfnGetResourceInfo(m_osInterface, osResource, resDetails); } MOS_STATUS Allocator::OsFillResource(PMOS_RESOURCE osResource, uint32_t size, uint8_t value) { return m_osInterface->pfnFillResource(m_osInterface, osResource, size, value); } MOS_STATUS Allocator::SyncOnResource( PMOS_RESOURCE osResource, bool bWriteOperation) { MOS_GPU_CONTEXT requestorGPUCtx = m_osInterface->pfnGetGpuContext(m_osInterface); m_osInterface->pfnSyncOnResource(m_osInterface, osResource, requestorGPUCtx, bWriteOperation); return MOS_STATUS_SUCCESS; } MOS_STATUS Allocator::UpdateResourceUsageType( PMOS_RESOURCE osResource, MOS_HW_RESOURCE_DEF resUsageType) { if (nullptr == osResource) { return MOS_STATUS_INVALID_PARAMETER; } return m_osInterface->pfnUpdateResourceUsageType(osResource, resUsageType); } bool Allocator::isSyncFreeNeededForMMCSurface(PMOS_SURFACE pOsSurface) { if (nullptr == pOsSurface) { return false; } //Compressed surface aux table update is after resource dealloction, aux table update need wait the WLs complete //the sync deallocation flag will make sure deallocation API return after all surface related WL been completed and resource been destroyed by OS auto *pSkuTable = m_osInterface->pfnGetSkuTable(m_osInterface); if (pSkuTable && MEDIA_IS_SKU(pSkuTable, FtrE2ECompression) && //Compression enabled platform !MEDIA_IS_SKU(pSkuTable, FtrFlatPhysCCS) && //NOT DGPU compression ((pOsSurface->bCompressible) && (pOsSurface->CompressionMode != MOS_MMC_DISABLED))) //Compressed enabled surface { return true; } return false; }