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 ¶m, 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 ¶m)
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 ¶m)
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 ¶ms)
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 ¶m = 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