xref: /aosp_15_r20/external/intel-media-driver/media_driver/agnostic/common/vp/hal/vphal.cpp (revision ba62d9d3abf0e404f2022b4cd7a85e107f48596f)
1 /*
2 * Copyright (c) 2009-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     vphal.cpp
24 //! \brief    Vphal Interface Definition
25 //! \details  Vphal Interface Definition Including:
26 //!           const and function
27 //!
28 #include "vphal.h"
29 #include "mos_os.h"
30 #include "mos_interface.h"
31 #include "mhw_vebox.h"
32 #include "renderhal_legacy.h"
33 #include "vphal_renderer.h"
34 #include "mos_solo_generic.h"
35 #include "media_interfaces_vphal.h"
36 #include "media_interfaces_mhw.h"
37 #include "mhw_vebox_itf.h"
38 #include "mos_oca_rtlog_mgr.h"
39 #include "vp_user_setting.h"
40 
41 //!
42 //! \brief    Allocate VPHAL Resources
43 //! \details  Allocate VPHAL Resources
44 //!           - Allocate and initialize HW states
45 //!           - Allocate and initialize renderer states
46 //! \param    [in] pVpHalSettings
47 //!           Pointer to VPHAL Settings
48 //! \return   MOS_STATUS
49 //!           Return MOS_STATUS_SUCCESS if successful, otherwise failed
50 //!
Allocate(const VphalSettings * pVpHalSettings)51 MOS_STATUS VphalState::Allocate(
52     const VphalSettings       *pVpHalSettings)
53 {
54     MHW_VEBOX_GPUNODE_LIMIT     GpuNodeLimit;
55     RENDERHAL_SETTINGS_LEGACY   RenderHalSettings;
56     MOS_GPU_NODE                VeboxGpuNode;
57     MOS_GPU_CONTEXT             VeboxGpuContext;
58     bool                        checkGpuCtxOverwriten = false;
59     bool                        addGpuCtxToCheckList  = false;
60     MOS_STATUS                  eStatus;
61 
62     VPHAL_PUBLIC_CHK_NULL(m_osInterface);
63     VPHAL_PUBLIC_CHK_NULL(pVpHalSettings);
64     VPHAL_PUBLIC_CHK_NULL(m_renderHal);
65 
66     m_clearVideoViewMode = pVpHalSettings->clearVideoViewMode;
67 
68     if ((MEDIA_IS_SKU(m_skuTable, FtrVERing) ||
69          MEDIA_IS_SKU(m_skuTable, FtrSFCPipe)) &&
70         !m_clearVideoViewMode)
71     {
72         MhwInterfaces *             mhwInterfaces = nullptr;
73         MhwInterfaces::CreateParams params;
74         MOS_ZeroMemory(&params, sizeof(params));
75         params.Flags.m_sfc   = MEDIA_IS_SKU(m_skuTable, FtrSFCPipe);
76         params.Flags.m_vebox = MEDIA_IS_SKU(m_skuTable, FtrVERing);
77 
78         mhwInterfaces = MhwInterfaces::CreateFactory(params, m_osInterface);
79         if (mhwInterfaces)
80         {
81             SetMhwVeboxInterface(mhwInterfaces->m_veboxInterface);
82             SetMhwSfcInterface(mhwInterfaces->m_sfcInterface);
83 
84             // MhwInterfaces always create CP and MI interfaces, so we have to delete those we don't need.
85             MOS_Delete(mhwInterfaces->m_miInterface);
86             m_osInterface->pfnDeleteMhwCpInterface(mhwInterfaces->m_cpInterface);
87             mhwInterfaces->m_cpInterface = nullptr;
88             MOS_Delete(mhwInterfaces);
89         }
90         else
91         {
92             VPHAL_DEBUG_ASSERTMESSAGE("Allocate MhwInterfaces failed");
93             eStatus = MOS_STATUS_NO_SPACE;
94             MT_ERR1(MT_VP_HAL_INIT, MT_CODE_LINE, __LINE__);
95         }
96     }
97 
98     if (IsApoEnabled() &&
99         m_osInterface->apoMosEnabled &&
100         m_osInterface->bSetHandleInvalid)
101     {
102         checkGpuCtxOverwriten = true;
103     }
104     addGpuCtxToCheckList = checkGpuCtxOverwriten && !IsGpuContextReused(m_renderGpuContext);
105 
106     if (IsRenderContextBasedSchedulingNeeded())
107     {
108         Mos_SetVirtualEngineSupported(m_osInterface, true);
109         m_osInterface->pfnVirtualEngineSupported(m_osInterface, true, true);
110     }
111 
112     // Create Render GPU Context
113     {
114         MOS_GPUCTX_CREATOPTIONS_ENHANCED createOption = {};
115         VPHAL_PUBLIC_CHK_STATUS(m_osInterface->pfnCreateGpuContext(
116             m_osInterface,
117             m_renderGpuContext,
118             m_renderGpuNode,
119             &createOption));
120     }
121 
122     // Set current GPU context
123     VPHAL_PUBLIC_CHK_STATUS(m_osInterface->pfnSetGpuContext(
124         m_osInterface,
125         m_renderGpuContext));
126 
127     // Add gpu context entry, including stream 0 gpu contexts
128     // In legacy path, stream 0 gpu contexts could be reused, and will keep these stream 0 gpu contexts alive
129     // But its mapping relation could be overwritten in APO path
130     // Now, don't reuse these stream 0 gpu contexts overwritten by MediaContext in APO path
131     // Can not add reused GPU context
132     if (addGpuCtxToCheckList)
133     {
134         AddGpuContextToCheckList(m_renderGpuContext);
135     }
136 
137     // Register Render GPU context with the event
138     VPHAL_PUBLIC_CHK_STATUS(m_osInterface->pfnRegisterBBCompleteNotifyEvent(
139         m_osInterface,
140         m_renderGpuContext));
141 
142     if (MEDIA_IS_SKU(m_skuTable, FtrVERing) && m_veboxInterface && !m_clearVideoViewMode)
143     {
144         GpuNodeLimit.bSfcInUse         = MEDIA_IS_SKU(m_skuTable, FtrSFCPipe);
145 
146         if (m_veboxItf)
147         {
148             // Check GPU Node decide logic together in this function
149             VPHAL_HW_CHK_STATUS(m_veboxItf->FindVeboxGpuNodeToUse(&GpuNodeLimit));
150 
151             VeboxGpuNode    = (MOS_GPU_NODE)(GpuNodeLimit.dwGpuNodeToUse);
152             VeboxGpuContext = (VeboxGpuNode == MOS_GPU_NODE_VE) ? MOS_GPU_CONTEXT_VEBOX : MOS_GPU_CONTEXT_VEBOX2;
153 
154             VPHAL_PUBLIC_CHK_STATUS(m_veboxItf->CreateGpuContext(
155                 m_osInterface,
156                 VeboxGpuContext,
157                 VeboxGpuNode));
158         }
159 
160         // Check GPU Node decide logic together in this function
161         VPHAL_HW_CHK_STATUS(m_veboxInterface->FindVeboxGpuNodeToUse(&GpuNodeLimit));
162 
163         VeboxGpuNode    = (MOS_GPU_NODE)(GpuNodeLimit.dwGpuNodeToUse);
164         VeboxGpuContext = (VeboxGpuNode == MOS_GPU_NODE_VE) ? MOS_GPU_CONTEXT_VEBOX : MOS_GPU_CONTEXT_VEBOX2;
165 
166         addGpuCtxToCheckList = checkGpuCtxOverwriten && !IsGpuContextReused(VeboxGpuContext);
167 
168         // Create VEBOX/VEBOX2 Context
169         VPHAL_PUBLIC_CHK_STATUS(m_veboxInterface->CreateGpuContext(
170             m_osInterface,
171             VeboxGpuContext,
172             VeboxGpuNode));
173 
174         // Add gpu context entry, including stream 0 gpu contexts
175         if (addGpuCtxToCheckList)
176         {
177             AddGpuContextToCheckList(VeboxGpuContext);
178         }
179 
180         // Register Vebox GPU context with the Batch Buffer completion event
181         // Ignore if creation fails
182         VPHAL_PUBLIC_CHK_STATUS(m_osInterface->pfnRegisterBBCompleteNotifyEvent(
183             m_osInterface,
184             MOS_GPU_CONTEXT_VEBOX));
185     }
186 
187     // Allocate and initialize HW states
188     RenderHalSettings.iMediaStates  = pVpHalSettings->mediaStates;
189     VPHAL_PUBLIC_CHK_STATUS(m_renderHal->pfnInitialize(m_renderHal, &RenderHalSettings));
190 
191     if (!m_clearVideoViewMode)
192     {
193         if (m_veboxItf)
194         {
195             const MHW_VEBOX_HEAP *veboxHeap = nullptr;
196             m_veboxItf->GetVeboxHeapInfo(&veboxHeap);
197             uint32_t uiNumInstances = m_veboxItf->GetVeboxNumInstances();
198 
199             if (uiNumInstances > 0 &&
200                 veboxHeap == nullptr)
201             {
202                 // Allocate VEBOX Heap
203                 VPHAL_PUBLIC_CHK_STATUS(m_veboxItf->CreateHeap());
204             }
205         }
206 
207         if (m_veboxInterface &&
208             m_veboxInterface->m_veboxSettings.uiNumInstances > 0 &&
209             m_veboxInterface->m_veboxHeap == nullptr)
210         {
211             VPHAL_PUBLIC_CHK_STATUS(m_veboxInterface->CreateHeap());
212         }
213     }
214 
215     // Create renderer
216     VPHAL_RENDER_CHK_STATUS(CreateRenderer());
217 
218     // Allocate and initialize renderer states
219     VPHAL_PUBLIC_CHK_STATUS(m_renderer->Initialize(pVpHalSettings, IsApoEnabled()));
220 
221 finish:
222     return eStatus;
223 }
224 
225 //!
226 //! \brief    Check if need to apply AVS for specified surface
227 //! \details  Check if need to apply AVS for specified surface
228 //! \param    pSurf
229 //!           [in] Pointer to VPHAL_SURFACE
230 //! \return   bool
231 //!           Return true if the input surface needs AVS scaling
232 //!
IsSurfNeedAvs(PVPHAL_SURFACE pSurf)233 static bool IsSurfNeedAvs(
234     PVPHAL_SURFACE pSurf)
235 {
236     VPHAL_PUBLIC_CHK_NULL_NO_STATUS(pSurf);
237 
238     // Not perform AVS for surface with alpha channel.
239     if (IS_ALPHA_YUV_FORMAT(pSurf->Format))
240     {
241         return false;
242     }
243 
244     if (pSurf->SurfType == SURF_IN_PRIMARY ||
245         pSurf->SurfType == SURF_IN_SUBSTREAM)
246     {
247         if (pSurf->pBlendingParams)
248         {
249             return false;
250         }
251 
252         if (IS_YUV_FORMAT(pSurf->Format))
253         {
254             // Not perform AVS for surface with VPHAL_SCALING_NEAREST
255             // or VPHAL_SCALING_BILINEAR scaling mode.
256             if (pSurf->ScalingMode == VPHAL_SCALING_AVS ||
257                 pSurf->ScalingMode == VPHAL_SCALING_ADV_QUALITY)
258             {
259                 return true;
260             }
261         }
262     }
263 finish:
264     return false;
265 }
266 
267 //!
268 //! \brief    Check if all surfaces format order in pcRenderParams is suitable to enable multiple avs rendering (YUV is prior than RGB)
269 //! \details  In VpHal_RenderWithAvsForMultiStreams() we group YUV surfaces in phase one and the others in phase two.
270 //!           However, if there are 2+ overlapped source surfaces, e.g., pSrc[0]=B8G8R8A8 and pSrc[1]=NV12.
271 //!           We don't enable multiple avs rendering for such case since we expect pSrc[1] is above pSrc[0] on target.
272 //!           If multiple avs rendering is enabled, the compositing order is reverse and turns out pSrc[1] is below pSrc[0],
273 //!           which is the case need to prevent.
274 //! \param    pcRenderParams
275 //!           [in] Pointer to const VPHAL_RENDER_PARAMS
276 //! \return   bool
277 //!           Allow to enable multiple avs rendering
278 //!
IsYuvPriorRgbInCompositeOrder(PCVPHAL_RENDER_PARAMS pcRenderParams)279 static bool IsYuvPriorRgbInCompositeOrder(
280     PCVPHAL_RENDER_PARAMS   pcRenderParams)
281 {
282     bool     bHasRgbSurface = false;
283     uint32_t uiLastYuvIdx   = 0;
284     uint32_t uiFirstRgbIdx  = 0;
285     uint32_t iSourceIdx;
286 
287     VPHAL_PUBLIC_CHK_NULL_NO_STATUS(pcRenderParams);
288 
289     for (iSourceIdx = 0; iSourceIdx < pcRenderParams->uSrcCount; iSourceIdx++)
290     {
291         PVPHAL_SURFACE pSurf = pcRenderParams->pSrc[iSourceIdx];
292         if (IsSurfNeedAvs(pSurf))
293         {
294                 uiLastYuvIdx = iSourceIdx;
295         }
296         else if (!bHasRgbSurface)
297         {
298                 bHasRgbSurface = true;
299                 uiFirstRgbIdx  = iSourceIdx;
300         }
301     }
302 
303 finish:
304     if (!bHasRgbSurface)
305     {   // return true if not contain any RGB surface
306         return true;
307     }
308     return (uiLastYuvIdx < uiFirstRgbIdx);
309 }
310 
311 //!
312 //! \brief    Check if need to apply AVS scaling for multiple surfaces
313 //! \details  Check if need to apply AVS scaling for multiple surfaces
314 //! \param    pcRenderParams
315 //!           [in] Pointer to const VPHAL_RENDER_PARAMS
316 //! \return   bool
317 //!           Return true if neeeded to enable AVS for all primary surfaces.
318 //!
VpHal_IsAvsSampleForMultiStreamsEnabled(PCVPHAL_RENDER_PARAMS pcRenderParams)319 static bool VpHal_IsAvsSampleForMultiStreamsEnabled(
320     PCVPHAL_RENDER_PARAMS   pcRenderParams)
321 {
322     uint32_t uSourceIdx;
323     uint32_t uSourceBIdx;
324     uint32_t uAvsSurfaceCnt            = 0;
325     bool     bEnableAvsForMultiSurface = false;
326 
327     VPHAL_PUBLIC_CHK_NULL_NO_STATUS(pcRenderParams);
328 
329     //disable if only one, zero or invalid number source
330     if (pcRenderParams->uSrcCount <= 1 ||
331         pcRenderParams->uSrcCount > VPHAL_MAX_SOURCES)
332     {
333        goto finish;
334     }
335 
336     for (uSourceIdx = 0; uSourceIdx < pcRenderParams->uSrcCount; uSourceIdx++)
337     {
338         PVPHAL_SURFACE pSrcSurf = pcRenderParams->pSrc[uSourceIdx];
339         if (pSrcSurf && pSrcSurf->SurfType == SURF_IN_PRIMARY)
340         {
341             // VPHAL_SCALING_PREFER_SFC_FOR_VEBOX means scaling mode is FastMode, don't apply AVS for multiples
342             if (pSrcSurf->ScalingPreference == VPHAL_SCALING_PREFER_SFC_FOR_VEBOX)
343             {
344                 goto finish;
345             }
346 
347             if (!IS_YUV_FORMAT(pSrcSurf->Format))
348             {
349                 goto finish;
350             }
351 
352             // disabled if need denoise or deinterlace
353             if (pSrcSurf->pDenoiseParams || pSrcSurf->pDeinterlaceParams)
354             {
355                 goto finish;
356             }
357 
358             if (0 < pSrcSurf->uFwdRefCount || 0 < pSrcSurf->uBwdRefCount)
359             {
360                 goto finish;
361             }
362         }
363         if (pSrcSurf && IsSurfNeedAvs(pSrcSurf))
364         {
365             uAvsSurfaceCnt++;
366         }
367     }
368 
369     if (uAvsSurfaceCnt <= 1)
370     {
371         goto finish;
372     }
373 
374     if (!IsYuvPriorRgbInCompositeOrder(pcRenderParams))
375     {
376         goto finish;
377     }
378 
379     // disable if any AVS surface overlay to other AVS surface.
380     for (uSourceIdx = 0; uSourceIdx < pcRenderParams->uSrcCount; uSourceIdx++)
381     {
382         PVPHAL_SURFACE pSrcSurfA         = pcRenderParams->pSrc[uSourceIdx];
383         if (pSrcSurfA && IsSurfNeedAvs(pSrcSurfA))
384         {
385             for (uSourceBIdx = uSourceIdx + 1; uSourceBIdx < pcRenderParams->uSrcCount; uSourceBIdx++)
386             {
387                 PVPHAL_SURFACE pSrcSurfB = pcRenderParams->pSrc[uSourceBIdx];
388                 if (pSrcSurfB && IsSurfNeedAvs(pSrcSurfB) &&
389                     !RECT1_OUTSIDE_RECT2(pSrcSurfA->rcDst, pSrcSurfB->rcDst)) // not outside means overlay
390                 {
391                     goto finish;
392                 }
393             }
394         }
395     }
396 
397     bEnableAvsForMultiSurface = true;
398 finish:
399     return bEnableAvsForMultiSurface;
400 }
401 
402 //!
403 //! \brief    Rendering with AVS scaling for multiple surfaces
404 //! \details  Rendering with AVS scaling for multiple surfaces
405 //!           Currently composition kernel only allows first primary surface with AVS.
406 //!           To apply AVS for multiple surfaces, this function do the following steps:
407 //!           (1) separating each AVS surface into different phases containing only one primary
408 //!           (2) rendering with individual primary, and let first pass with color filler
409 //!           (3) rendering remaining non-AVS substreams, if any, with intermediate surface in one phase to allow alpha blending.
410 //! \param    pRenderer
411 //!           [in]  Pointer to VphalRenderer
412 //! \param    pcRenderParams
413 //!           [in] Pointer to const VPHAL_RENDER_PARAMS
414 //! \return   MOS_STATUS
415 //!           Return MOS_STATUS_SUCCESS if successful, otherwise failed
416 //!
VpHal_RenderWithAvsForMultiStreams(VphalRenderer * pRenderer,PCVPHAL_RENDER_PARAMS pcRenderParams)417 static MOS_STATUS VpHal_RenderWithAvsForMultiStreams(
418     VphalRenderer        *pRenderer,
419     PCVPHAL_RENDER_PARAMS   pcRenderParams)
420 {
421     uint32_t                 uSourceIdx;
422     VPHAL_RENDER_PARAMS      RenderParams;
423     VPHAL_COLORFILL_PARAMS   colorFillForFirstRenderPass;
424     bool                     bColorFillForFirstRender;
425     bool                     bHasNonAvsSubstream;
426     MOS_STATUS               eStatusSingleRender;
427     PVPHAL_SURFACE           pIntermediateSurface;
428     PVPHAL_SURFACE           pBackGroundSurface;
429     MOS_STATUS               eStatus                   = MOS_STATUS_SUCCESS;
430     VPHAL_SCALING_PREFERENCE ePrimaryScalingPreference = VPHAL_SCALING_PREFER_SFC;
431     VPHAL_RENDER_PARAMS      *pRenderParams;
432 
433     VPHAL_PUBLIC_CHK_NULL(pRenderer);
434     VPHAL_PUBLIC_CHK_NULL(pRenderer->GetOsInterface());
435     VPHAL_PUBLIC_CHK_NULL(pcRenderParams);
436     VPHAL_PUBLIC_CHK_NULL(pcRenderParams->pTarget[0]);
437 
438     pRenderParams =
439         (VPHAL_RENDER_PARAMS*)pcRenderParams;
440 
441     if (pcRenderParams->pColorFillParams)
442     {
443         colorFillForFirstRenderPass = *pcRenderParams->pColorFillParams;
444     }
445     else
446     {
447         colorFillForFirstRenderPass.bYCbCr = false;
448         colorFillForFirstRenderPass.Color  = 0;
449         colorFillForFirstRenderPass.CSpace = CSpace_sRGB;
450     }
451 
452     pIntermediateSurface = &pRenderer->IntermediateSurface;
453 
454     // check if having non-AVS substream
455     bHasNonAvsSubstream   = false;
456     pBackGroundSurface    = nullptr;
457     for (uSourceIdx = 0; uSourceIdx < pcRenderParams->uSrcCount; uSourceIdx++)
458     {
459         PVPHAL_SURFACE pSurf = (PVPHAL_SURFACE)pcRenderParams->pSrc[uSourceIdx];
460         if (pSurf && pSurf->SurfType == SURF_IN_SUBSTREAM)
461         {
462             if (!IS_YUV_FORMAT(pSurf->Format))
463             {
464                 bHasNonAvsSubstream = true;
465             }
466         }
467 
468         if (pSurf && pSurf->SurfType == SURF_IN_BACKGROUND)
469         {
470             pBackGroundSurface = pSurf;
471         }
472 
473         // keep scaling preference of primary for later usage
474         if (pSurf && pSurf->SurfType == SURF_IN_PRIMARY)
475         {
476             ePrimaryScalingPreference = pSurf->ScalingPreference;
477         }
478     }
479 
480     // create an intermediate surface if having non-AVS substream, as phase 1 output and phase 2 input.
481     if (bHasNonAvsSubstream)
482     {
483         bool     bAllocated;
484         uint32_t dwTempWidth  = pcRenderParams->pTarget[0]->dwWidth;
485         uint32_t dwTempHeight = pcRenderParams->pTarget[0]->dwHeight;
486 
487         // Allocate/Reallocate temporary output
488         if (dwTempWidth  > pRenderer->IntermediateSurface.dwWidth ||
489             dwTempHeight > pRenderer->IntermediateSurface.dwHeight)
490         {
491             dwTempWidth  = MOS_MAX(dwTempWidth , pRenderer->IntermediateSurface.dwWidth);
492             dwTempHeight = MOS_MAX(dwTempHeight, pRenderer->IntermediateSurface.dwHeight);
493             dwTempWidth  = MOS_ALIGN_CEIL(dwTempWidth , VPHAL_BUFFER_SIZE_INCREMENT);
494             dwTempHeight = MOS_ALIGN_CEIL(dwTempHeight, VPHAL_BUFFER_SIZE_INCREMENT);
495 
496             eStatusSingleRender = VpHal_ReAllocateSurface(
497                 pRenderer->GetOsInterface(),
498                 &pRenderer->IntermediateSurface,
499                 "RenderIntermediateSurface",
500                 pcRenderParams->pTarget[0]->Format,
501                 MOS_GFXRES_2D,
502                 pcRenderParams->pTarget[0]->TileType,
503                 dwTempWidth,
504                 dwTempHeight,
505                 false,
506                 MOS_MMC_DISABLED,
507                 &bAllocated);
508 
509             if (MOS_SUCCEEDED(eStatusSingleRender))
510             {
511                 pIntermediateSurface->SurfType      = SURF_IN_PRIMARY;
512                 pIntermediateSurface->SampleType    = SAMPLE_PROGRESSIVE;
513                 pIntermediateSurface->ColorSpace    = pcRenderParams->pTarget[0]->ColorSpace;
514                 pIntermediateSurface->ExtendedGamut = pcRenderParams->pTarget[0]->ExtendedGamut;
515                 pIntermediateSurface->rcSrc         = pcRenderParams->pTarget[0]->rcSrc;
516                 pIntermediateSurface->rcDst         = pcRenderParams->pTarget[0]->rcDst;
517                 pIntermediateSurface->ScalingMode   = VPHAL_SCALING_AVS;
518                 pIntermediateSurface->bIEF          = false;
519             }
520             else
521             {
522                 eStatus             = eStatusSingleRender;
523                 bHasNonAvsSubstream = false;
524                 VPHAL_PUBLIC_ASSERTMESSAGE("Failed to create intermediate surface, eStatus: %d.\n", eStatus);
525                 MT_ERR1(MT_VP_HAL_REALLOC_SURF, MT_CODE_LINE, __LINE__);
526             }
527         }
528     }
529 
530     // phase 1: render each AVS surface in separated pass
531     bColorFillForFirstRender = true;
532     RenderParams             = *pRenderParams;
533     RenderParams.uDstCount   = 1;
534     MOS_ZeroMemory(RenderParams.pSrc, sizeof(PVPHAL_SURFACE) * VPHAL_MAX_SOURCES);
535 
536     for (uSourceIdx = 0; uSourceIdx < pcRenderParams->uSrcCount; uSourceIdx++)
537     {
538         VPHAL_SURFACE               SinglePassSource;
539         PVPHAL_SURFACE              pSurf = (PVPHAL_SURFACE)pcRenderParams->pSrc[uSourceIdx];
540         RenderParams.uSrcCount         = 0;
541 
542         if (pSurf && IsSurfNeedAvs(pSurf))
543         {
544             SinglePassSource                   = *(pSurf);
545             SinglePassSource.SurfType          = SURF_IN_PRIMARY;
546             SinglePassSource.ScalingMode       = VPHAL_SCALING_AVS;
547             SinglePassSource.ScalingPreference = ePrimaryScalingPreference;
548 
549             RenderParams.pTarget[0]   = (bHasNonAvsSubstream ? pIntermediateSurface : pcRenderParams->pTarget[0]);
550 
551             if (bColorFillForFirstRender) // apply color-fill for the first rendering
552             {
553                 bColorFillForFirstRender      = false;
554                 RenderParams.pColorFillParams = &colorFillForFirstRenderPass;
555 
556                 if (pBackGroundSurface)
557                 {
558                     RenderParams.pSrc[RenderParams.uSrcCount] = pBackGroundSurface;
559                     RenderParams.uSrcCount++;
560                 }
561             }
562             else if (!bColorFillForFirstRender && SinglePassSource.pLumaKeyParams)  // colorfill is needed if lumakey enabled on a single pass
563             {
564                 RenderParams.pColorFillParams  = &colorFillForFirstRenderPass;
565                 RenderParams.pTarget[0]->rcDst = SinglePassSource.rcDst;
566             }
567             else
568             {
569                 RenderParams.pTarget[0]->rcDst = SinglePassSource.rcDst;
570                 RenderParams.pColorFillParams  = nullptr;
571             }
572 
573             RenderParams.pSrc[RenderParams.uSrcCount] = &SinglePassSource;
574             RenderParams.uSrcCount++;
575 
576             // continue the next pfnRender even if single pass failed, but return eStatus failed.
577             eStatusSingleRender = pRenderer->Render((PCVPHAL_RENDER_PARAMS)(&RenderParams));
578             if (MOS_FAILED(eStatusSingleRender))
579             {
580                 eStatus = eStatusSingleRender;
581                 VPHAL_PUBLIC_ASSERTMESSAGE("Failed to redner for primary streams, eStatus: %d.\n", eStatus);
582                 MT_ERR2(MT_VP_HAL_RENDER, MT_ERROR_CODE, eStatus, MT_CODE_LINE, __LINE__);
583             }
584         }
585     }
586 
587     // phase 2: if having non-AVS substream, render them with previous output in one pass.
588     if (bHasNonAvsSubstream)
589     {
590         RenderParams                = *pRenderParams;
591         MOS_ZeroMemory(RenderParams.pSrc, sizeof(PVPHAL_SURFACE) * VPHAL_MAX_SOURCES);
592 
593         pIntermediateSurface->rcSrc = pcRenderParams->pTarget[0]->rcSrc;
594         pIntermediateSurface->rcDst = pcRenderParams->pTarget[0]->rcDst;
595         RenderParams.pSrc[0]        = pIntermediateSurface;
596         RenderParams.uSrcCount      = 1;
597         RenderParams.uDstCount      = 1;
598 
599         for (uSourceIdx = 0; uSourceIdx < pcRenderParams->uSrcCount; uSourceIdx++)
600         {
601             PVPHAL_SURFACE pSurf = pcRenderParams->pSrc[uSourceIdx];
602             bool bIsSurfForPhase2   = (pSurf &&
603                                     (!IsSurfNeedAvs(pSurf)) &&
604                                     (pSurf->SurfType != SURF_IN_BACKGROUND));
605             if (bIsSurfForPhase2)
606             {
607                 RenderParams.pSrc[RenderParams.uSrcCount] = pSurf;
608                 RenderParams.uSrcCount++;
609             }
610         }
611 
612         eStatusSingleRender = pRenderer->Render((PCVPHAL_RENDER_PARAMS)(&RenderParams));
613         if (MOS_FAILED(eStatusSingleRender))
614         {
615             eStatus = eStatusSingleRender;
616             VPHAL_PUBLIC_ASSERTMESSAGE("Failed to redner for substreams, eStatus: %d.\n", eStatus);
617             MT_ERR2(MT_VP_HAL_RENDER, MT_ERROR_CODE, eStatus, MT_CODE_LINE, __LINE__);
618         }
619     }
620 
621 finish:
622     return eStatus;
623 }
624 
625 //!
626 //! \brief    Performs VP Rendering
627 //! \details  Performs VP Rendering
628 //!           - call default render of video
629 //! \param    [in] pcRenderParams
630 //!           Pointer to Render Params
631 //! \return   MOS_STATUS
632 //!           Return MOS_STATUS_SUCCESS if successful, otherwise failed
633 //!
Render(PCVPHAL_RENDER_PARAMS pcRenderParams)634 MOS_STATUS VphalState::Render(
635     PCVPHAL_RENDER_PARAMS   pcRenderParams)
636 {
637     MOS_STATUS          eStatus;
638     VPHAL_RENDER_PARAMS RenderParams;
639 
640     VPHAL_PUBLIC_CHK_NULL(pcRenderParams);
641     RenderParams    = *pcRenderParams;
642 
643     // Explicitly initialize the maxSrcRect of VphalRenderer
644     // so that the maxSrcRect for the last set of surfaces does not get
645     // re-used for the current set of surfaces.
646     m_renderer->InitMaxSrcRect();
647 
648     if (VpHal_IsAvsSampleForMultiStreamsEnabled(pcRenderParams))
649     {
650         eStatus = VpHal_RenderWithAvsForMultiStreams(m_renderer, pcRenderParams);
651         goto finish;
652     }
653 
654     // default render of video
655     RenderParams.bIsDefaultStream = true;
656     eStatus = m_renderer->Render((PCVPHAL_RENDER_PARAMS)(&RenderParams));
657 
658 finish:
659     return eStatus;
660 }
661 
662 //!
663 //! \brief    Get feature reporting from renderer
664 //! \details  Get feature reporting from renderer
665 //! \return   VphalFeatureReport*
666 //!           Pointer to VphalFeatureReport: rendering features reported
667 //!
GetRenderFeatureReport()668 VphalFeatureReport* VphalState::GetRenderFeatureReport()
669 {
670     VPHAL_PUBLIC_ASSERT(m_renderer);
671 
672     return m_renderer->GetReport();
673 }
674 
675 //!
676 //! \brief    VphalState Constructor
677 //! \details  Creates instance of VphalState
678 //!           - Return pointer to initialized VPHAL state, but not yet fully allocated
679 //!           - Caller must call pfnAllocate to allocate all VPHAL states and objects.
680 //! \param    [in] pOsInterface
681 //!           OS interface, if provided externally - may be nullptr
682 //! \param    [in,out] peStatus
683 //!           Pointer to the MOS_STATUS flag.
684 //!           Will assign this flag to MOS_STATUS_SUCCESS if successful, otherwise failed
685 //!
VphalState(PMOS_INTERFACE pOsInterface,MOS_STATUS * peStatus)686 VphalState::VphalState(
687         PMOS_INTERFACE          pOsInterface,
688         MOS_STATUS              *peStatus) :
689         m_platform(),
690         m_skuTable(nullptr),
691         m_waTable(nullptr),
692         m_osInterface(pOsInterface),
693         m_renderHal(nullptr),
694         m_veboxInterface(nullptr),
695         m_cpInterface(nullptr),
696         m_sfcInterface(nullptr),
697         m_renderer(nullptr),
698         m_renderGpuNode(MOS_GPU_NODE_3D),
699         m_renderGpuContext(MOS_GPU_CONTEXT_RENDER)
700 {
701     MOS_STATUS                  eStatus;
702 
703     eStatus                     = MOS_STATUS_UNKNOWN;
704 
705     VPHAL_PUBLIC_CHK_NULL(m_osInterface);
706 
707     // Initialize platform, sku, wa tables
708     m_osInterface->pfnGetPlatform(m_osInterface, &m_platform);
709     m_skuTable = m_osInterface->pfnGetSkuTable(m_osInterface);
710     m_waTable  = m_osInterface->pfnGetWaTable (m_osInterface);
711 
712     m_userSettingPtr = m_osInterface->pfnGetUserSettingInstance(m_osInterface);
713     VpUserSetting::InitVpUserSetting(m_userSettingPtr);
714 
715     m_renderHal = (PRENDERHAL_INTERFACE_LEGACY)MOS_AllocAndZeroMemory(sizeof(RENDERHAL_INTERFACE_LEGACY));
716     VPHAL_PUBLIC_CHK_NULL(m_renderHal);
717     VPHAL_PUBLIC_CHK_STATUS(RenderHal_InitInterface_Legacy(
718         m_renderHal,
719         &m_cpInterface,
720         m_osInterface));
721 
722 finish:
723     if(peStatus)
724     {
725         *peStatus = eStatus;
726     }
727 }
728 
729 //!
730 //! \brief    Vphal Destructor
731 //! \details  Destroys VPHAL and all internal states and objects
732 //! \return   void
733 //!
~VphalState()734 VphalState::~VphalState()
735 {
736     MOS_STATUS              eStatus;
737 
738     // Wait for all cmd before destroy gpu resource
739     if (m_osInterface && m_osInterface->pfnWaitAllCmdCompletion && m_osInterface->bDeallocateOnExit)
740     {
741         VP_PUBLIC_NORMALMESSAGE("WaitAllCmdCompletion in VphalState::~VphalState");
742         m_osInterface->pfnWaitAllCmdCompletion(m_osInterface);
743     }
744 
745     // Destroy rendering objects (intermediate surfaces, BBs, etc)
746     if (m_renderer)
747     {
748         MOS_Delete(m_renderer);
749         m_renderer = nullptr;
750     }
751 
752     if (m_renderHal)
753     {
754         if (m_renderHal->pfnDestroy)
755         {
756             eStatus = m_renderHal->pfnDestroy(m_renderHal);
757             if (eStatus != MOS_STATUS_SUCCESS)
758             {
759                 VPHAL_PUBLIC_ASSERTMESSAGE("Failed to destroy RenderHal, eStatus:%d.\n", eStatus);
760                 MT_ERR1(MT_VP_HAL_DESTROY, MT_CODE_LINE, __LINE__);
761             }
762         }
763         MOS_FreeMemory(m_renderHal);
764     }
765 
766     if (m_cpInterface)
767     {
768         if (m_osInterface)
769         {
770             m_osInterface->pfnDeleteMhwCpInterface(m_cpInterface);
771             m_cpInterface = nullptr;
772         }
773         else
774         {
775             VPHAL_PUBLIC_ASSERTMESSAGE("Failed to destroy cpInterface.");
776         }
777     }
778 
779     if (m_sfcInterface)
780     {
781         MOS_Delete(m_sfcInterface);
782         m_sfcInterface = nullptr;
783     }
784 
785     if (m_veboxInterface)
786     {
787         if (m_veboxItf)
788         {
789             eStatus = m_veboxItf->DestroyHeap();
790             if (eStatus != MOS_STATUS_SUCCESS)
791             {
792                 VPHAL_PUBLIC_ASSERTMESSAGE("Failed to destroy Vebox Interface, eStatus:%d.\n", eStatus);
793                 MT_ERR1(MT_VP_HAL_DESTROY, MT_CODE_LINE, __LINE__);
794             }
795         }
796 
797         eStatus = m_veboxInterface->DestroyHeap();
798         MOS_Delete(m_veboxInterface);
799         m_veboxInterface = nullptr;
800         m_veboxItf       = nullptr;
801         if (eStatus != MOS_STATUS_SUCCESS)
802         {
803             VPHAL_PUBLIC_ASSERTMESSAGE("Failed to destroy Vebox Interface, eStatus:%d.\n", eStatus);
804             MT_ERR1(MT_VP_HAL_DESTROY, MT_CODE_LINE, __LINE__);
805         }
806     }
807 
808     // Destroy OS interface objects (CBs, etc)
809     if (m_osInterface)
810     {
811         if (m_osInterface->bDeallocateOnExit)
812         {
813             //Clear some overwriten gpucontext resources
814             if (!m_gpuContextCheckList.empty())
815             {
816                 DestroyGpuContextWithInvalidHandle();
817                 m_gpuContextCheckList.clear();
818             }
819 
820             m_osInterface->pfnDestroy(m_osInterface, true);
821 
822             // Deallocate OS interface structure (except if externally provided)
823             MOS_FreeMemory(m_osInterface);
824         }
825     }
826 }
827 
VphalStateFactory(PMOS_INTERFACE pOsInterface,PMOS_CONTEXT pOsDriverContext,MOS_STATUS * peStatus)828 VphalState* VphalState::VphalStateFactory(
829     PMOS_INTERFACE          pOsInterface,
830     PMOS_CONTEXT            pOsDriverContext,
831     MOS_STATUS              *peStatus)
832 {
833     VphalState* vphalState = dynamic_cast<VphalState*>(VphalDevice::CreateFactory(pOsInterface, pOsDriverContext, peStatus));
834     if(nullptr == vphalState)
835     {
836         VPHAL_PUBLIC_ASSERTMESSAGE("vphal state pointer is nullptr");
837         *peStatus = MOS_STATUS_NULL_POINTER;
838     }
839     return vphalState;
840 }
841 
842 //!
843 //! \brief    Get Status Report
844 //! \details  Get Status Report, will return back to app indicating if related frame id is done by gpu
845 //! \param    [out] pQueryReport
846 //!           Pointer to pQueryReport, the status query report array.
847 //! \param    [in] wStatusNum
848 //!           The size of array pQueryReport.
849 //! \return   MOS_STATUS
850 //!           Return MOS_STATUS_SUCCESS if successful, otherwise failed
GetStatusReport(PQUERY_STATUS_REPORT_APP pQueryReport,uint16_t wStatusNum)851 MOS_STATUS VphalState::GetStatusReport(
852     PQUERY_STATUS_REPORT_APP       pQueryReport,
853     uint16_t                       wStatusNum)
854 {
855     MOS_STATUS                     eStatus = MOS_STATUS_SUCCESS;
856 
857 #if (!EMUL)        // this function is dummy for emul
858     uint32_t                       i;
859     uint32_t                       uiTableLen;
860     PVPHAL_STATUS_TABLE            pStatusTable;
861     PMOS_CONTEXT                   pOsContext;
862     uint32_t                       uiIndex;
863     uint32_t                       uiNewHead;
864     PVPHAL_STATUS_ENTRY            pStatusEntry;
865     bool                           bMarkNotReadyForRemains = false;
866 
867     VPHAL_PUBLIC_CHK_NULL(pQueryReport);
868     VPHAL_PUBLIC_CHK_NULL(m_osInterface);
869     VPHAL_PUBLIC_CHK_NULL(m_osInterface->pOsContext);
870 
871     // it should be ok if we don't consider the null render
872     // eNullRender = m_pOsInterface->pfnGetNullHWRenderFlags(m_pOsInterface);
873 
874     pOsContext           = m_osInterface->pOsContext;
875     pStatusTable         = &m_statusTable;
876     uiNewHead            = pStatusTable->uiHead; // uiNewHead start from previous head value
877     // entry length from head to tail
878     if (pStatusTable->uiCurrent < pStatusTable->uiHead)
879     {
880         uiTableLen = pStatusTable->uiCurrent + VPHAL_STATUS_TABLE_MAX_SIZE - pStatusTable->uiHead;
881     }
882     else
883     {
884         uiTableLen = pStatusTable->uiCurrent - pStatusTable->uiHead;
885     }
886 
887     // step 1 - update pStatusEntry from driver if command associated with the dwTag is done by gpu
888     for (i = 0; i < wStatusNum && i < uiTableLen; i++)
889     {
890         uint32_t    dwGpuTag; // hardware tag updated by gpu command pipectl
891         bool        bDoneByGpu;
892         bool        bFailedOnSubmitCmd;
893 
894         uiIndex            = (pStatusTable->uiHead + i) & (VPHAL_STATUS_TABLE_MAX_SIZE - 1);
895         pStatusEntry       = &pStatusTable->aTableEntries[uiIndex];
896 
897         // for tasks using CM, different streamIndexes may be used
898         uint32_t oldStreamIndex = m_osInterface->streamIndex;
899         if (pStatusEntry->isStreamIndexSet)
900         {
901             m_osInterface->streamIndex = pStatusEntry->streamIndex;
902         }
903 
904         if (bMarkNotReadyForRemains)
905         {
906             // the status is set as VPREP_NOTREADY while submitting commands
907             pQueryReport[i].dwStatus         = pStatusEntry->dwStatus;
908             pQueryReport[i].StatusFeedBackID = pStatusEntry->StatusFeedBackID;
909             continue;
910         }
911 
912         dwGpuTag           = m_osInterface->pfnGetGpuStatusSyncTag(m_osInterface, pStatusEntry->GpuContextOrdinal);
913         bDoneByGpu         = (dwGpuTag >= pStatusEntry->dwTag);
914         bFailedOnSubmitCmd = (pStatusEntry->dwStatus == VPREP_ERROR);
915 
916 #if (_DEBUG || _RELEASE_INTERNAL)
917         MOS_NULL_RENDERING_FLAGS NullRender = m_osInterface->pfnGetNullHWRenderFlags(m_osInterface);
918         if (NullRender.Value != 0)
919         {
920             bDoneByGpu = true;
921         }
922 #endif
923 
924         if (bFailedOnSubmitCmd)
925         {
926             uiNewHead = (uiIndex + 1) & (VPHAL_STATUS_TABLE_MAX_SIZE - 1);
927         }
928         else if (bDoneByGpu)
929         {
930             pStatusEntry->dwStatus = VPREP_OK;
931             uiNewHead = (uiIndex + 1) & (VPHAL_STATUS_TABLE_MAX_SIZE - 1);
932         }
933         else
934         {   // here we have the first not ready entry.
935 #if (LINUX || ANDROID)
936             uiNewHead = (uiIndex + 1) & (VPHAL_STATUS_TABLE_MAX_SIZE - 1);
937 #else
938             uiNewHead = uiIndex;
939 #endif
940 
941             bMarkNotReadyForRemains = true;
942         }
943 
944         if (m_osInterface->pfnIsGPUHung(m_osInterface))
945         {
946             pStatusEntry->dwStatus = VPREP_NOTREADY;
947         }
948 
949         pQueryReport[i].dwStatus         = pStatusEntry->dwStatus;
950         pQueryReport[i].StatusFeedBackID = pStatusEntry->StatusFeedBackID;
951 
952         if (pStatusEntry->isStreamIndexSet)
953         {
954             m_osInterface->streamIndex = oldStreamIndex;
955         }
956     }
957     pStatusTable->uiHead = uiNewHead;
958     // step 2 - mark VPREP_NOTAVAILABLE for unused entry
959     for (/* continue from previous i */; i < wStatusNum; i++)
960     {
961         pQueryReport[i].dwStatus         = VPREP_NOTAVAILABLE;
962         pQueryReport[i].StatusFeedBackID = 0;
963     }
964 
965 finish:
966 #else
967     MOS_UNUSED(pQueryReport);
968     MOS_UNUSED(wStatusNum);
969 #endif // end (!EMUL && !ANDROID)
970     return eStatus;
971 }
972 
973 //!
974 //! \brief    Get Status Report's entry length from head to tail
975 //! \details  Get Status Report's entry length from head to tail
976 //! \param    [out] puiLength
977 //!           Pointer to the entry length
978 //! \return   MOS_STATUS
979 //!           Return MOS_STATUS_SUCCESS if successful, otherwise failed
980 //!
GetStatusReportEntryLength(uint32_t * puiLength)981 MOS_STATUS VphalState::GetStatusReportEntryLength(
982     uint32_t*                      puiLength)
983 {
984     MOS_STATUS                     eStatus = MOS_STATUS_SUCCESS;
985 #if(!EMUL)        // this function is dummy for emul
986     PVPHAL_STATUS_TABLE            pStatusTable;
987 
988     VPHAL_PUBLIC_CHK_NULL(puiLength);
989 
990     pStatusTable = &m_statusTable;
991 
992     // entry length from head to tail
993     if (pStatusTable->uiCurrent < pStatusTable->uiHead)
994     {
995         *puiLength = pStatusTable->uiCurrent + VPHAL_STATUS_TABLE_MAX_SIZE - pStatusTable->uiHead;
996     }
997     else
998     {
999         *puiLength = pStatusTable->uiCurrent - pStatusTable->uiHead;
1000     }
1001 finish:
1002 #else
1003     MOS_UNUSED(puiLength);
1004 #endif
1005     return eStatus;
1006 }
1007 
GetVpMhwInterface(VP_MHWINTERFACE & vpMhwinterface)1008 MOS_STATUS VphalState::GetVpMhwInterface(
1009     VP_MHWINTERFACE &vpMhwinterface)
1010 {
1011     MOS_STATUS eStatus              = MOS_STATUS_SUCCESS;
1012 
1013     vpMhwinterface.m_platform       = m_platform;
1014     vpMhwinterface.m_waTable        = m_waTable;
1015     vpMhwinterface.m_skuTable       = m_skuTable;
1016     vpMhwinterface.m_osInterface    = m_osInterface;
1017     vpMhwinterface.m_renderHal      = m_renderHal;
1018     vpMhwinterface.m_veboxInterface = m_veboxInterface;
1019     vpMhwinterface.m_sfcInterface   = m_sfcInterface;
1020     vpMhwinterface.m_cpInterface    = m_cpInterface;
1021     vpMhwinterface.m_mhwMiInterface = m_renderHal->pMhwMiInterface;
1022     vpMhwinterface.m_statusTable    = &m_statusTable;
1023 
1024     return eStatus;
1025 }
1026 
1027 //!
1028 //! \brief    Put GPU context entry
1029 //! \details  Put GPU context entry in the m_gpuContextCheckList
1030 //! \param    MOS_GPU_CONTEXT mosGpuConext
1031 //!           [in] Mos GPU context
1032 //! \return   MOS_STATUS
1033 //!           Return MOS_STATUS_SUCCESS if successful, otherwise failed
1034 //!
AddGpuContextToCheckList(MOS_GPU_CONTEXT mosGpuConext)1035 MOS_STATUS VphalState::AddGpuContextToCheckList(
1036     MOS_GPU_CONTEXT mosGpuConext)
1037 {
1038 #if !EMUL
1039     MOS_GPU_CONTEXT originalGpuCtxOrdinal = m_osInterface->CurrentGpuContextOrdinal;
1040     if (mosGpuConext != originalGpuCtxOrdinal)
1041     {
1042         // Set GPU context temporarily
1043         VPHAL_PUBLIC_CHK_STATUS_RETURN(m_osInterface->pfnSetGpuContext(
1044             m_osInterface,
1045             mosGpuConext));
1046     }
1047     VPHAL_GPU_CONTEXT_ENTRY tmpEntry;
1048     tmpEntry.gpuCtxForMos     = mosGpuConext;
1049     tmpEntry.gpuContextHandle = m_osInterface->CurrentGpuContextHandle;
1050     tmpEntry.pGpuContext      = m_osInterface->pfnGetGpuContextbyHandle(m_osInterface, m_osInterface->CurrentGpuContextHandle);
1051     m_gpuContextCheckList.push_back(tmpEntry);
1052 
1053     if (mosGpuConext != originalGpuCtxOrdinal)
1054     {
1055         //Recover original settings
1056         VPHAL_PUBLIC_CHK_STATUS_RETURN(m_osInterface->pfnSetGpuContext(
1057             m_osInterface,
1058             originalGpuCtxOrdinal));
1059     }
1060 #endif
1061 
1062     return MOS_STATUS_SUCCESS;
1063 }
1064 
1065 //!
1066 //! \brief    Destroy GPU context entry with invalid handle
1067 //! \details  Release these GPU context overwritten by MediaContext
1068 //! \return   MOS_STATUS
1069 //!           Return MOS_STATUS_SUCCESS if successful, otherwise failed
1070 //!
DestroyGpuContextWithInvalidHandle()1071 MOS_STATUS VphalState::DestroyGpuContextWithInvalidHandle()
1072 {
1073 #if !EMUL
1074     MOS_GPU_CONTEXT originalGpuCtxOrdinal = m_osInterface->CurrentGpuContextOrdinal;
1075     for (auto &curGpuEntry : m_gpuContextCheckList)
1076     {
1077         //Failure in switching GPU Context indicates that we can't find and release gpu context in normal flow later
1078         //So if failed to switch GPU Context, just need to check GPU context, and release it here
1079         //If switch GPU Context successfully, need to check both handle and GPU context
1080         if ((MOS_FAILED(m_osInterface->pfnSetGpuContext(m_osInterface, curGpuEntry.gpuCtxForMos)) ||
1081             m_osInterface->CurrentGpuContextHandle != curGpuEntry.gpuContextHandle) &&
1082             m_osInterface->pfnGetGpuContextbyHandle(m_osInterface, curGpuEntry.gpuContextHandle) == curGpuEntry.pGpuContext)
1083         {
1084             m_osInterface->pfnWaitForCmdCompletion(m_osInterface->osStreamState, curGpuEntry.gpuContextHandle);
1085 
1086             m_osInterface->pfnDestroyGpuContextByHandle(m_osInterface, curGpuEntry.gpuContextHandle);
1087         }
1088     }
1089     if (m_osInterface->CurrentGpuContextOrdinal != originalGpuCtxOrdinal)
1090     {
1091         //Recover original settings
1092         if (m_osInterface->pfnSetGpuContext(m_osInterface, originalGpuCtxOrdinal) != MOS_STATUS_SUCCESS)
1093         {
1094             VPHAL_PUBLIC_NORMALMESSAGE("Have not recovered original GPU Context settings in m_osInterface");
1095         }
1096     }
1097 #endif
1098 
1099     return MOS_STATUS_SUCCESS;
1100 }
1101 
1102 //!
1103 //! \brief    Check whether GPU context is reused or not
1104 //! \details  Check whether GPU context is reused or not
1105 //! \param    MOS_GPU_CONTEXT mosGpuConext
1106 //!           [in] Mos GPU context
1107 //! \return   bool
1108 //!           Return true if is reused, otherwise false
1109 //!
IsGpuContextReused(MOS_GPU_CONTEXT mosGpuContext)1110 bool VphalState::IsGpuContextReused(
1111     MOS_GPU_CONTEXT mosGpuContext)
1112 {
1113     bool reuseContextFlag = false;
1114 #if !EMUL
1115     MOS_GPU_CONTEXT originalGpuCtxOrdinal = m_osInterface->CurrentGpuContextOrdinal;
1116     if (MOS_SUCCEEDED(m_osInterface->pfnSetGpuContext(m_osInterface, mosGpuContext)))
1117     {
1118         VPHAL_PUBLIC_NORMALMESSAGE("Reuse mos GPU context %d. GPU handle %d", (uint32_t)mosGpuContext, m_osInterface->CurrentGpuContextHandle);
1119         reuseContextFlag = true;
1120     }
1121 
1122     if (originalGpuCtxOrdinal < MOS_GPU_CONTEXT_MAX &&
1123         m_osInterface->CurrentGpuContextOrdinal != originalGpuCtxOrdinal)
1124     {
1125         //Recover original settings
1126         if (m_osInterface->pfnSetGpuContext(m_osInterface, originalGpuCtxOrdinal) != MOS_STATUS_SUCCESS)
1127         {
1128             VPHAL_PUBLIC_NORMALMESSAGE("Have not recovered original GPU Context settings in m_osInterface");
1129         }
1130     }
1131 #endif
1132     return reuseContextFlag;
1133 }
1134