xref: /aosp_15_r20/external/intel-media-driver/media_softlet/agnostic/common/vp/hal/features/vp_fc_filter.cpp (revision ba62d9d3abf0e404f2022b4cd7a85e107f48596f)
1 /*
2 * Copyright (c) 2020-2022, Intel Corporation
3 *
4 * Permission is hereby granted, free of charge, to any person obtaining a
5 * copy of this software and associated documentation files (the "Software"),
6 * to deal in the Software without restriction, including without limitation
7 * the rights to use, copy, modify, merge, publish, distribute, sublicense,
8 * and/or sell copies of the Software, and to permit persons to whom the
9 * Software is furnished to do so, subject to the following conditions:
10 *
11 * The above copyright notice and this permission notice shall be included
12 * in all copies or substantial portions of the Software.
13 *
14 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
15 * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
16 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
17 * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR
18 * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
19 * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
20 * OTHER DEALINGS IN THE SOFTWARE.
21 */
22 //!
23 //! \file     vp_fc_filter.cpp
24 //! \brief    Defines the common interface for denoise
25 //!           this file is for the base interface which is shared by all fc in driver.
26 //!
27 #include "vp_fc_filter.h"
28 #include "vp_render_cmd_packet.h"
29 #include "hw_filter.h"
30 #include "sw_filter_pipe.h"
31 #include "vp_hal_ddi_utils.h"
32 #include <vector>
33 
34 namespace vp {
35 
36 static MOS_STATUS IsChromaSamplingNeeded(bool &isChromaUpSamplingNeeded, bool &isChromaDownSamplingNeeded,
37                                         VPHAL_SURFACE_TYPE surfType, int layerIndex,
38                                         MOS_FORMAT inputFormat, MOS_FORMAT outputFormat);
39 
40 bool PolicyFcHandler::s_forceNearestToBilinearIfBilinearExists = false;
41 
VpFcFilter(PVP_MHWINTERFACE vpMhwInterface)42 VpFcFilter::VpFcFilter(PVP_MHWINTERFACE vpMhwInterface) :
43     VpFilter(vpMhwInterface)
44 {
45 
46 }
47 
Init()48 MOS_STATUS VpFcFilter::Init()
49 {
50     VP_FUNC_CALL();
51 
52     return MOS_STATUS_SUCCESS;
53 }
54 
Prepare()55 MOS_STATUS VpFcFilter::Prepare()
56 {
57     VP_FUNC_CALL();
58 
59     return MOS_STATUS_SUCCESS;
60 }
61 
Destroy()62 MOS_STATUS VpFcFilter::Destroy()
63 {
64     VP_FUNC_CALL();
65 
66     if (m_renderFcParams)
67     {
68         MOS_FreeMemory(m_renderFcParams);
69         m_renderFcParams = nullptr;
70     }
71 
72     return MOS_STATUS_SUCCESS;
73 }
74 
SetExecuteEngineCaps(SwFilterPipe * executedPipe,VP_EXECUTE_CAPS vpExecuteCaps)75 MOS_STATUS VpFcFilter::SetExecuteEngineCaps(
76     SwFilterPipe *executedPipe,
77     VP_EXECUTE_CAPS vpExecuteCaps)
78 {
79     VP_FUNC_CALL();
80 
81     m_executedPipe  = executedPipe;
82     m_executeCaps   = vpExecuteCaps;
83 
84     return MOS_STATUS_SUCCESS;
85 }
86 
InitLayer(VP_FC_LAYER & layer,bool isInputPipe,int index,SwFilterPipe & executedPipe,VPHAL_SCALING_MODE defaultScalingMode)87 MOS_STATUS VpFcFilter::InitLayer(VP_FC_LAYER &layer, bool isInputPipe, int index, SwFilterPipe &executedPipe, VPHAL_SCALING_MODE defaultScalingMode)
88 {
89     auto &surfGroup             = executedPipe.GetSurfacesSetting().surfGroup;
90 
91     SurfaceType surfId          = isInputPipe ? (SurfaceType)(SurfaceTypeFcInputLayer0 + index) : SurfaceTypeFcTarget0;
92     auto        surfHandle = surfGroup.find(surfId);
93     VP_PUBLIC_CHK_NOT_FOUND_RETURN(surfHandle, &surfGroup);
94     layer.surf = surfHandle->second;
95 
96     VP_PUBLIC_CHK_NULL_RETURN(layer.surf);
97 
98     layer.layerID               = index;
99     layer.layerIDOrigin         = index;
100 
101     SwFilterScaling *scaling    = dynamic_cast<SwFilterScaling *>(executedPipe.GetSwFilter(isInputPipe, index, FeatureType::FeatureTypeScaling));
102     layer.scalingMode           = scaling ? scaling->GetSwFilterParams().scalingMode : defaultScalingMode;
103     layer.iscalingEnabled       = scaling ? ISCALING_INTERLEAVED_TO_INTERLEAVED == scaling->GetSwFilterParams().interlacedScalingType : false;
104     layer.fieldWeaving          = scaling ? ISCALING_FIELD_TO_INTERLEAVED == scaling->GetSwFilterParams().interlacedScalingType : false;
105 
106     SwFilterRotMir *rotation    = dynamic_cast<SwFilterRotMir *>(executedPipe.GetSwFilter(isInputPipe, index, FeatureType::FeatureTypeRotMir));
107     layer.rotation              = rotation ? rotation->GetSwFilterParams().rotation : VPHAL_ROTATION_IDENTITY;
108 
109     layer.useSampleUnorm        = false;    // Force using sampler16 (dscaler) when compute walker in use.
110     layer.useSamplerLumakey     = false;    // Only available on AVS sampler.
111     layer.iefEnabled            = false;    // IEF not supported by 3D sampler.
112 
113     layer.paletteID             = -1;       //!<Palette Allocation
114     layer.queryVariance         = layer.surf->bQueryVariance;
115 
116     SwFilterDeinterlace *di     = dynamic_cast<SwFilterDeinterlace *>(executedPipe.GetSwFilter(isInputPipe, index, FeatureType::FeatureTypeDi));
117     layer.diParams              = di ? di->GetSwFilterParams().diParams : nullptr;
118 
119     SwFilterLumakey *lumakey    = dynamic_cast<SwFilterLumakey *>(executedPipe.GetSwFilter(isInputPipe, index, FeatureType::FeatureTypeLumakey));
120     layer.lumaKeyParams         = lumakey ? lumakey->GetSwFilterParams().lumaKeyParams : nullptr;
121 
122     SwFilterBlending *blending  = dynamic_cast<SwFilterBlending *>(executedPipe.GetSwFilter(isInputPipe, index, FeatureType::FeatureTypeBlending));
123     layer.blendingParams        = blending ? blending->GetSwFilterParams().blendingParams : nullptr;
124     layer.xorComp               = blending ? BLEND_XOR_MONO == blending->GetSwFilterParams().blendingParams->BlendType : false;
125 
126     SwFilterProcamp *procamp    = dynamic_cast<SwFilterProcamp *>(executedPipe.GetSwFilter(isInputPipe, index, FeatureType::FeatureTypeProcamp));
127     layer.procampParams         = procamp ? procamp->GetSwFilterParams().procampParams : nullptr;
128 
129     surfId                      = (SurfaceType)(SurfaceTypeFcInputLayer0Field1Dual + index);
130 
131     auto it = surfGroup.find(surfId);
132     if (surfGroup.end() == it)
133     {
134         layer.surfField = nullptr;
135     }
136     else
137     {
138         layer.surfField = surfGroup.find(surfId)->second;
139     }
140 
141     return MOS_STATUS_SUCCESS;
142 }
143 
GetDefaultScalingMode(VPHAL_SCALING_MODE & defaultScalingMode,SwFilterPipe & executedPipe)144 MOS_STATUS VpFcFilter::GetDefaultScalingMode(VPHAL_SCALING_MODE& defaultScalingMode,SwFilterPipe &executedPipe)
145 {
146     bool isInited = false;
147     // Select default scaling mode for 3D sampler.
148     defaultScalingMode = VPHAL_SCALING_NEAREST;
149 
150     if (!PolicyFcHandler::s_forceNearestToBilinearIfBilinearExists)
151     {
152         return MOS_STATUS_SUCCESS;
153     }
154 
155     for (uint32_t i = 0; i < executedPipe.GetSurfaceCount(true); ++i)
156     {
157         SwFilterScaling *scaling    = dynamic_cast<SwFilterScaling *>(executedPipe.GetSwFilter(true, i, FeatureType::FeatureTypeScaling));
158         if (scaling &&
159             (VPHAL_SCALING_NEAREST == scaling->GetSwFilterParams().scalingMode ||
160             VPHAL_SCALING_BILINEAR == scaling->GetSwFilterParams().scalingMode))
161         {
162             if (isInited)
163             {
164                 if (scaling->GetSwFilterParams().scalingMode != defaultScalingMode)
165                 {
166                     VP_PUBLIC_ASSERTMESSAGE("Different 3D sampler scaling mode being selected!");
167                     VP_PUBLIC_CHK_STATUS_RETURN(MOS_STATUS_INVALID_PARAMETER);
168                 }
169             }
170             else
171             {
172                 defaultScalingMode = scaling->GetSwFilterParams().scalingMode;
173                 isInited = true;
174             }
175         }
176     }
177 
178     return MOS_STATUS_SUCCESS;
179 }
180 
InitCompParams(VP_COMPOSITE_PARAMS & compParams,SwFilterPipe & executedPipe)181 MOS_STATUS VpFcFilter::InitCompParams(VP_COMPOSITE_PARAMS &compParams, SwFilterPipe &executedPipe)
182 {
183     MOS_ZeroMemory(&compParams, sizeof(compParams));
184     auto &surfGroup = executedPipe.GetSurfacesSetting().surfGroup;
185     compParams.sourceCount = executedPipe.GetSurfaceCount(true);
186 
187     if (SurfaceTypeFcInputLayer0 + compParams.sourceCount - 1 > SurfaceTypeFcInputLayerMax)
188     {
189         VP_RENDER_ASSERTMESSAGE("Invalid source count (%d)!", compParams.sourceCount);
190         VP_RENDER_CHK_STATUS_RETURN(MOS_STATUS_INVALID_PARAMETER);
191     }
192 
193     // Select default scaling mode for 3D sampler.
194     VPHAL_SCALING_MODE defaultScalingMode = VPHAL_SCALING_NEAREST;
195     VP_PUBLIC_CHK_STATUS_RETURN(GetDefaultScalingMode(defaultScalingMode, executedPipe));
196 
197     for (uint32_t i = 0; i < executedPipe.GetSurfaceCount(true); ++i)
198     {
199         VP_RENDER_CHK_STATUS_RETURN(InitLayer(compParams.source[i], true, i, executedPipe, defaultScalingMode));
200     }
201 
202     compParams.targetCount = 1;
203     VP_RENDER_CHK_STATUS_RETURN(InitLayer(compParams.target[0], false, 0, executedPipe, defaultScalingMode));
204 
205     SwFilterColorFill *colorFill        = dynamic_cast<SwFilterColorFill *>(executedPipe.GetSwFilter(false, 0, FeatureType::FeatureTypeColorFill));
206     compParams.pColorFillParams         = colorFill ? colorFill->GetSwFilterParams().colorFillParams : nullptr;
207 
208     SwFilterAlpha *alpha                = dynamic_cast<SwFilterAlpha *>(executedPipe.GetSwFilter(false, 0, FeatureType::FeatureTypeAlpha));
209     compParams.pCompAlpha               = alpha ? alpha->GetSwFilterParams().compAlpha : nullptr;
210     // Enable alpha calculating
211     compParams.bAlphaCalculateEnable    = alpha ? alpha->GetSwFilterParams().calculatingAlpha : false;
212 
213     VP_RENDER_CHK_STATUS_RETURN(CalculateCompParams(compParams));
214 
215     return MOS_STATUS_SUCCESS;
216 }
217 
AdjustParamsBasedOnFcLimit(VP_COMPOSITE_PARAMS & compParams)218 MOS_STATUS VpFcFilter::AdjustParamsBasedOnFcLimit(VP_COMPOSITE_PARAMS &compParams)
219 {
220     //The kernel is using the rectangle data to calculate mask. If the rectangle configuration does not comply to kernel requirement, the mask calculation will be incorrect and will see corruption.
221     if (compParams.pColorFillParams == nullptr &&
222         compParams.sourceCount == 1 &&
223         compParams.targetCount == 1 &&
224         compParams.target[0].surf != nullptr &&
225         compParams.source[0].surf != nullptr)
226     {
227         if (compParams.target[0].surf->rcDst.top <= compParams.source[0].surf->rcDst.top &&
228             compParams.target[0].surf->rcDst.left <= compParams.source[0].surf->rcDst.left &&
229             compParams.target[0].surf->rcDst.right >= compParams.source[0].surf->rcDst.right &&
230             compParams.target[0].surf->rcDst.bottom >= compParams.source[0].surf->rcDst.bottom)
231         {
232             VP_RENDER_NORMALMESSAGE("Render Path : 1 Surface to 1 Surface FC Composition. ColorFill is Disabled. Output Dst is bigger than Input Dst. Will make Output Dst become Input Dst to Avoid FC Corruption. (%d %d %d %d) -> (%d %d %d %d)",
233                 compParams.target[0].surf->rcDst.left,
234                 compParams.target[0].surf->rcDst.top,
235                 compParams.target[0].surf->rcDst.right,
236                 compParams.target[0].surf->rcDst.bottom,
237                 compParams.source[0].surf->rcDst.left,
238                 compParams.source[0].surf->rcDst.top,
239                 compParams.source[0].surf->rcDst.right,
240                 compParams.source[0].surf->rcDst.bottom);
241             compParams.target[0].surf->rcSrc = compParams.source[0].surf->rcDst;
242             compParams.target[0].surf->rcDst = compParams.source[0].surf->rcDst;
243         }
244     }
245 
246     return MOS_STATUS_SUCCESS;
247 }
248 
249 
CalculateCompParams(VP_COMPOSITE_PARAMS & compParams)250 MOS_STATUS VpFcFilter::CalculateCompParams(VP_COMPOSITE_PARAMS &compParams)
251 {
252     int layerCount = 0;
253 
254     VP_RENDER_CHK_STATUS_RETURN(AdjustParamsBasedOnFcLimit(compParams));
255 
256     for (uint32_t i = 0; i < compParams.sourceCount; ++i)
257     {
258         VP_FC_LAYER *layer = &compParams.source[i];
259         auto params = &layer->calculatedParams;
260         auto params2 = &layer->calculatedParams2;
261 
262         VP_RENDER_CHK_STATUS_RETURN(CalculateConstantAlpha(params->alpha, *layer));
263 
264         if (layerCount != i)
265         {
266             compParams.source[layerCount] = *layer;
267             layer = &compParams.source[layerCount];
268             params = &layer->calculatedParams;
269             params2 = &layer->calculatedParams2;
270         }
271         layer->layerIDOrigin = i;
272         layer->layerID = layerCount++;
273 
274         VP_RENDER_CHK_STATUS_RETURN(CalculateScalingParams(layer, &compParams.target[0], params->fScaleX, params->fScaleY,
275             params->fOffsetX, params->fOffsetY, params->fShiftX, params->fShiftY, params->clipedDstRect,
276             params->isChromaUpSamplingNeeded, params->isChromaDownSamplingNeeded, params->samplerFilterMode,
277             params2->fStepX, params2->fStepY));
278 
279         if (params->isChromaUpSamplingNeeded || params->isChromaDownSamplingNeeded)
280         {
281             if (!MEDIA_IS_WA(m_pvpMhwInterface->m_waTable, WaEnableDscale)                      ||
282                 (MEDIA_IS_WA(m_pvpMhwInterface->m_waTable, WaEnableDscale)                      &&
283                  layer->scalingMode == VPHAL_SCALING_BILINEAR  &&
284                  params->fScaleX >= (float)(1.0/3.0)                     &&
285                  params->fScaleY >= (float)(1.0/3.0)))
286             {
287                 params->chromaSitingEnabled = true;
288             }
289             else
290             {
291                 params->chromaSitingEnabled = false;
292             }
293         }
294         else
295         {
296             params->chromaSitingEnabled = false;
297         }
298     }
299 
300     compParams.sourceCount = layerCount;
301 
302     return MOS_STATUS_SUCCESS;
303 }
304 
CalculateConstantAlpha(uint16_t & alpha,VP_FC_LAYER & layer)305 MOS_STATUS VpFcFilter::CalculateConstantAlpha(uint16_t &alpha, VP_FC_LAYER &layer)
306 {
307     alpha = 255;
308     //-----------------------------------
309     // Alpha blending optimization.
310     // If Constant blending and one of the following is true, disable blending.
311     // If Src+Constant blending and one of the following is true, fall back to Src blending.
312     // Condition; alpha <= 0. Layer is 100% transparent.
313     // Condition; alpha >= 1. Layer is 100% opaque.
314     //-----------------------------------
315     if (layer.blendingParams &&
316         ((layer.blendingParams->BlendType == BLEND_CONSTANT) ||
317          (layer.blendingParams->BlendType == BLEND_CONSTANT_SOURCE) ||
318          (layer.blendingParams->BlendType == BLEND_CONSTANT_PARTIAL)))
319     {
320         float fAlpha = layer.blendingParams->fAlpha;
321 
322         // Don't render layer with alpha <= 0.0f
323         if (fAlpha <= 0.0f)
324         {
325             // layer is not visible. Should not come to here as the transparent should
326             // have been removed during PolicyFcHandler::LayerSelectForProcess.
327             VP_RENDER_ASSERTMESSAGE("Transparent layer found, which is not expected in current function!");
328             VP_RENDER_CHK_STATUS_RETURN(MOS_STATUS_INVALID_PARAMETER);
329         }
330         else
331         {
332             alpha  = (uint16_t) (255.0f * fAlpha);
333         }
334 
335         VP_RENDER_NORMALMESSAGE("Layer %d: BlendType %d, fAlpha %d",
336             layer.layerID,
337             layer.blendingParams->BlendType,
338             layer.blendingParams->fAlpha);
339 
340         if (fAlpha >= 1.0f || alpha >= 255)
341         {
342             if (layer.blendingParams->BlendType == BLEND_CONSTANT)
343             {
344                 layer.blendingParams->BlendType = BLEND_NONE;
345             }
346             else // for BlendType == BLEND_CONSTANT_SOURCE
347             {
348                 layer.blendingParams->BlendType = BLEND_SOURCE;
349             }
350 
351             layer.blendingParams->fAlpha    = 1.0f;
352             alpha = 255;
353         }
354     }
355     return MOS_STATUS_SUCCESS;
356 }
357 
358 // x,y scaling steps
359 // cropping
CalculateScalingParams(VP_FC_LAYER * layer,VP_FC_LAYER * target,float & fScaleX,float & fScaleY,float & fOffsetX,float & fOffsetY,float & fShiftX,float & fShiftY,RECT & clipedDstRect,bool & isChromaUpSamplingNeeded,bool & isChromaDownSamplingNeeded,MHW_SAMPLER_FILTER_MODE & samplerFilterMode,float & fStepX,float & fStepY)360 MOS_STATUS VpFcFilter::CalculateScalingParams(VP_FC_LAYER *layer, VP_FC_LAYER *target, float &fScaleX, float &fScaleY,
361     float &fOffsetX, float &fOffsetY, float &fShiftX , float &fShiftY, RECT &clipedDstRect,
362     bool &isChromaUpSamplingNeeded, bool &isChromaDownSamplingNeeded, MHW_SAMPLER_FILTER_MODE &samplerFilterMode,
363     float &fStepX, float &fStepY)
364 {
365     float       fDiScaleY = 1.0f;                          // BOB scaling factor for Y
366     float       fCropX = 0, fCropY = 0;
367     float samplerLinearBiasX = VP_SAMPLER_BIAS;     //!< Linear sampler bias X
368     float samplerLinearBiasY = VP_SAMPLER_BIAS;     //!< Linear sampler bias Y
369 
370     VP_RENDER_CHK_NULL_RETURN(layer);
371     VP_RENDER_CHK_NULL_RETURN(target);
372 
373     // x,y scaling factor
374     fScaleX = 1.0;
375     fScaleY = 1.0;
376 
377     fOffsetX = samplerLinearBiasX;
378     fOffsetY = samplerLinearBiasY;
379 
380     // Source rectangle is pre-rotated, destination rectangle is post-rotated.
381     if (layer->rotation == VPHAL_ROTATION_IDENTITY    ||
382         layer->rotation == VPHAL_ROTATION_180         ||
383         layer->rotation == VPHAL_MIRROR_HORIZONTAL    ||
384         layer->rotation == VPHAL_MIRROR_VERTICAL)
385     {
386         fScaleX      = (float)(layer->surf->rcDst.right  - layer->surf->rcDst.left) /
387                         (float)(layer->surf->rcSrc.right  - layer->surf->rcSrc.left);
388         fScaleY      = (float)(layer->surf->rcDst.bottom - layer->surf->rcDst.top) /
389                         (float)(layer->surf->rcSrc.bottom - layer->surf->rcSrc.top);
390     }
391     else
392     {
393         // VPHAL_ROTATION_90 || VPHAL_ROTATION_270 ||
394         // VPHAL_ROTATE_90_MIRROR_HORIZONTAL || VPHAL_ROTATE_90_MIRROR_VERTICAL
395         fScaleX      = (float)(layer->surf->rcDst.right  - layer->surf->rcDst.left) /
396                         (float)(layer->surf->rcSrc.bottom  - layer->surf->rcSrc.top);
397         fScaleY      = (float)(layer->surf->rcDst.bottom - layer->surf->rcDst.top) /
398                         (float)(layer->surf->rcSrc.right - layer->surf->rcSrc.left);
399     }
400 
401 
402     // if 1:1 scaling and interlaced scaling or field weaving
403     // do not adjust offsets since it uses Nearest sampling
404     if (fScaleX == 1.0F &&
405         fScaleY == 1.0F &&
406         (layer->iscalingEnabled || layer->fieldWeaving))
407     {
408         fDiScaleY = 0.5f;
409     }
410     else
411     {
412         switch (layer->surf->SampleType)
413         {
414             case SAMPLE_INTERLEAVED_EVEN_FIRST_TOP_FIELD:
415             case SAMPLE_INTERLEAVED_ODD_FIRST_TOP_FIELD:
416                 fDiScaleY = 0.5f;
417                 // don't break
418             case SAMPLE_SINGLE_TOP_FIELD:
419                 fOffsetY += 0.25f;
420                 break;
421 
422             case SAMPLE_INTERLEAVED_EVEN_FIRST_BOTTOM_FIELD:
423             case SAMPLE_INTERLEAVED_ODD_FIRST_BOTTOM_FIELD:
424                 fDiScaleY = 0.5f;
425                 // don't break
426             case SAMPLE_SINGLE_BOTTOM_FIELD:
427                 fOffsetY -= 0.25f;
428                 break;
429 
430             case SAMPLE_PROGRESSIVE:
431             default:
432                 fDiScaleY = 1.0f;
433                 break;
434         }
435     }
436 
437     // Normalize source co-ordinates using the width and height programmed
438     // in surface state. step X, Y pre-rotated
439     // Source rectangle is pre-rotated, destination rectangle is post-rotated.
440     if (layer->rotation == VPHAL_ROTATION_IDENTITY    ||
441         layer->rotation == VPHAL_ROTATION_180         ||
442         layer->rotation == VPHAL_MIRROR_HORIZONTAL    ||
443         layer->rotation == VPHAL_MIRROR_VERTICAL)
444     {
445         fStepX = ((layer->surf->rcSrc.right - layer->surf->rcSrc.left - fCropX) * 1.0f) /
446                     ((layer->surf->rcDst.right - layer->surf->rcDst.left) > 0 ?
447                     (layer->surf->rcDst.right - layer->surf->rcDst.left) : 1);
448         fStepY = ((layer->surf->rcSrc.bottom - layer->surf->rcSrc.top - fCropY) * fDiScaleY) /
449                     ((layer->surf->rcDst.bottom - layer->surf->rcDst.top) > 0 ?
450                     (layer->surf->rcDst.bottom - layer->surf->rcDst.top) : 1);
451     }
452     else
453     {
454         // VPHAL_ROTATION_90 || VPHAL_ROTATION_270 ||
455         // VPHAL_ROTATE_90_MIRROR_HORIZONTAL || VPHAL_ROTATE_90_MIRROR_VERTICAL
456         fStepX = ((layer->surf->rcSrc.right - layer->surf->rcSrc.left - fCropX) * 1.0f) /
457                     ((layer->surf->rcDst.bottom - layer->surf->rcDst.top) > 0 ?
458                     (layer->surf->rcDst.bottom - layer->surf->rcDst.top) : 1);
459         fStepY = ((layer->surf->rcSrc.bottom - layer->surf->rcSrc.top - fCropY) * fDiScaleY) /
460                     ((layer->surf->rcDst.right - layer->surf->rcDst.left) > 0 ?
461                     (layer->surf->rcDst.right - layer->surf->rcDst.left) : 1);
462     }
463 
464     // Source sampling coordinates based on rcSrc
465     fOffsetX += (layer->surf->rcSrc.left + fCropX / 2);
466     fOffsetY += (layer->surf->rcSrc.top + fCropY / 2) * fDiScaleY;
467 
468     isChromaUpSamplingNeeded = false;
469     isChromaDownSamplingNeeded = false;
470     VP_PUBLIC_CHK_STATUS_RETURN(IsChromaSamplingNeeded(isChromaUpSamplingNeeded, isChromaDownSamplingNeeded,
471                                                     layer->surf->SurfType, layer->layerID,
472                                                     layer->surf->osSurface->Format, target->surf->osSurface->Format));
473 
474     if (VPHAL_SCALING_NEAREST == layer->scalingMode && (isChromaUpSamplingNeeded || isChromaDownSamplingNeeded))
475     {
476         VP_PUBLIC_NORMALMESSAGE("Scaling Info: Nearest scaling with isChromaUpSamplingNeeded (%d) and isChromaDownSamplingNeeded (%d)",
477             isChromaUpSamplingNeeded, isChromaDownSamplingNeeded);
478     }
479 
480     // Use 3D Nearest Mode only for 1x Scaling in both directions and only if the input is Progressive or interlaced scaling is used
481     // In case of two or more layers, set Sampler State to Bilinear if any layer requires Bilinear
482     // When primary surface needs chroma upsampling,
483     // force to use 3D Bilinear Mode for 1x scaling for better quality
484     samplerFilterMode = Get3DSamperFilterMode(layer->scalingMode);
485 
486     if (samplerFilterMode == MHW_SAMPLER_FILTER_NEAREST)
487     {
488         fShiftX  = 0.0f;
489         fShiftY  = 0.0f;
490     }
491     else if (samplerFilterMode == MHW_SAMPLER_FILTER_BILINEAR)
492     {
493         fShiftX = VP_HW_LINEAR_SHIFT;  // Bilinear scaling shift
494         fShiftY = VP_HW_LINEAR_SHIFT;
495     }
496     else
497     {
498         VP_PUBLIC_CHK_STATUS_RETURN(MOS_STATUS_INVALID_PARAMETER);
499     }
500 
501     clipedDstRect = layer->surf->rcDst;
502     uint32_t dwDestRectWidth  = target->surf->osSurface->dwWidth;
503     uint32_t dwDestRectHeight = target->surf->osSurface->dwHeight;
504     switch (layer->rotation)
505     {
506         case VPHAL_ROTATION_IDENTITY:
507             // Coordinate adjustment for render target coordinates (0,0)
508             fShiftX  -= layer->surf->rcDst.left;
509             fShiftY  -= layer->surf->rcDst.top;
510             break;
511         case VPHAL_ROTATION_90:
512             // Coordinate adjustment for 90 degree rotation
513             fShiftX  -= (float)layer->surf->rcDst.top;
514             fShiftY  -= (float)dwDestRectWidth -
515                         (float)(layer->surf->rcSrc.bottom - layer->surf->rcSrc.top) * fScaleX -
516                         (float)layer->surf->rcDst.left;
517             break;
518         case VPHAL_ROTATION_180:
519             // Coordinate adjustment for 180 degree rotation
520             fShiftX  -= (float)dwDestRectWidth -
521                         (float)(layer->surf->rcSrc.right - layer->surf->rcSrc.left) * fScaleX -
522                         (float)layer->surf->rcDst.left;
523             fShiftY  -= (float)dwDestRectHeight -
524                         (float)(layer->surf->rcSrc.bottom - layer->surf->rcSrc.top) * fScaleY -
525                         (float)layer->surf->rcDst.top;
526             break;
527         case VPHAL_ROTATION_270:
528             // Coordinate adjustment for 270 degree rotation
529             fShiftX  -= (float)dwDestRectHeight -
530                         (float)(layer->surf->rcSrc.right - layer->surf->rcSrc.left) * fScaleY -
531                         (float)layer->surf->rcDst.top;
532             fShiftY  -= (float)layer->surf->rcDst.left;
533             break;
534         case VPHAL_MIRROR_HORIZONTAL:
535             // Coordinate adjustment for horizontal mirroring
536             fShiftX  -= (float)dwDestRectWidth -
537                         (float)(layer->surf->rcSrc.right - layer->surf->rcSrc.left) * fScaleX -
538                         (float)layer->surf->rcDst.left;
539             fShiftY  -= layer->surf->rcDst.top;
540             break;
541         case VPHAL_MIRROR_VERTICAL:
542             // Coordinate adjustment for vertical mirroring
543             fShiftX  -= layer->surf->rcDst.left;
544             fShiftY  -= (float)dwDestRectHeight -
545                         (float)(layer->surf->rcSrc.bottom - layer->surf->rcSrc.top) * fScaleY -
546                         (float)layer->surf->rcDst.top;
547             break;
548         case VPHAL_ROTATE_90_MIRROR_HORIZONTAL:
549             // Coordinate adjustment for rotating 90 and horizontal mirroring
550             fShiftX  -= (float)layer->surf->rcDst.top;
551             fShiftY  -= (float)layer->surf->rcDst.left;
552             break;
553         case VPHAL_ROTATE_90_MIRROR_VERTICAL:
554         default:
555             // Coordinate adjustment for rotating 90 and vertical mirroring
556             fShiftX  -= (float)dwDestRectHeight -
557                         (float)(layer->surf->rcSrc.right - layer->surf->rcSrc.left) * fScaleY -
558                         (float)layer->surf->rcDst.top;
559             fShiftY  -= (float)dwDestRectWidth -
560                         (float)(layer->surf->rcSrc.bottom - layer->surf->rcSrc.top) * fScaleX -
561                         (float)layer->surf->rcDst.left;
562             break;
563     } // switch
564 
565     if (layer->xorComp)
566     {
567         // for cursor layer, every bit indicate 1 pixel. should extend the width as real output pixel.
568         clipedDstRect.right =
569             clipedDstRect.left + (clipedDstRect.right - clipedDstRect.left) * 8;
570     }
571 
572     return MOS_STATUS_SUCCESS;
573 }
574 
Get3DSamperFilterMode(VPHAL_SCALING_MODE scalingMode)575 MHW_SAMPLER_FILTER_MODE VpFcFilter::Get3DSamperFilterMode(VPHAL_SCALING_MODE scalingMode)
576 {
577     return (VPHAL_SCALING_NEAREST == scalingMode) ? MHW_SAMPLER_FILTER_NEAREST : MHW_SAMPLER_FILTER_BILINEAR;
578 }
579 
CalculateEngineParams()580 MOS_STATUS VpFcFilter::CalculateEngineParams()
581 {
582     VP_FUNC_CALL();
583     if (m_executeCaps.bRender)
584     {
585         // create a filter Param buffer
586         if (!m_renderFcParams)
587         {
588             m_renderFcParams = (PRENDER_FC_PARAMS)MOS_AllocAndZeroMemory(sizeof(RENDER_FC_PARAMS));
589 
590             if (m_renderFcParams == nullptr)
591             {
592                 VP_PUBLIC_ASSERTMESSAGE("render fc Pamas buffer allocate failed, return nullpointer");
593                 return MOS_STATUS_NO_SPACE;
594             }
595         }
596         else
597         {
598             MOS_ZeroMemory(m_renderFcParams, sizeof(RENDER_FC_PARAMS));
599         }
600 
601         m_renderFcParams->kernelId           = kernelCombinedFc;
602         InitCompParams(m_renderFcParams->compParams, *m_executedPipe);
603     }
604     else
605     {
606         VP_PUBLIC_ASSERTMESSAGE("Wrong engine caps! Vebox should be used for Dn");
607     }
608     return MOS_STATUS_SUCCESS;
609 }
610 
611 
612 /****************************************************************************************************/
613 /*                                   HwFilter Fc Parameter                                          */
614 /****************************************************************************************************/
Create(HW_FILTER_FC_PARAM & param,FeatureType featureType)615 HwFilterParameter *HwFilterFcParameter::Create(HW_FILTER_FC_PARAM &param, FeatureType featureType)
616 {
617     VP_FUNC_CALL();
618 
619     HwFilterFcParameter *p = MOS_New(HwFilterFcParameter, featureType);
620     if (p)
621     {
622         if (MOS_FAILED(p->Initialize(param)))
623         {
624             MOS_Delete(p);
625             return nullptr;
626         }
627     }
628     return p;
629 }
630 
HwFilterFcParameter(FeatureType featureType)631 HwFilterFcParameter::HwFilterFcParameter(FeatureType featureType) : HwFilterParameter(featureType)
632 {
633 }
634 
~HwFilterFcParameter()635 HwFilterFcParameter::~HwFilterFcParameter()
636 {
637 }
638 
ConfigParams(HwFilter & hwFilter)639 MOS_STATUS HwFilterFcParameter::ConfigParams(HwFilter &hwFilter)
640 {
641     VP_FUNC_CALL();
642 
643     return hwFilter.ConfigParam(m_Params);
644 }
645 
Initialize(HW_FILTER_FC_PARAM & param)646 MOS_STATUS HwFilterFcParameter::Initialize(HW_FILTER_FC_PARAM &param)
647 {
648     VP_FUNC_CALL();
649 
650     m_Params = param;
651     return MOS_STATUS_SUCCESS;
652 }
653 
654 /****************************************************************************************************/
655 /*                                   Packet Fc Parameter                                       */
656 /****************************************************************************************************/
Create(HW_FILTER_FC_PARAM & param)657 VpPacketParameter *VpRenderFcParameter::Create(HW_FILTER_FC_PARAM &param)
658 {
659     VP_FUNC_CALL();
660 
661     if (nullptr == param.pPacketParamFactory)
662     {
663         return nullptr;
664     }
665     VpRenderFcParameter *p = dynamic_cast<VpRenderFcParameter *>(param.pPacketParamFactory->GetPacketParameter(param.pHwInterface));
666     if (p)
667     {
668         if (MOS_FAILED(p->Initialize(param)))
669         {
670             VpPacketParameter *pParam = p;
671             param.pPacketParamFactory->ReturnPacketParameter(pParam);
672             return nullptr;
673         }
674     }
675     return p;
676 }
677 
VpRenderFcParameter(PVP_MHWINTERFACE pHwInterface,PacketParamFactoryBase * packetParamFactory)678 VpRenderFcParameter::VpRenderFcParameter(PVP_MHWINTERFACE pHwInterface, PacketParamFactoryBase *packetParamFactory) :
679     VpPacketParameter(packetParamFactory), m_fcFilter(pHwInterface)
680 {
681 }
~VpRenderFcParameter()682 VpRenderFcParameter::~VpRenderFcParameter() {}
683 
SetPacketParam(VpCmdPacket * pPacket)684 bool VpRenderFcParameter::SetPacketParam(VpCmdPacket *pPacket)
685 {
686     VP_FUNC_CALL();
687 
688     VpRenderCmdPacket *renderPacket = dynamic_cast<VpRenderCmdPacket *>(pPacket);
689     if (nullptr == renderPacket)
690     {
691         return false;
692     }
693 
694     PRENDER_FC_PARAMS params = m_fcFilter.GetFcParams();
695     if (nullptr == params)
696     {
697         return false;
698     }
699     return MOS_SUCCEEDED(renderPacket->SetFcParams(params));
700 }
701 
Initialize(HW_FILTER_FC_PARAM & params)702 MOS_STATUS VpRenderFcParameter::Initialize(HW_FILTER_FC_PARAM &params)
703 {
704     VP_FUNC_CALL();
705 
706     VP_PUBLIC_CHK_STATUS_RETURN(m_fcFilter.Init());
707     VP_PUBLIC_CHK_STATUS_RETURN(m_fcFilter.SetExecuteEngineCaps(params.executedPipe, params.vpExecuteCaps));
708     VP_PUBLIC_CHK_STATUS_RETURN(m_fcFilter.CalculateEngineParams());
709     return MOS_STATUS_SUCCESS;
710 }
711 
712 /****************************************************************************************************/
713 /*                                   Policy FC Feature Handler                                      */
714 /****************************************************************************************************/
715 
UpdateFeaturePipe(VP_EXECUTE_CAPS caps,SwFilter & feature,SwFilterPipe & featurePipe,SwFilterPipe & executePipe,bool isInputPipe,int index)716 MOS_STATUS PolicyFcFeatureHandler::UpdateFeaturePipe(VP_EXECUTE_CAPS caps, SwFilter &feature, SwFilterPipe &featurePipe, SwFilterPipe &executePipe, bool isInputPipe, int index)
717 {
718     VP_FUNC_CALL();
719 
720     FeatureType type = feature.GetFeatureType();
721 
722     if (caps.bRenderHdr)
723     {
724         // HDR Kernel
725         return PolicyFeatureHandler::UpdateFeaturePipe(caps, feature, featurePipe, executePipe, isInputPipe, index);
726     }
727     else
728     {
729         // FC
730         if (FeatureTypeLumakeyOnRender      == type ||
731             FeatureTypeBlendingOnRender     == type ||
732             FeatureTypeAlphaOnRender        == type ||
733             FeatureTypeCscOnRender          == type ||
734             FeatureTypeScalingOnRender      == type ||
735             FeatureTypeRotMirOnRender       == type ||
736             FeatureTypeDiOnRender           == type ||
737             FeatureTypeProcampOnRender      == type)
738         {
739             return PolicyFeatureHandler::UpdateFeaturePipe(caps, feature, featurePipe, executePipe, isInputPipe, index);
740         }
741         else if(FeatureTypeColorFillOnRender == type)
742         {
743             // Only apply color fill on 1st pass.
744             VP_PUBLIC_CHK_STATUS_RETURN(featurePipe.RemoveSwFilter(&feature));
745             VP_PUBLIC_CHK_STATUS_RETURN(executePipe.AddSwFilterUnordered(&feature, isInputPipe, index));
746         }
747         else
748         {
749             VP_PUBLIC_CHK_STATUS_RETURN(MOS_STATUS_INVALID_PARAMETER);
750         }
751     }
752 
753     return MOS_STATUS_SUCCESS;
754 }
755 
UpdateUnusedFeature(VP_EXECUTE_CAPS caps,SwFilter & feature,SwFilterPipe & featurePipe,SwFilterPipe & executePipe,bool isInputPipe,int index)756 MOS_STATUS PolicyFcFeatureHandler::UpdateUnusedFeature(VP_EXECUTE_CAPS caps, SwFilter &feature, SwFilterPipe &featurePipe, SwFilterPipe &executePipe, bool isInputPipe, int index)
757 {
758     // feature.GetFilterEngineCaps().bEnabled should be used here instead of feature.IsFeatureEnabled(caps)
759     // to ensure the feature does not be enabled.
760     // feature.IsFeatureEnabled(caps) being false means the feature is not being used in current workload,
761     // in which case, the feature itself may be enable and need be processed in following workloads.
762     if (0 == caps.bOutputPipeFeatureInuse &&
763         !feature.GetFilterEngineCaps().bEnabled &&
764         (feature.GetFilterEngineCaps().forceEnableForSfc ||
765          feature.GetFilterEngineCaps().forceEnableForFc))
766     {
767         // To avoid filter being destroyed in Policy::UpdateFeaturePipe.
768         feature.GetFilterEngineCaps().usedForNextPass = 1;
769     }
770     return MOS_STATUS_SUCCESS;
771 }
772 
773 /****************************************************************************************************/
774 /*                                   Policy FC Handler                                              */
775 /****************************************************************************************************/
PolicyFcHandler(VP_HW_CAPS & hwCaps)776 PolicyFcHandler::PolicyFcHandler(VP_HW_CAPS &hwCaps) : PolicyFeatureHandler(hwCaps)
777 {
778     m_Type = FeatureTypeFc;
779 }
~PolicyFcHandler()780 PolicyFcHandler::~PolicyFcHandler()
781 {
782 }
783 
IsFeatureEnabled(VP_EXECUTE_CAPS vpExecuteCaps)784 bool PolicyFcHandler::IsFeatureEnabled(VP_EXECUTE_CAPS vpExecuteCaps)
785 {
786     VP_FUNC_CALL();
787 
788     return vpExecuteCaps.bComposite;
789 }
790 
CreateHwFilterParam(VP_EXECUTE_CAPS vpExecuteCaps,SwFilterPipe & swFilterPipe,PVP_MHWINTERFACE pHwInterface)791 HwFilterParameter* PolicyFcHandler::CreateHwFilterParam(VP_EXECUTE_CAPS vpExecuteCaps, SwFilterPipe& swFilterPipe, PVP_MHWINTERFACE pHwInterface)
792 {
793     VP_FUNC_CALL();
794 
795     if (IsFeatureEnabled(vpExecuteCaps))
796     {
797         HW_FILTER_FC_PARAM param = {};
798         param.type = m_Type;
799         param.pHwInterface = pHwInterface;
800         param.vpExecuteCaps = vpExecuteCaps;
801         param.pPacketParamFactory = &m_PacketParamFactory;
802         param.executedPipe = &swFilterPipe;
803         param.pfnCreatePacketParam = PolicyFcHandler::CreatePacketParam;
804 
805         HwFilterParameter *pHwFilterParam = GetHwFeatureParameterFromPool();
806 
807         if (pHwFilterParam)
808         {
809             if (MOS_FAILED(((HwFilterFcParameter*)pHwFilterParam)->Initialize(param)))
810             {
811                 ReleaseHwFeatureParameter(pHwFilterParam);
812             }
813         }
814         else
815         {
816             pHwFilterParam = HwFilterFcParameter::Create(param, m_Type);
817         }
818 
819         return pHwFilterParam;
820     }
821     else
822     {
823         return nullptr;
824     }
825 }
826 
UpdateFeaturePipe(VP_EXECUTE_CAPS caps,SwFilter & feature,SwFilterPipe & featurePipe,SwFilterPipe & executePipe,bool isInputPipe,int index)827 MOS_STATUS PolicyFcHandler::UpdateFeaturePipe(VP_EXECUTE_CAPS caps, SwFilter &feature, SwFilterPipe &featurePipe, SwFilterPipe &executePipe, bool isInputPipe, int index)
828 {
829     VP_FUNC_CALL();
830     VP_PUBLIC_ASSERTMESSAGE("Should not coming here!");
831     return MOS_STATUS_SUCCESS;
832 }
833 
IsInterlacedInputSupported(VP_SURFACE & input)834 bool IsInterlacedInputSupported(VP_SURFACE &input)
835 {
836     // The parameter YOffset of surface state should be
837     // a multiple of 4 when the input is accessed in field mode.For interlaced NV12
838     // input, if its height is not a multiple of 4, the YOffset of UV plane will not
839     // be a multiple of 4.So under this condition, we treat it as progressive input.
840     return MOS_IS_ALIGNED(MOS_MIN((uint32_t)input.osSurface->dwHeight, (uint32_t)input.rcMaxSrc.bottom), 4) || input.osSurface->Format != Format_NV12;
841 }
842 
IsBobDiEnabled(SwFilterDeinterlace * di,VP_SURFACE & input)843 bool IsBobDiEnabled(SwFilterDeinterlace *di, VP_SURFACE &input)
844 {
845     if (nullptr == di || di->GetFilterEngineCaps().bEnabled == false)
846     {
847         return false;
848     }
849 
850     return IsInterlacedInputSupported(input);
851 }
852 
IsChromaSamplingNeeded(bool & isChromaUpSamplingNeeded,bool & isChromaDownSamplingNeeded,VPHAL_SURFACE_TYPE surfType,int layerIndex,MOS_FORMAT inputFormat,MOS_FORMAT outputFormat)853 static MOS_STATUS IsChromaSamplingNeeded(bool &isChromaUpSamplingNeeded, bool &isChromaDownSamplingNeeded,
854                                 VPHAL_SURFACE_TYPE surfType, int layerIndex,
855                                 MOS_FORMAT inputFormat, MOS_FORMAT outputFormat)
856 {
857     VPHAL_COLORPACK srcColorPack = VpHalDDIUtils::GetSurfaceColorPack(inputFormat);
858     VPHAL_COLORPACK dstColorPack = VpHalDDIUtils::GetSurfaceColorPack(outputFormat);
859 
860     if (SURF_IN_PRIMARY == surfType                         &&
861         // when 3D sampler been used, PL2 chromasitting kernel does not support sub-layer chromasitting
862         ((IS_PL2_FORMAT(inputFormat) && 0 == layerIndex)    ||
863         inputFormat == Format_YUY2))
864     {
865         isChromaUpSamplingNeeded   = ((srcColorPack == VPHAL_COLORPACK_420 &&
866                                     (dstColorPack == VPHAL_COLORPACK_422 || dstColorPack == VPHAL_COLORPACK_444)) ||
867                                     (srcColorPack == VPHAL_COLORPACK_422 && dstColorPack == VPHAL_COLORPACK_444));
868         isChromaDownSamplingNeeded = ((srcColorPack == VPHAL_COLORPACK_444 &&
869                                     (dstColorPack == VPHAL_COLORPACK_422 || dstColorPack == VPHAL_COLORPACK_420)) ||
870                                     (srcColorPack == VPHAL_COLORPACK_422 && dstColorPack == VPHAL_COLORPACK_420));
871     }
872     else
873     {
874         isChromaUpSamplingNeeded   = false;
875         isChromaDownSamplingNeeded = false;
876     }
877 
878     return MOS_STATUS_SUCCESS;
879 }
880 
Get3DSamplerScalingMode(VPHAL_SCALING_MODE & scalingMode,SwFilterSubPipe & pipe,int layerIndex,VP_SURFACE & input,VP_SURFACE & output)881 static MOS_STATUS Get3DSamplerScalingMode(VPHAL_SCALING_MODE &scalingMode, SwFilterSubPipe& pipe, int layerIndex, VP_SURFACE &input, VP_SURFACE &output)
882 {
883     bool isChromaUpSamplingNeeded = false;
884     bool isChromaDownSamplingNeeded = false;
885     VP_PUBLIC_CHK_STATUS_RETURN(IsChromaSamplingNeeded(isChromaUpSamplingNeeded, isChromaDownSamplingNeeded,
886                                 input.SurfType, layerIndex,
887                                 input.osSurface->Format, output.osSurface->Format));
888 
889     SwFilterScaling *scaling = dynamic_cast<SwFilterScaling *>(pipe.GetSwFilter(FeatureType::FeatureTypeScaling));
890 
891     bool iscalingEnabled       = scaling ? ISCALING_INTERLEAVED_TO_INTERLEAVED == scaling->GetSwFilterParams().interlacedScalingType : false;
892     bool fieldWeaving          = scaling ? ISCALING_FIELD_TO_INTERLEAVED == scaling->GetSwFilterParams().interlacedScalingType : false;
893 
894     // The rectangle in VP_SURFACE contains the rotation information.
895     // The rectangle in ScalingFilter has been adjusted based on the rotation,
896     // which can be used directly here.
897     bool isScalingNeeded = false;
898     if (scaling)
899     {
900         auto &scalingParamsInput = scaling->GetSwFilterParams().input;
901         isScalingNeeded = (scalingParamsInput.rcDst.right - scalingParamsInput.rcDst.left)
902         != (scalingParamsInput.rcSrc.right - scalingParamsInput.rcSrc.left) ||
903         (scalingParamsInput.rcDst.bottom - scalingParamsInput.rcDst.top)
904         != (scalingParamsInput.rcSrc.bottom - scalingParamsInput.rcSrc.top);
905     }
906     else
907     {
908         isScalingNeeded = false;
909     }
910 
911     if (!isScalingNeeded                                                                    &&
912         !isChromaUpSamplingNeeded                                                           &&
913         !isChromaDownSamplingNeeded                                                         &&
914         (input.SampleType == SAMPLE_PROGRESSIVE || iscalingEnabled || fieldWeaving))
915     {
916         scalingMode = VPHAL_SCALING_NEAREST;
917     }
918     else
919     {
920         scalingMode = VPHAL_SCALING_BILINEAR;
921     }
922 
923     return MOS_STATUS_SUCCESS;
924 }
925 
AddInputLayerForProcess(bool & bSkip,std::vector<int> & layerIndexes,VPHAL_SCALING_MODE & scalingMode,int index,VP_SURFACE & input,SwFilterSubPipe & pipe,VP_SURFACE & output,VP_EXECUTE_CAPS & caps)926 MOS_STATUS PolicyFcHandler::AddInputLayerForProcess(bool &bSkip, std::vector<int> &layerIndexes, VPHAL_SCALING_MODE &scalingMode,
927     int index, VP_SURFACE &input, SwFilterSubPipe& pipe, VP_SURFACE &output, VP_EXECUTE_CAPS& caps)
928 {
929     bSkip = false;
930     --m_resCounter.layers;
931 
932     if (VPHAL_PALETTE_NONE != input.Palette.PaletteType)
933     {
934         --m_resCounter.palettes;
935     }
936 
937     SwFilterProcamp *procamp = dynamic_cast<SwFilterProcamp *>(pipe.GetSwFilter(FeatureType::FeatureTypeProcamp));
938     if (procamp && procamp->IsFeatureEnabled(caps)  &&
939         procamp->GetSwFilterParams().procampParams  &&
940         procamp->GetSwFilterParams().procampParams->bEnabled)
941     {
942         --m_resCounter.procamp;
943     }
944 
945     SwFilterLumakey *lumakey = dynamic_cast<SwFilterLumakey *>(pipe.GetSwFilter(FeatureType::FeatureTypeLumakey));
946     if (lumakey)
947     {
948         --m_resCounter.lumaKeys;
949         if (m_resCounter.lumaKeys < 0 || layerIndexes.size() > 1)
950         {
951             bSkip = true;
952             VP_PUBLIC_NORMALMESSAGE("Scaling Info: layer %d is not selected. lumaKeys %d, layerIndexes.size() %d",
953                 index, m_resCounter.lumaKeys, layerIndexes.size());
954             return MOS_STATUS_SUCCESS;
955         }
956         if (layerIndexes.size() == 1)
957         {
958             m_resCounter.sampler = VP_COMP_MAX_SAMPLER;
959         }
960     }
961 
962     SwFilterScaling *scaling = dynamic_cast<SwFilterScaling *>(pipe.GetSwFilter(FeatureType::FeatureTypeScaling));
963     SwFilterDeinterlace *di = dynamic_cast<SwFilterDeinterlace *>(pipe.GetSwFilter(FeatureType::FeatureTypeDi));
964     VPHAL_SAMPLE_TYPE sampleType = input.SampleType;
965     bool samplerLumakeyEnabled = m_hwCaps.m_rules.isAvsSamplerSupported;
966 
967     if (nullptr == scaling)
968     {
969         VP_PUBLIC_ASSERTMESSAGE("Scaling Info: Scaling filter does not exist on layer %d!", index);
970         VP_PUBLIC_CHK_NULL_RETURN(scaling);
971     }
972 
973     scalingMode = scaling->GetSwFilterParams().scalingMode;
974 
975     // Disable AVS scaling mode
976     if (!m_hwCaps.m_rules.isAvsSamplerSupported)
977     {
978         if (VPHAL_SCALING_AVS == scalingMode)
979         {
980             scalingMode = VPHAL_SCALING_BILINEAR;
981         }
982     }
983 
984     if (!IsInterlacedInputSupported(input))
985     {
986         sampleType = SAMPLE_PROGRESSIVE;
987         // Disable DI
988         if (di && di->IsFeatureEnabled(caps))
989         {
990             di->GetFilterEngineCaps().bEnabled = false;
991         }
992         // Disable Iscaling
993         if (scaling->IsFeatureEnabled(caps) &&
994             ISCALING_NONE != scaling->GetSwFilterParams().interlacedScalingType)
995         {
996             scaling->GetSwFilterParams().interlacedScalingType = ISCALING_NONE;
997         }
998     }
999 
1000     // Number of AVS, but lumaKey and BOB DI needs 3D sampler instead of AVS sampler.
1001     if (VPHAL_SCALING_AVS == scalingMode &&
1002         nullptr == lumakey && !IsBobDiEnabled(di, input))
1003     {
1004         --m_resCounter.avs;
1005     }
1006     // Number of Sampler filter mode, we had better only support Nearest or Bilinear filter in one phase
1007     // If two filters are used together, the later filter overwrite the first and cause output quality issue.
1008     else
1009     {
1010         VP_PUBLIC_CHK_STATUS_RETURN(Get3DSamplerScalingMode(scalingMode, pipe, layerIndexes.size(), input, output));
1011 
1012         // If bilinear needed for one layer, it will also be used by other layers.
1013         // nearest only be used if it is used by all layers.
1014         int32_t samplerMask = (VP_COMP_SAMPLER_BILINEAR | VP_COMP_SAMPLER_NEAREST);
1015 
1016         // Use sampler luma key feature only if this is not the bottom most layer
1017         if (samplerLumakeyEnabled && lumakey && layerIndexes.size() > 0 && !IS_PL3_FORMAT(input.osSurface->Format))
1018         {
1019             m_resCounter.sampler &= VP_COMP_SAMPLER_LUMAKEY;
1020         }
1021         else if (m_resCounter.sampler & samplerMask)
1022         {
1023             m_resCounter.sampler &= samplerMask;
1024         }
1025         else
1026         {
1027             // switch to AVS if AVS sampler is not used, decrease the count of comp phase
1028             // For isAvsSamplerSupported == false case, curent layer will be rejected, since m_resCounter.avs == 0.
1029             scalingMode = VPHAL_SCALING_AVS;
1030             --m_resCounter.avs;
1031         }
1032     }
1033 
1034     // Fails if any of the limits are reached
1035     // Output structure has reason why failed :-)
1036     // multi-passes if rotation is not the same as Layer 0 rotation
1037     // single pass if Primary layer needs rotation and remaining layer does not need rotation
1038     if (m_resCounter.layers   < 0 ||
1039         m_resCounter.palettes < 0 ||
1040         m_resCounter.procamp  < 0 ||
1041         m_resCounter.lumaKeys < 0 ||
1042         m_resCounter.avs      < 0 ||
1043         m_resCounter.sampler == 0)
1044     {
1045         //Multipass
1046         bSkip = true;
1047         VP_PUBLIC_NORMALMESSAGE("Scaling Info: layer %d is not selected. layers %d, palettes %d, procamp %d, lumaKeys %d, avs %d, sampler %d",
1048             index, m_resCounter.layers, m_resCounter.palettes, m_resCounter.procamp, m_resCounter.lumaKeys, m_resCounter.avs, m_resCounter.sampler);
1049         return MOS_STATUS_SUCCESS;
1050     }
1051 
1052     VP_PUBLIC_NORMALMESSAGE("Scaling Info: scalingMode %d is selected for layer %d", scalingMode, index);
1053     MT_LOG2(MT_VP_HAL_FC_SCALINGINFO, MT_NORMAL, MT_VP_HAL_FC_LAYER, index, MT_VP_HAL_SCALING_MODE, scalingMode);
1054 
1055     // Append source to compositing operation
1056     scaling->GetSwFilterParams().scalingMode = scalingMode;
1057 
1058     if (di)
1059     {
1060         di->GetSwFilterParams().sampleTypeInput = sampleType;
1061     }
1062 
1063     input.SampleType = sampleType;
1064     layerIndexes.push_back(index);
1065 
1066     return MOS_STATUS_SUCCESS;
1067 }
1068 
RemoveTransparentLayers(SwFilterPipe & featurePipe)1069 MOS_STATUS PolicyFcHandler::RemoveTransparentLayers(SwFilterPipe& featurePipe)
1070 {
1071     for (uint32_t i = 0; i < featurePipe.GetSurfaceCount(true); ++i)
1072     {
1073         SwFilterSubPipe *subpipe = featurePipe.GetSwFilterSubPipe(true, i);
1074 
1075         auto blending = dynamic_cast<SwFilterBlending *>(featurePipe.GetSwFilter(true, i, FeatureTypeBlending));
1076         if (nullptr == blending)
1077         {
1078             continue;
1079         }
1080 
1081         auto &param = blending->GetSwFilterParams();
1082 
1083         //-----------------------------------
1084         // Alpha blending optimization.
1085         // If Constant blending and one of the following is true, disable blending.
1086         // If Src+Constant blending and one of the following is true, fall back to Src blending.
1087         // Condition; alpha <= 0. Layer is 100% transparent.
1088         // Condition; alpha >= 1. Layer is 100% opaque.
1089         //-----------------------------------
1090         if (param.blendingParams &&
1091             ((param.blendingParams->BlendType == BLEND_CONSTANT) ||
1092              (param.blendingParams->BlendType == BLEND_CONSTANT_SOURCE) ||
1093              (param.blendingParams->BlendType == BLEND_CONSTANT_PARTIAL)))
1094         {
1095             float fAlpha = param.blendingParams->fAlpha;
1096 
1097             // Don't render layer with alpha <= 0.0f
1098             if (fAlpha <= 0.0f)
1099             {
1100                 VP_PUBLIC_NORMALMESSAGE("Layer %d skipped: BlendType %d, fAlpha %d",
1101                     i,
1102                     param.blendingParams->BlendType,
1103                     param.blendingParams->fAlpha);
1104                 VP_PUBLIC_CHK_STATUS_RETURN(featurePipe.DestroySurface(true, i));
1105             }
1106         }
1107     }
1108     featurePipe.Update();
1109 
1110     return MOS_STATUS_SUCCESS;
1111 }
1112 
LayerSelectForProcess(std::vector<int> & layerIndexes,SwFilterPipe & featurePipe,VP_EXECUTE_CAPS & caps)1113 MOS_STATUS PolicyFcHandler::LayerSelectForProcess(std::vector<int> &layerIndexes, SwFilterPipe& featurePipe, VP_EXECUTE_CAPS& caps)
1114 {
1115     layerIndexes.clear();
1116     m_resCounter.Reset(m_hwCaps.m_rules.isAvsSamplerSupported);
1117 
1118     VP_PUBLIC_CHK_STATUS_RETURN(RemoveTransparentLayers(featurePipe));
1119 
1120     bool skip = false;
1121     VP_SURFACE *output = featurePipe.GetSurface(false, 0);
1122     bool bilinearInUseFor3DSampler = false;
1123     VP_PUBLIC_CHK_NULL_RETURN(output);
1124 
1125     for (uint32_t i = 0; i < featurePipe.GetSurfaceCount(true); ++i)
1126     {
1127         VPHAL_SCALING_MODE scalingMode = VPHAL_SCALING_NEAREST;
1128         VP_SURFACE *input = featurePipe.GetSurface(true, i);
1129         SwFilterSubPipe *subpipe = featurePipe.GetSwFilterSubPipe(true, i);
1130         VP_PUBLIC_CHK_NULL_RETURN(input);
1131         VP_PUBLIC_CHK_NULL_RETURN(subpipe);
1132         VP_PUBLIC_CHK_STATUS_RETURN(AddInputLayerForProcess(skip, layerIndexes, scalingMode, i, *input, *subpipe, *output, caps));
1133         if (skip)
1134         {
1135             break;
1136         }
1137 
1138         if (VPHAL_SCALING_BILINEAR == scalingMode)
1139         {
1140             bilinearInUseFor3DSampler = true;
1141         }
1142     }
1143 
1144     // Use bilinear for layers, which is using nearest.
1145     if (s_forceNearestToBilinearIfBilinearExists && bilinearInUseFor3DSampler)
1146     {
1147         for (uint32_t i = 0; i < layerIndexes.size(); ++i)
1148         {
1149             SwFilterSubPipe *subpipe = featurePipe.GetSwFilterSubPipe(true, layerIndexes[i]);
1150             VP_PUBLIC_CHK_NULL_RETURN(subpipe);
1151             SwFilterScaling *scaling = dynamic_cast<SwFilterScaling *>(subpipe->GetSwFilter(FeatureType::FeatureTypeScaling));
1152             if (scaling && VPHAL_SCALING_NEAREST == scaling->GetSwFilterParams().scalingMode)
1153             {
1154                 scaling->GetSwFilterParams().scalingMode = VPHAL_SCALING_BILINEAR;
1155                 VP_PUBLIC_NORMALMESSAGE("Scaling Info: Force nearest to bilinear for layer %d (%d)", layerIndexes[i], i);
1156                 MT_LOG3(MT_VP_HAL_FC_SCALINGINFO, MT_NORMAL, MT_VP_HAL_FC_LAYER, layerIndexes[i], MT_VP_HAL_SCALING_MODE, VPHAL_SCALING_NEAREST, MT_VP_HAL_SCALING_MODE_FORCE, VPHAL_SCALING_BILINEAR);
1157             }
1158         }
1159     }
1160 
1161     // No procamp in target being used.
1162     return MOS_STATUS_SUCCESS;
1163 }
1164 }
1165