xref: /aosp_15_r20/external/intel-media-driver/media_driver/agnostic/common/hw/mhw_sfc.cpp (revision ba62d9d3abf0e404f2022b4cd7a85e107f48596f)
1 /*
2 * Copyright (c) 2014-2018, 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     mhw_sfc.cpp
24 //! \brief    MHW interface for constructing commands for the SFC
25 //! \details  Impelements the functionalities common across all platforms for MHW_SFC
26 //!
27 
28 #include "mhw_sfc.h"
29 #include "mhw_utilities.h"
30 
MhwSfcInterface(PMOS_INTERFACE pOsInterface)31 MhwSfcInterface::MhwSfcInterface(PMOS_INTERFACE pOsInterface)
32 {
33     MHW_FUNCTION_ENTER;
34 
35     MOS_ZeroMemory(&m_outputSurfCtrl, sizeof(m_outputSurfCtrl));
36     MOS_ZeroMemory(&m_avsLineBufferCtrl, sizeof(m_avsLineBufferCtrl));
37     MOS_ZeroMemory(&m_iefLineBufferCtrl, sizeof(m_iefLineBufferCtrl));
38     MOS_ZeroMemory(&m_sfdLineBufferCtrl, sizeof(m_sfdLineBufferCtrl));
39     pfnAddResourceToCmd = nullptr;
40     m_scalingMode       = MHW_SCALING_AVS;
41 
42     if (pOsInterface == nullptr)
43     {
44         MHW_ASSERTMESSAGE("Invalid input pointers provided");
45         return;
46     }
47     if (!pOsInterface->bUsesGfxAddress && !pOsInterface->bUsesPatchList)
48     {
49         MHW_ASSERTMESSAGE("No valid addressing mode indicated");
50         return;
51     }
52 
53     m_osInterface = pOsInterface;
54 
55     if (m_osInterface->bUsesGfxAddress)
56     {
57         pfnAddResourceToCmd = Mhw_AddResourceToCmd_GfxAddress;
58     }
59     else  //PatchList
60     {
61         pfnAddResourceToCmd = Mhw_AddResourceToCmd_PatchList;
62     }
63 }
64 
SetSfcAVSChromaTable(PSFC_AVS_CHROMA_FILTER_COEFF pUVCoeffTable,int32_t * piUVCoefsX,int32_t * piUVCoefsY)65 void MhwSfcInterface::SetSfcAVSChromaTable(
66     PSFC_AVS_CHROMA_FILTER_COEFF        pUVCoeffTable,
67     int32_t                             *piUVCoefsX,
68     int32_t                             *piUVCoefsY)
69 {
70     int32_t i;
71 
72     MHW_CHK_NULL_NO_STATUS_RETURN(pUVCoeffTable);
73     MHW_CHK_NULL_NO_STATUS_RETURN(piUVCoefsX);
74     MHW_CHK_NULL_NO_STATUS_RETURN(piUVCoefsY);
75 
76     for (i = 0; i < NUM_HW_POLYPHASE_TABLES; i++, pUVCoeffTable++)
77     {
78         pUVCoeffTable->DW0.Table1XFilterCoefficient2 = *(piUVCoefsX++);
79         pUVCoeffTable->DW0.Table1XFilterCoefficient3 = *(piUVCoefsX++);
80         pUVCoeffTable->DW1.Table1XFilterCoefficient4 = *(piUVCoefsX++);
81         pUVCoeffTable->DW1.Table1XFilterCoefficient5 = *(piUVCoefsX++);
82 
83         pUVCoeffTable->DW0.Table1YFilterCoefficient2 = *(piUVCoefsY++);
84         pUVCoeffTable->DW0.Table1YFilterCoefficient3 = *(piUVCoefsY++);
85         pUVCoeffTable->DW1.Table1YFilterCoefficient4 = *(piUVCoefsY++);
86         pUVCoeffTable->DW1.Table1YFilterCoefficient5 = *(piUVCoefsY++);
87     }
88 }
89 
SetSfcAVSLumaTable(MOS_FORMAT SrcFormat,PSFC_AVS_LUMA_FILTER_COEFF pCoeffTable,int32_t * piYCoefsX,int32_t * piYCoefsY,bool bUse8x8Filter)90 void MhwSfcInterface::SetSfcAVSLumaTable(
91     MOS_FORMAT                      SrcFormat,
92     PSFC_AVS_LUMA_FILTER_COEFF      pCoeffTable,
93     int32_t                         *piYCoefsX,
94     int32_t                         *piYCoefsY,
95     bool                            bUse8x8Filter)
96 {
97     int32_t i;
98 
99     MHW_CHK_NULL_NO_STATUS_RETURN(pCoeffTable);
100     MHW_CHK_NULL_NO_STATUS_RETURN(piYCoefsX);
101     MHW_CHK_NULL_NO_STATUS_RETURN(piYCoefsY);
102 
103     for (i = 0; i < NUM_HW_POLYPHASE_TABLES; i++, pCoeffTable++)
104     {
105         // 4-tap filtering for G-channel, update only center 4 coeffs.
106         if (IS_RGB32_FORMAT(SrcFormat) && (!bUse8x8Filter))
107         {
108             pCoeffTable->DW0.Table0XFilterCoefficient0 = 0;
109             pCoeffTable->DW0.Table0XFilterCoefficient1 = 0;
110             pCoeffTable->DW1.Table0XFilterCoefficient2 = *(piYCoefsX++);
111             pCoeffTable->DW1.Table0XFilterCoefficient3 = *(piYCoefsX++);
112             pCoeffTable->DW2.Table0XFilterCoefficient4 = *(piYCoefsX++);
113             pCoeffTable->DW2.Table0XFilterCoefficient5 = *(piYCoefsX++);
114             pCoeffTable->DW3.Table0XFilterCoefficient6 = 0;
115             pCoeffTable->DW3.Table0XFilterCoefficient7 = 0;
116 
117             pCoeffTable->DW0.Table0YFilterCoefficient0 = 0;
118             pCoeffTable->DW0.Table0YFilterCoefficient1 = 0;
119             pCoeffTable->DW1.Table0YFilterCoefficient2 = *(piYCoefsY++);
120             pCoeffTable->DW1.Table0YFilterCoefficient3 = *(piYCoefsY++);
121             pCoeffTable->DW2.Table0YFilterCoefficient4 = *(piYCoefsY++);
122             pCoeffTable->DW2.Table0YFilterCoefficient5 = *(piYCoefsY++);
123             pCoeffTable->DW3.Table0YFilterCoefficient6 = 0;
124             pCoeffTable->DW3.Table0YFilterCoefficient7 = 0;
125         }
126         else
127         {
128             pCoeffTable->DW0.Table0XFilterCoefficient0 = *(piYCoefsX++);
129             pCoeffTable->DW0.Table0XFilterCoefficient1 = *(piYCoefsX++);
130             pCoeffTable->DW1.Table0XFilterCoefficient2 = *(piYCoefsX++);
131             pCoeffTable->DW1.Table0XFilterCoefficient3 = *(piYCoefsX++);
132             pCoeffTable->DW2.Table0XFilterCoefficient4 = *(piYCoefsX++);
133             pCoeffTable->DW2.Table0XFilterCoefficient5 = *(piYCoefsX++);
134             pCoeffTable->DW3.Table0XFilterCoefficient6 = *(piYCoefsX++);
135             pCoeffTable->DW3.Table0XFilterCoefficient7 = *(piYCoefsX++);
136 
137             pCoeffTable->DW0.Table0YFilterCoefficient0 = *(piYCoefsY++);
138             pCoeffTable->DW0.Table0YFilterCoefficient1 = *(piYCoefsY++);
139             pCoeffTable->DW1.Table0YFilterCoefficient2 = *(piYCoefsY++);
140             pCoeffTable->DW1.Table0YFilterCoefficient3 = *(piYCoefsY++);
141             pCoeffTable->DW2.Table0YFilterCoefficient4 = *(piYCoefsY++);
142             pCoeffTable->DW2.Table0YFilterCoefficient5 = *(piYCoefsY++);
143             pCoeffTable->DW3.Table0YFilterCoefficient6 = *(piYCoefsY++);
144             pCoeffTable->DW3.Table0YFilterCoefficient7 = *(piYCoefsY++);
145         }
146     }
147 }
148 
SetSfcSamplerTable(PMHW_SFC_AVS_LUMA_TABLE pLumaTable,PMHW_SFC_AVS_CHROMA_TABLE pChromaTable,PMHW_AVS_PARAMS pAvsParams,MOS_FORMAT SrcFormat,float fScaleX,float fScaleY,uint32_t dwChromaSiting,bool bUse8x8Filter,float fHPStrength,float fLanczosT)149 MOS_STATUS MhwSfcInterface::SetSfcSamplerTable(
150     PMHW_SFC_AVS_LUMA_TABLE         pLumaTable,
151     PMHW_SFC_AVS_CHROMA_TABLE       pChromaTable,
152     PMHW_AVS_PARAMS                 pAvsParams,
153     MOS_FORMAT                      SrcFormat,
154     float                           fScaleX,
155     float                           fScaleY,
156     uint32_t                        dwChromaSiting,
157     bool                            bUse8x8Filter,
158     float                           fHPStrength,
159     float                           fLanczosT)
160 {
161     int32_t                             iPhaseOffset;
162 
163     int32_t     *piYCoefsX, *piYCoefsY;
164     int32_t     *piUVCoefsX, *piUVCoefsY;
165     MHW_PLANE   Plane;
166 
167     MHW_CHK_NULL_RETURN(pLumaTable);
168     MHW_CHK_NULL_RETURN(pChromaTable);
169     MHW_CHK_NULL_RETURN(pAvsParams);
170 
171     piYCoefsX   = pAvsParams->piYCoefsX;
172     piYCoefsY   = pAvsParams->piYCoefsY;
173     piUVCoefsX  = pAvsParams->piUVCoefsX;
174     piUVCoefsY  = pAvsParams->piUVCoefsY;
175 
176     //  Skip calculation if no changes to AVS parameters
177     if (SrcFormat == pAvsParams->Format  &&
178         fScaleX   == pAvsParams->fScaleX &&
179         fScaleY   == pAvsParams->fScaleY)
180     {
181         return MOS_STATUS_SUCCESS;
182     }
183 
184     // AVS Coefficients don't change for Scaling Factors > 1.0x
185     // Hence recalculation is avoided
186     if (fScaleX > 1.0F && pAvsParams->fScaleX > 1.0F)
187     {
188         pAvsParams->fScaleX = fScaleX;
189     }
190 
191     // AVS Coefficients don't change for Scaling Factors > 1.0x
192     // Hence recalculation is avoided
193     if (fScaleY > 1.0F && pAvsParams->fScaleY > 1.0F)
194     {
195         pAvsParams->fScaleY = fScaleY;
196     }
197 
198     // Recalculate Horizontal scaling table
199     if (SrcFormat != pAvsParams->Format || fScaleX != pAvsParams->fScaleX)
200     {
201         MOS_ZeroMemory(
202             piYCoefsX,
203             8 * 32 * sizeof(int32_t));
204 
205         MOS_ZeroMemory(
206             piUVCoefsX,
207             4 * 32 * sizeof(int32_t));
208 
209         // 4-tap filtering for RGB format G-channel.
210         Plane = IS_RGB32_FORMAT(SrcFormat) ? MHW_U_PLANE : MHW_Y_PLANE;
211 
212         pAvsParams->fScaleX = fScaleX;
213 
214         // Nearest, overwrite the coefficients.
215         if (m_scalingMode == MHW_SCALING_NEAREST)
216         {
217             MHW_CHK_STATUS_RETURN(Mhw_SetNearestModeTable(
218                 piYCoefsX,
219                 Plane,
220                 true));
221 
222             MHW_CHK_STATUS_RETURN(Mhw_SetNearestModeTable(
223                 piUVCoefsX,
224                 MHW_U_PLANE,
225                 true));
226         }
227         else
228         {
229             // By default AVS coefficients
230             // For 1x scaling in horizontal direction and not force polyphase coefs, use special coefficients for filtering
231             if (fScaleX == 1.0F && !pAvsParams->bForcePolyPhaseCoefs)
232             {
233                 MHW_CHK_STATUS_RETURN(Mhw_SetNearestModeTable(
234                     piYCoefsX,
235                     Plane,
236                     true));
237 
238                 MHW_CHK_STATUS_RETURN(Mhw_SetNearestModeTable(
239                     piUVCoefsX,
240                     MHW_U_PLANE,
241                     true));
242             }
243             else
244             {
245                 // Clamp the Scaling Factor if > 1.0x
246                 fScaleX = MOS_MIN(1.0F, fScaleX);
247 
248                 MHW_CHK_STATUS_RETURN(Mhw_CalcPolyphaseTablesY(
249                     piYCoefsX,
250                     fScaleX,
251                     Plane,
252                     SrcFormat,
253                     fHPStrength,
254                     bUse8x8Filter,
255                     NUM_HW_POLYPHASE_TABLES,
256                     fLanczosT));
257             }
258 
259             // If Chroma Siting info is present
260             if (dwChromaSiting & MHW_CHROMA_SITING_HORZ_LEFT)
261             {
262                 // No Chroma Siting
263                 MHW_CHK_STATUS_RETURN(Mhw_CalcPolyphaseTablesUV(
264                     piUVCoefsX,
265                     2.0F,
266                     fScaleX));
267             }
268             else
269             {
270                 // Chroma siting offset needs to be added
271                 if (dwChromaSiting & MHW_CHROMA_SITING_HORZ_CENTER)
272                 {
273                     iPhaseOffset = MOS_UF_ROUND(0.5F * 16.0F);   // U0.4
274                 }
275                 else //if (ChromaSiting & MHW_CHROMA_SITING_HORZ_RIGHT)
276                 {
277                     iPhaseOffset = MOS_UF_ROUND(1.0F * 16.0F);   // U0.4
278                 }
279 
280                 MHW_CHK_STATUS_RETURN(Mhw_CalcPolyphaseTablesUVOffset(
281                     piUVCoefsX,
282                     3.0F,
283                     fScaleX,
284                     iPhaseOffset));
285             }
286         }
287     }
288 
289     // Recalculate Vertical scaling table
290     if (SrcFormat != pAvsParams->Format || fScaleY != pAvsParams->fScaleY)
291     {
292         MOS_ZeroMemory(piYCoefsY, 8 * 32 * sizeof(int32_t));
293 
294         MOS_ZeroMemory(piUVCoefsY, 4 * 32 * sizeof(int32_t));
295 
296         // 4-tap filtering for RGB format G-channel.
297         Plane = IS_RGB32_FORMAT(SrcFormat) ? MHW_U_PLANE : MHW_Y_PLANE;
298 
299         pAvsParams->fScaleY = fScaleY;
300 
301         // Nearest, overwrite the coefficients.
302         if (m_scalingMode == MHW_SCALING_NEAREST)
303         {
304             MHW_CHK_STATUS_RETURN(Mhw_SetNearestModeTable(
305                 piYCoefsY,
306                 Plane,
307                 true));
308 
309             MHW_CHK_STATUS_RETURN(Mhw_SetNearestModeTable(
310                 piUVCoefsY,
311                 MHW_U_PLANE,
312                 true));
313         }
314         else
315         {
316             // For 1x scaling in vertical direction and not force polyphase coefs, use special coefficients for filtering
317             if (fScaleY == 1.0F && !pAvsParams->bForcePolyPhaseCoefs)
318             {
319                 MHW_CHK_STATUS_RETURN(Mhw_SetNearestModeTable(
320                     piYCoefsY,
321                     Plane,
322                     true));
323 
324                 MHW_CHK_STATUS_RETURN(Mhw_SetNearestModeTable(
325                     piUVCoefsY,
326                     MHW_U_PLANE,
327                     true));
328             }
329             else
330             {
331                 // Clamp the Scaling Factor if > 1.0x
332                 fScaleY = MOS_MIN(1.0F, fScaleY);
333 
334                 MHW_CHK_STATUS_RETURN(Mhw_CalcPolyphaseTablesY(
335                     piYCoefsY,
336                     fScaleY,
337                     Plane,
338                     SrcFormat,
339                     fHPStrength,
340                     bUse8x8Filter,
341                     NUM_HW_POLYPHASE_TABLES,
342                     fLanczosT));
343             }
344 
345             // If Chroma Siting info is present
346             if (dwChromaSiting & MHW_CHROMA_SITING_VERT_TOP)
347             {
348                 // No Chroma Siting
349                 MHW_CHK_STATUS_RETURN(Mhw_CalcPolyphaseTablesUV(
350                     piUVCoefsY,
351                     2.0F,
352                     fScaleY));
353             }
354             else
355             {
356                 // Chroma siting offset needs to be added
357                 if (dwChromaSiting & MHW_CHROMA_SITING_VERT_CENTER)
358                 {
359                     iPhaseOffset = MOS_UF_ROUND(0.5F * 16.0F);   // U0.4
360                 }
361                 else //if (ChromaSiting & MHW_CHROMA_SITING_VERT_BOTTOM)
362                 {
363                     iPhaseOffset = MOS_UF_ROUND(1.0F * 16.0F);   // U0.4
364                 }
365 
366                 MHW_CHK_STATUS_RETURN(Mhw_CalcPolyphaseTablesUVOffset(
367                     piUVCoefsY,
368                     3.0F,
369                     fScaleY,
370                     iPhaseOffset));
371             }
372         }
373     }
374 
375     // Save format used to calculate AVS parameters
376     pAvsParams->Format = SrcFormat;
377 
378     SetSfcAVSLumaTable(
379         SrcFormat,
380         pLumaTable->LumaTable,
381         piYCoefsX,
382         piYCoefsY,
383         bUse8x8Filter);
384 
385     SetSfcAVSChromaTable(
386         pChromaTable->ChromaTable,
387         piUVCoefsX,
388         piUVCoefsY);
389 
390     return MOS_STATUS_SUCCESS;
391 }
392 
GetInputFrameWidthHeightAlignUnit(uint32_t & widthAlignUnit,uint32_t & heightAlignUnit,bool bVdbox,CODECHAL_STANDARD codecStandard,CodecDecodeJpegChromaType jpegChromaType)393 MOS_STATUS MhwSfcInterface::GetInputFrameWidthHeightAlignUnit(uint32_t &widthAlignUnit, uint32_t &heightAlignUnit,
394     bool bVdbox, CODECHAL_STANDARD codecStandard, CodecDecodeJpegChromaType jpegChromaType)
395 {
396     if (bVdbox)
397     {
398         if (CODECHAL_JPEG == codecStandard &&( jpegYUV400 == jpegChromaType ||
399             jpegYUV444 == jpegChromaType || jpegYUV422H2Y == jpegChromaType) ||
400             jpegBGR == jpegChromaType || jpegRGB == jpegChromaType)
401         {
402             widthAlignUnit = 8;
403             heightAlignUnit = 8;
404             return MOS_STATUS_SUCCESS;
405         }
406         else if (CODECHAL_HEVC == codecStandard || CODECHAL_VP9 == codecStandard)
407         {
408             widthAlignUnit = 8;
409             heightAlignUnit = 8;
410             return MOS_STATUS_SUCCESS;
411         }
412         else if (CODECHAL_AV1 == codecStandard)
413         {
414             widthAlignUnit  = 1;
415             heightAlignUnit = 1;
416             return MOS_STATUS_SUCCESS;
417         }
418         else
419         {
420             widthAlignUnit = 16;
421             heightAlignUnit = 16;
422             return MOS_STATUS_SUCCESS;
423         }
424     }
425     else
426     {
427         widthAlignUnit = m_veWidthAlignment;
428         heightAlignUnit = m_veHeightAlignment;
429         return MOS_STATUS_SUCCESS;
430     }
431 }
432