xref: /aosp_15_r20/external/intel-media-driver/media_softlet/agnostic/common/shared/mediacopy/media_copy.cpp (revision ba62d9d3abf0e404f2022b4cd7a85e107f48596f)
1 /*
2 * Copyright (c) 2020-2021, 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_copy.cpp
24 //! \brief    Common interface and structure used in media copy
25 //! \details  Common interface and structure used in media copy which are platform independent
26 //!
27 
28 #include "media_copy.h"
29 #include "media_copy_common.h"
30 #include "media_debug_dumper.h"
31 #include "mhw_cp_interface.h"
32 #include "mos_utilities.h"
33 #include "mos_util_debug.h"
34 
35 #define BLT_MAX_WIDTH  (1 << 16) - 1
36 #define BLT_MAX_HEIGHT (1 << 16) - 1
37 #define BLT_MAX_PITCH  (1 << 18) - 1
38 
39 #define VE_MIN_WIDTH  64
40 #define VE_MIN_HEIGHT 32
41 
42 #define RENDER_MIN_WIDTH  16
43 #define RENDER_MIN_HEIGHT 16
44 
MediaCopyBaseState()45 MediaCopyBaseState::MediaCopyBaseState():
46     m_osInterface(nullptr)
47 {
48 
49 }
50 
~MediaCopyBaseState()51 MediaCopyBaseState::~MediaCopyBaseState()
52 {
53     if (m_osInterface)
54     {
55         m_osInterface->pfnDestroy(m_osInterface, false);
56         MOS_FreeMemory(m_osInterface);
57         m_osInterface = nullptr;
58     }
59 
60     if (m_inUseGPUMutex)
61     {
62         MosUtilities::MosDestroyMutex(m_inUseGPUMutex);
63         m_inUseGPUMutex = nullptr;
64     }
65 
66    #if (_DEBUG || _RELEASE_INTERNAL)
67     if (m_surfaceDumper != nullptr)
68     {
69        MOS_Delete(m_surfaceDumper);
70        m_surfaceDumper = nullptr;
71     }
72    #endif
73 }
74 
75 //!
76 //! \brief    init Media copy
77 //! \details  init func.
78 //! \param    none
79 //! \return   MOS_STATUS
80 //!           Return MOS_STATUS_SUCCESS if success, otherwise return failed.
81 //!
Initialize(PMOS_INTERFACE osInterface)82 MOS_STATUS MediaCopyBaseState::Initialize(PMOS_INTERFACE osInterface)
83 {
84     if (m_inUseGPUMutex == nullptr)
85     {
86         m_inUseGPUMutex     = MosUtilities::MosCreateMutex();
87         MCPY_CHK_NULL_RETURN(m_inUseGPUMutex);
88     }
89     MCPY_CHK_NULL_RETURN(m_osInterface);
90     Mos_SetVirtualEngineSupported(m_osInterface, true);
91     m_osInterface->pfnVirtualEngineSupported(m_osInterface, true, true);
92 
93 #if (_DEBUG || _RELEASE_INTERNAL)
94     if (m_surfaceDumper == nullptr)
95     {
96        m_surfaceDumper = MOS_New(CommonSurfaceDumper, osInterface);
97        MOS_OS_CHK_NULL_RETURN(m_surfaceDumper);
98     }
99     MediaUserSettingSharedPtr           userSettingPtr = nullptr;
100 
101     m_surfaceDumper->GetSurfaceDumpLocation(m_dumpLocation_in, mcpy_in);
102     m_surfaceDumper->GetSurfaceDumpLocation(m_dumpLocation_out, mcpy_out);
103     if (m_osInterface)
104     {
105         userSettingPtr = m_osInterface->pfnGetUserSettingInstance(m_osInterface);
106         ReadUserSettingForDebug(
107             userSettingPtr,
108             m_MCPYForceMode,
109             __MEDIA_USER_FEATURE_SET_MCPY_FORCE_MODE,
110             MediaUserSetting::Group::Device);
111 
112         ReadUserSettingForDebug(
113             userSettingPtr,
114             m_enableVeCopySmallRes,
115             __MEDIA_USER_FEATURE_ENABLE_VECOPY_SMALL_RESOLUTION,
116             MediaUserSetting::Group::Device);
117     }
118 #endif
119     return MOS_STATUS_SUCCESS;
120 }
121 
122 //!
123 //! \brief    check copy capability.
124 //! \details  to determine surface copy is supported or not.
125 //! \param    none
126 //! \return   MOS_STATUS
127 //!           Return MOS_STATUS_SUCCESS if support, otherwise return unspoort.
128 //!
CapabilityCheck(MOS_FORMAT format,MCPY_STATE_PARAMS & mcpySrc,MCPY_STATE_PARAMS & mcpyDst,MCPY_ENGINE_CAPS & caps,MCPY_METHOD preferMethod)129 MOS_STATUS MediaCopyBaseState::CapabilityCheck(
130     MOS_FORMAT         format,
131     MCPY_STATE_PARAMS &mcpySrc,
132     MCPY_STATE_PARAMS &mcpyDst,
133     MCPY_ENGINE_CAPS  &caps,
134     MCPY_METHOD        preferMethod)
135 {
136     // derivate class specific check. include HW engine avaliable check.
137     MCPY_CHK_STATUS_RETURN(FeatureSupport(mcpySrc.OsRes, mcpyDst.OsRes, mcpySrc, mcpyDst, caps));
138 
139     // common policy check
140     // legal check
141     // Blt engine does not support protection, allow the copy if dst is staging buffer in system mem
142     if (preferMethod == MCPY_METHOD_POWERSAVING &&
143         (mcpySrc.CpMode == MCPY_CPMODE_CP || mcpyDst.CpMode == MCPY_CPMODE_CP))
144     {
145         MCPY_ASSERTMESSAGE("illegal usage");
146         return MOS_STATUS_INVALID_PARAMETER;
147     }
148 
149     // vebox cap check.
150     if (!IsVeboxCopySupported(mcpySrc.OsRes, mcpyDst.OsRes) || // format check, implemented on Gen derivate class.
151         mcpySrc.bAuxSuface)
152     {
153         caps.engineVebox = false;
154         // temp solution for FP16 enabling on new platform
155         if (format == Format_A16B16G16R16F || format == Format_A16R16G16B16F)
156         {
157             return MOS_STATUS_UNIMPLEMENTED;
158         }
159     }
160 
161     // Eu cap check.
162     if (!RenderFormatSupportCheck(mcpySrc.OsRes, mcpyDst.OsRes) || // format check, implemented on Gen derivate class.
163         mcpySrc.bAuxSuface)
164     {
165         caps.engineRender = false;
166     }
167 
168     if (!caps.engineVebox && !caps.engineBlt && !caps.engineRender)
169     {
170         return MOS_STATUS_INVALID_PARAMETER; // unsupport copy on each hw engine.
171     }
172 
173     return MOS_STATUS_SUCCESS;
174 }
175 
176 //!
177 //! \brief    surface copy pre process.
178 //! \details  pre process before doing surface copy.
179 //! \param    none
180 //! \return   MOS_STATUS
181 //!           Return MOS_STATUS_SUCCESS if support, otherwise return unspoort.
182 //!
PreCheckCpCopy(MCPY_STATE_PARAMS src,MCPY_STATE_PARAMS dest,MCPY_METHOD preferMethod)183 MOS_STATUS MediaCopyBaseState::PreCheckCpCopy(
184     MCPY_STATE_PARAMS src, MCPY_STATE_PARAMS dest, MCPY_METHOD preferMethod)
185 {
186     if (preferMethod == MCPY_METHOD_POWERSAVING &&
187         (src.CpMode == MCPY_CPMODE_CP || dest.CpMode == MCPY_CPMODE_CP))
188     {
189         MCPY_ASSERTMESSAGE("BLT Copy with CP is not supported");
190         return MOS_STATUS_PLATFORM_NOT_SUPPORTED;
191     }
192 
193     return MOS_STATUS_SUCCESS;
194 }
195 
196 //!
197 //! \brief    dispatch copy task if support.
198 //! \details  dispatch copy task to HW engine (vebox, EU, Blt) based on customer and default.
199 //! \param    src
200 //!           [in] Pointer to source surface
201 //! \param    dst
202 //!           [in] Pointer to destination surface
203 //! \return   MOS_STATUS
204 //!           Return MOS_STATUS_SUCCESS if support, otherwise return unspoort.
205 //!
CopyEnigneSelect(MCPY_METHOD & preferMethod,MCPY_ENGINE & mcpyEngine,MCPY_ENGINE_CAPS & caps)206 MOS_STATUS MediaCopyBaseState::CopyEnigneSelect(MCPY_METHOD& preferMethod, MCPY_ENGINE& mcpyEngine, MCPY_ENGINE_CAPS& caps)
207 {
208     // driver should make sure there is at least one he can process copy even customer choice doesn't match caps.
209     switch (preferMethod)
210     {
211         case MCPY_METHOD_PERFORMANCE:
212             mcpyEngine = caps.engineRender?MCPY_ENGINE_RENDER:(caps.engineBlt ? MCPY_ENGINE_BLT : MCPY_ENGINE_VEBOX);
213             break;
214         case MCPY_METHOD_BALANCE:
215             mcpyEngine = caps.engineVebox?MCPY_ENGINE_VEBOX:(caps.engineBlt?MCPY_ENGINE_BLT:MCPY_ENGINE_RENDER);
216             break;
217         case MCPY_METHOD_POWERSAVING:
218         case MCPY_METHOD_DEFAULT:
219             mcpyEngine = caps.engineBlt?MCPY_ENGINE_BLT:(caps.engineVebox?MCPY_ENGINE_VEBOX:MCPY_ENGINE_RENDER);
220             break;
221         default:
222             break;
223     }
224 #if (_DEBUG || _RELEASE_INTERNAL)
225     if (MCPY_METHOD_PERFORMANCE == m_MCPYForceMode)
226     {
227         mcpyEngine = MCPY_ENGINE_RENDER;
228     }
229     else if (MCPY_METHOD_POWERSAVING == m_MCPYForceMode)
230     {
231         mcpyEngine = MCPY_ENGINE_BLT;
232     }
233     else if (MCPY_METHOD_BALANCE == m_MCPYForceMode)
234     {
235         mcpyEngine = MCPY_ENGINE_VEBOX;
236     }
237     else if (MCPY_METHOD_DEFAULT != m_MCPYForceMode)
238     {
239         return MOS_STATUS_INVALID_PARAMETER; // bypass copy engine, just let APP handle it.
240     }
241 #endif
242     return MOS_STATUS_SUCCESS;
243 }
244 
GetMinRequiredSurfaceSizeInBytes(uint32_t pitch,uint32_t height,MOS_FORMAT format)245 uint32_t GetMinRequiredSurfaceSizeInBytes(uint32_t pitch, uint32_t height, MOS_FORMAT format)
246 {
247     uint32_t nBytes = 0;
248     switch (format)
249     {
250     case Format_NV12:
251     case Format_YV12:
252     case Format_I420:
253     case Format_P010:
254     case Format_P016:
255         nBytes = pitch * height + (pitch >> 1) * (height >> 1) + (pitch >> 1) * (height >> 1);
256         break;
257     case Format_RGBP:
258     case Format_BGRP:
259         nBytes = pitch * height + pitch * height + pitch * height;
260         break;
261     case Format_Y410:
262     case Format_Y416:
263     case Format_Y210:
264     case Format_Y216:
265     case Format_YUY2:
266     case Format_R5G6B5:
267     case Format_R8G8B8:
268     case Format_A8R8G8B8:
269     case Format_A8B8G8R8:
270     case Format_X8R8G8B8:
271     case Format_X8B8G8R8:
272     case Format_AYUV:
273     case Format_R10G10B10A2:
274     case Format_B10G10R10A2:
275     case Format_P8:
276     case Format_L8:
277     case Format_A8:
278     case Format_Y16U:
279     case Format_A16B16G16R16F:
280     case Format_A16R16G16B16F:
281     case Format_A16B16G16R16:
282     case Format_A16R16G16B16:
283     case Format_IRW0:
284     case Format_IRW1:
285     case Format_IRW2:
286     case Format_IRW3:
287         nBytes = pitch * height;
288         break;
289     default:
290         MCPY_ASSERTMESSAGE("Unsupported format!");
291         break;
292     }
293     return nBytes;
294 }
295 
CheckResourceSizeValidForCopy(const MOS_SURFACE & res,const MCPY_ENGINE method)296 MOS_STATUS MediaCopyBaseState::CheckResourceSizeValidForCopy(const MOS_SURFACE &res, const MCPY_ENGINE method)
297 {
298     if (res.TileType != MOS_TILE_LINEAR)
299     {
300         return MOS_STATUS_SUCCESS;
301     }
302 
303     uint32_t nBytes = GetMinRequiredSurfaceSizeInBytes(res.dwPitch, res.dwHeight, res.Format);
304     if (nBytes == 0)
305     {
306         return MOS_STATUS_INVALID_PARAMETER;
307     }
308     if (res.dwSize < nBytes)
309     {
310         MT_ERR2(MT_MEDIA_COPY,
311         MT_MEDIA_COPY_DATASIZE, nBytes,
312         MT_MEDIA_COPY_DATASIZE, res.dwSize);
313 
314         return MOS_STATUS_INVALID_PARAMETER;
315     }
316 
317     if (method == MCPY_ENGINE_BLT)
318     {
319         if (res.dwPitch > BLT_MAX_PITCH || res.dwHeight > BLT_MAX_HEIGHT || res.dwWidth > BLT_MAX_WIDTH)
320         {
321             MT_ERR3(MT_MEDIA_COPY,
322                 MT_SURF_WIDTH, res.dwWidth,
323                 MT_SURF_HEIGHT, res.dwHeight,
324                 MT_SURF_PITCH, res.dwPitch);
325             MCPY_ASSERTMESSAGE("Surface size overflow! pitch %d, height %d, width %d", res.dwPitch, res.dwHeight, res.dwWidth);
326             return MOS_STATUS_INVALID_PARAMETER;
327         }
328     }
329 
330     if (method == MCPY_ENGINE_RENDER)
331     {
332         if (res.dwHeight < RENDER_MIN_HEIGHT || res.dwWidth < RENDER_MIN_WIDTH)
333         {
334             MT_ERR2(MT_MEDIA_COPY,
335                 MT_SURF_WIDTH, res.dwWidth,
336                 MT_SURF_HEIGHT, res.dwHeight);
337             MCPY_ASSERTMESSAGE("Surface size not meet min requirement! height %d, width %d", res.dwHeight, res.dwWidth);
338             return MOS_STATUS_INVALID_PARAMETER;
339         }
340     }
341 
342     if (method == MCPY_ENGINE_VEBOX)
343     {
344 #if (_DEBUG || _RELEASE_INTERNAL)
345         if (!m_enableVeCopySmallRes)
346 #endif
347         {
348             if (res.dwHeight < VE_MIN_HEIGHT || res.dwWidth < VE_MIN_WIDTH)
349             {
350                 MT_ERR2(MT_MEDIA_COPY,
351                     MT_SURF_WIDTH, res.dwWidth,
352                     MT_SURF_HEIGHT, res.dwHeight);
353                 MCPY_ASSERTMESSAGE("Surface size not meet min requirement! height %d, width %d", res.dwHeight, res.dwWidth);
354                 return MOS_STATUS_INVALID_PARAMETER;
355             }
356         }
357     }
358 
359     return MOS_STATUS_SUCCESS;
360 }
361 
ValidateResource(const MOS_SURFACE & src,const MOS_SURFACE & dst,MCPY_ENGINE method)362 MOS_STATUS MediaCopyBaseState::ValidateResource(const MOS_SURFACE &src, const MOS_SURFACE &dst, MCPY_ENGINE method)
363 {
364     // For CP buffer copy, CP will handle the overflown size, skip size check
365     if (src.OsResource.pGmmResInfo->GetResourceType() == RESOURCE_BUFFER &&
366         dst.OsResource.pGmmResInfo->GetResourceType() == RESOURCE_BUFFER &&
367         method == MCPY_ENGINE_BLT)
368     {
369         return MOS_STATUS_SUCCESS;
370     }
371 
372     MCPY_CHK_STATUS_RETURN(CheckResourceSizeValidForCopy(src, method));
373     MCPY_CHK_STATUS_RETURN(CheckResourceSizeValidForCopy(dst, method));
374 
375     return MOS_STATUS_SUCCESS;
376 }
377 
378 //!
379 //! \brief    surface copy func.
380 //! \details  copy surface.
381 //! \param    src
382 //!           [in] Pointer to source surface
383 //! \param    dst
384 //!           [in] Pointer to destination surface
385 //! \return   MOS_STATUS
386 //!           Return MOS_STATUS_SUCCESS if support, otherwise return unspoort.
387 //!
SurfaceCopy(PMOS_RESOURCE src,PMOS_RESOURCE dst,MCPY_METHOD preferMethod)388 MOS_STATUS MediaCopyBaseState::SurfaceCopy(PMOS_RESOURCE src, PMOS_RESOURCE dst, MCPY_METHOD preferMethod)
389 {
390     MOS_TraceEventExt(EVENT_MEDIA_COPY, EVENT_TYPE_START, nullptr, 0, nullptr, 0);
391     MOS_STATUS eStatus = MOS_STATUS_SUCCESS;
392 
393     MOS_SURFACE SrcResDetails, DstResDetails;
394     MOS_ZeroMemory(&SrcResDetails, sizeof(MOS_SURFACE));
395     MOS_ZeroMemory(&DstResDetails, sizeof(MOS_SURFACE));
396     SrcResDetails.Format     = Format_Invalid;
397     SrcResDetails.OsResource = *src;
398     DstResDetails.Format     = Format_Invalid;
399     DstResDetails.OsResource = *dst;
400 
401     MCPY_STATE_PARAMS     mcpySrc = {nullptr, MOS_MMC_DISABLED, MOS_TILE_LINEAR, MCPY_CPMODE_CLEAR, false};
402     MCPY_STATE_PARAMS     mcpyDst = {nullptr, MOS_MMC_DISABLED, MOS_TILE_LINEAR, MCPY_CPMODE_CLEAR, false};
403     MCPY_ENGINE           mcpyEngine = MCPY_ENGINE_BLT;
404     MCPY_ENGINE_CAPS      mcpyEngineCaps = {1, 1, 1, 1};
405 
406     MCPY_CHK_STATUS_RETURN(m_osInterface->pfnGetResourceInfo(m_osInterface, src, &SrcResDetails));
407     MCPY_CHK_STATUS_RETURN(m_osInterface->pfnGetMemoryCompressionMode(m_osInterface, src, (PMOS_MEMCOMP_STATE)&(mcpySrc.CompressionMode)));
408     mcpySrc.CpMode   = src->pGmmResInfo->GetSetCpSurfTag(false, 0)?MCPY_CPMODE_CP:MCPY_CPMODE_CLEAR;
409     mcpySrc.TileMode = SrcResDetails.TileType;
410     mcpySrc.OsRes    = src;
411     MCPY_NORMALMESSAGE("input surface's format %d, width %d; hight %d, pitch %d, tiledmode %d, mmc mode %d, cp mode %d, ResType %d, preferMethod %d",
412         SrcResDetails.Format,
413         SrcResDetails.dwWidth,
414         SrcResDetails.dwHeight,
415         SrcResDetails.dwPitch,
416         mcpySrc.TileMode,
417         mcpySrc.CompressionMode,
418         mcpySrc.CpMode,
419         src->pGmmResInfo->GetResourceType(),
420         preferMethod);
421     MT_LOG7(MT_MEDIA_COPY, MT_NORMAL,
422         MT_SURF_PITCH,          SrcResDetails.dwPitch,
423         MT_SURF_HEIGHT,         SrcResDetails.dwHeight,
424         MT_SURF_WIDTH,          SrcResDetails.dwWidth,
425         MT_SURF_MOS_FORMAT,     SrcResDetails.Format,
426         MT_MEDIA_COPY_DATASIZE, SrcResDetails.dwSize,
427         MT_SURF_TILE_TYPE,      SrcResDetails.TileType,
428         MT_SURF_COMP_MODE,      mcpySrc.CompressionMode);
429 
430     MCPY_CHK_STATUS_RETURN(m_osInterface->pfnGetResourceInfo(m_osInterface, dst, &DstResDetails));
431     MCPY_CHK_STATUS_RETURN(m_osInterface->pfnGetMemoryCompressionMode(m_osInterface,dst, (PMOS_MEMCOMP_STATE) &(mcpyDst.CompressionMode)));
432     mcpyDst.CpMode   = dst->pGmmResInfo->GetSetCpSurfTag(false, 0)?MCPY_CPMODE_CP:MCPY_CPMODE_CLEAR;
433     mcpyDst.TileMode = DstResDetails.TileType;
434     mcpyDst.OsRes    = dst;
435     MCPY_NORMALMESSAGE("Output surface's format %d, width %d; hight %d, pitch %d, tiledmode %d, mmc mode %d,cp mode %d, ResType %d",
436         DstResDetails.Format,
437         DstResDetails.dwWidth,
438         DstResDetails.dwHeight,
439         DstResDetails.dwPitch,
440         mcpyDst.TileMode,
441         mcpyDst.CompressionMode,
442         mcpyDst.CpMode,
443         dst->pGmmResInfo->GetResourceType());
444     MT_LOG7(MT_MEDIA_COPY, MT_NORMAL,
445         MT_SURF_PITCH,          DstResDetails.dwPitch,
446         MT_SURF_HEIGHT,         DstResDetails.dwHeight,
447         MT_SURF_WIDTH,          DstResDetails.dwWidth,
448         MT_SURF_MOS_FORMAT,     DstResDetails.Format,
449         MT_MEDIA_COPY_DATASIZE, DstResDetails.dwSize,
450         MT_SURF_TILE_TYPE,      DstResDetails.TileType,
451         MT_SURF_COMP_MODE,      mcpyDst.CompressionMode);
452 
453 #if (_DEBUG || _RELEASE_INTERNAL) && !defined(LINUX)
454     TRACEDATA_MEDIACOPY eventData = {0};
455     TRACEDATA_MEDIACOPY_INIT(
456         eventData,
457         src->AllocationInfo.m_AllocationHandle,
458         SrcResDetails.dwWidth,
459         SrcResDetails.dwHeight,
460         SrcResDetails.Format,
461         *((int64_t *)&src->pGmmResInfo->GetResFlags().Gpu),
462         *((int64_t *)&src->pGmmResInfo->GetResFlags().Info),
463         src->pGmmResInfo->GetSetCpSurfTag(0, 0),
464         dst->AllocationInfo.m_AllocationHandle,
465         DstResDetails.dwWidth,
466         DstResDetails.dwHeight,
467         DstResDetails.Format,
468         *((int64_t *)&dst->pGmmResInfo->GetResFlags().Gpu),
469         *((int64_t *)&dst->pGmmResInfo->GetResFlags().Info),
470         dst->pGmmResInfo->GetSetCpSurfTag(0, 0)
471     );
472 
473     MOS_TraceEventExt(EVENT_MEDIA_COPY, EVENT_TYPE_INFO, &eventData, sizeof(eventData), nullptr, 0);
474 #endif
475 
476     MCPY_CHK_STATUS_RETURN(PreCheckCpCopy(mcpySrc, mcpyDst, preferMethod));
477 
478     MCPY_CHK_STATUS_RETURN(CapabilityCheck(SrcResDetails.Format,
479         mcpySrc, mcpyDst,
480         mcpyEngineCaps, preferMethod));
481 
482     CopyEnigneSelect(preferMethod, mcpyEngine, mcpyEngineCaps);
483 
484     MCPY_CHK_STATUS_RETURN(ValidateResource(SrcResDetails, DstResDetails, mcpyEngine));
485 
486     MCPY_CHK_STATUS_RETURN(TaskDispatch(mcpySrc, mcpyDst, mcpyEngine));
487 
488     MOS_TraceEventExt(EVENT_MEDIA_COPY, EVENT_TYPE_END, nullptr, 0, nullptr, 0);
489     return eStatus;
490 }
491 
TaskDispatch(MCPY_STATE_PARAMS mcpySrc,MCPY_STATE_PARAMS mcpyDst,MCPY_ENGINE mcpyEngine)492 MOS_STATUS MediaCopyBaseState::TaskDispatch(MCPY_STATE_PARAMS mcpySrc, MCPY_STATE_PARAMS mcpyDst, MCPY_ENGINE mcpyEngine)
493 {
494     MOS_STATUS eStatus = MOS_STATUS_SUCCESS;
495 
496 
497 #if (_DEBUG || _RELEASE_INTERNAL)
498     MOS_SURFACE sourceSurface = {};
499     MOS_SURFACE targetSurface = {};
500 
501     targetSurface.Format = Format_Invalid;
502     targetSurface.OsResource = *mcpyDst.OsRes;
503 
504 #if !defined(LINUX) && !defined(ANDROID) && !EMUL
505     MOS_ZeroMemory(&targetSurface.OsResource.AllocationInfo, sizeof(SResidencyInfo));
506 #endif
507 
508     sourceSurface.Format = Format_Invalid;
509     sourceSurface.OsResource = *mcpySrc.OsRes;
510 
511     m_osInterface->pfnGetResourceInfo(m_osInterface, &sourceSurface.OsResource, &sourceSurface);
512     m_osInterface->pfnGetResourceInfo(m_osInterface, &targetSurface.OsResource, &targetSurface);
513 
514     // Set the dump location like "dumpLocation before MCPY=path_to_dump_folder" in user feature configure file
515     // Otherwise, the surface may not be dumped
516     // Only dump linear surface
517     if (m_surfaceDumper && mcpySrc.TileMode == MOS_TILE_LINEAR)
518     {
519         if ((*m_dumpLocation_in == '\0') || (*m_dumpLocation_in == ' '))
520         {
521             MCPY_NORMALMESSAGE("Invalid dump location set, the surface will not be dumped");
522         }
523         else
524         {
525             m_surfaceDumper->DumpSurfaceToFile(m_osInterface, &sourceSurface, m_dumpLocation_in, m_surfaceDumper->m_frameNum, true, false, nullptr);
526         }
527     }
528 #endif
529 
530     MosUtilities::MosLockMutex(m_inUseGPUMutex);
531     switch(mcpyEngine)
532     {
533         case MCPY_ENGINE_VEBOX:
534             eStatus = MediaVeboxCopy(mcpySrc.OsRes, mcpyDst.OsRes);
535             break;
536         case MCPY_ENGINE_BLT:
537             if ((mcpyDst.TileMode != MOS_TILE_LINEAR) && (mcpyDst.CompressionMode == MOS_MMC_RC))
538             {
539                 MCPY_NORMALMESSAGE("mmc on, mcpyDst.TileMode= %d, mcpyDst.CompressionMode = %d", mcpyDst.TileMode, mcpyDst.CompressionMode);
540                 eStatus = m_osInterface->pfnDecompResource(m_osInterface, mcpyDst.OsRes);
541                 if (MOS_STATUS_SUCCESS != eStatus)
542                 {
543                     MosUtilities::MosUnlockMutex(m_inUseGPUMutex);
544                     MCPY_CHK_STATUS_RETURN(eStatus);
545                 }
546             }
547             eStatus = MediaBltCopy(mcpySrc.OsRes, mcpyDst.OsRes);
548             break;
549         case MCPY_ENGINE_RENDER:
550             eStatus = MediaRenderCopy(mcpySrc.OsRes, mcpyDst.OsRes);
551             break;
552         default:
553             break;
554     }
555     MosUtilities::MosUnlockMutex(m_inUseGPUMutex);
556 
557 #if (_DEBUG || _RELEASE_INTERNAL)
558     if (m_bRegReport)
559     {
560         std::string copyEngine = mcpyEngine ?(mcpyEngine == MCPY_ENGINE_BLT?"BLT":"Render"):"VeBox";
561         MediaUserSettingSharedPtr userSettingPtr = m_osInterface->pfnGetUserSettingInstance(m_osInterface);
562         ReportUserSettingForDebug(
563             userSettingPtr,
564             __MEDIA_USER_FEATURE_MCPY_MODE,
565             copyEngine,
566             MediaUserSetting::Group::Device);
567     }
568 
569     // Set the dump location like "dumpLocation after MCPY=path_to_dump_folder" in user feature configure file
570     // Otherwise, the surface may not be dumped
571     // Only dump linear surface
572     if (m_surfaceDumper && mcpyDst.TileMode == MOS_TILE_LINEAR)
573     {
574         if ((*m_dumpLocation_out == '\0') || (*m_dumpLocation_out == ' '))
575         {
576             MCPY_NORMALMESSAGE("Invalid dump location set, the surface will not be dumped");
577         }
578         else
579         {
580             m_surfaceDumper->DumpSurfaceToFile(m_osInterface, &targetSurface, m_dumpLocation_out, m_surfaceDumper->m_frameNum, true, false, nullptr);
581         }
582         m_surfaceDumper->m_frameNum++;
583     }
584 #endif
585     MCPY_NORMALMESSAGE("Media Copy works on %s Engine", mcpyEngine ?(mcpyEngine == MCPY_ENGINE_BLT?"BLT":"Render"):"VeBox");
586 
587     return eStatus;
588 }
589 
590 //!
591 //! \brief    aux surface copy.
592 //! \details  copy surface.
593 //! \param    src
594 //!           [in] Pointer to source surface
595 //! \param    dst
596 //!           [in] Pointer to destination surface
597 //! \return   MOS_STATUS
598 //!           Return MOS_STATUS_SUCCESS if support, otherwise return unspoort.
599 //!
AuxCopy(PMOS_RESOURCE src,PMOS_RESOURCE dst)600 MOS_STATUS MediaCopyBaseState::AuxCopy(PMOS_RESOURCE src, PMOS_RESOURCE dst)
601 {
602     // only support form Gen12+, will implement on deriavete class.
603     MCPY_ASSERTMESSAGE("doesn't support");
604     return MOS_STATUS_INVALID_HANDLE;
605 }
606 
GetMosInterface()607 PMOS_INTERFACE MediaCopyBaseState::GetMosInterface()
608 {
609     return m_osInterface;
610 }