Gmmlib uAPI Implemenetation to accept full comprehensive memory layout description
for the import path for both dmabuf and userptr.

Change-Id: Ie8dbcc740f942511ed8e9441fd453acc84924f78
diff --git a/Source/GmmLib/CMakeLists.txt b/Source/GmmLib/CMakeLists.txt
index cc655be..ee33ca9 100644
--- a/Source/GmmLib/CMakeLists.txt
+++ b/Source/GmmLib/CMakeLists.txt
@@ -25,14 +25,14 @@
 
 # GmmLib Api Version used for so naming
 set(GMMLIB_API_MAJOR_VERSION 11)
-set(GMMLIB_API_MINOR_VERSION 1)
+set(GMMLIB_API_MINOR_VERSION 2)
 
 if(NOT DEFINED MAJOR_VERSION)
 	set(MAJOR_VERSION 11)
 endif()
 
 if(NOT DEFINED MINOR_VERSION)
-	set(MINOR_VERSION 1)
+	set(MINOR_VERSION 2)
 endif()
 
 if(NOT DEFINED PATCH_VERSION)
diff --git a/Source/GmmLib/GlobalInfo/GmmClientContext.cpp b/Source/GmmLib/GlobalInfo/GmmClientContext.cpp
index 592dcbb..60541b0 100644
--- a/Source/GmmLib/GlobalInfo/GmmClientContext.cpp
+++ b/Source/GmmLib/GlobalInfo/GmmClientContext.cpp
@@ -337,6 +337,41 @@
 }
 
 /////////////////////////////////////////////////////////////////////////////////////
+/// Member function of ClientContext class for creation of Custiom ResourceInfo Object .
+/// @see        GmmLib::GmmResourceInfoCommon::Create()
+///
+/// @param[in] pCreateParams: Flags which specify what sort of resource to create
+/// @return     Pointer to GmmResourceInfo class.
+/////////////////////////////////////////////////////////////////////////////////////
+GMM_RESOURCE_INFO *GMM_STDCALL GmmLib::GmmClientContext::CreateCustomResInfoObject(GMM_RESCREATE_CUSTOM_PARAMS *pCreateParams)
+{
+    GMM_RESOURCE_INFO *pRes             = NULL;
+    GmmClientContext * pClientContextIn = NULL;
+
+    pClientContextIn = this;
+
+    if((pRes = new GMM_RESOURCE_INFO(pClientContextIn)) == NULL)
+    {
+        GMM_ASSERTDPF(0, "Allocation failed!");
+        goto ERROR_CASE;
+    }
+
+    if(pRes->CreateCustomRes(*pGmmGlobalContext, *pCreateParams) != GMM_SUCCESS)
+    {
+        goto ERROR_CASE;
+    }
+
+    return (pRes);
+
+ERROR_CASE:
+    if(pRes)
+    {
+        DestroyResInfoObject(pRes);
+    }
+
+    return (NULL);
+}
+/////////////////////////////////////////////////////////////////////////////////////
 /// Member function of ClientContext class for creation of ResourceInfo Object .
 /// @see        GmmLib::GmmResourceInfoCommon::Create()
 ///
diff --git a/Source/GmmLib/Resource/GmmResourceInfoCommon.cpp b/Source/GmmLib/Resource/GmmResourceInfoCommon.cpp
index 727da2d..4a08899 100644
--- a/Source/GmmLib/Resource/GmmResourceInfoCommon.cpp
+++ b/Source/GmmLib/Resource/GmmResourceInfoCommon.cpp
@@ -111,6 +111,126 @@
 }
 
 /////////////////////////////////////////////////////////////////////////////////////
