xref: /aosp_15_r20/external/gmmlib/Source/GmmLib/Texture/GmmXe_LPGTexture.cpp (revision 35ffd701415c9e32e53136d61a677a8d0a8fc4a5)
1 /*==============================================================================
2 Copyright(c) 2022 Intel Corporation
3 
4 Permission is hereby granted, free of charge, to any person obtaining a
5 copy of this software and associated documentation files(the "Software"),
6 to deal in the Software without restriction, including without limitation
7 the rights to use, copy, modify, merge, publish, distribute, sublicense,
8 and / or sell copies of the Software, and to permit persons to whom the
9 Software is furnished to do so, subject to the following conditions:
10 
11 The above copyright notice and this permission notice shall be included
12 in all copies or substantial portions of the Software.
13 
14 THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
15 OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
16 FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
17 THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR
18 OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
19 ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
20 OTHER DEALINGS IN THE SOFTWARE.
21 ============================================================================*/
22 
23 #include "Internal/Common/GmmLibInc.h"
24 #include "Internal/Common/Texture/GmmGen10TextureCalc.h"
25 #include "Internal/Common/Texture/GmmGen11TextureCalc.h"
26 #include "Internal/Common/Texture/GmmGen12TextureCalc.h"
27 #include "Internal/Common/Texture/GmmXe_LPGTextureCalc.h"
28 
29 
30 /////////////////////////////////////////////////////////////////////////////////////
31 /// This function will Setup a planar surface allocation.
32 ///
33 /// @param[in]  pTexInfo: Reference to ::GMM_TEXTURE_INFO
34 /// @param[in]  pRestrictions: Reference to surface alignment and size restrictions.
35 ///
36 /// @return     ::GMM_STATUS
37 /////////////////////////////////////////////////////////////////////////////////////
FillTexPlanar(GMM_TEXTURE_INFO * pTexInfo,__GMM_BUFFER_TYPE * pRestrictions)38 GMM_STATUS GMM_STDCALL GmmLib::GmmXe_LPGTextureCalc::FillTexPlanar(GMM_TEXTURE_INFO * pTexInfo,
39                                                                    __GMM_BUFFER_TYPE *pRestrictions)
40 {
41     uint32_t   WidthBytesPhysical, Height, YHeight, VHeight;
42     uint32_t   AdjustedVHeight = 0;
43     GMM_STATUS Status;
44     bool       UVPacked = false;
45     uint32_t   BitsPerPixel, AlignedWidth;
46 
47     GMM_DPF_ENTER;
48 
49     __GMM_ASSERTPTR(pTexInfo, GMM_ERROR);
50     __GMM_ASSERTPTR(pRestrictions, GMM_ERROR);
51     __GMM_ASSERT(!pTexInfo->Flags.Info.TiledW);
52     const GMM_PLATFORM_INFO *pPlatform = GMM_OVERRIDE_PLATFORM_INFO(pTexInfo, pGmmLibContext);
53 
54     BitsPerPixel = pTexInfo->BitsPerPixel;
55     AlignedWidth = GFX_ULONG_CAST(pTexInfo->BaseWidth);
56 
57     if(!pTexInfo->Flags.Gpu.__NonMsaaTileYCcs)
58     {
59         pTexInfo->TileMode = TILE_NONE;
60     }
61     else
62     {
63         pTexInfo->TileMode = LEGACY_TILE_Y;
64     }
65 
66     WidthBytesPhysical = AlignedWidth * BitsPerPixel >> 3;
67     Height = VHeight = 0;
68 
69     YHeight = pTexInfo->BaseHeight;
70 
71     switch(pTexInfo->Format)
72     {
73         case GMM_FORMAT_IMC1: // IMC1 = IMC3 with Swapped U/V
74         case GMM_FORMAT_IMC3:
75         case GMM_FORMAT_MFX_JPEG_YUV420: // Same as IMC3.
76         // YYYYYYYY
77         // YYYYYYYY
78         // YYYYYYYY
79         // YYYYYYYY
80         // UUUU
81         // UUUU
82         // VVVV
83         // VVVV
84         case GMM_FORMAT_MFX_JPEG_YUV422V: // Similar to IMC3 but U/V are full width.
85             // YYYYYYYY
86             // YYYYYYYY
87             // YYYYYYYY
88             // YYYYYYYY
89             // UUUUUUUU
90             // UUUUUUUU
91             // VVVVVVVV
92             // VVVVVVVV
93             {
94                 VHeight = GFX_ALIGN(GFX_CEIL_DIV(YHeight, 2), GMM_IMCx_PLANE_ROW_ALIGNMENT);
95 
96                 YHeight = GFX_ALIGN(YHeight, GMM_IMCx_PLANE_ROW_ALIGNMENT);
97 
98                 Height                                      = YHeight + 2 * VHeight; // One VHeight for V and one for U.
99                 pTexInfo->OffsetInfo.PlaneXe_LPG.NoOfPlanes = 3;
100                 break;
101             }
102         case GMM_FORMAT_MFX_JPEG_YUV411R_TYPE: //Similar to IMC3 but U/V are quarther height and full width.
103             //YYYYYYYY
104             //YYYYYYYY
105             //YYYYYYYY
106             //YYYYYYYY
107             //UUUUUUUU
108             //VVVVVVVV
109             {
110                 VHeight = GFX_ALIGN(GFX_CEIL_DIV(YHeight, 4), GMM_IMCx_PLANE_ROW_ALIGNMENT);
111 
112                 YHeight = GFX_ALIGN(YHeight, GMM_IMCx_PLANE_ROW_ALIGNMENT);
113 
114                 Height                                      = YHeight + 2 * VHeight;
115                 pTexInfo->OffsetInfo.PlaneXe_LPG.NoOfPlanes = 3;
116                 break;
117             }
118         case GMM_FORMAT_MFX_JPEG_YUV411: // Similar to IMC3 but U/V are quarter width and full height.
119         // YYYYYYYY
120         // YYYYYYYY
121         // YYYYYYYY
122         // YYYYYYYY
123         // UU
124         // UU
125         // UU
126         // UU
127         // VV
128         // VV
129         // VV
130         // VV
131         case GMM_FORMAT_MFX_JPEG_YUV422H: // Similar to IMC3 but U/V are full height.
132         // YYYYYYYY
133         // YYYYYYYY
134         // YYYYYYYY
135         // YYYYYYYY
136         // UUUU
137         // UUUU
138         // UUUU
139         // UUUU
140         // VVVV
141         // VVVV
142         // VVVV
143         // VVVV
144         case GMM_FORMAT_MFX_JPEG_YUV444: // Similar to IMC3 but U/V are full size.
145 #if _WIN32
146         case GMM_FORMAT_WGBOX_YUV444:
147         case GMM_FORMAT_WGBOX_PLANAR_YUV444:
148 #endif
149             // YYYYYYYY
150             // YYYYYYYY
151             // YYYYYYYY
152             // YYYYYYYY
153             // UUUUUUUU
154             // UUUUUUUU
155             // UUUUUUUU
156             // UUUUUUUU
157             // VVVVVVVV
158             // VVVVVVVV
159             // VVVVVVVV
160             // VVVVVVVV
161             {
162                 YHeight = GFX_ALIGN(YHeight, GMM_IMCx_PLANE_ROW_ALIGNMENT);
163                 VHeight = YHeight;
164 
165                 Height                                      = YHeight + 2 * VHeight;
166                 pTexInfo->OffsetInfo.PlaneXe_LPG.NoOfPlanes = 3;
167                 break;
168             }
169         case GMM_FORMAT_BGRP:
170         case GMM_FORMAT_RGBP:
171         {
172             //For RGBP linear Tile keep resource Offset non aligned and for other Tile format to be 16-bit aligned
173             if(pTexInfo->Flags.Info.Linear)
174             {
175                 VHeight = YHeight;
176 
177                 Height                                      = YHeight + 2 * VHeight;
178                 pTexInfo->OffsetInfo.PlaneXe_LPG.NoOfPlanes = 3;
179             }
180             else
181             {
182                 YHeight = GFX_ALIGN(YHeight, GMM_IMCx_PLANE_ROW_ALIGNMENT);
183                 VHeight = YHeight;
184 
185                 Height                                      = YHeight + 2 * VHeight;
186                 pTexInfo->OffsetInfo.PlaneXe_LPG.NoOfPlanes = 3;
187             }
188             break;
189         }
190         case GMM_FORMAT_IMC2: // IMC2 = IMC4 with Swapped U/V
191         case GMM_FORMAT_IMC4:
192         {
193             // YYYYYYYY
194             // YYYYYYYY
195             // YYYYYYYY
196             // YYYYYYYY
197             // UUUUVVVV
198             // UUUUVVVV
199 
200             YHeight = GFX_ALIGN(YHeight, GMM_IMCx_PLANE_ROW_ALIGNMENT);
201             VHeight = GFX_CEIL_DIV(YHeight, 2);
202 
203             WidthBytesPhysical = GFX_ALIGN(WidthBytesPhysical, 2); // If odd YWidth, pitch bumps-up to fit rounded-up U/V planes.
204 
205             Height = YHeight + VHeight;
206 
207             // With SURFACE_STATE.XOffset support, the U-V interface has
208             // much lighter restrictions--which will be naturally met by
209             // surface pitch restrictions (i.e. dividing an IMC2/4 pitch
210             // by 2--to get the U/V interface--will always produce a safe
211             // XOffset value).
212             // Not technically UV packed but sizing works out the same
213             // if the resource is std swizzled
214             UVPacked                                    = true;
215             pTexInfo->OffsetInfo.PlaneXe_LPG.NoOfPlanes = 2;
216             break;
217         }
218         case GMM_FORMAT_NV12:
219         case GMM_FORMAT_NV21:
220         case GMM_FORMAT_NV11:
221         case GMM_FORMAT_P010:
222         case GMM_FORMAT_P012:
223         case GMM_FORMAT_P016:
224         case GMM_FORMAT_P208:
225         case GMM_FORMAT_P216:
226         {
227             // YYYYYYYY
228             // YYYYYYYY
229             // YYYYYYYY
230             // YYYYYYYY
231             // [UV-Packing]
232 
233             if((pTexInfo->Format == GMM_FORMAT_NV12) ||
234                (pTexInfo->Format == GMM_FORMAT_NV21) ||
235                (pTexInfo->Format == GMM_FORMAT_P010) ||
236                (pTexInfo->Format == GMM_FORMAT_P012) ||
237                (pTexInfo->Format == GMM_FORMAT_P016))
238             {
239                 VHeight = GFX_CEIL_DIV(YHeight, 2); // U/V plane half of Y
240                 Height  = YHeight + VHeight;
241             }
242             else
243             {
244                 VHeight = YHeight; // U/V plane is same as Y
245                 Height  = YHeight + VHeight;
246             }
247 
248             if((pTexInfo->Format == GMM_FORMAT_NV12) ||
249                (pTexInfo->Format == GMM_FORMAT_NV21) ||
250                (pTexInfo->Format == GMM_FORMAT_P010) ||
251                (pTexInfo->Format == GMM_FORMAT_P012) ||
252                (pTexInfo->Format == GMM_FORMAT_P016) ||
253                (pTexInfo->Format == GMM_FORMAT_P208) ||
254                (pTexInfo->Format == GMM_FORMAT_P216))
255             {
256                 WidthBytesPhysical                          = GFX_ALIGN(WidthBytesPhysical, 2); // If odd YWidth, pitch bumps-up to fit rounded-up U/V planes.
257                 pTexInfo->OffsetInfo.PlaneXe_LPG.NoOfPlanes = 2;
258             }
259             else //if(pTexInfo->Format == GMM_FORMAT_NV11)
260             {
261                 // Tiling not supported, since YPitch != UVPitch...
262                 pTexInfo->Flags.Info.TiledYf = 0;
263                 pTexInfo->Flags.Info.TiledX  = 0;
264                 pTexInfo->Flags.Info.Linear  = 1;
265                 GMM_SET_64KB_TILE(pTexInfo->Flags, 0, pGmmLibContext);
266                 GMM_SET_4KB_TILE(pTexInfo->Flags, 0, pGmmLibContext);
267             }
268 
269             UVPacked = true;
270             break;
271         }
272         case GMM_FORMAT_I420: // IYUV & I420: are identical to YV12 except,
273         case GMM_FORMAT_IYUV: // U & V pl.s are reversed.
274         case GMM_FORMAT_YV12:
275         case GMM_FORMAT_YVU9:
276         {
277             // YYYYYYYY
278             // YYYYYYYY
279             // YYYYYYYY
280             // YYYYYYYY
281             // VVVVVV..  <-- V and U planes follow the Y plane, as linear
282             // ..UUUUUU      arrays--without respect to pitch.
283 
284             uint32_t YSize, UVSize, YVSizeRShift;
285             uint32_t YSizeForUVPurposes, YSizeForUVPurposesDimensionalAlignment;
286 
287             YSize = WidthBytesPhysical * YHeight;
288 
289             // YVU9 has one U/V pixel for each 4x4 Y block.
290             // The others have one U/V pixel for each 2x2 Y block.
291 
292             // YVU9 has a Y:V size ratio of 16 (4x4 --> 1).
293             // The others have a ratio of 4 (2x2 --> 1).
294             YVSizeRShift = (pTexInfo->Format != GMM_FORMAT_YVU9) ? 2 : 4;
295 
296             // If a Y plane isn't fully-aligned to its Y-->U/V block size, the
297             // extra/unaligned Y pixels still need corresponding U/V pixels--So
298             // for the purpose of computing the UVSize, we must consider a
299             // dimensionally "rounded-up" YSize. (E.g. a 13x5 YVU9 Y plane would
300             // require 4x2 U/V planes--the same UVSize as a fully-aligned 16x8 Y.)
301             YSizeForUVPurposesDimensionalAlignment = (pTexInfo->Format != GMM_FORMAT_YVU9) ? 2 : 4;
302             YSizeForUVPurposes =
303             GFX_ALIGN(WidthBytesPhysical, YSizeForUVPurposesDimensionalAlignment) *
304             GFX_ALIGN(YHeight, YSizeForUVPurposesDimensionalAlignment);
305 
306             UVSize = 2 * // <-- U + V
307                      (YSizeForUVPurposes >> YVSizeRShift);
308 
309             Height = GFX_CEIL_DIV(YSize + UVSize, WidthBytesPhysical);
310 
311             // Tiling not supported, since YPitch != UVPitch...
312             pTexInfo->Flags.Info.TiledYf                = 0;
313             pTexInfo->Flags.Info.TiledX                 = 0;
314             pTexInfo->Flags.Info.Linear                 = 1;
315             pTexInfo->OffsetInfo.PlaneXe_LPG.NoOfPlanes = 1;
316             GMM_SET_64KB_TILE(pTexInfo->Flags, 0, pGmmLibContext);
317             GMM_SET_4KB_TILE(pTexInfo->Flags, 0, pGmmLibContext);
318 
319             break;
320         }
321         default:
322         {
323             GMM_ASSERTDPF(0, "Unexpected format");
324             return GMM_ERROR;
325         }
326     }
327 
328     // Align Height to even row to avoid hang if HW over-fetch
329     Height = GFX_ALIGN(Height, __GMM_EVEN_ROW);
330 
331     SetTileMode(pTexInfo);
332 
333     // If the Surface has Odd height dimension, we will fall back to Linear Format.
334     // If MMC is enabled, disable MMC during such cases.
335     if(pTexInfo->Flags.Gpu.MMC)
336     {
337         if(!(GMM_IS_4KB_TILE(pTexInfo->Flags) || GMM_IS_64KB_TILE(pTexInfo->Flags)))
338         {
339             pTexInfo->Flags.Gpu.MMC = 0;
340         }
341     }
342 
343     // If the Surface has Odd height dimension, we will fall back to Linear Format.
344     // If MMC is enabled, disable .CCS/UnifiedAuxSurface during such cases.
345     if(pTexInfo->Flags.Gpu.CCS)
346     {
347         if(!(GMM_IS_4KB_TILE(pTexInfo->Flags) || GMM_IS_64KB_TILE(pTexInfo->Flags)) &&
348            !(pTexInfo->Flags.Gpu.__NonMsaaTileYCcs && GMM_IS_4KB_TILE(pTexInfo->Flags)))
349         {
350             pTexInfo->Flags.Gpu.MMC               = 0;
351             pTexInfo->Flags.Gpu.CCS               = 0;
352             pTexInfo->Flags.Gpu.UnifiedAuxSurface = 0;
353             pTexInfo->Flags.Gpu.__NonMsaaTileYCcs = 0;
354         }
355     }
356 
357     // Legacy Planar "Linear Video" Restrictions...
358     if(pTexInfo->Flags.Info.Linear && !pTexInfo->Flags.Wa.NoLegacyPlanarLinearVideoRestrictions)
359     {
360         pRestrictions->LockPitchAlignment   = GFX_MAX(pRestrictions->LockPitchAlignment, GMM_BYTES(64));
361         pRestrictions->MinPitch             = GFX_MAX(pRestrictions->MinPitch, GMM_BYTES(64));
362         pRestrictions->PitchAlignment       = GFX_MAX(pRestrictions->PitchAlignment, GMM_BYTES(64));
363         pRestrictions->RenderPitchAlignment = GFX_MAX(pRestrictions->RenderPitchAlignment, GMM_BYTES(64));
364     }
365 
366     // Multiply overall pitch alignment for surfaces whose U/V planes have a
367     // pitch down-scaled from that of Y--Since the U/V pitches must meet the
368     // original restriction, the Y pitch must meet a scaled-up multiple.
369     if((pTexInfo->Format == GMM_FORMAT_I420) ||
370        (pTexInfo->Format == GMM_FORMAT_IYUV) ||
371        (pTexInfo->Format == GMM_FORMAT_NV11) ||
372        (pTexInfo->Format == GMM_FORMAT_YV12) ||
373        (pTexInfo->Format == GMM_FORMAT_YVU9))
374     {
375         uint32_t LShift =
376         (pTexInfo->Format != GMM_FORMAT_YVU9) ?
377         1 : // UVPitch = 1/2 YPitch
378         2;  // UVPitch = 1/4 YPitch
379 
380         pRestrictions->LockPitchAlignment <<= LShift;
381         pRestrictions->MinPitch <<= LShift;
382         pRestrictions->PitchAlignment <<= LShift;
383         pRestrictions->RenderPitchAlignment <<= LShift;
384     }
385 
386     AdjustedVHeight = VHeight;
387 
388     FindMipTailStartLod(pTexInfo);
389 
390     // In case of Planar surfaces, only the last Plane has to be aligned to 64 for LCU access
391     if(pGmmLibContext->GetWaTable().WaAlignYUVResourceToLCU && GmmIsYUVFormatLCUAligned(pTexInfo->Format) && VHeight > 0)
392     {
393         AdjustedVHeight = GFX_ALIGN(VHeight, GMM_SCANLINES(GMM_MAX_LCU_SIZE));
394         Height += AdjustedVHeight - VHeight;
395     }
396 
397     // For std swizzled and UV packed tile Ys/Yf cases, the planes
398     // must be tile-boundary aligned. Actual alignment is handled
399     // in FillPlanarOffsetAddress, but height and width must
400     // be adjusted for correct size calculation
401     if(GMM_IS_TILED(pPlatform->TileInfo[pTexInfo->TileMode]) &&
402        !pTexInfo->Flags.Gpu.__NonMsaaTileYCcs)
403     {
404         uint32_t TileHeight = pGmmLibContext->GetPlatformInfo().TileInfo[pTexInfo->TileMode].LogicalTileHeight;
405         uint32_t TileWidth  = pGmmLibContext->GetPlatformInfo().TileInfo[pTexInfo->TileMode].LogicalTileWidth;
406 
407         pTexInfo->OffsetInfo.PlaneXe_LPG.IsTileAlignedPlanes = true;
408 
409         if(pTexInfo->Flags.Gpu.CCS && !pGmmLibContext->GetSkuTable().FtrFlatPhysCCS) // alignment adjustment needed only for aux tables
410         {
411             if(GMM_IS_64KB_TILE(pTexInfo->Flags))
412             {
413                 TileHeight *= (!WA64K(pGmmLibContext) && !WA16K(pGmmLibContext)) ? 16 : 1; // For 64Kb Tile mode: Multiply TileHeight by 16 for 1 MB alignment
414             }
415             else
416             {
417                 TileHeight *= (WA16K(pGmmLibContext) ? 1 : WA64K(pGmmLibContext) ? 4 : 64); // For 4k Tile:  Multiply TileHeight by 4 and Pitch by 4 for 64kb alignment, multiply TileHeight by 64 and Pitch by 4 for 1 MB alignment
418             }
419         }
420 
421         if(pTexInfo->Format == GMM_FORMAT_IMC2 || // IMC2, IMC4 needs even tile columns
422            pTexInfo->Format == GMM_FORMAT_IMC4)
423         {
424             // If the U & V planes are side-by-side then the surface pitch must be
425             // padded out so that U and V planes will being on a tile boundary.
426             // This means that an odd Y plane width must be padded out
427             // with an additional tile. Even widths do not need padding
428             uint32_t TileCols = GFX_CEIL_DIV(WidthBytesPhysical, TileWidth);
429             if(TileCols % 2)
430             {
431                 WidthBytesPhysical = (TileCols + 1) * TileWidth;
432             }
433         }
434 
435         Height = GFX_ALIGN(YHeight, TileHeight) + (UVPacked ? GFX_ALIGN(AdjustedVHeight, TileHeight) :
436                                                               (GFX_ALIGN(VHeight, TileHeight) + GFX_ALIGN(AdjustedVHeight, TileHeight)));
437 
438         if(GMM_IS_64KB_TILE(pTexInfo->Flags) || pTexInfo->Flags.Info.TiledYf)
439         {
440             pTexInfo->Flags.Info.RedecribedPlanes = true;
441         }
442     }
443     else if(pTexInfo->Flags.Gpu.__NonMsaaTileYCcs)
444     {
445         uint32_t TileHeight = pGmmLibContext->GetPlatformInfo().TileInfo[pTexInfo->TileMode].LogicalTileHeight;
446 
447         BitsPerPixel = 8;
448 
449         if(pTexInfo->Format == GMM_FORMAT_IMC2 || // IMC2, IMC4 needs even tile columns
450            pTexInfo->Format == GMM_FORMAT_IMC4)
451         {
452 // If the U & V planes are side-by-side then the surface pitch must be
453 // padded out so that U and V planes will being on a tile boundary.
454 // This means that an odd Y plane width must be padded out
455 // with an additional tile. Even widths do not need padding
456 
457 // CCS must use padded main surface width, so get main surface TileWidth
458 #define CCSMODE_TO_TILEMODE(y) ((y + TILE_YF_2D_8bpe) < TILE_YS_1D_8bpe) ? (y + TILE_YF_2D_8bpe) : \
459                                                                            ((y + TILE_YF_2D_8bpe + 5) >= TILE_YS_1D_128bpe) ? (y + TILE_YF_2D_8bpe + 5) : TILE_NONE
460 
461             uint32_t BaseTileWidth = pPlatform->TileInfo[CCSMODE_TO_TILEMODE(pTexInfo->CCSModeAlign)].LogicalTileWidth;
462             WidthBytesPhysical     = GFX_ALIGN(WidthBytesPhysical, 2 * BaseTileWidth);
463         }
464 
465         AlignedWidth = GFX_ULONG_CAST(WidthBytesPhysical / (pTexInfo->BitsPerPixel >> 3));
466 
467         WidthBytesPhysical = __GMM_EXPAND_WIDTH(this, AlignedWidth, pTexInfo->Alignment.HAlign, pTexInfo);
468         WidthBytesPhysical = ScaleTextureWidth(pTexInfo, WidthBytesPhysical); //Should both YAux and UVAux use same CCModeALign (ie using common bpe?)
469                                                                               //If different, then copy Aux info from per-plane Aux? HW has separate bpe or common?
470         YHeight = __GMM_EXPAND_HEIGHT(this, YHeight, pTexInfo->Alignment.VAlign, pTexInfo);
471         YHeight = ScaleTextureHeight(pTexInfo, YHeight);
472         YHeight = GFX_ALIGN(YHeight, TileHeight);
473 
474         VHeight = __GMM_EXPAND_HEIGHT(this, VHeight, pTexInfo->Alignment.VAlign, pTexInfo);
475         VHeight = ScaleTextureHeight(pTexInfo, VHeight);
476         VHeight = GFX_ALIGN(VHeight, TileHeight);
477 
478         Height = YHeight + VHeight;
479     }
480 
481     if(pTexInfo->Flags.Info.RedecribedPlanes)
482     {
483         if(false == RedescribeTexturePlanes(pTexInfo, &WidthBytesPhysical))
484         {
485             __GMM_ASSERT(false);
486         }
487     }
488     if((Status = // <-- Note assignment.
489         FillTexPitchAndSize(
490         pTexInfo, WidthBytesPhysical, Height, pRestrictions)) == GMM_SUCCESS)
491     {
492         FillPlanarOffsetAddress(pTexInfo);
493     }
494 
495     // Planar & hybrid 2D arrays supported in DX11.1+ spec but not HW. Memory layout
496     // is defined by SW requirements; Y plane must be 4KB aligned.
497     if(pTexInfo->ArraySize > 1)
498     {
499         GMM_GFX_SIZE_T ElementSizeBytes = pTexInfo->Size;
500         int64_t        LargeSize;
501 
502         // Size should always be page aligned.
503         __GMM_ASSERT((pTexInfo->Size % PAGE_SIZE) == 0);
504 
505         if((LargeSize = (int64_t)ElementSizeBytes * pTexInfo->ArraySize) <= pPlatform->SurfaceMaxSize)
506         {
507             pTexInfo->OffsetInfo.PlaneXe_LPG.ArrayQPitch = ElementSizeBytes;
508             pTexInfo->Size                               = LargeSize;
509         }
510         else
511         {
512             GMM_ASSERTDPF(0, "Surface too large!");
513             Status = GMM_ERROR;
514         }
515     }
516 
517     GMM_DPF_EXIT;
518     return (Status);
519 } // FillTexPlanar
520 
521 /////////////////////////////////////////////////////////////////////////////////////
522 /// This function calculates the (X,Y) address of each given plane. X is in bytes
523 /// and Y is in scanlines.
524 ///
525 /// @param[in]  pTexInfo: ptr to ::GMM_TEXTURE_INFO
526 ///
527 /////////////////////////////////////////////////////////////////////////////////////
FillPlanarOffsetAddress(GMM_TEXTURE_INFO * pTexInfo)528 void GmmLib::GmmXe_LPGTextureCalc::FillPlanarOffsetAddress(GMM_TEXTURE_INFO *pTexInfo)
529 {
530     GMM_GFX_SIZE_T *pUOffsetX, *pUOffsetY;
531     GMM_GFX_SIZE_T *pVOffsetX, *pVOffsetY;
532     uint32_t        YHeight = 0, VHeight = 0;
533     bool            UVPacked = false;
534     uint32_t        Height;
535     uint32_t        WidthBytesPhysical = GFX_ULONG_CAST(pTexInfo->BaseWidth) * pTexInfo->BitsPerPixel >> 3;
536 
537 #define SWAP_UV()              \
538     {                          \
539         GMM_GFX_SIZE_T *pTemp; \
540                                \
541         pTemp     = pUOffsetX; \
542         pUOffsetX = pVOffsetX; \
543         pVOffsetX = pTemp;     \
544                                \
545         pTemp     = pUOffsetY; \
546         pUOffsetY = pVOffsetY; \
547         pVOffsetY = pTemp;     \
548     }
549 
550     __GMM_ASSERTPTR(pTexInfo, VOIDRETURN);
551     __GMM_ASSERTPTR(((pTexInfo->TileMode < GMM_TILE_MODES) && (pTexInfo->TileMode >= TILE_NONE)), VOIDRETURN);
552     GMM_DPF_ENTER;
553 
554     const GMM_PLATFORM_INFO *pPlatform = GMM_OVERRIDE_PLATFORM_INFO(pTexInfo, pGmmLibContext);
555 
556     // GMM_PLANE_Y always at (0, 0)...
557     pTexInfo->OffsetInfo.PlaneXe_LPG.X[GMM_PLANE_Y] = 0;
558     pTexInfo->OffsetInfo.PlaneXe_LPG.Y[GMM_PLANE_Y] = 0;
559 
560     pTexInfo->OffsetInfo.PlaneXe_LPG.UnAligned.Height[GMM_PLANE_Y] = 0;
561     pTexInfo->OffsetInfo.PlaneXe_LPG.UnAligned.Height[GMM_PLANE_Y] = 0;
562 
563     Height = pTexInfo->BaseHeight;
564     if(pTexInfo->Flags.Gpu.__NonMsaaTileYCcs)
565     {
566         Height = __GMM_EXPAND_HEIGHT(this, Height, pTexInfo->Alignment.VAlign, pTexInfo);
567         Height = ScaleTextureHeight(pTexInfo, Height);
568         if(pTexInfo->Flags.Gpu.UnifiedAuxSurface)
569         {
570             pTexInfo->OffsetInfo.PlaneXe_LPG.Y[GMM_PLANE_Y] = 0;
571         }
572     }
573 
574     // GMM_PLANE_U/V Planes...
575     pUOffsetX = &pTexInfo->OffsetInfo.PlaneXe_LPG.X[GMM_PLANE_U];
576     pUOffsetY = &pTexInfo->OffsetInfo.PlaneXe_LPG.Y[GMM_PLANE_U];
577     pVOffsetX = &pTexInfo->OffsetInfo.PlaneXe_LPG.X[GMM_PLANE_V];
578     pVOffsetY = &pTexInfo->OffsetInfo.PlaneXe_LPG.Y[GMM_PLANE_V];
579 
580     switch(pTexInfo->Format)
581     {
582         case GMM_FORMAT_IMC1:
583             SWAP_UV(); // IMC1 = IMC3 with Swapped U/V
584         case GMM_FORMAT_IMC3:
585         case GMM_FORMAT_MFX_JPEG_YUV420:  // Same as IMC3.
586                                           // YYYYYYYY
587                                           // YYYYYYYY
588                                           // YYYYYYYY
589                                           // YYYYYYYY
590                                           // UUUU
591                                           // UUUU
592                                           // VVVV
593                                           // VVVV
594         case GMM_FORMAT_MFX_JPEG_YUV422V: // Similar to IMC3 but U/V are full width.
595                                           // YYYYYYYY
596                                           // YYYYYYYY
597                                           // YYYYYYYY
598                                           // YYYYYYYY
599                                           // UUUUUUUU
600                                           // UUUUUUUU
601                                           // VVVVVVVV
602                                           // VVVVVVVV
603             {
604                 *pUOffsetX = 0;
605                 YHeight    = GFX_ALIGN(pTexInfo->BaseHeight, GMM_IMCx_PLANE_ROW_ALIGNMENT);
606                 *pUOffsetY = GFX_ALIGN(pTexInfo->BaseHeight, GMM_IMCx_PLANE_ROW_ALIGNMENT);
607 
608                 *pVOffsetX = 0;
609                 VHeight    = GFX_ALIGN(GFX_CEIL_DIV(pTexInfo->BaseHeight, 2), GMM_IMCx_PLANE_ROW_ALIGNMENT);
610                 *pVOffsetY =
611                 GFX_ALIGN(pTexInfo->BaseHeight, GMM_IMCx_PLANE_ROW_ALIGNMENT) +
612                 GFX_ALIGN(GFX_CEIL_DIV(pTexInfo->BaseHeight, 2), GMM_IMCx_PLANE_ROW_ALIGNMENT);
613 
614                 break;
615             }
616         case GMM_FORMAT_MFX_JPEG_YUV411R_TYPE: //Similar to IMC3 but U/V are quarther height and full width.
617                                                //YYYYYYYY
618                                                //YYYYYYYY
619                                                //YYYYYYYY
620                                                //YYYYYYYY
621                                                //UUUUUUUU
622                                                //VVVVVVVV
623             {
624                 *pUOffsetX = 0;
625                 YHeight    = GFX_ALIGN(pTexInfo->BaseHeight, GMM_IMCx_PLANE_ROW_ALIGNMENT);
626                 *pUOffsetY = GFX_ALIGN(pTexInfo->BaseHeight, GMM_IMCx_PLANE_ROW_ALIGNMENT);
627 
628                 *pVOffsetX = 0;
629                 VHeight    = GFX_ALIGN(GFX_CEIL_DIV(pTexInfo->BaseHeight, 4), GMM_IMCx_PLANE_ROW_ALIGNMENT);
630                 *pVOffsetY =
631                 GFX_ALIGN(pTexInfo->BaseHeight, GMM_IMCx_PLANE_ROW_ALIGNMENT) +
632                 GFX_ALIGN(GFX_CEIL_DIV(pTexInfo->BaseHeight, 4), GMM_IMCx_PLANE_ROW_ALIGNMENT);
633 
634                 break;
635             }
636         case GMM_FORMAT_MFX_JPEG_YUV411:  // Similar to IMC3 but U/V are quarter width and full height.
637                                           // YYYYYYYY
638                                           // YYYYYYYY
639                                           // YYYYYYYY
640                                           // YYYYYYYY
641                                           // UU
642                                           // UU
643                                           // UU
644                                           // UU
645                                           // VV
646                                           // VV
647                                           // VV
648                                           // VV
649         case GMM_FORMAT_MFX_JPEG_YUV422H: // Similar to IMC3 but U/V are full height.
650                                           // YYYYYYYY
651                                           // YYYYYYYY
652                                           // YYYYYYYY
653                                           // YYYYYYYY
654                                           // UUUU
655                                           // UUUU
656                                           // UUUU
657                                           // UUUU
658                                           // VVVV
659                                           // VVVV
660                                           // VVVV
661                                           // VVVV
662         case GMM_FORMAT_MFX_JPEG_YUV444:  // Similar to IMC3 but U/V are full size.
663                                           // YYYYYYYY
664                                           // YYYYYYYY
665                                           // YYYYYYYY
666                                           // YYYYYYYY
667                                           // UUUUUUUU
668                                           // UUUUUUUU
669                                           // UUUUUUUU
670                                           // UUUUUUUU
671                                           // VVVVVVVV
672                                           // VVVVVVVV
673                                           // VVVVVVVV
674                                           // VVVVVVVV
675             {
676                 *pUOffsetX = 0;
677                 YHeight    = GFX_ALIGN(pTexInfo->BaseHeight, GMM_IMCx_PLANE_ROW_ALIGNMENT);
678                 *pUOffsetY = GFX_ALIGN(pTexInfo->BaseHeight, GMM_IMCx_PLANE_ROW_ALIGNMENT);
679 
680                 *pVOffsetX = 0;
681                 VHeight    = GFX_ALIGN(pTexInfo->BaseHeight, GMM_IMCx_PLANE_ROW_ALIGNMENT);
682                 *pVOffsetY = GFX_ALIGN(pTexInfo->BaseHeight, GMM_IMCx_PLANE_ROW_ALIGNMENT) * 2;
683 
684                 break;
685             }
686         case GMM_FORMAT_BGRP:
687         case GMM_FORMAT_RGBP:
688         {
689             //For RGBP linear Tile keep resource Offset non aligned and for other Tile format to be 16-bit aligned
690             if(pTexInfo->Flags.Info.Linear)
691             {
692                 *pUOffsetX = 0;
693                 YHeight    = pTexInfo->BaseHeight;
694                 *pUOffsetY = pTexInfo->BaseHeight;
695 
696                 *pVOffsetX = 0;
697                 VHeight    = pTexInfo->BaseHeight;
698                 *pVOffsetY = (GMM_GFX_SIZE_T)pTexInfo->BaseHeight * 2;
699             }
700             else //Tiled
701             {
702                 *pUOffsetX = 0;
703                 YHeight    = GFX_ALIGN(pTexInfo->BaseHeight, GMM_IMCx_PLANE_ROW_ALIGNMENT);
704                 *pUOffsetY = GFX_ALIGN(pTexInfo->BaseHeight, GMM_IMCx_PLANE_ROW_ALIGNMENT);
705 
706                 *pVOffsetX = 0;
707                 VHeight    = GFX_ALIGN(pTexInfo->BaseHeight, GMM_IMCx_PLANE_ROW_ALIGNMENT);
708                 *pVOffsetY = (GMM_GFX_SIZE_T)GFX_ALIGN(pTexInfo->BaseHeight, GMM_IMCx_PLANE_ROW_ALIGNMENT) * 2;
709             }
710             break;
711         }
712         case GMM_FORMAT_IMC2:
713             SWAP_UV(); // IMC2 = IMC4 with Swapped U/V
714         case GMM_FORMAT_IMC4:
715         {
716             // YYYYYYYY
717             // YYYYYYYY
718             // YYYYYYYY
719             // YYYYYYYY
720             // UUUUVVVV
721             // UUUUVVVV
722 
723             __GMM_ASSERT((pTexInfo->Pitch & 1) == 0);
724 
725             *pUOffsetX = 0;
726             YHeight    = GFX_ALIGN(pTexInfo->BaseHeight, GMM_IMCx_PLANE_ROW_ALIGNMENT);
727             *pUOffsetY = GFX_ALIGN(pTexInfo->BaseHeight, GMM_IMCx_PLANE_ROW_ALIGNMENT);
728 
729             *pVOffsetX = pTexInfo->Pitch / 2;
730             VHeight    = GFX_CEIL_DIV(YHeight, 2);
731             *pVOffsetY = GFX_ALIGN(pTexInfo->BaseHeight, GMM_IMCx_PLANE_ROW_ALIGNMENT);
732 
733             // Not technically UV packed but sizing works out the same
734             UVPacked = true;
735 
736             break;
737         }
738         case GMM_FORMAT_I420: // I420 = IYUV
739         case GMM_FORMAT_IYUV:
740             SWAP_UV(); // I420/IYUV = YV12 with Swapped U/V
741         case GMM_FORMAT_YV12:
742         case GMM_FORMAT_YVU9:
743         {
744             // YYYYYYYY
745             // YYYYYYYY
746             // YYYYYYYY
747             // YYYYYYYY
748             // VVVVVV..  <-- V and U planes follow the Y plane, as linear
749             // ..UUUUUU      arrays--without respect to pitch.
750 
751             uint32_t YSize, YVSizeRShift, VSize, UOffset;
752             uint32_t YSizeForUVPurposes, YSizeForUVPurposesDimensionalAlignment;
753 
754             YSize = GFX_ULONG_CAST(pTexInfo->Pitch) * pTexInfo->BaseHeight;
755 
756             // YVU9 has one U/V pixel for each 4x4 Y block.
757             // The others have one U/V pixel for each 2x2 Y block.
758 
759             // YVU9 has a Y:V size ratio of 16 (4x4 --> 1).
760             // The others have a ratio of 4 (2x2 --> 1).
761             YVSizeRShift = (pTexInfo->Format != GMM_FORMAT_YVU9) ? 2 : 4;
762 
763             // If a Y plane isn't fully-aligned to its Y-->U/V block size, the
764             // extra/unaligned Y pixels still need corresponding U/V pixels--So
765             // for the purpose of computing the UVSize, we must consider a
766             // dimensionally "rounded-up" YSize. (E.g. a 13x5 YVU9 Y plane would
767             // require 4x2 U/V planes--the same UVSize as a fully-aligned 16x8 Y.)
768             YSizeForUVPurposesDimensionalAlignment = (pTexInfo->Format != GMM_FORMAT_YVU9) ? 2 : 4;
769             YSizeForUVPurposes =
770             GFX_ALIGN(GFX_ULONG_CAST(pTexInfo->Pitch), YSizeForUVPurposesDimensionalAlignment) *
771             GFX_ALIGN(pTexInfo->BaseHeight, YSizeForUVPurposesDimensionalAlignment);
772 
773             VSize   = (YSizeForUVPurposes >> YVSizeRShift);
774             UOffset = YSize + VSize;
775 
776             *pVOffsetX = 0;
777             *pVOffsetY = pTexInfo->BaseHeight;
778 
779             *pUOffsetX = UOffset % pTexInfo->Pitch;
780             *pUOffsetY = UOffset / pTexInfo->Pitch;
781 
782             YHeight = GFX_CEIL_DIV(YSize + 2 * VSize, WidthBytesPhysical);
783 
784             break;
785         }
786         case GMM_FORMAT_NV12:
787         case GMM_FORMAT_NV21:
788         case GMM_FORMAT_NV11:
789         case GMM_FORMAT_P010:
790         case GMM_FORMAT_P012:
791         case GMM_FORMAT_P016:
792         case GMM_FORMAT_P208:
793         case GMM_FORMAT_P216:
794         {
795             // YYYYYYYY
796             // YYYYYYYY
797             // YYYYYYYY
798             // YYYYYYYY
799             // [UV-Packing]
800             *pUOffsetX = *pVOffsetX = 0;
801             YHeight                 = GFX_ALIGN(Height, __GMM_EVEN_ROW);
802             *pUOffsetY = *pVOffsetY = YHeight;
803 
804             if((pTexInfo->Format == GMM_FORMAT_NV12) ||
805                (pTexInfo->Format == GMM_FORMAT_NV21) ||
806                (pTexInfo->Format == GMM_FORMAT_P010) ||
807                (pTexInfo->Format == GMM_FORMAT_P012) ||
808                (pTexInfo->Format == GMM_FORMAT_P016))
809             {
810                 VHeight = GFX_CEIL_DIV(Height, 2);
811             }
812             else
813             {
814                 VHeight = YHeight; // U/V plane is same as Y
815             }
816 
817             UVPacked = true;
818             break;
819         }
820         default:
821         {
822             GMM_ASSERTDPF(0, "Unknown Video Format U\n");
823             break;
824         }
825     }
826 
827     pTexInfo->OffsetInfo.PlaneXe_LPG.UnAligned.Height[GMM_PLANE_Y] = YHeight;
828     if(pTexInfo->OffsetInfo.PlaneXe_LPG.NoOfPlanes == 2)
829     {
830         pTexInfo->OffsetInfo.PlaneXe_LPG.UnAligned.Height[GMM_PLANE_U] = VHeight;
831     }
832     else if(pTexInfo->OffsetInfo.PlaneXe_LPG.NoOfPlanes == 3)
833     {
834         pTexInfo->OffsetInfo.PlaneXe_LPG.UnAligned.Height[GMM_PLANE_U] =
835         pTexInfo->OffsetInfo.PlaneXe_LPG.UnAligned.Height[GMM_PLANE_V] = VHeight;
836     }
837 
838     if(GMM_IS_TILED(pPlatform->TileInfo[pTexInfo->TileMode]) || pTexInfo->Flags.Gpu.__NonMsaaTileYCcs)
839     {
840         uint32_t TileHeight         = pPlatform->TileInfo[pTexInfo->TileMode].LogicalTileHeight;
841         uint32_t TileWidth          = pPlatform->TileInfo[pTexInfo->TileMode].LogicalTileWidth;
842         uint32_t PhysicalTileHeight = TileHeight;
843 
844         if(GFX_GET_CURRENT_RENDERCORE(pPlatform->Platform) > IGFX_GEN11LP_CORE)
845         {
846             if(pTexInfo->Flags.Gpu.CCS && !pGmmLibContext->GetSkuTable().FtrFlatPhysCCS)
847             {
848                 //U/V must be aligned to AuxT granularity, 4x pitchalign enforces 16K-align for 4KB tile,
849                 //add extra padding for 64K AuxT, 1MB AuxT
850                 if(GMM_IS_64KB_TILE(pTexInfo->Flags))
851                 {
852                     TileHeight *= (!WA64K(pGmmLibContext) && !WA16K(pGmmLibContext)) ? 16 : 1; // For 64Kb Tile mode: Multiply TileHeight by 16 for 1 MB alignment
853                 }
854                 else
855                 {
856                     PhysicalTileHeight *= (WA16K(pGmmLibContext) ? 1 : WA64K(pGmmLibContext) ? 4 : 1); //  for 1 MB AuxT granularity, we do 1 MB alignment only in VA space and not in physical space, so do not multiply PhysicalTileHeight with 64 here
857                     TileHeight *= (WA16K(pGmmLibContext) ? 1 : WA64K(pGmmLibContext) ? 4 : 64);        // For 4k Tile:  Multiply TileHeight by 4 and Pitch by 4 for 64kb alignment, multiply TileHeight by 64 and Pitch by 4 for 1 MB alignment
858                 }
859                 if(!WA64K(pGmmLibContext) && !WA16K(pGmmLibContext))
860                 {
861                     pTexInfo->OffsetInfo.PlaneXe_LPG.Is1MBAuxTAlignedPlanes       = true;
862                     pTexInfo->OffsetInfo.PlaneXe_LPG.Physical.Height[GMM_PLANE_Y] = GFX_ALIGN(YHeight, PhysicalTileHeight); // confirm tilealignment is needed for physivcal backing, else calculate size from unaligned offset and use the same
863                     if(pTexInfo->OffsetInfo.PlaneXe_LPG.NoOfPlanes == 2)
864                     {
865                         pTexInfo->OffsetInfo.PlaneXe_LPG.Physical.Height[GMM_PLANE_U] = GFX_ALIGN(VHeight, PhysicalTileHeight);
866                     }
867                     else if(pTexInfo->OffsetInfo.PlaneXe_LPG.NoOfPlanes == 3)
868                     {
869                         pTexInfo->OffsetInfo.PlaneXe_LPG.Physical.Height[GMM_PLANE_U] =
870                         pTexInfo->OffsetInfo.PlaneXe_LPG.Physical.Height[GMM_PLANE_V] = GFX_ALIGN(VHeight, PhysicalTileHeight);
871                     }
872                 }
873             }
874         }
875 
876         *pUOffsetX = GFX_ALIGN(*pUOffsetX, TileWidth);
877         *pUOffsetY = GFX_ALIGN(*pUOffsetY, TileHeight);
878         *pVOffsetX = GFX_ALIGN(*pVOffsetX, TileWidth);
879         *pVOffsetY = UVPacked ?
880                      GFX_ALIGN(*pVOffsetY, TileHeight) :
881                      GFX_ALIGN(YHeight, TileHeight) + GFX_ALIGN(VHeight, TileHeight);
882 
883         if(pTexInfo->Flags.Gpu.UnifiedAuxSurface && pTexInfo->Flags.Gpu.__NonMsaaTileYCcs)
884         {
885             *pUOffsetY += pTexInfo->OffsetInfo.PlaneXe_LPG.Y[GMM_PLANE_Y];
886             *pVOffsetY = *pUOffsetY;
887         }
888 
889         // This is needed for FtrDisplayPageTables
890         if(pGmmLibContext->GetSkuTable().FtrDisplayPageTables)
891         {
892             if(pTexInfo->OffsetInfo.PlaneXe_LPG.Is1MBAuxTAlignedPlanes)
893             {
894                 pTexInfo->OffsetInfo.PlaneXe_LPG.Aligned.Height[GMM_PLANE_Y] = GFX_ALIGN(YHeight, PhysicalTileHeight); // confirm tilealignment is needed for physivcal backing, else calculate size from unaligned offset and use the same
895                 if(pTexInfo->OffsetInfo.PlaneXe_LPG.NoOfPlanes == 2)
896                 {
897                     pTexInfo->OffsetInfo.PlaneXe_LPG.Aligned.Height[GMM_PLANE_U] = GFX_ALIGN(VHeight, PhysicalTileHeight);
898                 }
899                 else if(pTexInfo->OffsetInfo.PlaneXe_LPG.NoOfPlanes == 3)
900                 {
901                     pTexInfo->OffsetInfo.PlaneXe_LPG.Aligned.Height[GMM_PLANE_U] =
902                     pTexInfo->OffsetInfo.PlaneXe_LPG.Aligned.Height[GMM_PLANE_V] = GFX_ALIGN(VHeight, PhysicalTileHeight);
903                 }
904             }
905             else
906             {
907                 pTexInfo->OffsetInfo.PlaneXe_LPG.Aligned.Height[GMM_PLANE_Y] = GFX_ALIGN(YHeight, TileHeight);
908                 if(pTexInfo->OffsetInfo.PlaneXe_LPG.NoOfPlanes == 2)
909                 {
910                     pTexInfo->OffsetInfo.PlaneXe_LPG.Aligned.Height[GMM_PLANE_U] = GFX_ALIGN(VHeight, TileHeight);
911                 }
912                 else if(pTexInfo->OffsetInfo.PlaneXe_LPG.NoOfPlanes == 3)
913                 {
914                     pTexInfo->OffsetInfo.PlaneXe_LPG.Aligned.Height[GMM_PLANE_U] =
915                     pTexInfo->OffsetInfo.PlaneXe_LPG.Aligned.Height[GMM_PLANE_V] = GFX_ALIGN(VHeight, TileHeight);
916                 }
917             }
918         }
919     }
920 
921     //Special case LKF MMC compressed surfaces
922     if(pTexInfo->Flags.Gpu.MMC &&
923        pTexInfo->Flags.Gpu.UnifiedAuxSurface &&
924        pTexInfo->Flags.Info.TiledY)
925     {
926         GMM_GFX_SIZE_T TileHeight = pGmmLibContext->GetPlatformInfo().TileInfo[pTexInfo->TileMode].LogicalTileHeight;
927         GMM_GFX_SIZE_T TileWidth  = pGmmLibContext->GetPlatformInfo().TileInfo[pTexInfo->TileMode].LogicalTileWidth;
928 
929         *pUOffsetX = GFX_ALIGN(*pUOffsetX, TileWidth);
930         *pUOffsetY = GFX_ALIGN(*pUOffsetY, TileHeight);
931         *pVOffsetX = GFX_ALIGN(*pVOffsetX, TileWidth);
932         *pVOffsetY = GFX_ALIGN(*pVOffsetY, TileHeight);
933     }
934 
935     GMM_DPF_EXIT;
936 
937 #undef SWAP_UV
938 }
939 
940 ////////////////////////////////////////////////////////////////////////////////////
941 /// Calculates offset address of a sub resource(i.e.  Mip Map, Cube face, volume texture)
942 ///
943 /// @param[in]  pTexInfo: ptr to ::GMM_TEXTURE_INFO
944 /// @param[in]  pReqInfo: ptr to GMM_REQ_OFFSET_INFO to store offset info
945 ///
946 /// @return     ::GMM_STATUS
947 /////////////////////////////////////////////////////////////////////////////////////
GetTexLockOffset(GMM_TEXTURE_INFO * pTexInfo,GMM_REQ_OFFSET_INFO * pReqInfo)948 GMM_STATUS GmmLib::GmmXe_LPGTextureCalc::GetTexLockOffset(GMM_TEXTURE_INFO *   pTexInfo,
949                                                           GMM_REQ_OFFSET_INFO *pReqInfo)
950 {
951     GMM_STATUS     Result = GMM_SUCCESS;
952     GMM_GFX_SIZE_T AddressOffset;
953     uint32_t       Pitch, Slice;
954     uint32_t       MipHeight, MipWidth, MipLevel;
955     uint32_t       NumberOfMipsInSingleRow, SliceRow;
956 
957     __GMM_ASSERTPTR(pTexInfo, GMM_ERROR);
958     __GMM_ASSERTPTR(pReqInfo, GMM_ERROR);
959 
960     const GMM_PLATFORM_INFO *pPlatform = GMM_OVERRIDE_PLATFORM_INFO(pTexInfo, pGmmLibContext);
961 
962     // set default value
963     AddressOffset = 0;
964     Pitch         = GFX_ULONG_CAST(pTexInfo->Pitch);
965     MipLevel      = pReqInfo->MipLevel;
966     Slice         = pReqInfo->Slice;
967 
968     if(GmmIsPlanar(pTexInfo->Format))
969     {
970         AddressOffset           = GetMipMapByteAddress(pTexInfo, pReqInfo);
971         pReqInfo->Lock.Offset64 = AddressOffset;
972         pReqInfo->Lock.Pitch    = pTexInfo->OffsetInfo.PlaneXe_LPG.Is1MBAuxTAlignedPlanes ? GFX_ULONG_CAST(pTexInfo->OffsetInfo.PlaneXe_LPG.PhysicalPitch) : Pitch;
973 
974         // Adjust returned pitch for non-uniform-pitch U/V queries...
975         if((pReqInfo->Plane == GMM_PLANE_U) ||
976            (pReqInfo->Plane == GMM_PLANE_V))
977         {
978             switch(pTexInfo->Format)
979             {
980                 case GMM_FORMAT_I420:
981                 case GMM_FORMAT_IYUV:
982                 case GMM_FORMAT_YV12:
983                 case GMM_FORMAT_NV11:
984                     pReqInfo->Lock.Pitch /= 2;
985                     break;
986                 case GMM_FORMAT_YVU9:
987                     pReqInfo->Lock.Pitch /= 4;
988                     break;
989                 default:
990                     //Cool--Constant pitch across all planes.
991                     break;
992             }
993         }
994 
995         return Result;
996     }
997 
998     switch(pTexInfo->Type)
999     {
1000         case RESOURCE_3D:
1001         {
1002             if(GFX_GET_CURRENT_RENDERCORE(pPlatform->Platform) >= IGFX_GEN9_CORE)
1003             {
1004                 AddressOffset = GFX_ULONG_CAST(GetMipMapByteAddress(pTexInfo, pReqInfo));
1005 
1006                 // Bytes from one slice to the next...
1007                 pReqInfo->Lock.Gen9PlusSlicePitch = GFX_ULONG_CAST(pTexInfo->OffsetInfo.Texture2DOffsetInfo.ArrayQPitchLock);
1008             }
1009             else
1010             {
1011                 MipHeight = pTexInfo->BaseHeight >> MipLevel;
1012                 MipWidth  = GFX_ULONG_CAST(pTexInfo->BaseWidth) >> MipLevel;
1013 
1014                 AlignTexHeightWidth(pTexInfo, &MipHeight, &MipWidth);
1015 
1016                 // See how many mip can fit in one row
1017                 NumberOfMipsInSingleRow = GFX_2_TO_POWER_OF(MipLevel);
1018 
1019                 SliceRow = Slice / NumberOfMipsInSingleRow;
1020 
1021                 // get the base address + Slice pitch
1022                 AddressOffset = pTexInfo->OffsetInfo.Texture3DOffsetInfo.Offset[MipLevel];
1023 
1024                 pReqInfo->Lock.Mip0SlicePitch = GFX_ULONG_CAST(pTexInfo->OffsetInfo.Texture3DOffsetInfo.Mip0SlicePitch);
1025 
1026                 // Actual address is offset based on requested slice
1027                 AddressOffset += (GMM_GFX_SIZE_T)SliceRow * MipHeight * Pitch;
1028 
1029                 // Get to particular slice
1030                 if(Slice % NumberOfMipsInSingleRow)
1031                 {
1032                     AddressOffset += (((GMM_GFX_SIZE_T)(Slice % NumberOfMipsInSingleRow) *
1033                                        MipWidth * pTexInfo->BitsPerPixel) >>
1034                                       3);
1035                 }
1036             }
1037             break;
1038         }
1039         case RESOURCE_CUBE:
1040         case RESOURCE_2D:
1041         case RESOURCE_1D:
1042         {
1043             AddressOffset = GetMipMapByteAddress(pTexInfo, pReqInfo);
1044             break;
1045         }
1046         default:
1047         { // These resources dont' have multiple levels of detail
1048             AddressOffset = 0;
1049             break;
1050         }
1051     }
1052 
1053     pReqInfo->Lock.Offset64 = AddressOffset;
1054     pReqInfo->Lock.Pitch    = Pitch;
1055 
1056     return Result;
1057 }
1058 
1059 /////////////////////////////////////////////////////////////////////////////////////
1060 /// Function used to calculate byte address of a specified mip map
1061 ///
1062 /// @param[in]  pTexInfo: ptr to ::GMM_TEXTURE_INFO
1063 /// @param[in]  pReqInfo: ptr to GMM_REQ_OFFSET_INFO
1064 ///
1065 /// @return     ::GMM_GFX_SIZE_T byte offset
1066 /////////////////////////////////////////////////////////////////////////////////////
GetMipMapByteAddress(GMM_TEXTURE_INFO * pTexInfo,GMM_REQ_OFFSET_INFO * pReqInfo)1067 GMM_GFX_SIZE_T GmmLib::GmmXe_LPGTextureCalc::GetMipMapByteAddress(GMM_TEXTURE_INFO *   pTexInfo,
1068                                                                   GMM_REQ_OFFSET_INFO *pReqInfo)
1069 {
1070     GMM_GFX_SIZE_T ArrayQPitch, MipMapByteAddress, Pitch;
1071     uint32_t       MipLevel;
1072 
1073     __GMM_ASSERTPTR(pTexInfo, GMM_ERROR);
1074     __GMM_ASSERTPTR(pReqInfo, GMM_ERROR);
1075     __GMM_ASSERT(!(pTexInfo->Flags.Gpu.CCS && !pTexInfo->Flags.Gpu.UnifiedAuxSurface));
1076     __GMM_ASSERT(pReqInfo->Plane < GMM_MAX_PLANE);
1077 
1078     MipLevel    = pReqInfo->MipLevel;
1079     Pitch       = pTexInfo->Pitch;
1080     ArrayQPitch = pReqInfo->ReqRender ?
1081                   pTexInfo->OffsetInfo.Texture2DOffsetInfo.ArrayQPitchRender :
1082                   pTexInfo->OffsetInfo.Texture2DOffsetInfo.ArrayQPitchLock;
1083 
1084     const GMM_PLATFORM_INFO *pPlatform = GMM_OVERRIDE_PLATFORM_INFO(pTexInfo, pGmmLibContext);
1085 
1086     if(pTexInfo->Type == RESOURCE_3D && !pTexInfo->Flags.Info.Linear)
1087     {
1088         ArrayQPitch *= pPlatform->TileInfo[pTexInfo->TileMode].LogicalTileDepth;
1089     }
1090 
1091     if((GFX_GET_CURRENT_RENDERCORE(pPlatform->Platform) >= IGFX_GEN8_CORE) &&
1092        ((pTexInfo->MSAA.NumSamples > 1) &&
1093         !(pTexInfo->Flags.Gpu.Depth ||
1094           pTexInfo->Flags.Gpu.SeparateStencil ||
1095           GMM_IS_64KB_TILE(pTexInfo->Flags) ||
1096           pTexInfo->Flags.Info.TiledYf)))
1097     {
1098         ArrayQPitch *= pTexInfo->MSAA.NumSamples;
1099     }
1100 
1101     if(GmmIsPlanar(pTexInfo->Format))
1102     {
1103         uint32_t Plane = pReqInfo->Plane;
1104 
1105         uint32_t OffsetX = 0;
1106         uint32_t OffsetY = 0;
1107         if(Plane < GMM_MAX_PLANE)
1108         {
1109             if(pReqInfo->ReqLock && pTexInfo->OffsetInfo.PlaneXe_LPG.Is1MBAuxTAlignedPlanes)
1110             {
1111                 OffsetX = GFX_ULONG_CAST(pTexInfo->OffsetInfo.PlaneXe_LPG.X[GMM_PLANE_Y]);
1112                 OffsetY = GFX_ULONG_CAST(pTexInfo->OffsetInfo.PlaneXe_LPG.Y[GMM_PLANE_Y]);
1113                 for(uint32_t PlaneId = GMM_PLANE_Y; PlaneId < Plane; PlaneId++)
1114                 {
1115                     // physical offset calculation: x offset remains same as PLANE_Y, YOffset = sum of physical height of all prev planes
1116                     OffsetY += GFX_ULONG_CAST(pTexInfo->OffsetInfo.PlaneXe_LPG.Physical.Height[PlaneId]);
1117                 }
1118                 Pitch       = pTexInfo->OffsetInfo.PlaneXe_LPG.PhysicalPitch;
1119                 ArrayQPitch = ((pTexInfo->OffsetInfo.PlaneXe_LPG.Physical.Height[GMM_PLANE_Y] + pTexInfo->OffsetInfo.PlaneXe_LPG.Physical.Height[GMM_PLANE_U] + pTexInfo->OffsetInfo.PlaneXe_LPG.Physical.Height[GMM_PLANE_V]) * pTexInfo->OffsetInfo.PlaneXe_LPG.PhysicalPitch); // Physical size of single array
1120             }
1121             else
1122             {
1123                 OffsetX     = GFX_ULONG_CAST(pTexInfo->OffsetInfo.PlaneXe_LPG.X[Plane]);
1124                 OffsetY     = GFX_ULONG_CAST(pTexInfo->OffsetInfo.PlaneXe_LPG.Y[Plane]);
1125                 ArrayQPitch = pTexInfo->OffsetInfo.PlaneXe_LPG.ArrayQPitch;
1126             }
1127         }
1128         MipMapByteAddress = (OffsetY * Pitch) + OffsetX;
1129 
1130         __GMM_ASSERT(!pReqInfo->ArrayIndex || (pReqInfo->ArrayIndex < pTexInfo->ArraySize));
1131 
1132         MipMapByteAddress += (ArrayQPitch * pReqInfo->ArrayIndex);
1133     }
1134     else
1135     {
1136         switch(pTexInfo->Type)
1137         {
1138             case RESOURCE_CUBE:
1139             {
1140                 uint32_t CubeFace = pReqInfo->CubeFace;
1141 
1142                 GMM_ASSERTDPF( // Validate Cube Map Params...
1143                 (!pReqInfo->ArrayIndex || (pReqInfo->ArrayIndex < pTexInfo->ArraySize)) &&
1144                 (pReqInfo->CubeFace < __GMM_MAX_CUBE_FACE) &&
1145                 (pReqInfo->CubeFace != __GMM_NO_CUBE_MAP) &&
1146                 (pReqInfo->Plane == GMM_NO_PLANE) &&
1147                 (pReqInfo->Slice == 0),
1148                 "Invalid parameter!");
1149 
1150                 // Support for CubeMap Arrays using 2D Arrays
1151                 MipMapByteAddress = pTexInfo->OffsetInfo.Texture2DOffsetInfo.Offset[MipLevel];
1152                 MipMapByteAddress += (ArrayQPitch * ((6 * pReqInfo->ArrayIndex) + CubeFace));
1153                 break;
1154             }
1155             case RESOURCE_2D:
1156             case RESOURCE_1D:
1157             {
1158                 MipMapByteAddress = pTexInfo->OffsetInfo.Texture2DOffsetInfo.Offset[MipLevel];
1159 
1160                 if(pReqInfo->ArrayIndex)
1161                 {
1162                     MipMapByteAddress += (ArrayQPitch * pReqInfo->ArrayIndex);
1163                 }
1164                 break;
1165             }
1166             case RESOURCE_3D:
1167             {
1168                 if(GFX_GET_CURRENT_RENDERCORE(pPlatform->Platform) >= IGFX_GEN9_CORE)
1169                 {
1170                     MipMapByteAddress = pTexInfo->OffsetInfo.Texture2DOffsetInfo.Offset[MipLevel];
1171 
1172                     if(pReqInfo->Slice)
1173                     {
1174                         MipMapByteAddress += (ArrayQPitch * pReqInfo->Slice);
1175                     }
1176                 }
1177                 else
1178                 {
1179                     MipMapByteAddress = Get3DMipByteAddress(pTexInfo, pReqInfo);
1180                 }
1181                 break;
1182             }
1183             default:
1184             { // These resources don't have multiple levels of detail
1185                 MipMapByteAddress = 0;
1186                 break;
1187             }
1188         }
1189     }
1190 
1191     MipMapByteAddress += pTexInfo->Flags.Gpu.S3d ?
1192                          GetDisplayFrameOffset(pTexInfo, pReqInfo) :
1193                          0;
1194 
1195     return MipMapByteAddress;
1196 }
1197 
SetPlanarOffsetInfo(GMM_TEXTURE_INFO * pTexInfo,GMM_RESCREATE_CUSTOM_PARAMS & CreateParams)1198 void GmmLib::GmmXe_LPGTextureCalc::SetPlanarOffsetInfo(GMM_TEXTURE_INFO *pTexInfo, GMM_RESCREATE_CUSTOM_PARAMS &CreateParams)
1199 {
1200     const GMM_PLATFORM_INFO *pPlatform;
1201     pPlatform = GMM_OVERRIDE_PLATFORM_INFO(pTexInfo, pGmmLibContext);
1202 
1203     if(GMM_IS_TILED(pPlatform->TileInfo[pTexInfo->TileMode]))
1204     {
1205         pTexInfo->OffsetInfo.PlaneXe_LPG.IsTileAlignedPlanes = true;
1206     }
1207     for(uint8_t i = 1; i <= CreateParams.NoOfPlanes; i++)
1208     {
1209         pTexInfo->OffsetInfo.PlaneXe_LPG.X[i] = CreateParams.PlaneOffset.X[i];
1210         pTexInfo->OffsetInfo.PlaneXe_LPG.Y[i] = CreateParams.PlaneOffset.Y[i];
1211     }
1212     pTexInfo->OffsetInfo.PlaneXe_LPG.NoOfPlanes = CreateParams.NoOfPlanes;
1213 }
1214 
1215 #ifndef __GMM_KMD__
SetPlanarOffsetInfo_2(GMM_TEXTURE_INFO * pTexInfo,GMM_RESCREATE_CUSTOM_PARAMS_2 & CreateParams)1216 void GmmLib::GmmXe_LPGTextureCalc::SetPlanarOffsetInfo_2(GMM_TEXTURE_INFO *pTexInfo, GMM_RESCREATE_CUSTOM_PARAMS_2 &CreateParams)
1217 {
1218     const GMM_PLATFORM_INFO *pPlatform;
1219     pPlatform = GMM_OVERRIDE_PLATFORM_INFO(pTexInfo, pGmmLibContext);
1220 
1221     if(GMM_IS_TILED(pPlatform->TileInfo[pTexInfo->TileMode]))
1222     {
1223         pTexInfo->OffsetInfo.PlaneXe_LPG.IsTileAlignedPlanes = true;
1224     }
1225     for(uint8_t i = 1; i <= CreateParams.NoOfPlanes; i++)
1226     {
1227         pTexInfo->OffsetInfo.PlaneXe_LPG.X[i] = CreateParams.PlaneOffset.X[i];
1228         pTexInfo->OffsetInfo.PlaneXe_LPG.Y[i] = CreateParams.PlaneOffset.Y[i];
1229     }
1230     pTexInfo->OffsetInfo.PlaneXe_LPG.NoOfPlanes = CreateParams.NoOfPlanes;
1231 }
1232 #endif
1233 
SetPlaneUnAlignedTexOffsetInfo(GMM_TEXTURE_INFO * pTexInfo,uint32_t YHeight,uint32_t VHeight)1234 void GmmLib::GmmXe_LPGTextureCalc::SetPlaneUnAlignedTexOffsetInfo(GMM_TEXTURE_INFO *pTexInfo, uint32_t YHeight, uint32_t VHeight)
1235 {
1236     uint32_t UmdUHeight = 0, UmdVHeight = 0;
1237 
1238     pTexInfo->OffsetInfo.PlaneXe_LPG.UnAligned.Height[GMM_PLANE_Y] = YHeight;
1239     if(pTexInfo->OffsetInfo.PlaneXe_LPG.NoOfPlanes == 2)
1240     {
1241         pTexInfo->OffsetInfo.PlaneXe_LPG.UnAligned.Height[GMM_PLANE_U] = VHeight;
1242         UmdUHeight                                                     = (GMM_GLOBAL_GFX_SIZE_T)((pTexInfo->Size / pTexInfo->Pitch) - pTexInfo->OffsetInfo.PlaneXe_LPG.Y[GMM_PLANE_U]);
1243     }
1244     else if(pTexInfo->OffsetInfo.PlaneXe_LPG.NoOfPlanes == 3)
1245     {
1246         pTexInfo->OffsetInfo.PlaneXe_LPG.UnAligned.Height[GMM_PLANE_U] =
1247         pTexInfo->OffsetInfo.PlaneXe_LPG.UnAligned.Height[GMM_PLANE_V] = VHeight;
1248         UmdUHeight                                                     = (GMM_GLOBAL_GFX_SIZE_T)(pTexInfo->OffsetInfo.PlaneXe_LPG.Y[GMM_PLANE_V] - pTexInfo->OffsetInfo.PlaneXe_LPG.Y[GMM_PLANE_U]);
1249         UmdVHeight                                                     = (GMM_GLOBAL_GFX_SIZE_T)(((pTexInfo->Size / pTexInfo->Pitch) - pTexInfo->OffsetInfo.PlaneXe_LPG.Y[GMM_PLANE_U]) / 2);
1250         __GMM_ASSERTPTR((UmdUHeight == UmdVHeight), VOIDRETURN);
1251     }
1252 
1253     __GMM_ASSERTPTR(((pTexInfo->OffsetInfo.PlaneXe_LPG.Y[GMM_PLANE_U] == YHeight) && (UmdUHeight == VHeight)), VOIDRETURN);
1254 }
1255 
IsTileAlignedPlanes(GMM_TEXTURE_INFO * pTexInfo)1256 uint32_t GmmLib::GmmXe_LPGTextureCalc::IsTileAlignedPlanes(GMM_TEXTURE_INFO *pTexInfo)
1257 {
1258     return pTexInfo->OffsetInfo.PlaneXe_LPG.IsTileAlignedPlanes;
1259 }
1260 
GetNumberOfPlanes(GMM_TEXTURE_INFO * pTexInfo)1261 uint32_t GmmLib::GmmXe_LPGTextureCalc::GetNumberOfPlanes(GMM_TEXTURE_INFO *pTexInfo)
1262 {
1263     return pTexInfo->OffsetInfo.PlaneXe_LPG.NoOfPlanes;
1264 }
1265 
GetPlaneIdForCpuBlt(GMM_TEXTURE_INFO * pTexInfo,GMM_RES_COPY_BLT * pBlt,uint32_t * PlaneId)1266 void GmmLib::GmmXe_LPGTextureCalc::GetPlaneIdForCpuBlt(GMM_TEXTURE_INFO *pTexInfo, GMM_RES_COPY_BLT *pBlt, uint32_t *PlaneId)
1267 {
1268     uint32_t TotalHeight = 0;
1269 
1270     if(pTexInfo->OffsetInfo.PlaneXe_LPG.NoOfPlanes == 2)
1271     {
1272         TotalHeight = GFX_ULONG_CAST(pTexInfo->OffsetInfo.PlaneXe_LPG.UnAligned.Height[GMM_PLANE_Y] +
1273                                      pTexInfo->OffsetInfo.PlaneXe_LPG.UnAligned.Height[GMM_PLANE_U]);
1274     }
1275     else if(pTexInfo->OffsetInfo.PlaneXe_LPG.NoOfPlanes == 3)
1276     {
1277         TotalHeight = GFX_ULONG_CAST(pTexInfo->OffsetInfo.PlaneXe_LPG.UnAligned.Height[GMM_PLANE_Y] +
1278                                      pTexInfo->OffsetInfo.PlaneXe_LPG.UnAligned.Height[GMM_PLANE_U] +
1279                                      pTexInfo->OffsetInfo.PlaneXe_LPG.UnAligned.Height[GMM_PLANE_V]);
1280     }
1281     else
1282     {
1283         TotalHeight = GFX_ULONG_CAST(pTexInfo->OffsetInfo.PlaneXe_LPG.UnAligned.Height[GMM_PLANE_Y]); //YV12 exception
1284     }
1285 
1286     // Determine if BLT rectange is for monolithic surface or contained in specific Y/UV plane
1287     if(((pBlt->Gpu.OffsetY + pBlt->Blt.Height <= pTexInfo->OffsetInfo.PlaneXe_LPG.Y[GMM_PLANE_U]) || pTexInfo->OffsetInfo.PlaneXe_LPG.NoOfPlanes == 1) &&
1288        (pBlt->Gpu.OffsetX + pBlt->Blt.Width <= pTexInfo->BaseWidth))
1289     {
1290         *PlaneId = GMM_PLANE_Y;
1291     }
1292     else if(pBlt->Gpu.OffsetY >= pTexInfo->OffsetInfo.PlaneXe_LPG.Y[GMM_PLANE_U] &&
1293             (pBlt->Gpu.OffsetY + pBlt->Blt.Height <= (pTexInfo->OffsetInfo.PlaneXe_LPG.Y[GMM_PLANE_U] + pTexInfo->OffsetInfo.PlaneXe_LPG.UnAligned.Height[GMM_PLANE_U])) &&
1294             (pBlt->Gpu.OffsetX + pBlt->Blt.Width <= pTexInfo->BaseWidth))
1295     {
1296         *PlaneId = GMM_PLANE_U;
1297     }
1298     else if(pBlt->Gpu.OffsetY >= pTexInfo->OffsetInfo.PlaneXe_LPG.Y[GMM_PLANE_V] &&
1299             (pBlt->Gpu.OffsetY + pBlt->Blt.Height <= (pTexInfo->OffsetInfo.PlaneXe_LPG.Y[GMM_PLANE_V] + pTexInfo->OffsetInfo.PlaneXe_LPG.UnAligned.Height[GMM_PLANE_U])) &&
1300             (pBlt->Gpu.OffsetX + pBlt->Blt.Width <= pTexInfo->BaseWidth))
1301     {
1302         *PlaneId = GMM_PLANE_V;
1303     }
1304 
1305     // For smaller surface, BLT rect may fall in Y Plane due to tile alignment but user may have requested monolithic BLT
1306     if(pBlt->Gpu.OffsetX == 0 &&
1307        pBlt->Gpu.OffsetY == 0 &&
1308        pBlt->Blt.Height >= TotalHeight)
1309     {
1310         *PlaneId = GMM_MAX_PLANE;
1311     }
1312 }
1313 
GetBltInfoPerPlane(GMM_TEXTURE_INFO * pTexInfo,GMM_RES_COPY_BLT * pBlt,uint32_t PlaneId)1314 void GmmLib::GmmXe_LPGTextureCalc::GetBltInfoPerPlane(GMM_TEXTURE_INFO *pTexInfo, GMM_RES_COPY_BLT *pBlt, uint32_t PlaneId)
1315 {
1316     if(PlaneId == GMM_PLANE_Y)
1317     {
1318         pBlt->Gpu.OffsetX = GFX_ULONG_CAST(pTexInfo->OffsetInfo.PlaneXe_LPG.X[GMM_PLANE_Y]);
1319         pBlt->Gpu.OffsetY = GFX_ULONG_CAST(pTexInfo->OffsetInfo.PlaneXe_LPG.Y[GMM_PLANE_Y]);
1320         pBlt->Blt.Height  = GFX_ULONG_CAST(pTexInfo->OffsetInfo.PlaneXe_LPG.UnAligned.Height[GMM_PLANE_Y]);
1321     }
1322     else if(PlaneId == GMM_PLANE_U)
1323     {
1324         pBlt->Gpu.OffsetX = GFX_ULONG_CAST(pTexInfo->OffsetInfo.PlaneXe_LPG.X[GMM_PLANE_U]);
1325         pBlt->Gpu.OffsetY = GFX_ULONG_CAST(pTexInfo->OffsetInfo.PlaneXe_LPG.Y[GMM_PLANE_U]);
1326 
1327         pBlt->Sys.pData  = (char *)pBlt->Sys.pData + uint32_t(pBlt->Blt.Height * pBlt->Sys.RowPitch);
1328         pBlt->Blt.Height = GFX_ULONG_CAST(pTexInfo->OffsetInfo.PlaneXe_LPG.UnAligned.Height[GMM_PLANE_U]);
1329         if(pTexInfo->Flags.Info.RedecribedPlanes)
1330         {
1331             __GMM_ASSERT(0);
1332         }
1333     }
1334     else
1335     {
1336         pBlt->Gpu.OffsetX = GFX_ULONG_CAST(pTexInfo->OffsetInfo.PlaneXe_LPG.X[GMM_PLANE_V]);
1337         pBlt->Gpu.OffsetY = GFX_ULONG_CAST(pTexInfo->OffsetInfo.PlaneXe_LPG.Y[GMM_PLANE_V]);
1338         pBlt->Blt.Height  = GFX_ULONG_CAST(pTexInfo->OffsetInfo.PlaneXe_LPG.UnAligned.Height[GMM_PLANE_U]);
1339         pBlt->Sys.pData   = (char *)pBlt->Sys.pData + uint32_t(pBlt->Blt.Height * pBlt->Sys.RowPitch);
1340     }
1341 }
1342