/*
* Copyright (c) 2016-2023, Intel Corporation
*
* Permission is hereby granted, free of charge, to any person obtaining a
* copy of this software and associated documentation files (the "Software"),
* to deal in the Software without restriction, including without limitation
* the rights to use, copy, modify, merge, publish, distribute, sublicense,
* and/or sell copies of the Software, and to permit persons to whom the
* Software is furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included
* in all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
* OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
* THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR
* OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
* ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
* OTHER DEALINGS IN THE SOFTWARE.
*/
//!
//! \file     vphal_render_composite.cpp
//! \brief    Composite related VPHAL functions
//! \details  Unified VP HAL Composite module including render initialization,
//!           resource allocation/free and rendering
//!
#include "vphal_render_composite.h"
#include "vphal_renderer.h"         // for VpHal_RenderAllocateBB
#include "vphal_render_common.h"    // for VPHAL_RENDER_CACHE_CNTL
#include "vphal_render_ief.h"
#include "vp_hal_ddi_utils.h"
#include "renderhal_platform_interface.h"

// Compositing surface binding table index
#define VPHAL_COMP_BTINDEX_LAYER0          0
#define VPHAL_COMP_BTINDEX_LAYER0_FIELD0   0
#define VPHAL_COMP_BTINDEX_LAYER1          3
#define VPHAL_COMP_BTINDEX_LAYER2          6
#define VPHAL_COMP_BTINDEX_LAYER3          9
#define VPHAL_COMP_BTINDEX_LAYER4         12
#define VPHAL_COMP_BTINDEX_LAYER5         15
#define VPHAL_COMP_BTINDEX_LAYER6         18
#define VPHAL_COMP_BTINDEX_LAYER7         21
#define VPHAL_COMP_BTINDEX_RENDERTARGET   24
#define VPHAL_COMP_BTINDEX_RT_SECOND      27    // Pre-SKL
#define VPHAL_COMP_BTINDEX_L0_FIELD1_DUAL 48    // Pre-SKL

#define VPHAL_HORIZONTAL_16X16BLOCK_MASK   0
#define VPHAL_VERTICAL_16X16BLOCK_MASK     1

// CMFC macro
#define VPHAL_COMP_CMFC_COEFF_WIDTH        64
#define VPHAL_COMP_CMFC_COEFF_HEIGHT       8
#define VPHAL_COMP_BTINDEX_CSC_COEFF       34

//!
//! \brief  Sampler State Indices
//!
#define VPHAL_SAMPLER_8x8_AVS_Y         4
#define VPHAL_SAMPLER_8x8_AVS_U         8
#define VPHAL_SAMPLER_8x8_AVS_V         12

static const MEDIA_OBJECT_KA2_STATIC_DATA g_cInit_MEDIA_OBJECT_KA2_STATIC_DATA =
{
    // DWORD 0
    {
        0,                                      // CscConstantC0
        0                                       // CscConstantC1
    },

    // DWORD 1
    {
        0,                                      // CscConstantC2
        0                                       // CscConstantC3
    },

    // DWORD 2
    {
        0,                                      // CscConstantC4
        0                                       // CscConstantC5
    },

    // DWORD 3
    {
        0,                                      // CscConstantC6
        0                                       // CscConstantC7
    },

    // DWORD 4
    {
        0,                                      // CscConstantC8
        0                                       // CscConstantC9
    },

    // DWORD 5
    {
        0,                                      // CscConstantC10
        0                                       // CscConstantC11
    },

    // DWORD 6
    {
        0,                                      // ConstantBlendingAlphaLayer1
        0,                                      // ConstantBlendingAlphaLayer2
        0,                                      // ConstantBlendingAlphaLayer3
        0                                       // ConstantBlendingAlphaLayer4
    },

    // DWORD 7
    {
        0,                                      // ConstantBlendingAlphaLayer5
        0,                                      // ConstantBlendingAlphaLayer6
        0,                                      // ConstantBlendingAlphaLayer7
        7                                       // PointerToInlineParameters
    },

    // DWORD 8
    {
        0,                                      // DestinationRectangleWidth
        0                                       // DestinationRectangleHeight
    },

    // DWORD 9
    {
        0,                                      // RotationMirrorMode
        0,                                      // RotationMirrorAllLayer
        0,                                      // DualOutputMode
        0,                                      // ChannelSwap
    },

    // DWORD 10
    0,

    // DWORD 11
    0,

    // DWORD 12
    {
        0,                                      // ColorProcessingEnable
        0,                                      // MessageFormat
        0                                       // ColorProcessingStatePointer
    },

    // DWORD 13
    {
        0,                                      // ColorFill_R
        0,                                      // ColorFill_G
        0,                                      // ColorFill_B
        0                                       // ColorFill_A
    },

    // DWORD 14
    {
        0,                                      // LumakeyLowThreshold
        0,                                      // LumakeyHighThreshold
        0,                                      // NLASEnable
    },

    // DWORD 15
    {
        0,                                      // DestinationPackedYOffset
        0,                                      // DestinationPackedUOffset
        0,                                      // DestinationPackedVOffset
        0                                       // DestinationRGBFormat
    },

    // DWORD 16
    0,                                          // HorizontalScalingStepRatioLayer0

    // DWORD 17
    0,                                          // HorizontalScalingStepRatioLayer1

    // DWORD 18
    0,                                          // HorizontalScalingStepRatioLayer2

    // DWORD 19
    0,                                          // HorizontalScalingStepRatioLayer3

    // DWORD 20
    0,                                          // HorizontalScalingStepRatioLayer4

    // DWORD 21
    0,                                          // HorizontalScalingStepRatioLayer5

    // DWORD 22
    0,                                          // HorizontalScalingStepRatioLayer6

    // DWORD 23
    0,                                          // HorizontalScalingStepRatioLayer7

    // DWORD 24
    0,                                          // VerticalScalingStepRatioLayer0

    // DWORD 25
    0,                                          // VerticalScalingStepRatioLayer1

    // DWORD 26
    0,                                          // VerticalScalingStepRatioLayer2

    // DWORD 27
    0,                                          // VerticalScalingStepRatioLayer3

    // DWORD 28
    0,                                          // VerticalScalingStepRatioLayer4

    // DWORD 29
    0,                                          // VerticalScalingStepRatioLayer5

    // DWORD 30
    0,                                          // VerticalScalingStepRatioLayer6

    // DWORD 31
    0,                                          // VerticalScalingStepRatioLayer7

    // DWORD 32
    0,                                          // VerticalFrameOriginLayer0

    // DWORD 33
    0,                                          // VerticalFrameOriginLayer1

    // DWORD 34
    0,                                          // VerticalFrameOriginLayer2

    // DWORD 35
    0,                                          // VerticalFrameOriginLayer3

    // DWORD 36
    0,                                          // VerticalFrameOriginLayer4

    // DWORD 37
    0,                                          // VerticalFrameOriginLayer5

    // DWORD 38
    0,                                          // VerticalFrameOriginLayer6

    // DWORD 39
    0,                                          // VerticalFrameOriginLayer7

    // DWORD 40
    0,                                          // HorizontalFrameOriginLayer0

    // DWORD 41
    0,                                          // HorizontalFrameOriginLayer1

    // DWORD 42
    0,                                          // HorizontalFrameOriginLayer2

    // DWORD 43
    0,                                          // HorizontalFrameOriginLayer3

    // DWORD 44
    0,                                          // HorizontalFrameOriginLayer4

    // DWORD 45
    0,                                          // HorizontalFrameOriginLayer5

    // DWORD 46
    0,                                          // HorizontalFrameOriginLayer6

    // DWORD 47
    0                                           // HorizontalFrameOriginLayer7
};

static const MEDIA_WALKER_KA2_STATIC_DATA g_cInit_MEDIA_WALKER_KA2_STATIC_DATA =
{
    // DWORD 0
    {
        0,                                      // CscConstantC0
        0                                       // CscConstantC1
    },

    // DWORD 1
    {
        0,                                      // CscConstantC2
        0                                       // CscConstantC3
    },

    // DWORD 2
    {
        0,                                      // CscConstantC4
        0                                       // CscConstantC5
    },

    // DWORD 3
    {
        0,                                      // CscConstantC6
        0                                       // CscConstantC7
    },

    // DWORD 4
    {
        0,                                      // CscConstantC8
        0                                       // CscConstantC9
    },

    // DWORD 5
    {
        0,                                      // CscConstantC10
        0                                       // CscConstantC11
    },

    // DWORD 6
    {
        0,                                      // ConstantBlendingAlphaLayer1
        0,                                      // ConstantBlendingAlphaLayer2
        0,                                      // ConstantBlendingAlphaLayer3
        0                                       // ConstantBlendingAlphaLayer4
    },

    // DWORD 7
    {
        0,                                      // ConstantBlendingAlphaLayer5
        0,                                      // ConstantBlendingAlphaLayer6
        0,                                      // ConstantBlendingAlphaLayer7
        7                                       // PointerToInlineParameters
    },

    // DWORD 8
    {
        0,                                      // DestinationRectangleWidth
        0                                       // DestinationRectangleHeight
    },

    // DWORD 9
    {
        0,                                      // RotationMirrorMode
        0,                                      // RotationMirrorAllLayer
        0,                                      // DualOutputMode
        0,                                      // ChannelSwap
    },

    // DWORD 10
    0,

    // DWORD 11
    0,

    // DWORD 12
    {
        0,                                      // ColorProcessingEnable
        0,                                      // MessageFormat
        0                                       // ColorProcessingStatePointer
    },

    // DWORD 13
    {
        0,                                      // ColorFill_R
        0,                                      // ColorFill_G
        0,                                      // ColorFill_B
        0                                       // ColorFill_A
    },

    // DWORD 14
    {
        0,                                      // LumakeyLowThreshold
        0,                                      // LumakeyHighThreshold
        0,                                  // NLASEnable
    },

    // DWORD 15
    {
        0,                                      // DestinationPackedYOffset
        0,                                      // DestinationPackedUOffset
        0,                                      // DestinationPackedVOffset
        0                                       // DestinationRGBFormat
    },

    // DWORD 16
    0,                                          // HorizontalScalingStepRatioLayer0

    // DWORD 17
    0,                                          // HorizontalScalingStepRatioLayer1

    // DWORD 18
    0,                                          // HorizontalScalingStepRatioLayer2

    // DWORD 19
    0,                                          // HorizontalScalingStepRatioLayer3

    // DWORD 20
    0,                                          // HorizontalScalingStepRatioLayer4

    // DWORD 21
    0,                                          // HorizontalScalingStepRatioLayer5

    // DWORD 22
    0,                                          // HorizontalScalingStepRatioLayer6

    // DWORD 23
    0,                                          // HorizontalScalingStepRatioLayer7

    // DWORD 24
    0,                                          // VerticalScalingStepRatioLayer0

    // DWORD 25
    0,                                          // VerticalScalingStepRatioLayer1

    // DWORD 26
    0,                                          // VerticalScalingStepRatioLayer2

    // DWORD 27
    0,                                          // VerticalScalingStepRatioLayer3

    // DWORD 28
    0,                                          // VerticalScalingStepRatioLayer4

    // DWORD 29
    0,                                          // VerticalScalingStepRatioLayer5

    // DWORD 30
    0,                                          // VerticalScalingStepRatioLayer6

    // DWORD 31
    0,                                          // VerticalScalingStepRatioLayer7

    // DWORD 32
    0,                                          // VerticalFrameOriginLayer0

    // DWORD 33
    0,                                          // VerticalFrameOriginLayer1

    // DWORD 34
    0,                                          // VerticalFrameOriginLayer2

    // DWORD 35
    0,                                          // VerticalFrameOriginLayer3

    // DWORD 36
    0,                                          // VerticalFrameOriginLayer4

    // DWORD 37
    0,                                          // VerticalFrameOriginLayer5

    // DWORD 38
    0,                                          // VerticalFrameOriginLayer6

    // DWORD 39
    0,                                          // VerticalFrameOriginLayer7

    // DWORD 40
    0,                                          // HorizontalFrameOriginLayer0

    // DWORD 41
    0,                                          // HorizontalFrameOriginLayer1

    // DWORD 42
    0,                                          // HorizontalFrameOriginLayer2

    // DWORD 43
    0,                                          // HorizontalFrameOriginLayer3

    // DWORD 44
    0,                                          // HorizontalFrameOriginLayer4

    // DWORD 45
    0,                                          // HorizontalFrameOriginLayer5

    // DWORD 46
    0,                                          // HorizontalFrameOriginLayer6

    // DWORD 47
    0,                                          // HorizontalFrameOriginLayer7

    // DWORD 48

    {
       0,                                       //  DestXTopLeftLayer0
       0                                        //  DestYTopLeftLayer0
    },

   // DWORD 49
   {
       0,                                      //  DestXTopLeftLayer1
       0                                       //  DestYTopLeftLayer1
   },

   // DWORD 50
   {
       0,                                      //  DestXTopLeftLayer2
       0                                       //  DestYTopLeftLayer2
   },

   // DWORD 51
   {
       0,                                      //  DestXTopLeftLayer3
       0                                       //  DestYTopLeftLayer3
   },

   // DWORD 52
   {
       0,                                      //  DestXTopLeftLayer4
       0                                       //  DestYTopLeftLayer4
   },

   // DWORD 53
   {
       0,                                      //  DestXTopLeftLayer5
       0                                       //  DestYTopLeftLayer5
   },

   // DWORD 54
   {
       0,                                      //  DestXTopLeftLayer6
       0                                       //  DestYTopLeftLayer6
   },

   // DWORD 55
   {
       0,                                      //  DestXTopLeftLayer7
       0                                       //  DestYTopLeftLayer7
   },

   // DWORD 56
   {
       0,                                      // DestXBottomRightLayer0
       0                                       // DestYBottomRightLayer0
   },

   // DWORD 57
   {
       0,                                      // DestXBottomRightLayer1
       0                                       // DestYBottomRightLayer1
   },

   // DWORD 58
   {
       0,                                      // DestXBottomRightLayer2
       0                                       // DestYBottomRightLayer2
   },

   // DWORD 59
   {
       0,                                      // DestXBottomRightLayer3
       0                                       // DestYBottomRightLayer3
   },

   // DWORD 60
   {
       0,                                      // DestXBottomRightLayer4
       0                                       // DestYBottomRightLayer4
   },

   // DWORD 61
   {
       0,                                      // DestXBottomRightLayer5
       0                                       // DestYBottomRightLayer5
   },

   // DWORD 62
   {
       0,                                     // DestXBottomRightLayer6
       0                                      // DestYBottomRightLayer6
   },

   // DWORD 63
   {
       0,                                     // DestXBottomRightLayer7
       0                                      // DestYBottomRightLayer7
   },

   // DWORD 64
   0,                                         // MainVideoXScalingStepLeft

   // DWORD 65
   0,                                         // VideoStepDeltaForNonLinearRegion

   // DWORD 66
   {
       0,                                     // StartofLinearScalingInPixelPositionC0
       0                                      // StartofRHSNonLinearScalingInPixelPositionC1
   },

   // DWORD 67
   0,                                         // MainVideoXScalingStepCenter

   // DWORD 68
   0,                                         // MainVideoXScalingStepRight

   // DWORD 69
   {
       0,                                     // DestHorizontalBlockOrigin
       0                                      // DestVerticalBlockOrigin
   },

   // DWORD 70 - DWORD 71
   {0,0}
};

static const MEDIA_OBJECT_NLAS_INLINE_DATA g_cInit_MEDIA_OBJECT_NLAS_INLINE_DATA =
{
    0,                                          // HorizontalFrameOriginLayer0
    0,                                          // HorizontalFrameOriginLayer1
    0,                                          // HorizontalFrameOriginLayer2
    0,                                          // HorizontalFrameOriginLayer3
    0,                                          // HorizontalFrameOriginLayer4
    0,                                          // HorizontalFrameOriginLayer5
    0,                                          // HorizontalFrameOriginLayer6
    0                                           // HorizontalFrameOriginLayer7
};

const Kdll_Layer g_cSurfaceType_Layer[] =
{
    Layer_None        ,    //!< SURF_NONE
    Layer_Background  ,    //!< SURF_IN_BACKGROUND
    Layer_MainVideo   ,    //!< SURF_IN_PRIMARY
    Layer_SubVideo    ,    //!< SURF_IN_SECONDARY
    Layer_SubPicture1 ,    //!< SURF_IN_SUBSTREAM
    Layer_Graphics    ,    //!< SURF_IN_GRAPHICS
    Layer_Invalid     ,    //!< SURF_IN_REFERENCE
    Layer_RenderTarget     //!< SURF_OUT_RENDERTARGET
};

const int32_t g_cBindingTableIndex[] =
{
    VPHAL_COMP_BTINDEX_RENDERTARGET,
    VPHAL_COMP_BTINDEX_LAYER0,
    VPHAL_COMP_BTINDEX_LAYER1,
    VPHAL_COMP_BTINDEX_LAYER2,
    VPHAL_COMP_BTINDEX_LAYER3,
    VPHAL_COMP_BTINDEX_LAYER4,
    VPHAL_COMP_BTINDEX_LAYER5,
    VPHAL_COMP_BTINDEX_LAYER6,
    VPHAL_COMP_BTINDEX_LAYER7
};

const RENDERHAL_KERNEL_PARAM g_cInitKernelParamsComposite =
{
    7,                              //!< Number of registers (7 => 128 registers)
    40,                             //!< Number of BT entries
    3,                              //!< Number of samplers (3 => 9-12 samplers)
    VPHAL_USE_MEDIA_THREADS_MAX,    //!< Number of threads
    0,                              //!< Start register
    6,                              //!< Constant URB length (in 256-bits) (6 => 48 dwords)
    VPHAL_COMP_BLOCK_WIDTH,         //!< Block width
    VPHAL_COMP_BLOCK_HEIGHT,        //!< Block height
    1,                              //!< Blocks in x
    1                               //!< Blocks in y
};

//!
//! \brief    Reverse bits in a word
//! \details  Convert a post-rotated 16x16 block mask to a pre-rotated one
//! \param    [in] x
//!           16x16 block mask
//! \return   uint16_t
//!           Return bit-reversed word
//!
static uint16_t ReverseWord(uint16_t x)
{
    x = (((x & 0xaaaa) >> 1) | ((x & 0x5555) << 1));
    x = (((x & 0xcccc) >> 2) | ((x & 0x3333) << 2));
    x = (((x & 0xf0f0) >> 4) | ((x & 0x0f0f) << 4));
    return ((x >> 8) | (x << 8));
}

//!
//! \brief    Judge whether Bob Di should be enabled
//! \details  Judge whether Bob Di should be enabled according to the parameter
//!           of pDeinterlaceParams and the height of the input surface
//! \param    [in] pSrc
//!           Pointer to Source Surface
//! \return   bool
//!           Return true if Bob DI should be enabled, otherwise false
//!
bool CompositeState::IsBobDiEnabled(PVPHAL_SURFACE pSrc)
{
    bool  bRet = false;

    VPHAL_RENDER_CHK_NULL_NO_STATUS(m_pOsInterface);

    // Kernel don't support inderlaced Y410/Y210 as input format
    bRet = (pSrc->pDeinterlaceParams     &&
           (pSrc->Format != Format_Y410  &&
            pSrc->Format != Format_Y210  &&
            pSrc->Format != Format_Y216  &&
            pSrc->Format != Format_Y416) &&
            !VpHal_RndrCommonIsAlignmentWANeeded(pSrc, m_pOsInterface->CurrentGpuContextOrdinal));

finish:
    return bRet;
}

//!
//! \brief    Judge whether 8-tap adaptive filter for all channels should be enabled
//! \details  Judge whether 8-tap adaptive filter for all channels should be enabled according to the input parameter
//! \param    [in] pSrc
//!           Pointer to Source Surface
//! \param    [in] fScaleX
//!           width scaling ratio
//! \param    [in] fScaleY
//!           height scaling ratio
//! \return   bool
//!           Return true 8-tap adaptive filter for all channels should be enabled, otherwise false
//!
bool CompositeState::Is8TapAdaptiveEnabled(
    PVPHAL_SURFACE          pSrc,
    float                   fScaleX,
    float                   fScaleY)
{
    return (m_b8TapAdaptiveEnable       &&
            (fScaleX > 1.0F || fScaleY > 1.0F)    &&
            (IS_RGB32_FORMAT(pSrc->Format)        ||
             pSrc->Format == Format_A16R16G16B16  ||
             pSrc->Format == Format_AYUV          ||
             pSrc->Format == Format_Y410          ||
             pSrc->Format == Format_Y416));
}

//!
//! \brief    Set 16x16 block inline mask based on the rotation
//! \details  Set 16x16 block inline mask with a pre-rotated 16x16 MB based on a
//!           post-rotated 16x16 block mask
//! \param    [in] rotation
//!           Rotation Degrees
//! \param    [out] pInlineDword
//!           Pointer to HW Interface
//! \param    [in] wMask
//!           Inline Mask
//! \param    [in] maskDirection
//!           Mask Direction
//! \return   void
//!
static void SetInline16x16Mask(
    VPHAL_ROTATION                      rotation,
    PVPHAL_16X16BLOCK_COMPOSITE_MASK    pInlineDword,
    uint16_t                            wMask,
    uint32_t                            maskDirection)
{
    if (VPHAL_VERTICAL_16X16BLOCK_MASK == maskDirection)
    {
        switch (rotation)
        {
            case VPHAL_ROTATION_IDENTITY:
            case VPHAL_MIRROR_HORIZONTAL:
                pInlineDword->VerticalBlockCompositeMask = wMask;
                break;
            case VPHAL_ROTATION_90:
            case VPHAL_ROTATE_90_MIRROR_HORIZONTAL:
                // swap vertical/horizontal
                pInlineDword->HorizontalBlockCompositeMask = wMask;
                break;
            case VPHAL_ROTATION_180:
            case VPHAL_MIRROR_VERTICAL:
                // reverse bits
                pInlineDword->VerticalBlockCompositeMask = ReverseWord(wMask);
                break;
            case VPHAL_ROTATION_270:
            case VPHAL_ROTATE_90_MIRROR_VERTICAL:
                // reverse bits and swap vertical/horizontal
                pInlineDword->HorizontalBlockCompositeMask = ReverseWord(wMask);
                break;
            default:
                VPHAL_RENDER_ASSERTMESSAGE("Invalid Rotation Angle.");
                break;
        }
    }
    else    // must be VPHAL_HORIZONTAL_16X16BLOCK_MASK
    {
        switch (rotation)
        {
            case VPHAL_ROTATION_IDENTITY:
            case VPHAL_MIRROR_VERTICAL:
                pInlineDword->HorizontalBlockCompositeMask = wMask;
                break;
            case VPHAL_ROTATION_90:
            case VPHAL_ROTATE_90_MIRROR_VERTICAL:
                // reverse bits and swap vertical/horizontal
                pInlineDword->VerticalBlockCompositeMask = ReverseWord(wMask);
                break;
            case VPHAL_ROTATION_180:
            case VPHAL_MIRROR_HORIZONTAL:
                // reverse bits
                pInlineDword->HorizontalBlockCompositeMask = ReverseWord(wMask);
                break;
            case VPHAL_ROTATION_270:
            case VPHAL_ROTATE_90_MIRROR_HORIZONTAL:
                // swap vertical/horizontal
                pInlineDword->VerticalBlockCompositeMask = wMask;
                break;
            default:
                VPHAL_RENDER_ASSERTMESSAGE("Invalid Rotation Angle.");
                break;
        }
    }
}

//!
//! \brief    Load Palette Data
//! \details  Load Palette Data according to color space and CSC matrix.
//! \param    [in] pInPalette
//!           Pointer to Input Palette structure
//! \param    [in] srcCspace
//!           Source color space
//! \param    [in] dstCspace
//!           Destination color space
//! \param    [in] piCscMatrix
//!           Pointer to CSC matrix to use in fixed point format
//! \param    [in] iNumEntries
//!           Number of Palette entries to be filled
//! \param    [in,out] pPaletteData
//!           Pointer to Output Palette Address
//! \return   MOS_STATUS
//!           MOS_STATUS_SUCCESS, otherwise MOS_STATUS_UNIMPLEMENTED if Destination Colorspace not supported,
//!            or MOS_STATUS_INVALID_PARAMETER/MOS_STATUS_NULL_POINTER
//!
MOS_STATUS CompositeState::LoadPaletteData(
    PVPHAL_PALETTE          pInPalette,
    VPHAL_CSPACE            srcCspace,
    VPHAL_CSPACE            dstCspace,
    int32_t*                piCscMatrix,
    int32_t                 iNumEntries,
    void*                   pPaletteData)
{
    PVPHAL_COLOR_SAMPLE_8   pSrcColor, pDstColor;
    bool                    bHasAlpha;
    int32_t                 R, G, B;
    int32_t                 Y, U, V;
    int32_t                 i;
    MOS_STATUS              eStatus = MOS_STATUS_SUCCESS;

    VPHAL_RENDER_CHK_NULL(pInPalette);
    VPHAL_RENDER_CHK_NULL(pInPalette->pPalette8);
    VPHAL_RENDER_CHK_NULL(piCscMatrix);
    VPHAL_RENDER_CHK_NULL(pPaletteData);

    if (pInPalette->iNumEntries < 1)
    {
        VPHAL_RENDER_ASSERTMESSAGE("invalid parameters.");
        eStatus = MOS_STATUS_INVALID_PARAMETER;
        goto finish;
    }

    bHasAlpha = pInPalette->bHasAlpha;

    // Obtain pointer to in/out color entries
    pSrcColor   = pInPalette->pPalette8;
    pDstColor   = (PVPHAL_COLOR_SAMPLE_8)pPaletteData;

    // Load Palette by performing the required conversions
    if (srcCspace == dstCspace)
    {
        // No conversion needed
        if ((dstCspace == CSpace_sRGB) || (dstCspace == CSpace_stRGB))
        {
            for (i = 0; i < iNumEntries; i++, pSrcColor++, pDstColor++)
            {
                pDstColor->A = (bHasAlpha) ? pSrcColor->A : 255;
                pDstColor->R = pSrcColor->R;
                pDstColor->G = pSrcColor->G;
                pDstColor->B = pSrcColor->B;
            }
        }
        else
        {
            for (i = 0; i < iNumEntries; i++, pSrcColor++, pDstColor++)
            {
                pDstColor->a = (bHasAlpha) ? pSrcColor->Alpha : 255;
                pDstColor->V = pSrcColor->Cr;
                pDstColor->Y = pSrcColor->YY;
                pDstColor->U = pSrcColor->Cb;
            }
        }
    }
    else
    {
        // Conversion needed
        switch (dstCspace)
        {
            case CSpace_sRGB:
            case CSpace_stRGB:
                for (i = 0; i < iNumEntries; i++, pSrcColor++, pDstColor++)
                {
                    // YUV to RGB conversions
                    Y = pSrcColor->YY;
                    U = pSrcColor->Cb;
                    V = pSrcColor->Cr;

                    R = (Y * piCscMatrix[0]  + U * piCscMatrix[1]  +
                         V * piCscMatrix[2]  +     piCscMatrix[3]  + 0x00080000) >> 20;
                    G = (Y * piCscMatrix[4]  + U * piCscMatrix[5]  +
                         V * piCscMatrix[6]  +     piCscMatrix[7]  + 0x00080000) >> 20;
                    B = (Y * piCscMatrix[8]  + U * piCscMatrix[9]  +
                         V * piCscMatrix[10] +     piCscMatrix[11] + 0x00080000) >> 20;

                    pDstColor->A = (bHasAlpha) ? pSrcColor->Alpha : 255;
                    if (dstCspace == CSpace_sRGB)
                    {
                        pDstColor->R = MOS_MIN(MOS_MAX(0,R),255);
                        pDstColor->G = MOS_MIN(MOS_MAX(0,G),255);
                        pDstColor->B = MOS_MIN(MOS_MAX(0,B),255);
                    }
                    else
                    {
                        pDstColor->R = MOS_MIN(MOS_MAX(16,R),235);
                        pDstColor->G = MOS_MIN(MOS_MAX(16,G),235);
                        pDstColor->B = MOS_MIN(MOS_MAX(16,B),235);
                    }
                }
                break;

            case CSpace_BT601:
            case CSpace_BT709:
            case CSpace_xvYCC601:
            case CSpace_xvYCC709:
            case CSpace_BT601_FullRange:
            case CSpace_BT709_FullRange:
                for (i = 0; i < iNumEntries; i++, pSrcColor++, pDstColor++)
                {
                    R = pSrcColor->R;
                    G = pSrcColor->G;
                    B = pSrcColor->B;

                    Y = (piCscMatrix[0]  * R + piCscMatrix[1]  * G +
                         piCscMatrix[2]  * B + piCscMatrix[3]      + 0x00080000) >> 20;
                    U = (piCscMatrix[4]  * R + piCscMatrix[5]  * G +
                         piCscMatrix[6]  * B + piCscMatrix[7]      + 0x00080000) >> 20;
                    V = (piCscMatrix[8]  * R + piCscMatrix[9]  * G +
                         piCscMatrix[10] * B + piCscMatrix[11]     + 0x00080000) >> 20;

                    pDstColor->a = (bHasAlpha) ? pSrcColor->Alpha : 255;
                    if ((dstCspace == CSpace_BT601) ||
                        (dstCspace == CSpace_BT709))
                    {
                        pDstColor->V = MOS_MIN(MOS_MAX(16,V),240);
                        pDstColor->Y = MOS_MIN(MOS_MAX(16,Y),235);
                        pDstColor->U = MOS_MIN(MOS_MAX(16,U),240);
                    }
                    else
                    {
                        pDstColor->V = MOS_MIN(MOS_MAX(0,V),255);
                        pDstColor->Y = MOS_MIN(MOS_MAX(0,Y),255);
                        pDstColor->U = MOS_MIN(MOS_MAX(0,U),255);
                    }
                }
                break;

            default:
                VPHAL_RENDER_ASSERTMESSAGE("Destination Colorspace not supported.");
                eStatus = MOS_STATUS_UNIMPLEMENTED;
                break;
        }
    }

finish:
    return eStatus;
}

//!
//! \brief    Recalculate Sampler Avs 8x8 Horizontal/Vertical scaling table
//! \param    [in] SrcFormat
//!           Source Format
//! \param    [in] fScale
//!           Horizontal or Vertical Scale Factor
//! \param    [in] bVertical
//!           true if Vertical Scaling, else Horizontal Scaling
//! \param    [in] dwChromaSiting
//!           Chroma Siting
//! \param    [in] bBalancedFilter
//!           true if Gen9+, balanced filter
//! \param    [in] b8TapAdaptiveEnable
//!           true if 8Tap Adaptive Enable
//! \param    [in,out] pAvsParams
//!           Pointer to AVS Params
//! \return   MOS_STATUS
//!
static MOS_STATUS SamplerAvsCalcScalingTable(
    MOS_FORMAT                      SrcFormat,
    float                           fScale,
    bool                            bVertical,
    uint32_t                        dwChromaSiting,
    bool                            bBalancedFilter,
    bool                            b8TapAdaptiveEnable,
    PMHW_AVS_PARAMS                 pAvsParams)
{
    MOS_STATUS                      eStatus = MOS_STATUS_SUCCESS;
    MHW_PLANE                       Plane;
    int32_t                         iUvPhaseOffset;
    uint32_t                        dwHwPhrase;
    uint32_t                        YCoefTableSize;
    uint32_t                        UVCoefTableSize;
    float                           fScaleParam;
    int32_t*                        piYCoefsParam;
    int32_t*                        piUVCoefsParam;
    float                           fHPStrength;

    VPHAL_RENDER_CHK_NULL(pAvsParams);
    VPHAL_RENDER_CHK_NULL(pAvsParams->piYCoefsY);
    VPHAL_RENDER_CHK_NULL(pAvsParams->piYCoefsX);
    VPHAL_RENDER_CHK_NULL(pAvsParams->piUVCoefsY);
    VPHAL_RENDER_CHK_NULL(pAvsParams->piUVCoefsX);

    if (bBalancedFilter)
    {
        YCoefTableSize      = POLYPHASE_Y_COEFFICIENT_TABLE_SIZE_G9;
        UVCoefTableSize     = POLYPHASE_UV_COEFFICIENT_TABLE_SIZE_G9;
        dwHwPhrase          = NUM_HW_POLYPHASE_TABLES_G9;
    }
    else
    {
        YCoefTableSize      = POLYPHASE_Y_COEFFICIENT_TABLE_SIZE_G8;
        UVCoefTableSize     = POLYPHASE_UV_COEFFICIENT_TABLE_SIZE_G8;
        dwHwPhrase          = MHW_NUM_HW_POLYPHASE_TABLES;
    }

    fHPStrength = 0.0F;
    piYCoefsParam   = bVertical ? pAvsParams->piYCoefsY : pAvsParams->piYCoefsX;
    piUVCoefsParam  = bVertical ? pAvsParams->piUVCoefsY : pAvsParams->piUVCoefsX;
    fScaleParam     = bVertical ? pAvsParams->fScaleY : pAvsParams->fScaleX;

    // Recalculate Horizontal or Vertical scaling table
    if (SrcFormat != pAvsParams->Format || fScale != fScaleParam)
    {
        MOS_ZeroMemory(piYCoefsParam, YCoefTableSize);
        MOS_ZeroMemory(piUVCoefsParam, UVCoefTableSize);

        // 4-tap filtering for RGB format G-channel if 8tap adaptive filter is not enabled.
        Plane = ((IS_RGB32_FORMAT(SrcFormat) || (SrcFormat == Format_Y410) || (SrcFormat == Format_AYUV) || (SrcFormat == Format_Y416)) && !b8TapAdaptiveEnable) ? MHW_U_PLANE : MHW_Y_PLANE;
        if (bVertical)
        {
            pAvsParams->fScaleY = fScale;
        }
        else
        {
            pAvsParams->fScaleX = fScale;
        }

        // For 1x scaling in horizontal direction, use special coefficients for filtering
        // we don't do this when bForcePolyPhaseCoefs flag is set
        if (fScale == 1.0F && !pAvsParams->bForcePolyPhaseCoefs)
        {
            VPHAL_RENDER_CHK_STATUS(Mhw_SetNearestModeTable(
                piYCoefsParam,
                Plane,
                bBalancedFilter));
            // If the 8-tap adaptive is enabled for all channel, then UV/RB use the same coefficient as Y/G
            // So, coefficient for UV/RB channels caculation can be passed
            if (!b8TapAdaptiveEnable)
            {
                VPHAL_RENDER_CHK_STATUS(Mhw_SetNearestModeTable(
                    piUVCoefsParam,
                    MHW_U_PLANE,
                    bBalancedFilter));
            }
        }
        else
        {
            // Clamp the Scaling Factor if > 1.0x
            fScale = MOS_MIN(1.0F, fScale);

            VPHAL_RENDER_CHK_STATUS(Mhw_CalcPolyphaseTablesY(
                piYCoefsParam,
                fScale,
                Plane,
                SrcFormat,
                fHPStrength,
                true,
                dwHwPhrase,
                0));

            // If the 8-tap adaptive is enabled for all channel, then UV/RB use the same coefficient as Y/G
            // So, coefficient for UV/RB channels caculation can be passed
            if (!b8TapAdaptiveEnable)
            {
                if (!bBalancedFilter)
                {
                    VPHAL_RENDER_CHK_STATUS(Mhw_CalcPolyphaseTablesY(
                        piUVCoefsParam,
                        fScale,
                        MHW_U_PLANE,
                        SrcFormat,
                        fHPStrength,
                        true,
                        dwHwPhrase,
                        0));
                }
                else
                {
                    // If Chroma Siting info is present
                    if (dwChromaSiting & (bVertical ? MHW_CHROMA_SITING_VERT_TOP : MHW_CHROMA_SITING_HORZ_LEFT))
                    {
                        // No Chroma Siting
                        VPHAL_RENDER_CHK_STATUS(Mhw_CalcPolyphaseTablesUV(
                            piUVCoefsParam,
                            2.0F,
                            fScale));
                    }
                    else
                    {
                        // Chroma siting offset needs to be added
                        if (dwChromaSiting & (bVertical ? MHW_CHROMA_SITING_VERT_CENTER : MHW_CHROMA_SITING_HORZ_CENTER))
                        {
                            iUvPhaseOffset = MOS_UF_ROUND(0.5F * 16.0F);   // U0.4
                        }
                        else //if (ChromaSiting & (bVertical ? MHW_CHROMA_SITING_VERT_BOTTOM : MHW_CHROMA_SITING_HORZ_RIGHT))
                        {
                            iUvPhaseOffset = MOS_UF_ROUND(1.0F * 16.0F);   // U0.4
                        }

                        VPHAL_RENDER_CHK_STATUS(Mhw_CalcPolyphaseTablesUVOffset(
                            piUVCoefsParam,
                            3.0F,
                            fScale,
                            iUvPhaseOffset));
                    }
                }
            }
        }
    }

finish:
    return eStatus;
}

//!
//! \brief    Set Sampler Avs 8x8 Table
//! \param    [in] pRenderHal
//!           Pointer to RenderHal Interface Structure
//! \param    [in] pSamplerStateParams
//!           Pointer to Sampler State Params
//! \param    [in,out] pAvsParams
//!           Pointer to AVS Params
//! \param    [in] SrcFormat
//!           Source Format
//! \param    [in] fScaleX
//!           Horizontal Scale Factor
//! \param    [in] fScaleY
//!           Vertical Scale Factor
//! \param    [in] dwChromaSiting
//!           Chroma Siting
//! \return   MOS_STATUS
//!
MOS_STATUS CompositeState::SetSamplerAvsTableParam(
    PRENDERHAL_INTERFACE            pRenderHal,
    PMHW_SAMPLER_STATE_PARAM        pSamplerStateParams,
    PMHW_AVS_PARAMS                 pAvsParams,
    MOS_FORMAT                      SrcFormat,
    float                           fScaleX,
    float                           fScaleY,
    uint32_t                        dwChromaSiting)
{
    MOS_STATUS                   eStatus = MOS_STATUS_SUCCESS;
    bool                         bBalancedFilter;
    PMHW_SAMPLER_AVS_TABLE_PARAM pMhwSamplerAvsTableParam;
    bool                         bIsUpScaleAndYuvFormat;

    VPHAL_RENDER_CHK_NULL(pSamplerStateParams);
    VPHAL_RENDER_CHK_NULL(pAvsParams);
    VPHAL_RENDER_CHK_NULL(pAvsParams->piYCoefsY);
    VPHAL_RENDER_CHK_NULL(pAvsParams->piYCoefsX);
    VPHAL_RENDER_CHK_NULL(pAvsParams->piUVCoefsY);
    VPHAL_RENDER_CHK_NULL(pAvsParams->piUVCoefsX);

    pMhwSamplerAvsTableParam = pSamplerStateParams->Avs.pMhwSamplerAvsTableParam;

    pMhwSamplerAvsTableParam->bIsCoeffExtraEnabled = m_bAvsTableCoeffExtraEnabled;
    pMhwSamplerAvsTableParam->b8TapAdaptiveEnable  = pSamplerStateParams->Avs.b8TapAdaptiveEnable;
    bBalancedFilter                                = m_bAvsTableBalancedFilter;

    pMhwSamplerAvsTableParam->byteTransitionArea8Pixels = MEDIASTATE_AVS_TRANSITION_AREA_8_PIXELS;
    pMhwSamplerAvsTableParam->byteTransitionArea4Pixels = MEDIASTATE_AVS_TRANSITION_AREA_4_PIXELS;
    pMhwSamplerAvsTableParam->byteMaxDerivative8Pixels  = MEDIASTATE_AVS_MAX_DERIVATIVE_8_PIXELS;
    pMhwSamplerAvsTableParam->byteMaxDerivative4Pixels  = MEDIASTATE_AVS_MAX_DERIVATIVE_4_PIXELS;
    pMhwSamplerAvsTableParam->byteDefaultSharpnessLevel = MEDIASTATE_AVS_SHARPNESS_LEVEL_SHARP;

    bIsUpScaleAndYuvFormat = ((fScaleX > 1.0F || fScaleY > 1.0F) && IS_YUV_FORMAT(SrcFormat));
    if (SrcFormat == Format_Y410 ||
        SrcFormat == Format_AYUV ||
        SrcFormat == Format_Y416)
    {
        bIsUpScaleAndYuvFormat = false;
    }

    if (pMhwSamplerAvsTableParam->b8TapAdaptiveEnable)
    {
        pMhwSamplerAvsTableParam->bBypassXAdaptiveFiltering  = false;
        pMhwSamplerAvsTableParam->bBypassYAdaptiveFiltering  = false;
        pMhwSamplerAvsTableParam->bAdaptiveFilterAllChannels = true;
        pMhwSamplerAvsTableParam->bEnableRGBAdaptive         = IS_RGB_FORMAT(SrcFormat);
    }
    else if (bIsUpScaleAndYuvFormat)
    {
        // enable adaptive filter if it's being upscaled in either direction. we check it before clamping the SF.
        pMhwSamplerAvsTableParam->bBypassXAdaptiveFiltering = false;
        pMhwSamplerAvsTableParam->bBypassYAdaptiveFiltering = false;
    }
    else
    {
        pMhwSamplerAvsTableParam->bBypassXAdaptiveFiltering = true;
        pMhwSamplerAvsTableParam->bBypassYAdaptiveFiltering = true;
    }

    // No changes to AVS parameters -> skip
    if (SrcFormat == pAvsParams->Format &&
        fScaleX == pAvsParams->fScaleX &&
        fScaleY == pAvsParams->fScaleY)
    {
        goto finish;
    }

    // not change AVS coefficients if upscaling, to avoid recalculation
    if (fScaleX > 1.0F && pAvsParams->fScaleX > 1.0F)
    {
        pAvsParams->fScaleX = fScaleX;
    }

    // not change AVS coefficients if upscaling, to avoid recalculation
    if (fScaleY > 1.0F && pAvsParams->fScaleY > 1.0F)
    {
        pAvsParams->fScaleY = fScaleY;
    }

    AvsCoeffsCacheTag tag;
    tag.m_format              = SrcFormat;
    tag.m_8TapAdaptiveEnable  = pMhwSamplerAvsTableParam->b8TapAdaptiveEnable ? true : false;
    tag.m_balancedFilter      = bBalancedFilter;
    tag.m_forcePolyPhaseCoefs = pAvsParams->bForcePolyPhaseCoefs ? true : false;
    tag.m_chromaSiting        = dwChromaSiting;
    tag.m_scaleX              = fScaleX;
    tag.m_scaleY              = fScaleY;

    const MHW_AVS_PARAMS *cachedAvsParams;
    cachedAvsParams = m_AvsCoeffsCache.Find(tag);

    if (cachedAvsParams)
    {
        m_AvsCoeffsCache.Clone(*cachedAvsParams, *pAvsParams);
    }
    else
    {
        // Recalculate Horizontal scaling table
        VPHAL_RENDER_CHK_STATUS(SamplerAvsCalcScalingTable(
            SrcFormat,
            fScaleX,
            false,
            dwChromaSiting,
            bBalancedFilter,
            pMhwSamplerAvsTableParam->b8TapAdaptiveEnable ? true : false,
            pAvsParams));

        // Recalculate Vertical scaling table
        VPHAL_RENDER_CHK_STATUS(SamplerAvsCalcScalingTable(
            SrcFormat,
            fScaleY,
            true,
            dwChromaSiting,
            bBalancedFilter,
            pMhwSamplerAvsTableParam->b8TapAdaptiveEnable ? true : false,
            pAvsParams));

        // Save format used to calculate AVS parameters
        pAvsParams->Format = SrcFormat;

        m_AvsCoeffsCache.Insert(tag, *pAvsParams);
    }

    pMhwSamplerAvsTableParam->b4TapGY   = ((IS_RGB32_FORMAT(SrcFormat) || SrcFormat == Format_Y410 || SrcFormat == Format_AYUV || SrcFormat == Format_Y416) && !pMhwSamplerAvsTableParam->b8TapAdaptiveEnable);
    pMhwSamplerAvsTableParam->b4TapRBUV = (!pMhwSamplerAvsTableParam->b8TapAdaptiveEnable);

    VPHAL_RENDER_CHK_STATUS(VpHal_RenderCommonSetAVSTableParam(pAvsParams, pMhwSamplerAvsTableParam));

finish:
    return eStatus;
}

//!
//! \brief    Prepare phases for composite and determine intermediate colorspace
//! \param    [in] pcRenderParams
//!           Pointer to Render parameters
//! \param    [in] ppSources
//!           Pointer to the address of Source Surfaces
//! \param    [in] iSources
//!           Count of Source Surfaces
//! \return   VPHAL_CSPACE
//!           Return intermediate colorspace
//!
VPHAL_CSPACE CompositeState::PrepareCSC(
    PCVPHAL_RENDER_PARAMS   pcRenderParams,
    PVPHAL_SURFACE          *ppSources,
    int32_t                 iSources)
{
    PVPHAL_SURFACE                  pTarget;
    PVPHAL_SURFACE                  pSrc;
    int32_t                         i, j;
    int32_t                         csc_count = 0;
    int32_t                         csc_min = iSources + 1;
    int32_t                         cspace_in_use[CSpace_Count];
    bool                            bYUVTarget;
    VPHAL_CSPACE                    cs;
    VPHAL_CSPACE                    Temp_ColorSpace = CSpace_Any;
    VPHAL_CSPACE                    Main_ColorSpace = CSpace_None;

    // Check if target is YUV
    pTarget    = pcRenderParams->pTarget[0];
    bYUVTarget = IS_RGB_FORMAT(pTarget->Format) ? false : true;

    // Gets primary video cspace
    // Implements xvYCC passthrough mode
    // Set Color Spaces in use
    MOS_ZeroMemory(cspace_in_use, sizeof(cspace_in_use));
    for (i = 0; i < iSources; i++)
    {
        // Get current source
        pSrc = ppSources[i];

        // Save Main Video color space
        if (pSrc->SurfType == SURF_IN_PRIMARY &&
            Main_ColorSpace == CSpace_None)
        {
            Main_ColorSpace = pSrc->ColorSpace;
        }

        // Set xvYCC pass through mode
        if (bYUVTarget &&
            (pSrc->ColorSpace == CSpace_xvYCC709 ||
             pSrc->ColorSpace == CSpace_xvYCC601))
        {
            Temp_ColorSpace = pSrc->ColorSpace;
            goto finish;
        }

        // Don't take PAL formats into consideration
        if ((!IS_PAL_FORMAT(pSrc->Format)) &&
             pSrc->ColorSpace > CSpace_Any &&
             pSrc->ColorSpace < CSpace_Count)
        {
            cs = KernelDll_TranslateCspace(pSrc->ColorSpace);
            if (cs >= CSpace_Any)
            {
                cspace_in_use[cs]++;
            }
        }
    }

    // For every CS in use, iterate through source CS and keep a
    // count of number of CSC operation needed. Determine the Temporary
    // color space as the one requiring min. # of CSC ops.
    for (j = (CSpace_Any + 1); j < CSpace_Count; j++)
    {
        // Skip color spaces not in use
        if (!cspace_in_use[j])
        {
            continue;
        }

        // Count # of CS conversions
        cs = (VPHAL_CSPACE) j;
        csc_count = 0;
        for (i = 0; i < iSources; i++)
        {
            // Get current source
            pSrc = ppSources[i];

            // Ignore palletized layers
            if (IS_PAL_FORMAT(pSrc->Format) ||
                pSrc->ColorSpace == CSpace_Any)
            {
                continue;
            }

            // Check if CSC/PA is required
            if (KernelDll_TranslateCspace(pSrc->ColorSpace) != cs ||
                (pSrc->pProcampParams != nullptr &&
                 pSrc->pProcampParams->bEnabled))
            {
                csc_count++;
            }
        }

        // Save best choice as requiring minimum number of CSC operations
        // Use main cspace as default if same CSC count
        if ((csc_count <  csc_min) ||
            (csc_count == csc_min && cs == Main_ColorSpace) )
        {
            Temp_ColorSpace = cs;
            csc_min = csc_count;
        }
    }

    // If all layers are palletized, use the CS from first layer (as good as any other)
    if (Temp_ColorSpace == CSpace_Any && iSources > 0)
    {
        Temp_ColorSpace = ppSources[0]->ColorSpace;
    }

finish:

    VPHAL_RENDER_NORMALMESSAGE("Main_ColorSpace %d, Temp_ColorSpace %d, csc_count %d.",
        Main_ColorSpace,
        Temp_ColorSpace,
        csc_count);

    return Temp_ColorSpace;
}

MOS_STATUS CompositeState::IntermediateAllocation(PVPHAL_SURFACE &pIntermediate,
    PMOS_INTERFACE                   pOsInterface,
    uint32_t                         dwTempWidth,
    uint32_t                         dwTempHeight,
    PVPHAL_SURFACE                   pTarget)
{
    MOS_RESOURCE            OsResource  = {};
    MOS_ALLOC_GFXRES_PARAMS AllocParams = {};
    VPHAL_GET_SURFACE_INFO  Info        = {};
    // Allocate/Reallocate temporary output
    if (dwTempWidth > pIntermediate->dwWidth ||
        dwTempHeight > pIntermediate->dwHeight)
    {
        // Get max values
        dwTempWidth  = MOS_MAX(dwTempWidth, pIntermediate->dwWidth);
        dwTempHeight = MOS_MAX(dwTempHeight, pIntermediate->dwHeight);

        // Allocate buffer in fixed increments
        dwTempWidth  = MOS_ALIGN_CEIL(dwTempWidth, VPHAL_BUFFER_SIZE_INCREMENT);
        dwTempHeight = MOS_ALIGN_CEIL(dwTempHeight, VPHAL_BUFFER_SIZE_INCREMENT);

        MOS_ZeroMemory(&AllocParams, sizeof(MOS_ALLOC_GFXRES_PARAMS));
        MOS_ZeroMemory(&OsResource, sizeof(MOS_RESOURCE));

        AllocParams.Type         = MOS_GFXRES_2D;
        AllocParams.TileType     = MOS_TILE_Y;
        AllocParams.dwWidth      = dwTempWidth;
        AllocParams.dwHeight     = dwTempHeight;
        AllocParams.Format       = Format_A8R8G8B8;
        AllocParams.ResUsageType = MOS_HW_RESOURCE_USAGE_VP_INTERNAL_READ_WRITE_RENDER;

        pOsInterface->pfnAllocateResource(
            pOsInterface,
            &AllocParams,
            &OsResource);

        // Get Allocation index of source for rendering
        pOsInterface->pfnRegisterResource(
            pOsInterface,
            &OsResource,
            false,
            true);

        if (!Mos_ResourceIsNull(&OsResource))
        {
            // Deallocate old resource
            pOsInterface->pfnFreeResource(pOsInterface,
                &pIntermediate->OsResource);

            // Set new resource
            pIntermediate->OsResource = OsResource;

            // Get resource info (width, height, pitch, tiling, etc)
            MOS_ZeroMemory(&Info, sizeof(VPHAL_GET_SURFACE_INFO));

            VPHAL_RENDER_CHK_STATUS_RETURN(VpHal_GetSurfaceInfo(
                pOsInterface,
                &Info,
                pIntermediate));
        }
    }

    // Set output parameters
    pIntermediate->SurfType      = SURF_IN_PRIMARY;
    pIntermediate->SampleType    = SAMPLE_PROGRESSIVE;
    pIntermediate->ColorSpace    = pTarget->ColorSpace;
    pIntermediate->ExtendedGamut = pTarget->ExtendedGamut;
    pIntermediate->rcSrc         = pTarget->rcSrc;
    pIntermediate->rcDst         = pTarget->rcDst;
    pIntermediate->ScalingMode   = VPHAL_SCALING_BILINEAR;
    pIntermediate->bIEF          = false;

    return MOS_STATUS_SUCCESS;
}

//!
//! \brief    Prepare phases for composite and allocate intermediate buffer for rendering
//! \param    [in] pcRenderParams
//!           Pointer to Render parameters
//! \param    [in] ppSources
//!           Pointer to the address of Source Surfaces
//! \param    [in] iSources
//!           Count of Source Surfaces
//! \return   bool
//!           Return true if multiple phases, otherwise false
//!
bool CompositeState::PreparePhases(
    PCVPHAL_RENDER_PARAMS       pcRenderParams,
    PVPHAL_SURFACE              *ppSources,
    int32_t                     iSources)
{
    PMOS_INTERFACE          pOsInterface;
    VPHAL_COMPOSITE_PARAMS  Composite;
    MOS_RESOURCE            OsResource = {};
    uint32_t                dwTempWidth;    // Temporary surface width
    uint32_t                dwTempHeight;   // Temporary surface height
    PVPHAL_SURFACE          pTarget;
    PVPHAL_SURFACE          pIntermediate;
    int32_t                 i;
    bool                    bMultiplePhases;
    MOS_ALLOC_GFXRES_PARAMS AllocParams = {};
    VPHAL_GET_SURFACE_INFO  Info = {};
    MOS_STATUS  eStatus = MOS_STATUS_SUCCESS;

    pTarget = pcRenderParams->pTarget[0];

    // Constriction support
    dwTempWidth = dwTempHeight = 0;
    if (pcRenderParams->pConstriction)
    {
        // Force multiple phases
        bMultiplePhases = true;

        // Temporary surface size = constriction rectangle
        dwTempWidth  = pcRenderParams->pConstriction->right;
        dwTempHeight = pcRenderParams->pConstriction->bottom;
    }
    else
    {
        // Reset multiple phase support
        bMultiplePhases = false;
        bool                    disableAvsSampler = false;

        // Temporary surface has the same size as render target
        dwTempWidth  = pTarget->dwWidth;
        dwTempHeight = pTarget->dwHeight;

        // Check if multiple phases by building filter for first phase
        ResetCompParams(&Composite);

        if (IsDisableAVSSampler(iSources, 0 < pTarget->rcDst.top))
        {
            VPHAL_RENDER_ASSERTMESSAGE("Disable AVS sampler for TargetTopY!");
            Composite.nAVS    = 0;
            disableAvsSampler = true;
        }

        for (i = 0; i < iSources; i++)
        {

            if (disableAvsSampler && VPHAL_SCALING_AVS == ppSources[i]->ScalingMode)
            {
                VPHAL_RENDER_ASSERTMESSAGE("Force to 3D sampler for layer %d.", i);
                ppSources[i]->ScalingMode = VPHAL_SCALING_BILINEAR;
            }

            // Decompression RGB10 RC input for multi input cases cases
            if ((ppSources[i]->CompressionMode == MOS_MMC_RC) &&
                (MEDIA_IS_SKU(m_pSkuTable, FtrLocalMemory)    &&
                !MEDIA_IS_SKU(m_pSkuTable, FtrFlatPhysCCS)))
            {
                bool bAllocated = false;
                //Use auxiliary surface to sync with decompression
                eStatus = VpHal_ReAllocateSurface(
                    m_pOsInterface,
                    &m_AuxiliarySyncSurface,
                    "AuxiliarySyncSurface",
                    Format_Buffer,
                    MOS_GFXRES_BUFFER,
                    MOS_TILE_LINEAR,
                    32,
                    1,
                    false,
                    MOS_MMC_DISABLED,
                    &bAllocated);

                if (eStatus != MOS_STATUS_SUCCESS)
                {
                    VPHAL_RENDER_ASSERTMESSAGE("Additional AuxiliarySyncSurface  for sync create fail");
                }

                eStatus = m_pOsInterface->pfnSetDecompSyncRes(m_pOsInterface, &m_AuxiliarySyncSurface.OsResource);

                if (eStatus != MOS_STATUS_SUCCESS)
                {
                    VPHAL_RENDER_ASSERTMESSAGE("Set Decomp sync resource fail");
                }

                eStatus = m_pOsInterface->pfnDecompResource(m_pOsInterface, &ppSources[i]->OsResource);

                if (eStatus != MOS_STATUS_SUCCESS)
                {
                    VPHAL_RENDER_ASSERTMESSAGE("Additional decompression for RC failed.");
                }

                eStatus = m_pOsInterface->pfnSetDecompSyncRes(m_pOsInterface, nullptr);

                if (eStatus != MOS_STATUS_SUCCESS)
                {
                    VPHAL_RENDER_ASSERTMESSAGE("Set Decomp sync resource fail");
                }

                eStatus = m_pOsInterface->pfnRegisterResource(m_pOsInterface, &m_AuxiliarySyncSurface.OsResource, true, true);

                if (eStatus != MOS_STATUS_SUCCESS)
                {
                    VPHAL_RENDER_ASSERTMESSAGE("register resources for sync failed.");
                }
            }

            if (!AddCompLayer(&Composite, ppSources[i], disableAvsSampler))
            {
                bMultiplePhases = true;
                break;
            }
        }

        // Add render target
        if (!AddCompTarget(&Composite, pTarget))
        {
            bMultiplePhases = true;
        }
    }

    // Reallocate Intermediate surface
    if (bMultiplePhases)
    {
        pOsInterface  = m_pOsInterface;
        pIntermediate = m_Intermediate;
        PVPHAL_SURFACE &p = pIntermediate;
        // Allocate/Reallocate temporary output
        IntermediateAllocation(p,
            pOsInterface,
            dwTempWidth,
            dwTempHeight,
            pTarget);

        pIntermediate = m_Intermediate1;
        // Allocate/Reallocate temporary output
        IntermediateAllocation(p,
            pOsInterface,
            dwTempWidth,
            dwTempHeight,
            pTarget);

        pIntermediate = m_Intermediate2;

        // Allocate/Reallocate temporary output
        if (dwTempWidth  > pIntermediate->dwWidth ||
            dwTempHeight > pIntermediate->dwHeight)
        {
            // Get max values
            dwTempWidth  = MOS_MAX(dwTempWidth , pIntermediate->dwWidth);
            dwTempHeight = MOS_MAX(dwTempHeight, pIntermediate->dwHeight);

            // Allocate buffer in fixed increments
            dwTempWidth  = MOS_ALIGN_CEIL(dwTempWidth , VPHAL_BUFFER_SIZE_INCREMENT);
            dwTempHeight = MOS_ALIGN_CEIL(dwTempHeight, VPHAL_BUFFER_SIZE_INCREMENT);

            MOS_ZeroMemory(&AllocParams, sizeof(MOS_ALLOC_GFXRES_PARAMS));

            AllocParams.Type     = MOS_GFXRES_2D;
            AllocParams.TileType = MOS_TILE_Y;
            AllocParams.dwWidth  = dwTempWidth;
            AllocParams.dwHeight = dwTempHeight;
            AllocParams.Format   = Format_A8R8G8B8;
            AllocParams.ResUsageType = MOS_HW_RESOURCE_USAGE_VP_INTERNAL_READ_WRITE_RENDER;

            pOsInterface->pfnAllocateResource(
                pOsInterface,
                &AllocParams,
                &OsResource);

            if (!Mos_ResourceIsNull(&OsResource))
            {
                // Deallocate old resource
                pOsInterface->pfnFreeResource(pOsInterface,
                                              &pIntermediate->OsResource);

                // Set new resource
                pIntermediate->OsResource = OsResource;

                // Get resource info (width, height, pitch, tiling, etc)
                MOS_ZeroMemory(&Info, sizeof(VPHAL_GET_SURFACE_INFO));

                VPHAL_RENDER_CHK_STATUS(VpHal_GetSurfaceInfo(
                    pOsInterface,
                    &Info,
                    pIntermediate));
            }
        }

        // Set output parameters
        pIntermediate->SurfType          = SURF_IN_PRIMARY;
        pIntermediate->SampleType        = SAMPLE_PROGRESSIVE;
        pIntermediate->ColorSpace        = pTarget->ColorSpace;
        pIntermediate->ExtendedGamut     = pTarget->ExtendedGamut;
        pIntermediate->rcSrc             = pTarget->rcSrc;
        pIntermediate->rcDst             = pTarget->rcDst;
        pIntermediate->ScalingMode       = VPHAL_SCALING_BILINEAR;
        pIntermediate->bIEF              = false;
    }

finish:
    return bMultiplePhases;
}

//!
//! \brief    Reset composite rendering parameters for the current phase
//! \param    [in,out] pComposite
//!           Pointer to Composite parameters
//! \return   void
//!
void CompositeState::ResetCompParams(
    PVPHAL_COMPOSITE_PARAMS     pComposite)
{
    MOS_ZeroMemory(pComposite, sizeof(*pComposite));

    pComposite->nLayers   = VPHAL_COMP_MAX_LAYERS;
    pComposite->nPalettes = VPHAL_COMP_MAX_PALETTES;
    pComposite->nProcamp  = VPHAL_COMP_MAX_PROCAMP;
    pComposite->nLumaKeys = VPHAL_COMP_MAX_LUMA_KEY;
    pComposite->nAVS      = VPHAL_COMP_MAX_AVS;
    pComposite->nSampler  = VPHAL_COMP_MAX_SAMPLER;

    // reset render target count to 1
    pComposite->uTargetCount = 1;

    pComposite->bAlphaCalculateEnable = false;
}

//!
//! \brief    Get intermediate surface output
//! \param    pOutput
//!           [in] Pointer to Intermediate Output Surface
//! \return   PVPHAL_SURFACE
//!           Return the chose output
//!
MOS_STATUS CompositeState::GetIntermediateOutput(PVPHAL_SURFACE &output)
{
    output = m_Intermediate;
    return MOS_STATUS_SUCCESS;
}

PVPHAL_SURFACE CompositeState::GetIntermediateSurface()
{
    return &m_IntermediateSurface;
}

PVPHAL_SURFACE CompositeState::GetIntermediate1Surface()
{
    return &m_IntermediateSurface1;
}

PVPHAL_SURFACE CompositeState::GetIntermediate2Surface()
{
    return &m_IntermediateSurface2;
}

//!
//! \brief    Adds a source layer for composite
//! \param    [in,out] pComposite
//!           Pointer to Composite parameters
//! \param    [in] pSource
//!           Pointer to Source Surface
//! \return   bool
//!           Return TURE if source may be processed in the same phase, otherwise false
//!
bool CompositeState::AddCompLayer(
    PVPHAL_COMPOSITE_PARAMS     pComposite,
    PVPHAL_SURFACE              pSource,
    bool                        bDisableAvsSampler = false)
{
    bool                bResult;
    PVPHAL_SURFACE      pPrevSource;
    bool                bSinglePhaseRotate;
    VPHAL_SCALING_MODE  scalingMode;

    bResult            = false;
    pPrevSource        = nullptr;
    bSinglePhaseRotate = false;

    if (pComposite == nullptr || pSource == nullptr)
    {
        goto finish;
    }

    scalingMode           = pSource->ScalingMode;

    // On Gen9+, Rotation is done in sampler. Multiple phases are not required.
    if (!m_bSamplerSupportRotation)
    {
        if (pComposite->uSourceCount == 0)
        {
            // Set Layer 0 rotation info
            pComposite->Rotation = pSource->Rotation;
            bSinglePhaseRotate = true;
        }
        else if (pComposite->uSourceCount == 1)
        {
            // Single phase if: L0 (angle) + L1 (no rotation) OR L1 angle == L0 angle
            bSinglePhaseRotate = (pSource->Rotation == VPHAL_ROTATION_IDENTITY ||
                                  pSource->Rotation == pComposite->Rotation) ? true : false;
        }
        else
        {
            // Get pointer to previous source
            pPrevSource = pComposite->pSource[pComposite->uSourceCount - 1];

            // Single phase if:L2 angle == L1 angle
            bSinglePhaseRotate = (pSource->Rotation == pPrevSource->Rotation) ? true : false;
        }
    }
    else
    {
        bSinglePhaseRotate = true;
    }

    // Number of layers
    pComposite->nLayers--;

    // Number of palettes
    if (pSource->Palette.PaletteType != VPHAL_PALETTE_NONE)
    {
        pComposite->nPalettes--;
    }

    // Number of procamp parameters
    if (pSource->pProcampParams)
    {
        pComposite->nProcamp--;
    }

    // Number of luma keys
    if (pSource->pLumaKeyParams)
    {
        pComposite->nLumaKeys--;
        if (pComposite->nLumaKeys < 0 || pComposite->uSourceCount > 1)
        {
            bResult = false;
            goto finish;
        }
        if (pComposite->uSourceCount == 1)
        {
            // This layer requires 3d sampler to perform luma key.
            // So set previous layer's scaling mode to AVS and reset the nSampler.
            // Disable AVS scaling mode in cases AVS is not available
            if (pComposite->pSource[0]->ScalingMode != VPHAL_SCALING_AVS && !m_need3DSampler)
            {
                pComposite->pSource[0]->ScalingMode = VPHAL_SCALING_AVS;
                pComposite->nAVS--;
            }
            pComposite->nSampler = VPHAL_COMP_MAX_SAMPLER;
        }
    }

    // Number of AVS, but lumaKey and BOB DI needs 3D sampler instead of AVS sampler.
    if (pSource->ScalingMode == VPHAL_SCALING_AVS  && !pSource->pLumaKeyParams && !IsBobDiEnabled(pSource))
    {
        pComposite->nAVS--;
    }
    // Number of Sampler filter mode, we had better only support Nearest or Bilinear filter in one phase
    // If two filters are used together, the later filter overwrite the first and cause output quality issue.
    else if ((pSource->rcDst.right - pSource->rcDst.left) == (pSource->rcSrc.right - pSource->rcSrc.left) &&
             (pSource->rcDst.bottom - pSource->rcDst.top) == (pSource->rcSrc.bottom - pSource->rcSrc.top) &&
             !IS_PL3_FORMAT(pSource->Format))
    {
        // Use sampler luma key feature only if this is not the bottom most layer
        if (pSource->pLumaKeyParams && pComposite->uSourceCount)
        {
            scalingMode           = VPHAL_SCALING_NEAREST;
            pComposite->nSampler &= VPHAL_COMP_SAMPLER_LUMAKEY;
        }
        else if (pComposite->nSampler & VPHAL_COMP_SAMPLER_NEAREST)
        {
            scalingMode           = VPHAL_SCALING_NEAREST;
            pComposite->nSampler &= VPHAL_COMP_SAMPLER_NEAREST;
        }
        else
        {
            if (bDisableAvsSampler && (pComposite->nSampler & VPHAL_COMP_SAMPLER_BILINEAR))
            {
                scalingMode = VPHAL_SCALING_BILINEAR;
            }
            else
            {
                // switch to AVS if AVS sampler is not used, decrease the count of comp phase
                scalingMode = VPHAL_SCALING_AVS;
                pComposite->nAVS--;
            }
        }
    }
    else if (!IS_PL3_FORMAT(pSource->Format))
    {
        // Use sampler luma key feature only if this is not the bottom most layer
        if (pSource->pLumaKeyParams && pComposite->uSourceCount)
        {
            scalingMode           = VPHAL_SCALING_BILINEAR;
            pComposite->nSampler &= VPHAL_COMP_SAMPLER_LUMAKEY;
        }
        else if (pComposite->nSampler & VPHAL_COMP_SAMPLER_BILINEAR)
        {
            scalingMode           = VPHAL_SCALING_BILINEAR;
            pComposite->nSampler &= VPHAL_COMP_SAMPLER_BILINEAR;
        }
        else
        {
            if (bDisableAvsSampler && (pComposite->nSampler & VPHAL_COMP_SAMPLER_NEAREST))
            {
                scalingMode = VPHAL_SCALING_NEAREST;
            }
            else
            {
                // switch to AVS if AVS sampler is not used, decrease the count of comp phase
                scalingMode = VPHAL_SCALING_AVS;
                pComposite->nAVS--;
            }
        }
    }

    // Fails if any of the limits are reached
    // Output structure has reason why failed :-)
    // multi-passes if rotation is not the same as Layer 0 rotation
    // single pass if Primary layer needs rotation and remaining layer does not need rotation
    if (pComposite->nLayers   < 0 ||
        pComposite->nPalettes < 0 ||
        pComposite->nProcamp  < 0 ||
        pComposite->nLumaKeys < 0 ||
        pComposite->nAVS      < 0 ||
        pComposite->nSampler == 0 ||
        bSinglePhaseRotate   == false)
    {
        //Multipass
        goto finish;
    }

    // Append source to compositing operation
    pSource->ScalingMode = scalingMode;
    pComposite->pSource[pComposite->uSourceCount] = pSource;
    pComposite->uSourceCount++;
    bResult = true;

    VPHAL_RENDER_NORMALMESSAGE("ScalingMode %d, nSampler %d", pSource->ScalingMode, pComposite->nSampler);

finish:
    return bResult;
}

//!
//! \brief    Adds render target layer for composite
//! \param    [in,out] pComposite
//!           Pointer to Composite parameters
//! \param    [in] pTarget
//!           Pointer to target surface
//! \return   bool
//!           Return TURE if target may be processed in the same phase, otherwise false
//!
bool CompositeState::AddCompTarget(
    PVPHAL_COMPOSITE_PARAMS     pComposite,
    PVPHAL_SURFACE              pTarget)
{
    bool    bResult = false;
    if (nullptr == pTarget)
    {
        return bResult;
    }
    // Set render target
    pComposite->Target[0] = *pTarget;

    // Number of procamp parameters
    if (pTarget->pProcampParams)
    {
        pComposite->nProcamp--;
    }

    // Fails if max procamp already reached
    // Procamp needs to be performed in a different phase
    if (pComposite->nProcamp  < 0)
    {
        bResult = false;
        pComposite->Target[0].pProcampParams = nullptr;
    }
    else
    {
        bResult = true;
    }

    return bResult;
}

//!
//! \brief    Composite multiple phase rendering
//! \details  Composite render with multiple phases. In some cases we cannot process composition just in one phase
//!           for example, if the input streams count is 9 (1 primary + 8 substreams), we need to postpone the
//!           9th stream to next second phase due to the input count limitation of current composition kernel.
//! \param    [in] pcRenderParams
//!           Pointer to VPHAL_RENDER_PARAMS
//! \param    [in] ppSources
//!           Pointer to PVPHAL_SURFACE, array of input surfaces
//! \param    [in] iSources
//!           constant int iSource indicating the size of ppSources
//! \param    [in] pOutput
//!           Pointer to VPHAL_SURFACE, output surface for the overall composition process
//! \return   MOS_STATUS
//!           Return MOS_STATUS_SUCCESS if successful, otherwise failed
//!
MOS_STATUS CompositeState::RenderMultiPhase(
    PCVPHAL_RENDER_PARAMS   pcRenderParams,
    PVPHAL_SURFACE          *ppSources,
    const int32_t           iSources,
    PVPHAL_SURFACE          pOutput)
{
    MOS_STATUS           eStatus;
    int32_t              phase;                         // Current phase
    int32_t              i;                             // Auxiliary integer
    uint32_t             index;                         // Current source index
    PVPHAL_SURFACE       pSrc                = nullptr; // Current source surface
    PRENDERHAL_INTERFACE pRenderHal          = m_pRenderHal;
    PMOS_INTERFACE       pOsInterface        = m_pOsInterface;
    bool                 bLastPhase          = false;
    bool                 bExtraRotationPhase = false;

    // Perf related
    bool                 bPrimary, bRotation;
    VPHAL_PERFTAG        PerfTag;

    for (index = 0, phase = 0; (!bLastPhase); phase++)
    {
        bool                   disableAvsSampler = false;
        // AdjustParamsBasedOnFcLimit must be called before IsDisableAVSSampler in legacy path, or it will miss the AVS WA
        bool                   adjustParamBasedOnFcLimit = AdjustParamsBasedOnFcLimit(pcRenderParams);
        VPHAL_COMPOSITE_PARAMS  CompositeParams;
        // Prepare compositing structure
        ResetCompParams(&CompositeParams);

        if (IsDisableAVSSampler(iSources, 0 < pOutput->rcDst.top))
        {
            VPHAL_RENDER_ASSERTMESSAGE("Disable AVS sampler for TargetTopY!");
            disableAvsSampler = true;
        }

//        VPHAL_DBG_STATE_DUMPPER_SET_CURRENT_PHASE(phase);

        //Set the alpha for composited surface
        CompositeParams.pCompAlpha = pcRenderParams->pCompAlpha;

        // First phase - set colorfill + render all blocks
        if (phase == 0)
        {
            CompositeParams.pColorFillParams = pcRenderParams->pColorFillParams;
            CompositeParams.bSkipBlocks      = false;
        }
        else
        // Other phases - skip blocks by default (modified if RT has Procamp)
        {
            CompositeParams.bSkipBlocks      = true;
        }

        // Constricted output - affects coordinate calculations
        CompositeParams.pConstriction = pcRenderParams->pConstriction;

        // Validate samples and number of samples for each layer
        bLastPhase = true;
        bPrimary   = false;
        bRotation  = false;
        for (i = 0; index < (uint32_t)iSources || bExtraRotationPhase; i++)
        {
            // Set previous output as the first layer
            if (i == 0 && phase != 0)
            {
                // Optimization for 2 layers composition (with sub-layer rotation) usage case , in the second phase, the first layer should be layer0
                if (!m_bApplyTwoLayersCompOptimize || (iSources != 2) || (ppSources[1]->Rotation == VPHAL_ROTATION_IDENTITY))
                {
                    pSrc = pOutput;
                    GetIntermediateOutput(pOutput);  // this is the virtual function to use the pingpang buffer for corruption fix on some platforms.
                }
                else
                {
                    CompositeParams.pColorFillParams = pcRenderParams->pColorFillParams;
                    CompositeParams.bSkipBlocks      = false;
                    pSrc = ppSources[0];
                }
            }
            else if (i == 1 && bExtraRotationPhase)
            {
                // bExtraRotationPhase == true means that Intermediate2 was used as a
                // temp output resource in the previous phase and now is to be
                // used as an input
                pSrc = m_Intermediate2;
                pSrc->SurfType = SURF_IN_SUBSTREAM; // set the surface type to substream
                bExtraRotationPhase = false;        // reset rotation phase
            }
            else
            {
                pSrc = ppSources[index];
                index++;
            }

            // Set if primary is present
            if (pSrc->SurfType == SURF_IN_PRIMARY)
            {
                bPrimary = true;
            }

            // Add layer to the compositing - breaks at end of phase
            pSrc->iLayerID = i;

            if (disableAvsSampler && VPHAL_SCALING_AVS == pSrc->ScalingMode)
            {
                VPHAL_RENDER_ASSERTMESSAGE("Force to 3D sampler for layer %d.", pSrc->iLayerID);
                pSrc->ScalingMode = VPHAL_SCALING_BILINEAR;
            }

            //Skip Blend PARTIAL for alpha input non alpha output
            if (pSrc->pBlendingParams && pSrc->pBlendingParams->BlendType == BLEND_PARTIAL)
            {
                if (pOutput)
                {
                    if (IS_ALPHA_FORMAT(pSrc->Format) &&
                        !IS_ALPHA_FORMAT(pOutput->Format))
                    {
                        VP_PUBLIC_NORMALMESSAGE("Force to use Blend Source instead of Blend Partial");
                        pSrc->pBlendingParams->BlendType = BLEND_SOURCE;
                    }
                }
            }
            if (!AddCompLayer(&CompositeParams, pSrc, disableAvsSampler))
            {
                bLastPhase = false;
                index--;
                break;
            }

            if (pSrc->Rotation != VPHAL_ROTATION_IDENTITY)
            {
                bRotation = true;
            }
        }

        // Setup render target
        bLastPhase &= AddCompTarget(&CompositeParams, pOutput);

        // Last phase
        if (bLastPhase && pcRenderParams->pConstriction == nullptr)
        {
            // Set the actual render target(s), process all blocks
            i = 0;
            do
            {
                CompositeParams.Target[i] = *pcRenderParams->pTarget[i];
                i++;
                CompositeParams.uTargetCount  = i;
            } while (i < (int32_t)pcRenderParams->uDstCount);

            CompositeParams.bSkipBlocks = false;

            // Force the output rectangles to be the final render target rectangles.
            // pTarget could be used as an input as well because it could be used
            // as a temp output in the previous render phase.
            CompositeParams.Target[0].rcSrc = pcRenderParams->pTarget[0]->rcSrc;
            CompositeParams.Target[0].rcDst = pcRenderParams->pTarget[0]->rcDst;
        }

        // Force output as "render target" surface type
        CompositeParams.Target[0].SurfType = SURF_OUT_RENDERTARGET;

        // Reset states before rendering (clear allocations, get GSH allocation index
        //                                + any additional housekeeping)
        pOsInterface->pfnResetOsStates(pOsInterface);
        VPHAL_RENDER_CHK_STATUS(pRenderHal->pfnReset(pRenderHal));

        // Set Slice Shutdown Mode
        if (m_bSingleSlice)
        {
            pRenderHal->pfnSetSliceShutdownMode(pRenderHal, true);
        }

        // Set performance tag for current phase
        // Set rotation perftag if there is a layer that needs to be rotated in
        // the current phase, regardless of primary or non-primary.
        if (bRotation)
        {
            PerfTag = (VPHAL_PERFTAG)((int)VPHAL_ROT + i - 1);
        }
        else if (bPrimary)
        {
            PerfTag = (VPHAL_PERFTAG)((int)VPHAL_PRI + i - 1);
        }
        else
        {
            PerfTag = (VPHAL_PERFTAG)((int)VPHAL_NONE + i);
        }
        pOsInterface->pfnSetPerfTag(pOsInterface, PerfTag);

        // Flag to indicate to do the alpha calculate
        CompositeParams.bAlphaCalculateEnable = pcRenderParams->bCalculatingAlpha;

        // Perform compositing operation
        // Optimization for 2 layers composition (with sub-layer rotation) usage case , skip the first phase composition (layer0 -> RT)
        if (!m_bApplyTwoLayersCompOptimize || bLastPhase || (iSources != 2) || (ppSources[1]->Rotation == VPHAL_ROTATION_IDENTITY))
        {
            m_bLastPhase = bLastPhase && (pcRenderParams->pConstriction == nullptr);
            VPHAL_RENDER_CHK_STATUS(RenderPhase(&CompositeParams));
        }

        // do an extra rotation if needed
        bExtraRotationPhase = false;

        // If rotation is done in sampler. Multiple phases are not required.
        if (!m_bSamplerSupportRotation)
        {
            if ((!bLastPhase) && pSrc && (pSrc->Rotation != VPHAL_ROTATION_IDENTITY))
            {
                bExtraRotationPhase = true;

                // Prepare compositing structure
                ResetCompParams(&CompositeParams);

                // Optimization for 2 layers composition (with sub-layer rotation) usage case, This is the first phase
                if ((iSources != 2) || (ppSources[1]->Rotation == VPHAL_ROTATION_IDENTITY))
                {
                    CompositeParams.bSkipBlocks   = true;
                }
                else
                {
                    // set colorfill + render all blocks
                    CompositeParams.pColorFillParams = pcRenderParams->pColorFillParams;
                    CompositeParams.bSkipBlocks      = false;
                }

                // Set the alpha for composited surface
                CompositeParams.pCompAlpha = pcRenderParams->pCompAlpha;

                // When building filter description, if the first layer is translucent,
                // colorfill will always be used. But in this rotation phase, if the
                // src rectangle can cover dest, there is no need to do colorfill.
                // Force skip it here to avoid performance drop.
                CompositeParams.bForceSkipColorFill = true;

                CompositeParams.pConstriction   = nullptr;
                // process the next sample, cannot group more samples here because
                // the temporary output will be the input of next phase and we need
                // new kernel to deal with the transparent area of the bigger rectangle
                // of the temporary output.
                pSrc = ppSources[index];
                index++;
                pSrc->iLayerID = 0;
                AddCompLayer(&CompositeParams, pSrc, disableAvsSampler);

                // using pTarget as a temp resource
                if (pSrc->pBlendingParams)
                {
                    if (m_Intermediate2 && m_Intermediate2->pBlendingParams == nullptr)
                    {
                        m_Intermediate2->pBlendingParams = (PVPHAL_BLENDING_PARAMS)
                            MOS_AllocAndZeroMemory(sizeof(VPHAL_BLENDING_PARAMS));
                    }
                    if (m_Intermediate2 && m_Intermediate2->pBlendingParams)
                    {
                        m_Intermediate2->pBlendingParams->BlendType = pSrc->pBlendingParams->BlendType;
                        m_Intermediate2->pBlendingParams->fAlpha    = pSrc->pBlendingParams->fAlpha;
                    }
                }
                else
                {
                    // clear the blending params if it was set from the previous phase
                    if (m_Intermediate2 && m_Intermediate2->pBlendingParams)
                    {
                        MOS_FreeMemory(m_Intermediate2->pBlendingParams);
                        m_Intermediate2->pBlendingParams = nullptr;
                    }
                }

                // update the output rectangles with the input rectangles
                if (m_Intermediate2)
                {
                    m_Intermediate2->rcDst = m_Intermediate2->rcSrc = pSrc->rcDst;
                }

                AddCompTarget(&CompositeParams, m_Intermediate2);
                // Force output as "render target" surface type
                CompositeParams.Target[0].SurfType = SURF_OUT_RENDERTARGET;

                // Reset states before rendering (clear allocations, get GSH allocation index
                //                                + any additional housekeeping)
                pOsInterface->pfnResetOsStates(pOsInterface);
                VPHAL_RENDER_CHK_STATUS(pRenderHal->pfnReset(pRenderHal));

                // Set performance tag for current rotation phase
                PerfTag = (VPHAL_PERFTAG)((int)VPHAL_ROT);
                pOsInterface->pfnSetPerfTag(pOsInterface, PerfTag);

                // Perform compositing operation
                VPHAL_RENDER_CHK_STATUS(RenderPhase(&CompositeParams));
            }
        }
    }
    eStatus = MOS_STATUS_SUCCESS;
finish:
    return eStatus;
}

//!
//! \brief    Composite Rendering
//! \details  VPHal Composite Render entry, this render handles Procamp/CSC/ColorFill/
//!           Scaling/BOBDI
//! \param    [in,out] pcRenderParams
//!           Pointer to Render parameters
//! \return   MOS_STATUS
//!           Return MOS_STATUS_SUCCESS if successful, otherwise failed
//!
MOS_STATUS CompositeState::Render(
    PCVPHAL_RENDER_PARAMS  pcRenderParams,
    RenderpassData         *pRenderPassData)
{
    MOS_STATUS              eStatus;

    PRENDERHAL_INTERFACE    pRenderHal = nullptr;
    PMOS_INTERFACE          pOsInterface;

    // Sorted sources for compositing
    int32_t                 iProcamp;                    // Procamp Index
    int32_t                 iSources;                    // Number of sources
    PVPHAL_SURFACE          pSources[VPHAL_MAX_SOURCES]; // Array of sources

    Kdll_Procamp            Procamp;
    Kdll_Procamp            *pProcamp;
    PVPHAL_PROCAMP_PARAMS   pProcampParams;

    PRENDERHAL_L3_CACHE_SETTINGS pCacheSettings = nullptr;

    VPHAL_CSPACE            ColorSpace;     // Temporary colorspace
    PVPHAL_SURFACE          pTarget;        // Render target
    PVPHAL_SURFACE          pOutput;        // Compositing output
    int32_t                 index;          // Current source index
    bool                    bMultiplePhases;
    PVPHAL_RNDR_PERF_DATA   pPerfData;

    eStatus = MOS_STATUS_UNKNOWN;

    VPHAL_RENDER_FUNCTION_ENTER;

    VPHAL_RENDER_CHK_NULL(pcRenderParams);
    VPHAL_RENDER_CHK_NULL(m_pOsInterface);
    VPHAL_RENDER_CHK_NULL(m_pRenderHal);
    VPHAL_RENDER_ASSERT(m_pKernelDllState);

    // Increment Call ID (regardless of failure)
    m_iCallID++;

    pOsInterface = m_pOsInterface;
    pRenderHal   = m_pRenderHal;
    pPerfData    = GetPerfData();
    m_Intermediate  = GetIntermediateSurface();
    VPHAL_RENDER_CHK_NULL(m_Intermediate);
    m_Intermediate1 = GetIntermediate1Surface();
    VPHAL_RENDER_CHK_NULL(m_Intermediate1);
    m_Intermediate2 = GetIntermediate2Surface();
    VPHAL_RENDER_CHK_NULL(m_Intermediate2);
    // Reset compositing sources
    iSources  = 0;
    iProcamp  = 0;
    pTarget   = pcRenderParams->pTarget[0];
    MOS_ZeroMemory(pSources, sizeof(pSources));

    // Reset reporting
    m_reporting->InitReportValue();

    // Reset states before rendering (clear allocations, get GSH allocation index
    //                                + any additional housekeeping)
    pOsInterface->pfnResetOsStates(pOsInterface);
    VPHAL_RENDER_CHK_STATUS(pRenderHal->pfnReset(pRenderHal));
    pOsInterface->pfnResetPerfBufferID(pOsInterface);   // reset once per frame

    // Configure cache settings for this render operation
    pCacheSettings      = &pRenderHal->L3CacheSettings;
    MOS_ZeroMemory(pCacheSettings, sizeof(*pCacheSettings));
    pCacheSettings->bOverride                  = true;
    pCacheSettings->bL3CachingEnabled          = m_SurfMemObjCtl.bL3CachingEnabled;
    if (pPerfData->L3SQCReg1Override.bEnabled)
    {
        pCacheSettings->bSqcReg1Override       = true;
        pCacheSettings->dwSqcReg1              = pPerfData->L3SQCReg1Override.uiVal;
    }

    if (pPerfData->L3CntlReg2Override.bEnabled)
    {
        pCacheSettings->bCntlReg2Override      = true;
        pCacheSettings->dwCntlReg2             = pPerfData->L3CntlReg2Override.uiVal;
    }

    if (pPerfData->L3CntlReg3Override.bEnabled)
    {
        pCacheSettings->bCntlReg3Override      = true;
        pCacheSettings->dwCntlReg3             = pPerfData->L3CntlReg3Override.uiVal;
    }

    if (pPerfData->L3LRA1RegOverride.bEnabled)
    {
        pCacheSettings->bLra1RegOverride       = true;
        pCacheSettings->dwLra1Reg              = pPerfData->L3LRA1RegOverride.uiVal;
    }

    if (pPerfData->L3CntlRegOverride.bEnabled)
    {
        pCacheSettings->bCntlRegOverride       = true;
        pCacheSettings->dwCntlReg              = pPerfData->L3CntlRegOverride.uiVal;
    }

    index = 0;
    while (iSources < (int)pcRenderParams->uSrcCount)
    {
        VPHAL_GET_SURFACE_INFO Info;
        PVPHAL_SURFACE         pSrc;    // Current source surface

        pSrc = pcRenderParams->pSrc[index++];
        if (pSrc == nullptr)
        {
            continue;
        }

        VPHAL_RENDER_ASSERT(!Mos_ResourceIsNull(&pSrc->OsResource));

        //update resource usage type
        pOsInterface->pfnUpdateResourceUsageType(&pSrc->OsResource, MOS_HW_RESOURCE_USAGE_VP_INPUT_PICTURE_RENDER);

        // Get resource information
        MOS_ZeroMemory(&Info, sizeof(VPHAL_GET_SURFACE_INFO));

        VPHAL_RENDER_CHK_STATUS(VpHal_GetSurfaceInfo(
            pOsInterface,
            &Info,
            pSrc));

        //Need to decompress input surface, only if input surface is interlaced and in the RC compression Mode
        VPHAL_RENDER_CHK_STATUS(DecompressInterlacedSurf(pSrc));

        // Ensure the input is ready to be read
        pOsInterface->pfnSyncOnResource(
            pOsInterface,
            &pSrc->OsResource,
            pOsInterface->CurrentGpuContextOrdinal,
            false);

        // Field Weaving needs ref sample
        if (pSrc->bFieldWeaving && pSrc->pBwdRef)
        {
            //update resource usage type
            pOsInterface->pfnUpdateResourceUsageType(&pSrc->OsResource, MOS_HW_RESOURCE_USAGE_VP_INPUT_REFERENCE_RENDER);

            MOS_ZeroMemory(&Info, sizeof(VPHAL_GET_SURFACE_INFO));

            VPHAL_RENDER_CHK_STATUS(VpHal_GetSurfaceInfo(
                pOsInterface,
                &Info,
                pSrc->pBwdRef));

            // Ensure the input is ready to be read
            pOsInterface->pfnSyncOnResource(
                pOsInterface,
                &pSrc->pBwdRef->OsResource,
                pOsInterface->CurrentGpuContextOrdinal,
                false);
        }

        // Procamp
        pProcampParams = pSrc->pProcampParams;
        if (pProcampParams && pProcampParams->bEnabled)
        {
            pProcamp = &m_Procamp[iProcamp];
            Procamp.iProcampVersion = pProcamp->iProcampVersion;
            Procamp.bEnabled    =  true;
            Procamp.fBrightness =  pProcampParams->fBrightness;
            Procamp.fContrast   =  pProcampParams->fContrast  ;
            Procamp.fHue        =  pProcampParams->fHue       ;
            Procamp.fSaturation =  pProcampParams->fSaturation;

            // Update procamp version and values only if changed
            if (memcmp(pProcamp, &Procamp, sizeof(Procamp)))
            {
                Procamp.iProcampVersion = m_iProcampVersion++;
                *pProcamp = Procamp;
            }

            iProcamp++;
        }

        // Set sources for rendering
        pSources[iSources] = pSrc;
        iSources++;
    }

    // Sync on Render Target(s)
    index = 0;
    do
    {
        //update resource usage type
        pOsInterface->pfnUpdateResourceUsageType(&pcRenderParams->pTarget[index]->OsResource, MOS_HW_RESOURCE_USAGE_VP_OUTPUT_PICTURE_RENDER);

        pOsInterface->pfnSyncOnResource(
            pOsInterface,
            &pcRenderParams->pTarget[index]->OsResource,
            pOsInterface->CurrentGpuContextOrdinal,
            true);
        index++;
    } while (index < (int32_t)pcRenderParams->uDstCount);

    // Sync Render Target with Overlay Context
    if (pTarget->bOverlay)
    {
        pOsInterface->pfnSyncOnOverlayResource(
            pOsInterface,
            &pTarget->OsResource,
            pOsInterface->CurrentGpuContextOrdinal);
    }

    // Check max number sources
    if (iSources > VPHAL_MAX_SOURCES)
    {
        VPHAL_RENDER_ASSERTMESSAGE("Invalid number of samples.");
        goto finish;
    }
    pRenderHal->eufusionBypass = pRenderHal->eufusionBypass || ((iSources > 1) ? 1:0);

    VPHAL_RENDER_NORMALMESSAGE("eufusionBypass = %d", pRenderHal->eufusionBypass ? 1 : 0);

    // Determine cspace for compositing
    ColorSpace = PrepareCSC(pcRenderParams,
                            pSources,
                            iSources);

    bMultiplePhases = PreparePhases(pcRenderParams,
                                    pSources,
                                    iSources);
    if (!bMultiplePhases)
    {
        pOutput = pTarget;
    }
    else
    {
        pOutput = m_Intermediate;
        pOutput->ColorSpace = ColorSpace;
        m_Intermediate2->ColorSpace = ColorSpace;

        // Set AYUV or ARGB output depending on intermediate cspace
        if (KernelDll_IsCspace(ColorSpace, CSpace_RGB))
        {
            pOutput->Format = Format_A8R8G8B8;
            m_Intermediate1->Format = Format_A8R8G8B8;
            m_Intermediate2->Format = Format_A8R8G8B8;
        }
        else
        {
            pOutput->Format = Format_AYUV;
            m_Intermediate1->Format = Format_AYUV;
            m_Intermediate2->Format = Format_AYUV;
        }
    }

    VPHAL_RENDER_CHK_STATUS(RenderMultiPhase(pcRenderParams, pSources, iSources, pOutput));

    // Last constriction phase
    if (pcRenderParams->pConstriction)
    {
        VPHAL_COMPOSITE_PARAMS  CompositeParams;

        // Prepare compositing structure
        ResetCompParams(&CompositeParams);

        // set additional render target
        if (pcRenderParams->uDstCount == 2)
        {
            CompositeParams.uTargetCount    = pcRenderParams->uDstCount;
            CompositeParams.Target[1]       = *pcRenderParams->pTarget[1];
        }

        pTarget->SurfType = SURF_OUT_RENDERTARGET;

        // Prepare temporary output for final upscaling
        pOutput->ScalingMode = VPHAL_SCALING_BILINEAR;
        pOutput->rcSrc       = *(pcRenderParams->pConstriction);
        pOutput->rcDst       = pTarget->rcDst;

        AddCompLayer(&CompositeParams, pOutput);

        AddCompTarget(&CompositeParams, pTarget);

        // Reset states before rendering (clear allocations, get GSH allocation index
        //                                + any additional housekeeping)
        pOsInterface->pfnResetOsStates(pOsInterface);
        VPHAL_RENDER_CHK_STATUS(pRenderHal->pfnReset(pRenderHal));

        // Raise the flag to indicate the last comp render phase
        m_bLastPhase = true;

        // Perform compositing operation
        VPHAL_RENDER_CHK_STATUS(RenderPhase(&CompositeParams));
    }

finish:
    if (pCacheSettings)
    {
        MOS_ZeroMemory(pCacheSettings, sizeof(*pCacheSettings));
    }
    // Reset Slice Shutdown Mode
    if (pRenderHal)
    {
        pRenderHal->pfnSetSliceShutdownMode(pRenderHal, false);
    }

    VPHAL_RENDER_EXITMESSAGE("eStatus %d", eStatus);

    return eStatus;
}

//!
//! \brief    Set Composite Scaling mode
//! \param    [in,out] pSource
//!           Pointer to Source Surface
//! \param    [in] uSourceCount
//!           Count of Source Surfaces
//! \return   void
//!
void CompositeState::SetScalingMode(
    PVPHAL_SURFACE          pSource,
    uint32_t                uSourceCount)
{
    float   fScaleX, fScaleY;

    VPHAL_RENDER_ASSERT(pSource);

    // Default mode
    pSource->bIEF = false;

    // Source rectangle is pre-rotated, destination rectangle is post-rotated.
    if (pSource->Rotation == VPHAL_ROTATION_IDENTITY    ||
        pSource->Rotation == VPHAL_ROTATION_180         ||
        pSource->Rotation == VPHAL_MIRROR_HORIZONTAL    ||
        pSource->Rotation == VPHAL_MIRROR_VERTICAL)
    {
        fScaleX      = (float)(pSource->rcDst.right  - pSource->rcDst.left) /
                       (float)(pSource->rcSrc.right  - pSource->rcSrc.left);
        fScaleY      = (float)(pSource->rcDst.bottom - pSource->rcDst.top) /
                       (float)(pSource->rcSrc.bottom - pSource->rcSrc.top);
    }
    else
    {
        // VPHAL_ROTATION_90 || VPHAL_ROTATION_270 ||
        // VPHAL_ROTATE_90_MIRROR_HORIZONTAL || VPHAL_ROTATE_90_MIRROR_VERTICAL
        fScaleX      = (float)(pSource->rcDst.right  - pSource->rcDst.left) /
                       (float)(pSource->rcSrc.bottom  - pSource->rcSrc.top);
        fScaleY      = (float)(pSource->rcDst.bottom - pSource->rcDst.top) /
                       (float)(pSource->rcSrc.right - pSource->rcSrc.left);
    }

    // Enable AVS/IEF for primary video only
    // AVS is supported only for y-scaling ratios > 0.0625
    // Starting from IVB, AVS is supported only for x-scaling ratios > 0.0625
    if (pSource->ScalingMode == VPHAL_SCALING_AVS   &&
        fScaleX > 0.0625f                           &&
        fScaleY > 0.0625f)
    {
        // Interlaced content - Disable AVS for BOB implementation
        if (IsBobDiEnabled(pSource))
        {
            pSource->ScalingMode = VPHAL_SCALING_BILINEAR;
        }
        // Enable IEF
        else if (pSource->pIEFParams             &&
                 pSource->pIEFParams->bEnabled   &&
                 pSource->pIEFParams->fIEFFactor > 0.0f)
        {
            pSource->bIEF = true;
        }
        // If IEF is disabled and Scaling Ratios are 1x, use 3D Nearest
        // for better performance (applicable for Primary-only case)
        // Don't fall back to bilinear scaling if Chroma up sampling is needed
        else if (fScaleX == 1.0F   &&
                 fScaleY == 1.0F   &&
                 uSourceCount == 1 &&
                 !m_bChromaUpSampling)
        {
            pSource->ScalingMode = VPHAL_SCALING_BILINEAR;
        }
    }
    else
    {
        pSource->ScalingMode = VPHAL_SCALING_BILINEAR;
    }

    // Fix Interlace Scaling Hang issue, switch avs to bilinear scaling because kernels
    // are using 3d samplers for unaligned cases
    if (pSource->bInterlacedScaling                                                 &&
        (!MOS_IS_ALIGNED(MOS_MIN(pSource->dwWidth, (uint32_t)pSource->rcSrc.right), 4) ||
         !MOS_IS_ALIGNED(pSource->dwHeight, 4)))
    {
        pSource->ScalingMode = VPHAL_SCALING_BILINEAR;
    }

    // Fix GPU Hang on EHL, since EHL has no AVS sampler
    if (MEDIA_IS_SKU(m_pSkuTable, FtrDisableVEBoxFeatures))
    {
        pSource->ScalingMode = VPHAL_SCALING_BILINEAR;
    }

    // WA for multilayer P010 AVS+3D one single pass corruption hw issue
    if (uSourceCount > 1 &&
        pSource->Format == Format_P010)
    {
        pSource->ScalingMode = VPHAL_SCALING_BILINEAR;
    }

}

//!
//! \brief    Initialize Composite Rendering data
//! \details  Initialize Composite Rendering data, set output area, number of blocks,
//!           Sources, constriction parameters, rendering states, etc.
//! \param    [in] pCompParams
//!           Pointer to Composite parameters
//! \param    [out] pRenderingData
//!           Pointer to Composite Rendering data
//! \return   MOS_STATUS
//!
MOS_STATUS CompositeState::RenderInit(
    PVPHAL_COMPOSITE_PARAMS         pCompParams,
    PVPHAL_RENDERING_DATA_COMPOSITE pRenderingData)
{
    PRENDERHAL_INTERFACE    pRenderHal;
    RECT                    AlignedRect;
    uint32_t                uiMediaWalkerBlockSize;
    PRECT                   pDst;
    MOS_STATUS              eStatus = MOS_STATUS_SUCCESS;

    VPHAL_RENDER_CHK_NULL(m_pRenderHal);
    VPHAL_RENDER_CHK_NULL(pCompParams);
    VPHAL_RENDER_CHK_NULL(pRenderingData);

    pRenderHal   = m_pRenderHal;

    //============================
    // Set rendering data
    //============================
    MOS_ZeroMemory(pRenderingData, sizeof(VPHAL_RENDERING_DATA_COMPOSITE));

    // Set output area
    if (pCompParams->uTargetCount == 2)
    {
        // Output rectangle based on non-rotated target in case of dual output
        pRenderingData->BbArgs.rcOutput = pCompParams->Target[1].rcDst;
        pRenderingData->pTarget[1]      = &pCompParams->Target[1];
    }
    else
    {
        pRenderingData->BbArgs.rcOutput = pCompParams->Target[0].rcDst;
    }

    pDst = &(pRenderingData->BbArgs.rcOutput);

    if (m_bFtrMediaWalker)
    {
        uiMediaWalkerBlockSize = pRenderHal->pHwSizes->dwSizeMediaWalkerBlock;
    }
    else
    {
        uiMediaWalkerBlockSize = VPHAL_COMP_BLOCK_WIDTH;
    }

    // Calculate aligned output area in order to determine the total # blocks to process
    // in case of non-16x16 aligned target
    AlignedRect         = *pDst;
    AlignedRect.right  += uiMediaWalkerBlockSize  - 1;
    AlignedRect.bottom += uiMediaWalkerBlockSize - 1;
    AlignedRect.left   -= AlignedRect.left   % uiMediaWalkerBlockSize;
    AlignedRect.top    -= AlignedRect.top    % uiMediaWalkerBlockSize;
    AlignedRect.right  -= AlignedRect.right  % uiMediaWalkerBlockSize;
    AlignedRect.bottom -= AlignedRect.bottom % uiMediaWalkerBlockSize;

    // Set number of blocks
    pRenderingData->iBlocksX =
        (AlignedRect.right  - AlignedRect.left) / uiMediaWalkerBlockSize;
    pRenderingData->iBlocksY =
        (AlignedRect.bottom - AlignedRect.top ) / uiMediaWalkerBlockSize;

    // Set sources
    pRenderingData->iLayers                = 0;
    pRenderingData->pTarget[0]             = &pCompParams->Target[0];
    pRenderingData->pColorFill             = pCompParams->pColorFillParams;
    pRenderingData->pCompAlpha             = pCompParams->pCompAlpha;

    // Set constriction parameters
    pRenderingData->pConstriction = pCompParams->pConstriction;
    if (pCompParams->pConstriction)
    {
        pRenderingData->ConstrictionOriginX = pDst->left;
        pRenderingData->ConstrictionOriginY = pDst->top;
        pRenderingData->fConstrictionStepX  = (pDst->right - pDst->left) * 1.0f /
                                               pCompParams->pConstriction->right;
        pRenderingData->fConstrictionStepY  = (pDst->bottom - pDst->top) * 1.0f /
                                               pCompParams->pConstriction->bottom;
    }
    else
    {
        pRenderingData->ConstrictionOriginX = 0;
        pRenderingData->ConstrictionOriginY = 0;
        pRenderingData->fConstrictionStepX  = 1.0f;
        pRenderingData->fConstrictionStepY  = 1.0f;
    }

    // Set AVS and 8x8 table from renderer
    pRenderingData->pAvsParams             = &m_AvsParameters;

    // Init extension data to nullptr
    pRenderingData->pExtensionData         = nullptr;

    // Initialize rendering states
    pRenderingData->Static                 = g_cInit_MEDIA_OBJECT_KA2_STATIC_DATA;
    pRenderingData->Inline                 = g_cInit_MEDIA_OBJECT_KA2_INLINE_DATA;
    pRenderingData->WalkerStatic           = g_cInit_MEDIA_WALKER_KA2_STATIC_DATA;
    pRenderingData->DPFCStatic             = {0};
    // By default, alpha is calculated in PartBlend kernel
    pRenderingData->bAlphaCalculateEnable = false;

    // Reset Sampler Params
    MOS_ZeroMemory(
        pRenderingData->SamplerStateParams,
        sizeof(pRenderingData->SamplerStateParams));

finish:
    return eStatus;
}

//!
//! \brief    Clean Composite Rendering data
//! \param    [in] pRenderingData
//!           Pointer to Composite Rendering data
//! \return   MOS_STATUS
//!
void CompositeState::CleanRenderingData(
    PVPHAL_RENDERING_DATA_COMPOSITE pRenderingData)
{
    MOS_UNUSED(pRenderingData);
}

//!
//! \brief    Get Binding Table Index associated with a given source for composite
//! \param    [in] pSource
//!           Pointer to Source Surface
//! \param    [out] pBindingIndex
//!           Pointer to Binding table index
//! \return   MOS_STATUS
//!           Return MOS_STATUS_SUCCESS if successful, otherwise MOS_STATUS_UNKNOWN
//!
static MOS_STATUS GetBindingIndex(
    PVPHAL_SURFACE          pSource,
    int32_t*                pBindingIndex)
{
    MOS_STATUS eStatus = MOS_STATUS_SUCCESS;

    if (pSource != nullptr && pBindingIndex != nullptr)
    {
        if (pSource->SurfType == SURF_OUT_RENDERTARGET)
        {
            *pBindingIndex = g_cBindingTableIndex[0];
        }
        else if (pSource->iLayerID >= 0 &&
                 pSource->iLayerID < VPHAL_COMP_MAX_LAYERS)
        {
            *pBindingIndex = g_cBindingTableIndex[pSource->iLayerID + 1];
        }
        else
        {
            eStatus = MOS_STATUS_UNKNOWN;
        }
    }
    else
    {
        eStatus = MOS_STATUS_UNKNOWN;
    }

    return eStatus;
}

//!
//! \brief    Update SamplerStateParams associated with a surface state for composite
//! \param    [in] pSamplerStateParams
//!           Pointer to SamplerStateParams
//! \param    [in] pEntry
//!           Pointer to Surface state
//! \param    [in] pRenderData
//!           Pointer to RenderData
//! \param    [in] uLayerNum
//!           Layer total number
//! \param    [in] SamplerFilterMode
//!           SamplerFilterMode to be set
//! \param    [out] pSamplerIndex
//!           Pointer to Sampler Index
//! \param    [out] pSurface
//!           point to Surface
//! \return   MOS_STATUS
//!           Return MOS_STATUS_SUCCESS if successful, otherwise MOS_STATUS_UNKNOWN
//!
MOS_STATUS CompositeState::SetSamplerFilterMode(
    PMHW_SAMPLER_STATE_PARAM&       pSamplerStateParams,
    PRENDERHAL_SURFACE_STATE_ENTRY  pEntry,
    PVPHAL_RENDERING_DATA_COMPOSITE pRenderData,
    uint32_t                        uLayerNum,
    MHW_SAMPLER_FILTER_MODE         SamplerFilterMode,
    int32_t*                        pSamplerIndex,
    PVPHAL_SURFACE                  pSource)
{
    VPHAL_RENDER_CHK_NULL_RETURN(pSamplerStateParams);
    MOS_UNUSED(pEntry);
    MOS_UNUSED(pRenderData);
    MOS_UNUSED(pSamplerIndex);
    MOS_UNUSED(pSource);

    pSamplerStateParams->Unorm.SamplerFilterMode = SamplerFilterMode;
    return MOS_STATUS_SUCCESS;
}

//!
//! \brief    Get Sampler Index associated with a surface state for composite
//! \param    [in] pSurface
//!           point to input Surface
//! \param    [in] pEntry
//!           Pointer to Surface state
//! \param    [out] pSamplerIndex
//!           Pointer to Sampler Index
//! \param    [out] pSamplerType
//!           Pointer to Sampler Type
//! \return   MOS_STATUS
//!           Return MOS_STATUS_SUCCESS if successful, otherwise MOS_STATUS_UNKNOWN
//!
MOS_STATUS CompositeState::GetSamplerIndex(
    PVPHAL_SURFACE                      pSurface,
    PRENDERHAL_SURFACE_STATE_ENTRY      pEntry,
    int32_t*                            pSamplerIndex,
    PMHW_SAMPLER_TYPE                   pSamplerType)
{
    MOS_UNUSED(pSurface);

    if (pSamplerIndex == nullptr || pSamplerType == nullptr || pEntry == nullptr)
    {
        VPHAL_RENDER_ASSERTMESSAGE(" Null pointer.");
        return MOS_STATUS_NULL_POINTER;
    }

    // AVS
    if (pEntry->bAVS)
    {
        *pSamplerType = MHW_SAMPLER_TYPE_AVS;

        if (pEntry->YUVPlane == MHW_U_PLANE)
        {
            *pSamplerIndex = VPHAL_SAMPLER_8x8_AVS_U;
        }
        else if (pEntry->YUVPlane == MHW_V_PLANE)
        {
            *pSamplerIndex = VPHAL_SAMPLER_8x8_AVS_V;
        }
        else
        {
            *pSamplerIndex = VPHAL_SAMPLER_8x8_AVS_Y;
        }
    }
    // Non-AVS
    else
    {
        *pSamplerType  = MHW_SAMPLER_TYPE_3D;

        if (pEntry->YUVPlane == MHW_U_PLANE)
        {
            *pSamplerIndex = VPHAL_SAMPLER_U;
        }
        else if (pEntry->YUVPlane == MHW_V_PLANE)
        {
            *pSamplerIndex = VPHAL_SAMPLER_V;
        }
        else
        {
            *pSamplerIndex = VPHAL_SAMPLER_Y;
        }
    }

    return MOS_STATUS_SUCCESS;
}

//!
//! \brief    Set Surface Parameters
//! \details  Set Surface Parameters, set flags for RT, set surface type based on scaling
//!           mode, set interlacing flags, etc.
//! \param    [in,out] pSource
//!           Pointer to Source Surface
//! \param    [out] pSurfaceParams
//!           Pointer to Surface Parameters
//! \return   void
//!
void CompositeState::SetSurfaceParams(
    PVPHAL_SURFACE                  pSource,
    PRENDERHAL_SURFACE_STATE_PARAMS pSurfaceParams)
{
    // Render target or private surface
    if (pSource->SurfType == SURF_OUT_RENDERTARGET)
    {
        // Disable AVS, IEF
        pSource->ScalingMode = VPHAL_SCALING_BILINEAR;
        pSource->bIEF        = false;

        // Set flags for RT
        pSurfaceParams->isOutput    = true;
        pSurfaceParams->bWidthInDword_Y  = true;
        pSurfaceParams->bWidthInDword_UV = true;
        pSurfaceParams->Boundary         = RENDERHAL_SS_BOUNDARY_DSTRECT;
    }
    // other surfaces
    else
    {
        pSurfaceParams->isOutput    = false;
        pSurfaceParams->bWidthInDword_Y  = false;
        pSurfaceParams->bWidthInDword_UV = false;
        pSurfaceParams->Boundary         = RENDERHAL_SS_BOUNDARY_SRCRECT;
    }

    // Set surface type based on scaling mode
    if (pSource->ScalingMode == VPHAL_SCALING_AVS)
    {
        pSurfaceParams->Type = m_pRenderHal->SurfaceTypeAdvanced;
        pSurfaceParams->bAVS = true;
    }
    else
    {
        pSurfaceParams->Type = m_pRenderHal->SurfaceTypeDefault;
        pSurfaceParams->bAVS = false;
    }

    // Set interlacing flags
    switch (pSource->SampleType)
    {
        case SAMPLE_INTERLEAVED_EVEN_FIRST_TOP_FIELD:
        case SAMPLE_INTERLEAVED_ODD_FIRST_TOP_FIELD:
            pSurfaceParams->bVertStride     = true;
            pSurfaceParams->bVertStrideOffs = 0;
            break;
        case SAMPLE_INTERLEAVED_EVEN_FIRST_BOTTOM_FIELD:
        case SAMPLE_INTERLEAVED_ODD_FIRST_BOTTOM_FIELD:
            pSurfaceParams->bVertStride     = true;
            pSurfaceParams->bVertStrideOffs = 1;
            break;
        default:
            pSurfaceParams->bVertStride     = false;
            pSurfaceParams->bVertStrideOffs = 0;
            break;
    }

    if (pSource->iLayerID && IsNV12SamplerLumakeyNeeded(pSource, m_pRenderHal))
    {
        pSurfaceParams->b2PlaneNV12NeededByKernel = true;
    }

     VPHAL_RENDER_NORMALMESSAGE("SurfaceTYpe %d, bAVS %d, b2PlaneNV12NeededByKernel %d",
        pSurfaceParams->Type,
        pSurfaceParams->bAVS,
        pSurfaceParams->b2PlaneNV12NeededByKernel);
}

//!
//! \brief    Decompress the Surface
//! \details  Decompress the interlaced Surface which is in the RC compression mode
//! \param    [in,out] pSource
//!           Pointer to Source Surface
//! \return   MOS_STATUS
//!           Return MOS_STATUS_SUCCESS if successful, otherwise failed
//!
MOS_STATUS CompositeState::DecompressInterlacedSurf(PVPHAL_SURFACE pSource)
{
    VPHAL_RENDER_CHK_NULL_RETURN(pSource);

    // Interlaced surface in the compression mode needs to decompress
    if (pSource->CompressionMode == MOS_MMC_RC                             &&
        (pSource->SampleType == SAMPLE_INTERLEAVED_EVEN_FIRST_TOP_FIELD    ||
         pSource->SampleType == SAMPLE_INTERLEAVED_EVEN_FIRST_BOTTOM_FIELD ||
         pSource->SampleType == SAMPLE_INTERLEAVED_ODD_FIRST_TOP_FIELD     ||
         pSource->SampleType == SAMPLE_INTERLEAVED_ODD_FIRST_BOTTOM_FIELD))
    {
        VPHAL_RENDER_CHK_NULL_RETURN(m_pOsInterface);
        bool bAllocated = false;

        //Use auxiliary surface to sync with decompression
        VPHAL_RENDER_CHK_STATUS_RETURN(VpHal_ReAllocateSurface(
            m_pOsInterface,
            &m_AuxiliarySyncSurface,
            "AuxiliarySyncSurface",
            Format_Buffer,
            MOS_GFXRES_BUFFER,
            MOS_TILE_LINEAR,
            32,
            1,
            false,
            MOS_MMC_DISABLED,
            &bAllocated));
      
        VPHAL_RENDER_CHK_STATUS_RETURN(m_pOsInterface->pfnSetDecompSyncRes(m_pOsInterface, &m_AuxiliarySyncSurface.OsResource));
        VPHAL_RENDER_CHK_STATUS_RETURN(m_pOsInterface->pfnDecompResource(m_pOsInterface, &pSource->OsResource));
        VPHAL_RENDER_CHK_STATUS_RETURN(m_pOsInterface->pfnSetDecompSyncRes(m_pOsInterface, nullptr));
        VPHAL_RENDER_CHK_STATUS_RETURN(m_pOsInterface->pfnRegisterResource(m_pOsInterface, &m_AuxiliarySyncSurface.OsResource, true, true));

        pSource->bIsCompressed     = false;
        pSource->CompressionMode   = MOS_MMC_DISABLED;
        pSource->CompressionFormat = 0;
    }
    return MOS_STATUS_SUCCESS;
}

//!
//! \brief    calculate the Horiz Gap and Vert Gap with different sample location
//! \param    [in] pTarget
//!           Pointer to Source Surface
//! \Param    [in] pHorzGap
//!           Pointer to Horzontal Gap
//! \Param    [in] pVertGap
//!           Pointer to Vertital Gap
//!
static void GetOffsetChromasiting(
    PVPHAL_SURFACE                      pSource,
    float*                              pHorizGap,
    float*                              pVertGap
    )
{
    float  HorizGap = 0.0f;
    float  VertGap  = 0.0f;

    VPHAL_RENDER_CHK_NULL_NO_STATUS(pSource);

    // If there is no DDI setting, we use the Horizontal Left Vertical Center as default for PL2 surface.
    if (pSource->ChromaSiting == CHROMA_SITING_NONE)
    {
        // PL2 default to Horizontal Left, Vertical Center
        if (IS_PL2_FORMAT(pSource->Format) || IS_PL2_FORMAT_UnAligned(pSource->Format))
        {
            VertGap = (float)(0.5f / pSource->dwHeight);
        }
    }
    else
    {
        // PL2, 6 positions are available
        if (IS_PL2_FORMAT(pSource->Format) || IS_PL2_FORMAT_UnAligned(pSource->Format))
        {
            // Horizontal Left
            if (pSource->ChromaSiting & CHROMA_SITING_HORZ_LEFT)
            {
                if (pSource->ChromaSiting & CHROMA_SITING_VERT_CENTER)
                {
                    VertGap = (float)(0.5f / pSource->dwHeight);
                }
                else if (pSource->ChromaSiting & CHROMA_SITING_VERT_BOTTOM)
                {
                    VertGap = (float)(1.0f / pSource->dwHeight);
                }
            }
            // Horizontal Center
            else if (pSource->ChromaSiting & CHROMA_SITING_HORZ_CENTER)
            {
                HorizGap = (float)(0.5f / pSource->dwWidth);
                if (pSource->ChromaSiting & CHROMA_SITING_VERT_CENTER)
                {
                    VertGap = (float)(0.5f / pSource->dwHeight);
                }
                else if (pSource->ChromaSiting & CHROMA_SITING_VERT_BOTTOM)
                {
                    VertGap = (float)(1.0f / pSource->dwHeight);
                }
            }
        }
        else if (IS_PA_FORMAT(pSource->Format))
        {
            // For PA surface, only (H Left, V Top) and (H Center, V top) are needed.
            if (pSource->ChromaSiting & (CHROMA_SITING_HORZ_CENTER))
            {
                HorizGap = (float)(0.5f / pSource->dwWidth);
            }
        }
    }
    *pVertGap = VertGap;
    *pHorizGap = HorizGap;
finish:
    return;
}

//!
//! \brief    Set Sampler AVS parameters
//! \param    [in] pRenderingData
//!           pointer to render data
//! \param    [in] pSource
//!           pointer to source surface
//! \param    [in] pSurfaceEntry
//!           pointer to source state entry
//! \param    [out] pSamplerStateParams
//!           pointer to Sampler state params
//! \param    [in] fScaleX
//!           width scaling ratio
//! \param    [in] fScaleY
//!           height scaling ratio
//! \return   MOS_STATUS
//!
MOS_STATUS CompositeState::SetSamplerAvsParams(
    PVPHAL_RENDERING_DATA_COMPOSITE pRenderingData,
    PVPHAL_SURFACE                  pSource,
    PRENDERHAL_SURFACE_STATE_ENTRY  pSurfaceEntry,
    PMHW_SAMPLER_STATE_PARAM        pSamplerStateParams,
    float                           fScaleX,
    float                           fScaleY)
{
    MOS_STATUS eStatus = MOS_STATUS_SUCCESS;

    pSamplerStateParams->Avs.bEnableAVS     = true;
    // Default values from g_cInit_SAMPLER_STATE_8x8_GX
    pSamplerStateParams->Avs.WeakEdgeThr    = DETAIL_WEAK_EDGE_THRESHOLD;
    pSamplerStateParams->Avs.StrongEdgeThr  = DETAIL_STRONG_EDGE_THRESHOLD;
    pSamplerStateParams->Avs.StrongEdgeWght = DETAIL_STRONG_EDGE_WEIGHT;
    pSamplerStateParams->Avs.RegularWght    = DETAIL_REGULAR_EDGE_WEIGHT;
    pSamplerStateParams->Avs.NonEdgeWght    = DETAIL_NON_EDGE_WEIGHT;

    pSamplerStateParams->Avs.pMhwSamplerAvsTableParam = &m_mhwSamplerAvsTableParam;

    // When primary surface needs chroma upsampling,
    // force to use polyphase coefficients for 1x scaling for better quality
    pRenderingData->pAvsParams->bForcePolyPhaseCoefs =
        m_bChromaUpSampling;

    // Setup IEF parameters for generic or luma planes (no need to setup chroma planes)
    if (pSource->pIEFParams &&
        pSource->bIEF &&
        pSurfaceEntry->YUVPlane != MHW_U_PLANE &&
        pSurfaceEntry->YUVPlane != MHW_V_PLANE &&
        (!m_bFallbackIefPatch))                                 // if m_bFallbackIefPatch is on, fallback IEF patch from AVS to SFC
    {
        Ief ief(pSource);

        eStatus = ief.SetHwState(pSamplerStateParams);
        if (eStatus != MOS_STATUS_SUCCESS)
        {
            VPHAL_RENDER_ASSERTMESSAGE("set Sampler IEF parameter failed.");
        }
    }

    eStatus = SetSamplerAvsTableParam(
        m_pRenderHal,
        pSamplerStateParams,
        pRenderingData->pAvsParams,
        pSource->Format,
        fScaleX,
        fScaleY,
        MHW_CHROMA_SITING_HORZ_LEFT | MHW_CHROMA_SITING_VERT_TOP);

    return eStatus;
}

//!
//! \brief    Calculate crop factor
//! \param    [in] iLayer
//!           layer index
//! \param    [in] pRenderingData
//!           pointer to render data
//! \param    [out] pfCropX
//!           crop factor
//! \param    [out] pfCropY
//!           crop factor
//! \return   MOS_STATUS
//!
MOS_STATUS CompositeState::CalculateCropParams(
    int32_t                         iLayer,
    PVPHAL_RENDERING_DATA_COMPOSITE pRenderingData,
    float*                          pfCropX,
    float*                          pfCropY)
{
    MOS_STATUS eStatus = MOS_STATUS_SUCCESS;

    MOS_UNUSED(iLayer);
    MOS_UNUSED(pRenderingData);

    VPHAL_RENDER_CHK_NULL_RETURN(pfCropX);
    VPHAL_RENDER_CHK_NULL_RETURN(pfCropY);

    *pfCropX = 0.0;
    *pfCropY = 0.0;

    return eStatus;
}

//!
//! \brief    Set Composite Layer
//! \details  Set Composite Layer, including setup surface state and binding table, setup
//!           lumakey parameters, setup samplers, setup alpha blending parameters, adjust
//!           geometry for BOB DI, normalize source co-ordinates, set curbe and inline
//!           data, and etc
//! \param    [in] pRenderingData
//!           Pointer to Composite Rendering data
//! \param    [in] pSource
//!           Pointer to Source Surface
//! \param    [in] iLayerIdInCompParams
//!           Index of pSource in pCompParams
//! \param    [in,out] pCompParams
//!           Pointer to Composite parameters
//! \return   int32_t
//!           Return 1 if set layer successful, otherwise -1
//!
int32_t CompositeState::SetLayer(
    PVPHAL_RENDERING_DATA_COMPOSITE pRenderingData,
    PVPHAL_SURFACE                  pSource,
    int                             iLayerIdInCompParams,
    PVPHAL_COMPOSITE_PARAMS         pCompParams)
{
    // Result
    MOS_STATUS                          eStatus;
    PRENDERHAL_SURFACE                  pRenderHalSurfaceSrc = nullptr;         // Pointer to Source RenderHal Surface related to VPHAL Surface
    PRENDERHAL_SURFACE                  pRenderHalSurfaceSrcField = nullptr;    // Pointer to Source RenderHal Surface (FieldWeaving) related to VPHAL Surface

    // States
    PRENDERHAL_INTERFACE                pRenderHal;
    int32_t                             iLayer; // The index of pSource in pRenderingData->pLayers.
    MEDIA_OBJECT_KA2_STATIC_DATA        *pStatic;
    MEDIA_OBJECT_KA2_INLINE_DATA        *pInline;
    MEDIA_DP_FC_STATIC_DATA             *pDPStatic;
    // Surface states
    int32_t                             iSurfaceEntries, i, iSurfaceEntries2;
    PRENDERHAL_SURFACE_STATE_ENTRY      pSurfaceEntries[MHW_MAX_SURFACE_PLANES];
    PRENDERHAL_SURFACE_STATE_ENTRY      pSurfaceEntries2[MHW_MAX_SURFACE_PLANES];
    PRENDERHAL_SURFACE_STATE_ENTRY      pSurfaceEntry;
    RENDERHAL_SURFACE_STATE_PARAMS      SurfaceParams, SurfaceParams2;
    int32_t                             iBTentry;

    // Sampler states
    int32_t                             iSamplerID;     // Sampler ID
    MHW_SAMPLER_TYPE                    SamplerType;    // Sampler Type
    PMHW_SAMPLER_STATE_PARAM            pSamplerStateParams;
    VPHAL_SCALING_MODE                  ScalingMode;

    // Constant alpha
    uint16_t                            wAlpha;         // Constant Alpha (8.8)

    // Geometry related parameters
    uint32_t    dwSurfStateWd, dwSurfStateHt;       // Surface Width Height as programmed in SS
    uint32_t    dwDestRectWidth, dwDestRectHeight;  // Target rectangle Width Height
    float       fOffsetY, fOffsetX;                 // x,y Sr offset
    float       fShiftX , fShiftY;                  // x,y Dst shift + Sampler BOB adj
    float       oriShiftX, oriShiftY;               // Used to check whether all entries of one layer share same shift.
    float       fDiScaleY;                          // BOB scaling factor for Y
    float       fScaleX, fScaleY;                   // x,y scaling factor
    float       fStepX , fStepY;                    // x,y scaling steps
    float       fOriginX, fOriginY;                 // x,y layer origin
    PRECT       pTargetRect;                        // Clipping rectangle (RT)
    RECT        DestRect;                           // Clipped dest rectangle
    int32_t     iResult = 0;                        // Default result = 0 (don't render the current plane)
    float       fHorizgap, fVertgap;                // horizontal gap and vertical gap: based on Sampler need
    uint32_t    dwLow, dwHigh;
    bool        bForceNearestForUV = false;

    // cropping
    float       fCropX, fCropY;

    // Temp variable for iScaling/Field Weaving
    PVPHAL_SURFACE               pTempSurf;

    if (nullptr == pRenderingData || nullptr == pSource || nullptr == pCompParams ||
        iLayerIdInCompParams < 0 || iLayerIdInCompParams >= (int)pCompParams->uSourceCount)
    {
        VPHAL_RENDER_ASSERTMESSAGE("invalid input parameters");
        iResult = -1;
        goto finish;
    }

    pRenderHalSurfaceSrc        = &pCompParams->RenderHalSurfaceSrc[iLayerIdInCompParams];
    pRenderHalSurfaceSrcField   = &pCompParams->RenderHalSurfaceSrcField[iLayerIdInCompParams];

    ScalingMode = pSource->ScalingMode;

    // init surface parameters
    MOS_ZeroMemory(&SurfaceParams, sizeof(SurfaceParams));
    MOS_ZeroMemory(&SurfaceParams2, sizeof(SurfaceParams2));
    pTempSurf   = nullptr;

    // Init x,y Sr offset/Dst shift.
    fOffsetX = 0;
    fOffsetY = 0;
    fShiftX  = 0;
    fShiftY  = 0;
    oriShiftX = 0.0f;
    oriShiftY = 0.0f;

    // Initialize States
    pRenderHal   = m_pRenderHal;
    iLayer       = pRenderingData->iLayers;
    if(m_bFtrMediaWalker)
    {
        pStatic      = (MEDIA_OBJECT_KA2_STATIC_DATA*)&pRenderingData->WalkerStatic;
    }
    else
    {
        pStatic      = &pRenderingData->Static;
    }
    pDPStatic = &pRenderingData->DPFCStatic;

    pInline      = &pRenderingData->Inline;

    // Set the default alpha value to 0 for Android platform
    // According to the Partial Blending algorithm, if the default colorfill_a is set to 255, the output alpha value will be 0xFE or 0xFF.
    // It means the padding area of top layer always be opaqued. To reduce the code change risk, modify it only for Android platform.
    // Need follow-up on formal solution.
#if ANDROID
    wAlpha = 0;
#else
    wAlpha = 255;
#endif

    // set destination width and height
    if (pRenderingData->pTarget[1] == nullptr)
    {
        dwDestRectWidth  = pRenderingData->pTarget[0]->dwWidth;
        dwDestRectHeight = pRenderingData->pTarget[0]->dwHeight;
    }
    else
    {
        // destination width and height base on non-rotated
        dwDestRectWidth  = pRenderingData->pTarget[1]->dwWidth;
        dwDestRectHeight = pRenderingData->pTarget[1]->dwHeight;
    }

    if (pSource->bXORComp)
    {
        // re-define the layer format, scaling mode.
        // for RGBP format, plane order is UVY, offset should be modified to match it.
        // only support cursor layer width == 4.
        if (pSource->dwWidth != 4)
        {
            VPHAL_RENDER_ASSERTMESSAGE("XOR layer invalid width size.");
            iResult = -1;
            goto finish;
        }

        pSource->Format = Format_RGBP;
        pSource->TileType = MOS_TILE_LINEAR;
        pSource->ScalingMode = VPHAL_SCALING_NEAREST;
        pSource->UPlaneOffset.iSurfaceOffset = 0;
        pSource->VPlaneOffset.iSurfaceOffset = pSource->dwWidth*pSource->dwHeight;
        pSource->dwPitch = pSource->dwPitch/(4*8);
    }

    // Source rectangle is pre-rotated, destination rectangle is post-rotated.
    if (pSource->Rotation == VPHAL_ROTATION_IDENTITY    ||
        pSource->Rotation == VPHAL_ROTATION_180         ||
        pSource->Rotation == VPHAL_MIRROR_HORIZONTAL    ||
        pSource->Rotation == VPHAL_MIRROR_VERTICAL)
    {
        fScaleX      = (float)(pSource->rcDst.right  - pSource->rcDst.left) /
                       (float)(pSource->rcSrc.right  - pSource->rcSrc.left);
        fScaleY      = (float)(pSource->rcDst.bottom - pSource->rcDst.top) /
                       (float)(pSource->rcSrc.bottom - pSource->rcSrc.top);
    }
    else
    {
        // VPHAL_ROTATION_90 || VPHAL_ROTATION_270 ||
        // VPHAL_ROTATE_90_MIRROR_HORIZONTAL || VPHAL_ROTATE_90_MIRROR_VERTICAL
        fScaleX      = (float)(pSource->rcDst.right  - pSource->rcDst.left) /
                       (float)(pSource->rcSrc.bottom  - pSource->rcSrc.top);
        fScaleY      = (float)(pSource->rcDst.bottom - pSource->rcDst.top) /
                       (float)(pSource->rcSrc.right - pSource->rcSrc.left);
    }
    fDiScaleY    = 1.0f;

    CalculateCropParams(iLayer, pRenderingData, &fCropX, &fCropY);

    pTargetRect = &pRenderingData->BbArgs.rcOutput;

    if (pRenderingData->pConstriction)
    {
        fScaleX /= pRenderingData->fConstrictionStepX;
        fScaleY /= pRenderingData->fConstrictionStepY;
    }

    //-------------------------------------------
    // Set layer ID - necessary to bind surface states
    //-------------------------------------------
    pSource->iLayerID = iLayer;

    pSource->bUseSampleUnorm = IsUsingSampleUnorm(pCompParams, pSource);
    // Check whether sampler lumakey is needed. It will be used in SetSurfaceParams
    // when IsNV12SamplerLumakeyNeeded being called.
    pSource->bUseSamplerLumakey = IsSamplerLumakeySupported(pSource);
    //-------------------------------------------
    // Setup surface states
    //-------------------------------------------
    SetSurfaceParams(pSource, &SurfaceParams);

    if (m_bChromaUpSampling || m_bChromaDownSampling)
    {
        if (!MEDIA_IS_WA(m_pWaTable, WaEnableDscale)                      ||
            (MEDIA_IS_WA(m_pWaTable, WaEnableDscale)                      &&
             pSource->ScalingMode == VPHAL_SCALING_BILINEAR  &&
             fScaleX >= (float)(1.0/3.0)                     &&
             fScaleY >= (float)(1.0/3.0)))
        {
            SurfaceParams.bChromasiting      = true;
            pSource->bChromaSiting           = true;
        }
        else
        {
            SurfaceParams.bChromasiting = false;
            pSource->bChromaSiting      = false;
        }
    }
    else
    {
            SurfaceParams.bChromasiting      = false;
            pSource->bChromaSiting           = false;
    }

    if (pSource->bInterlacedScaling)
    {
        // Top Input Field
        SurfaceParams.bVertStrideOffs   = false;
        SurfaceParams.bVertStride       = true;

        // Bottom Input Field
        SurfaceParams2 = SurfaceParams;
        SurfaceParams2.bVertStrideOffs  = true;
    }
    else if (pSource->bFieldWeaving)
    {
        // Top Input Field
        SurfaceParams.bVertStrideOffs   = false;
        SurfaceParams.bVertStride       = false;

        // Bottom Input Field
        SurfaceParams2 = SurfaceParams;
    }

    // Allocate palette ID for surface (do not load palette)
    if (IS_PAL_FORMAT(pSource->Format))
    {
        eStatus = pRenderHal->pfnAllocatePaletteID(pRenderHal, &pSource->iPalette);
        if (eStatus != MOS_STATUS_SUCCESS)
        {
            iResult = -1;
            goto finish;
        }
    }

    SurfaceParams.MemObjCtl = (pSource->SurfType == SURF_IN_PRIMARY) ?
                                m_SurfMemObjCtl.PrimaryInputSurfMemObjCtl :
                                m_SurfMemObjCtl.InputSurfMemObjCtl ;

    eStatus = VpHal_RndrCommonInitRenderHalSurface(pSource, pRenderHalSurfaceSrc);
    if (MOS_FAILED(eStatus))
    {
        iResult = -1;
        goto finish;
    }
    // Setup surface states
    eStatus = pRenderHal->pfnSetupSurfaceState(
            pRenderHal,
            pRenderHalSurfaceSrc,
            &SurfaceParams,
            &iSurfaceEntries,
            pSurfaceEntries,
            nullptr);
    if (MOS_FAILED(eStatus))
    {
        iResult = -1;
        goto finish;
    }

    if ((pDPStatic != nullptr) && (pSurfaceEntries[0] != nullptr))
    {
        pDPStatic->DW6.InputPictureWidth  = pSurfaceEntries[0]->dwWidth -1;
        pDPStatic->DW6.InputPictureHeight = pSurfaceEntries[0]->dwHeight -1;
    }

    eStatus = VpHal_RndrCommonGetBackVpSurfaceParams(
        pRenderHalSurfaceSrc,
        pSource);
    if (MOS_FAILED(eStatus))
    {
        iResult = -1;
        goto finish;
    }

    if (ScalingMode != pSource->ScalingMode)
    {
        // The AVS may be modified to Bilinear in RenderHal_SetupSurfaceState->RenderHal_GetSurfaceStateEntries if AVS
        // is not supported by the format of source.
        // Both bUseSampleUnorm and bUseSamplerLumakey need be updated.
        pSource->bUseSampleUnorm = IsUsingSampleUnorm(pCompParams, pSource);
        pSource->bUseSamplerLumakey = IsSamplerLumakeySupported(pSource);
    }

    //--------------------------------------------------------
    // iScaling & Field Weaving needs 2 sets of input surfaces
    //--------------------------------------------------------
    iSurfaceEntries2 = 0;
    if (pSource->bInterlacedScaling || pSource->bFieldWeaving)
    {
        SurfaceParams2.MemObjCtl = (pSource->SurfType == SURF_IN_PRIMARY) ?
                                    m_SurfMemObjCtl.PrimaryInputSurfMemObjCtl :
                                    m_SurfMemObjCtl.InputSurfMemObjCtl ;

        // For Interlaced scaling 2nd field is part of the same frame
        // For Field weaving 2nd field is passed in as a ref. surface
        pTempSurf = pSource->bFieldWeaving ? pSource->pBwdRef : pSource;
        eStatus = VpHal_RndrCommonInitRenderHalSurface(pTempSurf, pRenderHalSurfaceSrcField);
        if (MOS_FAILED(eStatus))
        {
            iResult = -1;
            goto finish;
        }
        eStatus = pRenderHal->pfnSetupSurfaceState(
            pRenderHal,
            pRenderHalSurfaceSrcField,
            &SurfaceParams2,
            &iSurfaceEntries2,
            pSurfaceEntries2,
            nullptr);
        if (MOS_FAILED(eStatus))
        {
            iResult = -1;
            goto finish;
        }
        eStatus = VpHal_RndrCommonGetBackVpSurfaceParams(
            pRenderHalSurfaceSrcField,
            pTempSurf);
        if (MOS_FAILED(eStatus))
        {
            iResult = -1;
            goto finish;
        }
    }

    if (iSurfaceEntries <= 0         ||
        (pSource->bInterlacedScaling &&
         pSource->bFieldWeaving      &&
         iSurfaceEntries2            != iSurfaceEntries))
    {
        VPHAL_RENDER_ASSERTMESSAGE("Failed to setup surface state.");
        iResult = -1;
        goto finish;
    }

    //-------------------------------------------
    // Bind surface states
    //-------------------------------------------
    eStatus = GetBindingIndex(pSource, &iBTentry);
    if (MOS_FAILED(eStatus))
    {
        goto finish;
    }

    for (i = 0; i < iSurfaceEntries; i++, iBTentry++)
    {
        eStatus = pRenderHal->pfnBindSurfaceState(pRenderHal,
                                        pRenderingData->iBindingTable,
                                        iBTentry,
                                        pSurfaceEntries[i]);
        if (MOS_FAILED(eStatus))
        {
            iResult = -1;
            goto finish;
        }

        // Interlaced scaling & Field Weaving case
        if (pSource->bInterlacedScaling || pSource->bFieldWeaving)
        {
            eStatus = pRenderHal->pfnBindSurfaceState(
                pRenderHal,
                pRenderingData->iBindingTable,
                VPHAL_COMP_BTINDEX_L0_FIELD1_DUAL + i,
                pSurfaceEntries2[i]);

            if (MOS_FAILED(eStatus))
            {
                iResult = -1;
                goto finish;
            }
        }
    }

    //-----------------------------------
    // Setup Luma keying parameters
    //-----------------------------------
    if (pSource->pLumaKeyParams != nullptr)
    {
        VPHAL_RENDER_NORMALMESSAGE("LumaLow %d, LumaHigh %d",
            pSource->pLumaKeyParams->LumaLow,
            pSource->pLumaKeyParams->LumaHigh);

        pStatic->DW14.LumakeyLowThreshold  = pSource->pLumaKeyParams->LumaLow;
        pStatic->DW14.LumakeyHighThreshold = pSource->pLumaKeyParams->LumaHigh;
    }

    //-----------------------------------
    // Setup Samplers
    //-----------------------------------
    for (i = 0; i < iSurfaceEntries; i++, iBTentry++)
    {
        if (pSurfaceEntries[i] == nullptr)
        {
            continue;
        }

        // Obtain Sampler ID and Type
        eStatus = GetSamplerIndex(pSource,
                                  pSurfaceEntries[i],
                                  &iSamplerID,
                                  &SamplerType);

        // Point to the current SamplerStateParam
        pSamplerStateParams = &pRenderingData->SamplerStateParams[iSamplerID];

        // No need to setup a sampler
        if (MOS_FAILED(eStatus))
        {
            continue;
        }

        pSamplerStateParams->SamplerType = SamplerType;

        if (SamplerType == MHW_SAMPLER_TYPE_3D)
        {
            fOffsetX = m_fSamplerLinearBiasX;
            fOffsetY = m_fSamplerLinearBiasY;

            // Use 3D Nearest Mode only for 1x Scaling in both directions and only if the input is Progressive or interlaced scaling is used
            // In case of two or more layers, set Sampler State to Bilinear if any layer requires Bilinear
            // When primary surface needs chroma upsampling,
            // force to use 3D Bilinear Mode for 1x scaling for better quality
            if (fScaleX == 1.0F &&
                fScaleY == 1.0F &&
                !m_bChromaUpSampling &&
                !m_bChromaDownSampling &&
                (pSource->SampleType == SAMPLE_PROGRESSIVE || pSource->bInterlacedScaling || pSource->bFieldWeaving) &&
                (!pSamplerStateParams->bInUse ||
                (pSamplerStateParams->bInUse && pSamplerStateParams->Unorm.SamplerFilterMode == MHW_SAMPLER_FILTER_NEAREST)))
            {
                fShiftX  = 0.0f;
                fShiftY  = 0.0f;
                eStatus  = SetSamplerFilterMode(pSamplerStateParams,
                                                pSurfaceEntries[i],
                                                pRenderingData,
                                                pCompParams->uSourceCount,
                                                MHW_SAMPLER_FILTER_NEAREST,
                                                &iSamplerID,
                                                pSource);
                if (MOS_FAILED(eStatus))
                {
                    continue;
                }
            }
            else
            {
                //For Y210/Y216 with AVS(Y)+3D(U/V) sampler, the shift is not needed.
                if ((pSource->Format == Format_Y210 ||
                    pSource->Format == Format_Y216)
                    && pSurfaceEntries[0]->bAVS)
                {
                    fShiftX = 0.0f;
                    fShiftY = 0.0f;
                }
                else
                {
                    fShiftX = VPHAL_HW_LINEAR_SHIFT;  // Bilinear scaling shift
                    fShiftY = VPHAL_HW_LINEAR_SHIFT;
                }

                eStatus     = SetSamplerFilterMode(pSamplerStateParams,
                                                   pSurfaceEntries[i],
                                                   pRenderingData,
                                                   pCompParams->uSourceCount,
                                                   MHW_SAMPLER_FILTER_BILINEAR,
                                                   &iSamplerID,
                                                   pSource);
                if (MOS_FAILED(eStatus))
                {
                    continue;
                }
            }

            if (MHW_SAMPLER_FILTER_BILINEAR == pSamplerStateParams->Unorm.SamplerFilterMode &&
                VPHAL_SCALING_BILINEAR != pSource->ScalingMode ||
                MHW_SAMPLER_FILTER_NEAREST == pSamplerStateParams->Unorm.SamplerFilterMode &&
                VPHAL_SCALING_NEAREST != pSource->ScalingMode)
            {
                VPHAL_RENDER_NORMALMESSAGE("Legacy Check: scaling mode and samplerFilterMode are not aligned.");
            }

            if (i != 0 && (oriShiftX != fShiftX || oriShiftY != fShiftY))
            {
                VPHAL_RENDER_NORMALMESSAGE("Legacy Check: fShiftX/fShiftY of entry %d is not same as previous entry.", i);
            }

            pSamplerStateParams->Unorm.AddressU = MHW_GFX3DSTATE_TEXCOORDMODE_CLAMP;
            pSamplerStateParams->Unorm.AddressV = MHW_GFX3DSTATE_TEXCOORDMODE_CLAMP;
            pSamplerStateParams->Unorm.AddressW = MHW_GFX3DSTATE_TEXCOORDMODE_CLAMP;

            if (IsSamplerIDForY(iSamplerID) && pSource->bUseSamplerLumakey)
            {
                //From Gen10,HW support 1 plane LumaKey process on NV12 format, Gen9 only support 2 plane LumaKey process
                //if go to 1 plane, MHW_GFX3DSTATE_SURFACEFORMAT_PLANAR_420_8 format will be used, LumaKey value need to be set on Y channel, the corresponding bit range is 15:8
                //if go to 2 plane, MHW_GFX3DSTATE_SURFACEFORMAT_R8_UNORM     format will be used, LumaKey value need to be set on R channel, the corresponding bit range is 23:16
                if (IsNV12SamplerLumakeyNeeded(pSource, pRenderHal) || (pSurfaceEntries[i]->dwFormat == MHW_GFX3DSTATE_SURFACEFORMAT_R8_UNORM))
                {
                    dwLow  = pSource->pLumaKeyParams->LumaLow << 16;
                    dwHigh = (pSource->pLumaKeyParams->LumaHigh << 16) | 0xFF00FFFF;
                    bForceNearestForUV = true;
                }
                else
                {
                    dwLow  = pSource->pLumaKeyParams->LumaLow << 8;
                    dwHigh = (pSource->pLumaKeyParams->LumaHigh << 8) | 0xFFFF00FF;
                }

                pSamplerStateParams->Unorm.bChromaKeyEnable = true;
                pSamplerStateParams->Unorm.ChromaKeyMode    = MHW_CHROMAKEY_MODE_KILL_ON_ANY_MATCH;
                pSamplerStateParams->Unorm.ChromaKeyIndex   = pRenderHal->pfnAllocateChromaKey(pRenderHal, dwLow, dwHigh);
            }

            if ((!IsSamplerIDForY(iSamplerID)) && bForceNearestForUV)
            {
                pSamplerStateParams->Unorm.SamplerFilterMode = MHW_SAMPLER_FILTER_NEAREST;
            }

            VPHAL_RENDER_NORMALMESSAGE("Scaling Info: layer %d, layerOrigin %d, entry %d, format %d, scalingMode %d, samplerType %d, samplerFilterMode %d, samplerIndex %d, yuvPlane %d",
                iLayer, iLayer, i, pSource->Format, pSource->ScalingMode, SamplerType, pSamplerStateParams->Unorm.SamplerFilterMode, iSamplerID, pSurfaceEntries[i]->YUVPlane);
        }
        else if (SamplerType == MHW_SAMPLER_TYPE_AVS)
        {
            // Disable sampler bias
            fOffsetX = 0.0f;
            fOffsetY = 0.0f;

            // Disable linear shift
            fShiftX = 0.0f;
            fShiftY = 0.0f;

            pSamplerStateParams->Avs.b8TapAdaptiveEnable = Is8TapAdaptiveEnabled(pSource, fScaleX, fScaleY);

            // Set HDC Direct Write Flag
            pSamplerStateParams->Avs.bHdcDwEnable = pRenderingData->bHdcDwEnable;

            VPHAL_RENDER_NORMALMESSAGE("Scaling Info: layer %d, entry %d, format %d, scalingMode %d, samplerType %d",
                iLayer, i, pSource->Format, pSource->ScalingMode, SamplerType);
        }
        else
        {
            VPHAL_RENDER_NORMALMESSAGE("Scaling Info: layer %d, entry %d, format %d, scalingMode %d, samplerType %d",
                iLayer, i, pSource->Format, pSource->ScalingMode, SamplerType);
        }

        oriShiftX = fShiftX;
        oriShiftY = fShiftY;

        pSamplerStateParams->bInUse        = true;

        // Set AVS Scaling Table
        if (pSurfaceEntries[i] && pSurfaceEntries[i]->bAVS)
        {
            VPHAL_RENDER_ASSERT(SamplerType == MHW_SAMPLER_TYPE_AVS);

            eStatus = SetSamplerAvsParams(
                pRenderingData,
                pSource,
                pSurfaceEntries[i],
                pSamplerStateParams,
                fScaleX,
                fScaleY);

            if (MOS_FAILED(eStatus))
            {
                iResult = -1;
                goto finish;
            }
        }
    }

    //-----------------------------------
    // Alpha blending optimization.
    // If Constant blending and one of the following is true, disable blending.
    // If Src+Constant blending and one of the following is true, fall back to Src blending.
    // Condition; alpha <= 0. Layer is 100% transparent.
    // Condition; alpha >= 1. Layer is 100% opaque.
    //-----------------------------------
    if (pSource->pBlendingParams &&
        ((pSource->pBlendingParams->BlendType == BLEND_CONSTANT) ||
         (pSource->pBlendingParams->BlendType == BLEND_CONSTANT_SOURCE) ||
         (pSource->pBlendingParams->BlendType == BLEND_CONSTANT_PARTIAL)))
    {
        float fAlpha = pSource->pBlendingParams->fAlpha;

        VPHAL_RENDER_NORMALMESSAGE("BlendType %d, fAlpha %d",
            pSource->pBlendingParams->BlendType,
            pSource->pBlendingParams->fAlpha);

        // Don't render layer with alpha <= 0.0f
        if (fAlpha <= 0.0f)
        {
            // layer is not visible - disable layer
            pSource->iLayerID = -1;
            goto finish;
        }
        else
        {
            wAlpha  = (uint16_t) (255.0f * fAlpha);
        }

        if (fAlpha >= 1.0f || wAlpha >= 255)
        {
            if (pSource->pBlendingParams->BlendType == BLEND_CONSTANT)
            {
                pSource->pBlendingParams->BlendType = BLEND_NONE;
            }
            else // for BlendType == BLEND_CONSTANT_SOURCE
            {
                pSource->pBlendingParams->BlendType = BLEND_SOURCE;
            }

            pSource->pBlendingParams->fAlpha    = 1.0f;
            wAlpha = 255;
        }
    }

    //-----------------------------------
    // Geometry adjustments for BOB DI
    //-----------------------------------
    // Use width and height that were used to setup surface state for plane 0
    pSurfaceEntry = pSurfaceEntries[0];
    dwSurfStateHt = pSurfaceEntry->dwHeight;
    dwSurfStateWd = pSurfaceEntry->dwWidth;

    // if 1:1 scaling and interlaced scaling or field weaving
    // do not adjust offsets since it uses Nearest sampling
    if (fScaleX == 1.0F &&
        fScaleY == 1.0F &&
        (pSource->bInterlacedScaling || pSource->bFieldWeaving))
    {
        fDiScaleY = 0.5f;
    }
    else
    {
        switch (pSource->SampleType)
        {
            case SAMPLE_INTERLEAVED_EVEN_FIRST_TOP_FIELD:
            case SAMPLE_INTERLEAVED_ODD_FIRST_TOP_FIELD:
                fDiScaleY = 0.5f;
                // don't break
            case SAMPLE_SINGLE_TOP_FIELD:
                fOffsetY += 0.25f;
                break;

            case SAMPLE_INTERLEAVED_EVEN_FIRST_BOTTOM_FIELD:
            case SAMPLE_INTERLEAVED_ODD_FIRST_BOTTOM_FIELD:
                fDiScaleY = 0.5f;
                // don't break
            case SAMPLE_SINGLE_BOTTOM_FIELD:
                fOffsetY -= 0.25f;
                break;

            case SAMPLE_PROGRESSIVE:
            default:
                fDiScaleY = 1.0f;
                break;
        }
    }

    // Normalize source co-ordinates using the width and height programmed
    // in surface state. step X, Y pre-rotated
    // Source rectangle is pre-rotated, destination rectangle is post-rotated.
    if (pSource->Rotation == VPHAL_ROTATION_IDENTITY    ||
        pSource->Rotation == VPHAL_ROTATION_180         ||
        pSource->Rotation == VPHAL_MIRROR_HORIZONTAL    ||
        pSource->Rotation == VPHAL_MIRROR_VERTICAL)
    {
        fStepX = ((pSource->rcSrc.right - pSource->rcSrc.left - fCropX) * 1.0f) /
                  ((pSource->rcDst.right - pSource->rcDst.left) > 0 ?
                   (pSource->rcDst.right - pSource->rcDst.left) : 1);
        fStepY = ((pSource->rcSrc.bottom - pSource->rcSrc.top - fCropY) * fDiScaleY) /
                  ((pSource->rcDst.bottom - pSource->rcDst.top) > 0 ?
                   (pSource->rcDst.bottom - pSource->rcDst.top) : 1);
    }
    else
    {
        // VPHAL_ROTATION_90 || VPHAL_ROTATION_270 ||
        // VPHAL_ROTATE_90_MIRROR_HORIZONTAL || VPHAL_ROTATE_90_MIRROR_VERTICAL
        fStepX = ((pSource->rcSrc.right - pSource->rcSrc.left - fCropX) * 1.0f) /
                  ((pSource->rcDst.bottom - pSource->rcDst.top) > 0 ?
                   (pSource->rcDst.bottom - pSource->rcDst.top) : 1);
        fStepY = ((pSource->rcSrc.bottom - pSource->rcSrc.top - fCropY) * fDiScaleY) /
                  ((pSource->rcDst.right - pSource->rcDst.left) > 0 ?
                   (pSource->rcDst.right - pSource->rcDst.left) : 1);
    }

    // Source sampling coordinates based on rcSrc
    fOffsetX += (pSource->rcSrc.left + fCropX / 2);
    fOffsetY += (pSource->rcSrc.top + fCropY / 2) * fDiScaleY;

    DestRect = pSource->rcDst;
    if (pRenderingData->pTarget[1] != nullptr)
    {
        // Calculate non-rotated rectangle based on rotated rcDst in source surface
        switch (pSource->Rotation)
        {
            case VPHAL_ROTATION_90:
                DestRect.left     = pSource->rcDst.top;
                DestRect.top      = dwDestRectHeight - pSource->rcDst.right;
                DestRect.right    = pSource->rcDst.bottom;
                DestRect.bottom   = dwDestRectHeight - pSource->rcDst.left;
                break;
            case VPHAL_ROTATION_180:
                DestRect.left     = dwDestRectWidth - pSource->rcDst.right;
                DestRect.top      = dwDestRectHeight - pSource->rcDst.bottom;
                DestRect.right    = dwDestRectWidth - pSource->rcDst.left;
                DestRect.bottom   = dwDestRectHeight - pSource->rcDst.top;
                break;
            case VPHAL_ROTATION_270:
                DestRect.left     = dwDestRectWidth - pSource->rcDst.bottom;
                DestRect.top      = pSource->rcDst.left;
                DestRect.right    = dwDestRectWidth - pSource->rcDst.top;
                DestRect.bottom   = pSource->rcDst.right;
                break;
            case VPHAL_MIRROR_HORIZONTAL:
                DestRect.left     = dwDestRectWidth - pSource->rcDst.right;
                DestRect.top      = pSource->rcDst.top;
                DestRect.right    = dwDestRectWidth - pSource->rcDst.left;
                DestRect.bottom   = pSource->rcDst.bottom;
                break;
            case VPHAL_MIRROR_VERTICAL:
                DestRect.left     = pSource->rcDst.left;
                DestRect.top      = dwDestRectHeight - pSource->rcDst.bottom;
                DestRect.right    = pSource->rcDst.right;
                DestRect.bottom   = dwDestRectHeight - pSource->rcDst.top;
                break;
            case VPHAL_ROTATE_90_MIRROR_HORIZONTAL:
                DestRect.left     = pSource->rcDst.top;
                DestRect.top      = pSource->rcDst.left;
                DestRect.right    = pSource->rcDst.bottom;
                DestRect.bottom   = pSource->rcDst.right;
                break;
            case VPHAL_ROTATE_90_MIRROR_VERTICAL:
                DestRect.left     = dwDestRectWidth - pSource->rcDst.bottom;
                DestRect.top      = dwDestRectHeight - pSource->rcDst.right;
                DestRect.right    = dwDestRectWidth - pSource->rcDst.top;
                DestRect.bottom   = dwDestRectHeight - pSource->rcDst.left;
                break;
            case VPHAL_ROTATION_IDENTITY:
            default:
                break;
        } // switch

        fShiftX  -= DestRect.left - pRenderingData->ConstrictionOriginX;
        fShiftY  -= DestRect.top  - pRenderingData->ConstrictionOriginY;
    }
    else
    {
        switch (pSource->Rotation)
        {
            case VPHAL_ROTATION_IDENTITY:
                // Coordinate adjustment for render target coordinates (0,0)
                fShiftX  -= pSource->rcDst.left - pRenderingData->ConstrictionOriginX;
                fShiftY  -= pSource->rcDst.top  - pRenderingData->ConstrictionOriginY;
                break;
            case VPHAL_ROTATION_90:
                // Coordinate adjustment for 90 degree rotation
                fShiftX  -= (float)pSource->rcDst.top  - (float)pRenderingData->ConstrictionOriginY;
                fShiftY  -= (float)dwDestRectWidth -
                            (float)(pSource->rcSrc.bottom - pSource->rcSrc.top) * fScaleX -
                            (float)pSource->rcDst.left - (float)pRenderingData->ConstrictionOriginX;
                break;
            case VPHAL_ROTATION_180:
                // Coordinate adjustment for 180 degree rotation
                fShiftX  -= (float)dwDestRectWidth -
                            (float)(pSource->rcSrc.right - pSource->rcSrc.left) * fScaleX -
                            (float)pSource->rcDst.left - (float)pRenderingData->ConstrictionOriginX;
                fShiftY  -= (float)dwDestRectHeight -
                            (float)(pSource->rcSrc.bottom - pSource->rcSrc.top) * fScaleY -
                            (float)pSource->rcDst.top  - (float)pRenderingData->ConstrictionOriginY;
                break;
            case VPHAL_ROTATION_270:
                // Coordinate adjustment for 270 degree rotation
                fShiftX  -= (float)dwDestRectHeight -
                            (float)(pSource->rcSrc.right - pSource->rcSrc.left) * fScaleY -
                            (float)pSource->rcDst.top - (float)pRenderingData->ConstrictionOriginY;
                fShiftY  -= (float)pSource->rcDst.left  - (float)pRenderingData->ConstrictionOriginX;
                break;
            case VPHAL_MIRROR_HORIZONTAL:
                // Coordinate adjustment for horizontal mirroring
                fShiftX  -= (float)dwDestRectWidth -
                            (float)(pSource->rcSrc.right - pSource->rcSrc.left) * fScaleX -
                            (float)pSource->rcDst.left - (float)pRenderingData->ConstrictionOriginX;
                fShiftY  -= pSource->rcDst.top  - pRenderingData->ConstrictionOriginY;
                break;
            case VPHAL_MIRROR_VERTICAL:
                // Coordinate adjustment for vertical mirroring
                fShiftX  -= pSource->rcDst.left - pRenderingData->ConstrictionOriginX;
                fShiftY  -= (float)dwDestRectHeight -
                            (float)(pSource->rcSrc.bottom - pSource->rcSrc.top) * fScaleY -
                            (float)pSource->rcDst.top  - (float)pRenderingData->ConstrictionOriginY;
                break;
            case VPHAL_ROTATE_90_MIRROR_HORIZONTAL:
                // Coordinate adjustment for rotating 90 and horizontal mirroring
                fShiftX  -= (float)pSource->rcDst.top  - (float)pRenderingData->ConstrictionOriginY;
                fShiftY  -= (float)pSource->rcDst.left  - (float)pRenderingData->ConstrictionOriginX;
                break;
            case VPHAL_ROTATE_90_MIRROR_VERTICAL:
            default:
                // Coordinate adjustment for rotating 90 and vertical mirroring
                fShiftX  -= (float)dwDestRectHeight -
                            (float)(pSource->rcSrc.right - pSource->rcSrc.left) * fScaleY -
                            (float)pSource->rcDst.top - (float)pRenderingData->ConstrictionOriginY;
                fShiftY  -= (float)dwDestRectWidth -
                            (float)(pSource->rcSrc.bottom - pSource->rcSrc.top) * fScaleX -
                            (float)pSource->rcDst.left - (float)pRenderingData->ConstrictionOriginX;
                break;
        } // switch
    }

    // Frame origins for the current layer
    fOriginX = (fOffsetX + fShiftX * fStepX) / dwSurfStateWd;
    fOriginY = (fOffsetY + fShiftY * fStepY) / dwSurfStateHt;

    // Adjust step
    if (pRenderingData->pConstriction)
    {
        fStepX *= pRenderingData->fConstrictionStepX;
        fStepY *= pRenderingData->fConstrictionStepY;
    }

    // Normalized block step for the current layer (block increment)
    fStepX /= dwSurfStateWd;
    fStepY /= dwSurfStateHt;

    // Clip source rectangle
    DestRect.left   = MOS_MIN(MOS_MAX(pTargetRect->left, DestRect.left  ),
                            pTargetRect->right);
    DestRect.right  = MOS_MIN(MOS_MAX(pTargetRect->left, DestRect.right ),
                            pTargetRect->right);
    DestRect.top    = MOS_MIN(MOS_MAX(pTargetRect->top , DestRect.top   ),
                            pTargetRect->bottom);
    DestRect.bottom = MOS_MIN(MOS_MAX(pTargetRect->top , DestRect.bottom),
                            pTargetRect->bottom);

    if (pRenderingData->pConstriction)
    {
        DestRect.left =
                (int)((DestRect.left   - pRenderingData->ConstrictionOriginX) /
                                         pRenderingData->fConstrictionStepX);
        DestRect.right =
                (int)((DestRect.right  - pRenderingData->ConstrictionOriginX) /
                                         pRenderingData->fConstrictionStepX);
        DestRect.top =
                (int)((DestRect.top    - pRenderingData->ConstrictionOriginY) /
                                         pRenderingData->fConstrictionStepY);
        DestRect.bottom =
                (int)((DestRect.bottom - pRenderingData->ConstrictionOriginY) /
                                         pRenderingData->fConstrictionStepY);
    }

    // Layer is outside the render target area
    if (DestRect.left == DestRect.right ||
        DestRect.top  == DestRect.bottom)
    {
        // layer is not visible - disable layer
        pSource->iLayerID = -1;
        goto finish;
    }

    // Set CURBE and INLINE data
    pStatic->DW08.DestinationRectangleWidth  = dwDestRectWidth;
    pStatic->DW08.DestinationRectangleHeight = dwDestRectHeight;

    pDPStatic->DW7.DestinationRectangleWidth = dwDestRectWidth;
    pDPStatic->DW7.DestinationRectangleHeight = dwDestRectHeight;

    if (pSource->bXORComp)
    {
        // set mono-chroma XOR composite specific curbe data. re-calculate fStep due to 1 bit = 1 pixel.
        pStatic->DW10.ObjKa2Gen9.MonoXORCompositeMask = pSource->rcDst.left & 0x7;
        fStepX /= 8;
        fOriginX /= 8;
    }

    VPHAL_RENDER_NORMALMESSAGE("Scaling Info: layer %d, width %d, height, %d, rotation %d, alpha %d, shiftX %f, shiftY %f, scaleX %f, scaleY %f, offsetX %f, offsetY %f, stepX %f, stepY %f, originX %f, originY %f",
        iLayer, dwSurfStateWd, dwSurfStateHt, pSource->Rotation, wAlpha, fShiftX, fShiftY, fScaleX, fScaleY, fOffsetX, fOffsetY, fStepX, fStepY, fOriginX, fOriginY);

    VP_RENDER_NORMALMESSAGE("Scaling Info: layer %d, chromaSitingEnabled %d, isChromaUpSamplingNeeded %d, isChromaDownSamplingNeeded %d",
        iLayer, pSource->bChromaSiting, m_bChromaUpSampling, m_bChromaDownSampling);

    switch (iLayer)
    {
        case 0:
            // Gen9+ uses HW based Rotation
            if (m_bSamplerSupportRotation)
            {
                pStatic->DW10.ObjKa2Gen9.RotationAngleofLayer0 = pSource->Rotation;
            }
            else
            {
                pStatic->DW09.RotationMirrorMode    = pSource->Rotation;
            }
            pStatic->DW13.ColorFill_A                       = wAlpha;
            pStatic->DW16.HorizontalScalingStepRatioLayer0  = fStepX;
            pStatic->DW24.VerticalScalingStepRatioLayer0    = fStepY;
            pStatic->DW40.HorizontalFrameOriginLayer0       = fOriginX;
            pStatic->DW32.VerticalFrameOriginLayer0         = fOriginY;
            pInline->DW04.VideoXScalingStep                 = fStepX;

            pDPStatic->DW9.HorizontalScalingStepRatioLayer0 = fStepX;
            pDPStatic->DW10.VerticalScalingStepRatioLayer0 = fStepY;
            pDPStatic->DW11.HorizontalFrameOriginLayer0 = fOriginX;
            pDPStatic->DW12.VerticalFrameOriginLayer0 = fOriginY;

            // ChromasitingUOffset and ChromasitingVOffset are only for 3D Sampler use case
            if (m_need3DSampler)
            {
                fHorizgap = 0;
                fVertgap = 0;
                GetOffsetChromasiting(pSource,
                                      &fHorizgap,
                                      &fVertgap);
                if (IS_PL2_FORMAT(pSource->Format))
                {

                    pStatic->DW11.ChromasitingUOffset = (float)((0.5f / (pSource->dwWidth)) - fHorizgap);
                    pStatic->DW12.ChromasitingVOffset = (float)((1.0f / (pSource->dwHeight)) - fVertgap);
                }
                else if (pSource->Format == Format_YUY2)
                {
                    pStatic->DW11.ChromasitingUOffset = (float)((1.0f / (pSource->dwWidth)) - fHorizgap);
                    pStatic->DW12.ChromasitingVOffset = (float)((0.5f / (pSource->dwHeight)) - fVertgap);
                }

                VPHAL_RENDER_NORMALMESSAGE("Scaling Info: layer 0, ChromasitingUOffset %f, ChromasitingVOffset %f",
                    pStatic->DW11.ChromasitingUOffset, pStatic->DW12.ChromasitingVOffset);
            }
            break;
        case 1:
            // if L0 and L1 have the same rotation, set for all layers.
            // L1 onwards must have the same rotation in a single rendering phase.
            // pStatic->DW09.RotationMirrorAllLayer is initialized to 0 by default
            // through RenderData init outside this function.
            if (!m_bSamplerSupportRotation)
            {
                if (pRenderingData->pLayers[0]->Rotation == pSource->Rotation)
                {
                    pStatic->DW09.RotationMirrorAllLayer    = 1;
                }
            }
            else // Gen9+ uses HW based Rotation
            {
                pStatic->DW10.ObjKa2Gen9.RotationAngleofLayer1 = pSource->Rotation;
            }
            pStatic->DW06.ConstantBlendingAlphaLayer1       = wAlpha;
            pStatic->DW17.HorizontalScalingStepRatioLayer1  = fStepX;
            pStatic->DW25.VerticalScalingStepRatioLayer1    = fStepY;
            pStatic->DW41.HorizontalFrameOriginLayer1       = fOriginX;
            pStatic->DW33.VerticalFrameOriginLayer1         = fOriginY;
            break;
        case 2:
            // Gen9+ uses HW based Rotation
            if (m_bSamplerSupportRotation)
            {
                pStatic->DW10.ObjKa2Gen9.RotationAngleofLayer2 = pSource->Rotation;
            }
            pStatic->DW06.ConstantBlendingAlphaLayer2       = wAlpha;
            pStatic->DW18.HorizontalScalingStepRatioLayer2  = fStepX;
            pStatic->DW26.VerticalScalingStepRatioLayer2    = fStepY;
            pStatic->DW42.HorizontalFrameOriginLayer2       = fOriginX;
            pStatic->DW34.VerticalFrameOriginLayer2         = fOriginY;
            break;
        case 3:
            // Gen9+ uses HW based Rotation
            if (m_bSamplerSupportRotation)
            {
                pStatic->DW10.ObjKa2Gen9.RotationAngleofLayer3 = pSource->Rotation;
            }
            pStatic->DW06.ConstantBlendingAlphaLayer3       = wAlpha;
            pStatic->DW19.HorizontalScalingStepRatioLayer3  = fStepX;
            pStatic->DW27.VerticalScalingStepRatioLayer3    = fStepY;
            pStatic->DW43.HorizontalFrameOriginLayer3       = fOriginX;
            pStatic->DW35.VerticalFrameOriginLayer3         = fOriginY;
            break;
        case 4:
            // Gen9+ uses HW based Rotation
            if (m_bSamplerSupportRotation)
            {
                pStatic->DW10.ObjKa2Gen9.RotationAngleofLayer4 = pSource->Rotation;
            }
            pStatic->DW06.ConstantBlendingAlphaLayer4       = wAlpha;
            pStatic->DW20.HorizontalScalingStepRatioLayer4  = fStepX;
            pStatic->DW28.VerticalScalingStepRatioLayer4    = fStepY;
            pStatic->DW44.HorizontalFrameOriginLayer4       = fOriginX;
            pStatic->DW36.VerticalFrameOriginLayer4         = fOriginY;
            break;
        case 5:
            // Gen9+ uses HW based Rotation
            if (m_bSamplerSupportRotation)
            {
                pStatic->DW10.ObjKa2Gen9.RotationAngleofLayer5 = pSource->Rotation;
            }
            pStatic->DW07.ConstantBlendingAlphaLayer5       = wAlpha;
            pStatic->DW21.HorizontalScalingStepRatioLayer5  = fStepX;
            pStatic->DW29.VerticalScalingStepRatioLayer5    = fStepY;
            pStatic->DW45.HorizontalFrameOriginLayer5       = fOriginX;
            pStatic->DW37.VerticalFrameOriginLayer5         = fOriginY;
            break;
        case 6:
            // Gen9+ uses HW based Rotation
            if (m_bSamplerSupportRotation)
            {
                pStatic->DW10.ObjKa2Gen9.RotationAngleofLayer6 = pSource->Rotation;
            }
            pStatic->DW07.ConstantBlendingAlphaLayer6       = wAlpha;
            pStatic->DW22.HorizontalScalingStepRatioLayer6  = fStepX;
            pStatic->DW30.VerticalScalingStepRatioLayer6    = fStepY;
            pStatic->DW46.HorizontalFrameOriginLayer6       = fOriginX;
            pStatic->DW38.VerticalFrameOriginLayer6         = fOriginY;
            break;
        case 7:
            // Gen9+ uses HW based Rotation
            if (m_bSamplerSupportRotation)
            {
                pStatic->DW10.ObjKa2Gen9.RotationAngleofLayer7 = pSource->Rotation;
            }
            pStatic->DW07.ConstantBlendingAlphaLayer7       = wAlpha;
            pStatic->DW23.HorizontalScalingStepRatioLayer7  = fStepX;
            pStatic->DW31.VerticalScalingStepRatioLayer7    = fStepY;
            pStatic->DW47.HorizontalFrameOriginLayer7       = fOriginX;
            pStatic->DW39.VerticalFrameOriginLayer7         = fOriginY;
            break;
        default:
            VPHAL_RENDER_ASSERTMESSAGE("Invalid layer.");
            iResult = -1;
            goto finish;
    }

    Set3DSamplerStatus(pSource, (uint8_t)iLayer, pStatic);

    // Save rendering parameters, increment number of layers
    pRenderingData->pLayers[iLayer] = pSource;
    pRenderingData->iLayers++;

    pRenderingData->BbArgs.rcDst[iLayer] = DestRect;
    pRenderingData->BbArgs.Rotation[iLayer] = pSource->Rotation;
    pRenderingData->BbArgs.iLayers++;

    VPHAL_RENDER_NORMALMESSAGE("Layer %d, SamplerType:%d, Scaling Model %d,  SamplerIndex %d",
                               iLayer, SamplerType, pSource->ScalingMode, iSamplerID);
    iResult = 1;

finish:
    return iResult;
}

//!
//! \brief    Set Composite Render Target Layer
//! \details  Set Composite Render Target Layer, setup surface state and binding table
//! \param    [in] pRenderingData
//!           Pointer to Composite Rendering data
//! \param    [in] pCompParams
//!           Pointer to Composite parameters
//! \return   int32_t
//!           Return number of Surface State entries if successful, otherwise -1
//!
int32_t CompositeState::SetLayerRT(
    PVPHAL_RENDERING_DATA_COMPOSITE pRenderingData,
    PVPHAL_COMPOSITE_PARAMS         pCompParams)
{
    MOS_STATUS                          eStatus;
    PRENDERHAL_INTERFACE                pRenderHal;
    PRENDERHAL_SURFACE                  pRenderHalSurface;
    RENDERHAL_SURFACE_STATE_PARAMS      SurfaceParams;
    PRENDERHAL_SURFACE_STATE_ENTRY      pSurfaceEntries[MHW_MAX_SURFACE_PLANES];
    int32_t                             iSurfaceEntries, i;
    int32_t                             iBTentry = 0;
    uint32_t                            uTargetIndex;
    RENDERHAL_OFFSET_OVERRIDE           PlaneOffsetOverride;
    PRENDERHAL_OFFSET_OVERRIDE          pPlaneOffsetOverride;

    iSurfaceEntries = -1;

    VPHAL_RENDER_CHK_NULL(m_pRenderHal);
    VPHAL_RENDER_CHK_NULL(pRenderingData);
    VPHAL_RENDER_CHK_NULL(pCompParams);
    VPHAL_RENDER_ASSERT(pRenderingData->pTarget[0]->SurfType == SURF_OUT_RENDERTARGET);

    pRenderHal   = m_pRenderHal;

    // init surface parameters
    MOS_ZeroMemory(&SurfaceParams, sizeof(SurfaceParams));

    SurfaceParams.MemObjCtl = m_SurfMemObjCtl.TargetSurfMemObjCtl;

    // Used for 32x32 Media walker kernel + Color fill kernel
    if (m_bFtrMediaWalker)
    {
        if (pRenderingData->pColorFill != nullptr &&
            pRenderingData->iLayers == 0 &&
            pRenderHal->pHwSizes->dwSizeMediaWalkerBlock == 32)
        {
            SurfaceParams.b32MWColorFillKern = true;
        }
    }

    uTargetIndex = 0;
    do
    {
        SetSurfaceCompressionParams(pRenderingData->pTarget[uTargetIndex], true);
        // Get surface state allocation parameters for RT (scaling mode, stride)
        SetSurfaceParams(
            pRenderingData->pTarget[uTargetIndex],
            &SurfaceParams);
        pRenderHalSurface = &pCompParams->RenderHalSurfaceTarget[uTargetIndex];
        VPHAL_RENDER_CHK_STATUS(VpHal_RndrCommonInitRenderHalSurface(pRenderingData->pTarget[uTargetIndex],
                                                                 pRenderHalSurface));
        pPlaneOffsetOverride = GetPlaneOffsetOverrideParam(
            pRenderHalSurface,
            &SurfaceParams,
            &PlaneOffsetOverride);

        // Setup surface state
        VPHAL_RENDER_CHK_STATUS(pRenderHal->pfnSetupSurfaceState(
                                               pRenderHal,
                                               pRenderHalSurface,
                                               &SurfaceParams,
                                               &iSurfaceEntries,
                                               pSurfaceEntries,
                                               pPlaneOffsetOverride));
        VPHAL_RENDER_CHK_STATUS(VpHal_RndrCommonGetBackVpSurfaceParams(
            pRenderHalSurface,
            pRenderingData->pTarget[uTargetIndex]));

        // Setup Binding table entries
        if (pRenderingData->pTarget[1] == nullptr)
        {
            GetBindingIndex(pRenderingData->pTarget[0], &iBTentry);
        }
        else
        {
            // pTarget[0] will be secondary render target in dual output mode
            if (uTargetIndex == 0)
            {
                iBTentry = VPHAL_COMP_BTINDEX_RT_SECOND;
            }
            else
            {
                // pTarget[1] will be primary render target
                iBTentry = VPHAL_COMP_BTINDEX_RENDERTARGET;
                // set dual output mode
                if(m_bFtrMediaWalker)
                {
                    ((MEDIA_OBJECT_KA2_STATIC_DATA*)
                        &pRenderingData->WalkerStatic)->DW09.DualOutputMode = 1;
                }
                else
                {
                    pRenderingData->Static.DW09.DualOutputMode = 1;
                }
            }
        }
        for (i = 0; i < iSurfaceEntries; i++, iBTentry++)
        {
            VPHAL_RENDER_CHK_STATUS(pRenderHal->pfnBindSurfaceState(
                                            pRenderHal,
                                            pRenderingData->iBindingTable,
                                            iBTentry,
                                            pSurfaceEntries[i]));
        }

        if (pRenderingData->iLayers == 0 &&
            pRenderingData->pColorFill == nullptr )
        {
            VPHAL_RENDER_ASSERTMESSAGE("Only Render Target is present, colorfill must be enabled.");
            goto finish;
        }

        uTargetIndex++;
    } while (uTargetIndex < VPHAL_MAX_TARGETS && pRenderingData->pTarget[uTargetIndex]);

finish:
    if (eStatus != MOS_STATUS_SUCCESS)
    {
        iSurfaceEntries = -1;
    }
    return iSurfaceEntries;
}

//!
//! \brief    Get Output Surface Chroma sitting position for kernel
//! \param    [in] pTarget
//!           Pointer to Target Surface
//! \return   uint32_t
//!           Return chroma sitting position
//!
uint32_t CompositeState::GetOutputChromaSitting(
    PVPHAL_SURFACE                      pTarget)
{
    uint32_t dwChromaSitingLocation = CHROMA_SUBSAMPLING_TOP_LEFT;

    VPHAL_RENDER_CHK_NULL_NO_STATUS(pTarget);

    // If there is no DDI setting, we use the Horizontal Left Vertical Center as default for PL2 surface.
    if (pTarget->ChromaSiting == CHROMA_SITING_NONE)
    {
        // PL2 default to Horizontal Left, Vertical Center
        if (IS_PL2_FORMAT(pTarget->Format) || IS_PL2_FORMAT_UnAligned(pTarget->Format))
        {
            dwChromaSitingLocation = CHROMA_SUBSAMPLING_CENTER_LEFT;
        }
    }
    else
    {
        // PL2, 6 positions are avalibale
        if (IS_PL2_FORMAT(pTarget->Format) || IS_PL2_FORMAT_UnAligned(pTarget->Format))
        {
            // Horizontal Left
            if (pTarget->ChromaSiting & CHROMA_SITING_HORZ_LEFT)
            {
                if (pTarget->ChromaSiting & CHROMA_SITING_VERT_TOP)
                {
                    dwChromaSitingLocation = CHROMA_SUBSAMPLING_TOP_LEFT;
                }
                else if (pTarget->ChromaSiting & CHROMA_SITING_VERT_CENTER)
                {
                    dwChromaSitingLocation = CHROMA_SUBSAMPLING_CENTER_LEFT;
                }
                else if (pTarget->ChromaSiting & CHROMA_SITING_VERT_BOTTOM)
                {
                    dwChromaSitingLocation = CHROMA_SUBSAMPLING_BOTTOM_LEFT;
                }
            }
            // Horizontal Center
            else if (pTarget->ChromaSiting & CHROMA_SITING_HORZ_CENTER)
            {
                if (pTarget->ChromaSiting & CHROMA_SITING_VERT_TOP)
                {
                    dwChromaSitingLocation = CHROMA_SUBSAMPLING_TOP_CENTER;
                }
                else if (pTarget->ChromaSiting & CHROMA_SITING_VERT_CENTER)
                {
                    dwChromaSitingLocation = CHROMA_SUBSAMPLING_CENTER_CENTER;
                }
                else if (pTarget->ChromaSiting & CHROMA_SITING_VERT_BOTTOM)
                {
                    dwChromaSitingLocation = CHROMA_SUBSAMPLING_BOTTOM_CENTER;
                }
            }
        }
        else if (IS_PA_FORMAT(pTarget->Format))
        {
            // For PA surface, only (H Left, V Top) and (H Center, V top) are needed.
            if (pTarget->ChromaSiting & (CHROMA_SITING_HORZ_CENTER))
            {
                dwChromaSitingLocation = CHROMA_SUBSAMPLING_TOP_CENTER;
            }
        }
    }
finish:
    return dwChromaSitingLocation;
}

//!
//! \brief    Set Surface Compressed Parameters
//! \details  Set Surface Compressed Parameters, and compression mode
//! \param    [in,out] pSource
//!           Pointer to Source Surface
//! \param    [in] isRenderTarget
//!           Render Target or not
//! \return   void
//!
void CompositeState::SetSurfaceCompressionParams(
    PVPHAL_SURFACE                  pSource,
    bool                            isRenderTarget)
{
    if (!MEDIA_IS_SKU(GetSkuTable(), FtrCompsitionMemoryCompressedOut) &&
        isRenderTarget)
    {
        if (pSource                                             &&
            pSource->bCompressible                              &&
            // For platforms support MC/RC, only enable Render engine MC write.
            (pSource->CompressionMode == MOS_MMC_RC             ||
            // For legacy platforms, no compression supported for composite RT.
            pSource->CompressionMode == MOS_MMC_HORIZONTAL      ||
            pSource->CompressionMode == MOS_MMC_VERTICAL))
        {
            // Set MC to let HW to clean Aux for RC surface
            if (pSource->CompressionMode == MOS_MMC_RC)
            {
                VPHAL_RENDER_NORMALMESSAGE("Force MC to clean Aux for RC RT surface due to CompsitionMemoryCompressedOut no supported");
                pSource->CompressionMode = MOS_MMC_MC;
            }
            else
            {
                VPHAL_RENDER_NORMALMESSAGE("MMC DISABLED for RT due to CompsitionMemoryCompressedOut no supported");
                pSource->bIsCompressed   = false;
                pSource->CompressionMode = MOS_MMC_DISABLED;
                m_pOsInterface->pfnSetMemoryCompressionMode(m_pOsInterface, &pSource->OsResource, MOS_MEMCOMP_STATE(MOS_MEMCOMP_DISABLED));
            }
        }
    }
}

//!
//! \brief    Check whether parameters for composition valid or not.
//! \param    [in] CompositeParams
//!           Parameters for composition
//! \return   MOS_STATUS
//!           Return MOS_STATUS_SUCCESS if successful, otherwise failed
//!
MOS_STATUS CompositeState::IsCompositeParamsValid(
    const VPHAL_COMPOSITE_PARAMS& CompositeParams)
{
    if (CompositeParams.uSourceCount > VPHAL_COMP_MAX_LAYERS)
    {
        VPHAL_RENDER_ASSERTMESSAGE("Invalid number of sources.");
        return MOS_STATUS_INVALID_PARAMETER;
    }
    return MOS_STATUS_SUCCESS;
}

//!
//! \brief    Calculate and set inline data size
//! \param    [in] pRenderingData
//!           pointer to render data
//! \param    [out] pStatic
//!           pointer to static data
//! \return   void
//!
int32_t CompositeState::CalculateInlineDataSize(
    PVPHAL_RENDERING_DATA_COMPOSITE pRenderingData,
    MEDIA_OBJECT_KA2_STATIC_DATA    *pStatic)
{
    // Set inline pointer
    pStatic->DW07.PointerToInlineParameters = 7;

    // Set Inline Data Size
    switch (pRenderingData->iLayers)
    {
        case 0:
            // Case 0 is trued only for colorfill only cases.
            // Colorfill uses inverted layer 0 block mask to determine colorfill region.
        case 1:
        case 2:
        case 3:
            pRenderingData->iCmdInlineSize =  8 * sizeof(uint32_t);
            break;
        case 4:
            pRenderingData->iCmdInlineSize =  9 * sizeof(uint32_t);
            break;
        case 5:
            pRenderingData->iCmdInlineSize = 10 * sizeof(uint32_t);
            break;
        case 6:
            pRenderingData->iCmdInlineSize = 11 * sizeof(uint32_t);
            break;
        case 7:
            pRenderingData->iCmdInlineSize = 12 * sizeof(uint32_t);
            break;
        case 8:
            pRenderingData->iCmdInlineSize = 13 * sizeof(uint32_t);
            break;
        default:
            VPHAL_RENDER_ASSERTMESSAGE("%s, Invalid Number of Layers.");
            break;
    }
    return pRenderingData->iCmdInlineSize;
}

//!
//! \brief    Submit Composite states
//! \details  Submit Composite states, including load CSC matrix, set Inline data,
//!           set background color, load Palettes, set output format, load kernel, load
//!           curbe data, set sampler state, set VFE State params, and etc
//! \param    [in] pRenderingData
//!           Pointer to Composite state
//! \return   bool
//!           Return TURE if successful, otherwise false
//!
bool CompositeState::SubmitStates(
    PVPHAL_RENDERING_DATA_COMPOSITE     pRenderingData)
{
    // States and objects
    PRENDERHAL_INTERFACE                pRenderHal;
    Kdll_State                          *pKernelDllState;   // Kernel DLL state
    Kdll_CacheEntry                     *pKernelEntry;      // Media kernel entry
    float                               pfCscMatrix[12];    // CSC matrix in floating point format
    int32_t                             piCscMatrix[12];    // CSC matrix in fixed point format

    PRENDERHAL_MEDIA_STATE              pMediaState;    // Media states
    MEDIA_OBJECT_KA2_STATIC_DATA        *pStatic;        // Static parameters
    PVPHAL_SURFACE                      pSurface;       // Surface parameters
    PVPHAL_SURFACE                      pTarget;        // Render Target parameters

    RENDERHAL_SURFACE_STATE_PARAMS      SurfaceParams;

    // Media kernel parameters
    int32_t                             iFilterSize, i, j;
    int32_t                             iThreadCount;
    Kdll_FilterEntry                    *pFilter;
    Kdll_CSC_Params                     *pCscParams;
    Kdll_CSC_Matrix                     *pMatrix;
    Kdll_Procamp                        *pProcamp;

    int32_t                             iKrnAllocation;
    int32_t                             iCurbeOffset;
    int32_t                             iCurbeLength;
    int32_t                             iInlineLength;
    MHW_KERNEL_PARAM                    MhwKernelParam;

    // CSC parameters for ColorFill and Palettes
    VPHAL_CSPACE                        src_cspace, dst_cspace;
    uint8_t                             ColorFill_A;
    float                               fStepX;
    bool                                bResult = false;
    MOS_STATUS                          eStatus;
    int32_t                             iNumEntries;
    void*                               pPaletteData = nullptr;

    VPHAL_RENDER_ASSERT(m_pKernelDllState);
    VPHAL_RENDER_CHK_NULL(m_pRenderHal);
    VPHAL_RENDER_CHK_NULL(pRenderingData);
    VPHAL_RENDER_CHK_NULL(pRenderingData->pKernelEntry);

    ColorFill_A     = 0;
    pKernelDllState = m_pKernelDllState;
    pRenderHal      = m_pRenderHal;
    pKernelEntry    = pRenderingData->pKernelEntry;

    // Get Pointer to rendering data
    if(m_bFtrMediaWalker)
    {
        pStatic    = (MEDIA_OBJECT_KA2_STATIC_DATA*)&pRenderingData->WalkerStatic;
    }
    else
    {
        pStatic    = &pRenderingData->Static;
    }

    VPHAL_RENDER_CHK_NULL(pStatic);
    // Get Pointer to Render Target Surface
    pTarget        = pRenderingData->pTarget[0];

    // Get Kernel Filter description
    pFilter        = pKernelEntry->pFilter;
    iFilterSize    = pKernelEntry->iFilterSize;

    // Get Kernel CSC information
    pCscParams     = pKernelEntry->pCscParams;

    pMatrix        = nullptr;
    for (i = 0; i < DL_CSC_MAX; i++)
    {
        if (pCscParams->Matrix[i].iCoeffID == CoeffID_0)
        {
            pMatrix = &pCscParams->Matrix[i];
            break;
        }
    }

    // Load CSC matrix
    if (pMatrix && pMatrix->bInUse && !m_bFtrCSCCoeffPatchMode)
    {
        // Procamp is present
        if (pMatrix->iProcampID != DL_PROCAMP_DISABLED &&
            pMatrix->iProcampID < m_iMaxProcampEntries)
        {
            // Get Procamp parameter - update matrix only if Procamp is changed
            pProcamp = &pRenderingData->pProcamp[pMatrix->iProcampID];
            if (pMatrix->iProcampVersion != pProcamp->iProcampVersion)
            {
                KernelDll_UpdateCscCoefficients(pKernelDllState, pMatrix);
            }
        }

        // CSC coeff from static parameter only applies to primary layer
        if (pMatrix->iCoeffID == CoeffID_0)
        {
            int16_t* pCoeff = pMatrix->Coeff;

            pStatic->DW00.CscConstantC0  = *(pCoeff++);
            pStatic->DW00.CscConstantC1  = *(pCoeff++);
            pStatic->DW01.CscConstantC2  = *(pCoeff++);
            pStatic->DW01.CscConstantC3  = *(pCoeff++);
            pStatic->DW02.CscConstantC4  = *(pCoeff++);
            pStatic->DW02.CscConstantC5  = *(pCoeff++);
            pStatic->DW03.CscConstantC6  = *(pCoeff++);
            pStatic->DW03.CscConstantC7  = *(pCoeff++);
            pStatic->DW04.CscConstantC8  = *(pCoeff++);
            pStatic->DW04.CscConstantC9  = *(pCoeff++);
            pStatic->DW05.CscConstantC10 = *(pCoeff++);
            pStatic->DW05.CscConstantC11 = *pCoeff;
        }
        else
        {
            VPHAL_RENDER_ASSERTMESSAGE("CSC matrix coefficient id is non-zero.");
            goto finish;
        }
    }

    if (pRenderingData->bCmFcEnable && m_bFtrCSCCoeffPatchMode)
    {
        MOS_ZeroMemory(&SurfaceParams, sizeof(SurfaceParams));

        SurfaceParams.Type          = pRenderHal->SurfaceTypeDefault;
        SurfaceParams.isOutput = false;
        SurfaceParams.Boundary      = RENDERHAL_SS_BOUNDARY_ORIGINAL;
        SurfaceParams.bWidth16Align = false;
        SurfaceParams.MemObjCtl     = m_SurfMemObjCtl.InputSurfMemObjCtl;

        if (!Mos_ResourceIsNull(&m_CmfcCoeff.OsResource))
        {
            VPHAL_RENDER_CHK_STATUS(VpHal_CommonSetSurfaceForHwAccess(
                m_pRenderHal,
                &m_CmfcCoeff,
                &m_RenderHalCmfcCoeff,
                &SurfaceParams,
                pRenderingData->iBindingTable,
                VPHAL_COMP_BTINDEX_CSC_COEFF,
                false));
        }
        else
        {
            VPHAL_RENDER_ASSERTMESSAGE("Null resource found");
            eStatus = MOS_STATUS_NULL_POINTER;
            goto finish;
        }
    }

    iInlineLength = CalculateInlineDataSize(pRenderingData, pStatic);

    if (pRenderingData->pLayers[0] && pStatic)
    {
        UpdateInlineDataStatus(pRenderingData->pLayers[0], pStatic);
    }

    // Set Background color (use cspace of first layer)
    if (pRenderingData->pColorFill)
    {
        VPHAL_COLOR_SAMPLE_8 Src;

        Src.dwValue = pRenderingData->pColorFill->Color;

        // get src and dst colorspaces
        src_cspace = pRenderingData->pColorFill->CSpace;

        // if iscale enabled, set colorspace to render target color space
        if ( pFilter->sampler == Sample_iScaling || pFilter->sampler == Sample_iScaling_034x || pFilter->sampler == Sample_iScaling_AVS )
        {
            dst_cspace = CSpace_None;
            // find the filter of render target and set dst_cspace to render target color space
            for (i = 0; i < iFilterSize; i++)
            {
                if ((pFilter + i)->layer == Layer_RenderTarget)
                {
                    dst_cspace = (pFilter + i)->cspace;
                }
            }

            if (dst_cspace == CSpace_None) // if color space is invalid return false
            {
                VPHAL_RENDER_ASSERTMESSAGE("Failed to assign dst color spcae for iScale case.");
                goto finish;
            }
        }
        else // use selected cspace by kdll
        {
            if (GFX_IS_GEN_9_OR_LATER(pRenderHal->Platform))
            {
                dst_cspace = pKernelDllState->colorfill_cspace;
            }
            else
            {
                dst_cspace = pFilter->cspace;
            }
        }

        // Convert BG color only if not done so before. CSC is expensive!
        if ((m_csSrc.dwValue != Src.dwValue) ||
            (m_CSpaceSrc     != src_cspace)  ||
            (m_CSpaceDst     != dst_cspace))
        {
            VpUtils::GetCscMatrixForRender8Bit(&m_csDst, &Src, src_cspace, dst_cspace);

            // store the values for next iteration
            m_csSrc     = Src;
            m_CSpaceSrc = src_cspace;
            m_CSpaceDst = dst_cspace;
        }

        // Set BG color
        if (KernelDll_IsCspace(dst_cspace, CSpace_RGB))
        {
            ColorFill_A = m_csDst.A;
            pStatic->DW13.ColorFill_R = m_csDst.R;
            pStatic->DW13.ColorFill_G = m_csDst.G;
            pStatic->DW13.ColorFill_B = m_csDst.B;
        }
        else
        {
            ColorFill_A = m_csDst.a;
            pStatic->DW13.ColorFill_Y = m_csDst.Y;
            pStatic->DW13.ColorFill_U = m_csDst.U;
            pStatic->DW13.ColorFill_V = m_csDst.V;
        }
    }

    // Load Palettes (layer cspace determines the output cspace)
    // REMARK - Last filter entry is for Render Target
    pSurface    = nullptr;     // initialize it as it may not be set such as for colorfill only case
    for (i = 0; i < iFilterSize - 1; i++, pFilter++)
    {
        // Get current layer ID
        pSurface = pRenderingData->pLayers[i];
        if (nullptr == pSurface)
        {
            continue;
        }
        // Check for palette
        if (pSurface->Palette.iNumEntries <= 0)
        {
            continue;
        }

        // Get palette CSC mode based on filter description
        src_cspace = pSurface->Palette.ColorSpace;
        dst_cspace = pFilter->cspace;

        MOS_ZeroMemory(pfCscMatrix, sizeof(pfCscMatrix));
        KernelDll_GetCSCMatrix(src_cspace, dst_cspace, pfCscMatrix);
        // convert float to fixed point format
        for (j = 0; j < 12; j++)
        {
            // multiply by 2^20 and round up
            piCscMatrix[j] = (int32_t)((pfCscMatrix[j] * 1048576.0f) + 0.5f);
        }

        eStatus = pRenderHal->pfnGetPaletteEntry(pRenderHal,
                                                 pSurface->iPalette,
                                                 pSurface->Palette.iNumEntries,
                                                 &iNumEntries,
                                                 &pPaletteData);
        if (eStatus != MOS_STATUS_SUCCESS)
        {
            VPHAL_RENDER_ASSERTMESSAGE("Failed to Get Palette Entry.");
            goto finish;
        }

        eStatus = LoadPaletteData(&pSurface->Palette,
                                   src_cspace,
                                   dst_cspace,
                                   piCscMatrix,
                                   iNumEntries,
                                   pPaletteData);
        if (eStatus != MOS_STATUS_SUCCESS)
        {
            VPHAL_RENDER_ASSERTMESSAGE("Failed to Load Palette.");
            eStatus = pRenderHal->pfnFreePaletteID(
                            pRenderHal,
                            &pSurface->iPalette);
            if (eStatus != MOS_STATUS_SUCCESS)
            {
                VPHAL_RENDER_ASSERTMESSAGE("Failed to Free Palette ID.");
            }
            goto finish;
        }
    }

/*
|    |---------------------------------------------------------------------|
|    |                      Alpha fill mode table                          |
|    |---------------------------------------------------------------------|
|    |                      ALPHA_FILL_MODE_NONE                           |
|    |---------------------------------------------------------------------|
|    |        Input         |         Output       |     Kernel used       |
|    |      Has Alpha       |        Has Alpha     |      Save_ARGB        |
|    |      No Alpha        |        Has Alpha     |Save_RGB(ALpha frm app)|
|    |      Has Alpha       |        No Alpha      |    Save_RGB(0xff)     |
|    |      No Alpha        |        No Alpha      |    Save_RGB(0xff)     |
|    |---------------------------------------------------------------------|
|    |                    ALPHA_FILL_MODE_OPAQUE                           |
|    |---------------------------------------------------------------------|
|    |        Input         |         Output       |     Kernel used       |
|    |      Has Alpha       |        Has Alpha     |    Save_RGB(0xff)     |
|    |      No Alpha        |        Has Alpha     |    Save_RGB(0xff)     |
|    |      Has Alpha       |        No Alpha      |    Save_RGB(0xff)     |
|    |      No Alpha        |        No Alpha      |    Save_RGB(0xff)     |
|    |---------------------------------------------------------------------|
|    |                   ALPHA_FILL_MODE_BACKGROUND                        |
|    |---------------------------------------------------------------------|
|    |        Input         |         Output       |     Kernel used       |
|    |      Has Alpha       |        Has Alpha     |  Save_RGB(BG Alpha)   |
|    |      No Alpha        |        Has Alpha     |  Save_RGB(BG Alpha)   |
|    |      Has Alpha       |        No Alpha      |    Save_RGB(0xff)     |
|    |      No Alpha        |        No Alpha      |    Save_RGB(0xff)     |
|    |---------------------------------------------------------------------|
|    |                  ALPHA_FILL_MODE_SOURCE_STREAM                      |
|    |---------------------------------------------------------------------|
|    |        Input         |         Output       |     Kernel used       |
|    |      Has Alpha       |        Has Alpha     |      Save_ARGB        |
|    |      No Alpha        |        Has Alpha     |    Save_RGB(0xff)     |
|    |      Has Alpha       |        No Alpha      |    Save_RGB(0xff)     |
|    |      No Alpha        |        No Alpha      |    Save_RGB(0xff)     |
|    |---------------------------------------------------------------------|
*/

    // Set output format
    if (IS_PA_FORMAT(pTarget->Format)  &&
        pTarget->Format != Format_Y410 &&
        pTarget->Format != Format_Y416)
    {
        VpHal_RndrSetYUVComponents(
            pTarget->Format,
            &(pStatic->DW15.DestinationPackedYOffset),
            &(pStatic->DW15.DestinationPackedUOffset),
            &(pStatic->DW15.DestinationPackedVOffset));
    }
    else if (pFilter->bFillOutputAlphaWithConstant && pRenderingData->pCompAlpha != nullptr)
    {
        switch (pRenderingData->pCompAlpha->AlphaMode)
        {
            case VPHAL_ALPHA_FILL_MODE_NONE:
                if (pFilter->format == Format_A8R8G8B8    ||
                    pFilter->format == Format_A8B8G8R8    ||
                    pFilter->format == Format_R10G10B10A2 ||
                    pFilter->format == Format_B10G10R10A2 ||
                    pFilter->format == Format_AYUV        ||
                    pFilter->format == Format_Y410        ||
                    pFilter->format == Format_Y416)
                {
                    pStatic->DW15.DestinationRGBFormat = (uint8_t)(0xff * pRenderingData->pCompAlpha->fAlpha);
                }
                else
                {
                    pStatic->DW15.DestinationRGBFormat = 0xff;
                }
                // For color fill only case, pass through alpha value
                if (pRenderingData->pColorFill && pRenderingData->iLayers == 0)
                {
                    pStatic->DW15.DestinationRGBFormat = ColorFill_A;
                }
                break;

            case VPHAL_ALPHA_FILL_MODE_BACKGROUND:
                pStatic->DW15.DestinationRGBFormat = ColorFill_A;
                break;

            // VPHAL_ALPHA_FILL_MODE_SOURCE_STREAM case is hit when the input does not have alpha
            // So we set Opaque alpha channel.
            case VPHAL_ALPHA_FILL_MODE_SOURCE_STREAM:
            case VPHAL_ALPHA_FILL_MODE_OPAQUE:
            default:
                pStatic->DW15.DestinationRGBFormat = 0xff;
                break;
        }
    }
    else
    {
        pStatic->DW15.DestinationRGBFormat = 0xff;
    }

    // Set flag to swap R and B in Save_RGB/ARGB if target format is Format_A8B8G8R8/Format_X8B8G8R8/Format_B10G10R10A2.
    // No need for RGBP/BGRP, since they are 3 plane format, kenel change the RB channel by different plane order
    pStatic->DW09.ChannelSwap = ((pTarget->Format == Format_A8B8G8R8) ||
                                 (pTarget->Format == Format_X8B8G8R8) ||
                                 (pTarget->Format == Format_B10G10R10A2)) ? 1 : 0;

    // Set primary video scaling factor
    fStepX = pRenderingData->Inline.DW04.VideoXScalingStep;
    if (fStepX <= 0.0f)
    {
        fStepX = pRenderingData->Inline.DW04.VideoXScalingStep = 1.0f;
    }

    // Set 1st layer step X to the Batch Buffer selection logic
    pRenderingData->BbArgs.fStepX = fStepX;

    // Normalize scaling factors for all layers
    // Ratio of Horizontal Scaling Step to Video X Scaling Step
    // Since NLAS is ZBBed, CM FC kernels simplified scaling factor calculation, no need to normalize here
    if (!pRenderingData->bCmFcEnable)
    {
        pStatic->DW16.HorizontalScalingStepRatioLayer0 /= fStepX;
        pStatic->DW17.HorizontalScalingStepRatioLayer1 /= fStepX;
        pStatic->DW18.HorizontalScalingStepRatioLayer2 /= fStepX;
        pStatic->DW19.HorizontalScalingStepRatioLayer3 /= fStepX;
        pStatic->DW20.HorizontalScalingStepRatioLayer4 /= fStepX;
        pStatic->DW21.HorizontalScalingStepRatioLayer5 /= fStepX;
        pStatic->DW22.HorizontalScalingStepRatioLayer6 /= fStepX;
        pStatic->DW23.HorizontalScalingStepRatioLayer7 /= fStepX;
    }

    pMediaState = pRenderingData->pMediaState;

    // Load media kernel for compositing
    INIT_MHW_KERNEL_PARAM(MhwKernelParam, pKernelEntry);
    iKrnAllocation = pRenderHal->pfnLoadKernel(
                                pRenderHal,
                                &m_KernelParams,
                                &MhwKernelParam,
                                pKernelEntry);

    // Check if kernel is successfully loaded in GSH
    if (iKrnAllocation < 0)
    {
        VPHAL_RENDER_ASSERTMESSAGE("Failed to load kernel in GSH.");
        goto finish;
    }

    SubmitStatesFillGenSpecificStaticData(pRenderingData,
                                   pTarget,
                                   pStatic);

    if (m_bFtrMediaWalker)
    {
        iCurbeLength = sizeof(MEDIA_WALKER_KA2_STATIC_DATA);
    }
    else
    {
        // Set Static parameters
        iCurbeLength = pStatic->DW14.NLASEnable ?
            sizeof(MEDIA_OBJECT_KA2_STATIC_DATA) -
            sizeof(MEDIA_OBJECT_NLAS_INLINE_DATA) :
            sizeof(MEDIA_OBJECT_KA2_STATIC_DATA);
    }

    iCurbeOffset = pRenderHal->pfnLoadCurbeData(
        pRenderHal,
        pMediaState,
        pStatic,
        iCurbeLength);
    if (iCurbeOffset < 0)
    {
        VPHAL_RENDER_ASSERTMESSAGE("Failed to setup CURBE data.");
        goto finish;
    }

    // Allocate Media ID, link to kernel
    pRenderingData->iMediaID = pRenderHal->pfnAllocateMediaID(
        pRenderHal,
        iKrnAllocation,
        pRenderingData->iBindingTable,
        iCurbeOffset,
        iCurbeLength,
        0,
        nullptr);
    if (pRenderingData->iMediaID < 0)
    {
        VPHAL_RENDER_ASSERTMESSAGE("Failed to setup Media Interface Descriptor.");
        goto finish;
    }

    pRenderingData->iCurbeOffset = iCurbeOffset;
    pRenderingData->iCurbeLength = iCurbeLength;

    // Set Sampler states for this Media ID
    eStatus = pRenderHal->pfnSetSamplerStates(
        pRenderHal,
        pRenderingData->iMediaID,
        pRenderingData->SamplerStateParams,
        MHW_RENDER_ENGINE_SAMPLERS_MAX);

    PrintSamplerParams(pRenderingData->SamplerStateParams);

    if (MOS_FAILED(eStatus))
    {
        VPHAL_RENDER_ASSERTMESSAGE("Failed to setup sampler states.");
        goto finish;
    }

    iThreadCount = GetThreadCountForVfeState(pRenderingData, pTarget);

    //----------------------------------
    // Setup VFE State params. Each Renderer MUST call pfnSetVfeStateParams().
    //----------------------------------
    VPHAL_RENDER_CHK_STATUS(pRenderHal->pfnSetVfeStateParams(
        pRenderHal,
        MEDIASTATE_DEBUG_COUNTER_FREE_RUNNING,
        iThreadCount,
        iCurbeLength,
        iInlineLength,
        nullptr));

    bResult = true;
    PrintCurbeData(pStatic);

finish:
    return bResult;
}

//!
//! \brief    Search for the best match BB according to the Composition BB arguments
//! \param    [in] pBatchBufferTable
//!           Pointer to the BB table to be searched
//! \param    [in] pInputBbParams
//!           Pointer to the BB params required for the best match
//! \param    [in] iBbSize
//!           the BB size required for the best match
//! \param    [out] ppBatchBuffer
//!           Pointer to the addr of the best matched BB, pointer to nullptr if there's
//!           no available matched BB
//! \return   MOS_STATUS
//!           Return MOS_STATUS_SUCCESS if successful, otherwise failed
//!
MOS_STATUS CompositeState::GetBestMatchBB(
    PVPHAL_BATCH_BUFFER_TABLE     pBatchBufferTable,
    PVPHAL_BATCH_BUFFER_PARAMS    pInputBbParams,
    int32_t                       iBbSize,
    PMHW_BATCH_BUFFER             *ppBatchBuffer)
{
    PMHW_BATCH_BUFFER             pBbEntry;          // 2nd level BBs array entry
    PMHW_BATCH_BUFFER             pBestMatch;        // Best match for BB allocation
    PVPHAL_BATCH_BUFFER_PARAMS    pSearchBbParams;   // Search BB parameters
    PVPHAL_BB_COMP_ARGS           pCompBbArgs;       // 2nd level buffer rendering arguments
    PVPHAL_BB_COMP_ARGS           pSearchBbArgs;     // Search BB comp parameters
    int32_t                       i;
    int32_t                       iCallID;
    int32_t                       iBbCount;
    MOS_STATUS                    eStatus;

    pBestMatch  = nullptr;
    pCompBbArgs = &pInputBbParams->BbArgs.CompositeBB;
    iCallID     = pInputBbParams->iCallID;
    eStatus     = MOS_STATUS_UNKNOWN;

    iBbCount = *pBatchBufferTable->piBatchBufferCount;
    pBbEntry = pBatchBufferTable->pBatchBufferHeader;

    for (i = iBbCount; i > 0; i--, pBbEntry++)
    {
        // Must contain valid Compositing BB Argument set, must have adequate size,
        // cannot reuse buffers from same call ID
        pSearchBbParams = (PVPHAL_BATCH_BUFFER_PARAMS)pBbEntry->pPrivateData;

        if (!pSearchBbParams                                      ||
            pBbEntry->iSize           < iBbSize                   ||
            pSearchBbParams->iCallID == iCallID                   ||
            pSearchBbParams->iType   != VPHAL_BB_TYPE_COMPOSITING ||
            pSearchBbParams->iSize   != sizeof(VPHAL_BB_COMP_ARGS))
        {
            continue;
        }

        // Must match Media ID, StepX, full blocks, different Call ID
        pSearchBbArgs = &(pSearchBbParams->BbArgs.CompositeBB);

        if (pSearchBbArgs->iMediaID    != pCompBbArgs->iMediaID ||  // != Media ID
            pSearchBbArgs->fStepX      != pCompBbArgs->fStepX   ||  // != Step X
            pSearchBbArgs->bSkipBlocks != pCompBbArgs->bSkipBlocks) // != Skip Blocks
        {
            continue;
        }

        // Target rectangle must match
        if (memcmp(&pSearchBbArgs->rcOutput, &pCompBbArgs->rcOutput, sizeof(RECT)))
        {
            continue;
        }

        // BB must contain same or more layers than input BB
        if (pSearchBbArgs->iLayers < pCompBbArgs->iLayers)
        {
            continue;
        }

        // Compare each layer, ignore layers that are not present in the input
        if (memcmp(&pSearchBbArgs->rcDst, &pCompBbArgs->rcDst, pCompBbArgs->iLayers * sizeof(RECT)))
        {
            continue;
        }

        // Compare each layer rotation, ignore layers that are not present in the input
        if (memcmp(&pSearchBbArgs->Rotation, &pCompBbArgs->Rotation, pCompBbArgs->iLayers * sizeof(VPHAL_ROTATION)))
        {
            continue;
        }

        // for AVS/Bi-Linear Scaling, NLAS enable or not
        if (pSearchBbArgs->bEnableNLAS != pCompBbArgs->bEnableNLAS)
        {
            continue;
        }

        // NLAS parameters must match when it's enabled
        if (pCompBbArgs->bEnableNLAS &&
            memcmp(&pSearchBbArgs->NLASParams, &pCompBbArgs->NLASParams, sizeof(VPHAL_NLAS_PARAMS)))
        {
            continue;
        }

        // Match -> reuse the BB regardless of the running state
        pBestMatch = pBbEntry;
        ((PVPHAL_BATCH_BUFFER_PARAMS)pBestMatch->pPrivateData)->bMatch = true;

        break;
    }

    *ppBatchBuffer = pBestMatch;
    eStatus        = MOS_STATUS_SUCCESS;
    return eStatus;
}

//!
//! \brief    Calculate Media Object size
//! \param    [in] pRenderingData
//!           Pointer to Rendering Data
//! \return   int32_t
//!           Return the size of Media Object
//!
int32_t CompositeState::CalculateMediaObjectSize(
    PVPHAL_RENDERING_DATA_COMPOSITE     pRenderingData)
{
    MOS_UNUSED(pRenderingData);
    int32_t size = 0;

    size += m_pRenderHal->pMhwRenderInterface->GetMediaObjectCmdSize();
    size += sizeof(MEDIA_OBJECT_KA2_INLINE_DATA);

    return size;
}

//!
//! \brief    Allocate Composite BatchBuffer
//! \details  Allocate Composite BatchBuffer, search from existing BBs for a match. If
//!           none, allocate new BB
//! \param    [in] PVPHAL_RENDERING_DATA_COMPOSITE pRenderingData
//!           Pointer to Rendering Data
//! \param    [out] PMHW_BATCH_BUFFER * ppBatchBuffer
//!           Pointer to the addr of the available BB. Pointer to nullptr if there's no
//! \return   MOS_STATUS
//!           Return MOS_STATUS_SUCCESS if successful, otherwise failed
//!
MOS_STATUS CompositeState::AllocateBuffer(
    PVPHAL_RENDERING_DATA_COMPOSITE     pRenderingData,
    PMHW_BATCH_BUFFER                   *ppBatchBuffer)
{
    PRENDERHAL_INTERFACE                pRenderHal;
    VPHAL_BATCH_BUFFER_TABLE            BatchBufferTable;
    VPHAL_BATCH_BUFFER_PARAMS           InputBbParams;
    int32_t                             iBbSize;
    int32_t                             iMobjSize;
    MOS_STATUS                          eStatus;

    eStatus      = MOS_STATUS_SUCCESS;
    pRenderHal   = m_pRenderHal;

    iMobjSize = CalculateMediaObjectSize(pRenderingData);
    iBbSize   = iMobjSize * pRenderingData->iBlocksX * pRenderingData->iBlocksY;

    iBbSize = iBbSize + pRenderHal->pMhwMiInterface->GetMiBatchBufferEndCmdSize();;

    InputBbParams.iSize              = sizeof(VPHAL_BB_COMP_ARGS);
    InputBbParams.iType              = VPHAL_BB_TYPE_COMPOSITING;
    InputBbParams.iCallID            = m_iCallID;
    InputBbParams.BbArgs.CompositeBB = pRenderingData->BbArgs;

    BatchBufferTable.pBatchBufferHeader = m_BatchBuffer;
    BatchBufferTable.pBbParamsHeader    = m_BufferParam;
    BatchBufferTable.iBbCountMax        = VPHAL_COMP_BUFFERS_MAX;
    BatchBufferTable.piBatchBufferCount = &m_iBatchBufferCount;

    VPHAL_RENDER_CHK_STATUS(VpHal_RenderAllocateBB(
                  &BatchBufferTable,
                  &InputBbParams,
                  iBbSize,
                  pRenderHal,
                  ppBatchBuffer));

    // Some app had memory overrun when generating the AI44/IA44 sample contents.
    // As result, the batch buffer was trashed and causes hardware hang (TDR).
    // Adding this solution to always regenerate the media objects for AI44
    // and IA44.
    if (pRenderingData->iLayers == 1                         &&
        (pRenderingData->pLayers[0]->Format == Format_AI44   ||
         pRenderingData->pLayers[0]->Format == Format_IA44))
    {
        ((PVPHAL_BATCH_BUFFER_PARAMS)(*ppBatchBuffer)->pPrivateData)->bMatch = false;
        (*ppBatchBuffer)->iCurrent = 0;
    }

finish:
    return eStatus;
}

//!
//! \brief    Render Composite BatchBuffer
//! \details  Render Composite BatchBuffer, setup Media Object header and inline data
//! \param    [in] pBatchBuffer
//!           Pointer to BatchBuffer
//! \param    [in] pRenderingData
//!           Pointer to Rendering Data
//! \return   bool
//!           Return true if successful, otherwise false
//!
bool CompositeState::RenderBuffer(
    PMHW_BATCH_BUFFER               pBatchBuffer,
    PVPHAL_RENDERING_DATA_COMPOSITE pRenderingData)
{
    PRENDERHAL_INTERFACE_LEGACY         pRenderHal;
    PMHW_MI_INTERFACE                   pMhwMiInterface;
    MOS_STATUS                          eStatus;
    PVPHAL_BB_COMP_ARGS                 pBbArgs;
    MEDIA_OBJECT_KA2_STATIC_DATA        *pStatic;
    MEDIA_OBJECT_KA2_INLINE_DATA        *pInline;
    MEDIA_OBJECT_NLAS_INLINE_DATA       *pInlineNLAS;
    VPHAL_COMPOSITE_MO_INLINE_DATA      MOInlineData;
    MHW_MEDIA_OBJECT_PARAMS             MediaObjectParams;
    uint16_t                            wMask;
    uint16_t                            wCombinedMask;
    PRECT                               rcDst;
    int32_t                             x, y, dx, dy;
    int32_t                             xl, xr, yt, yb;
    bool                                bResult;
    float                               fSrcX[8];
    uint32_t                            applyRotation;
    uint32_t                            targetIndex;

    bResult             = false;
    pRenderHal          = m_pRenderHal;
    pMhwMiInterface     = pRenderHal->pMhwMiInterface;
    MOS_ZeroMemory(fSrcX, sizeof(float) * 8);

    if (pRenderHal->pfnLockBB(pRenderHal, pBatchBuffer) != MOS_STATUS_SUCCESS)
    {
        VPHAL_RENDER_ASSERTMESSAGE("Failed to lock batch buffer.");
        goto finish;
    }

    pBbArgs   = &pRenderingData->BbArgs;
    rcDst     = pBbArgs->rcDst;

    MOS_ZeroMemory(&MediaObjectParams, sizeof(MediaObjectParams));
    MediaObjectParams.dwInterfaceDescriptorOffset   = pRenderingData->iMediaID;
    MediaObjectParams.dwInlineDataSize              =
        pRenderingData->iCmdInlineSize + pRenderingData->iNLASInlineSize;

    MOInlineData.NLASInline     = g_cInit_MEDIA_OBJECT_NLAS_INLINE_DATA;
    MOInlineData.KA2Inline      = pRenderingData->Inline;
    pInline                     = &MOInlineData.KA2Inline;
    pInlineNLAS                 = &MOInlineData.NLASInline;
    pStatic                     = &pRenderingData->Static;

    // Traverse blocks in the render target area. If destination is not 16x16
    // pixel aligned, the top-most row and left-most column will launch MO cmds
    // starting from non-16x16 aligned dest coords. But the rest of the MO cmds
    // are aligned to 16x16 pixel boundary. Worst-case we would process 15 pixel
    // rows top and columns left twice.
    // In case of dual render targets, all horizontal and vertical
    // settings should be set according to non-rotated output.
    if (pRenderingData->pTarget[1] == nullptr ||
        m_bKernelSupportDualOutput)
    {
        applyRotation   = 0xFFFFFFFF;
        targetIndex     = 0;
    }
    else
    {
        applyRotation   = 0;
        targetIndex     = 1;
    }

    y  = pBbArgs->rcOutput.top;
    for (dy = 0; dy < pRenderingData->iBlocksY; dy++)
    {
        pInline->DW00.DestinationBlockVerticalOrigin = y;

        wCombinedMask = (pBbArgs->bSkipBlocks) ? 0x0000 : 0xffff;
        switch (pRenderingData->iLayers)
        {
            case 8:
                yt = rcDst[7].top    - y;
                yb = rcDst[7].bottom - y;
                yt = MOS_MIN(MOS_MAX(0, yt), VPHAL_COMP_BLOCK_HEIGHT);
                yb = MOS_MIN(MOS_MAX(0, yb), VPHAL_COMP_BLOCK_HEIGHT);
                wMask = (0xffff << yt) & ((0x0001 << yb) - 1);
                wCombinedMask |= wMask;

                // Gen9+ Possible HW Rotation, kernels not available yet.
                // DW09 bits 2:0 indicate RotationMirrorMode,
                // bit 3 indicates if RotationMirrorMode applies to all layers,
                // =1 means to apply for all layers, =0 means only for Layer0
                // In case of RatationMirrorAllLayer(bit3) = 0, all layers from
                // layer 1 onwards must be no rotation in a single rendering phase.
                SetInline16x16Mask(
                    (VPHAL_ROTATION)((pStatic->DW09.RotationMirrorMode *
                    pStatic->DW09.RotationMirrorAllLayer) & applyRotation),
                    (PVPHAL_16X16BLOCK_COMPOSITE_MASK)&pInline->DW12,
                    wMask,
                    VPHAL_VERTICAL_16X16BLOCK_MASK);
            case 7:
                yt = rcDst[6].top    - y;
                yb = rcDst[6].bottom - y;
                yt = MOS_MIN(MOS_MAX(0, yt), VPHAL_COMP_BLOCK_HEIGHT);
                yb = MOS_MIN(MOS_MAX(0, yb), VPHAL_COMP_BLOCK_HEIGHT);
                wMask = (0xffff << yt) & ((0x0001 << yb) - 1);
                wCombinedMask |= wMask;
                SetInline16x16Mask(
                    (VPHAL_ROTATION)((pStatic->DW09.RotationMirrorMode *
                    pStatic->DW09.RotationMirrorAllLayer) & applyRotation),
                    (PVPHAL_16X16BLOCK_COMPOSITE_MASK)&pInline->DW11,
                    wMask,
                    VPHAL_VERTICAL_16X16BLOCK_MASK);
            case 6:
                yt = rcDst[5].top    - y;
                yb = rcDst[5].bottom - y;
                yt = MOS_MIN(MOS_MAX(0, yt), VPHAL_COMP_BLOCK_HEIGHT);
                yb = MOS_MIN(MOS_MAX(0, yb), VPHAL_COMP_BLOCK_HEIGHT);
                wMask = (0xffff << yt) & ((0x0001 << yb) - 1);
                wCombinedMask |= wMask;
                SetInline16x16Mask(
                    (VPHAL_ROTATION)((pStatic->DW09.RotationMirrorMode *
                    pStatic->DW09.RotationMirrorAllLayer) & applyRotation),
                    (PVPHAL_16X16BLOCK_COMPOSITE_MASK)&pInline->DW10,
                    wMask,
                    VPHAL_VERTICAL_16X16BLOCK_MASK);
            case 5:
                yt = rcDst[4].top    - y;
                yb = rcDst[4].bottom - y;
                yt = MOS_MIN(MOS_MAX(0, yt), VPHAL_COMP_BLOCK_HEIGHT);
                yb = MOS_MIN(MOS_MAX(0, yb), VPHAL_COMP_BLOCK_HEIGHT);
                wMask = (0xffff << yt) & ((0x0001 << yb) - 1);
                wCombinedMask |= wMask;
                SetInline16x16Mask(
                    (VPHAL_ROTATION)((pStatic->DW09.RotationMirrorMode *
                    pStatic->DW09.RotationMirrorAllLayer) & applyRotation),
                    (PVPHAL_16X16BLOCK_COMPOSITE_MASK)&pInline->DW09,
                    wMask,
                    VPHAL_VERTICAL_16X16BLOCK_MASK);
            case 4:
                yt = rcDst[3].top    - y;
                yb = rcDst[3].bottom - y;
                yt = MOS_MIN(MOS_MAX(0, yt), VPHAL_COMP_BLOCK_HEIGHT);
                yb = MOS_MIN(MOS_MAX(0, yb), VPHAL_COMP_BLOCK_HEIGHT);
                wMask = (0xffff << yt) & ((0x0001 << yb) - 1);
                wCombinedMask |= wMask;
                SetInline16x16Mask(
                    (VPHAL_ROTATION)((pStatic->DW09.RotationMirrorMode *
                    pStatic->DW09.RotationMirrorAllLayer) & applyRotation),
                    (PVPHAL_16X16BLOCK_COMPOSITE_MASK)&pInline->DW08,
                    wMask,
                    VPHAL_VERTICAL_16X16BLOCK_MASK);
            case 3:
                yt = rcDst[2].top    - y;
                yb = rcDst[2].bottom - y;
                yt = MOS_MIN(MOS_MAX(0, yt), VPHAL_COMP_BLOCK_HEIGHT);
                yb = MOS_MIN(MOS_MAX(0, yb), VPHAL_COMP_BLOCK_HEIGHT);
                wMask = (0xffff << yt) & ((0x0001 << yb) - 1);
                wCombinedMask |= wMask;
                SetInline16x16Mask(
                    (VPHAL_ROTATION)((pStatic->DW09.RotationMirrorMode *
                    pStatic->DW09.RotationMirrorAllLayer) & applyRotation),
                    (PVPHAL_16X16BLOCK_COMPOSITE_MASK)&pInline->DW03,
                    wMask,
                    VPHAL_VERTICAL_16X16BLOCK_MASK);
            case 2:
                yt = rcDst[1].top    - y;
                yb = rcDst[1].bottom - y;
                yt = MOS_MIN(MOS_MAX(0, yt), VPHAL_COMP_BLOCK_HEIGHT);
                yb = MOS_MIN(MOS_MAX(0, yb), VPHAL_COMP_BLOCK_HEIGHT);
                wMask = (0xffff << yt) & ((0x0001 << yb) - 1);
                wCombinedMask |= wMask;
                SetInline16x16Mask(
                    (VPHAL_ROTATION)((pStatic->DW09.RotationMirrorMode *
                    pStatic->DW09.RotationMirrorAllLayer) & applyRotation),
                    (PVPHAL_16X16BLOCK_COMPOSITE_MASK)&pInline->DW02,
                    wMask,
                    VPHAL_VERTICAL_16X16BLOCK_MASK);
            case 1:
                yt = rcDst[0].top    - y;
                yb = rcDst[0].bottom - y;
                yt = MOS_MIN(MOS_MAX(0, yt), VPHAL_COMP_BLOCK_HEIGHT);
                yb = MOS_MIN(MOS_MAX(0, yb), VPHAL_COMP_BLOCK_HEIGHT);
                wMask = (0xffff << yt) & ((0x0001 << yb) - 1);
                wCombinedMask |= wMask;
                SetInline16x16Mask((VPHAL_ROTATION)
                    (pStatic->DW09.RotationMirrorMode & applyRotation),
                    (PVPHAL_16X16BLOCK_COMPOSITE_MASK)&pInline->DW01,
                    wMask,
                    VPHAL_VERTICAL_16X16BLOCK_MASK);
                break;
            case 0:
                // This case is true only for colorfill only cases. Force block mask to zero.
                pInline->DW01.VerticalBlockCompositeMaskLayer0 = 0;
                break;
        }

        // Skip row if no blocks are flagged for rendering
        if (!wCombinedMask)
        {
            y += VPHAL_COMP_BLOCK_HEIGHT;
            y -= y % VPHAL_COMP_BLOCK_HEIGHT;
            continue;
        }

        x = pBbArgs->rcOutput.left;

        // get the horizontal origin - the second term is necessary to ensure
        // accurate computation of the starting value of fSrcX when the output
        // rectangle does not start at 0 (for example, split-screen demo mode)
        switch (pRenderingData->iLayers)
        {
            case 8:
                fSrcX[7] = pStatic->DW47.HorizontalFrameOriginLayer7 +
                    ((float)(x) / (float)(pRenderingData->pTarget[targetIndex]->dwWidth));
            case 7:
                fSrcX[6] = pStatic->DW46.HorizontalFrameOriginLayer6 +
                    ((float)(x) / (float)(pRenderingData->pTarget[targetIndex]->dwWidth));
            case 6:
                fSrcX[5] = pStatic->DW45.HorizontalFrameOriginLayer5 +
                    ((float)(x) / (float)(pRenderingData->pTarget[targetIndex]->dwWidth));
            case 5:
                fSrcX[4] = pStatic->DW44.HorizontalFrameOriginLayer4 +
                    ((float)(x) / (float)(pRenderingData->pTarget[targetIndex]->dwWidth));
            case 4:
                fSrcX[3] = pStatic->DW43.HorizontalFrameOriginLayer3 +
                    ((float)(x) / (float)(pRenderingData->pTarget[targetIndex]->dwWidth));
            case 3:
                fSrcX[2] = pStatic->DW42.HorizontalFrameOriginLayer2 +
                    ((float)(x) / (float)(pRenderingData->pTarget[targetIndex]->dwWidth));
            case 2:
                fSrcX[1] = pStatic->DW41.HorizontalFrameOriginLayer1 +
                    ((float)(x) / (float)(pRenderingData->pTarget[targetIndex]->dwWidth));
            case 1:
                fSrcX[0] = pStatic->DW40.HorizontalFrameOriginLayer0 +
                    ((float)(x) / (float)(pRenderingData->pTarget[targetIndex]->dwWidth));
                break;
            case 0:
            default:
                fSrcX[0] = fSrcX[1] = fSrcX[2] = fSrcX[3] = 0;
                fSrcX[4] = fSrcX[5] = fSrcX[6] = fSrcX[7] = 0;
                break;
        }

        for (dx = 0; dx < pRenderingData->iBlocksX; dx++)
        {
            pInline->DW00.DestinationBlockHorizontalOrigin = x;

            wCombinedMask = (pBbArgs->bSkipBlocks) ? 0x0000 : 0xffff;
            switch (pRenderingData->iLayers)
            {
                case 8:
                    xl = rcDst[7].left  - x;
                    xr = rcDst[7].right - x;
                    xl = MOS_MIN(MOS_MAX(0, xl), VPHAL_COMP_BLOCK_WIDTH);
                    xr = MOS_MIN(MOS_MAX(0, xr), VPHAL_COMP_BLOCK_WIDTH);
                    wMask = (0xffff << xl) & ((0x0001 << xr) - 1);
                    wCombinedMask |= wMask;
                    SetInline16x16Mask(
                        (VPHAL_ROTATION)((pStatic->DW09.RotationMirrorMode *
                        pStatic->DW09.RotationMirrorAllLayer) & applyRotation),
                        (PVPHAL_16X16BLOCK_COMPOSITE_MASK)&pInline->DW12,
                        wMask,
                        VPHAL_HORIZONTAL_16X16BLOCK_MASK);
                case 7:
                    xl = rcDst[6].left  - x;
                    xr = rcDst[6].right - x;
                    xl = MOS_MIN(MOS_MAX(0, xl), VPHAL_COMP_BLOCK_WIDTH);
                    xr = MOS_MIN(MOS_MAX(0, xr), VPHAL_COMP_BLOCK_WIDTH);
                    wMask = (0xffff << xl) & ((0x0001 << xr) - 1);
                    wCombinedMask |= wMask;
                    SetInline16x16Mask(
                        (VPHAL_ROTATION)((pStatic->DW09.RotationMirrorMode *
                        pStatic->DW09.RotationMirrorAllLayer) & applyRotation),
                        (PVPHAL_16X16BLOCK_COMPOSITE_MASK)&pInline->DW11,
                        wMask,
                        VPHAL_HORIZONTAL_16X16BLOCK_MASK);
                case 6:
                    xl = rcDst[5].left  - x;
                    xr = rcDst[5].right - x;
                    xl = MOS_MIN(MOS_MAX(0, xl), VPHAL_COMP_BLOCK_WIDTH);
                    xr = MOS_MIN(MOS_MAX(0, xr), VPHAL_COMP_BLOCK_WIDTH);
                    wMask = (0xffff << xl) & ((0x0001 << xr) - 1);
                    wCombinedMask |= wMask;
                    SetInline16x16Mask(
                        (VPHAL_ROTATION)((pStatic->DW09.RotationMirrorMode *
                        pStatic->DW09.RotationMirrorAllLayer) & applyRotation),
                        (PVPHAL_16X16BLOCK_COMPOSITE_MASK)&pInline->DW10,
                        wMask,
                        VPHAL_HORIZONTAL_16X16BLOCK_MASK);
                case 5:
                    xl = rcDst[4].left  - x;
                    xr = rcDst[4].right - x;
                    xl = MOS_MIN(MOS_MAX(0, xl), VPHAL_COMP_BLOCK_WIDTH);
                    xr = MOS_MIN(MOS_MAX(0, xr), VPHAL_COMP_BLOCK_WIDTH);
                    wMask = (0xffff << xl) & ((0x0001 << xr) - 1);
                    wCombinedMask |= wMask;
                    SetInline16x16Mask(
                        (VPHAL_ROTATION)((pStatic->DW09.RotationMirrorMode *
                        pStatic->DW09.RotationMirrorAllLayer) & applyRotation),
                        (PVPHAL_16X16BLOCK_COMPOSITE_MASK)&pInline->DW09,
                        wMask,
                        VPHAL_HORIZONTAL_16X16BLOCK_MASK);
                case 4:
                    xl = rcDst[3].left  - x;
                    xr = rcDst[3].right - x;
                    xl = MOS_MIN(MOS_MAX(0, xl), VPHAL_COMP_BLOCK_WIDTH);
                    xr = MOS_MIN(MOS_MAX(0, xr), VPHAL_COMP_BLOCK_WIDTH);
                    wMask = (0xffff << xl) & ((0x0001 << xr) - 1);
                    wCombinedMask |= wMask;
                    SetInline16x16Mask(
                        (VPHAL_ROTATION)((pStatic->DW09.RotationMirrorMode *
                        pStatic->DW09.RotationMirrorAllLayer) & applyRotation),
                        (PVPHAL_16X16BLOCK_COMPOSITE_MASK)&pInline->DW08,
                        wMask,
                        VPHAL_HORIZONTAL_16X16BLOCK_MASK);
                case 3:
                    xl = rcDst[2].left  - x;
                    xr = rcDst[2].right - x;
                    xl = MOS_MIN(MOS_MAX(0, xl), VPHAL_COMP_BLOCK_WIDTH);
                    xr = MOS_MIN(MOS_MAX(0, xr), VPHAL_COMP_BLOCK_WIDTH);
                    wMask = (0xffff << xl) & ((0x0001 << xr) - 1);
                    wCombinedMask |= wMask;
                    SetInline16x16Mask(
                        (VPHAL_ROTATION)((pStatic->DW09.RotationMirrorMode *
                        pStatic->DW09.RotationMirrorAllLayer) & applyRotation),
                        (PVPHAL_16X16BLOCK_COMPOSITE_MASK)&pInline->DW03,
                        wMask,
                        VPHAL_HORIZONTAL_16X16BLOCK_MASK);
                case 2:
                    xl = rcDst[1].left  - x;
                    xr = rcDst[1].right - x;
                    xl = MOS_MIN(MOS_MAX(0, xl), VPHAL_COMP_BLOCK_WIDTH);
                    xr = MOS_MIN(MOS_MAX(0, xr), VPHAL_COMP_BLOCK_WIDTH);
                    wMask = (0xffff << xl) & ((0x0001 << xr) - 1);
                    wCombinedMask |= wMask;
                    SetInline16x16Mask(
                        (VPHAL_ROTATION)((pStatic->DW09.RotationMirrorMode *
                        pStatic->DW09.RotationMirrorAllLayer) & applyRotation),
                        (PVPHAL_16X16BLOCK_COMPOSITE_MASK)&pInline->DW02,
                        wMask,
                        VPHAL_HORIZONTAL_16X16BLOCK_MASK);
                case 1:
                    xl = rcDst[0].left  - x;
                    xr = rcDst[0].right - x;
                    xl = MOS_MIN(MOS_MAX(0, xl), VPHAL_COMP_BLOCK_WIDTH);
                    xr = MOS_MIN(MOS_MAX(0, xr), VPHAL_COMP_BLOCK_WIDTH);
                    wMask = (0xffff << xl) & ((0x0001 << xr) - 1);
                    wCombinedMask |= wMask;
                    SetInline16x16Mask((VPHAL_ROTATION)
                        (pStatic->DW09.RotationMirrorMode & applyRotation),
                        (PVPHAL_16X16BLOCK_COMPOSITE_MASK)&pInline->DW01,
                        wMask,
                        VPHAL_HORIZONTAL_16X16BLOCK_MASK);
                    break;
                case 0:
                    // This case is true only for colorfill only cases. Force block mask to zero.
                    pInline->DW01.HorizontalBlockCompositeMaskLayer0 = 0;
                    break;
            }

            ModifyInlineData(pBbArgs, pRenderingData, pStatic, pInline, pInlineNLAS, x, fSrcX);

            if (wCombinedMask)
            {
                if (pBbArgs->bEnableNLAS)
                {
                    MediaObjectParams.pInlineData = &MOInlineData.NLASInline;
                }
                else
                {
                    MediaObjectParams.pInlineData = &MOInlineData.KA2Inline;
                }
                VPHAL_RENDER_CHK_STATUS(pRenderHal->pMhwRenderInterface->AddMediaObject(
                    nullptr,
                    pBatchBuffer,
                    &MediaObjectParams));
            }

            x += VPHAL_COMP_BLOCK_WIDTH;
            x -= x % VPHAL_COMP_BLOCK_WIDTH;
        }

        y += VPHAL_COMP_BLOCK_HEIGHT;
        y -= y % VPHAL_COMP_BLOCK_HEIGHT;
    }

    VPHAL_RENDER_CHK_STATUS(pMhwMiInterface->AddMiBatchBufferEnd(nullptr, pBatchBuffer));

    if (pRenderHal->pfnUnlockBB(pRenderHal, pBatchBuffer) != MOS_STATUS_SUCCESS)
    {
        VPHAL_RENDER_ASSERTMESSAGE("Failed to unlock batch buffer.");
        bResult = false;
        goto finish;
    }

    bResult = true;

finish:
    if (pBatchBuffer && pBatchBuffer->bLocked)
    {
        // Only happens in Error cases
        VPHAL_RENDER_ASSERT(0);
        eStatus = pRenderHal->pfnUnlockBB(pRenderHal, pBatchBuffer);
        VPHAL_RENDER_ASSERT(eStatus == MOS_STATUS_SUCCESS);
        bResult = false;
    }
    return bResult;
}

//!
//! \brief    Judge whether  media walker pattern  will be vertical or not
//! \details  if input layer is one , and input is linear format and rotation 90
//!           or 270 is needed then the media walker pattern should be vertical
//! \param    [in] pRenderingData
//!           Pointer to Rendering Data
//! \return   bool
//!           Return true if vertical media pattern used, otherwise false
//!
bool CompositeState::MediaWalkerVertical(
    PVPHAL_RENDERING_DATA_COMPOSITE pRenderingData)
{
    PVPHAL_SURFACE  pSource;
    bool            bVertical     = false;

    pSource     = pRenderingData->pLayers[0];

    if (pRenderingData->iLayers == 1 &&
        pSource->TileType == MOS_TILE_LINEAR &&
       (pSource->Rotation == VPHAL_ROTATION_90 || pSource->Rotation == VPHAL_ROTATION_270))
    {
        bVertical = true;
    }

    return bVertical;
}

//!
//! \brief    Modify MediaWalker Static Data
//! \param    [in] pRenderingData
//!           Pointer to Rendering Data
//! \return   void
//!
void CompositeState::ModifyMediaWalkerStaticData(
    PVPHAL_RENDERING_DATA_COMPOSITE pRenderingData)
{
    MOS_UNUSED(pRenderingData);
}

//!
//! \brief    Render Composite BatchBuffer
//! \details  Render Composite BatchBuffer, fill Walker static data fields and set walker
//!           cmd params
//! \param    [in] pBatchBuffer
//!           Pointer to BatchBuffer
//! \param    [in] pRenderingData
//!           Pointer to Rendering Data
//! \param    [in] pWalkerParams
//!           Pointer to Walker parameters
//! \return   bool
//!           Return true if successful, otherwise false
//!
bool CompositeState::RenderBufferMediaWalker(
    PMHW_BATCH_BUFFER               pBatchBuffer,
    PVPHAL_RENDERING_DATA_COMPOSITE pRenderingData,
    PMHW_WALKER_PARAMS              pWalkerParams)
{
    PRENDERHAL_INTERFACE                pRenderHal;
    MEDIA_WALKER_KA2_STATIC_DATA        *pWalkerStatic;
    PVPHAL_BB_COMP_ARGS                 pBbArgs;
    bool                                bResult;
    int32_t                             iLayers;
    uint32_t                            uiMediaWalkerBlockSize;
    uint32_t*                           pdwDestXYTopLeft;
    uint32_t*                           pdwDestXYBottomRight;
    RECT                                AlignedRect;
    bool                                bVerticalPattern;

    MOS_UNUSED(pBatchBuffer);

    bResult          = false;
    pRenderHal       = m_pRenderHal;
    bVerticalPattern = false;
    pBbArgs          = &pRenderingData->BbArgs;
    pWalkerStatic    = &pRenderingData->WalkerStatic;

    VPHAL_RENDER_ASSERT(m_bFtrMediaWalker && !pBatchBuffer);

    pdwDestXYTopLeft     = (uint32_t*)(&pWalkerStatic->DW48);
    pdwDestXYBottomRight = (uint32_t*)(&pWalkerStatic->DW56);

    // GRF7.0-7, GRF8.0-7
    for (iLayers = 0;
         iLayers < pBbArgs->iLayers;
         iLayers++, pdwDestXYBottomRight++, pdwDestXYTopLeft++)
    {
        if (pRenderingData->pLayers[iLayers]->bXORComp)
        {
            // for cursor layer, every bit indicate 1 pixel. should extend the width as real output pixel.
            pBbArgs->rcDst[iLayers].right =
                pBbArgs->rcDst[iLayers].left + (pBbArgs->rcDst[iLayers].right - pBbArgs->rcDst[iLayers].left)*8;
        }

        *pdwDestXYTopLeft     = (pBbArgs->rcDst[iLayers].top    << 16 ) |
                                 pBbArgs->rcDst[iLayers].left;
        *pdwDestXYBottomRight = ((pBbArgs->rcDst[iLayers].bottom - 1) << 16 ) |
                                 (pBbArgs->rcDst[iLayers].right - 1);

        VPHAL_RENDER_NORMALMESSAGE("Scaling Info: layer %d, DestXTopLeft %d, DestYTopLeft %d, DestXBottomRight %d, DestYBottomRight %d",
            iLayers, pBbArgs->rcDst[iLayers].left, pBbArgs->rcDst[iLayers].top, pBbArgs->rcDst[iLayers].right - 1, pBbArgs->rcDst[iLayers].bottom - 1);
    }

    // GRF 9.0-4
    pWalkerStatic->DW64.MainVideoXScalingStepLeft                   =
        (float)pRenderingData->Inline.DW04.VideoXScalingStep;
    pWalkerStatic->DW65.VideoStepDeltaForNonLinearRegion            = 0;
    pWalkerStatic->DW66.StartofLinearScalingInPixelPositionC0       = 0;
    pWalkerStatic->DW66.StartofRHSNonLinearScalingInPixelPositionC1 = 0;
    pWalkerStatic->DW67.MainVideoXScalingStepCenter                 = 0;
    pWalkerStatic->DW68.MainVideoXScalingStepRight                  = 0;

    if (pRenderingData->pTarget[1] == nullptr)
    {
        pWalkerStatic->DW69.DestHorizontalBlockOrigin               =
            (uint16_t)pRenderingData->pTarget[0]->rcDst.left;
        pWalkerStatic->DW69.DestVerticalBlockOrigin                 =
            (uint16_t)pRenderingData->pTarget[0]->rcDst.top;
        AlignedRect   = pRenderingData->pTarget[0]->rcDst;
    }
    else
    {
        // Horizontal and Vertical base on non-rotated in case of dual output
        pWalkerStatic->DW69.DestHorizontalBlockOrigin               =
            (uint16_t)pRenderingData->pTarget[1]->rcDst.left;
        pWalkerStatic->DW69.DestVerticalBlockOrigin                 =
            (uint16_t)pRenderingData->pTarget[1]->rcDst.top;
        
        AlignedRect   = pRenderingData->pTarget[1]->rcDst;
    }

    ModifyMediaWalkerStaticData(pRenderingData);

    // Get media walker kernel block size
    uiMediaWalkerBlockSize = pRenderHal->pHwSizes->dwSizeMediaWalkerBlock;
    bVerticalPattern       = MediaWalkerVertical(pRenderingData);

    // Calculate aligned output area in order to determine the total # blocks
    // to process in case of non-16x16 aligned target.
    AlignedRect.right  += uiMediaWalkerBlockSize  - 1;
    AlignedRect.bottom += uiMediaWalkerBlockSize - 1;
    AlignedRect.left   -= AlignedRect.left   % uiMediaWalkerBlockSize;
    AlignedRect.top    -= AlignedRect.top    % uiMediaWalkerBlockSize;
    AlignedRect.right  -= AlignedRect.right  % uiMediaWalkerBlockSize;
    AlignedRect.bottom -= AlignedRect.bottom % uiMediaWalkerBlockSize;

    // Set walker cmd params - Rasterscan
    pWalkerParams->InterfaceDescriptorOffset    = pRenderingData->iMediaID;

    pWalkerParams->dwGlobalLoopExecCount                = 1;

    if (uiMediaWalkerBlockSize == 32)
    {
        pWalkerParams->ColorCountMinusOne = 3;
    }
    else
    {
        pWalkerParams->ColorCountMinusOne = 0;
    }

    if (AlignedRect.left !=0 || AlignedRect.top !=0)
    {
        // if the rect starts from any other macro  block other than the first
        // then the global resolution should be the whole frame and the global
        // start should be the rect start.
        pWalkerParams->GlobalResolution.x           =
            (AlignedRect.right / uiMediaWalkerBlockSize);
        pWalkerParams->GlobalResolution.y           =
            (AlignedRect.bottom / uiMediaWalkerBlockSize);
    }
    else
    {
        pWalkerParams->GlobalResolution.x           = pRenderingData->iBlocksX;
        pWalkerParams->GlobalResolution.y           = pRenderingData->iBlocksY;
    }

    pWalkerParams->GlobalStart.x                =
        (AlignedRect.left / uiMediaWalkerBlockSize);
    pWalkerParams->GlobalStart.y                =
        (AlignedRect.top / uiMediaWalkerBlockSize);

    pWalkerParams->GlobalOutlerLoopStride.x     = pRenderingData->iBlocksX;
    pWalkerParams->GlobalOutlerLoopStride.y     = 0;

    pWalkerParams->GlobalInnerLoopUnit.x        = 0;
    pWalkerParams->GlobalInnerLoopUnit.y        = pRenderingData->iBlocksY;

    pWalkerParams->BlockResolution.x            = pRenderingData->iBlocksX;
    pWalkerParams->BlockResolution.y            = pRenderingData->iBlocksY;

    pWalkerParams->LocalStart.x                 = 0;
    pWalkerParams->LocalStart.y                 = 0;

    if(bVerticalPattern)
    {
        pWalkerParams->LocalOutLoopStride.x         = 1;
        pWalkerParams->LocalOutLoopStride.y         = 0;

        pWalkerParams->LocalInnerLoopUnit.x         = 0;
        pWalkerParams->LocalInnerLoopUnit.y         = 1;

        pWalkerParams->dwLocalLoopExecCount         = pRenderingData->iBlocksX - 1;
        pWalkerParams->LocalEnd.x                   = 0;
        pWalkerParams->LocalEnd.y                   = pRenderingData->iBlocksY - 1;
    }
    else
    {
        pWalkerParams->LocalOutLoopStride.x         = 0;
        pWalkerParams->LocalOutLoopStride.y         = 1;

        pWalkerParams->LocalInnerLoopUnit.x         = 1;
        pWalkerParams->LocalInnerLoopUnit.y         = 0;

        pWalkerParams->dwLocalLoopExecCount         = pRenderingData->iBlocksY - 1;
        pWalkerParams->LocalEnd.x                   = pRenderingData->iBlocksX - 1;
        pWalkerParams->LocalEnd.y                   = 0;
    }

    bResult = true;

    return bResult;
}

//!
//! \brief    Render GpGpu Walker Buffer
//! \details  Render GpGpu Walker Buffer, fill Walker static data fields and set walker
//!           cmd params
//! \param    [in] pBatchBuffer
//!           Pointer to BatchBuffer
//! \param    [in] pRenderingData
//!           Pointer to Rendering Data
//! \param    [in] pWalkerParams
//!           Pointer to Walker parameters
//! \return   bool
//!           Return true if successful, otherwise false
//!
bool CompositeState::RenderBufferComputeWalker(
    PMHW_BATCH_BUFFER               pBatchBuffer,
    PVPHAL_RENDERING_DATA_COMPOSITE pRenderingData,
    PMHW_GPGPU_WALKER_PARAMS        pWalkerParams)
{
    PRENDERHAL_INTERFACE                pRenderHal;
    MEDIA_WALKER_KA2_STATIC_DATA        *pWalkerStatic;
    PVPHAL_BB_COMP_ARGS                 pBbArgs;
    bool                                bResult;
    int32_t                             iLayers;
    uint32_t                            uiMediaWalkerBlockSize;
    uint32_t*                           pdwDestXYTopLeft;
    uint32_t*                           pdwDestXYBottomRight;
    RECT                                AlignedRect;

    MOS_UNUSED(pBatchBuffer);

    bResult          = false;
    pRenderHal       = m_pRenderHal;
    pBbArgs          = &pRenderingData->BbArgs;
    pWalkerStatic    = &pRenderingData->WalkerStatic;

    VPHAL_RENDER_ASSERT(m_bFtrMediaWalker && !pBatchBuffer);

    pdwDestXYTopLeft     = (uint32_t*)(&pWalkerStatic->DW48);
    pdwDestXYBottomRight = (uint32_t*)(&pWalkerStatic->DW56);

    // GRF7.0-7, GRF8.0-7
    for (iLayers = 0;
         iLayers < pBbArgs->iLayers;
         iLayers++, pdwDestXYBottomRight++, pdwDestXYTopLeft++)
    {
        *pdwDestXYTopLeft     = (pBbArgs->rcDst[iLayers].top    << 16 ) |
                                 pBbArgs->rcDst[iLayers].left;
        *pdwDestXYBottomRight = ((pBbArgs->rcDst[iLayers].bottom - 1) << 16 ) |
                                 (pBbArgs->rcDst[iLayers].right - 1);

        VPHAL_RENDER_NORMALMESSAGE("Scaling Info: layer %d, DestXTopLeft %d, DestYTopLeft %d, DestXBottomRight %d, DestYBottomRight %d",
            iLayers, pBbArgs->rcDst[iLayers].left, pBbArgs->rcDst[iLayers].top, pBbArgs->rcDst[iLayers].right - 1, pBbArgs->rcDst[iLayers].bottom - 1);
    }

    // GRF 9.0-4
    pWalkerStatic->DW64.MainVideoXScalingStepLeft                   =
        (float)pRenderingData->Inline.DW04.VideoXScalingStep;
    pWalkerStatic->DW65.VideoStepDeltaForNonLinearRegion            = 0;
    pWalkerStatic->DW66.StartofLinearScalingInPixelPositionC0       = 0;
    pWalkerStatic->DW66.StartofRHSNonLinearScalingInPixelPositionC1 = 0;
    pWalkerStatic->DW67.MainVideoXScalingStepCenter                 = 0;
    pWalkerStatic->DW68.MainVideoXScalingStepRight                  = 0;

    if (pRenderingData->pTarget[1] == nullptr)
    {
        pWalkerStatic->DW69.DestHorizontalBlockOrigin                  =
             (uint16_t)pRenderingData->pTarget[0]->rcDst.left;
        pWalkerStatic->DW69.DestVerticalBlockOrigin                    =
             (uint16_t)pRenderingData->pTarget[0]->rcDst.top;

        AlignedRect   = pRenderingData->pTarget[0]->rcDst;
    }
    else
    {
        // Horizontal and Vertical base on non-rotated in case of dual output
        pWalkerStatic->DW69.DestHorizontalBlockOrigin                   =
            (uint16_t)pRenderingData->pTarget[1]->rcDst.left;
        pWalkerStatic->DW69.DestVerticalBlockOrigin                     =
             (uint16_t)pRenderingData->pTarget[1]->rcDst.top;

         AlignedRect   = pRenderingData->pTarget[1]->rcDst;
    }

    ModifyMediaWalkerStaticData(pRenderingData);

    // Get media walker kernel block size
    uiMediaWalkerBlockSize = pRenderHal->pHwSizes->dwSizeMediaWalkerBlock;

    // Calculate aligned output area in order to determine the total # blocks
    // to process in case of non-16x16 aligned target.
    AlignedRect.right  += uiMediaWalkerBlockSize  - 1;
    AlignedRect.bottom += uiMediaWalkerBlockSize - 1;
    AlignedRect.left   -= AlignedRect.left   % uiMediaWalkerBlockSize;
    AlignedRect.top    -= AlignedRect.top    % uiMediaWalkerBlockSize;
    AlignedRect.right  -= AlignedRect.right  % uiMediaWalkerBlockSize;
    AlignedRect.bottom -= AlignedRect.bottom % uiMediaWalkerBlockSize;

    // Set walker cmd params - Rasterscan
    pWalkerParams->InterfaceDescriptorOffset    = pRenderingData->iMediaID;

    pWalkerParams->GroupStartingX = (AlignedRect.left / uiMediaWalkerBlockSize);
    pWalkerParams->GroupStartingY = (AlignedRect.top / uiMediaWalkerBlockSize);
    pWalkerParams->GroupWidth     = pWalkerParams->GroupStartingX + pRenderingData->iBlocksX;
    pWalkerParams->GroupHeight    = pWalkerParams->GroupStartingY + pRenderingData->iBlocksY;

    pWalkerParams->ThreadWidth  = VPHAL_COMP_COMPUTE_WALKER_THREAD_SPACE_WIDTH;
    pWalkerParams->ThreadHeight = VPHAL_COMP_COMPUTE_WALKER_THREAD_SPACE_HEIGHT;
    pWalkerParams->ThreadDepth  = VPHAL_COMP_COMPUTE_WALKER_THREAD_SPACE_DEPTH;
    pWalkerParams->IndirectDataStartAddress = pRenderingData->iCurbeOffset;
    // Indirect Data Length is a multiple of 64 bytes (size of L3 cacheline). Bits [5:0] are zero.
    pWalkerParams->IndirectDataLength       = MOS_ALIGN_CEIL(pRenderingData->iCurbeLength, 1 << MHW_COMPUTE_INDIRECT_SHIFT);
    pWalkerParams->BindingTableID = pRenderingData->iBindingTable;

    bResult = true;

    PrintWalkerParas(pWalkerParams);
    return bResult;
}

//!
//! \brief    Adjust Params Based On Fc Limit
//! \param    [in,out] pCompParams
//!           Pointer to Composite parameters.
//! \return   bool
//!
bool CompositeState::AdjustParamsBasedOnFcLimit(
    PCVPHAL_RENDER_PARAMS pcRenderParam)
{
    //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.
    if (pcRenderParam->pColorFillParams == nullptr &&
        pcRenderParam->uSrcCount == 1 &&
        pcRenderParam->uDstCount == 1 &&
        pcRenderParam->pSrc[0] != nullptr &&
        pcRenderParam->pTarget[0] != nullptr)
    {
         if (pcRenderParam->pSrc[0]->rcDst.top >= pcRenderParam->pTarget[0]->rcDst.top &&
             pcRenderParam->pSrc[0]->rcDst.left >= pcRenderParam->pTarget[0]->rcDst.left &&
             pcRenderParam->pSrc[0]->rcDst.right <= pcRenderParam->pTarget[0]->rcDst.right &&
             pcRenderParam->pSrc[0]->rcDst.bottom <= pcRenderParam->pTarget[0]->rcDst.bottom)
         {
            VPHAL_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)",
                pcRenderParam->pTarget[0]->rcDst.left,
                pcRenderParam->pTarget[0]->rcDst.top,
                pcRenderParam->pTarget[0]->rcDst.right,
                pcRenderParam->pTarget[0]->rcDst.bottom,
                pcRenderParam->pSrc[0]->rcDst.left,
                pcRenderParam->pSrc[0]->rcDst.top,
                pcRenderParam->pSrc[0]->rcDst.right,
                pcRenderParam->pSrc[0]->rcDst.bottom);
            pcRenderParam->pTarget[0]->rcSrc = pcRenderParam->pSrc[0]->rcDst;
            pcRenderParam->pTarget[0]->rcDst = pcRenderParam->pSrc[0]->rcDst;
            return true;
         }
    }
    return false;
}

//!
//! \brief    Calculate Composite parameter and render data
//! \param    [in] pCompParams
//!           Pointer to Composite parameters. For both input and output.
//! \param    [in] pSource
//!           Pointer to surface. For both input and output.
//! \param    [in] pRenderingData
//!           Pointer to Composite RenderData. For both input and output.
//! \param    [out] pbColorfill
//!           Pointer to color fill flag.
//! \return   void
//!
void CompositeState::CalculateRenderData(
    PVPHAL_COMPOSITE_PARAMS         pCompParams,
    PVPHAL_SURFACE                  pSource,
    PVPHAL_RENDERING_DATA_COMPOSITE pRenderingData,
    bool*                           pbColorfill)
{
    // Check if Colorfill is required
    if ((pCompParams->pColorFillParams != nullptr) &&
        (!RECT1_CONTAINS_RECT2(pSource->rcDst, pCompParams->Target[0].rcDst)))
    {
        VPHAL_RENDER_NORMALMESSAGE("bColorfill enabled");
        *pbColorfill = true;
    }

    // Set HDC Direct Write Flag
    if (pCompParams->uSourceCount == 1                                          &&  // Single Layer
        pSource->ScalingMode == VPHAL_SCALING_AVS                               &&  // AVS
        !pSource->bInterlacedScaling                                            &&  // No interlace scaling
        IS_PA_FORMAT(pSource->Format)                                           &&  // Input Format is Packed
        (IS_PA_FORMAT(pCompParams->Target[0].Format) ||
         pCompParams->Target[0].Format == Format_NV12)                          &&  // Output format is Packed or 4:2:0
        pSource->Rotation == VPHAL_ROTATION_IDENTITY                            &&  // No Rotation
        !(*pbColorfill)                                                         &&  // No Colorfill
        pSource->pLumaKeyParams == nullptr                                      &&  // No Lumakey
        pSource->pProcampParams == nullptr                                      &&  // No Procamp
        pSource->pBlendingParams == nullptr                                     &&  // No Blending
        m_bKernelSupportHdcDW)                                                      // if HDC direct write is supported
    {
        VPHAL_RENDER_NORMALMESSAGE("bHdcDwEnable enabled");
        pRenderingData->bHdcDwEnable = true;
    }
}

//!
//! \brief    Perform multiple layer composite operation in one phase
//! \details  Perform multiple layer composite operation in one phase(scaling, blending,
//!           lumakey, CSC)
//! \param    [in,out] pCompParams
//!           Pointer to Composite parameters
//! \return   MOS_STATUS
//!           Return MOS_STATUS_SUCCESS if successful, otherwise failed
//!
MOS_STATUS CompositeState::RenderPhase(
    PVPHAL_COMPOSITE_PARAMS pCompParams)
{
    VPHAL_RENDERING_DATA_COMPOSITE  RenderingData           = {};
    PMOS_INTERFACE                  pOsInterface            = nullptr;
    PRENDERHAL_INTERFACE            pRenderHal              = nullptr;
    PMHW_BATCH_BUFFER               pBatchBuffer            = nullptr;
    Kdll_State                      *pKernelDllState        = nullptr;
    Kdll_CacheEntry                 *pKernelEntry           = nullptr;
    Kdll_CSC_Params                 *pCscParams             = nullptr;;
    Kdll_CSC_Matrix                 *pMatrix                = nullptr;;
    Kdll_Procamp                    *pProcamp               = nullptr;;
    int32_t                         iFilterSize             = 0;
    Kdll_FilterEntry                *pFilter                = nullptr;;
    uint32_t                        dwKernelHash            = 0;
    MOS_STATUS                      eStatus                 = MOS_STATUS_UNKNOWN;
    PVPHAL_SURFACE                  pSource                 = nullptr;
    PVPHAL_SURFACE                  *pSourceArray           = nullptr;
    PRENDERHAL_MEDIA_STATE          pMediaState             = nullptr;
    int32_t                         iBindingTableID         = 0;
    int32_t                         iLayer                  = 0;
    int32_t                         iRes                    = 0;
    MHW_WALKER_PARAMS               WalkerParams            = {};
    PMHW_WALKER_PARAMS              pWalkerParams           = nullptr;
    MHW_GPGPU_WALKER_PARAMS         ComputeWalkerParams     = {};
    PMHW_GPGPU_WALKER_PARAMS        pComputeWalkerParams    = nullptr;
    bool                            bKernelEntryUpdate      = false;
    bool                            bColorfill              = false;
    bool                            bEUFusedDispatchFlag    = false;

    VPHAL_RENDER_ASSERT(pCompParams);
    VPHAL_RENDER_ASSERT(m_pOsInterface);
    VPHAL_RENDER_ASSERT(m_pOsInterface->osCpInterface);
    VPHAL_RENDER_ASSERT(m_pRenderHal);
    VPHAL_RENDER_ASSERT(m_pKernelDllState);

    pOsInterface    = m_pOsInterface;
    pRenderHal      = m_pRenderHal;
    pKernelDllState = m_pKernelDllState;

    //VPHAL_DBG_STATE_DUMPPER_SET_CURRENT_STAGE(VPHAL_DBG_STAGE_COMP);

    // Check whether composition parameters are valid.
    VPHAL_RENDER_CHK_STATUS(IsCompositeParamsValid(*pCompParams));

    //============================
    // Allocate states for rendering
    //============================
    // Prepare for rendering
    VPHAL_RENDER_CHK_STATUS(RenderInit(
        pCompParams,
        &RenderingData));

    // Allocate and reset media state
    RenderingData.pMediaState = pMediaState =
                            pRenderHal->pfnAssignMediaState(pRenderHal, RENDERHAL_COMPONENT_COMP);
    VPHAL_RENDER_CHK_NULL(pMediaState);

    // Allocate and reset SSH instance
    VPHAL_RENDER_CHK_STATUS(pRenderHal->pfnAssignSshInstance(pRenderHal));

    // Allocate and reset BT
    VPHAL_RENDER_CHK_STATUS(pRenderHal->pfnAssignBindingTable(
               pRenderHal,
               &iBindingTableID));

    RenderingData.iBindingTable = iBindingTableID;

    //===============================
    // Setup params for each layer
    //===============================
    pSourceArray = pCompParams->pSource;
    for (iLayer = 0; iLayer < (int32_t)pCompParams->uSourceCount; iLayer++, pSourceArray++)
    {
        // Get next source
        pSource = *pSourceArray;

        // Check Scaling mode for 3D Sampler use case
        if (m_need3DSampler && pSource->ScalingMode == VPHAL_SCALING_AVS)
        {
            VPHAL_RENDER_NORMALMESSAGE("Modify ScalingMode to BILINREA from AVS due to 3D Sampler enabled");
            pSource->ScalingMode = VPHAL_SCALING_BILINEAR;
        }

        // Set scaling mode for the current layer
        if (pCompParams->pConstriction)
        {
            pSource->ScalingMode = VPHAL_SCALING_BILINEAR;
        }
        else
        {
            if (pSource->ScalingMode == VPHAL_SCALING_AVS &&
                pSource->SurfType == SURF_IN_PRIMARY)
            {
                m_bChromaUpSampling = VpHal_IsChromaUpSamplingNeeded(
                                                    pSource,
                                                    &pCompParams->Target[0]);
            }
            else if (m_need3DSampler                                       &&
                     pSource->ScalingMode != VPHAL_SCALING_AVS             &&
                     pSource->SurfType == SURF_IN_PRIMARY                  &&
                     ((IS_PL2_FORMAT(pSource->Format) && iLayer == 0)      || // when 3D sampler been used, PL2 chromasitting kernel does not support sub-layer chromasitting
                     pSource->Format == Format_YUY2))
            {
                m_bChromaUpSampling   = VpHal_IsChromaUpSamplingNeeded(
                                                    pSource,
                                                    &pCompParams->Target[0]);
                m_bChromaDownSampling = VpHal_IsChromaDownSamplingNeeded(
                                                    pSource,
                                                    &pCompParams->Target[0]);
            }
            else
            {
                m_bChromaUpSampling   = false;
                m_bChromaDownSampling = false;
            }

            SetScalingMode(
                pSource,
                pCompParams->uSourceCount);
        }

        // Get Allocation index of source for rendering
        if (pOsInterface->pfnRegisterResource(
                pOsInterface,
                &pSource->OsResource,
                false,
                true) != MOS_STATUS_SUCCESS)
        {
            eStatus = MOS_STATUS_UNKNOWN;
            goto finish;
        }

        // The parameter YOffset of surface state should be
        // a multiple of 4 when the input is accessed in field mode.For interlaced NV12
        // input, if its height is not a multiple of 4, the YOffset of UV plane will not
        // be a multiple of 4.So under this condition, we treat it as progressive input.
        if (VpHal_RndrCommonIsAlignmentWANeeded(
                pSource,
                pOsInterface->CurrentGpuContextOrdinal))
        {
            pSource->SampleType         = SAMPLE_PROGRESSIVE;
            pSource->bInterlacedScaling = false;
        }

        // If there is no scaling used for interlace surface on 10bit PA formats, force to progressive due to no supoort for kernel.
        if (pSource->bInterlacedScaling &&
            (pSource->rcSrc.right - pSource->rcSrc.left) == (pSource->rcDst.right - pSource->rcDst.left) &&
            (pSource->rcSrc.bottom - pSource->rcSrc.top) == (pSource->rcDst.bottom - pSource->rcDst.top) &&
            (pSource->Format == Format_Y210 || pSource->Format == Format_Y410))
        {
            pSource->SampleType = SAMPLE_PROGRESSIVE;
            pSource->bInterlacedScaling = false;
        }

        // Get Allocation index of reference for rendering
        if (pSource->bFieldWeaving && pSource->pBwdRef)
        {
            if (pOsInterface->pfnRegisterResource(
                    pOsInterface,
                    &pSource->pBwdRef->OsResource,
                    false,
                    true) != MOS_STATUS_SUCCESS)
            {
                eStatus = MOS_STATUS_UNKNOWN;
                goto finish;
            }
        }

        CalculateRenderData(pCompParams, pSource, &RenderingData, &bColorfill);

        // Setup rendering parameters for current layer
        iRes = SetLayer(
                    &RenderingData,
                    pSource,
                    iLayer,
                    pCompParams);
        if (iRes < 0)
        {
            VPHAL_RENDER_ASSERTMESSAGE("Failed to set layer parameters.");
            eStatus = MOS_STATUS_UNKNOWN;
            goto finish;
        }

        // Report mode
        if (pSource->SurfType == SURF_IN_PRIMARY)
        {
            SetReporting(pSource);
        }
    }

    // Get allocation index for render target Setup Surface States for Render Target
    for (iLayer = 0; iLayer < (int32_t)pCompParams->uTargetCount; iLayer++)
    {
        if (pOsInterface->pfnRegisterResource(
                pOsInterface,
                &pCompParams->Target[iLayer].OsResource,
                true,
                true) != MOS_STATUS_SUCCESS)
        {
            eStatus = MOS_STATUS_UNKNOWN;
            goto finish;
        }
    }

    // Setup rendering parameters for RT layer(s)
    iRes = SetLayerRT(
               &RenderingData,
               pCompParams);
    if (iRes < 0)
    {
         VPHAL_RENDER_ASSERTMESSAGE("Failed to set Render Target.");
         eStatus = MOS_STATUS_UNKNOWN;
         goto finish;
    }

    //============================
    // Create search filter for Dynamic Linking
    //============================
    pFilter = m_SearchFilter;
    MOS_ZeroMemory(pFilter, sizeof(m_SearchFilter));

    if (!BuildFilter(
             pCompParams,
             pFilter,
             &iFilterSize))
    {
        VPHAL_RENDER_ASSERTMESSAGE("Failed to create filter description.");
        eStatus = MOS_STATUS_UNIMPLEMENTED;
        goto finish;
    }

    //Log for debug
    for (int32_t i = 0; i < iFilterSize; i++)
    {
        Kdll_FilterEntry *pTempFilter = (pFilter + i);

        if (pTempFilter == nullptr)
            continue;

        VPHAL_RENDER_NORMALMESSAGE("Kernel Search Filter %d: layer %d, format %d, cspace %d, \
                                   bEnableDscale %d, bIsDitherNeeded %d, chromasiting %d, colorfill %d, dualout %d, \
                                   lumakey %d, procamp %d, RenderMethod %d, sampler %d, samplerlumakey %d ",
                                   i, pTempFilter->layer, pTempFilter->format, pTempFilter->cspace,
                                   pTempFilter->bEnableDscale, pTempFilter->bIsDitherNeeded,
                                   pTempFilter->chromasiting, pTempFilter->colorfill,  pTempFilter->dualout,
                                   pTempFilter->lumakey, pTempFilter->procamp, pTempFilter->RenderMethod, pTempFilter->sampler, pTempFilter->samplerlumakey);
    }

    //============================
    // KERNEL SEARCH
    //============================
    dwKernelHash = KernelDll_SimpleHash(pFilter, iFilterSize * sizeof(Kdll_FilterEntry));
    pKernelEntry = KernelDll_GetCombinedKernel(pKernelDllState, pFilter, iFilterSize, dwKernelHash);

    if (pKernelEntry)
    {
        pCscParams = pKernelEntry->pCscParams;
        pMatrix    = &pCscParams->Matrix[pCscParams->MatrixID[0]];
        pKernelDllState->colorfill_cspace = pKernelEntry->colorfill_cspace;

        if ((pMatrix->iProcampID != DL_PROCAMP_DISABLED) &&
            (pMatrix->iProcampID < m_iMaxProcampEntries))
        {
            pProcamp           = &(m_Procamp[pMatrix->iProcampID]);
            bKernelEntryUpdate = (pProcamp->iProcampVersion != pMatrix->iProcampVersion) ? true : false;
        }
    }

    if (!pKernelEntry || bKernelEntryUpdate)
    {
        Kdll_SearchState *pSearchState = &m_KernelSearch;

        // Remove kernel entry from kernel caches
        if (bKernelEntryUpdate && pKernelEntry)
        {
            KernelDll_ReleaseHashEntry(&(pKernelDllState->KernelHashTable), pKernelEntry->wHashEntry);
            KernelDll_ReleaseCacheEntry(&(pKernelDllState->KernelCache), pKernelEntry);
        }

        // Setup kernel search
        pKernelDllState->pfnStartKernelSearch(
            pKernelDllState,
            pSearchState,
            pFilter,
            iFilterSize,
            1);

        // Search kernel
        if (!pKernelDllState->pfnSearchKernel(pKernelDllState, pSearchState))
        {
            VPHAL_RENDER_ASSERTMESSAGE("Failed to find a kernel.");
            eStatus = MOS_STATUS_UNKNOWN;
            goto finish;
        }

        // Build kernel
        if (!pKernelDllState->pfnBuildKernel(pKernelDllState, pSearchState))
        {
            VPHAL_RENDER_ASSERTMESSAGE("Failed to build kernel.");
            eStatus = MOS_STATUS_UNKNOWN;
            goto finish;
        }

        // Load resulting kernel into kernel cache
        pKernelEntry = KernelDll_AddKernel(
                           pKernelDllState,
                           pSearchState,
                           pFilter,
                           iFilterSize,
                           dwKernelHash);

        if (!pKernelEntry)
        {
            VPHAL_RENDER_ASSERTMESSAGE("Failed to store kernel in local cache.");
            eStatus = MOS_STATUS_UNKNOWN;
            goto finish;
        }
    }
    else
    {
        VPHAL_RENDER_NORMALMESSAGE("Use previous kernel list.");
    }

    RenderingData.bCmFcEnable  = pKernelDllState->bEnableCMFC ? true : false;

    RenderingData.bAlphaCalculateEnable = pCompParams->bAlphaCalculateEnable;

    RenderingData.pKernelEntry = pKernelEntry;
    RenderingData.pProcamp     = m_Procamp;

    //============================
    // Return RT Primaries to the app
    //============================
    if (pFilter[iFilterSize - 1].layer == Layer_RenderTarget)
    {
        pSource = &pCompParams->Target[0];
        switch (pFilter[iFilterSize - 1].cspace)
        {
            case CSpace_xvYCC709:
                pSource->ExtendedGamut = true;
                pSource->ColorSpace    = CSpace_BT709;
                break;
            case CSpace_BT709:
                pSource->ExtendedGamut = false;
                pSource->ColorSpace    = CSpace_BT709;
                break;
            case CSpace_BT709_FullRange:
                pSource->ExtendedGamut = false;
                pSource->ColorSpace    = CSpace_BT709_FullRange;
                break;
            case CSpace_xvYCC601:
                pSource->ExtendedGamut = true;
                pSource->ColorSpace    = CSpace_BT601;
                break;
            case CSpace_BT601:
                pSource->ExtendedGamut = false;
                pSource->ColorSpace    = CSpace_BT601;
                break;
            case CSpace_BT601_FullRange:
                pSource->ExtendedGamut = false;
                pSource->ColorSpace    = CSpace_BT601_FullRange;
                break;
            case CSpace_BT2020:
                pSource->ExtendedGamut = false;
                pSource->ColorSpace    = CSpace_BT2020;
                break;
            case CSpace_BT2020_FullRange:
                pSource->ExtendedGamut = false;
                pSource->ColorSpace    = CSpace_BT2020_FullRange;
                break;
            case CSpace_BT2020_RGB:
                pSource->ExtendedGamut = false;
                pSource->ColorSpace    = CSpace_BT2020_RGB;
                break;
            case CSpace_BT2020_stRGB:
                pSource->ExtendedGamut = false;
                pSource->ColorSpace    = CSpace_BT2020_stRGB;
                break;
            default:
                pSource->ExtendedGamut = false;
                pSource->ColorSpace    = CSpace_sRGB;
                break;
        }
    }

    // Set Fused EU Dispatch
    if (m_FusedEuDispatch && pRenderHal->pRenderHalPltInterface != nullptr)
    {
        pRenderHal->pRenderHalPltInterface->SetFusedEUDispatch(true);
        bEUFusedDispatchFlag = true;
    }

    if (m_bFtrMediaWalker && (!m_bFtrComputeWalker))
    {
        pBatchBuffer  = nullptr;
        pWalkerParams = &WalkerParams;

        MOS_ZeroMemory(&WalkerParams, sizeof(WalkerParams));

        // calculates media object walker static data fields
        if (!RenderBufferMediaWalker(
                 pBatchBuffer,
                 &RenderingData,
                 &WalkerParams))
        {
            VPHAL_RENDER_ASSERTMESSAGE("Failed to render media walker batch.");
            eStatus = MOS_STATUS_UNKNOWN;
            goto finish;
        }

        // Send Media states for compositing
        if (!SubmitStates(&RenderingData))
        {
            VPHAL_RENDER_ASSERTMESSAGE("Failed to submit compositing states.");
            eStatus = MOS_STATUS_UNKNOWN;
            goto finish;
        }

        // The VfeScoreboard is set after Vphal_CompSubmitStates calls pRenderHal->pfnSetVfeStateParams()
        pWalkerParams->UseScoreboard  = pRenderHal->VfeScoreboard.ScoreboardEnable;
        pWalkerParams->ScoreboardMask = pRenderHal->VfeScoreboard.ScoreboardMask;
    }
    else if (m_bFtrComputeWalker)
    {
        pBatchBuffer         = nullptr;
        pWalkerParams        = nullptr;
        pComputeWalkerParams = &ComputeWalkerParams;

        MOS_ZeroMemory(&ComputeWalkerParams, sizeof(ComputeWalkerParams));

        // calculates media object walker static data fields
        if (!RenderBufferComputeWalker(
                 pBatchBuffer,
                 &RenderingData,
                 &ComputeWalkerParams))
        {
            VPHAL_RENDER_ASSERTMESSAGE("Failed to render media walker batch.");
            eStatus = MOS_STATUS_UNKNOWN;
            goto finish;
        }

        // Send Media states for compositing
        if (!SubmitStates(&RenderingData))
        {
            VPHAL_RENDER_ASSERTMESSAGE("Failed to submit compositing states.");
            eStatus = MOS_STATUS_UNKNOWN;
            goto finish;
        }
    }
    else
    {
        // Send Media states for compositing
        if (!SubmitStates(&RenderingData))
        {
            VPHAL_RENDER_ASSERTMESSAGE("Failed to submit compositing states.");
            eStatus = MOS_STATUS_UNKNOWN;
            goto finish;
        }

        // Get a valid batch buffer (find a match if possible)
        VPHAL_RENDER_CHK_STATUS(AllocateBuffer(&RenderingData, &pBatchBuffer));

        // No match was found - render a new batch buffer
        if (!((PVPHAL_BATCH_BUFFER_PARAMS)pBatchBuffer->pPrivateData)->bMatch)
        {
            if (!RenderBuffer(
                     pBatchBuffer,
                     &RenderingData))
            {
                VPHAL_RENDER_ASSERTMESSAGE("Failed to render batch buffers.");
                eStatus = MOS_STATUS_UNKNOWN;
                goto finish;
            }
        }

        // Set CallID to avoid BB reuse in the same call
        ((PVPHAL_BATCH_BUFFER_PARAMS)pBatchBuffer->pPrivateData)->iCallID = m_iCallID;
    }

    // Enable extra PIPE_CONTROL in command buffer for CMFC Coeff Surface update
    if (RenderingData.bCmFcEnable)
    {
        pRenderHal->bCmfcCoeffUpdate  = true;
        pRenderHal->pCmfcCoeffSurface = &m_CmfcCoeff.OsResource;
    }
    else
    {
        pRenderHal->bCmfcCoeffUpdate  = false;
        pRenderHal->pCmfcCoeffSurface = nullptr;
    }

    VPHAL_DBG_STATE_DUMPPER_DUMP_GSH(pRenderHal);
    VPHAL_DBG_STATE_DUMPPER_DUMP_SSH(pRenderHal);
    VPHAL_DBG_STATE_DUMPPER_DUMP_BATCH_BUFFER(pRenderHal, pBatchBuffer);

    VPHAL_RENDER_CHK_STATUS(VpHal_RndrSubmitCommands(
        pRenderHal,
        pBatchBuffer,
        m_bNullHwRenderComp,
        pWalkerParams,
        pComputeWalkerParams,
        &m_StatusTableUpdateParams,
        kernelCombinedFc,
        m_KernelSearch.KernelCount,
        m_KernelSearch.KernelID,
        m_bLastPhase));

finish:
    // clean rendering data
    if (bEUFusedDispatchFlag)
    {
        // Reset Fused EU Dispatch
        pRenderHal->pRenderHalPltInterface->SetFusedEUDispatch(false);
    }
    CleanRenderingData(&RenderingData);
    pRenderHal->bCmfcCoeffUpdate  = false;
    pRenderHal->pCmfcCoeffSurface = nullptr;
    return eStatus;
}

//!
//! \brief    Build filter description for dynamic linking
//! \details  Build filter description(render method, current layer, layer format, layer
//!           rotation, layer colorspace, sampling mode, scaling mode, luma key, blending,
//!           colorfill, procamp, CSC) for dynamic linking
//!           parameters
//! \param    [in] pCompParams
//!           Pointer to Composite parameters
//! \param    [out] pFilter
//!           Pointer to first filter entry
//! \param    [out] piFilterSize
//!           Pointer to filter size
//! \return   bool
//!           Return true if successful, otherwise false
//!
bool CompositeState::BuildFilter(
    PVPHAL_COMPOSITE_PARAMS         pCompParams,
    PKdll_FilterEntry               pFilter,
    int32_t*                        piFilterSize)
{
    PVPHAL_SURFACE              pSrc;
    VPHAL_CSPACE                cspace_main;
    int32_t                     iMaxFilterSize;
    bool                        bColorFill, bLumaKey;
    int32_t                     i;
    PRECT                       pTargetRect;
    RENDERHAL_SURFACE           RenderHalSurface;
    bool                        bNeed;
    MOS_STATUS                  eStatus = MOS_STATUS_SUCCESS;

    VPHAL_RENDER_ASSERT(pCompParams);
    VPHAL_RENDER_ASSERT(pFilter);
    VPHAL_RENDER_ASSERT(piFilterSize);

    cspace_main    = CSpace_sRGB;                   // Default colorspace
    *piFilterSize  = 0;
    iMaxFilterSize = DL_MAX_SEARCH_FILTER_SIZE - 1; // Save one entry for Render Target
    pTargetRect    = &(pCompParams->Target[0].rcDst);

    // Initialize ColorFill flag
    bColorFill = (pCompParams->pColorFillParams != nullptr);

    for (i = 0; (i < (int)pCompParams->uSourceCount) && (iMaxFilterSize > 0); i++)
    {
        pSrc = pCompParams->pSource[i];

        //--------------------------------
        // Skip non-visible layers
        //--------------------------------
        if (pSrc->iLayerID < 0)
        {
            continue;
        }

        //--------------------------------
        // Composition path does not support conversion from BT2020->BT601/BT709, BT601/BT709 -> BT2020
        //--------------------------------
        if (IS_COLOR_SPACE_BT2020(pSrc->ColorSpace) &&
            !IS_COLOR_SPACE_BT2020(pCompParams->Target[0].ColorSpace)) //BT2020->BT601/BT709
        {
            eStatus = MOS_STATUS_UNIMPLEMENTED;
        }
        else if (!IS_COLOR_SPACE_BT2020(pSrc->ColorSpace) &&
                 IS_COLOR_SPACE_BT2020(pCompParams->Target[0].ColorSpace))  //BT601/BT709 -> BT2020
        {
            eStatus = MOS_STATUS_UNIMPLEMENTED;
        }

        if (eStatus == MOS_STATUS_UNIMPLEMENTED)
        {
            goto finish;
        }

        //--------------------------------
        // Set render method
        //--------------------------------
        pFilter->RenderMethod = m_bFtrMediaWalker ? RenderMethod_MediaObjectWalker : RenderMethod_MediaObject;

        //--------------------------------
        // Set CSC coefficient setting method for CoeffID_0
        //--------------------------------
        pFilter->SetCSCCoeffMode = m_bFtrCSCCoeffPatchMode ? SetCSCCoeffMethod_Patch : SetCSCCoeffMethod_Curbe;

        //--------------------------------
        // Set current layer
        //--------------------------------
        pFilter->layer = g_cSurfaceType_Layer[pSrc->SurfType];

        //--------------------------------
        // Set layer format
        //--------------------------------
        pFilter->format = pSrc->Format;

        // On G8, NV12 format needs the width and Height to be a multiple of 4 for both
        // 3D sampler and 8x8 sampler; G75 needs the width of NV12 input surface to be
        // a multiple of 4 for 3D sampler; G9 does not has such restriction; to simplify the
        // implementation, we enable 2 plane NV12 for all of the platform when the width
        // or Height is not a multiple of 4. Here to set the filter format in order to select
        // the PL2 kernel when building the combined kernel.
        VPHAL_RENDER_CHK_STATUS(VpHal_RndrCommonInitRenderHalSurface(pSrc, &RenderHalSurface));
        bNeed = m_pRenderHal->pfnIs2PlaneNV12Needed(
                m_pRenderHal,
                &RenderHalSurface,
                RENDERHAL_SS_BOUNDARY_SRCRECT) ? true : false;
        bNeed |= IsNV12SamplerLumakeyNeeded(pSrc, m_pRenderHal) && i;
        if (bNeed)
        {
            if (pFilter->format == Format_NV12)
            {
                pFilter->format = Format_NV12_UnAligned;
            }
            else if (pFilter->format == Format_P208)
            {
                pFilter->format = Format_P208_UnAligned;
            }
            else if (pFilter->format == Format_NV11)
            {
                pFilter->format = Format_NV11_UnAligned;
            }
            else if (pFilter->format == Format_PL2)
            {
                pFilter->format = Format_PL2_UnAligned;
            }
        }

        // Y_Uoffset(Height*2 + Height/2) of RENDERHAL_PLANES_YV12 define Bitfield_Range(0, 13) on gen9+.
        // The max value is 16383. So use PL3 kernel to avoid out of range when Y_Uoffset is larger than 16383.
        // Use PL3 plane to avoid YV12 blending issue with DI enabled and U channel shift issue with not 4-aligned height
        if (pFilter->format == Format_YV12)
        {
            if (m_pOsInterface->trinityPath == TRINITY9_ENABLED)
            {
                pFilter->format = Format_PL3;
            }
            else if ((pSrc->ScalingMode != VPHAL_SCALING_AVS) &&
                     (pSrc->bIEF != true) &&
                     (pSrc->SurfType != SURF_OUT_RENDERTARGET) &&
                     m_pRenderHal->bEnableYV12SinglePass &&
                     !pSrc->pDeinterlaceParams &&
                     !pSrc->bInterlacedScaling &&
                     MOS_IS_ALIGNED(pSrc->dwHeight, 4) &&
                     ((pSrc->dwHeight * 2 + pSrc->dwHeight / 2) < RENDERHAL_MAX_YV12_PLANE_Y_U_OFFSET_G9))
            {
                pFilter->format = Format_YV12_Planar;
            }
        }

        if (pFilter->format == Format_A8R8G8B8 ||
            pFilter->format == Format_X8R8G8B8 ||
            pFilter->format == Format_A8B8G8R8 ||
            pFilter->format == Format_X8B8G8R8 ||
            pFilter->format == Format_R5G6B5)
        {
            pFilter->format = Format_RGB;
        }

        //--------------------------------
        // Set layer rotation
        //--------------------------------
        pFilter->rotation = MEDIA_ROTATION(pSrc->Rotation);

        //--------------------------------
        // Set layer color space
        //--------------------------------
        // Source is palletized, leave CSC to software (driver)
        if (IS_PAL_FORMAT(pFilter->format))
        {
            pFilter->cspace = CSpace_Any;
        }
        // Source is YUV or RGB, set primaries
        else
        {
            pFilter->cspace = pSrc->ColorSpace;
        }

        // Save color space of main video
        if (pSrc->SurfType == SURF_IN_PRIMARY)
        {
            cspace_main = pFilter->cspace;
        }

        //--------------------------------
        // Set sampling mode
        //--------------------------------
        bLumaKey = (pSrc->pLumaKeyParams != nullptr);

        // Progressive main video (except RGB format) or for RGB10, use AVS
        if (pSrc->bUseSampleUnorm)
        {
            pFilter->sampler = (pSrc->bInterlacedScaling || pSrc->bFieldWeaving) ? Sample_iScaling : Sample_Scaling;
        }
        else
        {
            pFilter->sampler = (pSrc->ScalingMode == VPHAL_SCALING_AVS && !IsBobDiEnabled(pSrc)) ?
                (pSrc->bInterlacedScaling ? Sample_iScaling_AVS : Sample_Scaling_AVS) :
                (pSrc->bInterlacedScaling || pSrc->bFieldWeaving) ? Sample_iScaling_034x : Sample_Scaling_034x;
        }

        // When input format is Format_R10G10B10A2/Format_B10G10R10A2/Y410(kernel regards Y410 as Format_R10G10B10A2)
        // Dscale kernel should be used
        if (pSrc->Format == Format_R10G10B10A2 ||
            pSrc->Format == Format_B10G10R10A2 ||
            pSrc->Format == Format_Y410        ||
            pSrc->Format == Format_Y416)
        {
            pFilter->bEnableDscale = true;
        }
        else
        {
            pFilter->bEnableDscale = false;
        }

        if (m_bFtrComputeWalker)
        {
            pFilter->bWaEnableDscale = true;
        }
        else
        {
            pFilter->bWaEnableDscale = MEDIA_IS_WA(m_pWaTable, WaEnableDscale);
        }

        //--------------------------------
        // Set Luma key
        //--------------------------------
        if (bLumaKey)
        {
            pFilter->lumakey = LumaKey_True;
            pFilter->samplerlumakey = pSrc->bUseSamplerLumakey ? LumaKey_True : LumaKey_False;
        }
        else
        {
            pFilter->lumakey = LumaKey_False;
            pFilter->samplerlumakey = LumaKey_False;
        }

        //--------------------------------
        // Select function
        //--------------------------------
        if (pSrc->pBlendingParams != nullptr)
        {
            switch (pSrc->pBlendingParams->BlendType)
            {
                case BLEND_SOURCE:
                    if (IS_ALPHA4_FORMAT(pSrc->Format))
                    {
                        pFilter->process = Process_SBlend_4bits;
                    }
                    else
                    {
                        pFilter->process = Process_SBlend;
                    }
                    break;

                case BLEND_PARTIAL:
                    pFilter->process = Process_PBlend;
                    break;

                case BLEND_CONSTANT:
                    pFilter->process = Process_CBlend;
                    break;

                case BLEND_CONSTANT_SOURCE:
                    pFilter->process = Process_CSBlend;
                    break;

                case BLEND_CONSTANT_PARTIAL:
                    pFilter->process = Process_CPBlend;
                    break;

                case BLEND_XOR_MONO:
                    pFilter->process = Process_XORComposite;
                    break;

                case BLEND_NONE:
                default:
                    pFilter->process = Process_Composite;
                    break;
            }
        }
        else
        {
            pFilter->process = Process_Composite;
        }

        if (pFilter->samplerlumakey && pFilter->process != Process_Composite)
        {
            VPHAL_RENDER_ASSERTMESSAGE("Invalid kll processing for sampler lumakey! Sampler lumakey can only work with composition.");
            pFilter->samplerlumakey = LumaKey_False;
        }

        //--------------------------------
        // Set color fill
        //--------------------------------
        if (*piFilterSize == 0 &&
            (bLumaKey ||
             (bColorFill && (!RECT1_CONTAINS_RECT2(pSrc->rcDst, pCompParams->Target[0].rcDst))) ||
             (!pCompParams->bForceSkipColorFill &&
             ((pFilter->process == Process_PBlend) ||
              (pFilter->process == Process_CBlend) ||
              (pFilter->process == Process_SBlend) ||
              (pFilter->process == Process_CSBlend)))))
        {
            pFilter->colorfill = ColorFill_True;
        }
        else
        {
            pFilter->colorfill = ColorFill_False;
        }

        //--------------------------------
        // Set Procamp parameters
        //--------------------------------
        if (pSrc->pProcampParams && pSrc->pProcampParams->bEnabled)
        {
            pFilter->procamp = 0;
        }
        else
        {
            pFilter->procamp = DL_PROCAMP_DISABLED;
        }

        //--------------------------------
        // Set chromasiting parameters
        //--------------------------------
        pFilter->chromasiting = DL_CHROMASITING_DISABLE;
        if (pSrc->bChromaSiting)
        {
            pFilter->chromasiting = 0 ;
        }

        //--------------------------------
        // reset CSC
        //--------------------------------
        pFilter->matrix = DL_CSC_DISABLED;

        if (0 == pSrc->iLayerID)
        {
           //set first layer's scalingRatio
           SetFilterScalingRatio(&(pFilter->ScalingRatio));
        }

        // Update filter
        pFilter++;
        (*piFilterSize)++;
        iMaxFilterSize--;
    }

    //-----------------------------------------
    // Set Render Target parameters
    //-----------------------------------------
    if (pCompParams->uTargetCount == 2)
    {
        pFilter->dualout = true;
    }
    pSrc = &pCompParams->Target[0];
    pFilter->RenderMethod    = m_bFtrMediaWalker ? RenderMethod_MediaObjectWalker : RenderMethod_MediaObject;
    pFilter->SetCSCCoeffMode = m_bFtrCSCCoeffPatchMode ? SetCSCCoeffMethod_Patch : SetCSCCoeffMethod_Curbe;
    pFilter->layer    = Layer_RenderTarget;
    pFilter->format   = pSrc->Format;
    pFilter->tiletype = pSrc->TileType;
    pFilter->sampler  = Sample_None;
    pFilter->process  = Process_None;
    pFilter->procamp  = DL_PROCAMP_DISABLED;
    pFilter->matrix   = DL_CSC_DISABLED;
    pFilter->bFillOutputAlphaWithConstant = true;

    //set rendertarget's scalingRatio
    SetFilterScalingRatio(&(pFilter->ScalingRatio));

    if(pCompParams->pSource[0] != nullptr &&
       pCompParams->pSource[0]->Format == Format_R5G6B5 &&
       pCompParams->Target[0].Format == Format_R5G6B5)
    {
        pFilter->bIsDitherNeeded = false;
    }else
    {
        pFilter->bIsDitherNeeded = true;
    }

    if (pFilter->format == Format_A8R8G8B8    ||
        pFilter->format == Format_A8B8G8R8    ||
        pFilter->format == Format_R10G10B10A2 ||
        pFilter->format == Format_B10G10R10A2 ||
        pFilter->format == Format_AYUV        ||
        pFilter->format == Format_Y416)
    {
        if (pCompParams->pCompAlpha != nullptr && pCompParams->pSource[0] != nullptr &&
            (pCompParams->pCompAlpha->AlphaMode == VPHAL_ALPHA_FILL_MODE_NONE ||
             pCompParams->pCompAlpha->AlphaMode == VPHAL_ALPHA_FILL_MODE_SOURCE_STREAM))
        {
            // When layer 0 does not have alpha channel, Save_RGB will be linked instead of
            // Save_ARGB, to avoid output alpha value corruption.
            switch (pCompParams->pSource[0]->Format)
            {
                case Format_AYUV:
                case Format_AUYV:
                case Format_AI44:
                case Format_IA44:
                case Format_A8R8G8B8:
                case Format_A8B8G8R8:
                case Format_R10G10B10A2:
                case Format_B10G10R10A2:
                case Format_A8P8:
                case Format_A8:
                case Format_Y416:
                case Format_Y410:
                    pFilter->bFillOutputAlphaWithConstant = false;
                    break;

                default:
                    break;
            }
        }
    }

    // If Rotation is done in sampler. Multiple phases are not required.
    if ((!m_bSamplerSupportRotation) &&
        (pCompParams->uSourceCount > 0))
    {
        // either single layer L0 or all layer with the same rotation degree.
        pFilter->rotation = MEDIA_ROTATION(pCompParams->pSource[0]->Rotation);
    }

    //-------------------------------------------------------
    // Set color fill for RT. Valid for colorfill only cases
    //-------------------------------------------------------
    // If filter size is zero i.e. number of layers is zero, set colorfill to true.
    if (*piFilterSize == 0)
    {
        if(bColorFill)
        {
            pFilter->colorfill = ColorFill_True;
        }
        else
        {
            eStatus = MOS_STATUS_UNIMPLEMENTED;
            goto finish;
        }
    }
    else
    {
        pFilter->colorfill = ColorFill_False;
    }

    // Get App supplied RT format
    pFilter->cspace = pSrc->ColorSpace;

    // Update filter
    (*piFilterSize)++;

finish:
    return ((eStatus == MOS_STATUS_SUCCESS) ? true : false);
}

//!
//! \brief    Initialize Colorfill parameters
//! \details  Initialize Colorfill parameters
//! \return   void
//!
void CompositeState::InitColorFillParams()
{
    m_csSrc.dwValue   = 0;
    m_csDst.dwValue   = 0;
    m_CSpaceSrc       = CSpace_None;
    m_CSpaceDst       = CSpace_None;
}

//!
//! \brief    Check if sample unorm being used for source surface.
//! \param    [in] pCompParams
//!           Pointer to Composite parameters
//! \param    pSrc
//!           [in] Pointer to Source Surface
//! \return   bool
//!           Return TRUE if use sample unorm, otherwise FALSE
//!
bool CompositeState::IsUsingSampleUnorm(
    PVPHAL_COMPOSITE_PARAMS         pCompParams,
    PVPHAL_SURFACE                  pSrc)
{
    float                       fStepX = 0, fStepY = 0;
    float                       fAdjustX = 0, fAdjustY = 0;
    bool                        bRet;
    PRECT                       pTargetRect = {0};

    if (nullptr == pCompParams || nullptr == pSrc)
    {
        VPHAL_RENDER_ASSERTMESSAGE("nullptr for input parameters");
        bRet = false;
        goto finish;
    }

    // Force using sampler16 when compute walker in use
    if (m_bFtrComputeWalker)
    {
        bRet = false;
        goto finish;
    }

    pTargetRect    = &(pCompParams->Target[0].rcDst);
    if (pCompParams->pConstriction)
    {
        fAdjustX = (pTargetRect->right  - pTargetRect->left) * 1.0f /
            pCompParams->pConstriction->right;
        fAdjustY = (pTargetRect->bottom - pTargetRect->top ) * 1.0f /
            pCompParams->pConstriction->bottom;
    }
    else
    {
        fAdjustX = fAdjustY = 1.0f;
    }
    // Calculate scaling factor for X and Y (include BOB DI)
    if (pSrc->Rotation == VPHAL_ROTATION_IDENTITY ||
        pSrc->Rotation == VPHAL_ROTATION_180      ||
        pSrc->Rotation == VPHAL_MIRROR_HORIZONTAL ||
        pSrc->Rotation == VPHAL_MIRROR_VERTICAL)
    {
        fStepX = (pSrc->rcSrc.right  - pSrc->rcSrc.left) * fAdjustX /
                    ((pSrc->rcDst.right  - pSrc->rcDst.left) > 0 ?
                    (pSrc->rcDst.right  - pSrc->rcDst.left) : 1);
        fStepY = (pSrc->rcSrc.bottom - pSrc->rcSrc.top ) * fAdjustY /
                    ((pSrc->rcDst.bottom - pSrc->rcDst.top ) > 0 ?
                    (pSrc->rcDst.bottom - pSrc->rcDst.top ) : 1);
    }
    else
    {
        // VPHAL_ROTATION_90 || VPHAL_ROTATION_270 ||
        fStepX = (pSrc->rcSrc.right  - pSrc->rcSrc.left) * fAdjustX /
                    ((pSrc->rcDst.bottom - pSrc->rcDst.top ) > 0 ?
                    (pSrc->rcDst.bottom - pSrc->rcDst.top ) : 1);
        fStepY = (pSrc->rcSrc.bottom - pSrc->rcSrc.top ) * fAdjustY /
                    ((pSrc->rcDst.right  - pSrc->rcDst.left) > 0 ?
                    (pSrc->rcDst.right  - pSrc->rcDst.left) : 1);
    }

    if (IsBobDiEnabled(pSrc) &&
        pSrc->ScalingMode != VPHAL_SCALING_AVS)
    {
        fStepY *= 0.5f;
    }

    // Progressive main video (except RGB format) or for RGB10, use AVS
    if ((pSrc->ScalingMode == VPHAL_SCALING_AVS) &&
        !IsBobDiEnabled(pSrc))
    {
        // GEN8 cannot support YV12 input format for iAVS scaling
        if (pSrc->bInterlacedScaling && !m_bYV12iAvsScaling && pSrc->Format == Format_YV12)
        {
            bRet = true;
            goto finish;
        }
        else
        {
            bRet = false;  // AVS
            goto finish;
        }
    }
    else
    {
        if (pSrc->Format == Format_R10G10B10A2   ||
            pSrc->Format == Format_B10G10R10A2   ||
            pSrc->Format == Format_Y410          ||
            pSrc->Format == Format_Y416)
        {
            bRet = false;  // DScaler
            goto finish;
        }
        else if (fStepX >= 3.0f || fStepY >= 3.0f)
        {
            return !MEDIA_IS_WA(m_pWaTable, WaEnableDscale);
        }
        else
        {
            bRet = true;
            goto finish;
        }
    }

finish:
    return bRet;
}

//!
//! \brief    Check if sampler lumakey being supported or not for source surface.
//! \param    pSrc
//!           [in] Pointer to Source Surface
//! \return   bool
//!           Return TRUE if support, otherwise FALSE
//!
bool CompositeState::IsSamplerLumakeySupported(PVPHAL_SURFACE pSrc)
{
    // The kernel is different b/w sampler luma key and EU computed luma key.
    // Sampler based: IDR_VP_Prepare_LumaKey_SampleUnorm
    // EU computed:   IDR_VP_Compute_Lumakey
    // When sampler lumakey being enabled by set pUnormSampler->DW1.ChromakeyEnable to 1, a lumakey mask will be generated
    // during sampler scaling.
    // IDR_VP_Prepare_LumaKey_SampleUnorm is used to prepare lumakey related parameters for composition according to the
    // lumakey mask, and the result will be put in the common registers. To avoid the result being overwriten by other
    // operation, IDR_VP_Prepare_LumaKey_SampleUnorm need to be called rigth before IDR_VP_Call_Composite.
    // Following are the conditions to enable sampler lumakey.
    // 1 Flag m_bEnableSamplerLumakey is set to true.
    // 2 Lumakey is needed for current layer.
    // 3 Enable sampler lumakey only for composition.
    // 4 Disable sampler lumakey if there's no AVS as back up for layer 0
    // 5 Enable sampler lumakey only on YUY2 and NV12 surfaces due to hw limitation.
    // 6 Enable sampler lumakey feature only if this lumakey layer is not the bottom layer.
    // 7 Enable sampler lumakey only when sample unorm being used.
    // 8 Disable sampler lumakey for mirror/rotation case
    //   not matching the layer any more.
    return m_bEnableSamplerLumakey                                                              &&
            pSrc->pLumaKeyParams != NULL                                                        &&
            (pSrc->pBlendingParams == NULL || pSrc->pBlendingParams->BlendType == BLEND_NONE)   &&
            !m_need3DSampler                                                                    &&
            (pSrc->Format == Format_YUY2 || pSrc->Format == Format_NV12)                        &&
            pSrc->iLayerID                                                                      &&
            pSrc->bUseSampleUnorm                                                               &&
            pSrc->Rotation == VPHAL_ROTATION_IDENTITY;
}

//!
//! \brief    Initialize Composite state
//! \details  Initialize Composite state, including setup KernelDLL/Procamp/Colorfill
//! \param    [in] pSettings
//!           Pointer to VPHAL Settings
//! \param    [in] pKernelDllState
//!           Pointer to KernelDLL State
//! \return   MOS_STATUS
//!           Return MOS_STATUS_SUCCESS if successful
//!
MOS_STATUS CompositeState::Initialize(
    const VphalSettings             *pSettings,
    Kdll_State                      *pKernelDllState)
{
    MOS_NULL_RENDERING_FLAGS        NullRenderingFlags;
    bool                            bAllocated;
    MOS_STATUS                      eStatus;
    Mos_MemPool                     memTypeSurfVdieoMem = MOS_MEMPOOL_VIDEOMEMORY;

    eStatus = MOS_STATUS_SUCCESS;

    MOS_UNUSED(pSettings);
    VPHAL_RENDER_CHK_NULL(pKernelDllState);

    if (m_reporting == nullptr)
    {
        m_reporting = MOS_New(VphalFeatureReport);
    }

    if (MEDIA_IS_SKU(m_pSkuTable, FtrLimitedLMemBar))
    {
        memTypeSurfVdieoMem = MOS_MEMPOOL_DEVICEMEMORY;
    }

#if (_DEBUG || _RELEASE_INTERNAL)
    // Read user feature key to enable 8-tap adaptive filter;
    ReadUserSettingForDebug(
        m_userSettingPtr,
        m_b8TapAdaptiveEnable,
        __VPHAL_COMP_8TAP_ADAPTIVE_ENABLE,
        MediaUserSetting::Group::Sequence);
#endif

    NullRenderingFlags = m_pOsInterface->pfnGetNullHWRenderFlags(
                        m_pOsInterface);

    m_bNullHwRenderComp =
                    NullRenderingFlags.VPComp ||
                    NullRenderingFlags.VPGobal;

    // Setup kernelDLLL
    m_pKernelDllState = pKernelDllState;

    if (m_pKernelDllState->bEnableCMFC)
    {
        // Allocate auto CSC Coeff Surface
        VPHAL_RENDER_CHK_STATUS(VpHal_ReAllocateSurface(
            m_pOsInterface,
            &m_CmfcCoeff,
            "CSCCoeffSurface",
            Format_L8,
            MOS_GFXRES_2D,
            MOS_TILE_LINEAR,
            VPHAL_COMP_CMFC_COEFF_WIDTH,
            VPHAL_COMP_CMFC_COEFF_HEIGHT,
            false,
            MOS_MMC_DISABLED,
            &bAllocated,
            MOS_HW_RESOURCE_USAGE_VP_INTERNAL_READ_RENDER,
            MOS_TILE_UNSET_GMM,
            memTypeSurfVdieoMem,
            VPP_INTER_RESOURCE_NOTLOCKABLE));
    }

    // Setup Procamp Parameters
    KernelDll_SetupProcampParameters(pKernelDllState,
                                     m_Procamp,
                                     m_iMaxProcampEntries);

    // Init Color fill params
    InitColorFillParams();

finish:
    return eStatus;
}

//!
//! \brief    Composite Destructor
//!
CompositeState::~CompositeState()
{
}

//!
//! \brief    Composite Destroy function
//! \details  Destroy resource allocated by Composite
//!
void CompositeState::Destroy()
{
    PRENDERHAL_INTERFACE                pRenderHal;
    PMOS_INTERFACE                      pOsInterface;
    PMHW_BATCH_BUFFER                   pBuffer;
    int32_t                             i;

    VPHAL_RENDER_ASSERT(m_pRenderHal);
    VPHAL_RENDER_ASSERT(m_pOsInterface);

    pRenderHal   = m_pRenderHal;
    pOsInterface = m_pOsInterface;

    // Destroy Batch Buffers
    for (i = 0; i < m_iBatchBufferCount; i++)
    {
        pBuffer = &m_BatchBuffer[i];
        pRenderHal->pfnFreeBB(pRenderHal, pBuffer);
    }

    // Free intermediate compositing buffer

    if (m_Intermediate2 && m_Intermediate2->pBlendingParams)
    {
        MOS_FreeMemory(m_Intermediate2->pBlendingParams);
        m_Intermediate2->pBlendingParams = nullptr;
    }

    if (pOsInterface)
    {
        if (m_Intermediate)
        {
            pOsInterface->pfnFreeResource(
                pOsInterface,
                &m_Intermediate->OsResource);
        }
        if (m_Intermediate1)
        {
            pOsInterface->pfnFreeResource(
                pOsInterface,
                &m_Intermediate1->OsResource);
        }
        if (m_Intermediate2)
        {
            pOsInterface->pfnFreeResource(
                pOsInterface,
                &m_Intermediate2->OsResource);
        }

        pOsInterface->pfnFreeResource(
            pOsInterface,
            &m_AuxiliarySyncSurface.OsResource);

        pOsInterface->pfnFreeResource(
            pOsInterface,
            &m_CmfcCoeff.OsResource);
    }

    // Destroy sampler 8x8 state table parameters
    VpHal_RndrCommonDestroyAVSParams(&m_AvsParameters);
}

//! \brief    Initialize interface for Composite
//! \param    [in] pOsInterface
//!           Pointer to MOS interface structure
//! \param    [in] pRenderHal
//!           Pointer to RenderHal interface structure
//! \param    [in] pPerfData
//!           Pointer to performance data structure
//! \param    [in] compositeCacheCntl
//!           Composite Cache Control Data
//! \return   MOS_STATUS
//!           Return MOS_STATUS_SUCCESS if successful, otherwise failed
//!
CompositeState::CompositeState(
    PMOS_INTERFACE                      pOsInterface,
    PRENDERHAL_INTERFACE                pRenderHal,
    PVPHAL_RNDR_PERF_DATA               pPerfData,
    const VPHAL_COMPOSITE_CACHE_CNTL    &compositeCacheCntl,
    MOS_STATUS                          *peStatus)
    : RenderState(pOsInterface, pRenderHal, pPerfData, peStatus),
    m_iMaxProcampEntries(0),
    m_iProcampVersion(0),
    m_bNullHwRenderComp(false),
    m_b8TapAdaptiveEnable(false),
    m_ThreadCountPrimary(0),
    m_iBatchBufferCount(0),
    m_iCallID(0),
    m_bLastPhase(false),
    m_fSamplerLinearBiasX(0),
    m_fSamplerLinearBiasY(0),
    m_bFtrMediaWalker(false),
    m_bFtrComputeWalker(false),
    m_bFtrCSCCoeffPatchMode(false),
    m_bSamplerSupportRotation(false),
    m_bChromaUpSampling(false),
    m_bChromaDownSampling(false),
    m_bFallbackIefPatch(false),
    m_bKernelSupportDualOutput(false),
    m_bKernelSupportHdcDW(false),
    m_bApplyTwoLayersCompOptimize(false),
    m_need3DSampler(false),
    m_bEnableSamplerLumakey(false),
    m_bYV12iAvsScaling(false),
    m_bAvsTableCoeffExtraEnabled(false),
    m_bAvsTableBalancedFilter(false)
{
    MOS_STATUS                  eStatus = MOS_STATUS_SUCCESS;
    bool       ftrCSCCoeffPatchMode = false;

    MOS_ZeroMemory(&m_Procamp, sizeof(m_Procamp));
    MOS_ZeroMemory(&m_csSrc, sizeof(m_csSrc));
    MOS_ZeroMemory(&m_csDst, sizeof(m_csDst));
    MOS_ZeroMemory(&m_CSpaceSrc, sizeof(m_CSpaceSrc));
    MOS_ZeroMemory(&m_CSpaceDst, sizeof(m_CSpaceDst));
    MOS_ZeroMemory(&m_SurfMemObjCtl, sizeof(m_SurfMemObjCtl));
    MOS_ZeroMemory(&m_SearchFilter, sizeof(m_SearchFilter));
    MOS_ZeroMemory(&m_KernelSearch, sizeof(m_KernelSearch));
    MOS_ZeroMemory(&m_KernelParams, sizeof(m_KernelParams));
    MOS_ZeroMemory(&m_IntermediateSurface, sizeof(m_IntermediateSurface));
    MOS_ZeroMemory(&m_IntermediateSurface1, sizeof(m_IntermediateSurface1));
    MOS_ZeroMemory(&m_IntermediateSurface2, sizeof(m_IntermediateSurface2));
    MOS_ZeroMemory(&m_CmfcCoeff, sizeof(m_CmfcCoeff));
    MOS_ZeroMemory(&m_RenderHalCmfcCoeff, sizeof(m_RenderHalCmfcCoeff));
    MOS_ZeroMemory(&m_AvsParameters, sizeof(m_AvsParameters));
    MOS_ZeroMemory(&m_mhwSamplerAvsTableParam, sizeof(m_mhwSamplerAvsTableParam));
    MOS_ZeroMemory(&m_BatchBuffer, sizeof(m_BatchBuffer));
    MOS_ZeroMemory(&m_BufferParam, sizeof(m_BufferParam));

    // Set Bilinear Sampler Bias
    m_fSamplerLinearBiasX       = VPHAL_SAMPLER_BIAS_GEN575;
    m_fSamplerLinearBiasY       = VPHAL_SAMPLER_BIAS_GEN575;

    // Batch buffers
    m_iBatchBufferCount         = 0;

    // Procamp
    // Set Max number of procamp entries
    m_iMaxProcampEntries        = VPHAL_MAX_PROCAMP;
    m_iProcampVersion           = 1;

    //CSCCoeffPatchMode
    m_bFtrCSCCoeffPatchMode     = true;

    // Cache settings
    m_SurfMemObjCtl             = compositeCacheCntl;

    // Composite Kernel
    m_KernelParams              = g_cInitKernelParamsComposite;
    m_ThreadCountPrimary        = VPHAL_USE_MEDIA_THREADS_MAX;
    VPHAL_RENDER_CHK_NULL(pRenderHal);
    m_bFtrMediaWalker           = pRenderHal->pfnGetMediaWalkerStatus(pRenderHal) ? true : false;

    MOS_ZeroMemory(&m_mhwSamplerAvsTableParam, sizeof(m_mhwSamplerAvsTableParam));

    VPHAL_RENDER_CHK_NULL(pOsInterface);
    // Reset Intermediate output surface (multiple phase)
    if (m_Intermediate)
    {
        pOsInterface->pfnResetResourceAllocationIndex(pOsInterface, &m_Intermediate->OsResource);
    }
    if (m_Intermediate1)
    {
        pOsInterface->pfnResetResourceAllocationIndex(pOsInterface, &m_Intermediate1->OsResource);
    }
    if (m_Intermediate2)
    {
        pOsInterface->pfnResetResourceAllocationIndex(pOsInterface, &m_Intermediate2->OsResource);
    }

    ReadUserSetting(
        m_userSettingPtr,
        ftrCSCCoeffPatchMode,
        __MEDIA_USER_FEATURE_VALUE_CSC_COEFF_PATCH_MODE_DISABLE,
        MediaUserSetting::Group::Sequence);
    m_bFtrCSCCoeffPatchMode = ftrCSCCoeffPatchMode ? false : true;

finish:
    // copy status to output argument to pass status to caller
    if (peStatus)
    {
        *peStatus = eStatus;
    }
}

//!
//! \brief    Judge if Composite render is needed
//! \details  Check Render parameter/data if Composite render needed
//! \param    [in] pcRenderParams
//!           Pointer to Render parameters
//! \param    [in,out] pRenderPassData
//!           Pointer to Render data
//! \return   bool
//!           true if meeded. Else false
//!
// use set render flags
bool CompositeState::IsNeeded(
    PCVPHAL_RENDER_PARAMS  pcRenderParams,
    RenderpassData         *pRenderPassData)
{
    VPHAL_RENDER_ASSERT(pRenderPassData);

    MOS_UNUSED(pcRenderParams);

    return pRenderPassData->bCompNeeded;
}

//!
//! \brief    Print walkerParas
//! \param    [in] PMHW_GPGPU_WALKER_PARAMS
//!
void CompositeState::PrintWalkerParas(PMHW_GPGPU_WALKER_PARAMS pWalkerParams)
{
#if (_DEBUG || _RELEASE_INTERNAL)
    if (pWalkerParams == nullptr)
    {
        VPHAL_RENDER_ASSERTMESSAGE("The WalkerParams pointer is null");
        return;
    }
    VPHAL_RENDER_VERBOSEMESSAGE("WalkerParams: InterfaceDescriptorOffset = %x, GpGpuEnable = %x, ThreadWidth = %x, ThreadHeight = %x, ThreadDepth = %x, GroupWidth = %x, GroupHeight = %x, GroupDepth = %x, GroupStartingX = %x, GroupStartingY = %x, GroupStartingZ = %x, SLMSize = %x, IndirectDataLength = %x, IndirectDataStartAddress = %x, BindingTableID = %x",
        pWalkerParams->InterfaceDescriptorOffset,
        pWalkerParams->GpGpuEnable,
        pWalkerParams->ThreadWidth,
        pWalkerParams->ThreadHeight,
        pWalkerParams->ThreadDepth,
        pWalkerParams->GroupWidth,
        pWalkerParams->GroupHeight,
        pWalkerParams->GroupDepth,
        pWalkerParams->GroupStartingX,
        pWalkerParams->GroupStartingY,
        pWalkerParams->GroupStartingZ,
        pWalkerParams->SLMSize,
        pWalkerParams->IndirectDataLength,
        pWalkerParams->IndirectDataStartAddress,
        pWalkerParams->BindingTableID);
#endif
}

//!
//! \brief    Print SampleParams
//! \param    [in] PMHW_SAMPLER_STATE_PARAM
//!
void CompositeState::PrintSamplerParams(PMHW_SAMPLER_STATE_PARAM pSamplerParams)
{
#if (_DEBUG || _RELEASE_INTERNAL)
    if (pSamplerParams == nullptr)
    {
        VPHAL_RENDER_ASSERTMESSAGE("The SamplerParams pointer is null");
        return;
    }
    if (pSamplerParams->SamplerType == MHW_SAMPLER_TYPE_3D)
    {
        VPHAL_RENDER_VERBOSEMESSAGE("SamplerParams: bInUse = %x, SamplerType = %x, ElementType = %x, SamplerFilterMode = %x, MagFilter = %x, MinFilter = %x",
            pSamplerParams->bInUse,
            pSamplerParams->SamplerType,
            pSamplerParams->ElementType,
            pSamplerParams->Unorm.SamplerFilterMode,
            pSamplerParams->Unorm.MagFilter,
            pSamplerParams->Unorm.MinFilter);
        VPHAL_RENDER_VERBOSEMESSAGE("SamplerParams: AddressU = %x, AddressV = %x, AddressW = %x, SurfaceFormat = %x, BorderColorRedU = %x, BorderColorGreenU = %x",
            pSamplerParams->Unorm.AddressU,
            pSamplerParams->Unorm.AddressV,
            pSamplerParams->Unorm.AddressW,
            pSamplerParams->Unorm.SurfaceFormat,
            pSamplerParams->Unorm.BorderColorRedU,
            pSamplerParams->Unorm.BorderColorGreenU);
        VPHAL_RENDER_VERBOSEMESSAGE("SamplerParams: BorderColorBlueU = %x, BorderColorAlphaU = %x, IndirectStateOffset = %x, bBorderColorIsValid = %x, bChromaKeyEnable = %x, ChromaKeyIndex = %x, ChromaKeyMode = %x",
            pSamplerParams->Unorm.BorderColorBlueU,
            pSamplerParams->Unorm.BorderColorAlphaU,
            pSamplerParams->Unorm.IndirectStateOffset,
            pSamplerParams->Unorm.bBorderColorIsValid,
            pSamplerParams->Unorm.bChromaKeyEnable,
            pSamplerParams->Unorm.ChromaKeyIndex,
            pSamplerParams->Unorm.ChromaKeyMode);
    }
    else
    {
        VPHAL_RENDER_VERBOSEMESSAGE("SamplerParams: bInUse = %x, SamplerType = %x, ElementType = %x",
            pSamplerParams->bInUse,
            pSamplerParams->SamplerType,
            pSamplerParams->ElementType);
    }
#endif
}

//!
//! \brief    Print curbe data for legacy path
//! \param    [in] MEDIA_WALKER_KA2_STATIC_DATA *
//!
void CompositeState::PrintCurbeData(MEDIA_OBJECT_KA2_STATIC_DATA *pObjectStatic)
{
#if (_DEBUG || _RELEASE_INTERNAL)
    if (pObjectStatic == nullptr)
    {
        VPHAL_RENDER_ASSERTMESSAGE("The ObjectStatic pointer is null");
        return;
    }
    VPHAL_RENDER_VERBOSEMESSAGE("CurbeData: DW00.Value = %x",pObjectStatic->DW00.Value);
    VPHAL_RENDER_VERBOSEMESSAGE("CurbeData:     CscConstantC0 = %x, CscConstantC1 = %x, LocalDifferenceThresholdU = %x, LocalDifferenceThresholdV = %x, SobelEdgeThresholdU = %x, SobelEdgeThresholdV = %x",
        pObjectStatic->DW00.CscConstantC0,
        pObjectStatic->DW00.CscConstantC1,
        pObjectStatic->DW00.LocalDifferenceThresholdU,
        pObjectStatic->DW00.LocalDifferenceThresholdV,
        pObjectStatic->DW00.SobelEdgeThresholdU,
        pObjectStatic->DW00.SobelEdgeThresholdV);
    VPHAL_RENDER_VERBOSEMESSAGE("CurbeData: DW01.Value = %x",pObjectStatic->DW01.Value);
    VPHAL_RENDER_VERBOSEMESSAGE("CurbeData:     CscConstantC2 = %x, CscConstantC3 = %x, HistoryInitialValueU = %x, HistoryInitialValueV = %x, HistoryMaxU = %x, HistoryMaxV = %x",
        pObjectStatic->DW01.CscConstantC2,
        pObjectStatic->DW01.CscConstantC3,
        pObjectStatic->DW01.HistoryInitialValueU,
        pObjectStatic->DW01.HistoryInitialValueV,
        pObjectStatic->DW01.HistoryMaxU,
        pObjectStatic->DW01.HistoryMaxV);
    VPHAL_RENDER_VERBOSEMESSAGE("CurbeData: DW02.Value = %x", pObjectStatic->DW02.Value);
    VPHAL_RENDER_VERBOSEMESSAGE("CurbeData:     CscConstantC4 = %x, CscConstantC5 = %x, HistoryDeltaU = %x, HistoryDeltaV = %x, NSADThresholdU = %x, DNSADThresholdV = %x",
        pObjectStatic->DW02.CscConstantC4,
        pObjectStatic->DW02.CscConstantC5,
        pObjectStatic->DW02.HistoryDeltaU,
        pObjectStatic->DW02.HistoryDeltaV,
        pObjectStatic->DW02.DNSADThresholdU,
        pObjectStatic->DW02.DNSADThresholdV);
    VPHAL_RENDER_VERBOSEMESSAGE("CurbeData: DW03.Value = %x", pObjectStatic->DW03.Value);
    VPHAL_RENDER_VERBOSEMESSAGE("CurbeData:     CscConstantC6 = %x, CscConstantC7 = %x, DNTDThresholdU = %x, HistoryDeltaV = %x, DNLTDThresholdU = %x, DNLTDThresholdV = %x",
        pObjectStatic->DW03.CscConstantC6,
        pObjectStatic->DW03.CscConstantC7,
        pObjectStatic->DW03.DNTDThresholdU,
        pObjectStatic->DW03.DNTDThresholdV,
        pObjectStatic->DW03.DNLTDThresholdU,
        pObjectStatic->DW03.DNLTDThresholdV);
    VPHAL_RENDER_VERBOSEMESSAGE("CurbeData: DW04.Value = %x", pObjectStatic->DW04.Value);
    VPHAL_RENDER_VERBOSEMESSAGE("CurbeData:     CscConstantC8 = %x, CscConstantC9 = %x",
        pObjectStatic->DW04.CscConstantC8,
        pObjectStatic->DW04.CscConstantC9);
    VPHAL_RENDER_VERBOSEMESSAGE("CurbeData: DW05.Value = %x", pObjectStatic->DW05.Value);
    VPHAL_RENDER_VERBOSEMESSAGE("CurbeData:     CscConstantC10 = %x, CscConstantC11 = %x",
        pObjectStatic->DW05.CscConstantC10,
        pObjectStatic->DW05.CscConstantC11);
    VPHAL_RENDER_VERBOSEMESSAGE("CurbeData: DW06.Value = %x", pObjectStatic->DW06.Value);
    VPHAL_RENDER_VERBOSEMESSAGE("CurbeData:     ConstantBlendingAlphaLayer1 = %d, ConstantBlendingAlphaLayer2 = %d, ConstantBlendingAlphaLayer3 = %d, ConstantBlendingAlphaLayer4 = %d, HalfStatisticsSurfacePitch = %d, StatisticsSurfaceHeight = %d",
        pObjectStatic->DW06.ConstantBlendingAlphaLayer1,
        pObjectStatic->DW06.ConstantBlendingAlphaLayer2,
        pObjectStatic->DW06.ConstantBlendingAlphaLayer3,
        pObjectStatic->DW06.ConstantBlendingAlphaLayer4,
        pObjectStatic->DW06.HalfStatisticsSurfacePitch,
        pObjectStatic->DW06.StatisticsSurfaceHeight);
    VPHAL_RENDER_VERBOSEMESSAGE("CurbeData: DW07.Value = %x", pObjectStatic->DW07.Value);
    VPHAL_RENDER_VERBOSEMESSAGE("CurbeData:     ConstantBlendingAlphaLayer5 = %d, ConstantBlendingAlphaLayer6 = %d, ConstantBlendingAlphaLayer7 = %d, PointerToInlineParameters = %d, ConstantBlendingAlphaLayer51 = %d, ConstantBlendingAlphaLayer61 = %d, ConstantBlendingAlphaLayer71 = %d, OutputDepth = %d, TopFieldFirst = %d",
        pObjectStatic->DW07.ConstantBlendingAlphaLayer5,
        pObjectStatic->DW07.ConstantBlendingAlphaLayer6,
        pObjectStatic->DW07.ConstantBlendingAlphaLayer7,
        pObjectStatic->DW07.PointerToInlineParameters,
        pObjectStatic->DW07.ConstantBlendingAlphaLayer51,
        pObjectStatic->DW07.ConstantBlendingAlphaLayer61,
        pObjectStatic->DW07.ConstantBlendingAlphaLayer71,
        pObjectStatic->DW07.OutputDepth,
        pObjectStatic->DW07.TopFieldFirst);
    VPHAL_RENDER_VERBOSEMESSAGE("CurbeData: DW08.Value = %x", pObjectStatic->DW08.Value);
    VPHAL_RENDER_VERBOSEMESSAGE("CurbeData:     DestinationRectangleWidth = %d, DestinationRectangleHeight = %d",
        pObjectStatic->DW08.DestinationRectangleWidth,
        pObjectStatic->DW08.DestinationRectangleHeight);
    VPHAL_RENDER_VERBOSEMESSAGE("CurbeData: DW09.Value = %x", pObjectStatic->DW09.Value);
    VPHAL_RENDER_VERBOSEMESSAGE("CurbeData:     RotationMirrorMode = %d, RotationMirrorAllLayer = %d, DualOutputMode = %d, ChannelSwap = %d",
        pObjectStatic->DW09.RotationMirrorMode,
        pObjectStatic->DW09.RotationMirrorAllLayer,
        pObjectStatic->DW09.DualOutputMode,
        pObjectStatic->DW09.ChannelSwap);
    VPHAL_RENDER_VERBOSEMESSAGE("CurbeData: DW10.Value = %x", pObjectStatic->DW10.Value);
    VPHAL_RENDER_VERBOSEMESSAGE("CurbeData:     ChromaSitingLocation = %d",
        pObjectStatic->DW10.ObjKa2Gen9.ChromaSitingLocation);
    VPHAL_RENDER_VERBOSEMESSAGE("CurbeData: DW11.Value = %x", pObjectStatic->DW11.Value);
    VPHAL_RENDER_VERBOSEMESSAGE("CurbeData: DW12.Value = %x", pObjectStatic->DW12.Value);
    VPHAL_RENDER_VERBOSEMESSAGE("CurbeData:     ColorProcessingEnable = %d, MessageFormat = %d, ColorProcessingStatePointer = %x",
        pObjectStatic->DW12.ColorProcessingEnable,
        pObjectStatic->DW12.MessageFormat,
        pObjectStatic->DW12.ColorProcessingStatePointer);
    VPHAL_RENDER_VERBOSEMESSAGE("CurbeData: DW13.Value = %x", pObjectStatic->DW13.Value);
    VPHAL_RENDER_VERBOSEMESSAGE("CurbeData:     ColorFill_R = %x, ColorFill_G = %x, ColorFill_B = %x, ColorFill_A = %x, ColorFill_V = %x, ColorFill_Y = %x, ColorFill_U = %x",
        pObjectStatic->DW13.ColorFill_R,
        pObjectStatic->DW13.ColorFill_G,
        pObjectStatic->DW13.ColorFill_B,
        pObjectStatic->DW13.ColorFill_A,
        pObjectStatic->DW13.ColorFill_V,
        pObjectStatic->DW13.ColorFill_Y,
        pObjectStatic->DW13.ColorFill_U);
    VPHAL_RENDER_VERBOSEMESSAGE("CurbeData: DW14.Value = %x", pObjectStatic->DW14.Value);
    VPHAL_RENDER_VERBOSEMESSAGE("CurbeData:     LumakeyLowThreshold = %x, LumakeyHighThreshold = %x, NLASEnable = %d, Reserved = %d",
        pObjectStatic->DW14.LumakeyLowThreshold,
        pObjectStatic->DW14.LumakeyHighThreshold,
        pObjectStatic->DW14.NLASEnable,
        pObjectStatic->DW14.Reserved);
    VPHAL_RENDER_VERBOSEMESSAGE("CurbeData: DW15.Value = %x", pObjectStatic->DW15.Value);
    VPHAL_RENDER_VERBOSEMESSAGE("CurbeData:     DestinationPackedYOffset = %d, DestinationPackedUOffset = %d, DestinationPackedVOffset = %d, DestinationRGBFormat = %d",
        pObjectStatic->DW15.DestinationPackedYOffset,
        pObjectStatic->DW15.DestinationPackedUOffset,
        pObjectStatic->DW15.DestinationPackedVOffset,
        pObjectStatic->DW15.DestinationRGBFormat);
    VPHAL_RENDER_VERBOSEMESSAGE("CurbeData: DW16.Value = %x", pObjectStatic->DW16.Value);
    VPHAL_RENDER_VERBOSEMESSAGE("CurbeData:     HorizontalScalingStepRatioLayer0 = 0x%x",
        pObjectStatic->DW16.HorizontalScalingStepRatioLayer0);
    VPHAL_RENDER_VERBOSEMESSAGE("CurbeData: DW17.Value = %x", pObjectStatic->DW17.Value);
    VPHAL_RENDER_VERBOSEMESSAGE("CurbeData:     HorizontalScalingStepRatioLayer1 = 0x%x",
        pObjectStatic->DW17.HorizontalScalingStepRatioLayer1);
    VPHAL_RENDER_VERBOSEMESSAGE("CurbeData: DW18.Value = %x", pObjectStatic->DW18.Value);
    VPHAL_RENDER_VERBOSEMESSAGE("CurbeData:     HorizontalScalingStepRatioLayer2 = 0x%x",
        pObjectStatic->DW18.HorizontalScalingStepRatioLayer2);
    VPHAL_RENDER_VERBOSEMESSAGE("CurbeData: DW19.Value = %x", pObjectStatic->DW19.Value);
    VPHAL_RENDER_VERBOSEMESSAGE("CurbeData:     HorizontalScalingStepRatioLayer3 = 0x%x",
        pObjectStatic->DW19.HorizontalScalingStepRatioLayer3);
    VPHAL_RENDER_VERBOSEMESSAGE("CurbeData: DW20.Value = %x", pObjectStatic->DW20.Value);
    VPHAL_RENDER_VERBOSEMESSAGE("CurbeData:     HorizontalScalingStepRatioLayer4 = 0x%x",
        pObjectStatic->DW20.HorizontalScalingStepRatioLayer4);
    VPHAL_RENDER_VERBOSEMESSAGE("CurbeData: DW21.Value = %x", pObjectStatic->DW21.Value);
    VPHAL_RENDER_VERBOSEMESSAGE("CurbeData:     HorizontalScalingStepRatioLayer5 = 0x%x",
        pObjectStatic->DW21.HorizontalScalingStepRatioLayer5);
    VPHAL_RENDER_VERBOSEMESSAGE("CurbeData: DW22.Value = %x", pObjectStatic->DW22.Value);
    VPHAL_RENDER_VERBOSEMESSAGE("CurbeData:     HorizontalScalingStepRatioLayer6 = 0x%x",
        pObjectStatic->DW22.HorizontalScalingStepRatioLayer6);
    VPHAL_RENDER_VERBOSEMESSAGE("CurbeData: DW23.Value = %x", pObjectStatic->DW23.Value);
    VPHAL_RENDER_VERBOSEMESSAGE("CurbeData:    HorizontalScalingStepRatioLayer7 = 0x%x",
        pObjectStatic->DW23.HorizontalScalingStepRatioLayer7);
    VPHAL_RENDER_VERBOSEMESSAGE("CurbeData: DW24.Value = %x", pObjectStatic->DW24.Value);
    VPHAL_RENDER_VERBOSEMESSAGE("CurbeData:     VerticalScalingStepRatioLayer0 = 0x%x, SourcePackedYOffset = %d, SourcePackedUOffset = %d, SourcePackedVOffset = %d, Reserved = %d",
        pObjectStatic->DW24.VerticalScalingStepRatioLayer0,
        pObjectStatic->DW24.SourcePackedYOffset,
        pObjectStatic->DW24.SourcePackedUOffset,
        pObjectStatic->DW24.SourcePackedVOffset,
        pObjectStatic->DW24.Reserved);
    VPHAL_RENDER_VERBOSEMESSAGE("CurbeData: DW25.Value = %x", pObjectStatic->DW25.Value);
    VPHAL_RENDER_VERBOSEMESSAGE("CurbeData:     VerticalScalingStepRatioLayer1 = 0x%x",
        pObjectStatic->DW25.VerticalScalingStepRatioLayer1);
    VPHAL_RENDER_VERBOSEMESSAGE("CurbeData: DW26.Value = %x", pObjectStatic->DW26.Value);
    VPHAL_RENDER_VERBOSEMESSAGE("CurbeData:     VerticalScalingStepRatioLayer2 = 0x%x, HorizontalFrameOriginOffset = %d, VerticalFrameOriginOffset = %d",
        pObjectStatic->DW26.VerticalScalingStepRatioLayer2,
        pObjectStatic->DW26.HorizontalFrameOriginOffset,
        pObjectStatic->DW26.VerticalFrameOriginOffset);
    VPHAL_RENDER_VERBOSEMESSAGE("CurbeData: DW27.Value = %x", pObjectStatic->DW27.Value);
    VPHAL_RENDER_VERBOSEMESSAGE("CurbeData:     VerticalScalingStepRatioLayer3 = 0x%x",
        pObjectStatic->DW27.VerticalScalingStepRatioLayer3);
    VPHAL_RENDER_VERBOSEMESSAGE("CurbeData: DW28.Value = %x", pObjectStatic->DW28.Value);
    VPHAL_RENDER_VERBOSEMESSAGE("CurbeData:     VerticalScalingStepRatioLayer4 = 0x%x",
        pObjectStatic->DW28.VerticalScalingStepRatioLayer4);
    VPHAL_RENDER_VERBOSEMESSAGE("CurbeData: DW29.Value = %x", pObjectStatic->DW29.Value);
    VPHAL_RENDER_VERBOSEMESSAGE("CurbeData:     VerticalScalingStepRatioLayer5 = 0x%x",
        pObjectStatic->DW29.VerticalScalingStepRatioLayer5);
    VPHAL_RENDER_VERBOSEMESSAGE("CurbeData: DW30.Value = %x", pObjectStatic->DW30.Value);
    VPHAL_RENDER_VERBOSEMESSAGE("CurbeData:     VerticalScalingStepRatioLayer6 = 0x%x",
        pObjectStatic->DW30.VerticalScalingStepRatioLayer6);
    VPHAL_RENDER_VERBOSEMESSAGE("CurbeData: DW31.Value = %x", pObjectStatic->DW31.Value);
    VPHAL_RENDER_VERBOSEMESSAGE("CurbeData:     VerticalScalingStepRatioLayer7 = 0x%x",
         pObjectStatic->DW31.VerticalScalingStepRatioLayer7);
    VPHAL_RENDER_VERBOSEMESSAGE("CurbeData: DW32.Value = %x", pObjectStatic->DW32.Value);
    VPHAL_RENDER_VERBOSEMESSAGE("CurbeData:     VerticalFrameOriginLayer0 = 0x%x",
        pObjectStatic->DW32.VerticalFrameOriginLayer0);
    VPHAL_RENDER_VERBOSEMESSAGE("CurbeData: DW33.Value = %x", pObjectStatic->DW33.Value);
    VPHAL_RENDER_VERBOSEMESSAGE("CurbeData:     VerticalFrameOriginLayer1 = 0x%x",
        pObjectStatic->DW33.VerticalFrameOriginLayer1);
    VPHAL_RENDER_VERBOSEMESSAGE("CurbeData: DW34.Value = %x", pObjectStatic->DW34.Value);
    VPHAL_RENDER_VERBOSEMESSAGE("CurbeData:     VerticalFrameOriginLayer2 = 0x%x",
        pObjectStatic->DW34.VerticalFrameOriginLayer2);
    VPHAL_RENDER_VERBOSEMESSAGE("CurbeData: DW35.Value = %x", pObjectStatic->DW35.Value);
    VPHAL_RENDER_VERBOSEMESSAGE("CurbeData:     VerticalFrameOriginLayer3 = 0x%x",
        pObjectStatic->DW35.VerticalFrameOriginLayer3);
    VPHAL_RENDER_VERBOSEMESSAGE("CurbeData: DW36.Value = %x", pObjectStatic->DW36.Value);
    VPHAL_RENDER_VERBOSEMESSAGE("CurbeData:     VerticalFrameOriginLayer4 = 0x%x",
        pObjectStatic->DW36.VerticalFrameOriginLayer4);
    VPHAL_RENDER_VERBOSEMESSAGE("CurbeData: DW37.Value = %x", pObjectStatic->DW37.Value);
    VPHAL_RENDER_VERBOSEMESSAGE("CurbeData:     VerticalFrameOriginLayer5 = 0x%x",
        pObjectStatic->DW37.VerticalFrameOriginLayer5);
    VPHAL_RENDER_VERBOSEMESSAGE("CurbeData: DW38.Value = %x", pObjectStatic->DW38.Value);
    VPHAL_RENDER_VERBOSEMESSAGE("CurbeData:     VerticalFrameOriginLayer6 = 0x%x",
        pObjectStatic->DW38.VerticalFrameOriginLayer6);
    VPHAL_RENDER_VERBOSEMESSAGE("CurbeData: DW39.Value = %x", pObjectStatic->DW39.Value);
    VPHAL_RENDER_VERBOSEMESSAGE("CurbeData:     VerticalFrameOriginLayer7 = 0x%x",
        pObjectStatic->DW39.VerticalFrameOriginLayer7);
    VPHAL_RENDER_VERBOSEMESSAGE("CurbeData: DW40.Value = %x", pObjectStatic->DW40.Value);
    VPHAL_RENDER_VERBOSEMESSAGE("CurbeData:     HorizontalFrameOriginLayer0 = 0x%x",
        pObjectStatic->DW40.HorizontalFrameOriginLayer0);
    VPHAL_RENDER_VERBOSEMESSAGE("CurbeData: DW41.Value = %x", pObjectStatic->DW41.Value);
    VPHAL_RENDER_VERBOSEMESSAGE("CurbeData:     HorizontalFrameOriginLayer1 = 0x%x",
        pObjectStatic->DW41.HorizontalFrameOriginLayer1);
    VPHAL_RENDER_VERBOSEMESSAGE("CurbeData: DW42.Value = %x", pObjectStatic->DW42.Value);
    VPHAL_RENDER_VERBOSEMESSAGE("CurbeData:     HorizontalFrameOriginLayer2 = 0x%x",
        pObjectStatic->DW42.HorizontalFrameOriginLayer2);
    VPHAL_RENDER_VERBOSEMESSAGE("CurbeData: DW43.Value = %x", pObjectStatic->DW43.Value);
    VPHAL_RENDER_VERBOSEMESSAGE("CurbeData:     HorizontalFrameOriginLayer3 = 0x%x",
        pObjectStatic->DW43.HorizontalFrameOriginLayer3);
    VPHAL_RENDER_VERBOSEMESSAGE("CurbeData: DW44.Value = %x", pObjectStatic->DW44.Value);
    VPHAL_RENDER_VERBOSEMESSAGE("CurbeData:     HorizontalFrameOriginLayer4 = 0x%x",
        pObjectStatic->DW44.HorizontalFrameOriginLayer4);
    VPHAL_RENDER_VERBOSEMESSAGE("CurbeData: DW45.Value = %x", pObjectStatic->DW45.Value);
    VPHAL_RENDER_VERBOSEMESSAGE("CurbeData:     HorizontalFrameOriginLayer5 = 0x%x",
        pObjectStatic->DW45.HorizontalFrameOriginLayer5);
    VPHAL_RENDER_VERBOSEMESSAGE("CurbeData: DW46.Value = %x", pObjectStatic->DW46.Value);
    VPHAL_RENDER_VERBOSEMESSAGE("CurbeData:     HorizontalFrameOriginLayer6 = 0x%x",
        pObjectStatic->DW46.HorizontalFrameOriginLayer6);
    VPHAL_RENDER_VERBOSEMESSAGE("CurbeData: DW47.Value = %x", pObjectStatic->DW47.Value);
    VPHAL_RENDER_VERBOSEMESSAGE("CurbeData:     HorizontalFrameOriginLayer7 = 0x%x",
        pObjectStatic->DW47.HorizontalFrameOriginLayer7);

    MEDIA_WALKER_KA2_STATIC_DATA *pWalkerStatic = (MEDIA_WALKER_KA2_STATIC_DATA *)pObjectStatic;

    VPHAL_RENDER_VERBOSEMESSAGE("CurbeData: DW48.Value = %x", pWalkerStatic->DW48.Value);
    VPHAL_RENDER_VERBOSEMESSAGE("CurbeData:     DestXTopLeftLayer0 = %d, DestYTopLeftLayer0 = %d",
        pWalkerStatic->DW48.DestXTopLeftLayer0,
        pWalkerStatic->DW48.DestYTopLeftLayer0);
    VPHAL_RENDER_VERBOSEMESSAGE("CurbeData: DW49.Value = %x", pWalkerStatic->DW49.Value);
    VPHAL_RENDER_VERBOSEMESSAGE("CurbeData:     DestXTopLeftLayer1 = %d, DestYTopLeftLayer1 = %d",
        pWalkerStatic->DW49.DestXTopLeftLayer1,
        pWalkerStatic->DW49.DestYTopLeftLayer1);
    VPHAL_RENDER_VERBOSEMESSAGE("CurbeData: DW50.Value = %x", pWalkerStatic->DW50.Value);
    VPHAL_RENDER_VERBOSEMESSAGE("CurbeData:     DestXTopLeftLayer2 = %d, DestYTopLeftLayer2 = %d",
        pWalkerStatic->DW50.DestXTopLeftLayer2,
        pWalkerStatic->DW50.DestYTopLeftLayer2);
    VPHAL_RENDER_VERBOSEMESSAGE("CurbeData: DW51.Value = %x", pWalkerStatic->DW51.Value);
    VPHAL_RENDER_VERBOSEMESSAGE("CurbeData:     DestXTopLeftLayer3 = %d, DestYTopLeftLayer3 = %d",
        pWalkerStatic->DW51.DestXTopLeftLayer3,
        pWalkerStatic->DW51.DestYTopLeftLayer3);
    VPHAL_RENDER_VERBOSEMESSAGE("CurbeData: DW52.Value = %x", pWalkerStatic->DW52.Value);
    VPHAL_RENDER_VERBOSEMESSAGE("CurbeData:     DestXTopLeftLayer4 = %d, DestYTopLeftLayer4 = %d",
        pWalkerStatic->DW52.DestXTopLeftLayer4,
        pWalkerStatic->DW52.DestYTopLeftLayer4);
    VPHAL_RENDER_VERBOSEMESSAGE("CurbeData: DW53.Value = %x", pWalkerStatic->DW53.Value);
    VPHAL_RENDER_VERBOSEMESSAGE("CurbeData:     DestXTopLeftLayer5 = %d, DestYTopLeftLayer5 = %d",
        pWalkerStatic->DW53.DestXTopLeftLayer5,
        pWalkerStatic->DW53.DestYTopLeftLayer5);
    VPHAL_RENDER_VERBOSEMESSAGE("CurbeData: DW54.Value = %x", pWalkerStatic->DW54.Value);
    VPHAL_RENDER_VERBOSEMESSAGE("CurbeData:     DestXTopLeftLayer6 = %d, DestYTopLeftLayer6 = %d",
        pWalkerStatic->DW54.DestXTopLeftLayer6,
        pWalkerStatic->DW54.DestYTopLeftLayer6);
    VPHAL_RENDER_VERBOSEMESSAGE("CurbeData: DW55.Value = %x", pWalkerStatic->DW55.Value);
    VPHAL_RENDER_VERBOSEMESSAGE("CurbeData:     DestXTopLeftLayer7 = %d, DestYTopLeftLaye7 = %d",
        pWalkerStatic->DW55.DestXTopLeftLayer7,
        pWalkerStatic->DW55.DestYTopLeftLayer7);
    VPHAL_RENDER_VERBOSEMESSAGE("CurbeData: DW56.Value = %x", pWalkerStatic->DW56.Value);
    VPHAL_RENDER_VERBOSEMESSAGE("CurbeData:     DestXBottomRightLayer0 = %d, DestXBottomRightLayer0 = %d",
        pWalkerStatic->DW56.DestXBottomRightLayer0,
        pWalkerStatic->DW56.DestXBottomRightLayer0);
    VPHAL_RENDER_VERBOSEMESSAGE("CurbeData: DW57.Value = %x", pWalkerStatic->DW57.Value);
    VPHAL_RENDER_VERBOSEMESSAGE("CurbeData:     DestXBottomRightLayer1 = %d, DestXBottomRightLayer1 = %d",
        pWalkerStatic->DW57.DestXBottomRightLayer1,
        pWalkerStatic->DW57.DestXBottomRightLayer1);
    VPHAL_RENDER_VERBOSEMESSAGE("CurbeData: DW58.Value = %x", pWalkerStatic->DW58.Value);
    VPHAL_RENDER_VERBOSEMESSAGE("CurbeData:     DestXBottomRightLayer2 = %d, DestXBottomRightLayer2 = %d",
        pWalkerStatic->DW58.DestXBottomRightLayer2,
        pWalkerStatic->DW58.DestXBottomRightLayer2);
    VPHAL_RENDER_VERBOSEMESSAGE("CurbeData: DW59.Value = %x", pWalkerStatic->DW59.Value);
    VPHAL_RENDER_VERBOSEMESSAGE("CurbeData:     DestXBottomRightLayer3 = %d, DestXBottomRightLayer3 = %d",
        pWalkerStatic->DW59.DestXBottomRightLayer3,
        pWalkerStatic->DW59.DestXBottomRightLayer3);
    VPHAL_RENDER_VERBOSEMESSAGE("CurbeData: DW60.Value = %x", pWalkerStatic->DW60.Value);
    VPHAL_RENDER_VERBOSEMESSAGE("CurbeData:     DestXBottomRightLayer4 = %d, DestXBottomRightLayer4 = %d",
        pWalkerStatic->DW60.DestXBottomRightLayer4,
        pWalkerStatic->DW60.DestXBottomRightLayer4);
    VPHAL_RENDER_VERBOSEMESSAGE("CurbeData: DW61.Value = %x", pWalkerStatic->DW61.Value);
    VPHAL_RENDER_VERBOSEMESSAGE("CurbeData:     DestXBottomRightLayer5 = %d, DestXBottomRightLayer5 = %d",
        pWalkerStatic->DW61.DestXBottomRightLayer5,
        pWalkerStatic->DW61.DestXBottomRightLayer5);
    VPHAL_RENDER_VERBOSEMESSAGE("CurbeData: DW62.Value = %x", pWalkerStatic->DW62.Value);
    VPHAL_RENDER_VERBOSEMESSAGE("CurbeData:     DestXBottomRightLayer6 = %d, DestXBottomRightLayer6 = %d",
        pWalkerStatic->DW62.DestXBottomRightLayer6,
        pWalkerStatic->DW62.DestXBottomRightLayer6);
    VPHAL_RENDER_VERBOSEMESSAGE("CurbeData: DW63.Value = %x", pWalkerStatic->DW63.Value);
    VPHAL_RENDER_VERBOSEMESSAGE("CurbeData:     DestXBottomRightLayer7 = %d, DestXBottomRightLayer7 = %d",
        pWalkerStatic->DW63.DestXBottomRightLayer7,
        pWalkerStatic->DW63.DestXBottomRightLayer7);
    VPHAL_RENDER_VERBOSEMESSAGE("CurbeData: DW64.Value = %x", pWalkerStatic->DW64.Value);
    VPHAL_RENDER_VERBOSEMESSAGE("CurbeData:     MainVideoXScalingStepLeft = %x",
        pWalkerStatic->DW64.MainVideoXScalingStepLeft);
    VPHAL_RENDER_VERBOSEMESSAGE("CurbeData: DW65.Value = %x", pWalkerStatic->DW65.Value);
    VPHAL_RENDER_VERBOSEMESSAGE("CurbeData:     VideoStepDeltaForNonLinearRegion = %x",
        pWalkerStatic->DW65.VideoStepDeltaForNonLinearRegion);
    VPHAL_RENDER_VERBOSEMESSAGE("CurbeData: DW66.Value = %x", pWalkerStatic->DW66.Value);
    VPHAL_RENDER_VERBOSEMESSAGE("CurbeData:     StartofLinearScalingInPixelPositionC0 = %x, StartofRHSNonLinearScalingInPixelPositionC1 = %x",
        pWalkerStatic->DW66.StartofLinearScalingInPixelPositionC0,
        pWalkerStatic->DW66.StartofRHSNonLinearScalingInPixelPositionC1);
    VPHAL_RENDER_VERBOSEMESSAGE("CurbeData: DW67.Value = %x", pWalkerStatic->DW67.Value);
    VPHAL_RENDER_VERBOSEMESSAGE("CurbeData:     MainVideoXScalingStepCenter = %x",
        pWalkerStatic->DW67.MainVideoXScalingStepCenter);
    VPHAL_RENDER_VERBOSEMESSAGE("CurbeData: DW68.Value = %x", pWalkerStatic->DW68.Value);
    VPHAL_RENDER_VERBOSEMESSAGE("CurbeData:     MainVideoXScalingStepRight = %x",
        pWalkerStatic->DW68.MainVideoXScalingStepRight);
    VPHAL_RENDER_VERBOSEMESSAGE("CurbeData: DW69.Value = %x", pWalkerStatic->DW69.Value);
    VPHAL_RENDER_VERBOSEMESSAGE("CurbeData:     DestHorizontalBlockOrigin = %x, DestVerticalBlockOrigin = %x",
        pWalkerStatic->DW69.DestHorizontalBlockOrigin,
        pWalkerStatic->DW69.DestVerticalBlockOrigin);
    VPHAL_RENDER_VERBOSEMESSAGE("CurbeData: dwPad[0] = %x, dwPad[1] = %x",
        pWalkerStatic->dwPad[0],
        pWalkerStatic->dwPad[1]); 
#endif
}

//!
//! \brief    Judge if Composite render support multiple stream rendering
//! \details  Judge if Composite render support multiple stream rendering
//! \return   bool
//!           true if supported. Else false
//!
bool CompositeState::IsMultipleStreamSupported()
{
    return true;
}

//!
//! \brief    set Report data
//! \details  set Report data for this render
//! \param    [in] pSource
//!           pointer to the surface
//!
void CompositeState::SetReporting(PVPHAL_SURFACE pSource)
{
    m_reporting->GetFeatures().ief             = pSource->bIEF;
    m_reporting->GetFeatures().scalingMode     = pSource->ScalingMode;
    m_reporting->GetFeatures().deinterlaceMode =
                (IsBobDiEnabled(pSource)) ? VPHAL_DI_REPORT_BOB :
                                                VPHAL_DI_REPORT_PROGRESSIVE;
}

//!
//! \brief    copy Report data
//! \details  copy Report data from this render
//! \param    [out] pReporting
//!           pointer to the Report data to copy data to
//!
void CompositeState::CopyReporting(VphalFeatureReport* pReporting)
{
    VPHAL_RENDER_ASSERT(pReporting);

    pReporting->GetFeatures().ief         = m_reporting->GetFeatures().ief;
    pReporting->GetFeatures().scalingMode = m_reporting->GetFeatures().scalingMode;

    if (m_reporting->GetFeatures().deinterlaceMode != VPHAL_DI_REPORT_PROGRESSIVE)
    {
        pReporting->GetFeatures().deinterlaceMode = m_reporting->GetFeatures().deinterlaceMode;
    }
}

int32_t CompositeState::GetThreadCountForVfeState(
    PVPHAL_RENDERING_DATA_COMPOSITE     pRenderingData,
    PVPHAL_SURFACE                      pTarget)
{
    int iThreadCount;

    // For optimal performance, we use a different ThreadCount if we are doing
    // Composition for Primary Layer only, and the RenderTarget is Overlay or
    // FlipChain.
    iThreadCount = VPHAL_USE_MEDIA_THREADS_MAX;
    if (pRenderingData->iLayers == 1 &&
        (pTarget->bOverlay || pTarget->bFlipChain))
    {
        for (int i = 0; i < VPHAL_COMP_MAX_LAYERS; i++)
        {
            VPHAL_SURFACE *pSurface = pRenderingData->pLayers[i];
            if (pSurface != nullptr)
            {
                if (pSurface->SurfType == SURF_IN_PRIMARY)
                {
                    iThreadCount = m_ThreadCountPrimary;
                }
                break;
            }
        }
    }

    if (m_pPerfData->CompMaxThreads.bEnabled)
    {
        iThreadCount =
            m_pPerfData->CompMaxThreads.uiVal;
    }

    return iThreadCount;
}

bool CompositeState::IsSamplerIDForY(
    int32_t                            SamplerID)
{
    return (SamplerID == VPHAL_SAMPLER_Y) ? true : false;
}

 bool CompositeState::IsDisableAVSSampler(
    int32_t         iSources,
    bool            isTargetY)
{
     if (m_pOsInterface == nullptr)
     {
         return false;
     }

     MEDIA_WA_TABLE *waTable = m_pOsInterface->pfnGetWaTable(m_pOsInterface);
     if (waTable == nullptr)
     {
         return false;
     }

     if (MEDIA_IS_WA(waTable, WaTargetTopYOffset) && iSources > 1 && isTargetY)
     {
         return true;
     }
     return false;
 }