+/// Allows clients to "create"  Custom memory layout received from the App as user pointer or DMABUF
+// This function does not allocate any memory for the resource. It just calculates/ populates the various parameters
+/// which are useful for the client and can be queried using other functions.
+///
+/// @param[in]  GmmLib Context: Reference to ::GmmLibContext
+/// @param[in]  CreateParams: Flags which specify what sort of resource to create
+///
+/// @return     ::GMM_STATUS
+/////////////////////////////////////////////////////////////////////////////////////
+GMM_STATUS GMM_STDCALL GmmLib::GmmResourceInfoCommon::CreateCustomRes(Context &GmmLibContext, GMM_RESCREATE_CUSTOM_PARAMS &CreateParams)
+{
+    const GMM_PLATFORM_INFO *pPlatform;
+    GMM_STATUS               Status       = GMM_ERROR;
+    GMM_TEXTURE_CALC *       pTextureCalc = NULL;
+    uint32_t                 BitsPerPixel, i;
+
+
+    GMM_DPF_ENTER;
+
+    __GMM_ASSERTPTR(pGmmGlobalContext, GMM_ERROR);
+    pGmmLibContext = reinterpret_cast<uint64_t>(&GmmLibContext);
+
+
+    if((CreateParams.Format > GMM_FORMAT_INVALID) &&
+       (CreateParams.Format < GMM_RESOURCE_FORMATS))
+    {
+        BitsPerPixel = pGmmGlobalContext->GetPlatformInfo().FormatTable[CreateParams.Format].Element.BitsPer;
+    }
+    else
+    {
+        GMM_ASSERTDPF(0, "Format Error");
+        Status = GMM_INVALIDPARAM;
+        goto ERROR_CASE;
+    }
+
+    pPlatform    = GMM_OVERRIDE_PLATFORM_INFO(&Surf);
+    pTextureCalc = GMM_OVERRIDE_TEXTURE_CALC(&Surf);
+
+    Surf.Type                    = CreateParams.Type;
+    Surf.Format                  = CreateParams.Format;
+    Surf.BaseWidth               = CreateParams.BaseWidth64;
+    Surf.BaseHeight              = CreateParams.BaseHeight;
+    Surf.Flags                   = CreateParams.Flags;
+    Surf.CachePolicy.Usage       = CreateParams.Usage;
+    Surf.Pitch                   = CreateParams.Pitch;
+    Surf.Size                    = CreateParams.Size;
+    Surf.Alignment.BaseAlignment = CreateParams.BaseAlignment;
+    Surf.MaxLod                  = 1;
+    Surf.ArraySize               = 1;
+
+#if(_DEBUG || _RELEASE_INTERNAL)
+    Surf.Platform = pGmmGlobalContext->GetPlatformInfo().Platform;
+#endif
+    Surf.BitsPerPixel     = BitsPerPixel;
+    Surf.Alignment.QPitch = (GMM_GLOBAL_GFX_SIZE_T)(Surf.Pitch * Surf.BaseHeight);
+
+    pTextureCalc->SetTileMode(&Surf);
+
+    if(GmmIsPlanar(Surf.Format))
+    {
+        if(GMM_IS_TILED(pPlatform->TileInfo[Surf.TileMode]))
+        {
+            Surf.OffsetInfo.Plane.IsTileAlignedPlanes = true;
+        }
+        for(i = 1; i <= CreateParams.NoOfPlanes; i++)
+        {
+            Surf.OffsetInfo.Plane.X[i] = CreateParams.PlaneOffset.X[i];
+            Surf.OffsetInfo.Plane.Y[i] = CreateParams.PlaneOffset.Y[i];
+        }
+        Surf.OffsetInfo.Plane.NoOfPlanes  = CreateParams.NoOfPlanes;
+        Surf.OffsetInfo.Plane.ArrayQPitch = Surf.Pitch * Surf.BaseHeight;
+        UpdateUnAlignedParams();
+    }
+
+    switch(Surf.Type)
+    {
+        case RESOURCE_1D:
+        case RESOURCE_2D:
+        case RESOURCE_PRIMARY:
+        case RESOURCE_SHADOW:
+        case RESOURCE_STAGING:
+        case RESOURCE_GDI:
+        case RESOURCE_NNDI:
+        case RESOURCE_HARDWARE_MBM:
+        case RESOURCE_OVERLAY_INTERMEDIATE_SURFACE:
+        case RESOURCE_IFFS_MAPTOGTT:
+#if _WIN32
+        case RESOURCE_WGBOX_ENCODE_DISPLAY:
+        case RESOURCE_WGBOX_ENCODE_REFERENCE:
+#endif
+        {
+            Surf.OffsetInfo.Texture2DOffsetInfo.ArrayQPitchRender =
+            Surf.OffsetInfo.Texture2DOffsetInfo.ArrayQPitchLock = Surf.Pitch * Surf.BaseHeight;
+            for(i = 0; i <= Surf.MaxLod; i++)
+            {
+                Surf.OffsetInfo.Texture2DOffsetInfo.Offset[i] = 0;
+            }
+
+            break;
+        }
+        default:
+        {
+            GMM_ASSERTDPF(0, "GmmTexAlloc: Unknown surface type!");
+            Status = GMM_INVALIDPARAM;
+            goto ERROR_CASE;
+            ;
+        }
+    };
+
+    GMM_DPF_EXIT;
+    return GMM_SUCCESS;
+
+ERROR_CASE:
+    //Zero out all the members
+    new(this) GmmResourceInfoCommon();
+
+    GMM_DPF_EXIT;
+    return Status;
+}
+/////////////////////////////////////////////////////////////////////////////////////
 /// Allows clients to "create" any type of resource. This function does not
 /// allocate any memory for the resource. It just calculates the various parameters
 /// which are useful for the client and can be queried using other functions.
