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