1 /*
2 * Copyright (c) 2017-2020, 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 //!
24 //! \file     codechal_decode_vc1_g12.cpp
25 //! \brief    Implements the decode interface extension for Gen12 VC1.
26 //! \details  Implements all functions required by CodecHal for Gen12 VC1 decoding.
27 //!
28 
29 #include "codeckrnheader.h"
30 
31 #if defined(ENABLE_KERNELS) && !defined(_FULL_OPEN_SOURCE)
32 #include "igcodeckrn_g12.h"
33 #endif
34 
35 #include "codechal_decode_vc1_g12.h"
36 #include "codechal_secure_decode_interface.h"
37 #include "mhw_vdbox_mfx_g12_X.h"
38 #include "codechal_mmc_decode_vc1_g12.h"
39 #include "mhw_render_g12_X.h"
40 #include "hal_oca_interface.h"
41 
InitMmcState()42 MOS_STATUS CodechalDecodeVc1G12::InitMmcState()
43 {
44 #ifdef _MMC_SUPPORTED
45     m_mmc = MOS_New(CodechalMmcDecodeVc1G12, m_hwInterface, this);
46     CODECHAL_DECODE_CHK_NULL_RETURN(m_mmc);
47 #endif
48     return MOS_STATUS_SUCCESS;
49 }
50 
AllocateStandard(CodechalSetting * settings)51 MOS_STATUS CodechalDecodeVc1G12::AllocateStandard(
52     CodechalSetting *          settings)
53 {
54     MOS_STATUS eStatus = MOS_STATUS_SUCCESS;
55 
56     CODECHAL_DECODE_FUNCTION_ENTER;
57 
58     CODECHAL_DECODE_CHK_NULL_RETURN(settings);
59 
60     CODECHAL_DECODE_CHK_STATUS_RETURN(CodechalDecodeVc1::AllocateStandard(settings));
61 
62 #ifdef _MMC_SUPPORTED
63     // Disable Decode MMC for IGFX
64     if (!MEDIA_IS_SKU(m_hwInterface->GetSkuTable(), FtrFlatPhysCCS))
65     {
66         m_mmc->SetMmcDisabled();
67     }
68 
69     // To WA invalid aux data caused HW issue when MMC on
70     if (m_mmc->IsMmcEnabled() && (MEDIA_IS_WA(m_waTable, Wa_1408785368) || MEDIA_IS_WA(m_waTable, Wa_22010493002)))
71     {
72         //Add HUC STATE Commands
73         MHW_VDBOX_STATE_CMDSIZE_PARAMS stateCmdSizeParams;
74 
75         m_hwInterface->GetHucStateCommandSize(
76             CODECHAL_DECODE_MODE_VC1VLD,
77             &m_HucStateCmdBufferSizeNeeded,
78             &m_HucPatchListSizeNeeded,
79             &stateCmdSizeParams);
80     }
81 #endif
82 
83     if ( MOS_VE_SUPPORTED(m_osInterface))
84     {
85         static_cast<MhwVdboxMfxInterfaceG12*>(m_mfxInterface)->DisableScalabilitySupport();
86 
87         //single pipe VE initialize
88         m_veState = (PCODECHAL_DECODE_SINGLEPIPE_VIRTUALENGINE_STATE)MOS_AllocAndZeroMemory(sizeof(CODECHAL_DECODE_SINGLEPIPE_VIRTUALENGINE_STATE));
89         CODECHAL_DECODE_CHK_NULL_RETURN(m_veState);
90         CODECHAL_DECODE_CHK_STATUS_RETURN(CodecHalDecodeSinglePipeVE_InitInterface(m_osInterface, m_veState));
91     }
92 
93     return eStatus;
94 }
95 
SetGpuCtxCreatOption(CodechalSetting * codecHalSetting)96 MOS_STATUS CodechalDecodeVc1G12::SetGpuCtxCreatOption(
97     CodechalSetting *codecHalSetting)
98 {
99     MOS_STATUS eStatus = MOS_STATUS_SUCCESS;
100 
101     CODECHAL_DECODE_FUNCTION_ENTER;
102 
103     if (!MOS_VE_CTXBASEDSCHEDULING_SUPPORTED(m_osInterface))
104     {
105         CodechalDecode::SetGpuCtxCreatOption(codecHalSetting);
106     }
107     else
108     {
109         m_gpuCtxCreatOpt = MOS_New(MOS_GPUCTX_CREATOPTIONS_ENHANCED);
110         bool sfcInUse    = (codecHalSetting->sfcInUseHinted && codecHalSetting->downsamplingHinted
111                             && (MEDIA_IS_SKU(m_skuTable, FtrSFCPipe) && !MEDIA_IS_SKU(m_skuTable, FtrDisableVDBox2SFC)));
112         CODECHAL_DECODE_CHK_STATUS_RETURN(CodecHalDecodeSinglePipeVE_ConstructParmsForGpuCtxCreation(
113             m_veState,
114             (PMOS_GPUCTX_CREATOPTIONS_ENHANCED)m_gpuCtxCreatOpt,
115             sfcInUse));
116         m_videoContext = MOS_GPU_CONTEXT_VIDEO;
117     }
118 
119     return eStatus;
120 }
121 
SetFrameStates()122 MOS_STATUS CodechalDecodeVc1G12::SetFrameStates()
123 {
124     MOS_STATUS eStatus = MOS_STATUS_SUCCESS;
125 
126     CODECHAL_DECODE_FUNCTION_ENTER;
127 
128     CODECHAL_DECODE_CHK_STATUS_RETURN(CodechalDecodeVc1::SetFrameStates());
129 
130     if (MOS_VE_SUPPORTED(m_osInterface) && !MOS_VE_CTXBASEDSCHEDULING_SUPPORTED(m_osInterface))
131     {
132         MOS_VIRTUALENGINE_SET_PARAMS  vesetParams;
133 
134         MOS_ZeroMemory(&vesetParams, sizeof(vesetParams));
135         vesetParams.bSFCInUse = false;
136         vesetParams.bNeedSyncWithPrevious = true;
137         vesetParams.bSameEngineAsLastSubmission = false;
138         CODECHAL_DECODE_CHK_STATUS_RETURN(CodecHalDecodeSinglePipeVE_SetHintParams(m_veState, &vesetParams));
139     }
140 
141 #ifdef _MMC_SUPPORTED
142     bool isBPicture = m_mfxInterface->IsVc1BPicture(
143                         m_vc1PicParams->CurrPic,
144                         m_vc1PicParams->picture_fields.is_first_field,
145                         m_vc1PicParams->picture_fields.picture_type);
146 
147     bool isOverlapSmoothingFilter = false;
148 
149     isOverlapSmoothingFilter |= m_vc1PicParams->sequence_fields.AdvancedProfileFlag &&
150                                 m_vc1PicParams->sequence_fields.overlap;
151 
152     isOverlapSmoothingFilter |= !(isBPicture ||
153                                   (m_vc1PicParams->pic_quantizer_fields.pic_quantizer_scale < 9) ||
154                                   !m_vc1PicParams->sequence_fields.overlap);
155 
156     isOverlapSmoothingFilter |= m_intelEntrypointInUse &&
157                                 (m_mode == CODECHAL_DECODE_MODE_VC1VLD) &&
158                                 m_vc1PicParams->conditional_overlap_flag;
159 
160     //For VC1 frame with overlap smoothing filter enabled, force to post-deblock if MMC on
161     if (m_mmc && m_mmc->IsMmcEnabled() && isOverlapSmoothingFilter)
162     {
163         m_deblockingEnabled = true;
164     }
165 #endif
166 
167     return eStatus;
168 }
169 
DecodeStateLevel()170 MOS_STATUS CodechalDecodeVc1G12::DecodeStateLevel()
171 {
172     MOS_STATUS eStatus = MOS_STATUS_SUCCESS;
173 
174     CODECHAL_DECODE_FUNCTION_ENTER;
175 #ifdef _MMC_SUPPORTED
176     // To make sure aux table is clear when MMC off(IGFX)
177     // Can not clear aux table for DGFX because of stolen memory
178     if (!m_mmc->IsMmcEnabled() && !Mos_ResourceIsNull(&m_destSurface.OsResource) && m_destSurface.OsResource.bConvertedFromDDIResource)
179     {
180         if (m_secureDecoder && m_secureDecoder->IsAuxDataInvalid(&m_destSurface.OsResource))
181         {
182             // Not use CODECHAL_DECODE_CHK_STATUS_RETURN() here to avoid adding local variable
183             // Error can still be caught by CODECHAL_DECODE_CHK_STATUS_RETURN() in InitAuxSurface
184             CODECHAL_DECODE_VERBOSEMESSAGE("Clear CCS for secure decode before frame %d submission", m_frameNum);
185             CODECHAL_DECODE_CHK_STATUS_RETURN(m_secureDecoder->InitAuxSurface(&m_destSurface.OsResource, false, true));
186         }
187         else
188         {
189             CODECHAL_DECODE_VERBOSEMESSAGE("Clear CCS by Huc Copy before frame %d submission", m_frameNum);
190             CODECHAL_DECODE_CHK_STATUS_RETURN(static_cast<CodecHalMmcStateG12 *>(m_mmc)->ClearAuxSurf(
191                 this, m_miInterface, &m_destSurface.OsResource, m_veState));
192         }
193     }
194 #endif
195 
196     PCODEC_REF_LIST     *vc1RefList;
197     vc1RefList = &(m_vc1RefList[0]);
198 
199     uint8_t destIdx   = m_vc1PicParams->CurrPic.FrameIdx;
200     uint8_t fwdRefIdx = (uint8_t)m_vc1PicParams->ForwardRefIdx;
201     uint8_t bwdRefIdx = (uint8_t)m_vc1PicParams->BackwardRefIdx;
202 
203     bool isIPicture = m_mfxInterface->IsVc1IPicture(
204                           m_vc1PicParams->CurrPic,
205                           m_vc1PicParams->picture_fields.is_first_field,
206                           m_vc1PicParams->picture_fields.picture_type)
207                           ? true
208                           : false;
209     bool isPPicture = m_mfxInterface->IsVc1PPicture(
210                           m_vc1PicParams->CurrPic,
211                           m_vc1PicParams->picture_fields.is_first_field,
212                           m_vc1PicParams->picture_fields.picture_type)
213                           ? true
214                           : false;
215     bool isBPicture = m_mfxInterface->IsVc1BPicture(
216                           m_vc1PicParams->CurrPic,
217                           m_vc1PicParams->picture_fields.is_first_field,
218                           m_vc1PicParams->picture_fields.picture_type)
219                           ? true
220                           : false;
221 
222     PMOS_SURFACE    destSurface;
223     PMOS_RESOURCE   fwdRefSurface, bwdRefSurface;
224     if (m_unequalFieldWaInUse && CodecHal_PictureIsField(m_vc1PicParams->CurrPic))
225     {
226         destSurface =
227             &(m_unequalFieldSurface[vc1RefList[destIdx]->dwUnequalFieldSurfaceIdx]);
228         fwdRefSurface =
229             &(m_unequalFieldSurface[vc1RefList[fwdRefIdx]->dwUnequalFieldSurfaceIdx].OsResource);
230         bwdRefSurface =
231             &(m_unequalFieldSurface[vc1RefList[bwdRefIdx]->dwUnequalFieldSurfaceIdx].OsResource);
232 
233         // Overwrite the actual surface height with the coded height and width of the frame
234         // for VC1 since it's possible for a VC1 frame to change size during playback
235         destSurface->dwWidth = m_width;
236         destSurface->dwHeight = m_height;
237     }
238     else
239     {
240         destSurface   = &m_destSurface;
241         fwdRefSurface = &(vc1RefList[fwdRefIdx]->resRefPic);
242         bwdRefSurface = &(vc1RefList[bwdRefIdx]->resRefPic);
243     }
244 
245     // WA for SP/MP short format
246     if (m_shortFormatInUse &&
247         !m_vc1PicParams->sequence_fields.AdvancedProfileFlag)
248     {
249         CODECHAL_DECODE_CHK_STATUS_RETURN(ConstructBistreamBuffer());
250     }
251 
252     MOS_COMMAND_BUFFER  cmdBuffer;
253     CODECHAL_DECODE_CHK_STATUS_RETURN(m_osInterface->pfnGetCommandBuffer(m_osInterface, &cmdBuffer, 0));
254 
255     auto mmioRegisters = m_hwInterface->GetMfxInterface()->GetMmioRegisters(m_vdboxIndex);
256     HalOcaInterface::On1stLevelBBStart(cmdBuffer, *m_osInterface->pOsContext, m_osInterface->CurrentGpuContextHandle, *m_miInterface, *mmioRegisters);
257 
258     MHW_MI_FORCE_WAKEUP_PARAMS forceWakeupParams;
259     MOS_ZeroMemory(&forceWakeupParams, sizeof(MHW_MI_FORCE_WAKEUP_PARAMS));
260     forceWakeupParams.bMFXPowerWellControl = true;
261     forceWakeupParams.bMFXPowerWellControlMask = true;
262     forceWakeupParams.bHEVCPowerWellControl = false;
263     forceWakeupParams.bHEVCPowerWellControlMask = true;
264     CODECHAL_DECODE_CHK_STATUS_RETURN(m_miInterface->AddMiForceWakeupCmd(
265         &cmdBuffer,
266         &forceWakeupParams));
267 
268     MHW_VDBOX_PIPE_MODE_SELECT_PARAMS   pipeModeSelectParams;
269     pipeModeSelectParams.Mode = m_mode;
270     pipeModeSelectParams.bStreamOutEnabled = m_streamOutEnabled;
271     pipeModeSelectParams.bPostDeblockOutEnable = m_deblockingEnabled;
272     pipeModeSelectParams.bPreDeblockOutEnable  = !m_deblockingEnabled;
273     pipeModeSelectParams.bShortFormatInUse     = m_shortFormatInUse;
274     pipeModeSelectParams.bVC1OddFrameHeight    = m_vc1OddFrameHeight;
275 
276     MHW_VDBOX_SURFACE_PARAMS    surfaceParams;
277     MOS_ZeroMemory(&surfaceParams, sizeof(surfaceParams));
278     surfaceParams.Mode = m_mode;
279     surfaceParams.psSurface = destSurface;
280 
281     MHW_VDBOX_PIPE_BUF_ADDR_PARAMS  pipeBufAddrParams;
282     pipeBufAddrParams.Mode = m_mode;
283     if (m_deblockingEnabled)
284     {
285         pipeBufAddrParams.psPostDeblockSurface = destSurface;
286     }
287     else
288     {
289         pipeBufAddrParams.psPreDeblockSurface = destSurface;
290     }
291 
292 #ifdef _MMC_SUPPORTED
293     CODECHAL_DECODE_CHK_STATUS_RETURN(m_mmc->SetPipeBufAddr(&pipeBufAddrParams));
294 #endif
295 
296         // when there is not a forward or backward reference,
297         // the index is set to the destination frame index
298     m_presReferences[CodechalDecodeFwdRefTop] =
299         m_presReferences[CodechalDecodeFwdRefBottom] =
300             fwdRefSurface;
301     m_presReferences[CodechalDecodeBwdRefTop] =
302         m_presReferences[CodechalDecodeBwdRefBottom] =
303             bwdRefSurface;
304     // special case for second fields
305     if (!m_vc1PicParams->picture_fields.is_first_field &&
306         !m_mfxInterface->IsVc1IPicture(
307             m_vc1PicParams->CurrPic,
308             m_vc1PicParams->picture_fields.is_first_field,
309             m_vc1PicParams->picture_fields.picture_type))
310     {
311         if (m_vc1PicParams->picture_fields.top_field_first)
312         {
313             m_presReferences[CodechalDecodeFwdRefTop] =
314                 &destSurface->OsResource;
315         }
316         else
317         {
318             m_presReferences[CodechalDecodeFwdRefBottom] =
319                 &destSurface->OsResource;
320         }
321     }
322 
323     // set all ref pic addresses to valid addresses for error concealment purpose
324     for (uint32_t i = 0; i < CODEC_MAX_NUM_REF_FRAME_NON_AVC; i++)
325     {
326         if (m_presReferences[i] == nullptr &&
327             MEDIA_IS_WA(m_waTable, WaDummyReference) &&
328             !Mos_ResourceIsNull(&m_dummyReference.OsResource))
329         {
330             m_presReferences[i] = &m_dummyReference.OsResource;
331         }
332     }
333 
334     CODECHAL_DECODE_CHK_STATUS_RETURN(MOS_SecureMemcpy(pipeBufAddrParams.presReferences, sizeof(PMOS_RESOURCE) * CODEC_MAX_NUM_REF_FRAME_NON_AVC, m_presReferences, sizeof(PMOS_RESOURCE) * CODEC_MAX_NUM_REF_FRAME_NON_AVC));
335 
336     pipeBufAddrParams.presMfdDeblockingFilterRowStoreScratchBuffer =
337         &m_resMfdDeblockingFilterRowStoreScratchBuffer;
338 
339     if (m_streamOutEnabled)
340     {
341         pipeBufAddrParams.presStreamOutBuffer =
342             &(m_streamOutBuffer[m_streamOutCurrBufIdx]);
343     }
344 
345 #ifdef _MMC_SUPPORTED
346     CODECHAL_DECODE_CHK_STATUS_RETURN(m_mmc->CheckReferenceList(&pipeBufAddrParams));
347 
348     CODECHAL_DECODE_CHK_STATUS_RETURN(m_mmc->SetRefrenceSync(m_disableDecodeSyncLock, m_disableLockForTranscode));
349 #endif
350 
351     CODECHAL_DEBUG_TOOL(
352         for (int i = 0; i < CODEC_MAX_NUM_REF_FRAME_NON_AVC; i++)
353         {
354             if (pipeBufAddrParams.presReferences[i])
355             {
356                 MOS_SURFACE dstSurface;
357 
358                 MOS_ZeroMemory(&dstSurface, sizeof(MOS_SURFACE));
359                 dstSurface.Format = Format_NV12;
360                 dstSurface.OsResource = *(pipeBufAddrParams.presReferences[i]);
361                 CODECHAL_DECODE_CHK_STATUS_RETURN(CodecHalGetResourceInfo(
362                     m_osInterface,
363                     &dstSurface));
364 
365                 m_debugInterface->m_refIndex = (uint16_t)i;
366                 std::string refSurfName      = "RefSurf[" + std::to_string(static_cast<uint32_t>(m_debugInterface->m_refIndex)) + "]";
367                 CODECHAL_DECODE_CHK_STATUS_RETURN(m_debugInterface->DumpYUVSurface(
368                     &dstSurface,
369                     CodechalDbgAttr::attrDecodeReferenceSurfaces,
370                     refSurfName.data()));
371             }
372         }
373     )
374 
375     MHW_VDBOX_IND_OBJ_BASE_ADDR_PARAMS      indObjBaseAddrParams;
376     MOS_ZeroMemory(&indObjBaseAddrParams, sizeof(indObjBaseAddrParams));
377     indObjBaseAddrParams.Mode = m_mode;
378     if (m_shortFormatInUse &&
379         !m_vc1PicParams->sequence_fields.AdvancedProfileFlag)
380     {
381         indObjBaseAddrParams.dwDataSize     = m_dataSize + CODECHAL_DECODE_VC1_STUFFING_BYTES;
382         indObjBaseAddrParams.presDataBuffer = &m_resPrivateBistreamBuffer;
383     }
384     else
385     {
386         indObjBaseAddrParams.dwDataSize     = m_dataSize;
387         indObjBaseAddrParams.presDataBuffer = &m_resDataBuffer;
388     }
389 
390     MHW_VDBOX_BSP_BUF_BASE_ADDR_PARAMS  bspBufBaseAddrParams;
391     MOS_ZeroMemory(&bspBufBaseAddrParams, sizeof(bspBufBaseAddrParams));
392     bspBufBaseAddrParams.presBsdMpcRowStoreScratchBuffer = &m_resBsdMpcRowStoreScratchBuffer;
393 
394     if (m_vc1PicParams->raw_coding.bitplane_present || m_shortFormatInUse)
395     {
396         bspBufBaseAddrParams.presBitplaneBuffer = &m_resBitplaneBuffer;
397     }
398 
399     MHW_VDBOX_VC1_PRED_PIPE_PARAMS  vc1PredPipeParams;
400     vc1PredPipeParams.pVc1PicParams = m_vc1PicParams;
401     vc1PredPipeParams.ppVc1RefList = vc1RefList;
402 
403     MHW_VDBOX_VC1_PIC_STATE vc1PicState;
404     vc1PicState.pVc1PicParams             = m_vc1PicParams;
405     vc1PicState.Mode = m_mode;
406     vc1PicState.ppVc1RefList = vc1RefList;
407     vc1PicState.wPrevAnchorPictureTFF     = m_prevAnchorPictureTff;
408     vc1PicState.bPrevEvenAnchorPictureIsP = m_prevEvenAnchorPictureIsP;
409     vc1PicState.bPrevOddAnchorPictureIsP  = m_prevOddAnchorPictureIsP;
410 
411     if (m_shortFormatInUse)
412     {
413         // WA for WMP. WMP does not provide REFDIST for I/P pictures correctly
414         if (m_vc1PicParams->sequence_fields.AdvancedProfileFlag &&
415             CodecHal_PictureIsField(m_vc1PicParams->CurrPic) &&
416             (isIPicture || isPPicture) &&
417             m_vc1PicParams->reference_fields.reference_distance_flag)
418         {
419             if (m_vc1PicParams->picture_fields.is_first_field)
420             {
421                 CODECHAL_DECODE_CHK_STATUS_RETURN(ParsePictureHeader());
422                 m_referenceDistance = m_vc1PicParams->reference_fields.reference_distance;
423             }
424             else
425             {
426                 m_vc1PicParams->reference_fields.reference_distance = m_referenceDistance;
427             }
428         }
429 
430         // WA for WMP. WMP does not provide BFRACTION correctly. So parse picture header to get BFRACTION
431         if (isBPicture)
432         {
433             if (m_vc1PicParams->picture_fields.is_first_field)
434             {
435                 CODECHAL_DECODE_CHK_STATUS_RETURN(ParsePictureHeader());
436             }
437         }
438     }
439 
440     MHW_VDBOX_VC1_DIRECTMODE_PARAMS vc1DirectmodeParams;
441     if (m_mode == CODECHAL_DECODE_MODE_VC1VLD)
442     {
443         uint8_t dmvBufferIdx                   = (m_vc1PicParams->CurrPic.PicFlags == PICTURE_BOTTOM_FIELD) ? CODECHAL_DECODE_VC1_DMV_ODD : CODECHAL_DECODE_VC1_DMV_EVEN;
444         vc1DirectmodeParams.presDmvReadBuffer  = &m_resVc1BsdMvData[dmvBufferIdx];
445         vc1DirectmodeParams.presDmvWriteBuffer = &m_resVc1BsdMvData[dmvBufferIdx];
446     }
447 
448     CODECHAL_DECODE_CHK_STATUS_RETURN(SendPrologWithFrameTracking(&cmdBuffer, !m_olpNeeded));
449 
450     if (m_statusQueryReportingEnabled)
451     {
452         CODECHAL_DECODE_CHK_STATUS_RETURN(StartStatusReport(&cmdBuffer));
453     }
454 
455     if (!CodecHal_PictureIsField(m_vc1PicParams->CurrPic) &&
456         m_vc1PicParams->picture_fields.picture_type == vc1SkippedFrame)
457     {
458         // no further picture level commands needed for skipped frames
459         m_osInterface->pfnReturnCommandBuffer(m_osInterface, &cmdBuffer, 0);
460 
461         return eStatus;
462     }
463 
464     CODECHAL_DECODE_CHK_STATUS_RETURN(m_mfxInterface->AddMfxPipeModeSelectCmd(&cmdBuffer, &pipeModeSelectParams));
465 
466 #ifdef _MMC_SUPPORTED
467     CODECHAL_DECODE_CHK_STATUS_RETURN(m_mmc->SetSurfaceState(&surfaceParams));
468 #endif
469     CODECHAL_DECODE_CHK_STATUS_RETURN(m_mfxInterface->AddMfxSurfaceCmd(&cmdBuffer, &surfaceParams));
470 
471     CODECHAL_DECODE_CHK_STATUS_RETURN(m_mfxInterface->AddMfxPipeBufAddrCmd(&cmdBuffer, &pipeBufAddrParams));
472 
473     CODECHAL_DECODE_CHK_STATUS_RETURN(m_mfxInterface->AddMfxIndObjBaseAddrCmd(&cmdBuffer, &indObjBaseAddrParams));
474 
475     if (m_mode == CODECHAL_DECODE_MODE_VC1VLD)
476     {
477         CODECHAL_DECODE_CHK_STATUS_RETURN(m_mfxInterface->AddMfxBspBufBaseAddrCmd(&cmdBuffer, &bspBufBaseAddrParams));
478     }
479 
480     CODECHAL_DECODE_CHK_STATUS_RETURN(m_mfxInterface->AddMfxVc1PredPipeCmd(&cmdBuffer, &vc1PredPipeParams));
481 
482     if (m_intelEntrypointInUse || m_mode == CODECHAL_DECODE_MODE_VC1IT)
483     {
484         CODECHAL_DECODE_CHK_STATUS_RETURN(m_mfxInterface->AddMfxVc1LongPicCmd(&cmdBuffer, &vc1PicState));
485     }
486     else if (m_shortFormatInUse)
487     {
488         CODECHAL_DECODE_CHK_STATUS_RETURN(m_mfxInterface->AddMfdVc1ShortPicCmd(&cmdBuffer, &vc1PicState));
489     }
490     else
491     {
492         CODECHAL_DECODE_ASSERTMESSAGE("Unsupported decode mode.");
493         eStatus = MOS_STATUS_UNKNOWN;
494         return eStatus;
495     }
496 
497     if (m_mode == CODECHAL_DECODE_MODE_VC1VLD)
498     {
499         CODECHAL_DECODE_CHK_STATUS_RETURN(m_mfxInterface->AddMfxVc1DirectmodeCmd(&cmdBuffer, &vc1DirectmodeParams));
500     }
501 
502     m_osInterface->pfnReturnCommandBuffer(m_osInterface, &cmdBuffer, 0);
503 
504     return eStatus;
505 }
506 
DecodePrimitiveLevelVLD()507 MOS_STATUS CodechalDecodeVc1G12::DecodePrimitiveLevelVLD()
508 {
509     MOS_STATUS eStatus = MOS_STATUS_SUCCESS;
510 
511     CODECHAL_DECODE_FUNCTION_ENTER;
512 
513     MOS_SYNC_PARAMS syncParams;
514 
515     // static VC1 slice parameters
516     MHW_VDBOX_VC1_SLICE_STATE vc1SliceState;
517     vc1SliceState.presDataBuffer = &m_resDataBuffer;
518 
519     uint16_t frameFieldHeightInMb;
520     CodecHal_GetFrameFieldHeightInMb(
521         m_vc1PicParams->CurrPic,
522         m_picHeightInMb,
523         frameFieldHeightInMb);
524 
525     CODECHAL_DECODE_CHK_NULL_RETURN(m_osInterface);
526 
527     MOS_COMMAND_BUFFER cmdBuffer;
528     CODECHAL_DECODE_CHK_STATUS_RETURN(m_osInterface->pfnGetCommandBuffer(m_osInterface, &cmdBuffer, 0));
529 
530     if (m_incompletePicture)
531     {
532         MHW_MI_FORCE_WAKEUP_PARAMS forceWakeupParams;
533         MOS_ZeroMemory(&forceWakeupParams, sizeof(MHW_MI_FORCE_WAKEUP_PARAMS));
534         forceWakeupParams.bMFXPowerWellControl = true;
535         forceWakeupParams.bMFXPowerWellControlMask = true;
536         forceWakeupParams.bHEVCPowerWellControl = false;
537         forceWakeupParams.bHEVCPowerWellControlMask = true;
538         CODECHAL_DECODE_CHK_STATUS_RETURN(m_miInterface->AddMiForceWakeupCmd(
539             &cmdBuffer,
540             &forceWakeupParams));
541     }
542 
543     if (!CodecHal_PictureIsField(m_vc1PicParams->CurrPic) &&
544         m_vc1PicParams->picture_fields.picture_type == vc1SkippedFrame)
545     {
546         if (!bSkipFrameReported)
547         {
548             MOS_USER_FEATURE_VALUE_WRITE_DATA userFeatureWriteData;
549             MOS_ZeroMemory(&userFeatureWriteData, sizeof(userFeatureWriteData));
550             userFeatureWriteData.Value.i32Data = true;
551             userFeatureWriteData.ValueID       = __MEDIA_USER_FEATURE_VALUE_SKIP_FRAME_IN_USE_ID;
552             MOS_UserFeature_WriteValues_ID(nullptr, &userFeatureWriteData, 1, m_osInterface->pOsContext);
553             bSkipFrameReported = true;
554         }
555 
556         CODECHAL_DECODE_CHK_STATUS_RETURN(HandleSkipFrame());
557         goto submit;
558     }
559     else
560     {
561         PCODEC_VC1_SLICE_PARAMS slc             = m_vc1SliceParams;
562         bool firstValidSlice = true;
563         int prevValidSlc = 0;
564         for (uint32_t slcCount = 0; slcCount < m_numSlices; slcCount++)
565         {
566             m_vldSliceRecord[slcCount].dwSliceYOffset     = slc->slice_vertical_position;
567             m_vldSliceRecord[slcCount].dwNextSliceYOffset = frameFieldHeightInMb;  // init to last slice
568 
569             int32_t lLength = slc->slice_data_size >> 3;
570             int32_t lOffset = slc->macroblock_offset >> 3;
571 
572             CodechalResLock ResourceLock(m_osInterface, &m_resDataBuffer);
573             auto buf = (uint8_t*)ResourceLock.Lock(CodechalResLock::readOnly);
574             if(buf != nullptr)
575             {
576                 buf += slc->slice_data_offset;
577             }
578             if (lOffset > 3 && buf != nullptr &&
579                 m_vc1PicParams->sequence_fields.AdvancedProfileFlag)
580             {
581                 int i = 0;
582                 int j = 0;
583                 for (i = 0, j = 0; i < lOffset - 1; i++, j++)
584                 {
585                     if (!buf[j] && !buf[j + 1] && buf[j + 2] == 3 && buf[j + 3] < 4)
586                     {
587                         i++, j += 2;
588                     }
589                 }
590                 if (i == lOffset - 1)
591                 {
592                     if (!buf[j] && !buf[j + 1] && buf[j + 2] == 3 && buf[j + 3] < 4)
593                     {
594                         buf[j + 2] = 0;
595                         j++;
596                     }
597                     j++;
598                 }
599                 lOffset = (8 * j + slc->macroblock_offset % 8)>>3;
600             }
601 
602             // Check that the slice data does not overrun the bitstream buffer size
603             if ((slc->slice_data_offset + lLength) > m_dataSize)
604             {
605                 lLength = m_dataSize - slc->slice_data_offset;
606 
607                 if (lLength < 0)
608                 {
609                     lLength = 0;
610                 }
611             }
612 
613             // Error handling for garbage data
614             if (slc->slice_data_offset > m_dataSize)
615             {
616                 slc++;
617                 m_vldSliceRecord[slcCount].dwSkip = true;
618                 continue;
619             }
620 
621             // Check offset not larger than slice length, can have slice length of 0
622             if (lOffset > lLength)
623             {
624                 slc++;
625                 m_vldSliceRecord[slcCount].dwSkip = true;
626                 continue;
627             }
628 
629             // Check that the slices do not overlap, else do not send the lower slice
630             if (!firstValidSlice &&
631                 (m_vldSliceRecord[slcCount].dwSliceYOffset <= m_vldSliceRecord[prevValidSlc].dwSliceYOffset))
632             {
633                 slc++;
634                 m_vldSliceRecord[slcCount].dwSkip = true;
635                 continue;
636             }
637 
638             if (firstValidSlice)
639             {
640                 // Ensure that the first slice starts from 0
641                 m_vldSliceRecord[slcCount].dwSliceYOffset = 0;
642                 slc->slice_vertical_position = 0;
643             }
644             else
645             {
646                 // Set next slice start Y offset of previous slice
647                 m_vldSliceRecord[prevValidSlc].dwNextSliceYOffset =
648                     m_vldSliceRecord[slcCount].dwSliceYOffset;
649             }
650 
651             if (m_shortFormatInUse)
652             {
653                 if (m_vc1PicParams->sequence_fields.AdvancedProfileFlag)
654                 {
655                     if ((slc->macroblock_offset >> 3) < CODECHAL_DECODE_VC1_SC_PREFIX_LENGTH)
656                     {
657                         slc++;
658                         m_vldSliceRecord[slcCount].dwSkip = true;
659                         continue;
660                     }
661 
662                     // set macroblock_offset of the first slice to 0 to avoid crash
663                     if (slcCount == 0)
664                     {
665                         slc->macroblock_offset = CODECHAL_DECODE_VC1_SC_PREFIX_LENGTH << 3;
666                     }
667 
668                     lOffset = CODECHAL_DECODE_VC1_SC_PREFIX_LENGTH;
669                 }
670                 else // Simple Profile or Main Profile
671                 {
672                     {
673                         lOffset = CODECHAL_DECODE_VC1_STUFFING_BYTES - 1;
674                         lLength += CODECHAL_DECODE_VC1_STUFFING_BYTES;
675                         slc->macroblock_offset += CODECHAL_DECODE_VC1_STUFFING_BYTES << 3;
676                         slc->macroblock_offset &= (~0x7); // Clear bit offset of first MB for short format
677                     }
678                 }
679             }
680 
681             m_vldSliceRecord[slcCount].dwOffset = lOffset;
682             m_vldSliceRecord[slcCount].dwLength = lLength - lOffset;
683             firstValidSlice = false;
684             prevValidSlc = slcCount;
685             slc++;
686         }
687 
688         if (m_shortFormatInUse &&
689             m_vc1PicParams->sequence_fields.AdvancedProfileFlag)
690         {
691             CODECHAL_DECODE_CHK_STATUS_RETURN(GetSliceMbDataOffset());
692         }
693 
694         // Reset slc pointer
695         slc -= m_numSlices;
696 
697         //------------------------------------
698         // Fill BSD Object Commands
699         //------------------------------------
700         for (uint32_t slcCount = 0; slcCount < m_numSlices; slcCount++)
701         {
702             if (m_vldSliceRecord[slcCount].dwSkip)
703             {
704                 slc++;
705                 continue;
706             }
707 
708             vc1SliceState.pSlc = slc;
709             vc1SliceState.dwOffset               = m_vldSliceRecord[slcCount].dwOffset;
710             vc1SliceState.dwLength               = m_vldSliceRecord[slcCount].dwLength;
711             vc1SliceState.dwNextVerticalPosition = m_vldSliceRecord[slcCount].dwNextSliceYOffset;
712 
713             CODECHAL_DECODE_CHK_STATUS_RETURN(m_mfxInterface->AddMfdVc1BsdObjectCmd(&cmdBuffer, &vc1SliceState));
714 
715             slc++;
716         }
717 
718         // Free VLD slice record
719         MOS_ZeroMemory(m_vldSliceRecord, (m_numSlices * sizeof(CODECHAL_VC1_VLD_SLICE_RECORD)));
720     }
721 
722     // Check if destination surface needs to be synchronized
723     if (m_unequalFieldWaInUse &&
724         CodecHal_PictureIsField(m_vc1PicParams->CurrPic) &&
725         !m_vc1PicParams->picture_fields.is_first_field)
726     {
727         MHW_MI_FLUSH_DW_PARAMS flushDwParams;
728         MOS_ZeroMemory(&flushDwParams, sizeof(flushDwParams));
729 
730         CODECHAL_DECODE_CHK_STATUS_RETURN(m_miInterface->AddMiFlushDwCmd(&cmdBuffer, &flushDwParams));
731     }
732     else
733     {
734         // Check if destination surface needs to be synchronized
735         syncParams = g_cInitSyncParams;
736         syncParams.GpuContext = m_videoContext;
737         syncParams.presSyncResource         = &m_destSurface.OsResource;
738         syncParams.bReadOnly = false;
739         syncParams.bDisableDecodeSyncLock = m_disableDecodeSyncLock;
740         syncParams.bDisableLockForTranscode = m_disableLockForTranscode;
741 
742         if (!CodecHal_PictureIsField(m_vc1PicParams->CurrPic) ||
743             m_vc1PicParams->picture_fields.is_first_field)
744         {
745             CODECHAL_DECODE_CHK_STATUS_RETURN(m_osInterface->pfnPerformOverlaySync(m_osInterface, &syncParams));
746             CODECHAL_DECODE_CHK_STATUS_RETURN(m_osInterface->pfnResourceWait(m_osInterface, &syncParams));
747 
748             // Update the resource tag (s/w tag) for On-Demand Sync
749             m_osInterface->pfnSetResourceSyncTag(m_osInterface, &syncParams);
750         }
751 
752         MHW_MI_FLUSH_DW_PARAMS flushDwParams;
753         MOS_ZeroMemory(&flushDwParams, sizeof(flushDwParams));
754 
755         CODECHAL_DECODE_CHK_STATUS_RETURN(m_miInterface->AddMiFlushDwCmd(&cmdBuffer, &flushDwParams));
756 
757         // Update the tag in GPU Sync eStatus buffer (H/W Tag) to match the current S/W tag
758         if (m_osInterface->bTagResourceSync &&
759             !(CodecHal_PictureIsField(m_vc1PicParams->CurrPic) && m_vc1PicParams->picture_fields.is_first_field))
760         {
761             CODECHAL_DECODE_CHK_STATUS_RETURN(m_hwInterface->WriteSyncTagToResource(&cmdBuffer, &syncParams));
762         }
763     }
764 
765 submit:
766     if (m_statusQueryReportingEnabled)
767     {
768         CodechalDecodeStatusReport decodeStatusReport;
769 
770         decodeStatusReport.m_statusReportNumber = m_statusReportFeedbackNumber;
771         decodeStatusReport.m_currDecodedPic     = m_vc1PicParams->CurrPic;
772         if (m_olpNeeded)
773         {
774             CODECHAL_DEBUG_TOOL(
775                 decodeStatusReport.m_currDeblockedPic.FrameIdx = (uint8_t)m_vc1PicParams->DeblockedPicIdx;
776                 decodeStatusReport.m_currDeblockedPic.PicFlags = PICTURE_FRAME;)
777             decodeStatusReport.m_deblockedPicResOlp = m_deblockSurface.OsResource;
778         }
779         else
780         {
781             decodeStatusReport.m_currDeblockedPic = m_vc1PicParams->CurrPic;
782         }
783         decodeStatusReport.m_codecStatus = CODECHAL_STATUS_UNAVAILABLE;
784         decodeStatusReport.m_currDecodedPicRes = m_vc1RefList[m_vc1PicParams->CurrPic.FrameIdx]->resRefPic;
785 
786         CODECHAL_DEBUG_TOOL(
787             decodeStatusReport.m_secondField =
788                 (m_vc1PicParams->picture_fields.is_first_field == 1) ? false : true;
789             decodeStatusReport.m_olpNeeded = m_olpNeeded;
790             decodeStatusReport.m_frameType = m_perfType;)
791 
792         CODECHAL_DECODE_CHK_STATUS_RETURN(EndStatusReport(decodeStatusReport, &cmdBuffer));
793     }
794 
795 #if (_DEBUG || _RELEASE_INTERNAL)
796     uint32_t curIdx         = (GetDecodeStatusBuf()->m_currIndex + CODECHAL_DECODE_STATUS_NUM - 1) % CODECHAL_DECODE_STATUS_NUM;
797     uint32_t frameCrcOffset = curIdx * sizeof(CodechalDecodeStatus) + GetDecodeStatusBuf()->m_decFrameCrcOffset + sizeof(uint32_t) * 2;
798     std::vector<MOS_RESOURCE> vSemaResource{GetDecodeStatusBuf()->m_statusBuffer};
799     m_debugInterface->DetectCorruptionHw(m_hwInterface, &m_frameCountTypeBuf, curIdx, frameCrcOffset, vSemaResource, &cmdBuffer, m_frameNum);
800 #endif
801 
802     CODECHAL_DECODE_CHK_STATUS_RETURN(m_miInterface->AddMiBatchBufferEnd(&cmdBuffer, nullptr));
803 
804     m_osInterface->pfnReturnCommandBuffer(m_osInterface, &cmdBuffer, 0);
805 
806     CODECHAL_DEBUG_TOOL(
807         CODECHAL_DECODE_CHK_STATUS_RETURN(m_debugInterface->DumpCmdBuffer(
808             &cmdBuffer,
809             CODECHAL_NUM_MEDIA_STATES,
810             "_DEC"));
811 
812     //CODECHAL_DECODE_CHK_STATUS_RETURN(CodecHal_DbgReplaceAllCommands(
813     //    m_debugInterface,
814     //    &cmdBuffer));
815     )
816 
817     if ( MOS_VE_SUPPORTED(m_osInterface))
818     {
819         CodecHalDecodeSinglePipeVE_PopulateHintParams(m_veState, &cmdBuffer, false);
820     }
821 
822     if (m_huCCopyInUse)
823     {
824         syncParams = g_cInitSyncParams;
825         syncParams.GpuContext = m_videoContextForWa;
826         syncParams.presSyncResource = &m_resSyncObjectWaContextInUse;
827 
828         CODECHAL_DECODE_CHK_STATUS_RETURN(m_osInterface->pfnEngineSignal(m_osInterface, &syncParams));
829 
830         syncParams = g_cInitSyncParams;
831         syncParams.GpuContext = m_videoContext;
832         syncParams.presSyncResource = &m_resSyncObjectWaContextInUse;
833 
834         CODECHAL_DECODE_CHK_STATUS_RETURN(m_osInterface->pfnEngineWait(m_osInterface, &syncParams));
835 
836         m_huCCopyInUse = false;
837     }
838 
839     HalOcaInterface::On1stLevelBBEnd(cmdBuffer, *m_osInterface);
840 
841     CODECHAL_DECODE_CHK_STATUS_RETURN(m_osInterface->pfnSubmitCommandBuffer(m_osInterface, &cmdBuffer, m_videoContextUsesNullHw));
842 
843     CODECHAL_DEBUG_TOOL(
844         m_mmc->UpdateUserFeatureKey(&m_destSurface);)
845 
846     if (m_unequalFieldWaInUse &&
847         CodecHal_PictureIsField(m_vc1PicParams->CurrPic) &&
848         !m_vc1PicParams->picture_fields.is_first_field)
849     {
850         CODECHAL_DECODE_CHK_NULL_RETURN(m_vc1RefList);
851 
852         uint32_t destFrameIdx = m_vc1PicParams->CurrPic.FrameIdx;
853 
854         CODECHAL_DECODE_CHK_STATUS_RETURN(FormatUnequalFieldPicture(
855             m_unequalFieldSurface[m_vc1RefList[destFrameIdx]->dwUnequalFieldSurfaceIdx],
856             m_destSurface,
857             true,
858             m_videoContextUsesNullHw ? true : false));
859     }
860 
861     if (m_olpNeeded)
862     {
863         if (!bOlpReported)
864         {
865             MOS_USER_FEATURE_VALUE_WRITE_DATA userFeatureWriteData;
866             MOS_ZeroMemory(&userFeatureWriteData, sizeof(userFeatureWriteData));
867             userFeatureWriteData.Value.i32Data = m_olpNeeded;
868             userFeatureWriteData.ValueID       = __MEDIA_USER_FEATURE_VALUE_OLP_IN_USE_ID;
869             MOS_UserFeature_WriteValues_ID(nullptr, &userFeatureWriteData, 1, m_osInterface->pOsContext);
870             bOlpReported = true;
871         }
872 
873         CODECHAL_DECODE_CHK_STATUS_RETURN(PerformVc1Olp());
874     }
875     else
876     {
877         if (m_statusQueryReportingEnabled)
878         {
879             CODECHAL_DECODE_CHK_STATUS_RETURN(ResetStatusReport(m_videoContextUsesNullHw));
880         }
881     }
882 
883     // Needs to be re-set for Linux buffer re-use scenarios
884     m_vc1RefList[m_vc1PicParams->CurrPic.FrameIdx]->resRefPic = m_destSurface.OsResource;
885 
886     // Send the signal to indicate decode completion, in case On-Demand Sync is not present
887     if (!(CodecHal_PictureIsField(m_vc1PicParams->CurrPic) &&
888             m_vc1PicParams->picture_fields.is_first_field))
889     {
890         MOS_SYNC_PARAMS syncParams;
891         syncParams = g_cInitSyncParams;
892         syncParams.GpuContext = m_videoContext;
893         syncParams.presSyncResource = &m_destSurface.OsResource;
894 
895         CODECHAL_DECODE_CHK_STATUS_RETURN(m_osInterface->pfnResourceSignal(m_osInterface, &syncParams));
896 
897         if (m_olpNeeded)
898         {
899             syncParams = g_cInitSyncParams;
900             syncParams.GpuContext = m_renderContext;
901             syncParams.presSyncResource = &m_deblockSurface.OsResource;
902 
903             CODECHAL_DECODE_CHK_STATUS_RETURN(m_osInterface->pfnResourceSignal(m_osInterface, &syncParams));
904         }
905     }
906 
907     m_olpNeeded = false;
908 
909     return eStatus;
910 }
911 
DecodePrimitiveLevelIT()912 MOS_STATUS CodechalDecodeVc1G12::DecodePrimitiveLevelIT()
913 {
914     MOS_STATUS eStatus = MOS_STATUS_SUCCESS;
915 
916     CODECHAL_DECODE_FUNCTION_ENTER;
917 
918     MOS_SYNC_PARAMS syncParams;
919 
920     PCODEC_VC1_MB_PARAMS mb = m_vc1MbParams;
921 
922     MHW_VDBOX_VC1_MB_STATE vc1MbState;
923     MOS_ZeroMemory(&vc1MbState, sizeof(vc1MbState));
924 
925     // static VC1 MB parameters
926     vc1MbState.presDataBuffer     = &m_resDataBuffer;
927     vc1MbState.pVc1PicParams      = m_vc1PicParams;
928     vc1MbState.pWaTable = m_waTable;
929     vc1MbState.pDeblockDataBuffer = m_deblockDataBuffer;
930     vc1MbState.dwDataSize         = m_dataSize;
931     vc1MbState.wPicWidthInMb      = m_picWidthInMb;
932     vc1MbState.wPicHeightInMb     = m_picHeightInMb;
933     vc1MbState.PicFlags           = m_vc1PicParams->CurrPic.PicFlags;
934     vc1MbState.bFieldPolarity     = m_fieldPolarity;
935 
936     uint16_t frameFieldHeightInMb;
937     CodecHal_GetFrameFieldHeightInMb(
938         m_vc1PicParams->CurrPic,
939         m_picHeightInMb,
940         frameFieldHeightInMb);
941 
942     CODECHAL_DECODE_CHK_NULL_RETURN(m_osInterface);
943 
944     MOS_COMMAND_BUFFER cmdBuffer;
945     CODECHAL_DECODE_CHK_STATUS_RETURN(m_osInterface->pfnGetCommandBuffer(m_osInterface, &cmdBuffer, 0));
946 
947     if (m_incompletePicture)
948     {
949         MHW_MI_FORCE_WAKEUP_PARAMS forceWakeupParams;
950         MOS_ZeroMemory(&forceWakeupParams, sizeof(MHW_MI_FORCE_WAKEUP_PARAMS));
951         forceWakeupParams.bMFXPowerWellControl = true;
952         forceWakeupParams.bMFXPowerWellControlMask = true;
953         forceWakeupParams.bHEVCPowerWellControl = false;
954         forceWakeupParams.bHEVCPowerWellControlMask = true;
955         CODECHAL_DECODE_CHK_STATUS_RETURN(m_miInterface->AddMiForceWakeupCmd(
956             &cmdBuffer,
957             &forceWakeupParams));
958     }
959 
960     CODECHAL_DECODE_CHK_STATUS_RETURN(m_miInterface->AddMiBatchBufferStartCmd(&cmdBuffer, &m_itObjectBatchBuffer));
961 
962     CODECHAL_DECODE_CHK_STATUS_RETURN(Mhw_LockBb(m_osInterface, &m_itObjectBatchBuffer));
963 
964     PMHW_BATCH_BUFFER batchBuffer = &m_itObjectBatchBuffer;
965 
966     uint32_t mbAddress = 0;
967     uint32_t mbCount;
968     for (mbCount = 0; mbCount < m_numMacroblocks; mbCount++)
969     {
970         vc1MbState.pMb = mb + mbCount;
971 
972         // Skipped MBs before current MB
973         uint16_t skippedMBs = (mbCount) ?
974             (mb[mbCount].mb_address - mb[mbCount - 1].mb_address - 1) :
975             (mb[mbCount].mb_address);
976 
977         while (skippedMBs--)
978         {
979             vc1MbState.bMbHorizOrigin = (uint8_t)(mbAddress % m_picWidthInMb);
980             vc1MbState.bMbVertOrigin  = (uint8_t)(mbAddress / m_picWidthInMb);
981             vc1MbState.bSkipped = true;
982 
983             CODECHAL_DECODE_CHK_STATUS_RETURN(m_mfxInterface->AddMfdVc1ItObjectCmd(batchBuffer, &vc1MbState));
984 
985             mbAddress++;
986         }
987 
988         // Current MB
989         if (mbCount + 1 == m_numMacroblocks)
990         {
991             vc1MbState.dwLength = m_dataSize - mb[mbCount].data_offset;
992         }
993         else
994         {
995             vc1MbState.dwLength = mb[mbCount + 1].data_offset - mb[mbCount].data_offset;
996         }
997 
998         vc1MbState.bMbHorizOrigin = mb[mbCount].mb_address % m_picWidthInMb;
999         vc1MbState.bMbVertOrigin  = mb[mbCount].mb_address / m_picWidthInMb;
1000         vc1MbState.dwOffset = (vc1MbState.dwLength) ? mb[mbCount].data_offset : 0;
1001         vc1MbState.bSkipped = false;
1002 
1003         if (m_vc1PicParams->entrypoint_fields.loopfilter)
1004         {
1005             eStatus = MOS_SecureMemcpy(vc1MbState.DeblockData,
1006                 CODEC_NUM_BLOCK_PER_MB,
1007                 m_deblockDataBuffer + CODEC_NUM_BLOCK_PER_MB * mb[mbCount].mb_address,
1008                 CODEC_NUM_BLOCK_PER_MB);
1009             if (eStatus != MOS_STATUS_SUCCESS)
1010             {
1011                 CODECHAL_DECODE_ASSERTMESSAGE("Failed to copy memory.");
1012                 m_olpNeeded = false;
1013                 return eStatus;
1014             }
1015         }
1016 
1017         if (!mb[mbCount].mb_type.intra_mb)
1018         {
1019             if (mb[mbCount].mb_type.motion_forward || mb[mbCount].mb_type.motion_backward)
1020             {
1021                 PackMotionVectors(
1022                     &vc1MbState,
1023                     (short *)mb[mbCount].motion_vector,
1024                     (short *)vc1MbState.PackedLumaMvs,
1025                     (short *)&vc1MbState.PackedChromaMv);
1026             }
1027             else
1028             {
1029                 mb[mbCount].mb_type.motion_forward = 1;
1030                 MOS_ZeroMemory(vc1MbState.PackedLumaMvs, sizeof(vc1MbState.PackedLumaMvs)); // MV's of zero
1031                 vc1MbState.bMotionSwitch = 0;
1032             }
1033         }
1034 
1035         CODECHAL_DECODE_CHK_STATUS_RETURN(m_mfxInterface->AddMfdVc1ItObjectCmd(batchBuffer, &vc1MbState));
1036 
1037         mbAddress = mb[mbCount].mb_address;
1038     }
1039 
1040     m_fieldPolarity = vc1MbState.bFieldPolarity;
1041 
1042     // skipped MBs at the end
1043     uint16_t skippedMBs = m_picWidthInMb * frameFieldHeightInMb - mb[mbCount - 1].mb_address - 1;
1044 
1045     while (skippedMBs--)
1046     {
1047         vc1MbState.bSkipped = true;
1048         CODECHAL_DECODE_CHK_STATUS_RETURN(m_mfxInterface->AddMfdVc1ItObjectCmd(batchBuffer, &vc1MbState));
1049     }
1050 
1051     CODECHAL_DECODE_CHK_STATUS_RETURN(m_miInterface->AddMiBatchBufferEnd(nullptr, &m_itObjectBatchBuffer));
1052 
1053     CODECHAL_DEBUG_TOOL(
1054         CODECHAL_DECODE_CHK_STATUS_RETURN(m_debugInterface->Dump2ndLvlBatch(
1055             batchBuffer,
1056             CODECHAL_NUM_MEDIA_STATES,
1057             "_DEC"));
1058     )
1059 
1060     CODECHAL_DECODE_CHK_STATUS_RETURN(Mhw_UnlockBb(m_osInterface, &m_itObjectBatchBuffer, true));
1061 
1062     // Check if destination surface needs to be synchronized
1063     if (m_unequalFieldWaInUse &&
1064         CodecHal_PictureIsField(m_vc1PicParams->CurrPic))
1065     {
1066         if (!m_vc1PicParams->picture_fields.is_first_field)
1067         {
1068             MHW_MI_FLUSH_DW_PARAMS flushDwParams;
1069             MOS_ZeroMemory(&flushDwParams, sizeof(flushDwParams));
1070 
1071             CODECHAL_DECODE_CHK_STATUS_RETURN(m_miInterface->AddMiFlushDwCmd(&cmdBuffer, &flushDwParams));
1072         }
1073     }
1074     else
1075     {
1076         syncParams = g_cInitSyncParams;
1077         syncParams.GpuContext = m_videoContext;
1078         syncParams.presSyncResource         = &m_destSurface.OsResource;
1079         syncParams.bReadOnly = false;
1080         syncParams.bDisableDecodeSyncLock = m_disableDecodeSyncLock;
1081         syncParams.bDisableLockForTranscode = m_disableLockForTranscode;
1082 
1083         if (!CodecHal_PictureIsField(m_vc1PicParams->CurrPic) ||
1084             m_vc1PicParams->picture_fields.is_first_field)
1085         {
1086             CODECHAL_DECODE_CHK_STATUS_RETURN(m_osInterface->pfnPerformOverlaySync(m_osInterface, &syncParams));
1087             CODECHAL_DECODE_CHK_STATUS_RETURN(m_osInterface->pfnResourceWait(m_osInterface, &syncParams));
1088 
1089             // Update the resource tag (s/w tag) for On-Demand Sync
1090             m_osInterface->pfnSetResourceSyncTag(m_osInterface, &syncParams);
1091         }
1092 
1093         MHW_MI_FLUSH_DW_PARAMS flushDwParams;
1094         MOS_ZeroMemory(&flushDwParams, sizeof(flushDwParams));
1095 
1096         CODECHAL_DECODE_CHK_STATUS_RETURN(m_miInterface->AddMiFlushDwCmd(&cmdBuffer, &flushDwParams));
1097 
1098         // Update the tag in GPU Sync eStatus buffer (H/W Tag) to match the current S/W tag
1099         if (m_osInterface->bTagResourceSync &&
1100             !(CodecHal_PictureIsField(m_vc1PicParams->CurrPic) && m_vc1PicParams->picture_fields.is_first_field))
1101         {
1102             CODECHAL_DECODE_CHK_STATUS_RETURN(m_hwInterface->WriteSyncTagToResource(&cmdBuffer, &syncParams));
1103         }
1104     }
1105 
1106     if (m_statusQueryReportingEnabled)
1107     {
1108         CodechalDecodeStatusReport decodeStatusReport;
1109 
1110         decodeStatusReport.m_statusReportNumber = m_statusReportFeedbackNumber;
1111         decodeStatusReport.m_currDecodedPic     = m_vc1PicParams->CurrPic;
1112         if (m_olpNeeded)
1113         {
1114             CODECHAL_DEBUG_TOOL(
1115                 decodeStatusReport.m_currDeblockedPic.FrameIdx = (uint8_t)m_vc1PicParams->DeblockedPicIdx;
1116                 decodeStatusReport.m_currDeblockedPic.PicFlags = PICTURE_FRAME;)
1117             decodeStatusReport.m_deblockedPicResOlp = m_deblockSurface.OsResource;
1118         }
1119         else
1120         {
1121             decodeStatusReport.m_currDeblockedPic = m_vc1PicParams->CurrPic;
1122         }
1123         decodeStatusReport.m_codecStatus = CODECHAL_STATUS_UNAVAILABLE;
1124         decodeStatusReport.m_currDecodedPicRes = m_vc1RefList[m_vc1PicParams->CurrPic.FrameIdx]->resRefPic;
1125 
1126         CODECHAL_DEBUG_TOOL(
1127             decodeStatusReport.m_secondField =
1128                 (m_vc1PicParams->picture_fields.is_first_field == 1) ? false : true;
1129             decodeStatusReport.m_olpNeeded = m_olpNeeded;
1130             decodeStatusReport.m_frameType = m_perfType;)
1131 
1132         CODECHAL_DECODE_CHK_STATUS_RETURN(EndStatusReport(decodeStatusReport, &cmdBuffer));
1133     }
1134 
1135     CODECHAL_DECODE_CHK_STATUS_RETURN(m_miInterface->AddMiBatchBufferEnd(&cmdBuffer, nullptr));
1136 
1137     m_osInterface->pfnReturnCommandBuffer(m_osInterface, &cmdBuffer, 0);
1138 
1139     CODECHAL_DEBUG_TOOL(
1140         CODECHAL_DECODE_CHK_STATUS_RETURN(m_debugInterface->DumpCmdBuffer(
1141             &cmdBuffer,
1142             CODECHAL_NUM_MEDIA_STATES,
1143             "_DEC"));
1144 
1145     //CODECHAL_DECODE_CHK_STATUS_RETURN(CodecHal_DbgReplaceAllCommands(
1146     //    m_debugInterface,
1147     //    &cmdBuffer));
1148     )
1149 
1150     if ( MOS_VE_SUPPORTED(m_osInterface))
1151     {
1152         CodecHalDecodeSinglePipeVE_PopulateHintParams(m_veState, &cmdBuffer, false);
1153     }
1154 
1155     if (m_huCCopyInUse)
1156     {
1157         syncParams = g_cInitSyncParams;
1158         syncParams.GpuContext = m_videoContextForWa;
1159         syncParams.presSyncResource = &m_resSyncObjectWaContextInUse;
1160 
1161         CODECHAL_DECODE_CHK_STATUS_RETURN(m_osInterface->pfnEngineSignal(m_osInterface, &syncParams));
1162 
1163         syncParams = g_cInitSyncParams;
1164         syncParams.GpuContext = m_videoContext;
1165         syncParams.presSyncResource = &m_resSyncObjectWaContextInUse;
1166 
1167         CODECHAL_DECODE_CHK_STATUS_RETURN(m_osInterface->pfnEngineWait(m_osInterface, &syncParams));
1168 
1169         m_huCCopyInUse = false;
1170     }
1171 
1172     HalOcaInterface::On1stLevelBBEnd(cmdBuffer, *m_osInterface);
1173 
1174     CODECHAL_DECODE_CHK_STATUS_RETURN(m_osInterface->pfnSubmitCommandBuffer(m_osInterface, &cmdBuffer, m_videoContextUsesNullHw));
1175 
1176     CODECHAL_DEBUG_TOOL(
1177         m_mmc->UpdateUserFeatureKey(&m_destSurface);)
1178 
1179     if (m_unequalFieldWaInUse &&
1180         CodecHal_PictureIsField(m_vc1PicParams->CurrPic) &&
1181         !m_vc1PicParams->picture_fields.is_first_field)
1182     {
1183         CODECHAL_DECODE_CHK_NULL_RETURN(m_vc1RefList);
1184 
1185         uint32_t destFrameIdx = m_vc1PicParams->CurrPic.FrameIdx;
1186 
1187         CODECHAL_DECODE_CHK_STATUS_RETURN(FormatUnequalFieldPicture(
1188             m_unequalFieldSurface[m_vc1RefList[destFrameIdx]->dwUnequalFieldSurfaceIdx],
1189             m_destSurface,
1190             true,
1191             m_videoContextUsesNullHw ? true : false));
1192         }
1193 
1194         if (m_olpNeeded)
1195         {
1196             CODECHAL_DECODE_CHK_STATUS_RETURN(PerformVc1Olp());
1197     }
1198     else
1199     {
1200         if (m_statusQueryReportingEnabled)
1201         {
1202             CODECHAL_DECODE_CHK_STATUS_RETURN(ResetStatusReport(m_videoContextUsesNullHw));
1203         }
1204     }
1205 
1206     // Needs to be re-set for Linux buffer re-use scenarios
1207     m_vc1RefList[m_vc1PicParams->CurrPic.FrameIdx]->resRefPic = m_destSurface.OsResource;
1208 
1209     // Send the signal to indicate decode completion, in case On-Demand Sync is not present
1210     if (!(CodecHal_PictureIsField(m_vc1PicParams->CurrPic) &&
1211             m_vc1PicParams->picture_fields.is_first_field))
1212     {
1213         MOS_SYNC_PARAMS syncParams;
1214         syncParams = g_cInitSyncParams;
1215         syncParams.GpuContext = m_videoContext;
1216         syncParams.presSyncResource = &m_destSurface.OsResource;
1217 
1218         CODECHAL_DECODE_CHK_STATUS_RETURN(m_osInterface->pfnResourceSignal(m_osInterface, &syncParams));
1219 
1220         if (m_olpNeeded)
1221         {
1222             syncParams = g_cInitSyncParams;
1223             syncParams.GpuContext = m_renderContext;
1224             syncParams.presSyncResource = &m_deblockSurface.OsResource;
1225 
1226             CODECHAL_DECODE_CHK_STATUS_RETURN(m_osInterface->pfnResourceSignal(m_osInterface, &syncParams));
1227         }
1228     }
1229 
1230     m_olpNeeded = false;
1231 
1232     return eStatus;
1233 }
1234 
HandleSkipFrame()1235 MOS_STATUS CodechalDecodeVc1G12::HandleSkipFrame()
1236 {
1237     MOS_COMMAND_BUFFER                  cmdBuffer;
1238     MHW_MI_FLUSH_DW_PARAMS              flushDwParams;
1239     MHW_GENERIC_PROLOG_PARAMS           genericPrologParams;
1240     MOS_SURFACE                         srcSurface;
1241     uint8_t                             fwdRefIdx;
1242     uint32_t                            surfaceSize;
1243     MOS_SYNC_PARAMS                     syncParams;
1244     MOS_STATUS                          eStatus = MOS_STATUS_SUCCESS;
1245 
1246     CODECHAL_DECODE_FUNCTION_ENTER;
1247 
1248     fwdRefIdx = (uint8_t)m_vc1PicParams->ForwardRefIdx;
1249 
1250     MOS_ZeroMemory(&srcSurface, sizeof(MOS_SURFACE));
1251     srcSurface.Format = Format_NV12;
1252     srcSurface.OsResource = m_vc1RefList[fwdRefIdx]->resRefPic;
1253     CODECHAL_DECODE_CHK_STATUS_RETURN(CodecHalGetResourceInfo(m_osInterface, &srcSurface));
1254 
1255     CODECHAL_DECODE_CHK_NULL_RETURN(srcSurface.OsResource.pGmmResInfo);
1256     surfaceSize = ((srcSurface.OsResource.pGmmResInfo->GetArraySize()) > 1) ?
1257         ((uint32_t)(srcSurface.OsResource.pGmmResInfo->GetQPitchPlanar(GMM_PLANE_Y) *
1258                     srcSurface.OsResource.pGmmResInfo->GetRenderPitch())) :
1259         (uint32_t)(srcSurface.OsResource.pGmmResInfo->GetSizeMainSurface());
1260 
1261     if (m_hwInterface->m_noHuC)
1262     {
1263         CodechalDataCopyParams dataCopyParams;
1264         MOS_ZeroMemory(&dataCopyParams, sizeof(CodechalDataCopyParams));
1265         dataCopyParams.srcResource = &srcSurface.OsResource;
1266         dataCopyParams.srcSize     = surfaceSize;
1267         dataCopyParams.srcOffset = srcSurface.dwOffset;
1268         dataCopyParams.dstResource = &m_destSurface.OsResource;
1269         dataCopyParams.dstSize     = surfaceSize;
1270         dataCopyParams.dstOffset   = m_destSurface.dwOffset;
1271 
1272         CODECHAL_DECODE_CHK_STATUS_RETURN(m_hwInterface->CopyDataSourceWithDrv(&dataCopyParams));
1273     }
1274     else
1275     {
1276         m_huCCopyInUse = true;
1277 
1278         syncParams = g_cInitSyncParams;
1279         syncParams.GpuContext = m_videoContext;
1280         syncParams.presSyncResource = &m_resSyncObjectVideoContextInUse;
1281 
1282         CODECHAL_DECODE_CHK_STATUS_RETURN(m_osInterface->pfnEngineSignal(m_osInterface, &syncParams));
1283 
1284         syncParams = g_cInitSyncParams;
1285         syncParams.GpuContext = m_videoContextForWa;
1286         syncParams.presSyncResource = &m_resSyncObjectVideoContextInUse;
1287 
1288         CODECHAL_DECODE_CHK_STATUS_RETURN(m_osInterface->pfnEngineWait(m_osInterface, &syncParams));
1289 
1290         CODECHAL_DECODE_CHK_STATUS_RETURN(m_osInterface->pfnSetGpuContext(m_osInterface, m_videoContextForWa));
1291         m_osInterface->pfnResetOsStates(m_osInterface);
1292 
1293         CODECHAL_DECODE_CHK_STATUS_RETURN(m_osInterface->pfnGetCommandBuffer(m_osInterface, &cmdBuffer, 0));
1294 
1295         CODECHAL_DECODE_CHK_STATUS_RETURN(SendPrologWithFrameTracking(&cmdBuffer, false));
1296 
1297         CODECHAL_DECODE_CHK_STATUS_RETURN(HucCopy(
1298             &cmdBuffer,                             // pCmdBuffer
1299             &srcSurface.OsResource,                 // presSrc
1300             &m_destSurface.OsResource,              // presDst
1301             surfaceSize,                            // u32CopyLength
1302             srcSurface.dwOffset,                    // u32CopyInputOffset
1303             m_destSurface.dwOffset));               // u32CopyOutputOffset
1304 #ifdef _MMC_SUPPORTED
1305         auto mmc = static_cast<CodechalMmcDecodeVc1G12*>(m_mmc);
1306         CODECHAL_DECODE_CHK_STATUS_RETURN(mmc->CopyAuxSurfForSkip(&cmdBuffer, &srcSurface.OsResource, &m_destSurface.OsResource));
1307 #endif
1308         syncParams = g_cInitSyncParams;
1309         syncParams.GpuContext = m_videoContextForWa;
1310         syncParams.presSyncResource         = &m_destSurface.OsResource;
1311         syncParams.bReadOnly = false;
1312         syncParams.bDisableDecodeSyncLock = m_disableDecodeSyncLock;
1313         syncParams.bDisableLockForTranscode = m_disableLockForTranscode;
1314 
1315         CODECHAL_DECODE_CHK_STATUS_RETURN(m_osInterface->pfnPerformOverlaySync(m_osInterface, &syncParams));
1316         CODECHAL_DECODE_CHK_STATUS_RETURN(m_osInterface->pfnResourceWait(m_osInterface, &syncParams));
1317 
1318         // Update the resource tag (s/w tag) for On-Demand Sync
1319         m_osInterface->pfnSetResourceSyncTag(m_osInterface, &syncParams);
1320 
1321         // Update the tag in GPU Sync eStatus buffer (H/W Tag) to match the current S/W tag
1322         if (m_osInterface->bTagResourceSync)
1323         {
1324             CODECHAL_DECODE_CHK_STATUS_RETURN(m_hwInterface->WriteSyncTagToResource(
1325                 &cmdBuffer,
1326                 &syncParams));
1327         }
1328 
1329         MOS_ZeroMemory(&flushDwParams, sizeof(flushDwParams));
1330         CODECHAL_DECODE_CHK_STATUS_RETURN(m_miInterface->AddMiFlushDwCmd(
1331             &cmdBuffer,
1332             &flushDwParams));
1333 
1334         CODECHAL_DECODE_CHK_STATUS_RETURN(m_miInterface->AddMiBatchBufferEnd(
1335             &cmdBuffer,
1336             nullptr));
1337 
1338         m_osInterface->pfnReturnCommandBuffer(m_osInterface, &cmdBuffer, 0);
1339 
1340         if ( MOS_VE_SUPPORTED(m_osInterface))
1341         {
1342             CodecHalDecodeSinglePipeVE_PopulateHintParams(m_veState, &cmdBuffer, false);
1343         }
1344 
1345         CODECHAL_DECODE_CHK_STATUS_RETURN(m_osInterface->pfnSubmitCommandBuffer(m_osInterface, &cmdBuffer, m_videoContextUsesNullHw));
1346 
1347         CODECHAL_DECODE_CHK_STATUS_RETURN(m_osInterface->pfnSetGpuContext(m_osInterface, m_videoContext));
1348     }
1349 
1350     return (MOS_STATUS)eStatus;
1351 }
1352 
PerformVc1Olp()1353 MOS_STATUS CodechalDecodeVc1G12::PerformVc1Olp()
1354 {
1355     MOS_STATUS eStatus = MOS_STATUS_SUCCESS;
1356 
1357     CODECHAL_DECODE_FUNCTION_ENTER;
1358 
1359     MhwRenderInterface *renderEngineInterface = m_hwInterface->GetRenderInterface();
1360     PMHW_KERNEL_STATE         kernelState           = &m_olpKernelState;
1361     PMHW_STATE_HEAP_INTERFACE stateHeapInterface = renderEngineInterface->m_stateHeapInterface;
1362 
1363     CODECHAL_DECODE_CHK_NULL_RETURN(stateHeapInterface);
1364 
1365     MOS_SYNC_PARAMS syncParams;
1366     syncParams = g_cInitSyncParams;
1367     syncParams.GpuContext = m_videoContext;
1368     syncParams.presSyncResource = &m_resSyncObject;
1369 
1370     CODECHAL_DECODE_CHK_STATUS_RETURN(m_osInterface->pfnEngineSignal(m_osInterface, &syncParams));
1371 
1372     syncParams = g_cInitSyncParams;
1373     syncParams.GpuContext = m_renderContext;
1374     syncParams.presSyncResource = &m_resSyncObject;
1375 
1376     CODECHAL_DECODE_CHK_STATUS_RETURN(m_osInterface->pfnEngineWait(m_osInterface, &syncParams));
1377 
1378     // Initialize DSH kernel region
1379     m_osInterface->pfnSetGpuContext(m_osInterface, m_renderContext);
1380     m_osInterface->pfnResetOsStates(m_osInterface);
1381 
1382     m_osInterface->pfnSetPerfTag(
1383         m_osInterface,
1384         (uint16_t)(((m_mode << 4) & 0xF0) | OLP_TYPE));
1385     m_osInterface->pfnResetPerfBufferID(m_osInterface);
1386 
1387     CodecHalGetResourceInfo(m_osInterface, &m_deblockSurface);  // DstSurface
1388 
1389     CODECHAL_DECODE_CHK_STATUS_RETURN(stateHeapInterface->pfnRequestSshSpaceForCmdBuf(
1390         stateHeapInterface,
1391         kernelState->KernelParams.iBTCount));
1392 
1393     CODECHAL_DECODE_CHK_STATUS_RETURN(m_hwInterface->AssignDshAndSshSpace(
1394         stateHeapInterface,
1395         kernelState,
1396         false,
1397         m_olpDshSize,
1398         false,
1399         m_decodeStatusBuf.m_swStoreData));
1400 
1401     MHW_INTERFACE_DESCRIPTOR_PARAMS idParams;
1402     MOS_ZeroMemory(&idParams, sizeof(idParams));
1403     idParams.pKernelState = kernelState;
1404     CODECHAL_DECODE_CHK_STATUS_RETURN(stateHeapInterface->pfnSetInterfaceDescriptor(
1405         stateHeapInterface,
1406         1,
1407         &idParams));
1408     CODECHAL_DECODE_CHK_STATUS_RETURN(SetCurbeOlp());
1409 
1410     // Send HW commands (including SSH)
1411     MOS_COMMAND_BUFFER cmdBuffer;
1412     CODECHAL_DECODE_CHK_STATUS_RETURN(m_osInterface->pfnGetCommandBuffer(m_osInterface, &cmdBuffer, 0));
1413 
1414     MHW_PIPE_CONTROL_PARAMS pipeControlParams;
1415     MOS_ZeroMemory(&pipeControlParams, sizeof(pipeControlParams));
1416 
1417     CODECHAL_DECODE_CHK_STATUS_RETURN(m_hwInterface->GetDefaultSSEuSetting(CODECHAL_MEDIA_STATE_OLP, false, false, false));
1418 
1419     CODECHAL_DECODE_CHK_STATUS_RETURN(SendPrologWithFrameTracking(
1420         &cmdBuffer, true));
1421 
1422     if (renderEngineInterface->GetL3CacheConfig()->bL3CachingEnabled)
1423     {
1424         CODECHAL_DECODE_CHK_STATUS_RETURN(renderEngineInterface->SetL3Cache(&cmdBuffer));
1425     }
1426 
1427     CODECHAL_DECODE_CHK_STATUS_RETURN(renderEngineInterface->EnablePreemption(&cmdBuffer));
1428 
1429     CODECHAL_DECODE_CHK_STATUS_RETURN(renderEngineInterface->AddPipelineSelectCmd(&cmdBuffer, false));
1430 
1431     CODECHAL_DECODE_CHK_STATUS_RETURN(stateHeapInterface->pfnSetBindingTable(
1432         stateHeapInterface,
1433         kernelState));
1434 
1435     // common function for codec needed when we make change for AVC
1436     MHW_RCS_SURFACE_PARAMS surfaceParamsSrc;
1437     MOS_ZeroMemory(&surfaceParamsSrc, sizeof(surfaceParamsSrc));
1438     surfaceParamsSrc.dwNumPlanes = 2;    // Y, UV
1439     surfaceParamsSrc.psSurface          = &m_destSurface;
1440     surfaceParamsSrc.psSurface->dwDepth = 1;    // depth needs to be 0 for codec 2D surface
1441                                                 // Y Plane
1442     surfaceParamsSrc.dwBindingTableOffset[MHW_Y_PLANE] = CODECHAL_DECODE_VC1_OLP_SRC_Y;
1443     surfaceParamsSrc.ForceSurfaceFormat[MHW_Y_PLANE] = MHW_GFX3DSTATE_SURFACEFORMAT_R8_UNORM;
1444     // UV Plane
1445     surfaceParamsSrc.dwBindingTableOffset[MHW_U_PLANE] = CODECHAL_DECODE_VC1_OLP_SRC_UV;
1446     surfaceParamsSrc.ForceSurfaceFormat[MHW_U_PLANE] = MHW_GFX3DSTATE_SURFACEFORMAT_R16_UINT;
1447     surfaceParamsSrc.dwBaseAddrOffset[MHW_U_PLANE] =
1448         m_destSurface.dwPitch *
1449         MOS_ALIGN_FLOOR(m_destSurface.UPlaneOffset.iYOffset, MOS_YTILE_H_ALIGNMENT);
1450     surfaceParamsSrc.dwHeightToUse[MHW_U_PLANE] = surfaceParamsSrc.psSurface->dwHeight / 2;
1451     surfaceParamsSrc.dwYOffset[MHW_U_PLANE] =
1452         (m_destSurface.UPlaneOffset.iYOffset % MOS_YTILE_H_ALIGNMENT);
1453     surfaceParamsSrc.dwCacheabilityControl  =
1454         m_hwInterface->GetCacheabilitySettings()[MOS_CODEC_RESOURCE_USAGE_PRE_DEBLOCKING_CODEC].Value;
1455 
1456 #ifdef _MMC_SUPPORTED
1457     if (m_mmc)
1458     {
1459         CODECHAL_SURFACE_CODEC_PARAMS srcSurfaceParam = {};
1460         srcSurfaceParam.psSurface = &m_destSurface;
1461         CODECHAL_DECODE_CHK_STATUS_RETURN(m_mmc->SetSurfaceParams(&srcSurfaceParam));
1462     }
1463 #endif
1464 
1465     MHW_RCS_SURFACE_PARAMS surfaceParamsDst;
1466     MOS_ZeroMemory(&surfaceParamsDst, sizeof(surfaceParamsDst));
1467     surfaceParamsDst = surfaceParamsSrc;
1468     surfaceParamsDst.bIsWritable = true;
1469     surfaceParamsDst.psSurface                         = &m_deblockSurface;
1470     surfaceParamsDst.psSurface->dwDepth = 1;    // depth needs to be 0 for codec 2D surface
1471     surfaceParamsDst.dwBindingTableOffset[MHW_Y_PLANE] = CODECHAL_DECODE_VC1_OLP_DST_Y;
1472     surfaceParamsDst.dwBindingTableOffset[MHW_U_PLANE] = CODECHAL_DECODE_VC1_OLP_DST_UV;
1473     surfaceParamsDst.dwCacheabilityControl =
1474         m_hwInterface->GetCacheabilitySettings()[MOS_CODEC_RESOURCE_USAGE_POST_DEBLOCKING_CODEC].Value;
1475 
1476 #ifdef _MMC_SUPPORTED
1477     if (m_mmc)
1478     {
1479         CODECHAL_SURFACE_CODEC_PARAMS dstSurfaceParam = {};
1480         dstSurfaceParam.psSurface = &m_deblockSurface;
1481         CODECHAL_DECODE_CHK_STATUS_RETURN(m_mmc->SetSurfaceParams(&dstSurfaceParam));
1482     }
1483 #endif
1484 
1485     CODECHAL_DECODE_CHK_STATUS_RETURN(stateHeapInterface->pfnSetSurfaceState(
1486         stateHeapInterface,
1487         kernelState,
1488         &cmdBuffer,
1489         1,
1490         &surfaceParamsSrc));
1491     CODECHAL_DECODE_CHK_STATUS_RETURN(stateHeapInterface->pfnSetSurfaceState(
1492         stateHeapInterface,
1493         kernelState,
1494         &cmdBuffer,
1495         1,
1496         &surfaceParamsDst));
1497 
1498     MHW_STATE_BASE_ADDR_PARAMS stateBaseAddrParams;
1499     MOS_ZeroMemory(&stateBaseAddrParams, sizeof(stateBaseAddrParams));
1500     MOS_RESOURCE *dsh = nullptr, *ish = nullptr;
1501     CODECHAL_DECODE_CHK_NULL_RETURN(dsh = kernelState->m_dshRegion.GetResource());
1502     CODECHAL_DECODE_CHK_NULL_RETURN(ish = kernelState->m_ishRegion.GetResource());
1503     stateBaseAddrParams.presDynamicState = dsh;
1504     stateBaseAddrParams.dwDynamicStateSize = kernelState->m_dshRegion.GetHeapSize();
1505     stateBaseAddrParams.presInstructionBuffer = ish;
1506     stateBaseAddrParams.dwInstructionBufferSize = kernelState->m_ishRegion.GetHeapSize();
1507     stateBaseAddrParams.mocs4GeneralState = m_hwInterface->GetCacheabilitySettings()[MOS_CODEC_RESOURCE_USAGE_SURFACE_UNCACHED].Gen12.Index;
1508     stateBaseAddrParams.mocs4DynamicState = m_hwInterface->GetCacheabilitySettings()[MOS_CODEC_RESOURCE_USAGE_SURFACE_UNCACHED].Gen12.Index;
1509     stateBaseAddrParams.mocs4SurfaceState       = m_hwInterface->GetCacheabilitySettings()[MOS_CODEC_RESOURCE_USAGE_SURFACE_UNCACHED].Gen12.Index;
1510     stateBaseAddrParams.mocs4IndirectObjectBuffer = m_hwInterface->GetCacheabilitySettings()[MOS_CODEC_RESOURCE_USAGE_SURFACE_UNCACHED].Gen12.Index;
1511     stateBaseAddrParams.mocs4StatelessDataport = m_hwInterface->GetCacheabilitySettings()[MOS_CODEC_RESOURCE_USAGE_SURFACE_UNCACHED].Gen12.Index;
1512     CODECHAL_DECODE_CHK_STATUS_RETURN(renderEngineInterface->AddStateBaseAddrCmd(&cmdBuffer, &stateBaseAddrParams));
1513 
1514     MHW_VFE_PARAMS_G12 vfeParams= {};
1515     vfeParams.pKernelState = kernelState;
1516     CODECHAL_DECODE_CHK_STATUS_RETURN(renderEngineInterface->AddMediaVfeCmd(&cmdBuffer, &vfeParams));
1517 
1518     MHW_CURBE_LOAD_PARAMS curbeLoadParams;
1519     MOS_ZeroMemory(&curbeLoadParams, sizeof(curbeLoadParams));
1520     curbeLoadParams.pKernelState = kernelState;
1521     CODECHAL_DECODE_CHK_STATUS_RETURN(renderEngineInterface->AddMediaCurbeLoadCmd(&cmdBuffer, &curbeLoadParams));
1522 
1523     MHW_ID_LOAD_PARAMS idLoadParams;
1524     MOS_ZeroMemory(&idLoadParams, sizeof(idLoadParams));
1525     idLoadParams.pKernelState = kernelState;
1526     idLoadParams.dwNumKernelsLoaded = 1;
1527     CODECHAL_DECODE_CHK_STATUS_RETURN(renderEngineInterface->AddMediaIDLoadCmd(&cmdBuffer, &idLoadParams));
1528 
1529     CODECHAL_DEBUG_TOOL(
1530         CODECHAL_DECODE_CHK_STATUS_RETURN(m_debugInterface->DumpKernelRegion(
1531             CODECHAL_MEDIA_STATE_OLP,
1532             MHW_DSH_TYPE,
1533             kernelState));
1534 
1535     CODECHAL_DECODE_CHK_STATUS_RETURN(m_debugInterface->DumpKernelRegion(
1536         CODECHAL_MEDIA_STATE_OLP,
1537         MHW_SSH_TYPE,
1538         kernelState));
1539     )
1540 
1541     CODECHAL_DECODE_VC1_OLP_PARAMS vc1OlpParams;
1542     vc1OlpParams.pCmdBuffer = &cmdBuffer;
1543     vc1OlpParams.pPipeControlParams = &pipeControlParams;
1544     vc1OlpParams.pStateBaseAddrParams = &stateBaseAddrParams;
1545     vc1OlpParams.pVfeParams = &vfeParams;
1546     vc1OlpParams.pCurbeLoadParams = &curbeLoadParams;
1547     vc1OlpParams.pIdLoadParams = &idLoadParams;
1548     CODECHAL_DECODE_CHK_STATUS_RETURN(AddVc1OlpCmd(&vc1OlpParams));
1549 
1550     // Check if destination surface needs to be synchronized, before command buffer submission
1551     syncParams = g_cInitSyncParams;
1552     syncParams.GpuContext = m_renderContext;
1553     syncParams.presSyncResource         = &m_deblockSurface.OsResource;
1554     syncParams.bReadOnly = false;
1555     syncParams.bDisableDecodeSyncLock = m_disableDecodeSyncLock;
1556     syncParams.bDisableLockForTranscode = m_disableLockForTranscode;
1557 
1558     CODECHAL_DECODE_CHK_STATUS_RETURN(m_osInterface->pfnPerformOverlaySync(m_osInterface, &syncParams));
1559     CODECHAL_DECODE_CHK_STATUS_RETURN(m_osInterface->pfnResourceWait(m_osInterface, &syncParams));
1560 
1561     // Update the resource tag (s/w tag) for On-Demand Sync
1562     m_osInterface->pfnSetResourceSyncTag(m_osInterface, &syncParams);
1563 
1564     // Update GPU Sync tag for on demand synchronization
1565     if (m_osInterface->bTagResourceSync)
1566     {
1567         pipeControlParams.dwFlushMode = MHW_FLUSH_WRITE_CACHE;
1568         CODECHAL_DECODE_CHK_STATUS_RETURN(m_miInterface->AddPipeControl(&cmdBuffer, nullptr, &pipeControlParams));
1569         CODECHAL_DECODE_CHK_STATUS_RETURN(m_hwInterface->WriteSyncTagToResource(&cmdBuffer, &syncParams));
1570     }
1571     CODECHAL_DECODE_CHK_STATUS_RETURN(stateHeapInterface->pfnSubmitBlocks(
1572         stateHeapInterface,
1573         kernelState));
1574     CODECHAL_DECODE_CHK_STATUS_RETURN(stateHeapInterface->pfnUpdateGlobalCmdBufId(
1575         stateHeapInterface));
1576 
1577     // Add PipeControl to invalidate ISP and MediaState to avoid PageFault issue
1578     // This code is temporal and it will be moved to batch buffer end in short
1579     MOS_ZeroMemory(&pipeControlParams, sizeof(pipeControlParams));
1580     pipeControlParams.dwFlushMode = MHW_FLUSH_WRITE_CACHE;
1581     pipeControlParams.bGenericMediaStateClear = true;
1582     pipeControlParams.bIndirectStatePointersDisable = true;
1583     pipeControlParams.bDisableCSStall = false;
1584     CODECHAL_DECODE_CHK_STATUS_RETURN(m_miInterface->AddPipeControl(&cmdBuffer, nullptr, &pipeControlParams));
1585 
1586     CODECHAL_DECODE_CHK_STATUS_RETURN(m_miInterface->AddMiBatchBufferEnd(&cmdBuffer, nullptr));
1587 
1588     // To clear the SSEU values in the hw interface struct, so next kernel can be programmed correctly
1589     CODECHAL_DECODE_CHK_STATUS_RETURN(m_hwInterface->UpdateSSEuForCmdBuffer(&cmdBuffer, false, true));
1590 
1591     m_osInterface->pfnReturnCommandBuffer(m_osInterface, &cmdBuffer, 0);
1592 
1593     CODECHAL_DEBUG_TOOL(
1594         CODECHAL_DECODE_CHK_STATUS_RETURN(m_debugInterface->DumpCmdBuffer(
1595             &cmdBuffer,
1596             CODECHAL_MEDIA_STATE_OLP,
1597             "_DEC"));
1598     )
1599 
1600     if ( MOS_VE_SUPPORTED(m_osInterface))
1601     {
1602         CodecHalDecodeSinglePipeVE_PopulateHintParams(m_veState, &cmdBuffer, false);
1603     }
1604 
1605     CODECHAL_DECODE_CHK_STATUS_RETURN(m_osInterface->pfnSubmitCommandBuffer(m_osInterface, &cmdBuffer, m_renderContextUsesNullHw));
1606 
1607     if (m_statusQueryReportingEnabled)
1608     {
1609         CODECHAL_DECODE_CHK_STATUS_RETURN(ResetStatusReport(m_renderContextUsesNullHw));
1610     }
1611 
1612     m_osInterface->pfnSetGpuContext(m_osInterface, m_videoContext);
1613 
1614     return eStatus;
1615 }
1616 
CodechalDecodeVc1G12(CodechalHwInterface * hwInterface,CodechalDebugInterface * debugInterface,PCODECHAL_STANDARD_INFO standardInfo)1617 CodechalDecodeVc1G12::CodechalDecodeVc1G12(
1618     CodechalHwInterface   *hwInterface,
1619     CodechalDebugInterface* debugInterface,
1620     PCODECHAL_STANDARD_INFO standardInfo) :
1621     CodechalDecodeVc1(hwInterface, debugInterface, standardInfo)
1622 {
1623     CODECHAL_DECODE_FUNCTION_ENTER;
1624 
1625     CODECHAL_DECODE_CHK_NULL_NO_STATUS_RETURN(hwInterface);
1626     CODECHAL_DECODE_CHK_NULL_NO_STATUS_RETURN(m_osInterface);
1627 
1628     m_osInterface->pfnVirtualEngineSupported(m_osInterface, true, true);
1629 
1630     m_olpCurbeStaticDataLength = CODECHAL_DECODE_VC1_CURBE_SIZE_OLP;
1631 
1632     uint32_t kuid = 0;
1633     MOS_STATUS eStatus = MOS_STATUS_SUCCESS;
1634 
1635 #if defined(ENABLE_KERNELS) && !defined(_FULL_OPEN_SOURCE)
1636     eStatus = CodecHalGetKernelBinaryAndSize(
1637         (uint8_t *)IGCODECKRN_G12,
1638         IDR_CODEC_AllVC1_NV12,
1639         &m_olpKernelBase,
1640         &m_olpKernelSize);
1641 #endif
1642 
1643     CODECHAL_DECODE_ASSERT(eStatus == MOS_STATUS_SUCCESS);
1644 
1645     hwInterface->GetStateHeapSettings()->dwNumSyncTags = CODECHAL_DECODE_VC1_NUM_SYNC_TAGS;
1646     hwInterface->GetStateHeapSettings()->dwIshSize =
1647         MOS_ALIGN_CEIL(m_olpKernelSize, (1 << MHW_KERNEL_OFFSET_SHIFT));
1648     hwInterface->GetStateHeapSettings()->dwDshSize = CODECHAL_DECODE_VC1_INITIAL_DSH_SIZE;
1649 }
1650 
~CodechalDecodeVc1G12()1651 CodechalDecodeVc1G12::~CodechalDecodeVc1G12()
1652 {
1653     CODECHAL_DECODE_FUNCTION_ENTER;
1654 
1655     if (m_veState != nullptr)
1656     {
1657         MOS_FreeMemAndSetNull(m_veState);
1658         m_veState = nullptr;
1659     }
1660 }
1661 
CalcRequestedSpace(uint32_t & requestedSize,uint32_t & additionalSizeNeeded,uint32_t & requestedPatchListSize)1662 void CodechalDecodeVc1G12::CalcRequestedSpace(
1663     uint32_t &requestedSize,
1664     uint32_t &additionalSizeNeeded,
1665     uint32_t &requestedPatchListSize)
1666 {
1667     CODECHAL_DECODE_FUNCTION_ENTER;
1668 
1669     requestedSize = m_commandBufferSizeNeeded + m_HucStateCmdBufferSizeNeeded +
1670                     (m_standardDecodeSizeNeeded * (m_decodeParams.m_numSlices + 1));
1671     requestedPatchListSize = m_commandPatchListSizeNeeded + m_HucPatchListSizeNeeded +
1672                              (m_standardDecodePatchListSizeNeeded * (m_decodeParams.m_numSlices + 1));
1673     additionalSizeNeeded = COMMAND_BUFFER_RESERVED_SPACE;
1674 }
1675