@@ -367,6 +487,220 @@
     return Status;
 }
 
+void GmmLib::GmmResourceInfoCommon::UpdateUnAlignedParams()
+{
+    uint32_t YHeight = 0, VHeight = 0;
+    uint32_t Height = 0, UmdUHeight = 0, UmdVHeight = 0;
+    uint32_t WidthBytesPhysical = GFX_ULONG_CAST(Surf.BaseWidth) * Surf.BitsPerPixel >> 3;
+
+    __GMM_ASSERTPTR(((Surf.TileMode < GMM_TILE_MODES) && (Surf.TileMode >= TILE_NONE)), VOIDRETURN);
+    GMM_DPF_ENTER;
+
+    Height = Surf.BaseHeight;
+
+    switch(Surf.Format)
+    {
+        case GMM_FORMAT_IMC1: // IMC1 = IMC3 with Swapped U/V
+        case GMM_FORMAT_IMC3:
+        case GMM_FORMAT_MFX_JPEG_YUV420: // Same as IMC3.
+        // YYYYYYYY
+        // YYYYYYYY
+        // YYYYYYYY
+        // YYYYYYYY
+        // UUUU
+        // UUUU
+        // VVVV
+        // VVVV
+        case GMM_FORMAT_MFX_JPEG_YUV422V: // Similar to IMC3 but U/V are full width.
+            // YYYYYYYY
+            // YYYYYYYY
+            // YYYYYYYY
+            // YYYYYYYY
+            // UUUUUUUU
+            // UUUUUUUU
+            // VVVVVVVV
+            // VVVVVVVV
+            {
+                YHeight = GFX_ALIGN(Surf.BaseHeight, GMM_IMCx_PLANE_ROW_ALIGNMENT);
+
+                VHeight = GFX_ALIGN(GFX_CEIL_DIV(Surf.BaseHeight, 2), GMM_IMCx_PLANE_ROW_ALIGNMENT);
+
+                break;
+            }
+        case GMM_FORMAT_MFX_JPEG_YUV411R_TYPE: //Similar to IMC3 but U/V are quarther height and full width.
+            //YYYYYYYY
+            //YYYYYYYY
+            //YYYYYYYY
+            //YYYYYYYY
+            //UUUUUUUU
+            //VVVVVVVV
+            {
+                YHeight = GFX_ALIGN(Surf.BaseHeight, GMM_IMCx_PLANE_ROW_ALIGNMENT);
+
+                VHeight = GFX_ALIGN(GFX_CEIL_DIV(Surf.BaseHeight, 4), GMM_IMCx_PLANE_ROW_ALIGNMENT);
+
+                break;
+            }
+        case GMM_FORMAT_MFX_JPEG_YUV411: // Similar to IMC3 but U/V are quarter width and full height.
+        // YYYYYYYY
+        // YYYYYYYY
+        // YYYYYYYY
+        // YYYYYYYY
+        // UU
+        // UU
+        // UU
+        // UU
+        // VV
+        // VV
+        // VV
+        // VV
+        case GMM_FORMAT_MFX_JPEG_YUV422H: // Similar to IMC3 but U/V are full height.
+        // YYYYYYYY
+        // YYYYYYYY
+        // YYYYYYYY
+        // YYYYYYYY
+        // UUUU
+        // UUUU
+        // UUUU
+        // UUUU
+        // VVVV
+        // VVVV
+        // VVVV
+        // VVVV
+        case GMM_FORMAT_BGRP:
+        case GMM_FORMAT_RGBP:
+        case GMM_FORMAT_MFX_JPEG_YUV444: // Similar to IMC3 but U/V are full size.
+            // YYYYYYYY
+            // YYYYYYYY
+            // YYYYYYYY
+            // YYYYYYYY
+            // UUUUUUUU
+            // UUUUUUUU
+            // UUUUUUUU
+            // UUUUUUUU
+            // VVVVVVVV
+            // VVVVVVVV
+            // VVVVVVVV
+            // VVVVVVVV
+            {
+                YHeight = GFX_ALIGN(Surf.BaseHeight, GMM_IMCx_PLANE_ROW_ALIGNMENT);
+
+                VHeight = GFX_ALIGN(Surf.BaseHeight, GMM_IMCx_PLANE_ROW_ALIGNMENT);
+
+                break;
+            }
+        case GMM_FORMAT_IMC2: // IMC2 = IMC4 with Swapped U/V
+        case GMM_FORMAT_IMC4:
+        {
+            // YYYYYYYY
+            // YYYYYYYY
+            // YYYYYYYY
+            // YYYYYYYY
+            // UUUUVVVV
+            // UUUUVVVV
+
+            __GMM_ASSERT((Surf.Pitch & 1) == 0);
+
+            YHeight = GFX_ALIGN(Surf.BaseHeight, GMM_IMCx_PLANE_ROW_ALIGNMENT);
+
+            VHeight = GFX_CEIL_DIV(YHeight, 2);
+
+            break;
+        }
+        case GMM_FORMAT_I420: // I420 = IYUV
+        case GMM_FORMAT_IYUV: // I420/IYUV = YV12 with Swapped U/V
+        case GMM_FORMAT_YV12:
+        case GMM_FORMAT_YVU9:
+        {
+            // YYYYYYYY
+            // YYYYYYYY
+            // YYYYYYYY
+            // YYYYYYYY
+            // VVVVVV..  <-- V and U planes follow the Y plane, as linear
+            // ..UUUUUU      arrays--without respect to pitch.
+
+            uint32_t YSize, YVSizeRShift, VSize, UOffset;
+            uint32_t YSizeForUVPurposes, YSizeForUVPurposesDimensionalAlignment;
+
+            YSize = GFX_ULONG_CAST(Surf.Pitch) * Surf.BaseHeight;
+
+            // YVU9 has one U/V pixel for each 4x4 Y block.
+            // The others have one U/V pixel for each 2x2 Y block.
+
+            // YVU9 has a Y:V size ratio of 16 (4x4 --> 1).
+            // The others have a ratio of 4 (2x2 --> 1).
+            YVSizeRShift = (Surf.Format != GMM_FORMAT_YVU9) ? 2 : 4;
+
+            // If a Y plane isn't fully-aligned to its Y-->U/V block size, the
+            // extra/unaligned Y pixels still need corresponding U/V pixels--So
+            // for the purpose of computing the UVSize, we must consider a
+            // dimensionally "rounded-up" YSize. (E.g. a 13x5 YVU9 Y plane would
+            // require 4x2 U/V planes--the same UVSize as a fully-aligned 16x8 Y.)
+            YSizeForUVPurposesDimensionalAlignment = (Surf.Format != GMM_FORMAT_YVU9) ? 2 : 4;
+            YSizeForUVPurposes =
+            GFX_ALIGN(GFX_ULONG_CAST(Surf.Pitch), YSizeForUVPurposesDimensionalAlignment) *
+            GFX_ALIGN(Surf.BaseHeight, YSizeForUVPurposesDimensionalAlignment);
+
+            VSize = (YSizeForUVPurposes >> YVSizeRShift);
+
+            YHeight = GFX_CEIL_DIV(YSize + 2 * VSize, WidthBytesPhysical);
+
+            break;
+        }
+        case GMM_FORMAT_NV12:
+        case GMM_FORMAT_NV21:
+        case GMM_FORMAT_NV11:
+        case GMM_FORMAT_P010:
+        case GMM_FORMAT_P012:
+        case GMM_FORMAT_P016:
+        case GMM_FORMAT_P208:
+        {
+            // YYYYYYYY
+            // YYYYYYYY
+            // YYYYYYYY
+            // YYYYYYYY
+            // [UV-Packing]
+            YHeight = GFX_ALIGN(Height, __GMM_EVEN_ROW);
+
+            if((Surf.Format == GMM_FORMAT_NV12) ||
+               (Surf.Format == GMM_FORMAT_NV21) ||
+               (Surf.Format == GMM_FORMAT_P010) ||
+               (Surf.Format == GMM_FORMAT_P012) ||
+               (Surf.Format == GMM_FORMAT_P016))
+            {
+                VHeight = GFX_CEIL_DIV(Height, 2);
+            }
+            else
+            {
+                VHeight = YHeight; // U/V plane is same as Y
+            }
+
+            break;
+        }
+        default:
+        {
+            GMM_ASSERTDPF(0, "Unknown Video Format U\n");
+            break;
+        }
+    }
+
+    Surf.OffsetInfo.Plane.UnAligned.Height[GMM_PLANE_Y] = YHeight;
+    if(Surf.OffsetInfo.Plane.NoOfPlanes == 2)
+    {
+        Surf.OffsetInfo.Plane.UnAligned.Height[GMM_PLANE_U] = VHeight;
+        UmdUHeight                                          = (GMM_GLOBAL_GFX_SIZE_T)((Surf.Size / Surf.Pitch) - Surf.OffsetInfo.Plane.Y[GMM_PLANE_U]);
+    }
+    else if(Surf.OffsetInfo.Plane.NoOfPlanes == 3)
+    {
+        Surf.OffsetInfo.Plane.UnAligned.Height[GMM_PLANE_U] =
+        Surf.OffsetInfo.Plane.UnAligned.Height[GMM_PLANE_V] = VHeight;
+        UmdUHeight                                          = (GMM_GLOBAL_GFX_SIZE_T)(Surf.OffsetInfo.Plane.Y[GMM_PLANE_V] - Surf.OffsetInfo.Plane.Y[GMM_PLANE_U]);
+        UmdVHeight                                          = (GMM_GLOBAL_GFX_SIZE_T)(((Surf.Size / Surf.Pitch) - Surf.OffsetInfo.Plane.Y[GMM_PLANE_U]) / 2);
+        __GMM_ASSERTPTR((UmdUHeight == UmdVHeight), VOIDRETURN);
+    }
+
+    __GMM_ASSERTPTR(((Surf.OffsetInfo.Plane.Y[GMM_PLANE_U] == YHeight) && (UmdUHeight == VHeight)), VOIDRETURN);
+}
 /////////////////////////////////////////////////////////////////////////////////////
 /// This function calculates number of planes required for the given input format
 /// and allocates texture info for the respective planes.
