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 /// This function calculates the (X,Y) address of each given plane. X is in bytes
28 /// and Y is in scanlines.
29 ///
30 /// @param[in] pTexInfo: ptr to ::GMM_TEXTURE_INFO
31 ///
32 /////////////////////////////////////////////////////////////////////////////////////
FillPlanarOffsetAddress(GMM_TEXTURE_INFO * pTexInfo)33 void GmmLib::GmmTextureCalc::FillPlanarOffsetAddress(GMM_TEXTURE_INFO *pTexInfo)
34 {
35 GMM_GFX_SIZE_T *pUOffsetX, *pUOffsetY;
36 GMM_GFX_SIZE_T *pVOffsetX, *pVOffsetY;
37 uint32_t YHeight = 0, VHeight = 0;
38 bool UVPacked = false;
39 uint32_t Height;
40 uint32_t WidthBytesPhysical = GFX_ULONG_CAST(pTexInfo->BaseWidth) * pTexInfo->BitsPerPixel >> 3;
41
42 #define SWAP_UV() \
43 { \
44 GMM_GFX_SIZE_T *pTemp; \
45 \
46 pTemp = pUOffsetX; \
47 pUOffsetX = pVOffsetX; \
48 pVOffsetX = pTemp; \
49 \
50 pTemp = pUOffsetY; \
51 pUOffsetY = pVOffsetY; \
52 pVOffsetY = pTemp; \
53 }
54
55 __GMM_ASSERTPTR(pTexInfo, VOIDRETURN);
56 __GMM_ASSERTPTR(((pTexInfo->TileMode < GMM_TILE_MODES) && (pTexInfo->TileMode >= TILE_NONE)), VOIDRETURN);
57 GMM_DPF_ENTER;
58
59 const GMM_PLATFORM_INFO *pPlatform = GMM_OVERRIDE_PLATFORM_INFO(pTexInfo, pGmmLibContext);
60
61 // GMM_PLANE_Y always at (0, 0)...
62 pTexInfo->OffsetInfo.Plane.X[GMM_PLANE_Y] = 0;
63 pTexInfo->OffsetInfo.Plane.Y[GMM_PLANE_Y] = 0;
64
65 Height = pTexInfo->BaseHeight;
66 if(pTexInfo->Flags.Gpu.__NonMsaaTileYCcs)
67 {
68 Height = __GMM_EXPAND_HEIGHT(this, Height, pTexInfo->Alignment.VAlign, pTexInfo);
69 Height = ScaleTextureHeight(pTexInfo, Height);
70 if(pTexInfo->Flags.Gpu.UnifiedAuxSurface)
71 {
72 pTexInfo->OffsetInfo.Plane.Y[GMM_PLANE_Y] = 0;
73 }
74 }
75
76 // GMM_PLANE_U/V Planes...
77 pUOffsetX = &pTexInfo->OffsetInfo.Plane.X[GMM_PLANE_U];
78 pUOffsetY = &pTexInfo->OffsetInfo.Plane.Y[GMM_PLANE_U];
79 pVOffsetX = &pTexInfo->OffsetInfo.Plane.X[GMM_PLANE_V];
80 pVOffsetY = &pTexInfo->OffsetInfo.Plane.Y[GMM_PLANE_V];
81
82 switch(pTexInfo->Format)
83 {
84 case GMM_FORMAT_IMC1:
85 SWAP_UV(); // IMC1 = IMC3 with Swapped U/V
86 case GMM_FORMAT_IMC3:
87 case GMM_FORMAT_MFX_JPEG_YUV420: // Same as IMC3.
88 // YYYYYYYY
89 // YYYYYYYY
90 // YYYYYYYY
91 // YYYYYYYY
92 // UUUU
93 // UUUU
94 // VVVV
95 // VVVV
96 case GMM_FORMAT_MFX_JPEG_YUV422V: // Similar to IMC3 but U/V are full width.
97 // YYYYYYYY
98 // YYYYYYYY
99 // YYYYYYYY
100 // YYYYYYYY
101 // UUUUUUUU
102 // UUUUUUUU
103 // VVVVVVVV
104 // VVVVVVVV
105 {
106 *pUOffsetX = 0;
107 YHeight = GFX_ALIGN(pTexInfo->BaseHeight, GMM_IMCx_PLANE_ROW_ALIGNMENT);
108 *pUOffsetY = GFX_ALIGN(pTexInfo->BaseHeight, GMM_IMCx_PLANE_ROW_ALIGNMENT);
109
110 *pVOffsetX = 0;
111 VHeight = GFX_ALIGN(GFX_CEIL_DIV(pTexInfo->BaseHeight, 2), GMM_IMCx_PLANE_ROW_ALIGNMENT);
112 *pVOffsetY =
113 GFX_ALIGN(pTexInfo->BaseHeight, GMM_IMCx_PLANE_ROW_ALIGNMENT) +
114 GFX_ALIGN(GFX_CEIL_DIV(pTexInfo->BaseHeight, 2), GMM_IMCx_PLANE_ROW_ALIGNMENT);
115
116 break;
117 }
118 case GMM_FORMAT_MFX_JPEG_YUV411R_TYPE: //Similar to IMC3 but U/V are quarther height and full width.
119 //YYYYYYYY
120 //YYYYYYYY
121 //YYYYYYYY
122 //YYYYYYYY
123 //UUUUUUUU
124 //VVVVVVVV
125 {
126 *pUOffsetX = 0;
127 YHeight = GFX_ALIGN(pTexInfo->BaseHeight, GMM_IMCx_PLANE_ROW_ALIGNMENT);
128 *pUOffsetY = GFX_ALIGN(pTexInfo->BaseHeight, GMM_IMCx_PLANE_ROW_ALIGNMENT);
129
130 *pVOffsetX = 0;
131 VHeight = GFX_ALIGN(GFX_CEIL_DIV(pTexInfo->BaseHeight, 4), GMM_IMCx_PLANE_ROW_ALIGNMENT);
132 *pVOffsetY =
133 GFX_ALIGN(pTexInfo->BaseHeight, GMM_IMCx_PLANE_ROW_ALIGNMENT) +
134 GFX_ALIGN(GFX_CEIL_DIV(pTexInfo->BaseHeight, 4), GMM_IMCx_PLANE_ROW_ALIGNMENT);
135
136 break;
137 }
138 case GMM_FORMAT_MFX_JPEG_YUV411: // Similar to IMC3 but U/V are quarter width and full height.
139 // YYYYYYYY
140 // YYYYYYYY
141 // YYYYYYYY
142 // YYYYYYYY
143 // UU
144 // UU
145 // UU
146 // UU
147 // VV
148 // VV
149 // VV
150 // VV
151 case GMM_FORMAT_MFX_JPEG_YUV422H: // Similar to IMC3 but U/V are full height.
152 // YYYYYYYY
153 // YYYYYYYY
154 // YYYYYYYY
155 // YYYYYYYY
156 // UUUU
157 // UUUU
158 // UUUU
159 // UUUU
160 // VVVV
161 // VVVV
162 // VVVV
163 // VVVV
164 case GMM_FORMAT_MFX_JPEG_YUV444: // Similar to IMC3 but U/V are full size.
165 // YYYYYYYY
166 // YYYYYYYY
167 // YYYYYYYY
168 // YYYYYYYY
169 // UUUUUUUU
170 // UUUUUUUU
171 // UUUUUUUU
172 // UUUUUUUU
173 // VVVVVVVV
174 // VVVVVVVV
175 // VVVVVVVV
176 // VVVVVVVV
177 {
178 *pUOffsetX = 0;
179 YHeight = GFX_ALIGN(pTexInfo->BaseHeight, GMM_IMCx_PLANE_ROW_ALIGNMENT);
180 *pUOffsetY = GFX_ALIGN(pTexInfo->BaseHeight, GMM_IMCx_PLANE_ROW_ALIGNMENT);
181
182 *pVOffsetX = 0;
183 VHeight = GFX_ALIGN(pTexInfo->BaseHeight, GMM_IMCx_PLANE_ROW_ALIGNMENT);
184 *pVOffsetY = GFX_ALIGN(pTexInfo->BaseHeight, GMM_IMCx_PLANE_ROW_ALIGNMENT) * 2;
185
186 break;
187 }
188 case GMM_FORMAT_BGRP:
189 case GMM_FORMAT_RGBP:
190 {
191 //For RGBP linear Tile keep resource Offset non aligned and for other Tile format to be 16-bit aligned
192 if(pTexInfo->Flags.Info.Linear)
193 {
194 *pUOffsetX = 0;
195 YHeight = pTexInfo->BaseHeight;
196 *pUOffsetY = pTexInfo->BaseHeight;
197
198 *pVOffsetX = 0;
199 VHeight = pTexInfo->BaseHeight;
200 *pVOffsetY = (GMM_GFX_SIZE_T)pTexInfo->BaseHeight * 2;
201 }
202 else // Tiled
203 {
204 *pUOffsetX = 0;
205 YHeight = GFX_ALIGN(pTexInfo->BaseHeight, GMM_IMCx_PLANE_ROW_ALIGNMENT);
206 *pUOffsetY = GFX_ALIGN(pTexInfo->BaseHeight, GMM_IMCx_PLANE_ROW_ALIGNMENT);
207
208 *pVOffsetX = 0;
209 VHeight = GFX_ALIGN(pTexInfo->BaseHeight, GMM_IMCx_PLANE_ROW_ALIGNMENT);
210 *pVOffsetY = (GMM_GFX_SIZE_T)GFX_ALIGN(pTexInfo->BaseHeight, GMM_IMCx_PLANE_ROW_ALIGNMENT) * 2;
211 }
212 break;
213 }
214 case GMM_FORMAT_IMC2:
215 SWAP_UV(); // IMC2 = IMC4 with Swapped U/V
216 case GMM_FORMAT_IMC4:
217 {
218 // YYYYYYYY
219 // YYYYYYYY
220 // YYYYYYYY
221 // YYYYYYYY
222 // UUUUVVVV
223 // UUUUVVVV
224
225 __GMM_ASSERT((pTexInfo->Pitch & 1) == 0);
226
227 *pUOffsetX = 0;
228 YHeight = GFX_ALIGN(pTexInfo->BaseHeight, GMM_IMCx_PLANE_ROW_ALIGNMENT);
229 *pUOffsetY = GFX_ALIGN(pTexInfo->BaseHeight, GMM_IMCx_PLANE_ROW_ALIGNMENT);
230
231 *pVOffsetX = pTexInfo->Pitch / 2;
232 VHeight = GFX_CEIL_DIV(YHeight, 2);
233 *pVOffsetY = GFX_ALIGN(pTexInfo->BaseHeight, GMM_IMCx_PLANE_ROW_ALIGNMENT);
234
235 // Not technically UV packed but sizing works out the same
236 UVPacked = true;
237
238 break;
239 }
240 case GMM_FORMAT_I420: // I420 = IYUV
241 case GMM_FORMAT_IYUV:
242 SWAP_UV(); // I420/IYUV = YV12 with Swapped U/V
243 case GMM_FORMAT_YV12:
244 case GMM_FORMAT_YVU9:
245 {
246 // YYYYYYYY
247 // YYYYYYYY
248 // YYYYYYYY
249 // YYYYYYYY
250 // VVVVVV.. <-- V and U planes follow the Y plane, as linear
251 // ..UUUUUU arrays--without respect to pitch.
252
253 uint32_t YSize, YVSizeRShift, VSize, UOffset;
254 uint32_t YSizeForUVPurposes, YSizeForUVPurposesDimensionalAlignment;
255
256 YSize = GFX_ULONG_CAST(pTexInfo->Pitch) * pTexInfo->BaseHeight;
257
258 // YVU9 has one U/V pixel for each 4x4 Y block.
259 // The others have one U/V pixel for each 2x2 Y block.
260
261 // YVU9 has a Y:V size ratio of 16 (4x4 --> 1).
262 // The others have a ratio of 4 (2x2 --> 1).
263 YVSizeRShift = (pTexInfo->Format != GMM_FORMAT_YVU9) ? 2 : 4;
264
265 // If a Y plane isn't fully-aligned to its Y-->U/V block size, the
266 // extra/unaligned Y pixels still need corresponding U/V pixels--So
267 // for the purpose of computing the UVSize, we must consider a
268 // dimensionally "rounded-up" YSize. (E.g. a 13x5 YVU9 Y plane would
269 // require 4x2 U/V planes--the same UVSize as a fully-aligned 16x8 Y.)
270 YSizeForUVPurposesDimensionalAlignment = (pTexInfo->Format != GMM_FORMAT_YVU9) ? 2 : 4;
271 YSizeForUVPurposes =
272 GFX_ALIGN(GFX_ULONG_CAST(pTexInfo->Pitch), YSizeForUVPurposesDimensionalAlignment) *
273 GFX_ALIGN(pTexInfo->BaseHeight, YSizeForUVPurposesDimensionalAlignment);
274
275 VSize = (YSizeForUVPurposes >> YVSizeRShift);
276 UOffset = YSize + VSize;
277
278 *pVOffsetX = 0;
279 *pVOffsetY = pTexInfo->BaseHeight;
280
281 *pUOffsetX = UOffset % pTexInfo->Pitch;
282 *pUOffsetY = UOffset / pTexInfo->Pitch;
283
284 YHeight = GFX_CEIL_DIV(YSize + 2 * VSize, WidthBytesPhysical);
285
286 break;
287 }
288 case GMM_FORMAT_NV12:
289 case GMM_FORMAT_NV21:
290 case GMM_FORMAT_NV11:
291 case GMM_FORMAT_P010:
292 case GMM_FORMAT_P012:
293 case GMM_FORMAT_P016:
294 case GMM_FORMAT_P208:
295 case GMM_FORMAT_P216:
296 {
297 // YYYYYYYY
298 // YYYYYYYY
299 // YYYYYYYY
300 // YYYYYYYY
301 // [UV-Packing]
302 *pUOffsetX = *pVOffsetX = 0;
303 YHeight = GFX_ALIGN(Height, __GMM_EVEN_ROW);
304 *pUOffsetY = *pVOffsetY = YHeight;
305
306 if((pTexInfo->Format == GMM_FORMAT_NV12) ||
307 (pTexInfo->Format == GMM_FORMAT_NV21) ||
308 (pTexInfo->Format == GMM_FORMAT_P010) ||
309 (pTexInfo->Format == GMM_FORMAT_P012) ||
310 (pTexInfo->Format == GMM_FORMAT_P016))
311 {
312 VHeight = GFX_CEIL_DIV(Height, 2);
313 }
314 else
315 {
316 VHeight = YHeight; // U/V plane is same as Y
317 }
318
319 UVPacked = true;
320 break;
321 }
322 default:
323 {
324 GMM_ASSERTDPF(0, "Unknown Video Format U\n");
325 break;
326 }
327 }
328
329 pTexInfo->OffsetInfo.Plane.UnAligned.Height[GMM_PLANE_Y] = YHeight;
330 if(pTexInfo->OffsetInfo.Plane.NoOfPlanes == 2)
331 {
332 pTexInfo->OffsetInfo.Plane.UnAligned.Height[GMM_PLANE_U] = VHeight;
333 }
334 else if(pTexInfo->OffsetInfo.Plane.NoOfPlanes == 3)
335 {
336 pTexInfo->OffsetInfo.Plane.UnAligned.Height[GMM_PLANE_U] =
337 pTexInfo->OffsetInfo.Plane.UnAligned.Height[GMM_PLANE_V] = VHeight;
338 }
339
340
341 if(GMM_IS_TILED(pPlatform->TileInfo[pTexInfo->TileMode]) || pTexInfo->Flags.Gpu.__NonMsaaTileYCcs)
342 {
343 GMM_GFX_SIZE_T TileHeight = pGmmLibContext->GetPlatformInfo().TileInfo[pTexInfo->TileMode].LogicalTileHeight;
344 GMM_GFX_SIZE_T TileWidth = pGmmLibContext->GetPlatformInfo().TileInfo[pTexInfo->TileMode].LogicalTileWidth;
345
346 *pUOffsetX = GFX_ALIGN(*pUOffsetX, TileWidth);
347 *pUOffsetY = GFX_ALIGN(*pUOffsetY, TileHeight);
348 *pVOffsetX = GFX_ALIGN(*pVOffsetX, TileWidth);
349 *pVOffsetY = UVPacked ?
350 GFX_ALIGN(*pVOffsetY, TileHeight) :
351 GFX_ALIGN(YHeight, TileHeight) + GFX_ALIGN(VHeight, TileHeight);
352
353 if(pTexInfo->Flags.Gpu.UnifiedAuxSurface && pTexInfo->Flags.Gpu.__NonMsaaTileYCcs)
354 {
355 *pUOffsetY += pTexInfo->OffsetInfo.Plane.Y[GMM_PLANE_Y];
356 *pVOffsetY = *pUOffsetY;
357 }
358 }
359
360 //Special case LKF MMC compressed surfaces
361 if(pTexInfo->Flags.Gpu.MMC &&
362 pTexInfo->Flags.Gpu.UnifiedAuxSurface &&
363 GMM_IS_4KB_TILE(pTexInfo->Flags))
364 {
365 GMM_GFX_SIZE_T TileHeight = pGmmLibContext->GetPlatformInfo().TileInfo[pTexInfo->TileMode].LogicalTileHeight;
366 GMM_GFX_SIZE_T TileWidth = pGmmLibContext->GetPlatformInfo().TileInfo[pTexInfo->TileMode].LogicalTileWidth;
367
368 *pUOffsetX = GFX_ALIGN(*pUOffsetX, TileWidth);
369 *pUOffsetY = GFX_ALIGN(*pUOffsetY, TileHeight);
370 *pVOffsetX = GFX_ALIGN(*pVOffsetX, TileWidth);
371 *pVOffsetY = GFX_ALIGN(*pVOffsetY, TileHeight);
372 }
373
374 GMM_DPF_EXIT;
375
376 #undef SWAP_UV
377 }
378
379
380 /////////////////////////////////////////////////////////////////////////////////////
381 /// Sibling function of GmmLib::GmmTextureCalc::ExpandWidth. it returns the given
382 /// Width, as appropriately scaled by the MSAA NumSamples parameter and aligned to the
383 /// given UnitAlignment.
384 ///
385 /// @param[in] Height: Height of the surface
386 /// @param[in] UnitAlignment: Unit alignment factor
387 /// @param[in] NumSamples: No of MSAA samples
388 ///
389 /// @return scaled height
390 /////////////////////////////////////////////////////////////////////////////////////
ExpandHeight(uint32_t Height,uint32_t UnitAlignment,uint32_t NumSamples)391 uint32_t GmmLib::GmmTextureCalc::ExpandHeight(uint32_t Height, uint32_t UnitAlignment, uint32_t NumSamples)
392 {
393 // Implemented as separate function (instead of as a single function with a
394 // Width/Height parameter) so both functions can be later implemented without
395 // branches, if need be.
396
397 return (
398 GmmLib::GmmTextureCalc::ExpandWidth(
399 Height, UnitAlignment,
400 (NumSamples == 2) ? 1 : // MSAA_2X: No height adjustment
401 ((NumSamples == 8) ? 4 : NumSamples))); // <-- MSAA_8X:Height = MSAA_4X:Height.
402 }
403
404
405 /////////////////////////////////////////////////////////////////////////////////////
406 /// This function returns the given Width, as appropriately scaled by the MSAA
407 /// NumSamples parameter and aligned to the given UnitAlignment.
408 ///
409 /// @param[in] Width: Height of the surface
410 /// @param[in] UnitAlignment: Unit alignment factor
411 /// @param[in] NumSamples: No of MSAA samples
412 ///
413 /// @return scaled width
414 /////////////////////////////////////////////////////////////////////////////////////
ExpandWidth(uint32_t Width,uint32_t UnitAlignment,uint32_t NumSamples)415 uint32_t GmmLib::GmmTextureCalc::ExpandWidth(uint32_t Width, uint32_t UnitAlignment, uint32_t NumSamples)
416 {
417 uint32_t ExpandedWidth;
418
419 switch(NumSamples)
420 {
421 case 1:
422 ExpandedWidth = Width;
423 break;
424 case 2: // Same as 4x...
425 case 4:
426 ExpandedWidth = GFX_CEIL_DIV(GFX_MAX(Width, 1), 2) * 4;
427 break;
428 case 8: // Same as 16x...
429 case 16:
430 ExpandedWidth = GFX_CEIL_DIV(GFX_MAX(Width, 1), 2) * 8;
431 break;
432 default:
433 ExpandedWidth = Width;
434 __GMM_ASSERT(0);
435 }
436
437 ExpandedWidth = GFX_MAX(ExpandedWidth, UnitAlignment);
438 ExpandedWidth = GFX_ALIGN_NP2(ExpandedWidth, UnitAlignment);
439
440 return (ExpandedWidth);
441 }
442
443
444 /////////////////////////////////////////////////////////////////////////////////////
445 /// This function calculates Mip Tail Start LOD using max mip tail dimensions and
446 /// populates pTexInfo->Alignment.MipTailStartLod
447 ///
448 /// @param[in] pTexInfo: ptr to ::GMM_TEXTURE_INFO
449 ///
450 /////////////////////////////////////////////////////////////////////////////////////
FindMipTailStartLod(GMM_TEXTURE_INFO * pTexInfo)451 void GmmLib::GmmTextureCalc::FindMipTailStartLod(GMM_TEXTURE_INFO *pTexInfo)
452 {
453 GMM_DPF_ENTER;
454
455 if(!(pTexInfo->Flags.Info.TiledYf || GMM_IS_64KB_TILE(pTexInfo->Flags)) ||
456 (pTexInfo->MaxLod == 0) ||
457 (pTexInfo->Flags.Wa.DisablePackedMipTail))
458 {
459 // HW never ignores MipTailStartLod for Yf/Ys surfaces. If we do not
460 // want a mip tail, we set MipTailStartLod to be greater than MaxLod.
461 pTexInfo->Alignment.MipTailStartLod = GMM_TILED_RESOURCE_NO_MIP_TAIL;
462 }
463 else
464 {
465 uint32_t MipDepth, MipHeight, MipWidth, CompressWidth, CompressHeight, CompressDepth;
466 uint32_t Level = 0;
467 const GMM_PLATFORM_INFO *pPlatform = GMM_OVERRIDE_PLATFORM_INFO(pTexInfo, pGmmLibContext);
468
469 MipDepth = pTexInfo->Depth;
470 MipHeight = pTexInfo->BaseHeight;
471 MipWidth = GFX_ULONG_CAST(pTexInfo->BaseWidth);
472
473 //if compressed texture format, use compressed height, width
474 GetCompressionBlockDimensions(pTexInfo->Format, &CompressWidth, &CompressHeight, &CompressDepth);
475
476 if(GmmIsCompressed(pGmmLibContext, pTexInfo->Format))
477 {
478 MipWidth = GFX_CEIL_DIV(MipWidth, CompressWidth);
479 MipHeight = GFX_CEIL_DIV(MipHeight, CompressHeight);
480 MipDepth = GFX_CEIL_DIV(MipDepth, CompressDepth);
481 }
482
483 __GMM_ASSERT(pTexInfo->TileMode < GMM_TILE_MODES);
484
485 while((Level < pTexInfo->MaxLod) &&
486 (((pTexInfo->Type == RESOURCE_1D) &&
487 !(MipWidth <= pPlatform->TileInfo[pTexInfo->TileMode].MaxMipTailStartWidth)) ||
488 (((pTexInfo->Type == RESOURCE_2D) || (pTexInfo->Type == RESOURCE_CUBE)) &&
489 !((MipWidth <= pPlatform->TileInfo[pTexInfo->TileMode].MaxMipTailStartWidth) &&
490 (MipHeight <= pPlatform->TileInfo[pTexInfo->TileMode].MaxMipTailStartHeight))) ||
491 ((pTexInfo->Type == RESOURCE_3D) &&
492 !((MipWidth <= pPlatform->TileInfo[pTexInfo->TileMode].MaxMipTailStartWidth) &&
493 (MipHeight <= pPlatform->TileInfo[pTexInfo->TileMode].MaxMipTailStartHeight) &&
494 (MipDepth <= pPlatform->TileInfo[pTexInfo->TileMode].MaxMipTailStartDepth)))))
495 {
496 Level++;
497
498 MipWidth = GFX_ULONG_CAST(GmmTexGetMipWidth(pTexInfo, Level));
499 MipHeight = GmmTexGetMipHeight(pTexInfo, Level);
500 MipDepth = GmmTexGetMipDepth(pTexInfo, Level);
501
502 MipWidth = GFX_CEIL_DIV(MipWidth, CompressWidth);
503 MipHeight = GFX_CEIL_DIV(MipHeight, CompressHeight);
504 MipDepth = GFX_CEIL_DIV(MipDepth, CompressDepth);
505 }
506
507 if(((pTexInfo->Type == RESOURCE_1D) &&
508 (MipWidth <= pPlatform->TileInfo[pTexInfo->TileMode].MaxMipTailStartWidth)) ||
509 (((pTexInfo->Type == RESOURCE_2D) || (pTexInfo->Type == RESOURCE_CUBE)) &&
510 ((MipWidth <= pPlatform->TileInfo[pTexInfo->TileMode].MaxMipTailStartWidth) &&
511 (MipHeight <= pPlatform->TileInfo[pTexInfo->TileMode].MaxMipTailStartHeight))) ||
512 ((pTexInfo->Type == RESOURCE_3D) &&
513 ((MipWidth <= pPlatform->TileInfo[pTexInfo->TileMode].MaxMipTailStartWidth) &&
514 (MipHeight <= pPlatform->TileInfo[pTexInfo->TileMode].MaxMipTailStartHeight) &&
515 (MipDepth <= pPlatform->TileInfo[pTexInfo->TileMode].MaxMipTailStartDepth))))
516 {
517 pTexInfo->Alignment.MipTailStartLod = Level;
518 }
519 else
520 {
521 pTexInfo->Alignment.MipTailStartLod = GMM_TILED_RESOURCE_NO_MIP_TAIL;
522 }
523 }
524
525 GMM_DPF_EXIT;
526 }
527
528
529 /////////////////////////////////////////////////////////////////////////////////////
530 /// This function returns the height, width and depth of the compression block for a
531 /// given surface format.
532 ///
533 /// @param[in] Format: ::GMM_RESOURCE_FORMAT
534 /// @param[in] pWidth: populates Width
535 /// @param[in] pHeight: populates Height
536 /// @param[in] pDepth: populates Depth
537 ///
538 /////////////////////////////////////////////////////////////////////////////////////
GetCompressionBlockDimensions(GMM_RESOURCE_FORMAT Format,uint32_t * pWidth,uint32_t * pHeight,uint32_t * pDepth)539 void GmmLib::GmmTextureCalc::GetCompressionBlockDimensions(GMM_RESOURCE_FORMAT Format,
540 uint32_t * pWidth,
541 uint32_t * pHeight,
542 uint32_t * pDepth)
543 {
544
545 GMM_DPF_ENTER;
546 __GMM_ASSERT(pWidth && pHeight && pDepth);
547
548 if(pWidth && pHeight && pDepth)
549 {
550 if((Format > GMM_FORMAT_INVALID) && (Format < GMM_RESOURCE_FORMATS))
551 {
552 *pWidth = pGmmLibContext->GetPlatformInfo().FormatTable[Format].Element.Width;
553 *pHeight = pGmmLibContext->GetPlatformInfo().FormatTable[Format].Element.Height;
554 *pDepth = pGmmLibContext->GetPlatformInfo().FormatTable[Format].Element.Depth;
555 }
556 else
557 {
558 *pWidth = 1;
559 *pHeight = 1;
560 *pDepth = 1;
561 }
562 }
563 GMM_DPF_EXIT;
564 }
565
566 /////////////////////////////////////////////////////////////////////////////////////
567 /// This function Convert from d3d tile (64KB) to h/w tile
568 ///
569 /// @param[in] pTexInfo: ::GMM_TEXTURE_INFO
570 /// @param[in/out] pColFactor: populates Width
571 /// @param[in/out] pRowFactor: populates Height
572 /// @param[out] true on Success else false
573 ///
574 /////////////////////////////////////////////////////////////////////////////////////
GmmGetD3DToHwTileConversion(GMM_TEXTURE_INFO * pTexInfo,uint32_t * pColFactor,uint32_t * pRowFactor)575 bool GmmLib::GmmTextureCalc::GmmGetD3DToHwTileConversion(GMM_TEXTURE_INFO *pTexInfo,
576 uint32_t * pColFactor,
577 uint32_t * pRowFactor)
578 {
579 uint32_t i = 0;
580 uint32_t Bpp = pTexInfo->BitsPerPixel;
581
582 // check for unsupported bpp
583 if(!(Bpp == 8 || Bpp == 16 || Bpp == 32 || Bpp == 64 || Bpp == 128))
584 {
585 __GMM_ASSERT(false);
586 goto EXIT_ERROR;
587 }
588
589 // for TileYS, no conversion
590 if(GMM_IS_64KB_TILE(pTexInfo->Flags) || pTexInfo->Flags.Info.Linear)
591 {
592 *pColFactor = 1;
593 *pRowFactor = 1;
594 }
595 else if(GMM_IS_4KB_TILE(pTexInfo->Flags))
596 {
597 // Logic for non-MSAA
598 {
599 // Bpp = 8 => i = 0 , Bpp = 16 => i = 1, ...
600 // Log2(Bpp = 8) = 3 => i = Log2(8) - 3.
601
602 i = __GmmLog2(Bpp) - 3;
603 *pColFactor = __GmmTileYConversionTable[i][0];
604 *pRowFactor = __GmmTileYConversionTable[i][1];
605 }
606
607 // Logic for MSAA
608 if(pTexInfo->MSAA.NumSamples > 1)
609 {
610
611 // For MSAA, the DirectX tile dimensions change, using the table __GmmMSAAConversion.
612 uint32_t W = __GmmMSAAConversion[__GmmLog2(pTexInfo->MSAA.NumSamples)][0];
613 uint32_t H = __GmmMSAAConversion[__GmmLog2(pTexInfo->MSAA.NumSamples)][1];
614
615 // For the new DirectX tile dimensions the new Col and Row conversion factors are:
616 *pColFactor /= W;
617 *pRowFactor /= H;
618 }
619 }
620 else
621 {
622 // unsupported format.
623 __GMM_ASSERT(false);
624 goto EXIT_ERROR;
625 }
626
627 return true;
628
629 EXIT_ERROR:
630 *pColFactor = 0;
631 *pRowFactor = 0;
632 return false;
633 }
634
635 /////////////////////////////////////////////////////////////////////////////////////
636 /// This function redescribes WidthBytesPhysical of main surface as per UV plane bpp and tilemode
637 ///
638 /// @return ::bool
639 /////////////////////////////////////////////////////////////////////////////////////
RedescribeTexturePlanes(GMM_TEXTURE_INFO * pTexInfo,uint32_t * pWidthBytesPhysical)640 bool GmmLib::GmmTextureCalc::RedescribeTexturePlanes(GMM_TEXTURE_INFO *pTexInfo, uint32_t *pWidthBytesPhysical)
641 {
642 GMM_STATUS Status = GMM_SUCCESS;
643 GMM_TEXTURE_INFO TexInfoUVPlane;
644 const GMM_PLATFORM_INFO *pPlatform = GMM_OVERRIDE_PLATFORM_INFO(pTexInfo, pGmmLibContext);
645
646 __GMM_ASSERT(pTexInfo);
647 __GMM_ASSERT(pTexInfo->Flags.Info.RedecribedPlanes);
648 __GMM_ASSERT(pWidthBytesPhysical);
649
650 TexInfoUVPlane = *pTexInfo;
651 #ifdef _WIN32
652 memcpy_s(&TexInfoUVPlane, sizeof(GMM_TEXTURE_INFO), pTexInfo, sizeof(GMM_TEXTURE_INFO));
653 #else
654 memcpy(&TexInfoUVPlane, pTexInfo, sizeof(GMM_TEXTURE_INFO));
655 #endif // _WIN32
656
657
658 if(GmmIsUVPacked(pTexInfo->Format))
659 {
660 // UV packed resources must have two seperate
661 // tiling modes per plane, due to the packed
662 // UV plane having twice the bits per pixel
663 // as the Y plane.
664 switch(pTexInfo->Format)
665 {
666 case GMM_FORMAT_NV12:
667 case GMM_FORMAT_NV21:
668 case GMM_FORMAT_P208:
669 TexInfoUVPlane.BitsPerPixel = 16; // Redescribe bpp to 16 from 8
670 break;
671 case GMM_FORMAT_P010:
672 case GMM_FORMAT_P012:
673 case GMM_FORMAT_P016:
674 case GMM_FORMAT_P216:
675 TexInfoUVPlane.BitsPerPixel = 32;
676 break;
677 default:
678 GMM_ASSERTDPF(0, "Unsupported format/pixel size combo!");
679 Status = GMM_INVALIDPARAM;
680 goto ERROR_CASE;
681 break;
682 }
683 }
684 else
685 {
686 // Non-UV packed surfaces, TileMode and bpp of each plane is same as that of pTexInfo
687 }
688
689 SetTileMode(&TexInfoUVPlane);
690 *pWidthBytesPhysical = GFX_ALIGN(*pWidthBytesPhysical, pPlatform->TileInfo[TexInfoUVPlane.TileMode].LogicalTileWidth);
691
692 ERROR_CASE:
693 return (Status == GMM_SUCCESS) ? true : false;
694 }
695
696 /////////////////////////////////////////////////////////////////////////////////////
697 /// This function returns per plane redescribed parameters (pRedescribedTexInfo: fmt, tilemode,bpp, width, height, size) when main surface pTexInfo is passed
698 ///
699 /// @return ::bool
700 /////////////////////////////////////////////////////////////////////////////////////
GetRedescribedPlaneParams(GMM_TEXTURE_INFO * pTexInfo,GMM_YUV_PLANE PlaneType,GMM_TEXTURE_INFO * pRedescribedTexInfo)701 bool GmmLib::GmmTextureCalc::GetRedescribedPlaneParams(GMM_TEXTURE_INFO *pTexInfo, GMM_YUV_PLANE PlaneType, GMM_TEXTURE_INFO *pRedescribedTexInfo)
702 {
703 GMM_STATUS Status = GMM_SUCCESS;
704 GMM_TEXTURE_INFO TexInfoUVPlane;
705 const GMM_PLATFORM_INFO *pPlatform = GMM_OVERRIDE_PLATFORM_INFO(pTexInfo, pGmmLibContext);
706
707 __GMM_ASSERT(pTexInfo);
708 __GMM_ASSERT(pTexInfo->Flags.Info.RedecribedPlanes);
709 __GMM_ASSERT(pRedescribedTexInfo);
710
711 *pRedescribedTexInfo = *pTexInfo;
712 pRedescribedTexInfo->Flags.Info.RedecribedPlanes = 0;
713 #ifdef _WIN32
714 memcpy_s(&TexInfoUVPlane, sizeof(GMM_TEXTURE_INFO), pTexInfo, sizeof(GMM_TEXTURE_INFO));
715 #else
716 memcpy(&TexInfoUVPlane, pTexInfo, sizeof(GMM_TEXTURE_INFO));
717 #endif // _WIN32
718
719 if(GmmIsUVPacked(pTexInfo->Format))
720 {
721 // UV packed resources must have two seperate
722 // tiling modes per plane, due to the packed
723 // UV plane having twice the bits per pixel
724 // as the Y plane.
725 if((PlaneType == GMM_PLANE_U) || (PlaneType == GMM_PLANE_V))
726 {
727 switch(pTexInfo->Format)
728 {
729 // GMM_FORMAT_NV11 : linear format, no tiling supported, hence no redescription supported
730 case GMM_FORMAT_NV12:
731 case GMM_FORMAT_NV21:
732 pRedescribedTexInfo->BitsPerPixel = 16;
733 pRedescribedTexInfo->BaseWidth = GFX_CEIL_DIV(pTexInfo->BaseWidth, 2);
734 pRedescribedTexInfo->BaseHeight = GFX_CEIL_DIV(pTexInfo->BaseHeight, 2);
735 break;
736 case GMM_FORMAT_P208:
737 pRedescribedTexInfo->BitsPerPixel = 16;
738 pRedescribedTexInfo->BaseWidth = GFX_CEIL_DIV(pTexInfo->BaseWidth, 2);
739 // same base height as main surface
740 break;
741 case GMM_FORMAT_P010:
742 case GMM_FORMAT_P012:
743 case GMM_FORMAT_P016:
744 pRedescribedTexInfo->BitsPerPixel = 32;
745 pRedescribedTexInfo->BaseWidth = GFX_CEIL_DIV(pTexInfo->BaseWidth, 2);
746 pRedescribedTexInfo->BaseHeight = GFX_CEIL_DIV(pTexInfo->BaseHeight, 2);
747 break;
748 case GMM_FORMAT_P216:
749 pRedescribedTexInfo->BitsPerPixel = 32;
750 pRedescribedTexInfo->BaseWidth = GFX_CEIL_DIV(pTexInfo->BaseWidth, 2);
751 // same base height as main surface
752 break;
753 default:
754 GMM_ASSERTDPF(0, "Unsupported format/pixel size combo!");
755 Status = GMM_INVALIDPARAM;
756 goto ERROR_CASE;
757 break;
758 }
759 }
760 }
761 else
762 {
763 // Non-UV packed surfaces TileMode of each plane is same as that of pTexInfo
764 if((PlaneType == GMM_PLANE_U) || (PlaneType == GMM_PLANE_V))
765 { // Non-UV packed surfaces only require the plane descriptors have proper height and width for each plane
766 switch(pTexInfo->Format)
767 {
768 case GMM_FORMAT_IMC1:
769 case GMM_FORMAT_IMC2:
770 case GMM_FORMAT_IMC3:
771 case GMM_FORMAT_IMC4:
772 case GMM_FORMAT_MFX_JPEG_YUV420:
773 pRedescribedTexInfo->BaseWidth = GFX_CEIL_DIV(pTexInfo->BaseWidth, 2);
774 pRedescribedTexInfo->BaseHeight = GFX_CEIL_DIV(pTexInfo->BaseHeight, 2);
775 break;
776 case GMM_FORMAT_MFX_JPEG_YUV422V:
777 pRedescribedTexInfo->BaseHeight = GFX_CEIL_DIV(pTexInfo->BaseHeight, 2);
778 break;
779 case GMM_FORMAT_MFX_JPEG_YUV411R_TYPE:
780 pRedescribedTexInfo->BaseHeight = GFX_CEIL_DIV(pTexInfo->BaseHeight, 4);
781 break;
782 case GMM_FORMAT_MFX_JPEG_YUV411:
783 pRedescribedTexInfo->BaseWidth = GFX_CEIL_DIV(pTexInfo->BaseWidth, 4);
784 break;
785 case GMM_FORMAT_MFX_JPEG_YUV422H:
786 pRedescribedTexInfo->BaseWidth = GFX_CEIL_DIV(pTexInfo->BaseWidth, 2);
787 break;
788 default:
789 GMM_ASSERTDPF(0, "Unsupported format/pixel size combo!");
790 Status = GMM_INVALIDPARAM;
791 goto ERROR_CASE;
792 break;
793 }
794 }
795 }
796
797 SetTileMode(pRedescribedTexInfo);
798 switch(pRedescribedTexInfo->BitsPerPixel)
799 {
800 case 8:
801 pRedescribedTexInfo->Format = GMM_FORMAT_R8_UINT;
802 break;
803 case 16:
804 pRedescribedTexInfo->Format = GMM_FORMAT_R16_UINT;
805 break;
806 case 32:
807 pRedescribedTexInfo->Format = GMM_FORMAT_R32_UINT;
808 break;
809 default:
810 GMM_ASSERTDPF(0, "Unsupported format/pixel size combo!");
811 Status = GMM_INVALIDPARAM;
812 goto ERROR_CASE;
813 break;
814 }
815 if(pTexInfo->ArraySize > 1)
816 {
817 pRedescribedTexInfo->OffsetInfo.Plane.ArrayQPitch = 0; // no longer a planar format on redescription
818 pRedescribedTexInfo->Alignment.QPitch = GFX_ALIGN(pRedescribedTexInfo->BaseHeight, pTexInfo->Alignment.VAlign);
819 pRedescribedTexInfo->OffsetInfo.Texture2DOffsetInfo.ArrayQPitchRender =
820 pRedescribedTexInfo->OffsetInfo.Texture2DOffsetInfo.ArrayQPitchLock = pRedescribedTexInfo->Alignment.QPitch * pTexInfo->Pitch;
821 pRedescribedTexInfo->Size = pRedescribedTexInfo->Alignment.QPitch * pTexInfo->Pitch * pTexInfo->ArraySize;
822 }
823 else
824 {
825 pRedescribedTexInfo->Size = (GFX_ALIGN(pRedescribedTexInfo->BaseHeight, pTexInfo->Alignment.VAlign)) * pTexInfo->Pitch;
826 }
827
828 ERROR_CASE:
829 return (Status == GMM_SUCCESS) ? true : false;
830 }
831