xref: /aosp_15_r20/external/gmmlib/Source/GmmLib/Texture/GmmTextureOffset.cpp (revision 35ffd701415c9e32e53136d61a677a8d0a8fc4a5)
1 /*==============================================================================
2 Copyright(c) 2017 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 
25 
26 /////////////////////////////////////////////////////////////////////////////////////
27 /// GMM Interface to return lock or render aligned offset to a mip map
28 ///
29 /// @param[in]  pTexInfo: ptr to ::GMM_TEXTURE_INFO
30 /// @param[in]  pReqInfo: ptr to GMM_REQ_OFFSET_INFO to store offset info
31 ///
32 /// @return     ::GMM_STATUS
33 /////////////////////////////////////////////////////////////////////////////////////
GmmTexGetMipMapOffset(GMM_TEXTURE_INFO * pTexInfo,GMM_REQ_OFFSET_INFO * pReqInfo,GMM_LIB_CONTEXT * pGmmLibContext)34 GMM_STATUS GmmTexGetMipMapOffset(GMM_TEXTURE_INFO *   pTexInfo,
35                                  GMM_REQ_OFFSET_INFO *pReqInfo,
36                                  GMM_LIB_CONTEXT *    pGmmLibContext)
37 {
38     GMM_STATUS        Status           = GMM_SUCCESS;
39     bool              RestoreRenderReq = false;
40     bool              RestoreLockReq   = false;
41     GMM_TEXTURE_CALC *pTextureCalc;
42 
43     GMM_DPF_ENTER;
44     __GMM_ASSERTPTR(pTexInfo, GMM_ERROR);
45     __GMM_ASSERTPTR(pReqInfo, GMM_ERROR);
46     __GMM_ASSERT(pReqInfo->CubeFace <= __GMM_NO_CUBE_MAP);
47 
48     pTextureCalc = GMM_OVERRIDE_TEXTURE_CALC(pTexInfo, pGmmLibContext);
49 
50     if((pReqInfo->Plane >= GMM_MAX_PLANE) ||
51        (pReqInfo->Plane < GMM_NO_PLANE) ||
52        (pReqInfo->MipLevel >= GMM_MAX_MIPMAP))
53     {
54         GMM_ASSERTDPF(0, "Invalid parameter!");
55         return GMM_ERROR;
56     }
57 
58     if((pTexInfo->TileMode >= GMM_TILE_MODES) ||
59        (pTexInfo->TileMode < TILE_NONE))
60     {
61         GMM_ASSERTDPF(0, "Invalid parameter!");
62         return GMM_ERROR;
63     }
64 
65     // Retrieve offset info at pReqInfo->MipLevel
66     if(pReqInfo->ReqLock)
67     {
68         if(pReqInfo->ReqRender)
69         {
70             pReqInfo->ReqRender = 0;
71             RestoreRenderReq    = true;
72         }
73 
74         if(pTextureCalc->GetTexLockOffset(pTexInfo, pReqInfo) != GMM_SUCCESS)
75         {
76             GMM_ASSERTDPF(0, "ReqLock failed!");
77             Status = GMM_ERROR;
78         }
79     }
80 
81     if(RestoreRenderReq == true)
82         pReqInfo->ReqRender = 1;
83 
84     if(pReqInfo->ReqLock)
85     {
86         pReqInfo->ReqLock = 0;
87         RestoreLockReq    = 1;
88     }
89 
90     if(pReqInfo->ReqRender)
91     {
92         if(pTextureCalc->GetTexRenderOffset(pTexInfo, pReqInfo) != GMM_SUCCESS)
93         {
94             GMM_ASSERTDPF(0, "ReqRender failed!");
95             Status = GMM_ERROR;
96         }
97     }
98 
99     if(RestoreLockReq)
100     {
101         pReqInfo->ReqLock = 1;
102     }
103 
104     if(pReqInfo->ReqStdLayout)
105     {
106         if(pTextureCalc->GetTexStdLayoutOffset(pTexInfo, pReqInfo) != GMM_SUCCESS)
107         {
108             GMM_ASSERTDPF(0, "ReqStdLayout failed!");
109             Status = GMM_ERROR;
110         }
111     }
112 
113     GMM_DPF_EXIT;
114     return Status;
115 }
116 
117 
118 /////////////////////////////////////////////////////////////////////////////////////
119 /// Calculates StdLayout offsets and related pitches of
120 /// subresource..
121 ///
122 /// @param[in]  pTexInfo: ptr to ::GMM_TEXTURE_INFO
123 /// @param[in]  pReqInfo: ptr to GMM_REQ_OFFSET_INFO to store offset info
124 ///
125 /// @return     ::GMM_STATUS
126 /////////////////////////////////////////////////////////////////////////////////////
GetTexStdLayoutOffset(GMM_TEXTURE_INFO * pTexInfo,GMM_REQ_OFFSET_INFO * pReqInfo)127 GMM_STATUS GmmLib::GmmTextureCalc::GetTexStdLayoutOffset(GMM_TEXTURE_INFO *   pTexInfo,
128                                                          GMM_REQ_OFFSET_INFO *pReqInfo)
129 {
130     uint32_t ReqArrayIndex;
131     bool     NeedSurfaceSize = false;
132 
133     __GMM_ASSERT(pTexInfo);
134     __GMM_ASSERT(GMM_IS_64KB_TILE(pTexInfo->Flags) || pTexInfo->Flags.Info.TiledYf);
135     __GMM_ASSERT(
136     (pTexInfo->Type == RESOURCE_2D) ||
137     (pTexInfo->Type == RESOURCE_3D) ||
138     (pTexInfo->Type == RESOURCE_CUBE));
139     __GMM_ASSERT(GmmIsPlanar(pTexInfo->Format) == false); // Planar not support
140 
141     if(pReqInfo->StdLayout.Offset == -1) // Special Req for Surface Size
142     {
143         NeedSurfaceSize = true;
144         ReqArrayIndex   = // TODO(Medium): Add planar support.
145         (pTexInfo->ArraySize * ((pTexInfo->Type == RESOURCE_CUBE) ? 6 : 1));
146     }
147     else
148     {
149         ReqArrayIndex =
150         (pReqInfo->ArrayIndex * ((pTexInfo->Type == RESOURCE_CUBE) ? 6 : 1));
151     }
152 
153     {
154         uint32_t TileSize = 0;
155 
156         // TileYs (64) and TileYf (4)
157         if(GMM_IS_64KB_TILE(pTexInfo->Flags))
158         {
159             TileSize = GMM_KBYTE(64);
160         }
161         else if(GMM_IS_4KB_TILE(pTexInfo->Flags))
162         {
163             TileSize = GMM_KBYTE(4);
164         }
165 
166         const GMM_PLATFORM_INFO *pPlatform       = GMM_OVERRIDE_PLATFORM_INFO(pTexInfo, pGmmLibContext);
167         uint32_t                 BytesPerElement = pTexInfo->BitsPerPixel / CHAR_BIT;
168         GMM_TILE_MODE            TileMode        = pTexInfo->TileMode;
169         struct
170         {
171             uint32_t Width, Height, Depth;
172         } Element, Tile;
173 
174         __GMM_ASSERT(TileMode < GMM_TILE_MODES);
175 
176         GetCompressionBlockDimensions(
177         pTexInfo->Format,
178         &Element.Width,
179         &Element.Height,
180         &Element.Depth);
181 
182         Tile.Width =
183         (pPlatform->TileInfo[TileMode].LogicalTileWidth / BytesPerElement) *
184         Element.Width;
185 
186         Tile.Height =
187         pPlatform->TileInfo[TileMode].LogicalTileHeight *
188         Element.Height;
189 
190         Tile.Depth =
191         pPlatform->TileInfo[TileMode].LogicalTileDepth *
192         Element.Depth;
193 
194         {
195             GMM_GFX_ADDRESS TargetLodOffset = 0;
196             GMM_GFX_SIZE_T  PrevMipSize     = 0;
197             GMM_GFX_SIZE_T  SliceOffset     = 0;
198             GMM_GFX_SIZE_T  SlicePitch      = 0;
199             uint32_t        Lod;
200             uint32_t        EffectiveMaxLod =
201             (ReqArrayIndex == 0) ?
202             pReqInfo->MipLevel :
203             GFX_MIN(pTexInfo->MaxLod, pTexInfo->Alignment.MipTailStartLod);
204 
205             pReqInfo->StdLayout.Offset = 0;
206             for(Lod = 0; Lod <= EffectiveMaxLod; Lod++)
207             {
208                 GMM_GFX_SIZE_T MipWidth  = GmmTexGetMipWidth(pTexInfo, Lod);
209                 uint32_t       MipHeight = GmmTexGetMipHeight(pTexInfo, Lod);
210                 uint32_t       MipDepth  = GmmTexGetMipDepth(pTexInfo, Lod);
211 
212                 uint32_t MipCols = GFX_ULONG_CAST(
213                 GFX_CEIL_DIV(
214                 MipWidth,
215                 Tile.Width));
216                 uint32_t MipRows =
217                 GFX_CEIL_DIV(
218                 MipHeight,
219                 Tile.Height);
220                 uint32_t MipDepthTiles =
221                 GFX_CEIL_DIV(
222                 MipDepth,
223                 Tile.Depth);
224                 uint32_t RowPitch   = MipCols * TileSize; // Bytes from one tile row to the next.
225                 uint32_t DepthPitch = RowPitch * MipRows; // Bytes from one depth slice of tiles to the next.
226 
227                 if(Lod <= pTexInfo->Alignment.MipTailStartLod)
228                 {
229                     pReqInfo->StdLayout.Offset += PrevMipSize;
230                 }
231 
232                 if(Lod == pReqInfo->MipLevel)
233                 {
234                     TargetLodOffset = pReqInfo->StdLayout.Offset;
235 
236                     pReqInfo->StdLayout.TileRowPitch   = RowPitch;
237                     pReqInfo->StdLayout.TileDepthPitch = DepthPitch;
238                 }
239 
240                 PrevMipSize = (GMM_GFX_SIZE_T)DepthPitch * MipDepthTiles;
241                 SlicePitch += DepthPitch;
242             }
243 
244             if(pReqInfo->Slice > 0)
245             {
246                 SliceOffset = SlicePitch * pReqInfo->Slice;
247             }
248 
249             if(!NeedSurfaceSize && pReqInfo->MipLevel >= pTexInfo->Alignment.MipTailStartLod)
250             {
251                 pReqInfo->StdLayout.Offset += (ReqArrayIndex * (pReqInfo->StdLayout.Offset + PrevMipSize)) +
252                                               GetMipTailByteOffset(pTexInfo, pReqInfo->MipLevel);
253             }
254             else
255             {
256                 pReqInfo->StdLayout.Offset = ReqArrayIndex * (pReqInfo->StdLayout.Offset + PrevMipSize) +
257                                              TargetLodOffset;
258             }
259 
260             pReqInfo->StdLayout.Offset += SliceOffset;
261         }
262     }
263 
264     return GMM_SUCCESS;
265 }
266 
267 
268 /////////////////////////////////////////////////////////////////////////////////////
269 /// Calculates offset address of a sub resource(i.e.  Mip Map, Cube face, volume texture)
270 ///
271 /// @param[in]  pTexInfo: ptr to ::GMM_TEXTURE_INFO
272 /// @param[in]  pReqInfo: ptr to GMM_REQ_OFFSET_INFO to store offset info
273 ///
274 /// @return     ::GMM_STATUS
275 /////////////////////////////////////////////////////////////////////////////////////
GetTexLockOffset(GMM_TEXTURE_INFO * pTexInfo,GMM_REQ_OFFSET_INFO * pReqInfo)276 GMM_STATUS GmmLib::GmmTextureCalc::GetTexLockOffset(GMM_TEXTURE_INFO *   pTexInfo,
277                                                     GMM_REQ_OFFSET_INFO *pReqInfo)
278 {
279     GMM_STATUS     Result = GMM_SUCCESS;
280     GMM_GFX_SIZE_T AddressOffset;
281     uint32_t       Pitch, Slice;
282     uint32_t       MipHeight, MipWidth, MipLevel;
283     uint32_t       NumberOfMipsInSingleRow, SliceRow;
284 
285     __GMM_ASSERTPTR(pTexInfo, GMM_ERROR);
286     __GMM_ASSERTPTR(pReqInfo, GMM_ERROR);
287 
288     const GMM_PLATFORM_INFO *pPlatform = GMM_OVERRIDE_PLATFORM_INFO(pTexInfo, pGmmLibContext);
289 
290     // set default value
291     AddressOffset = 0;
292     Pitch         = GFX_ULONG_CAST(pTexInfo->Pitch);
293     MipLevel      = pReqInfo->MipLevel;
294     Slice         = pReqInfo->Slice;
295 
296     if(GmmIsPlanar(pTexInfo->Format))
297     {
298         AddressOffset           = GetMipMapByteAddress(pTexInfo, pReqInfo);
299         pReqInfo->Lock.Offset64 = AddressOffset;
300         pReqInfo->Lock.Pitch    = Pitch;
301 
302         // Adjust returned pitch for non-uniform-pitch U/V queries...
303         if((pReqInfo->Plane == GMM_PLANE_U) ||
304            (pReqInfo->Plane == GMM_PLANE_V))
305         {
306             switch(pTexInfo->Format)
307             {
308                 case GMM_FORMAT_I420:
309                 case GMM_FORMAT_IYUV:
310                 case GMM_FORMAT_YV12:
311                 case GMM_FORMAT_NV11:
312                     pReqInfo->Lock.Pitch /= 2;
313                     break;
314                 case GMM_FORMAT_YVU9:
315                     pReqInfo->Lock.Pitch /= 4;
316                     break;
317                 default:
318                     //Cool--Constant pitch across all planes.
319                     break;
320             }
321         }
322 
323         return Result;
324     }
325 
326     switch(pTexInfo->Type)
327     {
328         case RESOURCE_3D:
329         {
330             if(GFX_GET_CURRENT_RENDERCORE(pPlatform->Platform) >= IGFX_GEN9_CORE)
331             {
332                 AddressOffset = GFX_ULONG_CAST(GetMipMapByteAddress(pTexInfo, pReqInfo));
333 
334                 // Bytes from one slice to the next...
335                 pReqInfo->Lock.Gen9PlusSlicePitch = GFX_ULONG_CAST(pTexInfo->OffsetInfo.Texture2DOffsetInfo.ArrayQPitchLock);
336             }
337             else
338             {
339                 MipHeight = pTexInfo->BaseHeight >> MipLevel;
340                 MipWidth  = GFX_ULONG_CAST(pTexInfo->BaseWidth) >> MipLevel;
341 
342                 AlignTexHeightWidth(pTexInfo, &MipHeight, &MipWidth);
343 
344                 // See how many mip can fit in one row
345                 NumberOfMipsInSingleRow = GFX_2_TO_POWER_OF(MipLevel);
346 
347                 SliceRow = Slice / NumberOfMipsInSingleRow;
348 
349                 // get the base address + Slice pitch
350                 AddressOffset = pTexInfo->OffsetInfo.Texture3DOffsetInfo.Offset[MipLevel];
351 
352                 pReqInfo->Lock.Mip0SlicePitch = GFX_ULONG_CAST(pTexInfo->OffsetInfo.Texture3DOffsetInfo.Mip0SlicePitch);
353 
354                 // Actual address is offset based on requested slice
355                 AddressOffset += (GMM_GFX_SIZE_T)SliceRow * MipHeight * Pitch;
356 
357                 // Get to particular slice
358                 if(Slice % NumberOfMipsInSingleRow)
359                 {
360                     AddressOffset += (((GMM_GFX_SIZE_T)(Slice % NumberOfMipsInSingleRow) *
361                                        MipWidth * pTexInfo->BitsPerPixel) >>
362                                       3);
363                 }
364             }
365             break;
366         }
367         case RESOURCE_CUBE:
368         case RESOURCE_2D:
369         case RESOURCE_1D:
370         {
371             AddressOffset = GetMipMapByteAddress(pTexInfo, pReqInfo);
372             break;
373         }
374         default:
375         { // These resources dont' have multiple levels of detail
376             AddressOffset = 0;
377             break;
378         }
379     }
380 
381     pReqInfo->Lock.Offset64 = AddressOffset;
382     pReqInfo->Lock.Pitch    = Pitch;
383 
384     return Result;
385 }
386 
387 
388 /////////////////////////////////////////////////////////////////////////////////////
389 /// Function used to align width and height of texture so that it satisfy our HW
390 /// restriction
391 ///
392 /// @param[in]  pTexInfo: ptr to ::GMM_TEXTURE_INFO
393 /// @param[in]  pHeight: ptr to height of mip
394 /// @param[in]  pWidth: ptr to width of mip
395 ///
396 /////////////////////////////////////////////////////////////////////////////////////
AlignTexHeightWidth(GMM_TEXTURE_INFO * pTexInfo,uint32_t * pHeight,uint32_t * pWidth)397 void GmmLib::GmmTextureCalc::AlignTexHeightWidth(GMM_TEXTURE_INFO *pTexInfo,
398                                                  uint32_t *        pHeight,
399                                                  uint32_t *        pWidth)
400 {
401     uint32_t MipWidth        = 0;
402     uint32_t MipHeight       = 0;
403     uint32_t UnitAlignHeight = 0;
404     uint32_t UnitAlignWidth  = 0;
405 
406     uint8_t Compress = 0;
407 
408     __GMM_ASSERTPTR(pTexInfo, VOIDRETURN);
409     __GMM_ASSERTPTR(pWidth, VOIDRETURN);
410     __GMM_ASSERTPTR(pHeight, VOIDRETURN);
411     __GMM_ASSERTPTR(pGmmLibContext, VOIDRETURN);
412 
413     MipWidth  = *pWidth;
414     MipHeight = *pHeight;
415 
416     UnitAlignWidth  = pTexInfo->Alignment.HAlign;
417     UnitAlignHeight = pTexInfo->Alignment.VAlign;
418     Compress        = GmmIsCompressed(pGmmLibContext, pTexInfo->Format);
419 
420     MipWidth  = GFX_MAX(MipWidth, UnitAlignWidth);
421     MipHeight = GFX_MAX(MipHeight, UnitAlignHeight);
422 
423     MipWidth  = GFX_ALIGN(MipWidth, UnitAlignWidth);
424     MipHeight = GFX_ALIGN(MipHeight, UnitAlignHeight);
425 
426     if(Compress)
427     {
428         uint32_t CompressHeight, CompressWidth, CompressDepth;
429         GetCompressionBlockDimensions(pTexInfo->Format, &CompressWidth, &CompressHeight, &CompressDepth);
430         MipWidth /= CompressWidth;
431         MipHeight /= CompressHeight;
432     }
433     else if(pTexInfo->Flags.Gpu.SeparateStencil && pTexInfo->Flags.Info.TiledW)
434     {
435         MipWidth *= 2;
436         MipHeight /= 2;
437     }
438 
439     *pHeight = MipHeight;
440     *pWidth  = MipWidth;
441 }
442 
443 
444 /////////////////////////////////////////////////////////////////////////////////////
445 /// Function used to calculate the render aligned offset of a given surface
446 ///
447 /// @param[in]  pTexInfo: ptr to ::GMM_TEXTURE_INFO
448 /// @param[in]  pReqInfo: ptr to GMM_REQ_OFFSET_INFO
449 ///
450 /// @return     ::GMM_STATUS
451 /////////////////////////////////////////////////////////////////////////////////////
GetTexRenderOffset(GMM_TEXTURE_INFO * pTexInfo,GMM_REQ_OFFSET_INFO * pReqInfo)452 GMM_STATUS GmmLib::GmmTextureCalc::GetTexRenderOffset(GMM_TEXTURE_INFO *   pTexInfo,
453                                                       GMM_REQ_OFFSET_INFO *pReqInfo)
454 {
455 
456     const GMM_TILE_INFO *    pTileInfo         = NULL;
457     GMM_GFX_SIZE_T           AddressOffset     = 0;
458     GMM_GFX_SIZE_T           RenderAlignOffset = 0;
459     uint32_t                 OffsetX           = 0;
460     uint32_t                 OffsetY           = 0;
461     uint32_t                 OffsetZ           = 0;
462     const GMM_PLATFORM_INFO *pPlatform         = NULL;
463 
464     __GMM_ASSERTPTR(pTexInfo, GMM_ERROR);
465     __GMM_ASSERTPTR(pReqInfo, GMM_ERROR);
466 
467     pPlatform     = GMM_OVERRIDE_PLATFORM_INFO(pTexInfo, pGmmLibContext);
468     pTileInfo     = &pPlatform->TileInfo[pTexInfo->TileMode];
469     AddressOffset = GetMipMapByteAddress(pTexInfo, pReqInfo);
470 
471     if(GMM_IS_TILED(*pTileInfo))
472     {
473         uint32_t       TileAlignedOffsetX = 0;
474         uint32_t       TileAlignedOffsetY = 0;
475         GMM_GFX_SIZE_T MipTailByteOffset  = 0;
476 
477         //--- Compute Tile-Aligned Offset, and Corresponding X/Y Offsets -------
478         // Render/Tiled-Aligned offsets and corresponding X/Y offsets are used
479         // to program the Surface Base Address and X/Y Offset fields of a
480         // SURFACE_STATE. For a given subresource, the tiled-aligned offset
481         // addresses the tile containing the base of the subresource; the X/Y
482         // offsets then give the additional offsets into the tile of the
483         // subresource base. (Though in SURFACE_STATE, X Offset is specified in
484         // pixels, this function will return the X Offset in bytes. Y Offset is
485         // in pixel rows.)
486 
487         if((pTexInfo->Flags.Info.TiledYf || GMM_IS_64KB_TILE(pTexInfo->Flags)) &&
488            (pReqInfo->MipLevel >= pTexInfo->Alignment.MipTailStartLod))
489         {
490             MipTailByteOffset = GetMipTailByteOffset(pTexInfo, pReqInfo->MipLevel);
491 
492             // For MipTail, Offset is really with respect to start of MipTail,
493             // so taking out individual Mipoffset within miptail region to get correct Tile aligned offset.
494             AddressOffset -= MipTailByteOffset;
495         }
496 
497         if(!pTexInfo->Flags.Info.RedecribedPlanes)
498         {
499             GMM_GFX_SIZE_T Pitch = pTexInfo->Pitch;
500             if(!pTexInfo->Pitch)
501             {
502                 // If no pitch exists, but the surface is still marked as tiled, then it is a 1D TileYf/Ys surface.
503                 // Technically no pitch exists for 1D surfaces, but we will fake it to make calculations work below.
504                 // Since 1D surfaces only have an X-dimension, this Pitch calculation is only used for OffsetX calculation.
505                 Pitch = pTexInfo->Size;
506             }
507 
508 	    if(pTexInfo->Flags.Gpu.SeparateStencil && pTexInfo->Flags.Info.TiledW)
509             {
510                 OffsetX            = GFX_ULONG_CAST(AddressOffset % Pitch);
511                 TileAlignedOffsetX = GFX_ALIGN_FLOOR(OffsetX, pTileInfo->LogicalTileWidth / 2);
512                 OffsetX -= TileAlignedOffsetX;
513             }
514             else
515             {
516                 OffsetX            = GFX_ULONG_CAST(AddressOffset % Pitch);
517                 TileAlignedOffsetX = GFX_ALIGN_FLOOR(OffsetX, pTileInfo->LogicalTileWidth);
518                 OffsetX -= TileAlignedOffsetX;
519             }
520 
521             if(pTexInfo->Pitch)
522             {
523                 if(pTexInfo->Flags.Gpu.SeparateStencil && pTexInfo->Flags.Info.TiledW)
524                 {
525                     //Expt: YOffset ignore row-interleave -- verify both 2d/3d mips
526                     OffsetY = GFX_ULONG_CAST(AddressOffset / pTexInfo->Pitch);
527                     OffsetY *= 2;
528                     TileAlignedOffsetY = GFX_ALIGN_FLOOR(OffsetY, pTileInfo->LogicalTileHeight * 2 * pTileInfo->LogicalTileDepth);
529                     OffsetY -= TileAlignedOffsetY;
530                     TileAlignedOffsetY /= 2;
531                 }
532                 else
533                 {
534                     OffsetY            = GFX_ULONG_CAST(AddressOffset / pTexInfo->Pitch);
535                     TileAlignedOffsetY = GFX_ALIGN_FLOOR(OffsetY, pTileInfo->LogicalTileHeight * pTileInfo->LogicalTileDepth);
536                     OffsetY -= TileAlignedOffsetY;
537                 }
538             }
539 
540             RenderAlignOffset =
541             TileAlignedOffsetY * pTexInfo->Pitch +
542             (TileAlignedOffsetX / pTileInfo->LogicalTileWidth) * pTileInfo->LogicalSize;
543 
544             // For Gen9+, Miptail Lods should be reported in a way that
545             //      - Base Address equals tile-aligned "Miptail start address"
546             //      - OffsetX equals to offset (in bytes) from "Miptail start Lod" to "current Lod" in geometric X direction
547             //      - OffsetY and OffsetZ are their pixel distance from "Miptail start Lod" to "current Lod" in geometric Y, Z directions
548             // Note: only Tile Yf and TileYs have Miptails and their Mips are always "tile aligned"
549 
550             if((pTexInfo->Flags.Info.TiledYf || GMM_IS_64KB_TILE(pTexInfo->Flags)) &&
551                (pReqInfo->MipLevel >= pTexInfo->Alignment.MipTailStartLod) &&
552                // Planar surfaces do not support MIPs
553                !GmmIsPlanar(pTexInfo->Format))
554             {
555                 GetMipTailGeometryOffset(pTexInfo, pReqInfo->MipLevel, &OffsetX, &OffsetY, &OffsetZ);
556             }
557         }
558         else
559         {
560             // Std swizzled and UV packed planes begin at tile-aligned
561             // offsets and do not support MIPs, so no adjustment is needed
562             RenderAlignOffset = AddressOffset;
563             OffsetX = OffsetY = OffsetZ = 0;
564         }
565     }
566     else
567     {
568         // Linear case make sure Render address is DWORD aligned.
569         RenderAlignOffset = GFX_ALIGN_FLOOR(AddressOffset, GMM_BYTES(4));
570 
571         if(pTexInfo->Pitch)
572         {
573             OffsetX = GFX_ULONG_CAST((AddressOffset - RenderAlignOffset) % pTexInfo->Pitch);
574             OffsetY = GFX_ULONG_CAST((AddressOffset - RenderAlignOffset) / pTexInfo->Pitch);
575         }
576         else
577         {
578             // One-dimensional textures (no height)
579             OffsetX = GFX_ULONG_CAST(AddressOffset - RenderAlignOffset);
580             OffsetY = 0;
581         }
582     }
583 
584     pReqInfo->Render.Offset64 = RenderAlignOffset;
585     pReqInfo->Render.XOffset  = GFX_ULONG_CAST(OffsetX);
586     pReqInfo->Render.YOffset  = GFX_ULONG_CAST(OffsetY);
587     pReqInfo->Render.ZOffset  = GFX_ULONG_CAST(OffsetZ);
588 
589     return GMM_SUCCESS;
590 } // __GmmGetRenderAlignAddress
591 
592 
593 /////////////////////////////////////////////////////////////////////////////////////
594 /// Function used to calculate byte address of a specified mip map
595 ///
596 /// @param[in]  pTexInfo: ptr to ::GMM_TEXTURE_INFO
597 /// @param[in]  pReqInfo: ptr to GMM_REQ_OFFSET_INFO
598 ///
599 /// @return     ::GMM_GFX_SIZE_T byte offset
600 /////////////////////////////////////////////////////////////////////////////////////
GetMipMapByteAddress(GMM_TEXTURE_INFO * pTexInfo,GMM_REQ_OFFSET_INFO * pReqInfo)601 GMM_GFX_SIZE_T GmmLib::GmmTextureCalc::GetMipMapByteAddress(GMM_TEXTURE_INFO *   pTexInfo,
602                                                             GMM_REQ_OFFSET_INFO *pReqInfo)
603 {
604     GMM_GFX_SIZE_T ArrayQPitch, MipMapByteAddress, Pitch;
605     uint32_t       MipLevel;
606 
607     __GMM_ASSERTPTR(pTexInfo, GMM_ERROR);
608     __GMM_ASSERTPTR(pReqInfo, GMM_ERROR);
609     __GMM_ASSERT(!(pTexInfo->Flags.Gpu.CCS && !pTexInfo->Flags.Gpu.UnifiedAuxSurface));
610     __GMM_ASSERT(pReqInfo->Plane < GMM_MAX_PLANE);
611 
612     MipLevel    = pReqInfo->MipLevel;
613     Pitch       = pTexInfo->Pitch;
614     ArrayQPitch = pReqInfo->ReqRender ?
615                   pTexInfo->OffsetInfo.Texture2DOffsetInfo.ArrayQPitchRender :
616                   pTexInfo->OffsetInfo.Texture2DOffsetInfo.ArrayQPitchLock;
617 
618     const GMM_PLATFORM_INFO *pPlatform = GMM_OVERRIDE_PLATFORM_INFO(pTexInfo, pGmmLibContext);
619 
620     if(pTexInfo->Type == RESOURCE_3D && !pTexInfo->Flags.Info.Linear)
621     {
622         ArrayQPitch *= pPlatform->TileInfo[pTexInfo->TileMode].LogicalTileDepth;
623     }
624 
625     if((GFX_GET_CURRENT_RENDERCORE(pPlatform->Platform) >= IGFX_GEN8_CORE) &&
626        ((pTexInfo->MSAA.NumSamples > 1) &&
627         !(pTexInfo->Flags.Gpu.Depth ||
628           pTexInfo->Flags.Gpu.SeparateStencil ||
629           GMM_IS_64KB_TILE(pTexInfo->Flags) ||
630           pTexInfo->Flags.Info.TiledYf)))
631     {
632         ArrayQPitch *= pTexInfo->MSAA.NumSamples;
633     }
634 
635     if(GmmIsPlanar(pTexInfo->Format))
636     {
637         uint32_t Plane = pReqInfo->Plane;
638 
639         uint32_t OffsetX = 0;
640         uint32_t OffsetY = 0;
641         if(Plane < GMM_MAX_PLANE)
642         {
643             OffsetX     = GFX_ULONG_CAST(pTexInfo->OffsetInfo.Plane.X[Plane]);
644             OffsetY     = GFX_ULONG_CAST(pTexInfo->OffsetInfo.Plane.Y[Plane]);
645             ArrayQPitch = pTexInfo->OffsetInfo.Plane.ArrayQPitch;
646 	}
647         MipMapByteAddress = (OffsetY * Pitch) + OffsetX;
648 
649         __GMM_ASSERT(!pReqInfo->ArrayIndex || (pReqInfo->ArrayIndex < pTexInfo->ArraySize));
650 
651         MipMapByteAddress += (ArrayQPitch * pReqInfo->ArrayIndex);
652     }
653     else
654     {
655         switch(pTexInfo->Type)
656         {
657             case RESOURCE_CUBE:
658             {
659                 uint32_t CubeFace = pReqInfo->CubeFace;
660 
661                 GMM_ASSERTDPF( // Validate Cube Map Params...
662                 (!pReqInfo->ArrayIndex || (pReqInfo->ArrayIndex < pTexInfo->ArraySize)) &&
663                 (pReqInfo->CubeFace < __GMM_MAX_CUBE_FACE) &&
664                 (pReqInfo->CubeFace != __GMM_NO_CUBE_MAP) &&
665                 (pReqInfo->Plane == GMM_NO_PLANE) &&
666                 (pReqInfo->Slice == 0),
667                 "Invalid parameter!");
668 
669                 // Support for CubeMap Arrays using 2D Arrays
670                 MipMapByteAddress = pTexInfo->OffsetInfo.Texture2DOffsetInfo.Offset[MipLevel];
671                 MipMapByteAddress += (ArrayQPitch * ((6 * pReqInfo->ArrayIndex) + CubeFace));
672                 break;
673             }
674             case RESOURCE_2D:
675             case RESOURCE_1D:
676             {
677                 MipMapByteAddress = pTexInfo->OffsetInfo.Texture2DOffsetInfo.Offset[MipLevel];
678 
679                 if(pReqInfo->ArrayIndex)
680                 {
681                     MipMapByteAddress += (ArrayQPitch * pReqInfo->ArrayIndex);
682                 }
683                 break;
684             }
685             case RESOURCE_3D:
686             {
687                 if(GFX_GET_CURRENT_RENDERCORE(pPlatform->Platform) >= IGFX_GEN9_CORE)
688                 {
689                     MipMapByteAddress = pTexInfo->OffsetInfo.Texture2DOffsetInfo.Offset[MipLevel];
690 
691                     if(pReqInfo->Slice)
692                     {
693                         MipMapByteAddress += (ArrayQPitch * pReqInfo->Slice);
694                     }
695                 }
696                 else
697                 {
698                     MipMapByteAddress = Get3DMipByteAddress(pTexInfo, pReqInfo);
699                 }
700                 break;
701             }
702             default:
703             { // These resources don't have multiple levels of detail
704                 MipMapByteAddress = 0;
705                 break;
706             }
707         }
708     }
709 
710     MipMapByteAddress += pTexInfo->Flags.Gpu.S3d ?
711                          GetDisplayFrameOffset(pTexInfo, pReqInfo) :
712                          0;
713 
714     return MipMapByteAddress;
715 }
716 
717 
718 /////////////////////////////////////////////////////////////////////////////////////
719 /// Utility function used to calculate byte address to a mip slice
720 ///
721 /// @param[in]  pTexInfo: ptr to ::GMM_TEXTURE_INFO
722 /// @param[in]  pReqInfo: ptr to GMM_REQ_OFFSET_INFO
723 ///
724 /// @return     byte offset
725 /////////////////////////////////////////////////////////////////////////////////////
Get3DMipByteAddress(GMM_TEXTURE_INFO * pTexInfo,GMM_REQ_OFFSET_INFO * pReqInfo)726 GMM_GFX_SIZE_T GmmLib::GmmTextureCalc::Get3DMipByteAddress(GMM_TEXTURE_INFO *   pTexInfo,
727                                                            GMM_REQ_OFFSET_INFO *pReqInfo)
728 {
729     uint32_t            MipsInThisRow, PlaneRows;
730     uint32_t            MipHeight, MipWidth;
731     uint32_t            UnitAlignHeight, UnitAlignWidth;
732     GMM_GFX_SIZE_T      MipMapByteAddress, ExtraBytes;
733     uint32_t            Slice, MipLevel, Pitch;
734     uint8_t             Compress;
735     GMM_RESOURCE_FORMAT GenericFormat;
736     uint32_t            CompressHeight, CompressWidth, CompressDepth;
737 
738     __GMM_ASSERTPTR(pGmmLibContext, 0);
739 
740     GenericFormat = pTexInfo->Format;
741     Slice         = pReqInfo->Slice;
742     MipLevel      = pReqInfo->MipLevel;
743     Pitch         = GFX_ULONG_CAST(pTexInfo->Pitch);
744 
745     // For slice 0 for any mip address is simple and stored in table
746     if(Slice == 0)
747     {
748         MipMapByteAddress = pTexInfo->OffsetInfo.Texture3DOffsetInfo.Offset[MipLevel];
749     }
750     // For any slice
751     else
752     {
753         MipMapByteAddress = pTexInfo->OffsetInfo.Texture3DOffsetInfo.Offset[MipLevel];
754 
755         // See how many mip can fit in one row
756         MipsInThisRow = GFX_2_TO_POWER_OF(MipLevel);
757 
758         PlaneRows = Slice / MipsInThisRow;
759 
760         // make sure we get the height and mip of base level
761         MipWidth  = GFX_ULONG_CAST(pTexInfo->BaseWidth);
762         MipHeight = pTexInfo->BaseHeight;
763 
764         MipWidth >>= MipLevel;
765         MipHeight >>= MipLevel;
766 
767         UnitAlignWidth  = pTexInfo->Alignment.HAlign;
768         UnitAlignHeight = pTexInfo->Alignment.VAlign;
769         Compress        = GmmIsCompressed(pGmmLibContext, pTexInfo->Format);
770         GetCompressionBlockDimensions(pTexInfo->Format, &CompressWidth, &CompressHeight, &CompressDepth);
771 
772         // clamp such that mip height is at least min height
773         MipHeight = GFX_MAX(MipHeight, UnitAlignHeight);
774         MipHeight = GFX_ALIGN(MipHeight, UnitAlignHeight);
775 
776         // clamp such that mip width is at least min width
777         MipWidth = GFX_MAX(MipWidth, UnitAlignWidth);
778         MipWidth = GFX_ALIGN(MipWidth, UnitAlignWidth);
779 
780         if(Compress)
781         {
782             MipWidth /= CompressWidth;
783             MipHeight /= CompressHeight;
784         }
785         else if(pTexInfo->Flags.Gpu.SeparateStencil)
786         {
787             MipWidth *= 2;
788             MipHeight /= 2;
789         }
790 
791         ExtraBytes = (GMM_GFX_SIZE_T)PlaneRows * MipHeight * Pitch;
792 
793         ExtraBytes += ((GMM_GFX_SIZE_T)(Slice % MipsInThisRow) *
794                        MipWidth * pTexInfo->BitsPerPixel) >>
795                       3;
796 
797         // get address offset
798         MipMapByteAddress += ExtraBytes;
799     }
800 
801     return MipMapByteAddress;
802 }
803 
804 
805 /////////////////////////////////////////////////////////////////////////////////////
806 /// Utility function calculates a byte offset from the base of the allocation
807 //  to L frame, R frame, or blank region.
808 ///
809 /// @param[in]  pTexInfo: ptr to ::GMM_TEXTURE_INFO
810 /// @param[in]  pReqInfo: ptr to GMM_REQ_OFFSET_INFO
811 ///
812 /// @return     byte offset
813 /////////////////////////////////////////////////////////////////////////////////////
GetDisplayFrameOffset(GMM_TEXTURE_INFO * pTexInfo,GMM_REQ_OFFSET_INFO * pReqInfo)814 uint32_t GmmLib::GmmTextureCalc::GetDisplayFrameOffset(GMM_TEXTURE_INFO *   pTexInfo,
815                                                        GMM_REQ_OFFSET_INFO *pReqInfo)
816 {
817     uint32_t Offset;
818 
819     __GMM_ASSERTPTR(pTexInfo, GMM_ERROR);
820     __GMM_ASSERTPTR(pReqInfo, GMM_ERROR);
821 
822     switch(pReqInfo->Frame)
823     {
824         case GMM_DISPLAY_L:
825             Offset = 0;
826             break;
827         case GMM_DISPLAY_R:
828             Offset = pTexInfo->S3d.RFrameOffset;
829             break;
830         case GMM_DISPLAY_BLANK_AREA:
831             Offset = pTexInfo->S3d.BlankAreaOffset;
832             break;
833         default:
834             Offset = 0;
835             GMM_ASSERTDPF(0, "Unknown Frame Type!");
836             break;
837     }
838 
839     return Offset;
840 }
841 
SetPlanarOffsetInfo(GMM_TEXTURE_INFO * pTexInfo,GMM_RESCREATE_CUSTOM_PARAMS & CreateParams)842 void GmmLib::GmmTextureCalc::SetPlanarOffsetInfo(GMM_TEXTURE_INFO *pTexInfo, GMM_RESCREATE_CUSTOM_PARAMS &CreateParams)
843 {
844     const GMM_PLATFORM_INFO *pPlatform;
845     pPlatform = GMM_OVERRIDE_PLATFORM_INFO(pTexInfo, pGmmLibContext);
846 
847     if(GMM_IS_TILED(pPlatform->TileInfo[pTexInfo->TileMode]))
848     {
849         pTexInfo->OffsetInfo.Plane.IsTileAlignedPlanes = true;
850     }
851     for(uint8_t i = 1; i <= CreateParams.NoOfPlanes; i++)
852     {
853         pTexInfo->OffsetInfo.Plane.X[i] = CreateParams.PlaneOffset.X[i];
854         pTexInfo->OffsetInfo.Plane.Y[i] = CreateParams.PlaneOffset.Y[i];
855     }
856     pTexInfo->OffsetInfo.Plane.NoOfPlanes = CreateParams.NoOfPlanes;
857 }
858 
859 #ifndef __GMM_KMD__
SetPlanarOffsetInfo_2(GMM_TEXTURE_INFO * pTexInfo,GMM_RESCREATE_CUSTOM_PARAMS_2 & CreateParams)860 void GmmLib::GmmTextureCalc::SetPlanarOffsetInfo_2(GMM_TEXTURE_INFO *pTexInfo, GMM_RESCREATE_CUSTOM_PARAMS_2 &CreateParams)
861 {
862     const GMM_PLATFORM_INFO *pPlatform;
863     pPlatform = GMM_OVERRIDE_PLATFORM_INFO(pTexInfo, pGmmLibContext);
864 
865     if(GMM_IS_TILED(pPlatform->TileInfo[pTexInfo->TileMode]))
866     {
867         pTexInfo->OffsetInfo.Plane.IsTileAlignedPlanes = true;
868     }
869     for(uint8_t i = 1; i <= CreateParams.NoOfPlanes; i++)
870     {
871         pTexInfo->OffsetInfo.Plane.X[i] = CreateParams.PlaneOffset.X[i];
872         pTexInfo->OffsetInfo.Plane.Y[i] = CreateParams.PlaneOffset.Y[i];
873     }
874     pTexInfo->OffsetInfo.Plane.NoOfPlanes = CreateParams.NoOfPlanes;
875 }
876 #endif
877 
SetPlaneUnAlignedTexOffsetInfo(GMM_TEXTURE_INFO * pTexInfo,uint32_t YHeight,uint32_t VHeight)878 void GmmLib::GmmTextureCalc::SetPlaneUnAlignedTexOffsetInfo(GMM_TEXTURE_INFO *pTexInfo, uint32_t YHeight, uint32_t VHeight)
879 {
880     uint32_t UmdUHeight = 0, UmdVHeight = 0;
881 
882     pTexInfo->OffsetInfo.Plane.UnAligned.Height[GMM_PLANE_Y] = YHeight;
883     if(pTexInfo->OffsetInfo.Plane.NoOfPlanes == 2)
884     {
885         pTexInfo->OffsetInfo.Plane.UnAligned.Height[GMM_PLANE_U] = VHeight;
886         UmdUHeight                                               = (GMM_GLOBAL_GFX_SIZE_T)((pTexInfo->Size / pTexInfo->Pitch) - pTexInfo->OffsetInfo.Plane.Y[GMM_PLANE_U]);
887     }
888     else if(pTexInfo->OffsetInfo.Plane.NoOfPlanes == 3)
889     {
890         pTexInfo->OffsetInfo.Plane.UnAligned.Height[GMM_PLANE_U] =
891         pTexInfo->OffsetInfo.Plane.UnAligned.Height[GMM_PLANE_V] = VHeight;
892         UmdUHeight                                               = (GMM_GLOBAL_GFX_SIZE_T)(pTexInfo->OffsetInfo.Plane.Y[GMM_PLANE_V] - pTexInfo->OffsetInfo.Plane.Y[GMM_PLANE_U]);
893         UmdVHeight                                               = (GMM_GLOBAL_GFX_SIZE_T)(((pTexInfo->Size / pTexInfo->Pitch) - pTexInfo->OffsetInfo.Plane.Y[GMM_PLANE_U]) / 2);
894         __GMM_ASSERTPTR((UmdUHeight == UmdVHeight), VOIDRETURN);
895     }
896 
897     __GMM_ASSERTPTR(((pTexInfo->OffsetInfo.Plane.Y[GMM_PLANE_U] == YHeight) && (UmdUHeight == VHeight)), VOIDRETURN);
898 }
899 
IsTileAlignedPlanes(GMM_TEXTURE_INFO * pTexInfo)900 uint32_t GmmLib::GmmTextureCalc::IsTileAlignedPlanes(GMM_TEXTURE_INFO *pTexInfo)
901 {
902     return pTexInfo->OffsetInfo.Plane.IsTileAlignedPlanes;
903 }
904 
GetNumberOfPlanes(GMM_TEXTURE_INFO * pTexInfo)905 uint32_t GmmLib::GmmTextureCalc::GetNumberOfPlanes(GMM_TEXTURE_INFO *pTexInfo)
906 {
907     return pTexInfo->OffsetInfo.Plane.NoOfPlanes;
908 }
909 
GetPlaneIdForCpuBlt(GMM_TEXTURE_INFO * pTexInfo,GMM_RES_COPY_BLT * pBlt,uint32_t * PlaneId)910 void GmmLib::GmmTextureCalc::GetPlaneIdForCpuBlt(GMM_TEXTURE_INFO *pTexInfo, GMM_RES_COPY_BLT *pBlt, uint32_t *PlaneId)
911 {
912     uint32_t TotalHeight = 0;
913 
914     if(pTexInfo->OffsetInfo.Plane.NoOfPlanes == 2)
915     {
916         TotalHeight = GFX_ULONG_CAST(pTexInfo->OffsetInfo.Plane.UnAligned.Height[GMM_PLANE_Y] +
917                                      pTexInfo->OffsetInfo.Plane.UnAligned.Height[GMM_PLANE_U]);
918     }
919     else if(pTexInfo->OffsetInfo.Plane.NoOfPlanes == 3)
920     {
921         TotalHeight = GFX_ULONG_CAST(pTexInfo->OffsetInfo.Plane.UnAligned.Height[GMM_PLANE_Y] +
922                                      pTexInfo->OffsetInfo.Plane.UnAligned.Height[GMM_PLANE_U] +
923                                      pTexInfo->OffsetInfo.Plane.UnAligned.Height[GMM_PLANE_V]);
924     }
925     else
926     {
927         TotalHeight = GFX_ULONG_CAST(pTexInfo->OffsetInfo.Plane.UnAligned.Height[GMM_PLANE_Y]); //YV12 exception
928     }
929 
930     // Determine if BLT rectange is for monolithic surface or contained in specific Y/UV plane
931     if(((pBlt->Gpu.OffsetY + pBlt->Blt.Height <= pTexInfo->OffsetInfo.Plane.Y[GMM_PLANE_U]) || pTexInfo->OffsetInfo.Plane.NoOfPlanes == 1) &&
932        (pBlt->Gpu.OffsetX + pBlt->Blt.Width <= pTexInfo->BaseWidth))
933     {
934         *PlaneId = GMM_PLANE_Y;
935     }
936     else if(pBlt->Gpu.OffsetY >= pTexInfo->OffsetInfo.Plane.Y[GMM_PLANE_U] &&
937             (pBlt->Gpu.OffsetY + pBlt->Blt.Height <= (pTexInfo->OffsetInfo.Plane.Y[GMM_PLANE_U] + pTexInfo->OffsetInfo.Plane.UnAligned.Height[GMM_PLANE_U])) &&
938             (pBlt->Gpu.OffsetX + pBlt->Blt.Width <= pTexInfo->BaseWidth))
939     {
940         *PlaneId = GMM_PLANE_U;
941     }
942     else if(pBlt->Gpu.OffsetY >= pTexInfo->OffsetInfo.Plane.Y[GMM_PLANE_V] &&
943             (pBlt->Gpu.OffsetY + pBlt->Blt.Height <= (pTexInfo->OffsetInfo.Plane.Y[GMM_PLANE_V] + pTexInfo->OffsetInfo.Plane.UnAligned.Height[GMM_PLANE_U])) &&
944             (pBlt->Gpu.OffsetX + pBlt->Blt.Width <= pTexInfo->BaseWidth))
945     {
946         *PlaneId = GMM_PLANE_V;
947     }
948 
949     // For smaller surface, BLT rect may fall in Y Plane due to tile alignment but user may have requested monolithic BLT
950     if(pBlt->Gpu.OffsetX == 0 &&
951        pBlt->Gpu.OffsetY == 0 &&
952        pBlt->Blt.Height >= TotalHeight)
953     {
954         *PlaneId = GMM_MAX_PLANE;
955     }
956 }
957 
GetBltInfoPerPlane(GMM_TEXTURE_INFO * pTexInfo,GMM_RES_COPY_BLT * pBlt,uint32_t PlaneId)958 void GmmLib::GmmTextureCalc::GetBltInfoPerPlane(GMM_TEXTURE_INFO *pTexInfo, GMM_RES_COPY_BLT *pBlt, uint32_t PlaneId)
959 {
960     if(PlaneId == GMM_PLANE_Y)
961     {
962         pBlt->Gpu.OffsetX = GFX_ULONG_CAST(pTexInfo->OffsetInfo.Plane.X[GMM_PLANE_Y]);
963         pBlt->Gpu.OffsetY = GFX_ULONG_CAST(pTexInfo->OffsetInfo.Plane.Y[GMM_PLANE_Y]);
964         pBlt->Blt.Height  = GFX_ULONG_CAST(pTexInfo->OffsetInfo.Plane.UnAligned.Height[GMM_PLANE_Y]);
965     }
966     else if(PlaneId == GMM_PLANE_U)
967     {
968         pBlt->Gpu.OffsetX = GFX_ULONG_CAST(pTexInfo->OffsetInfo.Plane.X[GMM_PLANE_U]);
969         pBlt->Gpu.OffsetY = GFX_ULONG_CAST(pTexInfo->OffsetInfo.Plane.Y[GMM_PLANE_U]);
970 
971         pBlt->Sys.pData  = (char *)pBlt->Sys.pData + uint32_t(pBlt->Blt.Height * pBlt->Sys.RowPitch);
972         pBlt->Blt.Height = GFX_ULONG_CAST(pTexInfo->OffsetInfo.Plane.UnAligned.Height[GMM_PLANE_U]);
973         if(pTexInfo->Flags.Info.RedecribedPlanes)
974         {
975             __GMM_ASSERT(0);
976         }
977     }
978     else
979     {
980         pBlt->Gpu.OffsetX = GFX_ULONG_CAST(pTexInfo->OffsetInfo.Plane.X[GMM_PLANE_V]);
981         pBlt->Gpu.OffsetY = GFX_ULONG_CAST(pTexInfo->OffsetInfo.Plane.Y[GMM_PLANE_V]);
982         pBlt->Blt.Height  = GFX_ULONG_CAST(pTexInfo->OffsetInfo.Plane.UnAligned.Height[GMM_PLANE_U]);
983         pBlt->Sys.pData   = (char *)pBlt->Sys.pData + uint32_t(pBlt->Blt.Height * pBlt->Sys.RowPitch);
984     }
985 }
986