diff --git a/Source/GmmLib/ULT/GmmGen11ResourceULT.cpp b/Source/GmmLib/ULT/GmmGen11ResourceULT.cpp
index e4e9fa6..c7fd370 100644
--- a/Source/GmmLib/ULT/GmmGen11ResourceULT.cpp
+++ b/Source/GmmLib/ULT/GmmGen11ResourceULT.cpp
@@ -302,6 +302,85 @@
     }
 }
 
+/// @brief ULT for Plannar 2D Resource - RGBP
+TEST_F(CTestGen11Resource, TestPlanar2DCustom_RGBP)
+{
+    /* Test planar surfaces where all planes are full-sized */
+    // YYYYYYYY
+    // YYYYYYYY
+    // YYYYYYYY
+    // YYYYYYYY
+    // UUUUUUUU
+    // UUUUUUUU
+    // UUUUUUUU
+    // UUUUUUUU
+    // VVVVVVVV
+    // VVVVVVVV
+    // VVVVVVVV
+    // VVVVVVVV
+    const TEST_TILE_TYPE TileTypes[]          = {TEST_LINEAR, TEST_TILEX, TEST_TILEY};
+    const uint32_t          PlaneRowAlignment = 16;
+
+    const uint32_t TileSize[3][2] = {{1, 1},     //Linear
+                                  {512, 8},   // TileX
+                                  {128, 32}}; // TileY
+    for(uint32_t TileIndex = 0; TileIndex < sizeof(TileTypes) / sizeof(TileTypes[0]); TileIndex++)
+    {
+        TEST_TILE_TYPE Tile = TileTypes[TileIndex];
+
+        GMM_RESCREATE_CUSTOM_PARAMS gmmParams = {};
+        gmmParams.Type                        = RESOURCE_2D;
+        gmmParams.Flags.Gpu.Texture           = 1;
+        gmmParams.BaseWidth64                 = 0x101;
+        gmmParams.BaseHeight                  = GMM_ULT_ALIGN(0x101, PlaneRowAlignment);
+        SetTileFlag_Custom(gmmParams, static_cast<TEST_TILE_TYPE>(Tile));
+        gmmParams.Format = GMM_FORMAT_RGBP;
+
+        uint32_t Pitch, Height;
+
+        Pitch  = GMM_ULT_ALIGN(gmmParams.BaseWidth64, GMM_BYTES(64));
+        Height = GMM_ULT_ALIGN(gmmParams.BaseHeight, PlaneRowAlignment /* min16 rows*/) * 3 /*Y, U, V*/;
+
+        uint32_t Size                        = Pitch * Height;
+        gmmParams.Pitch                      = Pitch;
+        gmmParams.Size                       = Size;
+        gmmParams.PlaneOffset.X[GMM_PLANE_Y] = 0;
+        gmmParams.PlaneOffset.Y[GMM_PLANE_Y] = 0;
+        gmmParams.PlaneOffset.X[GMM_PLANE_U] = 0;
+        gmmParams.PlaneOffset.Y[GMM_PLANE_U] = Height / 3;
+        gmmParams.PlaneOffset.X[GMM_PLANE_V] = 0;
+        gmmParams.PlaneOffset.Y[GMM_PLANE_V] = 2 * (Height / 3);
+        gmmParams.NoOfPlanes                 = 3;
+
+        GMM_RESOURCE_INFO *ResourceInfo;
+        ResourceInfo = pGmmULTClientContext->CreateCustomResInfoObject(&gmmParams);
+
+        VerifyResourcePitch<true>(ResourceInfo, Pitch);
+        if(Tile != TEST_LINEAR)
+        {
+            VerifyResourcePitchInTiles<true>(ResourceInfo, Pitch / TileSize[TileIndex][0]);
+        }
+        VerifyResourceSize<true>(ResourceInfo, Size);
+        VerifyResourceHAlign<false>(ResourceInfo, 0); // Same as any other 2D surface -- tested elsewhere
+        VerifyResourceVAlign<false>(ResourceInfo, 0); // Same as any other 2D surface -- tested elsewhere
+        VerifyResourceQPitch<false>(ResourceInfo, 0); // N/A for planar
+
+        // Y plane should be at 0,0
+        EXPECT_EQ(0, ResourceInfo->GetPlanarXOffset(GMM_PLANE_Y));
+        EXPECT_EQ(0, ResourceInfo->GetPlanarYOffset(GMM_PLANE_Y));
+
+        // U plane should be at end of Y plane
+        EXPECT_EQ(0, ResourceInfo->GetPlanarXOffset(GMM_PLANE_U));
+        EXPECT_EQ(Height / 3, ResourceInfo->GetPlanarYOffset(GMM_PLANE_U));
+
+        // V plane should be at end of U plane
+        EXPECT_EQ(0, ResourceInfo->GetPlanarXOffset(GMM_PLANE_V));
+        EXPECT_EQ(2 * (Height / 3), ResourceInfo->GetPlanarYOffset(GMM_PLANE_V));
+
+        pGmmULTClientContext->DestroyResInfoObject(ResourceInfo);
+    }
+}
+
 /// @brief ULT for Plannar 2D Resource - MFX_JPEG_YUV422V , IMC1, IMC3
 TEST_F(CTestGen11Resource, TestPlanar2D_MFX_JPEG_YUV422V)
 {
diff --git a/Source/GmmLib/ULT/GmmResourceULT.h b/Source/GmmLib/ULT/GmmResourceULT.h
index fb8ddee..e2242f2 100644
--- a/Source/GmmLib/ULT/GmmResourceULT.h
+++ b/Source/GmmLib/ULT/GmmResourceULT.h
@@ -203,6 +203,37 @@
         }
     }
 
