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 while((Level < pTexInfo->MaxLod) &&
484 (((pTexInfo->Type == RESOURCE_1D) &&
485 !(MipWidth <= pPlatform->TileInfo[pTexInfo->TileMode].MaxMipTailStartWidth)) ||
486 (((pTexInfo->Type == RESOURCE_2D) || (pTexInfo->Type == RESOURCE_CUBE)) &&
487 !((MipWidth <= pPlatform->TileInfo[pTexInfo->TileMode].MaxMipTailStartWidth) &&
488 (MipHeight <= pPlatform->TileInfo[pTexInfo->TileMode].MaxMipTailStartHeight))) ||
489 ((pTexInfo->Type == RESOURCE_3D) &&
490 !((MipWidth <= pPlatform->TileInfo[pTexInfo->TileMode].MaxMipTailStartWidth) &&
491 (MipHeight <= pPlatform->TileInfo[pTexInfo->TileMode].MaxMipTailStartHeight) &&
492 (MipDepth <= pPlatform->TileInfo[pTexInfo->TileMode].MaxMipTailStartDepth)))))
493 {
494 Level++;
495
496 MipWidth = GFX_ULONG_CAST(GmmTexGetMipWidth(pTexInfo, Level));
497 MipHeight = GmmTexGetMipHeight(pTexInfo, Level);
498 MipDepth = GmmTexGetMipDepth(pTexInfo, Level);
499
500 MipWidth = GFX_CEIL_DIV(MipWidth, CompressWidth);
501 MipHeight = GFX_CEIL_DIV(MipHeight, CompressHeight);
502 MipDepth = GFX_CEIL_DIV(MipDepth, CompressDepth);
503 }
504
505 if(((pTexInfo->Type == RESOURCE_1D) &&
506 (MipWidth <= pPlatform->TileInfo[pTexInfo->TileMode].MaxMipTailStartWidth)) ||
507 (((pTexInfo->Type == RESOURCE_2D) || (pTexInfo->Type == RESOURCE_CUBE)) &&
508 ((MipWidth <= pPlatform->TileInfo[pTexInfo->TileMode].MaxMipTailStartWidth) &&
509 (MipHeight <= pPlatform->TileInfo[pTexInfo->TileMode].MaxMipTailStartHeight))) ||
510 ((pTexInfo->Type == RESOURCE_3D) &&
511 ((MipWidth <= pPlatform->TileInfo[pTexInfo->TileMode].MaxMipTailStartWidth) &&
512 (MipHeight <= pPlatform->TileInfo[pTexInfo->TileMode].MaxMipTailStartHeight) &&
513 (MipDepth <= pPlatform->TileInfo[pTexInfo->TileMode].MaxMipTailStartDepth))))
514 {
515 pTexInfo->Alignment.MipTailStartLod = Level;
516 }
517 else
518 {
519 pTexInfo->Alignment.MipTailStartLod = GMM_TILED_RESOURCE_NO_MIP_TAIL;
520 }
521 }
522
523 GMM_DPF_EXIT;
524 }
525
526
527 /////////////////////////////////////////////////////////////////////////////////////
528 /// This function returns the height, width and depth of the compression block for a
529 /// given surface format.
530 ///
531 /// @param[in] Format: ::GMM_RESOURCE_FORMAT
532 /// @param[in] pWidth: populates Width
533 /// @param[in] pHeight: populates Height
534 /// @param[in] pDepth: populates Depth
535 ///
536 /////////////////////////////////////////////////////////////////////////////////////
GetCompressionBlockDimensions(GMM_RESOURCE_FORMAT Format,uint32_t * pWidth,uint32_t * pHeight,uint32_t * pDepth)537 void GmmLib::GmmTextureCalc::GetCompressionBlockDimensions(GMM_RESOURCE_FORMAT Format,
538 uint32_t * pWidth,
539 uint32_t * pHeight,
540 uint32_t * pDepth)
541 {
542
543 GMM_DPF_ENTER;
544 __GMM_ASSERT(pWidth && pHeight && pDepth);
545
546 if(pWidth && pHeight && pDepth)
547 {
548 if((Format > GMM_FORMAT_INVALID) && (Format < GMM_RESOURCE_FORMATS))
549 {
550 *pWidth = pGmmLibContext->GetPlatformInfo().FormatTable[Format].Element.Width;
551 *pHeight = pGmmLibContext->GetPlatformInfo().FormatTable[Format].Element.Height;
552 *pDepth = pGmmLibContext->GetPlatformInfo().FormatTable[Format].Element.Depth;
553 }
554 else
555 {
556 *pWidth = 1;
557 *pHeight = 1;
558 *pDepth = 1;
559 }
560 }
561 GMM_DPF_EXIT;
562 }
563
564 /////////////////////////////////////////////////////////////////////////////////////
565 /// This function Convert from d3d tile (64KB) to h/w tile
566 ///
567 /// @param[in] pTexInfo: ::GMM_TEXTURE_INFO
568 /// @param[in/out] pColFactor: populates Width
569 /// @param[in/out] pRowFactor: populates Height
570 /// @param[out] true on Success else false
571 ///
572 /////////////////////////////////////////////////////////////////////////////////////
GmmGetD3DToHwTileConversion(GMM_TEXTURE_INFO * pTexInfo,uint32_t * pColFactor,uint32_t * pRowFactor)573 bool GmmLib::GmmTextureCalc::GmmGetD3DToHwTileConversion(GMM_TEXTURE_INFO *pTexInfo,
574 uint32_t * pColFactor,
575 uint32_t * pRowFactor)
576 {
577 uint32_t i = 0;
578 uint32_t Bpp = pTexInfo->BitsPerPixel;
579
580 // check for unsupported bpp
581 if(!(Bpp == 8 || Bpp == 16 || Bpp == 32 || Bpp == 64 || Bpp == 128))
582 {
583 __GMM_ASSERT(false);
584 goto EXIT_ERROR;
585 }
586
587 // for TileYS, no conversion
588 if(GMM_IS_64KB_TILE(pTexInfo->Flags) || pTexInfo->Flags.Info.Linear)
589 {
590 *pColFactor = 1;
591 *pRowFactor = 1;
592 }
593 else if(GMM_IS_4KB_TILE(pTexInfo->Flags))
594 {
595 // Logic for non-MSAA
596 {
597 // Bpp = 8 => i = 0 , Bpp = 16 => i = 1, ...
598 // Log2(Bpp = 8) = 3 => i = Log2(8) - 3.
599
600 i = __GmmLog2(Bpp) - 3;
601 *pColFactor = __GmmTileYConversionTable[i][0];
602 *pRowFactor = __GmmTileYConversionTable[i][1];
603 }
604
605 // Logic for MSAA
606 if(pTexInfo->MSAA.NumSamples > 1)
607 {
608
609 // For MSAA, the DirectX tile dimensions change, using the table __GmmMSAAConversion.
610 uint32_t W = __GmmMSAAConversion[__GmmLog2(pTexInfo->MSAA.NumSamples)][0];
611 uint32_t H = __GmmMSAAConversion[__GmmLog2(pTexInfo->MSAA.NumSamples)][1];
612
613 // For the new DirectX tile dimensions the new Col and Row conversion factors are:
614 *pColFactor /= W;
615 *pRowFactor /= H;
616 }
617 }
618 else
619 {
620 // unsupported format.
621 __GMM_ASSERT(false);
622 goto EXIT_ERROR;
623 }
624
625 return true;
626
627 EXIT_ERROR:
628 *pColFactor = 0;
629 *pRowFactor = 0;
630 return false;
631 }
632
633 /////////////////////////////////////////////////////////////////////////////////////
634 /// This function redescribes WidthBytesPhysical of main surface as per UV plane bpp and tilemode
635 ///
636 /// @return ::bool
637 /////////////////////////////////////////////////////////////////////////////////////
RedescribeTexturePlanes(GMM_TEXTURE_INFO * pTexInfo,uint32_t * pWidthBytesPhysical)638 bool GmmLib::GmmTextureCalc::RedescribeTexturePlanes(GMM_TEXTURE_INFO *pTexInfo, uint32_t *pWidthBytesPhysical)
639 {
640 GMM_STATUS Status = GMM_SUCCESS;
641 GMM_TEXTURE_INFO TexInfoUVPlane;
642 const GMM_PLATFORM_INFO *pPlatform = GMM_OVERRIDE_PLATFORM_INFO(pTexInfo, pGmmLibContext);
643
644 __GMM_ASSERT(pTexInfo);
645 __GMM_ASSERT(pTexInfo->Flags.Info.RedecribedPlanes);
646 __GMM_ASSERT(pWidthBytesPhysical);
647
648 TexInfoUVPlane = *pTexInfo;
649 #ifdef _WIN32
650 memcpy_s(&TexInfoUVPlane, sizeof(GMM_TEXTURE_INFO), pTexInfo, sizeof(GMM_TEXTURE_INFO));
651 #else
652 memcpy(&TexInfoUVPlane, pTexInfo, sizeof(GMM_TEXTURE_INFO));
653 #endif // _WIN32
654
655
656 if(GmmIsUVPacked(pTexInfo->Format))
657 {
658 // UV packed resources must have two seperate
659 // tiling modes per plane, due to the packed
660 // UV plane having twice the bits per pixel
661 // as the Y plane.
662 switch(pTexInfo->Format)
663 {
664 case GMM_FORMAT_NV12:
665 case GMM_FORMAT_NV21:
666 case GMM_FORMAT_P208:
667 TexInfoUVPlane.BitsPerPixel = 16; // Redescribe bpp to 16 from 8
668 break;
669 case GMM_FORMAT_P010:
670 case GMM_FORMAT_P012:
671 case GMM_FORMAT_P016:
672 case GMM_FORMAT_P216:
673 TexInfoUVPlane.BitsPerPixel = 32;
674 break;
675 default:
676 GMM_ASSERTDPF(0, "Unsupported format/pixel size combo!");
677 Status = GMM_INVALIDPARAM;
678 goto ERROR_CASE;
679 break;
680 }
681 }
682 else
683 {
684 // Non-UV packed surfaces, TileMode and bpp of each plane is same as that of pTexInfo
685 }
686
687 SetTileMode(&TexInfoUVPlane);
688 *pWidthBytesPhysical = GFX_ALIGN(*pWidthBytesPhysical, pPlatform->TileInfo[TexInfoUVPlane.TileMode].LogicalTileWidth);
689
690 ERROR_CASE:
691 return (Status == GMM_SUCCESS) ? true : false;
692 }
693
694 /////////////////////////////////////////////////////////////////////////////////////
695 /// This function returns per plane redescribed parameters (pRedescribedTexInfo: fmt, tilemode,bpp, width, height, size) when main surface pTexInfo is passed
696 ///
697 /// @return ::bool
698 /////////////////////////////////////////////////////////////////////////////////////
GetRedescribedPlaneParams(GMM_TEXTURE_INFO * pTexInfo,GMM_YUV_PLANE PlaneType,GMM_TEXTURE_INFO * pRedescribedTexInfo)699 bool GmmLib::GmmTextureCalc::GetRedescribedPlaneParams(GMM_TEXTURE_INFO *pTexInfo, GMM_YUV_PLANE PlaneType, GMM_TEXTURE_INFO *pRedescribedTexInfo)
700 {
701 GMM_STATUS Status = GMM_SUCCESS;
702 GMM_TEXTURE_INFO TexInfoUVPlane;
703 const GMM_PLATFORM_INFO *pPlatform = GMM_OVERRIDE_PLATFORM_INFO(pTexInfo, pGmmLibContext);
704
705 __GMM_ASSERT(pTexInfo);
706 __GMM_ASSERT(pTexInfo->Flags.Info.RedecribedPlanes);
707 __GMM_ASSERT(pRedescribedTexInfo);
708
709 *pRedescribedTexInfo = *pTexInfo;
710 pRedescribedTexInfo->Flags.Info.RedecribedPlanes = 0;
711 #ifdef _WIN32
712 memcpy_s(&TexInfoUVPlane, sizeof(GMM_TEXTURE_INFO), pTexInfo, sizeof(GMM_TEXTURE_INFO));
713 #else
714 memcpy(&TexInfoUVPlane, pTexInfo, sizeof(GMM_TEXTURE_INFO));
715 #endif // _WIN32
716
717 if(GmmIsUVPacked(pTexInfo->Format))
718 {
719 // UV packed resources must have two seperate
720 // tiling modes per plane, due to the packed
721 // UV plane having twice the bits per pixel
722 // as the Y plane.
723 if((PlaneType == GMM_PLANE_U) || (PlaneType == GMM_PLANE_V))
724 {
725 switch(pTexInfo->Format)
726 {
727 // GMM_FORMAT_NV11 : linear format, no tiling supported, hence no redescription supported
728 case GMM_FORMAT_NV12:
729 case GMM_FORMAT_NV21:
730 pRedescribedTexInfo->BitsPerPixel = 16;
731 pRedescribedTexInfo->BaseWidth = GFX_CEIL_DIV(pTexInfo->BaseWidth, 2);
732 pRedescribedTexInfo->BaseHeight = GFX_CEIL_DIV(pTexInfo->BaseHeight, 2);
733 break;
734 case GMM_FORMAT_P208:
735 pRedescribedTexInfo->BitsPerPixel = 16;
736 pRedescribedTexInfo->BaseWidth = GFX_CEIL_DIV(pTexInfo->BaseWidth, 2);
737 // same base height as main surface
738 break;
739 case GMM_FORMAT_P010:
740 case GMM_FORMAT_P012:
741 case GMM_FORMAT_P016:
742 pRedescribedTexInfo->BitsPerPixel = 32;
743 pRedescribedTexInfo->BaseWidth = GFX_CEIL_DIV(pTexInfo->BaseWidth, 2);
744 pRedescribedTexInfo->BaseHeight = GFX_CEIL_DIV(pTexInfo->BaseHeight, 2);
745 break;
746 case GMM_FORMAT_P216:
747 pRedescribedTexInfo->BitsPerPixel = 32;
748 pRedescribedTexInfo->BaseWidth = GFX_CEIL_DIV(pTexInfo->BaseWidth, 2);
749 // same base height as main surface
750 break;
751 default:
752 GMM_ASSERTDPF(0, "Unsupported format/pixel size combo!");
753 Status = GMM_INVALIDPARAM;
754 goto ERROR_CASE;
755 break;
756 }
757 }
758 }
759 else
760 {
761 // Non-UV packed surfaces TileMode of each plane is same as that of pTexInfo
762 if((PlaneType == GMM_PLANE_U) || (PlaneType == GMM_PLANE_V))
763 { // Non-UV packed surfaces only require the plane descriptors have proper height and width for each plane
764 switch(pTexInfo->Format)
765 {
766 case GMM_FORMAT_IMC1:
767 case GMM_FORMAT_IMC2:
768 case GMM_FORMAT_IMC3:
769 case GMM_FORMAT_IMC4:
770 case GMM_FORMAT_MFX_JPEG_YUV420:
771 pRedescribedTexInfo->BaseWidth = GFX_CEIL_DIV(pTexInfo->BaseWidth, 2);
772 pRedescribedTexInfo->BaseHeight = GFX_CEIL_DIV(pTexInfo->BaseHeight, 2);
773 break;
774 case GMM_FORMAT_MFX_JPEG_YUV422V:
775 pRedescribedTexInfo->BaseHeight = GFX_CEIL_DIV(pTexInfo->BaseHeight, 2);
776 break;
777 case GMM_FORMAT_MFX_JPEG_YUV411R_TYPE:
778 pRedescribedTexInfo->BaseHeight = GFX_CEIL_DIV(pTexInfo->BaseHeight, 4);
779 break;
780 case GMM_FORMAT_MFX_JPEG_YUV411:
781 pRedescribedTexInfo->BaseWidth = GFX_CEIL_DIV(pTexInfo->BaseWidth, 4);
782 break;
783 case GMM_FORMAT_MFX_JPEG_YUV422H:
784 pRedescribedTexInfo->BaseWidth = GFX_CEIL_DIV(pTexInfo->BaseWidth, 2);
785 break;
786 default:
787 GMM_ASSERTDPF(0, "Unsupported format/pixel size combo!");
788 Status = GMM_INVALIDPARAM;
789 goto ERROR_CASE;
790 break;
791 }
792 }
793 }
794
795 SetTileMode(pRedescribedTexInfo);
796 switch(pRedescribedTexInfo->BitsPerPixel)
797 {
798 case 8:
799 pRedescribedTexInfo->Format = GMM_FORMAT_R8_UINT;
800 break;
801 case 16:
802 pRedescribedTexInfo->Format = GMM_FORMAT_R16_UINT;
803 break;
804 case 32:
805 pRedescribedTexInfo->Format = GMM_FORMAT_R32_UINT;
806 break;
807 default:
808 GMM_ASSERTDPF(0, "Unsupported format/pixel size combo!");
809 Status = GMM_INVALIDPARAM;
810 goto ERROR_CASE;
811 break;
812 }
813 if(pTexInfo->ArraySize > 1)
814 {
815 pRedescribedTexInfo->OffsetInfo.Plane.ArrayQPitch = 0; // no longer a planar format on redescription
816 pRedescribedTexInfo->Alignment.QPitch = GFX_ALIGN(pRedescribedTexInfo->BaseHeight, pTexInfo->Alignment.VAlign);
817 pRedescribedTexInfo->OffsetInfo.Texture2DOffsetInfo.ArrayQPitchRender =
818 pRedescribedTexInfo->OffsetInfo.Texture2DOffsetInfo.ArrayQPitchLock = pRedescribedTexInfo->Alignment.QPitch * pTexInfo->Pitch;
819 pRedescribedTexInfo->Size = pRedescribedTexInfo->Alignment.QPitch * pTexInfo->Pitch * pTexInfo->ArraySize;
820 }
821 else
822 {
823 pRedescribedTexInfo->Size = (GFX_ALIGN(pRedescribedTexInfo->BaseHeight, pTexInfo->Alignment.VAlign)) * pTexInfo->Pitch;
824 }
825
826 ERROR_CASE:
827 return (Status == GMM_SUCCESS) ? true : false;
828 }
829