| /* |
| * 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 resouce manage |
| //! \details Media allocator will allocate and destory buffers, the caller |
| //! can use directly |
| //! |
| #include <algorithm> |
| #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<MOS_RESOURCE *>(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<MOS_SURFACE *>(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); |
| 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); |
| 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); |
| 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); |
| 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; |
| } |