+    /////////////////////////////////////////////////////////////////////////////////////
+    /// Set the tile flag in Gmm Custom ResCreate Params
+    ///
+    /// @param[in]  Parms: Gmm Rescreate params
+    /// @param[in]  Tile: Tile Type
+    ///
+    /////////////////////////////////////////////////////////////////////////////////////
+    void SetTileFlag_Custom(GMM_RESCREATE_CUSTOM_PARAMS& Params, TEST_TILE_TYPE Tile)
+    {
+        switch (Tile)
+        {
+        case TEST_LINEAR:
+            Params.Flags.Info.Linear = 1;
+            break;
+        case TEST_TILEX:
+            Params.Flags.Info.TiledX = 1;
+            break;
+        case TEST_TILEY:
+            Params.Flags.Info.TiledY = 1;
+            break;
+        case TEST_TILEYF:
+            Params.Flags.Info.TiledY = 1;
+            Params.Flags.Info.TiledYf = 1;
+            break;
+        case TEST_TILEYS:
+            Params.Flags.Info.TiledY = 1;
+            Params.Flags.Info.TiledYs = 1;
+            break;
+        default: break;
+        }
+    }
 
     /////////////////////////////////////////////////////////////////////////////////////
     /// Sets Resource Type in GmmParams
@@ -468,4 +499,4 @@
 /// @return   Number of tuples in the list
 /// @see      GmmGen9ResourceULT.cpp
 /////////////////////////////////////////////////////////////////////////
