1 /*
2 * Copyright (c) 2019-2022, 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     mos_graphicsresource_specific_next.cpp
24 //! \brief   Container class for the linux/Android specfic graphic resource
25 //!
26 
27 #include "mos_defs.h"
28 #include "mos_util_debug.h"
29 
30 #include "mos_graphicsresource_specific_next.h"
31 #include "mos_context_specific_next.h"
32 #include "memory_policy_manager.h"
33 
GraphicsResourceSpecificNext()34 GraphicsResourceSpecificNext::GraphicsResourceSpecificNext()
35 {
36     MOS_OS_FUNCTION_ENTER;
37 }
38 
~GraphicsResourceSpecificNext()39 GraphicsResourceSpecificNext::~GraphicsResourceSpecificNext()
40 {
41     MOS_OS_FUNCTION_ENTER;
42 }
43 
ResourceIsNull()44 bool GraphicsResourceSpecificNext::ResourceIsNull()
45 {
46     return ((m_bo == nullptr)
47 #if (_DEBUG || _RELEASE_INTERNAL)
48          && ((m_pData == nullptr) )
49 #endif // (_DEBUG || _RELEASE_INTERNAL)
50     );
51 
52 }
53 
Allocate(OsContextNext * osContextPtr,CreateParams & params)54 MOS_STATUS GraphicsResourceSpecificNext::Allocate(OsContextNext* osContextPtr, CreateParams& params)
55 {
56     MOS_OS_FUNCTION_ENTER;
57 
58     if (osContextPtr == nullptr)
59     {
60         MOS_OS_ASSERTMESSAGE("Unable to get the active OS context.");
61         return MOS_STATUS_INVALID_HANDLE;
62     }
63 
64     if (osContextPtr->GetOsContextValid() == false)
65     {
66         MOS_OS_ASSERTMESSAGE("The OS context got is not valid.");
67         return MOS_STATUS_INVALID_HANDLE;
68     }
69 
70     OsContextSpecificNext *pOsContextSpecific = static_cast<OsContextSpecificNext *>(osContextPtr);
71 
72     GMM_CLIENT_CONTEXT    *gmmClientContext = pOsContextSpecific->GetGmmClientContext();
73     if (nullptr == gmmClientContext)
74     {
75         MOS_OS_ASSERTMESSAGE("Get GMM Client Context failed.");
76         return MOS_STATUS_INVALID_HANDLE;
77     }
78 
79     MOS_STATUS         status          = MOS_STATUS_SUCCESS;
80     uint32_t           tileFormatLinux = TILING_NONE;
81     uint32_t           alignedHeight   = params.m_height;
82     uint32_t           bufHeight       = params.m_height;
83     GMM_RESOURCE_TYPE  resourceType    = RESOURCE_2D;
84     int32_t            mem_type        = MOS_MEMPOOL_VIDEOMEMORY;
85 
86     GMM_RESCREATE_PARAMS    gmmParams;
87     MosUtilities::MosZeroMemory(&gmmParams, sizeof(gmmParams));
88 
89     gmmParams.Usage   = params.m_gmmResUsageType;
90 
91     switch (params.m_type)
92     {
93         case MOS_GFXRES_BUFFER:
94         case MOS_GFXRES_SCRATCH:
95           gmmParams.Type = RESOURCE_BUFFER;
96           gmmParams.Flags.Gpu.State = true;
97           alignedHeight = 1;
98           break;
99 
100         case MOS_GFXRES_2D:
101             gmmParams.Type = RESOURCE_2D;
102             gmmParams.Flags.Gpu.Video = true;
103             break;
104 
105         case MOS_GFXRES_VOLUME:
106             gmmParams.Type = RESOURCE_3D;
107             gmmParams.Flags.Gpu.Video = true;
108             gmmParams.Depth = params.m_depth;
109             break;
110 
111         default:
112             MOS_OS_ASSERTMESSAGE("Unknown surface type");
113             return MOS_STATUS_UNKNOWN;
114     }
115 
116     // Create GmmResourceInfo
117     gmmParams.Format = MosInterface::MosFmtToGmmFmt(params.m_format);
118     if (gmmParams.Format == GMM_FORMAT_INVALID)
119     {
120         MOS_OS_ASSERTMESSAGE("Unsupported format");
121         return MOS_STATUS_UNIMPLEMENTED;
122     }
123     gmmParams.BaseWidth = params.m_width;
124     gmmParams.BaseHeight = alignedHeight;
125     gmmParams.ArraySize = 1;
126 
127     MOS_TILE_TYPE tileformat = params.m_tileType;
128     MOS_OS_NORMALMESSAGE("tilemode: tileformat = %d for %s, tileModeByForce = %d", tileformat, params.m_name.c_str(), params.m_tileModeByForce);
129     switch (tileformat)
130     {
131         case MOS_TILE_Y:
132             tileFormatLinux               = TILING_Y;
133             if (params.m_isCompressible                                            &&
134                 MEDIA_IS_SKU(pOsContextSpecific->GetSkuTable(), FtrE2ECompression) &&
135                 MEDIA_IS_SKU(pOsContextSpecific->GetSkuTable(), FtrCompressibleSurfaceDefault))
136             {
137                 gmmParams.Flags.Gpu.MMC  = 1;
138 
139                 if (params.m_compressionMode == MOS_MMC_RC)
140                 {
141                     gmmParams.Flags.Info.MediaCompressed = 0;
142                     gmmParams.Flags.Info.RenderCompressed = 1;
143                 }
144                 else
145                 {
146                     gmmParams.Flags.Info.MediaCompressed = 1;
147                     gmmParams.Flags.Info.RenderCompressed = 0;
148                 }
149 
150                 gmmParams.Flags.Gpu.CCS = 1;
151                 gmmParams.Flags.Gpu.UnifiedAuxSurface = 1;
152                 gmmParams.Flags.Gpu.RenderTarget = 1;
153 
154                 if(MEDIA_IS_SKU(pOsContextSpecific->GetSkuTable(), FtrFlatPhysCCS))
155                 {
156                     gmmParams.Flags.Gpu.UnifiedAuxSurface = 0;
157                 }
158             }
159             SetTileModebyForce(gmmParams, params.m_tileModeByForce);
160             break;
161         case MOS_TILE_X:
162             gmmParams.Flags.Info.TiledX   = true;
163             tileFormatLinux               = TILING_X;
164             break;
165         default:
166             gmmParams.Flags.Info.Linear   = true;
167             tileFormatLinux               = TILING_NONE;
168     }
169 
170     if (nullptr != params.m_pSystemMemory)
171     {
172         // If user provides a system memory pointer, the gfx resource is backed
173         // by the system memory pages. The resource is required to be linear.
174         gmmParams.Flags.Info.Linear     = true;
175         gmmParams.Flags.Info.Cacheable  = true;
176         gmmParams.NoGfxMemory           = true;
177         GMM_RESOURCE_INFO *tmpGmmResInfoPtr = pOsContextSpecific
178                 ->GetGmmClientContext()->CreateResInfoObject(&gmmParams);
179         if (tmpGmmResInfoPtr == nullptr)
180         {
181             MOS_OS_ASSERTMESSAGE("Create GmmResInfo failed");
182             return MOS_STATUS_UNKNOWN;
183         }
184 
185         gmmParams.ExistingSysMemSize = GFX_ULONG_CAST(tmpGmmResInfoPtr->GetSizeSurface());
186         gmmParams.pExistingSysMem = (GMM_VOIDPTR64)params.m_pSystemMemory;
187         gmmParams.NoGfxMemory = false;
188         gmmParams.Flags.Info.ExistingSysMem = true;
189 
190         pOsContextSpecific->GetGmmClientContext()
191                 ->DestroyResInfoObject(tmpGmmResInfoPtr);
192     }
193     else
194     {
195         gmmParams.Flags.Info.LocalOnly = MEDIA_IS_SKU(pOsContextSpecific->GetSkuTable(), FtrLocalMemory);
196     }
197 
198     GMM_RESOURCE_INFO*  gmmResourceInfoPtr = pOsContextSpecific->GetGmmClientContext()->CreateResInfoObject(&gmmParams);
199 
200     if (gmmResourceInfoPtr == nullptr)
201     {
202         MOS_OS_ASSERTMESSAGE("Get gmmResourceInfoPtr failed.");
203         return MOS_STATUS_INVALID_PARAMETER;
204     }
205 
206     switch (gmmResourceInfoPtr->GetTileType())
207     {
208         case GMM_TILED_X:
209             tileformat      = MOS_TILE_X;
210             tileFormatLinux = TILING_X;
211             break;
212         case GMM_TILED_Y:
213             tileformat      = MOS_TILE_Y;
214             tileFormatLinux = TILING_Y;
215             break;
216         case GMM_NOT_TILED:
217             tileformat      = MOS_TILE_LINEAR;
218             tileFormatLinux = TILING_NONE;
219             break;
220         default:
221             tileformat      = MOS_TILE_Y;
222             tileFormatLinux = TILING_Y;
223             break;
224     }
225 
226     if (params.m_tileType== MOS_TILE_Y)
227     {
228         gmmResourceInfoPtr->SetMmcMode((GMM_RESOURCE_MMC_INFO)params.m_compressionMode, 0);
229     }
230 
231     if(!params.m_pSystemMemory)
232     {
233         MemoryPolicyParameter memPolicyPar;
234         MOS_ZeroMemory(&memPolicyPar, sizeof(MemoryPolicyParameter));
235 
236         memPolicyPar.skuTable         = pOsContextSpecific->GetSkuTable();
237         memPolicyPar.waTable          = pOsContextSpecific->GetWaTable();
238         memPolicyPar.resInfo          = gmmResourceInfoPtr;
239         memPolicyPar.resName          = params.m_name.c_str();
240         memPolicyPar.preferredMemType = params.m_memType;
241         memPolicyPar.isServer         = PLATFORM_INFORMATION_IS_SERVER & mos_get_platform_information(pOsContextSpecific->GetBufMgr());
242 
243         mem_type = MemoryPolicyManager::UpdateMemoryPolicy(&memPolicyPar);
244     }
245 
246     uint32_t bufPitch        = GFX_ULONG_CAST(gmmResourceInfoPtr->GetRenderPitch());
247     uint32_t bufSize         = GFX_ULONG_CAST(gmmResourceInfoPtr->GetSizeSurface());
248     bufHeight                = gmmResourceInfoPtr->GetBaseHeight();
249     MOS_LINUX_BO* boPtr      = nullptr;
250 
251     char bufName[m_maxBufNameLength];
252     MosUtilities::MosSecureStrcpy(bufName, m_maxBufNameLength, params.m_name.c_str());
253 
254     unsigned int patIndex = MosInterface::GetPATIndexFromGmm(gmmClientContext, gmmResourceInfoPtr);
255     bool isCpuCacheable   = gmmResourceInfoPtr->GetResFlags().Info.Cacheable;
256 
257     MOS_TraceEventExt(EVENT_RESOURCE_ALLOCATE, EVENT_TYPE_START, nullptr, 0, nullptr, 0);
258     if (nullptr != params.m_pSystemMemory)
259     {
260         struct mos_drm_bo_alloc_userptr alloc_uptr;
261         alloc_uptr.name = bufName;
262         alloc_uptr.addr = params.m_pSystemMemory;
263         alloc_uptr.tiling_mode = tileFormatLinux;
264         alloc_uptr.stride = bufPitch;
265         alloc_uptr.size = bufSize;
266         alloc_uptr.pat_index = patIndex;
267 
268         boPtr = mos_bo_alloc_userptr(pOsContextSpecific->m_bufmgr, &alloc_uptr);
269     }
270     // Only Linear and Y TILE supported
271     else if (tileFormatLinux == TILING_NONE)
272     {
273         struct mos_drm_bo_alloc alloc;
274         alloc.name = bufName;
275         alloc.size = bufSize;
276         alloc.alignment = 4096;
277         alloc.ext.mem_type = mem_type;
278         alloc.ext.pat_index = patIndex;
279         alloc.ext.cpu_cacheable = isCpuCacheable;
280         boPtr = mos_bo_alloc(pOsContextSpecific->m_bufmgr, &alloc);
281     }
282     else
283     {
284         struct mos_drm_bo_alloc_tiled alloc_tiled;
285         alloc_tiled.name = bufName;
286         alloc_tiled.x = bufPitch;
287         alloc_tiled.y = bufSize/bufPitch;
288         alloc_tiled.cpp = 1;
289         alloc_tiled.ext.tiling_mode = tileFormatLinux;
290         alloc_tiled.ext.mem_type = mem_type;
291         alloc_tiled.ext.pat_index = patIndex;
292         alloc_tiled.ext.cpu_cacheable = isCpuCacheable;
293 
294         boPtr = mos_bo_alloc_tiled(pOsContextSpecific->m_bufmgr, &alloc_tiled);
295         bufPitch = (uint32_t)alloc_tiled.pitch;
296     }
297 
298     m_mapped = false;
299     if (boPtr)
300     {
301         m_format   = params.m_format;
302         m_width    = params.m_width;
303         m_height   = bufHeight;
304         m_pitch    = bufPitch;
305         m_count    = 0;
306         m_bo       = boPtr;
307         m_name     = params.m_name;
308         m_pData    = (uint8_t*) boPtr->virt;
309 
310         m_gmmResInfo    = gmmResourceInfoPtr;
311         m_mapped        = false;
312         m_mmapOperation = MOS_MMAP_OPERATION_NONE;
313 
314         m_arraySize = 1;
315         m_depth     = MOS_MAX(1, gmmResourceInfoPtr->GetBaseDepth());
316         m_size      = (uint32_t)gmmResourceInfoPtr->GetSizeSurface();
317         m_tileType  = tileformat;
318         m_tileModeGMM           = (MOS_TILE_MODE_GMM)gmmResourceInfoPtr->GetTileModeSurfaceState();
319         m_isGMMTileEnabled      = true;
320 
321         m_compressible    = gmmParams.Flags.Gpu.MMC ?
322             (gmmResourceInfoPtr->GetMmcHint(0) == GMM_MMC_HINT_ON) : false;
323         m_isCompressed    = gmmResourceInfoPtr->IsMediaMemoryCompressed(0);
324         m_compressionMode = (MOS_RESOURCE_MMC_MODE)gmmResourceInfoPtr->GetMmcMode(0);
325         m_memObjCtrlState = MosInterface::GetCachePolicyMemoryObject(pOsContextSpecific->GetGmmClientContext(), params.m_mocsMosResUsageType);
326 
327         MOS_OS_VERBOSEMESSAGE("Alloc %7d bytes (%d x %d resource), tile encoding %d.", bufSize, params.m_width, bufHeight, m_tileModeGMM);
328 
329         struct {
330             uint32_t m_handle;
331             uint32_t m_resFormat;
332             uint32_t m_baseWidth;
333             uint32_t m_baseHeight;
334             uint32_t m_pitch;
335             uint32_t m_size;
336             uint32_t m_resTileType;
337             GMM_RESOURCE_FLAG m_resFlag;
338             uint32_t          m_reserve;
339         } eventData;
340 
341         eventData.m_handle       = boPtr->handle;
342         eventData.m_baseWidth    = m_width;
343         eventData.m_baseHeight   = m_height;
344         eventData.m_pitch        = m_pitch;
345         eventData.m_size         = m_size;
346         eventData.m_resFormat    = m_format;
347         eventData.m_resTileType  = m_tileType;
348         eventData.m_resFlag      = gmmResourceInfoPtr->GetResFlags();
349         eventData.m_reserve      = 0;
350         MOS_TraceEventExt(EVENT_RESOURCE_ALLOCATE,
351             EVENT_TYPE_INFO,
352             &eventData,
353             sizeof(eventData),
354             params.m_name.c_str(),
355             params.m_name.size() + 1);
356     }
357     else
358     {
359         MOS_OS_ASSERTMESSAGE("Fail to Alloc %7d bytes (%d x %d resource).",bufSize, params.m_width, params.m_height);
360         status = MOS_STATUS_NO_SPACE;
361     }
362     MOS_TraceEventExt(EVENT_RESOURCE_ALLOCATE, EVENT_TYPE_END, &status, sizeof(status), nullptr, 0);
363 
364     m_memAllocCounterGfx++;
365     return  status;
366 }
367 
Free(OsContextNext * osContextPtr,uint32_t freeFlag)368 void GraphicsResourceSpecificNext::Free(OsContextNext* osContextPtr, uint32_t  freeFlag)
369 {
370     MOS_OS_FUNCTION_ENTER;
371 
372     MOS_UNUSED(osContextPtr);
373     MOS_UNUSED(freeFlag);
374 
375     OsContextSpecificNext *pOsContextSpecific = static_cast<OsContextSpecificNext *>(osContextPtr);
376 
377     MOS_LINUX_BO* boPtr = m_bo;
378 
379     if (boPtr)
380     {
381         AuxTableMgr *auxTableMgr = pOsContextSpecific->GetAuxTableMgr();
382         if (auxTableMgr)
383         {
384             auxTableMgr->UnmapResource(m_gmmResInfo, boPtr);
385         }
386         mos_bo_unreference(boPtr);
387         m_bo = nullptr;
388         if (nullptr != m_gmmResInfo)
389         {
390             pOsContextSpecific->GetGmmClientContext()->DestroyResInfoObject(m_gmmResInfo);
391             m_gmmResInfo = nullptr;
392             m_memAllocCounterGfx--;
393         }
394     }
395     return;
396 }
397 
IsEqual(GraphicsResourceNext * toCompare)398 bool GraphicsResourceSpecificNext::IsEqual(GraphicsResourceNext* toCompare)
399 {
400     if  (toCompare == nullptr)
401     {
402         return false;
403     }
404 
405     GraphicsResourceSpecificNext *resSpecificPtr = static_cast<GraphicsResourceSpecificNext *>(toCompare);
406 
407     return (m_bo == resSpecificPtr->m_bo);
408 }
409 
IsValid()410 bool GraphicsResourceSpecificNext::IsValid()
411 {
412     return (m_bo != nullptr);
413 }
414 
ConvertToMosResource(MOS_RESOURCE * pMosResource)415 MOS_STATUS GraphicsResourceSpecificNext::ConvertToMosResource(MOS_RESOURCE* pMosResource)
416 {
417     if (pMosResource == nullptr)
418     {
419         return MOS_STATUS_INVALID_PARAMETER;
420     }
421 
422     pMosResource->Format   = m_format;
423     pMosResource->iWidth   = m_width;
424     pMosResource->iHeight  = m_height;
425     pMosResource->iSize    = m_size;
426     pMosResource->iPitch   = m_pitch;
427     pMosResource->iDepth   = m_depth;
428     pMosResource->TileType = m_tileType;
429     pMosResource->TileModeGMM = m_tileModeGMM;
430     pMosResource->bGMMTileEnabled = m_isGMMTileEnabled;
431     pMosResource->iCount   = 0;
432     pMosResource->pData    = m_pData;
433     pMosResource->bufname  = m_name.c_str();
434     pMosResource->bo       = m_bo;
435     pMosResource->bMapped  = m_mapped;
436     pMosResource->MmapOperation = m_mmapOperation;
437     pMosResource->pGmmResInfo   = m_gmmResInfo;
438 
439     pMosResource->user_provided_va  = m_userProvidedVA;
440 
441     pMosResource->memObjCtrlState   = m_memObjCtrlState;
442     pMosResource->mocsMosResUsageType = m_mocsMosResUsageType;
443 
444     pMosResource->pGfxResourceNext  = this;
445 
446     return  MOS_STATUS_SUCCESS;
447 }
448 
Lock(OsContextNext * osContextPtr,LockParams & params)449 void* GraphicsResourceSpecificNext::Lock(OsContextNext* osContextPtr, LockParams& params)
450 {
451     MOS_OS_FUNCTION_ENTER;
452 
453     if (osContextPtr == nullptr)
454     {
455         MOS_OS_ASSERTMESSAGE("Unable to get the active OS context.");
456         return nullptr;
457     }
458 
459     if (osContextPtr ->GetOsContextValid() == false)
460     {
461         MOS_OS_ASSERTMESSAGE("The OS context got is not valid.");
462         return nullptr;
463     }
464 
465     OsContextSpecificNext *pOsContextSpecific = static_cast<OsContextSpecificNext *>(osContextPtr);
466 
467     void*   dataPtr     = nullptr;
468     MOS_LINUX_BO* boPtr = m_bo;
469 
470     if (boPtr)
471     {
472         // Do decompression for a compressed surface before lock
473         const auto pGmmResInfo = m_gmmResInfo;
474         MOS_OS_ASSERT(pGmmResInfo);
475         GMM_RESOURCE_FLAG GmmFlags = pGmmResInfo->GetResFlags();
476 
477         if (!params.m_noDecompress &&
478             (((GmmFlags.Gpu.MMC || GmmFlags.Gpu.CCS) && GmmFlags.Info.MediaCompressed) ||
479              pGmmResInfo->IsMediaMemoryCompressed(0)))
480         {
481             MOS_RESOURCE mosResource = {};
482             ConvertToMosResource(&mosResource);
483 
484             MosDecompression *mosDecompression = pOsContextSpecific->GetMosDecompression();
485             if (nullptr == mosDecompression)
486             {
487                 MOS_OS_ASSERTMESSAGE("mosDecompression is NULL.");
488                 return nullptr;
489             }
490             mosDecompression->MemoryDecompress(&mosResource);
491         }
492 
493         if(false == m_mapped)
494         {
495             if (pOsContextSpecific->IsAtomSoc())
496             {
497                 mos_bo_map_gtt(boPtr);
498             }
499             else
500             {
501                 if (m_tileType != MOS_TILE_LINEAR && !params.m_tileAsTiled)
502                 {
503                     if (pOsContextSpecific->UseSwSwizzling())
504                     {
505                         mos_bo_map(boPtr, ( OSKM_LOCKFLAG_WRITEONLY & params.m_writeRequest ));
506                         m_mmapOperation = MOS_MMAP_OPERATION_MMAP;
507                         if (m_systemShadow == nullptr)
508                         {
509                             m_systemShadow = (uint8_t *)MOS_AllocMemory(boPtr->size);
510                             MOS_OS_CHECK_CONDITION((m_systemShadow == nullptr), "Failed to allocate shadow surface", nullptr);
511                         }
512                         if (m_systemShadow)
513                         {
514                             int32_t flags = pOsContextSpecific->GetTileYFlag() ? 0 : 1;
515                             uint64_t surfSize = m_gmmResInfo->GetSizeMainSurface();
516                             MOS_OS_CHECK_CONDITION((m_tileType != MOS_TILE_Y), "Unsupported tile type", nullptr);
517                             MOS_OS_CHECK_CONDITION((boPtr->size <= 0 || m_pitch <= 0), "Invalid BO size or pitch", nullptr);
518                             MosUtilities::MosSwizzleData((uint8_t*)boPtr->virt, m_systemShadow,
519                                             MOS_TILE_Y, MOS_TILE_LINEAR,
520                                             (int32_t)(surfSize / m_pitch), m_pitch, flags);
521                         }
522                     }
523                     else
524                     {
525                         mos_bo_map_gtt(boPtr);
526                         m_mmapOperation = MOS_MMAP_OPERATION_MMAP_GTT;
527                     }
528                 }
529                 else if (params.m_uncached)
530                 {
531                     mos_bo_map_wc(boPtr);
532                     m_mmapOperation = MOS_MMAP_OPERATION_MMAP_WC;
533                 }
534                 else
535                 {
536                     mos_bo_map(boPtr, ( OSKM_LOCKFLAG_WRITEONLY & params.m_writeRequest ));
537                     m_mmapOperation = MOS_MMAP_OPERATION_MMAP;
538                 }
539             }
540             m_mapped = true;
541             m_pData  = m_systemShadow ? m_systemShadow : (uint8_t *)boPtr->virt;
542         }
543 
544         dataPtr = m_pData;
545     }
546 
547     MOS_OS_ASSERT(dataPtr);
548     return dataPtr;
549 }
550 
Unlock(OsContextNext * osContextPtr)551 MOS_STATUS GraphicsResourceSpecificNext::Unlock(OsContextNext* osContextPtr)
552 {
553     MOS_OS_FUNCTION_ENTER;
554 
555     if (osContextPtr == nullptr)
556     {
557         MOS_OS_ASSERTMESSAGE("Unable to get the active OS context.");
558         return MOS_STATUS_INVALID_HANDLE;
559     }
560 
561     if (osContextPtr ->GetOsContextValid() == false)
562     {
563         MOS_OS_ASSERTMESSAGE("The OS context got is not valid.");
564         return MOS_STATUS_INVALID_HANDLE;
565     }
566 
567     OsContextSpecificNext *pOsContextSpecific = static_cast<OsContextSpecificNext *>(osContextPtr);
568 
569     MOS_LINUX_BO* boPtr = m_bo;
570     if (boPtr)
571     {
572         if (m_mapped)
573         {
574            if (pOsContextSpecific->IsAtomSoc())
575            {
576                mos_bo_unmap_gtt(boPtr);
577            }
578            else
579            {
580 
581                if (m_systemShadow)
582                {
583                    int32_t flags = pOsContextSpecific->GetTileYFlag() ? 0 : 1;
584                    uint64_t surfSize = m_gmmResInfo->GetSizeMainSurface();
585                    MosUtilities::MosSwizzleData(m_systemShadow, (uint8_t*)boPtr->virt,
586                                    MOS_TILE_LINEAR, MOS_TILE_Y,
587                                    (int32_t)(surfSize / m_pitch), m_pitch, flags);
588                    MOS_FreeMemory(m_systemShadow);
589                    m_systemShadow = nullptr;
590                }
591 
592                switch(m_mmapOperation)
593                {
594                    case MOS_MMAP_OPERATION_MMAP_GTT:
595                         mos_bo_unmap_gtt(boPtr);
596                         break;
597                    case MOS_MMAP_OPERATION_MMAP_WC:
598                         mos_bo_unmap_wc(boPtr);
599                         break;
600                    case MOS_MMAP_OPERATION_MMAP:
601                         mos_bo_unmap(boPtr);
602                         break;
603                    default:
604                         MOS_OS_ASSERTMESSAGE("Invalid mmap operation type");
605                         break;
606                }
607             }
608 
609             m_mapped           = false;
610             m_mmapOperation    = MOS_MMAP_OPERATION_NONE;
611 
612             boPtr->virt        = nullptr;
613             m_bo = boPtr;
614         }
615 
616         m_pData = nullptr;
617     }
618 
619     return MOS_STATUS_SUCCESS;
620 }
621 
AllocateExternalResource(MOS_STREAM_HANDLE streamState,PMOS_ALLOC_GFXRES_PARAMS params,MOS_RESOURCE_HANDLE & resource)622 MOS_STATUS GraphicsResourceSpecificNext::AllocateExternalResource(
623     MOS_STREAM_HANDLE streamState,
624     PMOS_ALLOC_GFXRES_PARAMS params,
625     MOS_RESOURCE_HANDLE& resource)
626 {
627     MOS_OS_FUNCTION_ENTER;
628 
629     MOS_STATUS eStatus = MOS_STATUS_SUCCESS;
630 
631     MOS_OS_CHK_NULL_RETURN(resource);
632     MOS_OS_CHK_NULL_RETURN(streamState);
633     MOS_OS_CHK_NULL_RETURN(streamState->osDeviceContext);
634 
635     const char *bufname = params->pBufName;;
636     int32_t iSize = 0;
637     int32_t iPitch = 0;
638     MOS_LINUX_BO *bo = nullptr;
639     MOS_TILE_TYPE tileformat = params->TileType;
640     uint32_t tileformat_linux = TILING_NONE;
641     int32_t iHeight = params->dwHeight;
642     int32_t iAlignedHeight = 0;
643     GMM_RESCREATE_PARAMS gmmParams;
644     GMM_RESOURCE_INFO *gmmResourceInfo = nullptr;
645     GMM_RESOURCE_TYPE resourceType = RESOURCE_2D;
646     unsigned int patIndex = PAT_INDEX_INVALID;
647     bool isCpuCacheable = true;
648 
649     MosUtilities::MosZeroMemory(&gmmParams, sizeof(gmmParams));
650 
651     MOS_OS_CHK_NULL_RETURN(streamState->perStreamParameters);
652     auto perStreamParameters = (PMOS_CONTEXT)streamState->perStreamParameters;
653 
654     gmmParams.Usage = MosInterface::GetGmmResourceUsageType(params->ResUsageType);
655 
656     switch (params->Format)
657     {
658     case Format_Buffer:
659     case Format_RAW:
660         resourceType   = RESOURCE_BUFFER;
661         iAlignedHeight = 1;
662         //indicate buffer Restriction is Vertex.
663         gmmParams.Flags.Gpu.State = true;
664         break;
665     case Format_L8:
666     case Format_L16:
667     case Format_STMM:
668     case Format_AI44:
669     case Format_IA44:
670     case Format_R5G6B5:
671     case Format_R8G8B8:
672     case Format_X8R8G8B8:
673     case Format_A8R8G8B8:
674     case Format_X8B8G8R8:
675     case Format_A8B8G8R8:
676     case Format_R32S:
677     case Format_R32F:
678     case Format_V8U8:
679     case Format_YUY2:
680     case Format_UYVY:
681     case Format_P8:
682     case Format_A8:
683     case Format_AYUV:
684     case Format_NV12:
685     case Format_NV21:
686     case Format_YV12:
687     case Format_Buffer_2D:
688     case Format_R32U:
689     case Format_444P:
690     case Format_422H:
691     case Format_422V:
692     case Format_IMC3:
693     case Format_411P:
694     case Format_411R:
695     case Format_RGBP:
696     case Format_BGRP:
697     case Format_R16U:
698     case Format_R8U:
699     case Format_R8UN:
700     case Format_P010:
701     case Format_P016:
702     case Format_Y216:
703     case Format_Y416:
704     case Format_P208:
705     case Format_Y210:
706     case Format_Y410:
707     case Format_R16F:
708         resourceType = RESOURCE_2D;
709         //indicate buffer Restriction is Planar surface restrictions.
710         gmmParams.Flags.Gpu.Video = true;
711         break;
712     default:
713         MOS_OS_ASSERTMESSAGE("Unsupported format");
714         eStatus = MOS_STATUS_UNIMPLEMENTED;
715         return eStatus;
716     }
717 
718     // Create GmmResourceInfo
719     gmmParams.BaseWidth  = params->dwWidth;
720     gmmParams.BaseHeight = iAlignedHeight;
721     gmmParams.ArraySize  = 1;
722     gmmParams.Type       = resourceType;
723     gmmParams.Format     = MosInterface::MosFmtToGmmFmt(params->Format);
724 
725     MOS_OS_CHECK_CONDITION(gmmParams.Format == GMM_FORMAT_INVALID,
726         "Unsupported format",
727         MOS_STATUS_UNKNOWN);
728 
729     switch (tileformat)
730     {
731     case MOS_TILE_Y:
732         gmmParams.Flags.Gpu.MMC = params->bIsCompressible;
733         tileformat_linux        = TILING_Y;
734         break;
735     case MOS_TILE_X:
736         gmmParams.Flags.Info.TiledX = true;
737         tileformat_linux            = TILING_X;
738         break;
739     default:
740         gmmParams.Flags.Info.Linear = true;
741         tileformat_linux            = TILING_NONE;
742     }
743     gmmParams.Flags.Info.LocalOnly = MEDIA_IS_SKU(&perStreamParameters->m_skuTable, FtrLocalMemory);
744 
745     MOS_OS_CHK_NULL_RETURN(perStreamParameters->pGmmClientContext);
746     resource->pGmmResInfo = gmmResourceInfo = perStreamParameters->pGmmClientContext->CreateResInfoObject(&gmmParams);
747 
748     MOS_OS_CHK_NULL_RETURN(gmmResourceInfo);
749 
750     switch (gmmResourceInfo->GetTileType())
751     {
752     case GMM_TILED_X:
753         tileformat       = MOS_TILE_X;
754         tileformat_linux = TILING_X;
755         break;
756     case GMM_TILED_Y:
757         tileformat       = MOS_TILE_Y;
758         tileformat_linux = TILING_Y;
759         break;
760     case GMM_NOT_TILED:
761         tileformat       = MOS_TILE_LINEAR;
762         tileformat_linux = TILING_NONE;
763         break;
764     default:
765         tileformat       = MOS_TILE_Y;
766         tileformat_linux = TILING_Y;
767         break;
768     }
769 
770     if (params->TileType == MOS_TILE_Y)
771     {
772         gmmResourceInfo->SetMmcMode((GMM_RESOURCE_MMC_INFO)params->CompressionMode, 0);
773     }
774 
775     iPitch  = GFX_ULONG_CAST(gmmResourceInfo->GetRenderPitch());
776     iSize   = GFX_ULONG_CAST(gmmResourceInfo->GetSizeSurface());
777     iHeight = gmmResourceInfo->GetBaseHeight();
778 
779     patIndex = MosInterface::GetPATIndexFromGmm(perStreamParameters->pGmmClientContext, gmmResourceInfo);
780     isCpuCacheable = gmmResourceInfo->GetResFlags().Info.Cacheable;
781 
782     // Only Linear and Y TILE supported
783     if (tileformat_linux == TILING_NONE)
784     {
785         struct mos_drm_bo_alloc alloc;
786         alloc.name = bufname;
787         alloc.size = iSize;
788         alloc.alignment = 4096;
789         alloc.ext.mem_type = MOS_MEMPOOL_VIDEOMEMORY;
790         alloc.ext.pat_index = patIndex;
791         alloc.ext.cpu_cacheable = isCpuCacheable;
792         bo = mos_bo_alloc(perStreamParameters->bufmgr, &alloc);
793     }
794     else
795     {
796         struct mos_drm_bo_alloc_tiled alloc_tiled;
797         alloc_tiled.name = bufname;
798         alloc_tiled.x = iPitch;
799         alloc_tiled.y = iSize / iPitch;
800         alloc_tiled.cpp = 1;
801         alloc_tiled.ext.tiling_mode = tileformat_linux;
802         alloc_tiled.ext.mem_type = MOS_MEMPOOL_VIDEOMEMORY;
803         alloc_tiled.ext.pat_index = patIndex;
804         alloc_tiled.ext.cpu_cacheable = isCpuCacheable;
805 
806         bo = mos_bo_alloc_tiled(perStreamParameters->bufmgr, &alloc_tiled);
807         iPitch = (int32_t)alloc_tiled.pitch;
808     }
809 
810     resource->bMapped = false;
811     if (bo)
812     {
813         resource->Format   = params->Format;
814         resource->iWidth   = params->dwWidth;
815         resource->iHeight  = iHeight;
816         resource->iPitch   = iPitch;
817         resource->iCount   = 0;
818         resource->bufname  = bufname;
819         resource->bo       = bo;
820         resource->TileType = tileformat;
821         resource->TileModeGMM     = (MOS_TILE_MODE_GMM)gmmResourceInfo->GetTileModeSurfaceState();
822         resource->bGMMTileEnabled = true;
823         resource->pData    = (uint8_t *)bo->virt;  //It is useful for batch buffer to fill commands
824         if (params->ResUsageType == MOS_CODEC_RESOURCE_USAGE_BEGIN_CODEC ||
825             params->ResUsageType >= MOS_HW_RESOURCE_USAGE_MEDIA_BATCH_BUFFERS)
826         {
827             resource->memObjCtrlState = MosInterface::GetCachePolicyMemoryObject(perStreamParameters->pGmmClientContext, MOS_MP_RESOURCE_USAGE_DEFAULT);
828             resource->mocsMosResUsageType = MOS_MP_RESOURCE_USAGE_DEFAULT;
829         }
830         else
831         {
832             resource->memObjCtrlState = MosInterface::GetCachePolicyMemoryObject(perStreamParameters->pGmmClientContext, params->ResUsageType);
833             resource->mocsMosResUsageType = params->ResUsageType;
834         }
835         MOS_OS_VERBOSEMESSAGE("Alloc %7d bytes (%d x %d resource), tile encoding.", iSize, params->dwWidth, iHeight, resource->TileModeGMM);
836     }
837     else
838     {
839         MOS_OS_ASSERTMESSAGE("Fail to Alloc %7d bytes (%d x %d resource).", iSize, params->dwWidth, params->dwHeight);
840         eStatus = MOS_STATUS_NO_SPACE;
841     }
842 
843     return eStatus;
844 }
845 
FreeExternalResource(MOS_STREAM_HANDLE streamState,MOS_RESOURCE_HANDLE resource,uint32_t flag)846 MOS_STATUS GraphicsResourceSpecificNext::FreeExternalResource(
847     MOS_STREAM_HANDLE   streamState,
848     MOS_RESOURCE_HANDLE resource,
849     uint32_t            flag)
850 {
851     MOS_OS_FUNCTION_ENTER;
852 
853     MOS_STATUS eStatus = MOS_STATUS_SUCCESS;
854 
855     MOS_OS_CHK_NULL_RETURN(resource);
856     MOS_OS_CHK_NULL_RETURN(streamState);
857     MOS_OS_CHK_NULL_RETURN(streamState->osDeviceContext);
858 
859     if (resource && resource->bo)
860     {
861         OsContextSpecificNext *osCtx = static_cast<OsContextSpecificNext *>(streamState->osDeviceContext);
862         if (osCtx == nullptr)
863         {
864             MOS_OS_ASSERTMESSAGE("osCtx is nullptr!");
865             return MOS_STATUS_NULL_POINTER;
866         }
867         else
868         {
869             AuxTableMgr *auxTableMgr = osCtx->GetAuxTableMgr();
870 
871             // Unmap Resource from Aux Table
872             if (auxTableMgr)
873             {
874                 auxTableMgr->UnmapResource(resource->pGmmResInfo, resource->bo);
875             }
876         }
877 
878         mos_bo_unreference((MOS_LINUX_BO *)(resource->bo));
879 
880         MOS_OS_CHK_NULL_RETURN(streamState->perStreamParameters);
881         auto perStreamParameters = (PMOS_CONTEXT)streamState->perStreamParameters;
882 
883         if (perStreamParameters != nullptr && perStreamParameters->contextOffsetList.size())
884         {
885             MOS_CONTEXT *pOsCtx   = perStreamParameters;
886             auto         item_ctx = pOsCtx->contextOffsetList.begin();
887 
888             for (; item_ctx != pOsCtx->contextOffsetList.end();)
889             {
890                 if (item_ctx->target_bo == resource->bo)
891                 {
892                     item_ctx = pOsCtx->contextOffsetList.erase(item_ctx);
893                 }
894                 else
895                 {
896                     item_ctx++;
897                 }
898             }
899         }
900 
901         resource->bo = nullptr;
902     }
903 
904     return eStatus;
905 }
906 
LockExternalResource(MOS_STREAM_HANDLE streamState,MOS_RESOURCE_HANDLE resource,PMOS_LOCK_PARAMS flags)907 void* GraphicsResourceSpecificNext::LockExternalResource(
908     MOS_STREAM_HANDLE   streamState,
909     MOS_RESOURCE_HANDLE resource,
910     PMOS_LOCK_PARAMS    flags)
911 {
912     MOS_OS_FUNCTION_ENTER;
913 
914     void *pData = nullptr;
915     if (nullptr == streamState)
916     {
917         MOS_OS_ASSERTMESSAGE("input parameter streamState is NULL.");
918         return nullptr;
919     }
920 
921     if (nullptr == resource)
922     {
923         MOS_OS_ASSERTMESSAGE("input parameter resource is NULL.");
924         return nullptr;
925     }
926 
927     if (streamState->perStreamParameters == nullptr)
928     {
929         MOS_OS_ASSERTMESSAGE("perStreamParameters is nullptr, skip lock");
930         return nullptr;
931     }
932     auto perStreamParameters = (PMOS_CONTEXT)streamState->perStreamParameters;
933     if (resource && resource->bo && resource->pGmmResInfo)
934     {
935         MOS_LINUX_BO *bo = resource->bo;
936         GMM_RESOURCE_FLAG GmmFlags = resource->pGmmResInfo->GetResFlags();
937 
938         // Do decompression for a compressed surface before lock
939         if (!flags->NoDecompress &&
940             (((GmmFlags.Gpu.MMC || GmmFlags.Gpu.CCS) && GmmFlags.Info.MediaCompressed) ||
941             resource->pGmmResInfo->IsMediaMemoryCompressed(0)))
942         {
943             MosDecompression   *mosDecompression = nullptr;
944             MOS_STATUS status = MosInterface::GetMosDecompressionFromStreamState(streamState, mosDecompression);
945             if (status != MOS_STATUS_SUCCESS)
946             {
947                 MOS_OS_ASSERTMESSAGE("Get Mos Decompression From StreamState failed, skip lock");
948                 return nullptr;
949             }
950             if (nullptr == mosDecompression)
951             {
952                 MOS_OS_ASSERTMESSAGE("mosDecompression is NULL.");
953                 return nullptr;
954             }
955             mosDecompression->MemoryDecompress(resource);
956         }
957 
958         if (false == resource->bMapped)
959         {
960             if (perStreamParameters->bIsAtomSOC)
961             {
962                 mos_bo_map_gtt(bo);
963             }
964             else
965             {
966                 if (resource->TileType != MOS_TILE_LINEAR && !flags->TiledAsTiled)
967                 {
968                     if (perStreamParameters->bUseSwSwizzling)
969                     {
970                         mos_bo_map(bo, (OSKM_LOCKFLAG_WRITEONLY & flags->WriteOnly));
971                         resource->MmapOperation = MOS_MMAP_OPERATION_MMAP;
972                         if (resource->pSystemShadow == nullptr)
973                         {
974                             resource->pSystemShadow = (uint8_t *)MOS_AllocMemory(bo->size);
975                             MOS_OS_CHECK_CONDITION((resource->pSystemShadow == nullptr), "Failed to allocate shadow surface", nullptr);
976                         }
977                         if (resource->pSystemShadow)
978                         {
979                             int32_t swizzleflags = perStreamParameters->bTileYFlag ? 0 : 1;
980                             MOS_OS_CHECK_CONDITION((resource->TileType != MOS_TILE_Y), "Unsupported tile type", nullptr);
981                             MOS_OS_CHECK_CONDITION((bo->size <= 0 || resource->iPitch <= 0), "Invalid BO size or pitch", nullptr);
982                             MosUtilities::MosSwizzleData((uint8_t *)bo->virt, resource->pSystemShadow, MOS_TILE_Y, MOS_TILE_LINEAR, bo->size / resource->iPitch, resource->iPitch, swizzleflags);
983                         }
984                     }
985                     else
986                     {
987                         mos_bo_map_gtt(bo);
988                         resource->MmapOperation = MOS_MMAP_OPERATION_MMAP_GTT;
989                     }
990                 }
991                 else if (flags->Uncached)
992                 {
993                     mos_bo_map_wc(bo);
994                     resource->MmapOperation = MOS_MMAP_OPERATION_MMAP_WC;
995                 }
996                 else
997                 {
998                     mos_bo_map(bo, (OSKM_LOCKFLAG_WRITEONLY & flags->WriteOnly));
999                     resource->MmapOperation = MOS_MMAP_OPERATION_MMAP;
1000                 }
1001             }
1002             resource->pData   = resource->pSystemShadow ? resource->pSystemShadow : (uint8_t *)bo->virt;
1003             resource->bMapped = true;
1004         }
1005 
1006         pData = resource->pData;
1007     }
1008 
1009     MOS_OS_ASSERT(pData);
1010     return pData;
1011 }
1012 
UnlockExternalResource(MOS_STREAM_HANDLE streamState,MOS_RESOURCE_HANDLE resource)1013 MOS_STATUS GraphicsResourceSpecificNext::UnlockExternalResource(
1014     MOS_STREAM_HANDLE   streamState,
1015     MOS_RESOURCE_HANDLE resource)
1016 {
1017     MOS_OS_FUNCTION_ENTER;
1018 
1019     MOS_OS_CHK_NULL_RETURN(resource);
1020     MOS_OS_CHK_NULL_RETURN(streamState);
1021     MOS_OS_CHK_NULL_RETURN(streamState->osDeviceContext);
1022 
1023     MOS_OS_CHK_NULL_RETURN(streamState->perStreamParameters);
1024     auto perStreamParameters = (PMOS_CONTEXT)streamState->perStreamParameters;
1025 
1026     if (resource->bo)
1027     {
1028         if (true == resource->bMapped)
1029         {
1030             if (perStreamParameters->bIsAtomSOC)
1031             {
1032                 mos_bo_unmap_gtt(resource->bo);
1033             }
1034             else
1035             {
1036                 if (resource->pSystemShadow)
1037                 {
1038                     int32_t flags = perStreamParameters->bTileYFlag ? 0 : 1;
1039                     MosUtilities::MosSwizzleData(resource->pSystemShadow, (uint8_t *)resource->bo->virt, MOS_TILE_LINEAR, MOS_TILE_Y, resource->bo->size / resource->iPitch, resource->iPitch, flags);
1040                     MOS_FreeMemory(resource->pSystemShadow);
1041                     resource->pSystemShadow = nullptr;
1042                 }
1043 
1044                 switch (resource->MmapOperation)
1045                 {
1046                 case MOS_MMAP_OPERATION_MMAP_GTT:
1047                     mos_bo_unmap_gtt(resource->bo);
1048                     break;
1049                 case MOS_MMAP_OPERATION_MMAP_WC:
1050                     mos_bo_unmap_wc(resource->bo);
1051                     break;
1052                 case MOS_MMAP_OPERATION_MMAP:
1053                     mos_bo_unmap(resource->bo);
1054                     break;
1055                 default:
1056                     MOS_OS_ASSERTMESSAGE("Invalid mmap operation type");
1057                     break;
1058                 }
1059             }
1060             resource->bo->virt = nullptr;
1061             resource->bMapped  = false;
1062         }
1063         resource->pData = nullptr;
1064     }
1065 
1066     return MOS_STATUS_SUCCESS;
1067 }
1068 
SetTileModebyForce(GMM_RESCREATE_PARAMS & gmmParams,MOS_TILE_MODE_GMM tileMode)1069 MOS_STATUS GraphicsResourceSpecificNext::SetTileModebyForce(GMM_RESCREATE_PARAMS &gmmParams, MOS_TILE_MODE_GMM tileMode)
1070 {
1071     if (tileMode == MOS_TILE_64_GMM)
1072     {
1073         gmmParams.Flags.Info.Tile64 = true;
1074     }
1075     else if (tileMode == MOS_TILE_4_GMM)
1076     {
1077         gmmParams.Flags.Info.Tile4 = true;
1078     }
1079     return MOS_STATUS_SUCCESS;
1080 }
1081