xref: /aosp_15_r20/external/gmmlib/Source/GmmLib/Texture/GmmTexture.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 /// 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