-int BuildInputIterator(std::vector<std::tuple<int, int, int, bool, int, int>> &List, int maxTestDimension, int TestArray);
\ No newline at end of file
+int BuildInputIterator(std::vector<std::tuple<int, int, int, bool, int, int>> &List, int maxTestDimension, int TestArray);
diff --git a/Source/GmmLib/inc/External/Common/GmmClientContext.h b/Source/GmmLib/inc/External/Common/GmmClientContext.h
index 525585a..cf3aa9d 100644
--- a/Source/GmmLib/inc/External/Common/GmmClientContext.h
+++ b/Source/GmmLib/inc/External/Common/GmmClientContext.h
@@ -160,6 +160,7 @@
         GMM_VIRTUAL void GMM_STDCALL                    DestroyPageTblMgrObject(GMM_PAGETABLE_MGR* pPageTableMgr,
                                                         GmmClientAllocationCallbacks* pAllocCbs);
         GMM_VIRTUAL GMM_STATUS GMM_STDCALL              GmmSetDeviceInfo(GMM_DEVICE_INFO* DeviceInfo);
+        GMM_VIRTUAL GMM_RESOURCE_INFO* GMM_STDCALL      CreateCustomResInfoObject(GMM_RESCREATE_CUSTOM_PARAMS* pCreateParams);
     };
 }
 
