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 ¶m, 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, ¶m, 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 ¶m, 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, ¶m, &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 ¶m, 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, ¶m, &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 ¶m)
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, ¶m, 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 ¶m)
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