1 /*
2 * Copyright (c) 2018, Intel Corporation
3 *
4 * Permission is hereby granted, free of charge, to any person obtaining a
5 * copy of this software and associated documentation files (the "Software"),
6 * to deal in the Software without restriction, including without limitation
7 * the rights to use, copy, modify, merge, publish, distribute, sublicense,
8 * and/or sell copies of the Software, and to permit persons to whom the
9 * Software is furnished to do so, subject to the following conditions:
10 *
11 * The above copyright notice and this permission notice shall be included
12 * in all copies or substantial portions of the Software.
13 *
14 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
15 * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
16 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
17 * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR
18 * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
19 * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
20 * OTHER DEALINGS IN THE SOFTWARE.
21 */
22 //!
23 //! \file     media_allocator.cpp
24 //! \brief    Defines the common interface for media resource manage
25 //! \details  Media allocator will allocate and destory buffers, the caller
26 //!           can use directly
27 //!
28 #include <algorithm>
29 #include "media_allocator.h"
30 
Allocator(PMOS_INTERFACE osInterface)31 Allocator::Allocator(PMOS_INTERFACE osInterface) : m_osInterface(osInterface)
32 {
33 
34 }
35 
~Allocator()36 Allocator::~Allocator()
37 {
38     DestroyAllResources();
39 }
40 
DestroyAllResources()41 MOS_STATUS Allocator::DestroyAllResources()
42 {
43 #if (_DEBUG || _RELEASE_INTERNAL)
44     for (auto it : m_resourcePool)
45     {
46         MOS_RESOURCE *resource = const_cast<MOS_RESOURCE *>(it.first);
47         m_osInterface->pfnFreeResource(m_osInterface, resource);
48         MOS_Delete(resource);
49         MOS_Delete(it.second);
50     }
51 
52     m_resourcePool.clear();
53 
54     for (auto it : m_surfacePool)
55     {
56         MOS_SURFACE *surface = const_cast<MOS_SURFACE *>(it.first);
57         if (surface)
58         {
59             m_osInterface->pfnFreeResource(m_osInterface, &(surface->OsResource));
60         }
61         MOS_Delete(surface);
62         MOS_Delete(it.second);
63     }
64 
65     m_surfacePool.clear();
66 #else
67 
68     for (auto it : m_resourcePool)
69     {
70         m_osInterface->pfnFreeResource(m_osInterface, it);
71         MOS_Delete(it);
72     }
73     m_resourcePool.clear();
74 
75     for (auto it : m_surfacePool)
76     {
77         m_osInterface->pfnFreeResource(m_osInterface, &it->OsResource);
78         MOS_Delete(it);
79     }
80     m_surfacePool.clear();
81 
82 #endif
83     return MOS_STATUS_SUCCESS;
84 }
85 
AllocateResource(MOS_ALLOC_GFXRES_PARAMS & param,bool zeroOnAllocate,MOS_COMPONENT component)86 MOS_RESOURCE *Allocator::AllocateResource(MOS_ALLOC_GFXRES_PARAMS &param, bool zeroOnAllocate, MOS_COMPONENT component)
87 {
88     if (nullptr == m_osInterface)
89     {
90         return nullptr;
91     }
92 
93     MOS_RESOURCE *resource = MOS_New(MOS_RESOURCE);
94     memset(resource, 0, sizeof(MOS_RESOURCE));
95     MOS_STATUS status = m_osInterface->pfnAllocateResource(m_osInterface, &param, resource);
96 
97     if (status != MOS_STATUS_SUCCESS)
98     {
99         MOS_Delete(resource);
100         return nullptr;
101     }
102 
103 #if (_DEBUG || _RELEASE_INTERNAL)
104     TraceInfo *info = MOS_New(TraceInfo);
105     if (nullptr == info)
106     {
107         FreeResource(resource);
108         MOS_Delete(resource);
109         return nullptr;
110     }
111     info->component = component;
112     //Note, param.pBufName cannot be null.
113     //This assignment statement will calcualte the string length and copy param.pBufName to info->name.
114     //If param.pBufName is null, exception happens when to calculate the string length.
115     MOS_OS_ASSERT(param.pBufName != nullptr);
116     info->name     = param.pBufName;
117 
118     m_resourcePool.insert(std::make_pair(resource, info));
119 #else
120     m_resourcePool.push_back(resource);
121 #endif
122 
123     if (zeroOnAllocate)
124     {
125         ClearResource(resource, param);
126     }
127     return resource;
128 }
129 
AllocateBuffer(MOS_ALLOC_GFXRES_PARAMS & param,bool zeroOnAllocate,MOS_COMPONENT component)130 PMOS_BUFFER Allocator::AllocateBuffer(MOS_ALLOC_GFXRES_PARAMS &param, bool zeroOnAllocate, MOS_COMPONENT component)
131 {
132     if (nullptr == m_osInterface)
133     {
134         return nullptr;
135     }
136 
137     MOS_BUFFER *buffer = MOS_New(MOS_BUFFER);
138     if (nullptr == buffer)
139     {
140         return nullptr;
141     }
142 
143     memset(buffer, 0, sizeof(MOS_BUFFER));
144     MOS_STATUS status = m_osInterface->pfnAllocateResource(m_osInterface, &param, &buffer->OsResource);
145 
146     if (status != MOS_STATUS_SUCCESS)
147     {
148         MOS_Delete(buffer);
149         return nullptr;
150     }
151 
152 #if (_DEBUG || _RELEASE_INTERNAL)
153     TraceInfo *info = MOS_New(TraceInfo);
154     if (nullptr == info)
155     {
156         FreeResource(&buffer->OsResource);
157         MOS_Delete(buffer);
158         return nullptr;
159     }
160 
161     info->component = component;
162     //Note, param.pBufName cannot be null.
163     //This assignment statement will calcualte the string length and copy param.pBufName to info->name.
164     //If param.pBufName is null, exception happens when to calculate the string length.
165     MOS_OS_ASSERT(param.pBufName != nullptr);
166     info->name     = param.pBufName;
167 
168     m_resourcePool.insert(std::make_pair(&buffer->OsResource, info));
169 #else
170     m_resourcePool.push_back(&buffer->OsResource);
171 #endif
172 
173     if (zeroOnAllocate)
174     {
175         ClearResource(&buffer->OsResource, param);
176     }
177     return buffer;
178 }
179 
AllocateSurface(MOS_ALLOC_GFXRES_PARAMS & param,bool zeroOnAllocate,MOS_COMPONENT component)180 MOS_SURFACE *Allocator::AllocateSurface(MOS_ALLOC_GFXRES_PARAMS &param, bool zeroOnAllocate, MOS_COMPONENT component)
181 {
182     MOS_SURFACE *surface = MOS_New(MOS_SURFACE);
183     if (nullptr == surface)
184     {
185         return nullptr;
186     }
187     MOS_STATUS status = m_osInterface->pfnAllocateResource(m_osInterface, &param, &surface->OsResource);
188 
189     m_osInterface->pfnGetResourceInfo(m_osInterface, &surface->OsResource, surface);
190 #if (_DEBUG || _RELEASE_INTERNAL)
191     TraceInfo *info = MOS_New(TraceInfo);
192     if (nullptr == info)
193     {
194         FreeResource(&surface->OsResource);
195         MOS_Delete(surface);
196         return nullptr;
197     }
198     info->component = component;
199     MOS_OS_ASSERT(param.pBufName != nullptr);
200     info->name      = param.pBufName;
201 
202     m_surfacePool.insert(std::make_pair(surface, info));
203 #else
204     m_surfacePool.push_back(surface);
205 #endif
206 
207     if (zeroOnAllocate)
208     {
209         ClearResource(&surface->OsResource, param);
210     }
211     return surface;
212 }
213 
DestroyResource(MOS_RESOURCE * resource)214 MOS_STATUS Allocator::DestroyResource(MOS_RESOURCE *resource)
215 {
216     if (nullptr == resource)
217     {
218         return MOS_STATUS_NULL_POINTER;
219     }
220 #if (_DEBUG || _RELEASE_INTERNAL)
221     auto it = m_resourcePool.find(resource);
222     if (it == m_resourcePool.end())
223     {
224         return MOS_STATUS_SUCCESS;
225     }
226 
227     MOS_Delete(it->second);
228 #else
229     auto it = std::find(m_resourcePool.begin(), m_resourcePool.end(), resource);
230     if (it == m_resourcePool.end())
231     {
232         return MOS_STATUS_SUCCESS;
233     }
234 #endif
235 
236     m_resourcePool.erase(it);
237     m_osInterface->pfnFreeResource(m_osInterface, resource);
238     MOS_Delete(resource);
239 
240     return MOS_STATUS_SUCCESS;
241 }
242 
DestroyBuffer(MOS_BUFFER * buffer)243 MOS_STATUS Allocator::DestroyBuffer(MOS_BUFFER *buffer)
244 {
245     if (nullptr == buffer)
246     {
247         return MOS_STATUS_NULL_POINTER;
248     }
249 #if (_DEBUG || _RELEASE_INTERNAL)
250     auto it = m_resourcePool.find(&buffer->OsResource);
251     if (it == m_resourcePool.end())
252     {
253         return MOS_STATUS_SUCCESS;
254     }
255 
256     MOS_Delete(it->second);
257 #else
258     auto it = std::find(m_resourcePool.begin(), m_resourcePool.end(), &buffer->OsResource);
259     if (it == m_resourcePool.end())
260     {
261         return MOS_STATUS_SUCCESS;
262     }
263 #endif
264 
265     m_resourcePool.erase(it);
266     m_osInterface->pfnFreeResource(m_osInterface, &buffer->OsResource);
267     MOS_Delete(buffer);
268 
269     return MOS_STATUS_SUCCESS;
270 }
271 
DestroySurface(MOS_SURFACE * surface,MOS_GFXRES_FREE_FLAGS flags)272 MOS_STATUS Allocator::DestroySurface(MOS_SURFACE *surface, MOS_GFXRES_FREE_FLAGS flags)
273 {
274     if (nullptr == surface)
275     {
276         return MOS_STATUS_NULL_POINTER;
277     }
278 #if (_DEBUG || _RELEASE_INTERNAL)
279     auto it = m_surfacePool.find(surface);
280     if (it == m_surfacePool.end())
281     {
282         return MOS_STATUS_SUCCESS;
283     }
284 
285     MOS_Delete(it->second);
286 #else
287     auto it = std::find(m_surfacePool.begin(), m_surfacePool.end(), surface);
288     if (it == m_surfacePool.end())
289     {
290         return MOS_STATUS_SUCCESS;
291     }
292 #endif
293 
294     m_surfacePool.erase(it);
295     m_osInterface->pfnFreeResourceWithFlag(m_osInterface, &surface->OsResource, flags.Value);
296     MOS_Delete(surface);
297 
298     return MOS_STATUS_SUCCESS;
299 }
300 
AllocateResource(MOS_RESOURCE * res,MOS_ALLOC_GFXRES_PARAMS & param)301 MOS_STATUS Allocator::AllocateResource(MOS_RESOURCE *res, MOS_ALLOC_GFXRES_PARAMS &param)
302 {
303     if (nullptr == m_osInterface || nullptr == res)
304     {
305         return MOS_STATUS_NULL_POINTER;
306     }
307 
308     memset(res, 0, sizeof(MOS_RESOURCE));
309     MOS_STATUS status = m_osInterface->pfnAllocateResource(m_osInterface, &param, res);
310 
311     return status;
312 }
313 
FreeResource(MOS_RESOURCE * res)314 MOS_STATUS Allocator::FreeResource(MOS_RESOURCE *res)
315 {
316     if (nullptr == m_osInterface)
317     {
318         return MOS_STATUS_NULL_POINTER;
319     }
320 
321     m_osInterface->pfnFreeResource(m_osInterface, res);
322 
323     return MOS_STATUS_SUCCESS;
324 }
325 
ClearResource(MOS_RESOURCE * resource,MOS_ALLOC_GFXRES_PARAMS & param)326 MOS_STATUS Allocator::ClearResource(MOS_RESOURCE *resource, MOS_ALLOC_GFXRES_PARAMS &param)
327 {
328     MOS_LOCK_PARAMS lockFlag;
329     memset(&lockFlag, 0, sizeof(lockFlag));
330     lockFlag.WriteOnly = true;
331 
332     uint8_t *data = (uint8_t *)m_osInterface->pfnLockResource(m_osInterface, resource, &lockFlag);
333     if (data == 0)
334     {
335         return MOS_STATUS_NULL_POINTER;
336     }
337 
338     if (param.Format == Format_Buffer)
339     {
340         memset(data, 0, param.dwBytes);
341     }
342     else if (param.Format == Format_Buffer_2D)
343     {
344         memset(data, 0, param.dwHeight * param.dwWidth);
345     }
346     else if (param.Format == Format_NV12)
347     {
348         memset(data, 0, param.dwHeight * param.dwWidth);
349     }
350     else
351     {
352         m_osInterface->pfnUnlockResource(m_osInterface, resource);
353         return MOS_STATUS_INVALID_PARAMETER;
354     }
355 
356     m_osInterface->pfnUnlockResource(m_osInterface, resource);
357 
358     return MOS_STATUS_SUCCESS;
359 }
360 
Lock(MOS_RESOURCE * resource,MOS_LOCK_PARAMS * lockFlag)361 void* Allocator::Lock(MOS_RESOURCE* resource, MOS_LOCK_PARAMS* lockFlag)
362 {
363     if (nullptr == resource || nullptr == lockFlag)
364     {
365         return nullptr;
366     }
367 
368     return (m_osInterface->pfnLockResource(m_osInterface, resource, lockFlag));
369 }
370 
UnLock(MOS_RESOURCE * resource)371 MOS_STATUS Allocator::UnLock(MOS_RESOURCE* resource)
372 {
373     if (nullptr == resource)
374     {
375         return MOS_STATUS_INVALID_PARAMETER;
376     }
377 
378     return (m_osInterface->pfnUnlockResource(m_osInterface, resource));
379 }
380 
SkipResourceSync(MOS_RESOURCE * resource)381 MOS_STATUS Allocator::SkipResourceSync(MOS_RESOURCE* resource)
382 {
383     if (nullptr == resource)
384     {
385         return MOS_STATUS_INVALID_PARAMETER;
386     }
387 
388     return (m_osInterface->pfnSkipResourceSync(resource));
389 }
390 
GetSurfaceInfo(PMOS_RESOURCE osResource,PMOS_SURFACE resDetails)391 MOS_STATUS Allocator::GetSurfaceInfo(PMOS_RESOURCE osResource, PMOS_SURFACE resDetails)
392 {
393     return m_osInterface->pfnGetResourceInfo(m_osInterface, osResource, resDetails);
394 }
395 
OsFillResource(PMOS_RESOURCE osResource,uint32_t size,uint8_t value)396 MOS_STATUS Allocator::OsFillResource(PMOS_RESOURCE osResource, uint32_t size, uint8_t value)
397 {
398     return m_osInterface->pfnFillResource(m_osInterface, osResource, size, value);
399 }
400 
SyncOnResource(PMOS_RESOURCE osResource,bool bWriteOperation)401 MOS_STATUS Allocator::SyncOnResource(
402     PMOS_RESOURCE         osResource,
403     bool                  bWriteOperation)
404 {
405     MOS_GPU_CONTEXT requestorGPUCtx = m_osInterface->pfnGetGpuContext(m_osInterface);
406     m_osInterface->pfnSyncOnResource(m_osInterface, osResource, requestorGPUCtx, bWriteOperation);
407     return MOS_STATUS_SUCCESS;
408 }
409 
UpdateResourceUsageType(PMOS_RESOURCE osResource,MOS_HW_RESOURCE_DEF resUsageType)410 MOS_STATUS Allocator::UpdateResourceUsageType(
411     PMOS_RESOURCE           osResource,
412     MOS_HW_RESOURCE_DEF     resUsageType)
413 {
414     if (nullptr == osResource)
415     {
416         return MOS_STATUS_INVALID_PARAMETER;
417     }
418 
419     return m_osInterface->pfnUpdateResourceUsageType(osResource, resUsageType);
420 }
421 
isSyncFreeNeededForMMCSurface(PMOS_SURFACE pOsSurface)422 bool Allocator::isSyncFreeNeededForMMCSurface(PMOS_SURFACE pOsSurface)
423 {
424     if (nullptr == pOsSurface)
425     {
426         return false;
427     }
428 
429     //Compressed surface aux table update is after resource dealloction, aux table update need wait the WLs complete
430     //the sync deallocation flag will make sure deallocation API return after all surface related WL been completed and resource been destroyed by OS
431     auto *pSkuTable = m_osInterface->pfnGetSkuTable(m_osInterface);
432     if (pSkuTable &&
433         MEDIA_IS_SKU(pSkuTable, FtrE2ECompression) &&                                        //Compression enabled platform
434         !MEDIA_IS_SKU(pSkuTable, FtrFlatPhysCCS) &&                                          //NOT DGPU compression
435         ((pOsSurface->bCompressible) && (pOsSurface->CompressionMode != MOS_MMC_DISABLED)))  //Compressed enabled surface
436     {
437         return true;
438     }
439 
440     return false;
441 }
442