diff --git a/Source/GmmLib/inc/External/Common/GmmResourceInfoCommon.h b/Source/GmmLib/inc/External/Common/GmmResourceInfoCommon.h
index 0966d89..ce95cf0 100644
--- a/Source/GmmLib/inc/External/Common/GmmResourceInfoCommon.h
+++ b/Source/GmmLib/inc/External/Common/GmmResourceInfoCommon.h
@@ -1634,6 +1634,10 @@
                 Surf.OffsetInfo.Plane.Y[Plane] = YOffset;
             }
 
+            GMM_VIRTUAL GMM_STATUS              GMM_STDCALL CreateCustomRes(Context& GmmLibContext, GMM_RESCREATE_CUSTOM_PARAMS& CreateParams);
+            protected:
+                GMM_VIRTUAL void UpdateUnAlignedParams();
+
     };
 
 } // namespace GmmLib
diff --git a/Source/GmmLib/inc/External/Common/GmmResourceInfoExt.h b/Source/GmmLib/inc/External/Common/GmmResourceInfoExt.h
index 63fbd98..66c7ffe 100644
--- a/Source/GmmLib/inc/External/Common/GmmResourceInfoExt.h
+++ b/Source/GmmLib/inc/External/Common/GmmResourceInfoExt.h
@@ -288,6 +288,28 @@
 
 } GMM_RESCREATE_PARAMS;
 
