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     vphal_render_vebox_memdecomp.cpp
24 //! \brief    Defines data structures and interfaces for media memory decompression.
25 //! \details
26 //!
27 #include "vphal_render_vebox_memdecomp.h"
28 #include "mos_os_cp_interface_specific.h"
29 #include "vphal_debug.h"
30 #include "vp_utils.h"
31 
32 #define DECOMPRESSION_WIDTH_ALIGNMENT_IN_BYTE 32
33 
MediaVeboxDecompState()34 MediaVeboxDecompState::MediaVeboxDecompState():
35     MediaMemDecompBaseState(),
36     m_osInterface(nullptr),
37     m_veboxInterface(nullptr),
38     m_mhwMiInterface(nullptr),
39     m_cpInterface(nullptr)
40 {
41     m_veboxMMCResolveEnabled = false;
42 }
43 
~MediaVeboxDecompState()44 MediaVeboxDecompState::~MediaVeboxDecompState()
45 {
46     MOS_STATUS              eStatus;
47 
48     if (m_cpInterface)
49     {
50         if(m_osInterface)
51         {
52             m_osInterface->pfnDeleteMhwCpInterface(m_cpInterface);
53             m_cpInterface = nullptr;
54         }
55         else
56         {
57             VPHAL_MEMORY_DECOMP_ASSERTMESSAGE("Failed to destroy cpInterface.");
58         }
59     }
60 
61     if (m_veboxInterface)
62     {
63 #if (_DEBUG || _RELEASE_INTERNAL)
64         if (m_surfaceDumper)
65         {
66             MOS_Delete(m_surfaceDumper);
67             m_surfaceDumper = nullptr;
68         }
69 #endif
70         eStatus = m_veboxInterface->DestroyHeap();
71         MOS_Delete(m_veboxInterface);
72         m_veboxInterface = nullptr;
73         if (eStatus != MOS_STATUS_SUCCESS)
74         {
75             VPHAL_MEMORY_DECOMP_ASSERTMESSAGE("Failed to destroy Vebox Interface, eStatus:%d.\n", eStatus);
76         }
77     }
78 
79     if (m_mhwMiInterface)
80     {
81         MOS_Delete(m_mhwMiInterface);
82         m_mhwMiInterface = nullptr;
83     }
84 
85     if (m_osInterface)
86     {
87         m_osInterface->pfnDestroy(m_osInterface, false);
88         MOS_FreeMemory(m_osInterface);
89         m_osInterface = nullptr;
90     }
91 }
92 
93 #if (_DEBUG || _RELEASE_INTERNAL)
CloneResourceInfo(PVPHAL_SURFACE pVphalSurface,PMOS_SURFACE pMosSurface)94 MOS_STATUS CloneResourceInfo(PVPHAL_SURFACE pVphalSurface, PMOS_SURFACE pMosSurface)
95 {
96     MOS_STATUS eStatus = MOS_STATUS_SUCCESS;
97 
98     VPHAL_MEMORY_DECOMP_CHK_NULL_RETURN(pVphalSurface);
99     VPHAL_MEMORY_DECOMP_CHK_NULL_RETURN(pMosSurface);
100 
101     pVphalSurface->SurfType = SURF_NONE;
102 
103     pVphalSurface->OsResource        = pMosSurface->OsResource;
104     pVphalSurface->dwWidth           = pMosSurface->dwWidth;
105     pVphalSurface->dwHeight          = pMosSurface->dwHeight;
106     pVphalSurface->dwPitch           = pMosSurface->dwPitch;
107     pVphalSurface->Format            = pMosSurface->Format;
108     pVphalSurface->TileType          = pMosSurface->TileType;
109     pVphalSurface->TileModeGMM       = pMosSurface->TileModeGMM;
110     pVphalSurface->bGMMTileEnabled   = pMosSurface->bGMMTileEnabled;
111     pVphalSurface->dwDepth           = pMosSurface->dwDepth;
112     pVphalSurface->dwSlicePitch      = pMosSurface->dwSlicePitch;
113     pVphalSurface->dwOffset          = pMosSurface->dwOffset;
114     pVphalSurface->bCompressible     = pMosSurface->bCompressible;
115     pVphalSurface->bIsCompressed     = pMosSurface->bIsCompressed;
116     pVphalSurface->CompressionMode   = pMosSurface->CompressionMode;
117     pVphalSurface->CompressionFormat = pMosSurface->CompressionFormat;
118 
119     pVphalSurface->YPlaneOffset.iLockSurfaceOffset = pMosSurface->YPlaneOffset.iLockSurfaceOffset;
120     pVphalSurface->YPlaneOffset.iSurfaceOffset     = pMosSurface->YPlaneOffset.iSurfaceOffset;
121     pVphalSurface->YPlaneOffset.iXOffset           = pMosSurface->YPlaneOffset.iXOffset;
122     pVphalSurface->YPlaneOffset.iYOffset           = pMosSurface->YPlaneOffset.iYOffset;
123 
124     pVphalSurface->UPlaneOffset.iLockSurfaceOffset = pMosSurface->UPlaneOffset.iLockSurfaceOffset;
125     pVphalSurface->UPlaneOffset.iSurfaceOffset     = pMosSurface->UPlaneOffset.iSurfaceOffset;
126     pVphalSurface->UPlaneOffset.iXOffset           = pMosSurface->UPlaneOffset.iXOffset;
127     pVphalSurface->UPlaneOffset.iYOffset           = pMosSurface->UPlaneOffset.iYOffset;
128 
129     pVphalSurface->VPlaneOffset.iLockSurfaceOffset = pMosSurface->VPlaneOffset.iLockSurfaceOffset;
130     pVphalSurface->VPlaneOffset.iSurfaceOffset     = pMosSurface->VPlaneOffset.iSurfaceOffset;
131     pVphalSurface->VPlaneOffset.iXOffset           = pMosSurface->VPlaneOffset.iXOffset;
132     pVphalSurface->VPlaneOffset.iYOffset           = pMosSurface->VPlaneOffset.iYOffset;
133 
134     return eStatus;
135 }
136 
137 #define DumpSurfaceMemDecomp(MosSurface, SurfaceCounter, BufferCopy, Location) \
138     {                                                                                                      \
139         VPHAL_SURFACE VphalSurface = {};                                                                   \
140         CloneResourceInfo(&VphalSurface, &MosSurface);                                     \
141         if (m_surfaceDumper)                                                                               \
142         {                                                                                                  \
143             m_surfaceDumper->DumpSurface(&VphalSurface, SurfaceCounter, BufferCopy, Location);             \
144         }                                                                                                  \
145     }
146 #else
147 #define DumpSurfaceMemDecomp(MosSurface, surfaceCounter, DoubleCopy, Locationlocation) {}
148 #endif
149 
MemoryDecompress(PMOS_RESOURCE targetResource)150 MOS_STATUS MediaVeboxDecompState::MemoryDecompress(PMOS_RESOURCE targetResource)
151 {
152     MOS_STATUS              eStatus = MOS_STATUS_SUCCESS;
153     MOS_SURFACE             TargetSurface;
154 
155     MHW_FUNCTION_ENTER;
156 
157     VPHAL_MEMORY_DECOMP_CHK_NULL_RETURN(targetResource);
158     MOS_TraceEventExt(EVENT_MEDIA_COPY, EVENT_TYPE_START, nullptr, 0, nullptr, 0);
159 #if MOS_MEDIASOLO_SUPPORTED
160     if (m_osInterface->bSoloInUse)
161     {
162         // Bypass
163     }
164     else
165 #endif
166     {
167         if (m_veboxMMCResolveEnabled)
168         {
169             MOS_ZeroMemory(&TargetSurface, sizeof(MOS_SURFACE));
170 
171             TargetSurface.Format = Format_Invalid;
172             TargetSurface.OsResource = *targetResource;
173             VPHAL_MEMORY_DECOMP_CHK_STATUS_RETURN(GetResourceInfo(&TargetSurface));
174 
175             //Get context before proceeding
176             auto gpuContext = m_osInterface->CurrentGpuContextOrdinal;
177 
178             if (TargetSurface.bCompressible)
179             {
180                 DumpSurfaceMemDecomp(TargetSurface, m_surfaceDumpCounter, 0, VPHAL_DBG_DUMP_TYPE_PRE_MEMDECOMP);
181 
182                 VPHAL_MEMORY_DECOMP_CHK_STATUS_RETURN(RenderDecompCMD(&TargetSurface));
183 
184                 DumpSurfaceMemDecomp(TargetSurface, m_surfaceDumpCounter++, 0, VPHAL_DBG_DUMP_TYPE_POST_MEMDECOMP);
185             }
186         }
187     }
188     MOS_TraceEventExt(EVENT_MEDIA_COPY, EVENT_TYPE_END, nullptr, 0, nullptr, 0);
189     return eStatus;
190 }
191 
MediaMemoryCopy(PMOS_RESOURCE inputResource,PMOS_RESOURCE outputResource,bool outputCompressed)192 MOS_STATUS MediaVeboxDecompState::MediaMemoryCopy(
193     PMOS_RESOURCE inputResource,
194     PMOS_RESOURCE outputResource,
195     bool          outputCompressed)
196 {
197     MOS_STATUS eStatus             = MOS_STATUS_SUCCESS;
198     bool       bValidInputSurface  = false;
199     bool       bValidOutputSurface = false;
200 
201     MHW_FUNCTION_ENTER;
202 
203     VPHAL_MEMORY_DECOMP_CHK_NULL_RETURN(inputResource);
204     VPHAL_MEMORY_DECOMP_CHK_NULL_RETURN(outputResource);
205     MOS_TraceEventExt(EVENT_MEDIA_COPY, EVENT_TYPE_START, nullptr, 0, nullptr, 0);
206 
207     MOS_SURFACE             sourceSurface;
208     MOS_SURFACE             targetSurface;
209 
210     MOS_ZeroMemory(&targetSurface, sizeof(MOS_SURFACE));
211     MOS_ZeroMemory(&sourceSurface, sizeof(MOS_SURFACE));
212 
213     targetSurface.Format     = Format_Invalid;
214     targetSurface.OsResource = *outputResource;
215 
216 #if !defined(LINUX) && !defined(ANDROID) && !EMUL && !_VULKAN
217     // for Double Buffer copy, clear the allocationInfo temply
218     MOS_ZeroMemory(&targetSurface.OsResource.AllocationInfo, sizeof(SResidencyInfo));
219 #endif
220 
221     sourceSurface.Format = Format_Invalid;
222     sourceSurface.OsResource = *inputResource;
223     VPHAL_MEMORY_DECOMP_CHK_STATUS_RETURN(GetResourceInfo(&targetSurface));
224     VPHAL_MEMORY_DECOMP_CHK_STATUS_RETURN(GetResourceInfo(&sourceSurface));
225 
226 #if (_DEBUG || _RELEASE_INTERNAL)
227     {
228         // Read user feature key to force outputCompressed
229         ReadUserSettingForDebug(
230             m_userSettingPtr,
231             outputCompressed,
232             __VPHAL_VEBOX_FORCE_VP_MEMCOPY_OUTPUTCOMPRESSED,
233             MediaUserSetting::Group::Sequence);
234     }
235 #endif
236 
237     if (!outputCompressed && targetSurface.CompressionMode != MOS_MMC_DISABLED)
238     {
239         targetSurface.CompressionMode = MOS_MMC_RC;
240     }
241 
242     //if surface is linear buffer, use mos copy
243     if (sourceSurface.TileType == MOS_TILE_LINEAR          &&
244         targetSurface.TileType == MOS_TILE_LINEAR          &&
245         sourceSurface.Type     == MOS_GFXRES_BUFFER        &&
246         targetSurface.Type     == MOS_GFXRES_BUFFER )
247     {
248         DumpSurfaceMemDecomp(sourceSurface, m_surfaceDumpCounter, 1, VPHAL_DBG_DUMP_TYPE_PRE_MEMDECOMP);
249         do
250         {
251             MOS_LOCK_PARAMS lockSourceFlags;
252             MOS_ZeroMemory(&lockSourceFlags, sizeof(MOS_LOCK_PARAMS));
253             lockSourceFlags.ReadOnly     = 1;
254             lockSourceFlags.WriteOnly    = 0;
255 
256             MOS_LOCK_PARAMS lockTargetFlags;
257             MOS_ZeroMemory(&lockTargetFlags, sizeof(MOS_LOCK_PARAMS));
258             lockTargetFlags.ReadOnly     = 0;
259             lockTargetFlags.WriteOnly    = 1;
260 
261             uint8_t *lockedSrcAddr       = (uint8_t *)m_osInterface->pfnLockResource(m_osInterface, &sourceSurface.OsResource, &lockSourceFlags);
262 
263             if (lockedSrcAddr == nullptr)
264             {
265                 //non lockable resource enabled, we can't lock source surface
266                 eStatus = MOS_STATUS_NULL_POINTER;
267                 VPHAL_MEMORY_DECOMP_ASSERTMESSAGE("Failed to lock non-lockable input resource, buffer copy failed, eStatus:%d.\n", eStatus);
268                 MT_ERR2(MT_VE_DECOMP_COPY, MT_SURF_IS_INPUT, 1, MT_VE_DECOMP_COPY_SURF_LOCK_STATUS, eStatus);
269                 break;
270             }
271 
272             uint8_t *lockedTarAddr       = (uint8_t *)m_osInterface->pfnLockResource(m_osInterface, &targetSurface.OsResource, &lockTargetFlags);
273 
274             if (lockedTarAddr == nullptr)
275             {
276                 eStatus = MOS_STATUS_NULL_POINTER;
277                 m_osInterface->pfnUnlockResource(m_osInterface, &sourceSurface.OsResource);
278                 VPHAL_MEMORY_DECOMP_ASSERTMESSAGE("Failed to lock non-lockable output resource, buffer copy failed, eStatus:%d.\n", eStatus);
279                 MT_ERR2(MT_VE_DECOMP_COPY, MT_SURF_IS_OUTPUT, 1, MT_VE_DECOMP_COPY_SURF_LOCK_STATUS, eStatus);
280                 break;
281             }
282             // This resource is a series of bytes. Is not 2 dimensional.
283             uint32_t sizeSrcMain    = sourceSurface.dwWidth;
284             uint32_t sizeTargetMain = targetSurface.dwWidth;
285             eStatus                 = MOS_SecureMemcpy(lockedTarAddr, sizeTargetMain, lockedSrcAddr, sizeSrcMain);
286             m_osInterface->pfnUnlockResource(m_osInterface, &sourceSurface.OsResource);
287             m_osInterface->pfnUnlockResource(m_osInterface, &targetSurface.OsResource);
288 
289             if (eStatus != MOS_STATUS_SUCCESS)
290             {
291                 VPHAL_MEMORY_DECOMP_ASSERTMESSAGE("Failed to copy linear buffer from source to target, eStatus:%d.\n", eStatus);
292                 MT_ERR1(MT_VE_DECOMP_COPY, MT_MOS_STATUS, eStatus);
293                 break;
294             }
295         } while (false);
296 
297         DumpSurfaceMemDecomp(targetSurface, m_surfaceDumpCounter++, 1, VPHAL_DBG_DUMP_TYPE_POST_MEMDECOMP);
298         MOS_TraceEventExt(EVENT_MEDIA_COPY, EVENT_TYPE_END, nullptr, 0, nullptr, 0);
299         return eStatus;
300     }
301 
302     // if source surface or target surface is non-64align linear, return error here
303     if((sourceSurface.dwPitch%64 != 0 && sourceSurface.TileType == MOS_TILE_LINEAR) ||
304        (targetSurface.dwPitch%64 != 0 && targetSurface.TileType == MOS_TILE_LINEAR))
305     {
306         eStatus = MOS_STATUS_INVALID_PARAMETER;
307         VPHAL_MEMORY_DECOMP_ASSERTMESSAGE("VEBOX does not support non-64align pitch linear surface, eStatus:%d.\n", eStatus);
308         MT_ERR2(MT_VE_DECOMP_COPY, MT_SURF_PITCH, sourceSurface.dwPitch, MT_SURF_PITCH, targetSurface.dwPitch);
309         MOS_TraceEventExt(EVENT_MEDIA_COPY, EVENT_TYPE_END, nullptr, 0, nullptr, 0);
310         return eStatus;
311     }
312 
313     //Get context before proceeding
314     auto gpuContext = m_osInterface->CurrentGpuContextOrdinal;
315 
316     //Check whether surface is valid, or it will cause page fault
317     m_osInterface->pfnVerifyMosSurface(&sourceSurface, bValidInputSurface);
318     m_osInterface->pfnVerifyMosSurface(&targetSurface, bValidOutputSurface);
319     if (!bValidInputSurface || !bValidOutputSurface)
320     {
321         VPHAL_MEMORY_DECOMP_CHK_STATUS_RETURN(MOS_STATUS_INVALID_PARAMETER);
322     }
323 
324     // Sync for Vebox read
325     m_osInterface->pfnSyncOnResource(
326         m_osInterface,
327         &sourceSurface.OsResource,
328         MOS_GPU_CONTEXT_VEBOX,
329         false);
330 
331     // Sync for Vebox write
332     m_osInterface->pfnSyncOnResource(
333         m_osInterface,
334         &targetSurface.OsResource,
335         MOS_GPU_CONTEXT_VEBOX,
336         false);
337 
338     DumpSurfaceMemDecomp(sourceSurface, m_surfaceDumpCounter, 1, VPHAL_DBG_DUMP_TYPE_PRE_MEMDECOMP);
339 
340     VPHAL_MEMORY_DECOMP_CHK_STATUS_RETURN(RenderDoubleBufferDecompCMD(&sourceSurface, &targetSurface));
341 
342     DumpSurfaceMemDecomp(targetSurface, m_surfaceDumpCounter++, 1, VPHAL_DBG_DUMP_TYPE_POST_MEMDECOMP);
343     MOS_TraceEventExt(EVENT_MEDIA_COPY, EVENT_TYPE_END, nullptr, 0, nullptr, 0);
344     return eStatus;
345 }
346 
MediaMemoryCopy2D(PMOS_RESOURCE inputResource,PMOS_RESOURCE outputResource,uint32_t copyWidth,uint32_t copyHeight,uint32_t copyInputOffset,uint32_t copyOutputOffset,uint32_t bpp,bool outputCompressed)347 MOS_STATUS MediaVeboxDecompState::MediaMemoryCopy2D(
348     PMOS_RESOURCE inputResource,
349     PMOS_RESOURCE outputResource,
350     uint32_t      copyWidth,
351     uint32_t      copyHeight,
352     uint32_t      copyInputOffset,
353     uint32_t      copyOutputOffset,
354     uint32_t      bpp,
355     bool          outputCompressed)
356 {
357     MOS_STATUS eStatus             = MOS_STATUS_SUCCESS;
358     bool       bValidInputSurface  = false;
359     bool       bValidOutputSurface = false;
360 
361     MHW_FUNCTION_ENTER;
362 
363     VPHAL_MEMORY_DECOMP_CHK_NULL_RETURN(inputResource);
364     VPHAL_MEMORY_DECOMP_CHK_NULL_RETURN(outputResource);
365     MOS_TraceEventExt(EVENT_MEDIA_COPY, EVENT_TYPE_START, nullptr, 0, nullptr, 0);
366 
367     MOS_SURFACE             sourceSurface;
368     MOS_SURFACE             targetSurface;
369 
370     MOS_ZeroMemory(&targetSurface, sizeof(MOS_SURFACE));
371     MOS_ZeroMemory(&sourceSurface, sizeof(MOS_SURFACE));
372 
373     targetSurface.Format = Format_Invalid;
374     targetSurface.OsResource = *outputResource;
375 
376 #if !defined(LINUX) && !defined(ANDROID) && !EMUL && !_VULKAN
377     // for Double Buffer copy, clear the allocationInfo temply
378     MOS_ZeroMemory(&targetSurface.OsResource.AllocationInfo, sizeof(SResidencyInfo));
379 #endif
380 
381     sourceSurface.Format = Format_Invalid;
382     sourceSurface.OsResource = *inputResource;
383     VPHAL_MEMORY_DECOMP_CHK_STATUS_RETURN(GetResourceInfo(&targetSurface));
384     VPHAL_MEMORY_DECOMP_CHK_STATUS_RETURN(GetResourceInfo(&sourceSurface));
385 
386 #if (_DEBUG || _RELEASE_INTERNAL)
387     {
388         // Read user feature key to Force outputCompressed
389         ReadUserSettingForDebug(
390             m_userSettingPtr,
391             outputCompressed,
392             __VPHAL_VEBOX_FORCE_VP_MEMCOPY_OUTPUTCOMPRESSED,
393             MediaUserSetting::Group::Sequence);
394     }
395 #endif
396 
397     if (!outputCompressed && targetSurface.CompressionMode != MOS_MMC_DISABLED)
398     {
399         targetSurface.CompressionMode = MOS_MMC_RC;
400     }
401 
402     //Get context before proceeding
403     auto gpuContext = m_osInterface->CurrentGpuContextOrdinal;
404     uint32_t pixelInByte = 1;
405 
406     switch (bpp)
407     {
408     case 8:
409         targetSurface.Format = Format_Y8;
410         sourceSurface.Format = Format_Y8;
411         pixelInByte = 1;
412         break;
413     case 16:
414         targetSurface.Format = Format_Y16U;
415         sourceSurface.Format = Format_Y16U;
416         pixelInByte = 2;
417         break;
418     case 32:
419         targetSurface.Format = Format_AYUV;
420         sourceSurface.Format = Format_AYUV;
421         pixelInByte = 4;
422         break;
423     case 64:
424         targetSurface.Format = Format_Y416;
425         sourceSurface.Format = Format_Y416;
426         pixelInByte = 8;
427         break;
428     default:
429         targetSurface.Format = Format_Y8;
430         sourceSurface.Format = Format_Y8;
431         pixelInByte = 1;
432         break;
433     }
434 
435 
436     sourceSurface.dwOffset = copyInputOffset;
437     targetSurface.dwOffset = copyOutputOffset;
438 
439     sourceSurface.dwWidth  = copyWidth / pixelInByte;
440     sourceSurface.dwHeight = copyHeight;
441     targetSurface.dwWidth  = copyWidth / pixelInByte;
442     targetSurface.dwHeight = copyHeight;
443 
444     //Check whether surface is valid, or it will cause page fault
445     m_osInterface->pfnVerifyMosSurface(&sourceSurface, bValidInputSurface);
446     m_osInterface->pfnVerifyMosSurface(&targetSurface, bValidOutputSurface);
447     if (!bValidInputSurface || !bValidOutputSurface)
448     {
449         VPHAL_MEMORY_DECOMP_CHK_STATUS_RETURN(MOS_STATUS_INVALID_PARAMETER);
450     }
451 
452     // Sync for Vebox write
453     m_osInterface->pfnSyncOnResource(
454         m_osInterface,
455         &sourceSurface.OsResource,
456         MOS_GPU_CONTEXT_VEBOX,
457         false);
458 
459     DumpSurfaceMemDecomp(sourceSurface, m_surfaceDumpCounter, 1, VPHAL_DBG_DUMP_TYPE_PRE_MEMDECOMP);
460 
461     VPHAL_MEMORY_DECOMP_CHK_STATUS_RETURN(RenderDoubleBufferDecompCMD(&sourceSurface, &targetSurface));
462 
463     DumpSurfaceMemDecomp(targetSurface, m_surfaceDumpCounter++, 1, VPHAL_DBG_DUMP_TYPE_POST_MEMDECOMP);
464     MOS_TraceEventExt(EVENT_MEDIA_COPY, EVENT_TYPE_END, nullptr, 0, nullptr, 0);
465     return eStatus;
466 }
467 
MediaMemoryTileConvert(PMOS_RESOURCE inputResource,PMOS_RESOURCE outputResource,uint32_t copyWidth,uint32_t copyHeight,uint32_t copyInputOffset,uint32_t copyOutputOffset,bool isTileToLinear,bool outputCompressed)468 MOS_STATUS MediaVeboxDecompState::MediaMemoryTileConvert(
469         PMOS_RESOURCE inputResource,
470         PMOS_RESOURCE outputResource,
471         uint32_t      copyWidth,
472         uint32_t      copyHeight,
473         uint32_t      copyInputOffset,
474         uint32_t      copyOutputOffset,
475         bool          isTileToLinear,
476         bool          outputCompressed)
477 {
478     MOS_STATUS                          eStatus = MOS_STATUS_SUCCESS;
479 
480     MHW_FUNCTION_ENTER;
481 
482     VPHAL_MEMORY_DECOMP_CHK_NULL_RETURN(inputResource);
483     VPHAL_MEMORY_DECOMP_CHK_NULL_RETURN(outputResource);
484     MOS_TraceEventExt(EVENT_MEDIA_COPY, EVENT_TYPE_START, nullptr, 0, nullptr, 0);
485 
486     MOS_SURFACE             sourceSurface;
487     MOS_SURFACE             targetSurface;
488 
489     MOS_ZeroMemory(&targetSurface, sizeof(MOS_SURFACE));
490     MOS_ZeroMemory(&sourceSurface, sizeof(MOS_SURFACE));
491 
492     targetSurface.Format = Format_Invalid;
493     targetSurface.OsResource = *outputResource;
494 
495 #if !defined(LINUX) && !defined(ANDROID) && !EMUL && !_VULKAN
496     // for Double Buffer copy, clear the allocationInfo temply
497     MOS_ZeroMemory(&targetSurface.OsResource.AllocationInfo, sizeof(SResidencyInfo));
498 #endif
499 
500     sourceSurface.Format = Format_Invalid;
501     sourceSurface.OsResource = *inputResource;
502     VPHAL_MEMORY_DECOMP_CHK_STATUS_RETURN(GetResourceInfo(&targetSurface));
503     VPHAL_MEMORY_DECOMP_CHK_STATUS_RETURN(GetResourceInfo(&sourceSurface));
504 
505     if (targetSurface.TileType == MOS_TILE_LINEAR &&
506         sourceSurface.TileType == MOS_TILE_LINEAR)
507     {
508         VPHAL_MEMORY_DECOMP_NORMALMESSAGE("unsupport linear to linear convert, return unsupport feature");
509         MT_ERR2(MT_VE_DECOMP_COPY, MT_SURF_TILE_TYPE, MOS_TILE_LINEAR, MT_SURF_TILE_TYPE, MOS_TILE_LINEAR);
510         return MOS_STATUS_PLATFORM_NOT_SUPPORTED;
511     }
512 
513     MOS_FORMAT format = Format_Any;
514     if (isTileToLinear)
515     {
516         if (!IsFormatSupported(&sourceSurface))
517         {
518             VPHAL_MEMORY_DECOMP_NORMALMESSAGE("unsupport processing format, return unsupport feature");
519             MT_ERR2(MT_VE_DECOMP_COPY, MT_SURF_MOS_FORMAT, sourceSurface.Format, MT_SURF_IS_INPUT, 1);
520             return MOS_STATUS_PLATFORM_NOT_SUPPORTED;
521         }
522 
523         format = sourceSurface.Format;
524         copyHeight = sourceSurface.dwHeight;
525     }
526     else
527     {
528         if (!IsFormatSupported(&targetSurface))
529         {
530             VPHAL_MEMORY_DECOMP_NORMALMESSAGE("unsupport processing format, return unsupport feature");
531             MT_ERR2(MT_VE_DECOMP_COPY, MT_SURF_MOS_FORMAT, targetSurface.Format, MT_SURF_IS_OUTPUT, 1);
532             return MOS_STATUS_PLATFORM_NOT_SUPPORTED;
533         }
534 
535         format = targetSurface.Format;
536         copyHeight = targetSurface.dwHeight;
537     }
538 
539     if (!outputCompressed && targetSurface.CompressionMode != MOS_MMC_DISABLED)
540     {
541         targetSurface.CompressionMode = MOS_MMC_RC;
542     }
543 
544     //Get context before proceeding
545     auto gpuContext = m_osInterface->CurrentGpuContextOrdinal;
546 
547     targetSurface.Format = format;
548     sourceSurface.Format = format;
549 
550     sourceSurface.dwOffset = copyInputOffset;
551     targetSurface.dwOffset = copyOutputOffset;
552 
553     sourceSurface.dwWidth = copyWidth;
554     sourceSurface.dwHeight = copyHeight;
555     targetSurface.dwWidth = copyWidth;
556     targetSurface.dwHeight = copyHeight;
557 
558     // Sync for Vebox write
559     m_osInterface->pfnSyncOnResource(
560         m_osInterface,
561         &targetSurface.OsResource,
562         MOS_GPU_CONTEXT_VEBOX,
563         false);
564 
565     DumpSurfaceMemDecomp(sourceSurface, m_surfaceDumpCounter, 1, VPHAL_DBG_DUMP_TYPE_PRE_MEMDECOMP);
566 
567     VPHAL_MEMORY_DECOMP_CHK_STATUS_RETURN(RenderDoubleBufferDecompCMD(&sourceSurface, &targetSurface));
568 
569     DumpSurfaceMemDecomp(targetSurface, m_surfaceDumpCounter++, 1, VPHAL_DBG_DUMP_TYPE_POST_MEMDECOMP);
570     MOS_TraceEventExt(EVENT_MEDIA_COPY, EVENT_TYPE_END, nullptr, 0, nullptr, 0);
571     return eStatus;
572 }
573 
Initialize(PMOS_INTERFACE osInterface,MhwCpInterface * cpInterface,PMHW_MI_INTERFACE mhwMiInterface,PMHW_VEBOX_INTERFACE veboxInterface)574 MOS_STATUS MediaVeboxDecompState::Initialize(
575     PMOS_INTERFACE               osInterface,
576     MhwCpInterface              *cpInterface,
577     PMHW_MI_INTERFACE            mhwMiInterface,
578     PMHW_VEBOX_INTERFACE         veboxInterface)
579 {
580     MOS_STATUS                  eStatus;
581     MHW_VEBOX_GPUNODE_LIMIT     GpuNodeLimit;
582     MOS_GPU_NODE                VeboxGpuNode;
583     MOS_GPU_CONTEXT             VeboxGpuContext;
584     RENDERHAL_SETTINGS_LEGACY   RenderHalSettings;
585 
586     eStatus = MOS_STATUS_SUCCESS;
587 
588     VPHAL_MEMORY_DECOMP_CHK_NULL_RETURN(osInterface);
589     VPHAL_MEMORY_DECOMP_CHK_NULL_RETURN(cpInterface);
590     VPHAL_MEMORY_DECOMP_CHK_NULL_RETURN(mhwMiInterface);
591     VPHAL_MEMORY_DECOMP_CHK_NULL_RETURN(veboxInterface);
592 
593     m_osInterface     = osInterface;
594     m_cpInterface     = cpInterface;
595     m_mhwMiInterface  = mhwMiInterface;
596     m_veboxInterface  = veboxInterface;
597 
598     m_userSettingPtr  = m_osInterface->pfnGetUserSettingInstance(m_osInterface);
599 
600     // Set-Up Vebox decompression enable or not
601     IsVeboxDecompressionEnabled();
602 
603     if (m_veboxInterface)
604     {
605         GpuNodeLimit.bCpEnabled = (m_osInterface->osCpInterface->IsCpEnabled())? true : false;
606 
607         // Check GPU Node decide logic together in this function
608         VPHAL_MEMORY_DECOMP_CHK_STATUS_RETURN(m_veboxInterface->FindVeboxGpuNodeToUse(&GpuNodeLimit));
609 
610         VeboxGpuNode = (MOS_GPU_NODE)(GpuNodeLimit.dwGpuNodeToUse);
611         VeboxGpuContext = (VeboxGpuNode == MOS_GPU_NODE_VE) ? MOS_GPU_CONTEXT_VEBOX : MOS_GPU_CONTEXT_VEBOX2;
612 
613         // Create VEBOX/VEBOX2 Context
614         VPHAL_MEMORY_DECOMP_CHK_STATUS_RETURN(m_veboxInterface->CreateGpuContext(
615             m_osInterface,
616             VeboxGpuContext,
617             VeboxGpuNode));
618 
619         // Register Vebox GPU context with the Batch Buffer completion event
620         VPHAL_MEMORY_DECOMP_CHK_STATUS_RETURN(m_osInterface->pfnRegisterBBCompleteNotifyEvent(
621             m_osInterface,
622             MOS_GPU_CONTEXT_VEBOX));
623 
624         if (m_veboxInterface->m_veboxHeap == nullptr)
625         {
626             VPHAL_MEMORY_DECOMP_CHK_STATUS_RETURN(m_veboxInterface->CreateHeap());
627         }
628 
629 #if (_DEBUG || _RELEASE_INTERNAL)
630         CreateSurfaceDumper();
631         if (m_surfaceDumper)
632         {
633             m_surfaceDumper->GetSurfaceDumpSpec();
634         }
635         else
636         {
637             VPHAL_MEMORY_DECOMP_ASSERTMESSAGE("surface dumpper creation failed.");
638         }
639 #endif
640     }
641 
642     return eStatus;
643 }
644 #if (_DEBUG || _RELEASE_INTERNAL)
CreateSurfaceDumper()645 void MediaVeboxDecompState::CreateSurfaceDumper()
646 {
647     m_surfaceDumper = MOS_New(VphalSurfaceDumper, m_osInterface);
648 }
649 #endif
650 
GetResourceInfo(PMOS_SURFACE surface)651 MOS_STATUS MediaVeboxDecompState::GetResourceInfo(PMOS_SURFACE surface)
652 {
653     MOS_STATUS  eStatus = MOS_STATUS_SUCCESS;
654 
655     VPHAL_MEMORY_DECOMP_CHK_NULL_RETURN(m_osInterface);
656     VPHAL_MEMORY_DECOMP_CHK_NULL_RETURN(surface);
657 
658     MOS_SURFACE resDetails;
659     MOS_ZeroMemory(&resDetails, sizeof(resDetails));
660     resDetails.Format = Format_Invalid;
661 
662     VPHAL_MEMORY_DECOMP_CHK_STATUS_RETURN(m_osInterface->pfnGetResourceInfo(
663         m_osInterface,
664         &surface->OsResource,
665         &resDetails));
666 
667     surface->Format                                             = resDetails.Format;
668 #if defined(LINUX) && !defined(WDDM_LINUX)
669     if ((surface->Format == Format_NV12 || surface->Format == Format_P010) && surface->OsResource.iWidth & 1 != 0)
670     {
671         uint32_t bitsPerPixel = 8;
672         if (surface->Format == Format_P010)
673         {
674             bitsPerPixel = 16;
675         }
676 
677         uint32_t alignWidth = MOS_ALIGN_CEIL(resDetails.dwWidth, DECOMPRESSION_WIDTH_ALIGNMENT_IN_BYTE*8/bitsPerPixel);
678         if (alignWidth <= resDetails.dwPitch*8/bitsPerPixel)
679         {
680             surface->dwWidth = alignWidth;
681         }
682         else
683         {
684             VPHAL_MEMORY_DECOMP_ASSERTMESSAGE("May got green line corruption.");
685             surface->dwWidth = resDetails.dwWidth;
686         }
687     }
688     else
689     {
690         surface->dwWidth                                        = resDetails.dwWidth;
691     }
692 #else
693     surface->dwWidth                                            = resDetails.dwWidth;
694 #endif
695     surface->dwHeight                                           = resDetails.dwHeight;
696     surface->dwPitch                                            = resDetails.dwPitch;
697     surface->dwDepth                                            = resDetails.dwDepth;
698     surface->bArraySpacing                                      = resDetails.bArraySpacing;
699     surface->TileType                                           = resDetails.TileType;
700     surface->TileModeGMM                                        = resDetails.TileModeGMM;
701     surface->bGMMTileEnabled                                    = resDetails.bGMMTileEnabled;
702     surface->bCompressible                                      = resDetails.bCompressible;
703     surface->bIsCompressed                                      = resDetails.bIsCompressed;
704     surface->dwOffset                                           = resDetails.RenderOffset.YUV.Y.BaseOffset;
705     surface->YPlaneOffset.iSurfaceOffset                        = resDetails.RenderOffset.YUV.Y.BaseOffset;
706     surface->YPlaneOffset.iXOffset                              = resDetails.RenderOffset.YUV.Y.XOffset;
707     surface->YPlaneOffset.iYOffset                              = resDetails.RenderOffset.YUV.Y.YOffset;
708     surface->UPlaneOffset.iSurfaceOffset                        = resDetails.RenderOffset.YUV.U.BaseOffset;
709     surface->UPlaneOffset.iXOffset                              = resDetails.RenderOffset.YUV.U.XOffset;
710     surface->UPlaneOffset.iYOffset                              = resDetails.RenderOffset.YUV.U.YOffset;
711     surface->VPlaneOffset.iSurfaceOffset                        = resDetails.RenderOffset.YUV.V.BaseOffset;
712     surface->VPlaneOffset.iXOffset                              = resDetails.RenderOffset.YUV.V.XOffset;
713     surface->VPlaneOffset.iYOffset                              = resDetails.RenderOffset.YUV.V.YOffset;
714     surface->dwSize                                             = (uint32_t)surface->OsResource.pGmmResInfo->GetSizeMainSurface();
715 
716     MOS_MEMCOMP_STATE mmcMode;
717 
718     MOS_ZeroMemory(&mmcMode, sizeof(mmcMode));
719     m_osInterface->pfnGetMemoryCompressionMode(m_osInterface, &surface->OsResource, &mmcMode);
720     surface->CompressionMode = (MOS_RESOURCE_MMC_MODE)mmcMode;
721 
722     if (mmcMode)
723     {
724         m_osInterface->pfnGetMemoryCompressionFormat(m_osInterface, &surface->OsResource, &surface->CompressionFormat);
725         if ((surface->TileType == MOS_TILE_Y ||
726              surface->TileType == MOS_TILE_YS))
727         {
728             surface->bCompressible   = true;
729             surface->bIsCompressed   = true;
730             surface->CompressionMode = (MOS_RESOURCE_MMC_MODE)mmcMode;
731         }
732     }
733 
734     return eStatus;
735 }
736 
737 #define SURFACE_DW_UY_OFFSET(pSurface) \
738     ((pSurface) != nullptr ? ((pSurface)->UPlaneOffset.iSurfaceOffset - (pSurface)->dwOffset) / (pSurface)->dwPitch + (pSurface)->UPlaneOffset.iYOffset : 0)
739 
740 #define SURFACE_DW_VY_OFFSET(pSurface) \
741     ((pSurface) != nullptr ? ((pSurface)->VPlaneOffset.iSurfaceOffset - (pSurface)->dwOffset) / (pSurface)->dwPitch + (pSurface)->VPlaneOffset.iYOffset : 0)
742 
SetupVeboxSurfaceState(PMHW_VEBOX_SURFACE_STATE_CMD_PARAMS mhwVeboxSurfaceStateCmdParams,PMOS_SURFACE inputSurface,PMOS_SURFACE outputSurface)743 MOS_STATUS MediaVeboxDecompState::SetupVeboxSurfaceState(
744     PMHW_VEBOX_SURFACE_STATE_CMD_PARAMS mhwVeboxSurfaceStateCmdParams,
745     PMOS_SURFACE                        inputSurface,
746     PMOS_SURFACE                        outputSurface)
747 {
748     MOS_STATUS              eStatus = MOS_STATUS_SUCCESS;
749     bool  inputIsLinearBuffer = false;
750     bool  outputIsLinearBuffer = false;
751     uint32_t bpp = 1;
752     uint32_t inputWidth = 0;
753     uint32_t outputWidth = 0;
754 
755     VPHAL_MEMORY_DECOMP_CHK_NULL_RETURN(inputSurface);
756     VPHAL_MEMORY_DECOMP_CHK_NULL_RETURN(mhwVeboxSurfaceStateCmdParams);
757 
758     MOS_ZeroMemory(mhwVeboxSurfaceStateCmdParams, sizeof(*mhwVeboxSurfaceStateCmdParams));
759 
760     mhwVeboxSurfaceStateCmdParams->SurfInput.bActive    = mhwVeboxSurfaceStateCmdParams->SurfOutput.bActive    = true;
761     mhwVeboxSurfaceStateCmdParams->SurfInput.dwBitDepth = mhwVeboxSurfaceStateCmdParams->SurfOutput.dwBitDepth = inputSurface->dwDepth;
762     mhwVeboxSurfaceStateCmdParams->SurfInput.dwHeight   = mhwVeboxSurfaceStateCmdParams->SurfOutput.dwHeight   =
763         MOS_MIN(inputSurface->dwHeight, ((outputSurface!= nullptr) ? outputSurface->dwHeight : inputSurface->dwHeight));
764     mhwVeboxSurfaceStateCmdParams->SurfInput.dwWidth    = mhwVeboxSurfaceStateCmdParams->SurfOutput.dwWidth    =
765         MOS_MIN(inputSurface->dwWidth, ((outputSurface != nullptr) ? outputSurface->dwWidth : inputSurface->dwWidth));
766     mhwVeboxSurfaceStateCmdParams->SurfInput.Format     = mhwVeboxSurfaceStateCmdParams->SurfOutput.Format     = inputSurface->Format;
767 
768     MOS_SURFACE inputDetails, outputDetails;
769     MOS_ZeroMemory(&inputDetails, sizeof(inputDetails));
770     MOS_ZeroMemory(&outputDetails, sizeof(outputDetails));
771     inputDetails.Format = Format_Invalid;
772     outputDetails.Format = Format_Invalid;
773 
774     if (inputSurface)
775     {
776         VPHAL_MEMORY_DECOMP_CHK_STATUS_RETURN(m_osInterface->pfnGetResourceInfo(
777             m_osInterface,
778             &inputSurface->OsResource,
779             &inputDetails));
780     }
781 
782     if (outputSurface)
783     {
784         VPHAL_MEMORY_DECOMP_CHK_STATUS_RETURN(m_osInterface->pfnGetResourceInfo(
785             m_osInterface,
786             &outputSurface->OsResource,
787             &outputDetails));
788 
789         // Following settings are enabled only when outputSurface is availble
790         inputIsLinearBuffer  = (inputDetails.dwHeight == 1) ? true : false;
791         outputIsLinearBuffer = (outputDetails.dwHeight == 1) ? true : false;
792 
793         inputWidth = inputSurface->dwWidth;
794         outputWidth = outputSurface->dwWidth;
795 
796         if (inputIsLinearBuffer)
797         {
798             bpp = outputDetails.dwPitch / outputDetails.dwWidth;
799             if (outputDetails.dwPitch % outputDetails.dwWidth != 0)
800             {
801                 inputWidth = outputDetails.dwPitch / bpp;
802             }
803         }
804         else if (outputIsLinearBuffer)
805         {
806             bpp = inputDetails.dwPitch / inputDetails.dwWidth;
807             if (inputDetails.dwPitch % inputDetails.dwWidth != 0)
808             {
809                 outputWidth = inputDetails.dwPitch / bpp;
810             }
811         }
812         else
813         {
814             VPHAL_MEMORY_DECOMP_NORMALMESSAGE("2D to 2D, no need for bpp setting.");
815         }
816     }
817 
818 
819     if (inputSurface->dwPitch > 0            &&
820        (inputSurface->Format == Format_P010  ||
821         inputSurface->Format == Format_P016  ||
822         inputSurface->Format == Format_NV12))
823     {
824         mhwVeboxSurfaceStateCmdParams->SurfInput.dwUYoffset = (!inputIsLinearBuffer) ? SURFACE_DW_UY_OFFSET(inputSurface) :
825                                                               inputSurface->dwHeight;
826 
827         if (outputSurface)
828         {
829             mhwVeboxSurfaceStateCmdParams->SurfOutput.dwUYoffset = (!outputIsLinearBuffer) ? SURFACE_DW_UY_OFFSET(outputSurface) :
830                                                                    outputSurface->dwHeight;
831         }
832         else
833         {
834             mhwVeboxSurfaceStateCmdParams->SurfOutput.dwUYoffset = mhwVeboxSurfaceStateCmdParams->SurfInput.dwUYoffset;
835         }
836     }
837 
838     mhwVeboxSurfaceStateCmdParams->SurfInput.rcMaxSrc.left   = mhwVeboxSurfaceStateCmdParams->SurfOutput.rcMaxSrc.left   = 0;
839     mhwVeboxSurfaceStateCmdParams->SurfInput.rcMaxSrc.right  = mhwVeboxSurfaceStateCmdParams->SurfOutput.rcMaxSrc.right  = (long)(mhwVeboxSurfaceStateCmdParams->SurfInput.dwWidth);
840     mhwVeboxSurfaceStateCmdParams->SurfInput.rcMaxSrc.top    = mhwVeboxSurfaceStateCmdParams->SurfOutput.rcMaxSrc.top    = 0;
841     mhwVeboxSurfaceStateCmdParams->SurfInput.rcMaxSrc.bottom = mhwVeboxSurfaceStateCmdParams->SurfOutput.rcMaxSrc.bottom = (long)(mhwVeboxSurfaceStateCmdParams->SurfInput.dwHeight);
842     mhwVeboxSurfaceStateCmdParams->bOutputValid = true;
843 
844     // if output surface is null, then Inplace resolve happens
845     if (!outputSurface)
846     {
847         mhwVeboxSurfaceStateCmdParams->SurfInput.TileType        = mhwVeboxSurfaceStateCmdParams->SurfOutput.TileType            = inputSurface->TileType;
848         mhwVeboxSurfaceStateCmdParams->SurfInput.TileModeGMM     = mhwVeboxSurfaceStateCmdParams->SurfOutput.TileModeGMM         = inputSurface->TileModeGMM;
849         mhwVeboxSurfaceStateCmdParams->SurfInput.bGMMTileEnabled = mhwVeboxSurfaceStateCmdParams->SurfOutput.bGMMTileEnabled     = inputSurface->bGMMTileEnabled;
850         mhwVeboxSurfaceStateCmdParams->SurfOutput.dwPitch        = mhwVeboxSurfaceStateCmdParams->SurfInput.dwPitch              = inputSurface->dwPitch;
851         mhwVeboxSurfaceStateCmdParams->SurfInput.pOsResource     = mhwVeboxSurfaceStateCmdParams->SurfOutput.pOsResource         = &(inputSurface->OsResource);
852         mhwVeboxSurfaceStateCmdParams->SurfInput.dwYoffset       = mhwVeboxSurfaceStateCmdParams->SurfOutput.dwYoffset           = inputSurface->YPlaneOffset.iYOffset;
853 
854         mhwVeboxSurfaceStateCmdParams->SurfInput.dwCompressionFormat = mhwVeboxSurfaceStateCmdParams->SurfOutput.dwCompressionFormat =
855             inputSurface->CompressionFormat;
856     }
857     else
858     // double buffer resolve
859     {
860         mhwVeboxSurfaceStateCmdParams->SurfInput.TileType             = inputSurface->TileType;
861         mhwVeboxSurfaceStateCmdParams->SurfInput.TileModeGMM          = inputSurface->TileModeGMM;
862         mhwVeboxSurfaceStateCmdParams->SurfInput.bGMMTileEnabled      = inputSurface->bGMMTileEnabled;
863         mhwVeboxSurfaceStateCmdParams->SurfOutput.TileType            = outputSurface->TileType;
864         mhwVeboxSurfaceStateCmdParams->SurfOutput.TileModeGMM         = outputSurface->TileModeGMM;
865         mhwVeboxSurfaceStateCmdParams->SurfOutput.bGMMTileEnabled     = outputSurface->bGMMTileEnabled;
866 
867         // When surface is 1D but processed as 2D, fake a min(pitch, width) is needed as the pitch API passed may less surface width in 1D surface
868         mhwVeboxSurfaceStateCmdParams->SurfInput.dwPitch              = (inputIsLinearBuffer) ?
869                                                                          MOS_MIN(inputWidth * bpp, inputSurface->dwPitch) : inputSurface->dwPitch;
870         mhwVeboxSurfaceStateCmdParams->SurfOutput.dwPitch             = (outputIsLinearBuffer) ?
871                                                                          MOS_MIN(outputWidth * bpp, outputSurface->dwPitch) : outputSurface->dwPitch;
872         mhwVeboxSurfaceStateCmdParams->SurfInput.pOsResource          = &(inputSurface->OsResource);
873         mhwVeboxSurfaceStateCmdParams->SurfOutput.pOsResource         = &(outputSurface->OsResource);
874         mhwVeboxSurfaceStateCmdParams->SurfInput.dwYoffset            = inputSurface->YPlaneOffset.iYOffset;
875         mhwVeboxSurfaceStateCmdParams->SurfOutput.dwYoffset           = outputSurface->YPlaneOffset.iYOffset;
876         mhwVeboxSurfaceStateCmdParams->SurfInput.dwCompressionFormat  = inputSurface->CompressionFormat;
877         mhwVeboxSurfaceStateCmdParams->SurfOutput.dwCompressionFormat = outputSurface->CompressionFormat;
878     }
879 
880     return eStatus;
881 }
882 
InitCommandBuffer(PMOS_COMMAND_BUFFER cmdBuffer)883 MOS_STATUS MediaVeboxDecompState::InitCommandBuffer(
884     PMOS_COMMAND_BUFFER               cmdBuffer)
885 {
886     PMOS_INTERFACE              pOsInterface;
887     MOS_STATUS                  eStatus = MOS_STATUS_SUCCESS;
888     uint32_t                    iRemaining;
889     RENDERHAL_GENERIC_PROLOG_PARAMS         GenericPrologParams = {};
890     PMOS_RESOURCE                           gpuStatusBuffer     = nullptr;
891 
892     //---------------------------------------------
893     VPHAL_MEMORY_DECOMP_CHK_NULL_RETURN(cmdBuffer);
894     VPHAL_MEMORY_DECOMP_CHK_NULL_RETURN(m_osInterface);
895     VPHAL_MEMORY_DECOMP_CHK_NULL_RETURN(m_mhwMiInterface);
896     //---------------------------------------------
897 
898     eStatus = MOS_STATUS_SUCCESS;
899     pOsInterface = m_osInterface;
900 
901     MOS_GPU_CONTEXT gpuContext = m_osInterface->pfnGetGpuContext(m_osInterface);
902 
903 #ifndef EMUL
904     if (pOsInterface->bEnableKmdMediaFrameTracking)
905     {
906         // Get GPU Status buffer
907         VPHAL_MEMORY_DECOMP_CHK_STATUS_RETURN(pOsInterface->pfnGetGpuStatusBufferResource(pOsInterface, gpuStatusBuffer));
908         VPHAL_MEMORY_DECOMP_CHK_NULL_RETURN(gpuStatusBuffer);
909         // Register the buffer
910         VPHAL_MEMORY_DECOMP_CHK_STATUS_RETURN(pOsInterface->pfnRegisterResource(pOsInterface, gpuStatusBuffer, true, true));
911 
912         GenericPrologParams.bEnableMediaFrameTracking      = true;
913         GenericPrologParams.presMediaFrameTrackingSurface  = gpuStatusBuffer;
914         GenericPrologParams.dwMediaFrameTrackingTag        = pOsInterface->pfnGetGpuStatusTag(pOsInterface, pOsInterface->CurrentGpuContextOrdinal);
915         GenericPrologParams.dwMediaFrameTrackingAddrOffset = pOsInterface->pfnGetGpuStatusTagOffset(pOsInterface, pOsInterface->CurrentGpuContextOrdinal);
916 
917         // Increment GPU Status Tag
918         pOsInterface->pfnIncrementGpuStatusTag(pOsInterface, pOsInterface->CurrentGpuContextOrdinal);
919     }
920 #endif
921 
922     if (GenericPrologParams.bEnableMediaFrameTracking)
923     {
924         VPHAL_MEMORY_DECOMP_CHK_NULL_RETURN(GenericPrologParams.presMediaFrameTrackingSurface);
925         cmdBuffer->Attributes.bEnableMediaFrameTracking       = GenericPrologParams.bEnableMediaFrameTracking;
926         cmdBuffer->Attributes.dwMediaFrameTrackingTag         = GenericPrologParams.dwMediaFrameTrackingTag;
927         cmdBuffer->Attributes.dwMediaFrameTrackingAddrOffset  = GenericPrologParams.dwMediaFrameTrackingAddrOffset;
928         cmdBuffer->Attributes.resMediaFrameTrackingSurface    = GenericPrologParams.presMediaFrameTrackingSurface;
929     }
930 
931     // initialize command buffer attributes
932     cmdBuffer->Attributes.bTurboMode = false;
933     cmdBuffer->Attributes.bMediaPreemptionEnabled = false;
934     cmdBuffer->Attributes.dwMediaFrameTrackingAddrOffset = 0;
935 
936     MHW_GENERIC_PROLOG_PARAMS genericPrologParams;
937     MOS_ZeroMemory(&genericPrologParams, sizeof(genericPrologParams));
938     genericPrologParams.pOsInterface = m_osInterface;
939     genericPrologParams.pvMiInterface = m_mhwMiInterface;
940     genericPrologParams.bMmcEnabled = true;
941 
942     VPHAL_MEMORY_DECOMP_CHK_STATUS_RETURN(Mhw_SendGenericPrologCmd(
943         cmdBuffer,
944         &genericPrologParams));
945 
946     return eStatus;
947 }
948 
IsFormatSupported(PMOS_SURFACE surface)949 bool MediaVeboxDecompState::IsFormatSupported(PMOS_SURFACE surface)
950 {
951     bool    bRet = false;
952 
953     if (surface->Format == Format_R10G10B10A2 ||
954         surface->Format == Format_B10G10R10A2 ||
955         surface->Format == Format_Y410 ||
956         surface->Format == Format_Y210)
957     {
958         // Re-map RGB10/RGB10/Y410/Y210 as AYUV
959         surface->Format = Format_AYUV;
960     }
961 
962     if (surface->Format == Format_A8 ||
963         surface->Format == Format_Y8 ||
964         surface->Format == Format_L8 ||
965         surface->Format == Format_P8 ||
966         surface->Format == Format_STMM)
967     {
968         surface->Format = Format_P8;
969     }
970 
971     if (surface->Format == Format_IMC3 ||
972         surface->Format == Format_444P ||
973         surface->Format == Format_422H ||
974         surface->Format == Format_422V ||
975         surface->Format == Format_411P ||
976         surface->Format == Format_411R ||
977         surface->Format == Format_444P ||
978         surface->Format == Format_RGBP ||
979         surface->Format == Format_BGRP ||
980         surface->Format == Format_400P ||
981         surface->Format == Format_420O )
982     {
983         surface->Format   = Format_P8;
984         surface->dwHeight = surface->dwSize / surface->dwPitch;
985     }
986 
987     if (IS_RGB64_FLOAT_FORMAT(surface->Format) ||
988         IS_RGB64_FORMAT(surface->Format)       ||
989         surface->Format == Format_G32R32F)
990     {
991         surface->Format = Format_Y416;
992     }
993 
994     // Check if Sample Format is supported for decompression
995     if (surface->Format != Format_NV12        &&
996         surface->Format != Format_AYUV        &&
997         surface->Format != Format_Y416        &&
998         surface->Format != Format_P010        &&
999         surface->Format != Format_P016        &&
1000         !IS_PA_FORMAT(surface->Format)        &&
1001         surface->Format != Format_A8R8G8B8    &&
1002         surface->Format != Format_A8B8G8R8    &&
1003         surface->Format != Format_X8R8G8B8    &&
1004         surface->Format != Format_X8B8G8R8    &&
1005         surface->Format != Format_P8          &&
1006         surface->Format != Format_Y16U)
1007     {
1008         VPHAL_MEMORY_DECOMP_NORMALMESSAGE("Unsupported Source Format '0x%08x' for VEBOX Decompression.", surface->Format);
1009         goto finish;
1010     }
1011 
1012     bRet = true;
1013 
1014 finish:
1015     return bRet;
1016 }
1017