+typedef struct GMM_RESCREATE_CUSTOM_PARAMS__REC
+{
+    GMM_RESOURCE_TYPE              Type;    // 1D/2D/.../SCRATCH/...
+    GMM_RESOURCE_FORMAT            Format;         // Pixel format e.g. NV12, GENERIC_8BIT
+    GMM_RESOURCE_FLAG              Flags;          // See substructure type.
+    GMM_RESOURCE_USAGE_TYPE        Usage;   // Intended use for this resource. See enumerated type.
+    GMM_GFX_SIZE_T                 BaseWidth64;
+    uint32_t                       BaseHeight;     // Aligned height of buffer (aligned according to .Format)
+
+    uint32_t                       Pitch;
+    GMM_GFX_SIZE_T                 Size;
+    uint32_t                       BaseAlignment;
+
+    struct
+    {
+        uint32_t X[GMM_MAX_PLANE];
+        uint32_t Y[GMM_MAX_PLANE];
+    }PlaneOffset;
+
+    uint32_t NoOfPlanes;
+}GMM_RESCREATE_CUSTOM_PARAMS;
+
 //===========================================================================
 // enum :
 //        GMM_UNIFIED_AUX_TYPE
diff --git a/Source/GmmLib/inc/Internal/Common/Texture/GmmTextureCalc.h b/Source/GmmLib/inc/Internal/Common/Texture/GmmTextureCalc.h
index 421903d..b31a065 100644
--- a/Source/GmmLib/inc/Internal/Common/Texture/GmmTextureCalc.h
+++ b/Source/GmmLib/inc/Internal/Common/Texture/GmmTextureCalc.h
@@ -165,11 +165,10 @@
                 return 0;
             }
 
-            void            SetTileMode(GMM_TEXTURE_INFO* pTexInfo);
-
         public:
             /* Constructors */
             // "Creates GmmTextureCalc object based on platform ID"
+            void            SetTileMode(GMM_TEXTURE_INFO* pTexInfo);
             static GmmTextureCalc* Create(PLATFORM Platform, uint8_t Override);
 
             static void IncrementRefCount()