xref: /aosp_15_r20/external/mesa3d/src/amd/addrlib/src/core/addrlib3.cpp (revision 6104692788411f58d303aa86923a9ff6ecaded22)
1 /*
2 ************************************************************************************************************************
3 *
4 *  Copyright (C) 2007-2022 Advanced Micro Devices, Inc.  All rights reserved.
5 *  SPDX-License-Identifier: MIT
6 *
7 ***********************************************************************************************************************/
8 
9 
10 /**
11 ************************************************************************************************************************
12 * @file  addrlib3.cpp
13 * @brief Contains the implementation for the AddrLib3 base class.
14 ************************************************************************************************************************
15 */
16 
17 #include "addrinterface.h"
18 #include "addrlib3.h"
19 #include "addrcommon.h"
20 
21 namespace Addr
22 {
23 namespace V3
24 {
25 
26 ////////////////////////////////////////////////////////////////////////////////////////////////////
27 //                               Constructor/Destructor
28 ////////////////////////////////////////////////////////////////////////////////////////////////////
29 
30 /**
31 ************************************************************************************************************************
32 *   Lib::Lib
33 *
34 *   @brief
35 *       Constructor for the Addr::V3::Lib class
36 *
37 ************************************************************************************************************************
38 */
Lib()39 Lib::Lib()
40     :
41     Addr::Lib(),
42     m_pipesLog2(0),
43     m_pipeInterleaveLog2(0),
44     m_numEquations(0)
45 {
46     Init();
47 }
48 
49 /**
50 ************************************************************************************************************************
51 *   Lib::Lib
52 *
53 *   @brief
54 *       Constructor for the AddrLib3 class with hClient as parameter
55 *
56 ************************************************************************************************************************
57 */
Lib(const Client * pClient)58 Lib::Lib(
59     const Client* pClient)
60     :
61     Addr::Lib(pClient),
62     m_pipesLog2(0),
63     m_pipeInterleaveLog2(0),
64     m_numEquations(0)
65 {
66     Init();
67 }
68 
69 /**
70 ************************************************************************************************************************
71 *   Lib::Init
72 *
73 *   @brief
74 *       Initialization of class
75 *
76 ************************************************************************************************************************
77 */
Init()78 void Lib::Init()
79 {
80     memset(m_blockDimensionTable, 0, sizeof(m_blockDimensionTable));
81 
82     // There is no equation table entry for linear, so start at the "next" swizzle mode entry.
83     for (UINT_32  swizzleModeIdx = ADDR3_LINEAR + 1; swizzleModeIdx < ADDR3_MAX_TYPE; swizzleModeIdx++)
84     {
85         for (UINT_32  msaaRateIdx = 0; msaaRateIdx < MaxMsaaRateLog2; msaaRateIdx++)
86         {
87             for (UINT_32  log2BytesIdx = 0; log2BytesIdx < MaxElementBytesLog2; log2BytesIdx++)
88             {
89                 SetEquationTableEntry(static_cast<Addr3SwizzleMode>(swizzleModeIdx),
90                                       msaaRateIdx,
91                                       log2BytesIdx,
92                                       ADDR_INVALID_EQUATION_INDEX);
93             }
94         }
95     }
96 }
97 
98 /**
99 ************************************************************************************************************************
100 *   Lib::~Lib
101 *
102 *   @brief
103 *       Destructor for the AddrLib2 class
104 *
105 ************************************************************************************************************************
106 */
~Lib()107 Lib::~Lib()
108 {
109 }
110 
111 /**
112 ************************************************************************************************************************
113 *   Lib::GetLib
114 *
115 *   @brief
116 *       Get Addr::V3::Lib pointer
117 *
118 *   @return
119 *      An Addr::V2::Lib class pointer
120 ************************************************************************************************************************
121 */
GetLib(ADDR_HANDLE hLib)122 Lib* Lib::GetLib(
123     ADDR_HANDLE hLib)   ///< [in] handle of ADDR_HANDLE
124 {
125     Addr::Lib* pAddrLib = Addr::Lib::GetLib(hLib);
126 
127     return static_cast<Lib*>(pAddrLib);
128 }
129 
130 /**
131 ************************************************************************************************************************
132 *   Lib::GetBlockSize
133 *
134 *   @brief
135 *       Returns the byte size of a block for the swizzle mode.
136 *
137 *   @return
138 *       Byte size of the block, zero if swizzle mode is invalid.
139 ************************************************************************************************************************
140 */
GetBlockSize(Addr3SwizzleMode swizzleMode,BOOL_32 forPitch) const141 UINT_32  Lib::GetBlockSize(
142     Addr3SwizzleMode  swizzleMode,
143     BOOL_32           forPitch
144     ) const
145 {
146     return  (1 << GetBlockSizeLog2(swizzleMode, forPitch));
147 }
148 
149 /**
150 ************************************************************************************************************************
151 *   Lib::GetBlockSizeLog2
152 *
153 *   @brief
154 *       Returns the log2 of the byte size of a block for the swizzle mode.
155 *
156 *   @return
157 *       Byte size of the block, zero if swizzle mode is invalid.
158 ************************************************************************************************************************
159 */
GetBlockSizeLog2(Addr3SwizzleMode swizzleMode,BOOL_32 forPitch) const160 UINT_32  Lib::GetBlockSizeLog2(
161     Addr3SwizzleMode  swizzleMode,
162     BOOL_32           forPitch
163     ) const
164 {
165     UINT_32  blockSize = 0;
166 
167     switch (swizzleMode)
168     {
169         case ADDR3_256B_2D:
170             blockSize = 8;
171             break;
172         case ADDR3_4KB_2D:
173         case ADDR3_4KB_3D:
174             blockSize = 12;
175             break;
176         case ADDR3_64KB_2D:
177         case ADDR3_64KB_3D:
178             blockSize = 16;
179             break;
180         case ADDR3_256KB_2D:
181         case ADDR3_256KB_3D:
182             blockSize = 18;
183             break;
184         case ADDR3_LINEAR:
185             blockSize = (forPitch ? 7 : 8);
186             break;
187         default:
188             ADDR_ASSERT_ALWAYS();
189             break;
190     }
191 
192     return  blockSize;
193 }
194 
195 /**
196 ************************************************************************************************************************
197 *   Lib::ComputeSurfaceInfo
198 *
199 *   @brief
200 *       Interface function stub of ComputeSurfaceInfo.
201 *
202 *   @return
203 *       ADDR_E_RETURNCODE
204 ************************************************************************************************************************
205 */
ComputeSurfaceInfo(const ADDR3_COMPUTE_SURFACE_INFO_INPUT * pIn,ADDR3_COMPUTE_SURFACE_INFO_OUTPUT * pOut) const206 ADDR_E_RETURNCODE Lib::ComputeSurfaceInfo(
207      const ADDR3_COMPUTE_SURFACE_INFO_INPUT* pIn,    ///< [in] input structure
208      ADDR3_COMPUTE_SURFACE_INFO_OUTPUT*      pOut    ///< [out] output structure
209      ) const
210 {
211     ADDR_E_RETURNCODE returnCode = ADDR_OK;
212 
213     if (GetFillSizeFieldsFlags() == TRUE)
214     {
215         if ((pIn->size != sizeof(ADDR3_COMPUTE_SURFACE_INFO_INPUT)) ||
216             (pOut->size != sizeof(ADDR3_COMPUTE_SURFACE_INFO_OUTPUT)))
217         {
218             returnCode = ADDR_PARAMSIZEMISMATCH;
219         }
220     }
221 
222     // Adjust incoming parameters.
223     ADDR3_COMPUTE_SURFACE_INFO_INPUT localIn = *pIn;
224     localIn.width        = Max(pIn->width, 1u);
225     localIn.height       = Max(pIn->height, 1u);
226     localIn.numMipLevels = Max(pIn->numMipLevels, 1u);
227     localIn.numSlices    = Max(pIn->numSlices, 1u);
228     localIn.numSamples   = Max(pIn->numSamples, 1u);
229 
230     UINT_32  expandX  = 1;
231     UINT_32  expandY  = 1;
232     ElemMode elemMode = ADDR_UNCOMPRESSED;
233 
234     if (returnCode == ADDR_OK)
235     {
236         // Set format to INVALID will skip this conversion
237         if (localIn.format != ADDR_FMT_INVALID)
238         {
239             // Get compression/expansion factors and element mode which indicates compression/expansion
240             localIn.bpp = GetElemLib()->GetBitsPerPixel(localIn.format,
241                                                         &elemMode,
242                                                         &expandX,
243                                                         &expandY);
244 
245             // Special flag for 96 bit surface. 96 (or 48 if we support) bit surface's width is
246             // pre-multiplied by 3 and bpp is divided by 3. So pitch alignment for linear-
247             // aligned does not meet 64-pixel in real. We keep special handling in hwl since hw
248             // restrictions are different.
249             // Also Mip 1+ needs an element pitch of 32 bits so we do not need this workaround
250             // but we use this flag to skip RestoreSurfaceInfo below
251             if ((elemMode == ADDR_EXPANDED) && (expandX > 1))
252             {
253                 ADDR_ASSERT(IsLinear(localIn.swizzleMode));
254             }
255 
256             UINT_32 basePitch = 0;
257             GetElemLib()->AdjustSurfaceInfo(elemMode,
258                                             expandX,
259                                             expandY,
260                                             &localIn.bpp,
261                                             &basePitch,
262                                             &localIn.width,
263                                             &localIn.height);
264 
265             // Overwrite these parameters if we have a valid format
266         }
267 
268         if (localIn.bpp != 0)
269         {
270             localIn.width  = Max(localIn.width, 1u);
271             localIn.height = Max(localIn.height, 1u);
272         }
273         else // Rule out some invalid parameters
274         {
275             returnCode = ADDR_INVALIDPARAMS;
276         }
277     }
278 
279     if (returnCode == ADDR_OK)
280     {
281         returnCode = HwlComputeSurfaceInfo(&localIn, pOut);
282 
283         if (returnCode == ADDR_OK)
284         {
285             pOut->bpp         = localIn.bpp;
286             pOut->pixelPitch  = pOut->pitch;
287             pOut->pixelHeight = pOut->height;
288 
289             if (localIn.format != ADDR_FMT_INVALID)
290             {
291                 UINT_32 pixelBits = pOut->pixelBits;
292 
293                 GetElemLib()->RestoreSurfaceInfo(elemMode,
294                                                  expandX,
295                                                  expandY,
296                                                  &pOut->pixelBits,
297                                                  &pOut->pixelPitch,
298                                                  &pOut->pixelHeight);
299 
300                 GetElemLib()->RestoreSurfaceInfo(elemMode,
301                                                  expandX,
302                                                  expandY,
303                                                  &pixelBits,
304                                                  &pOut->pixelMipChainPitch,
305                                                  &pOut->pixelMipChainHeight);
306 
307                 if ((localIn.numMipLevels > 1) && (pOut->pMipInfo != NULL))
308                 {
309                     for (UINT_32 i = 0; i < localIn.numMipLevels; i++)
310                     {
311                         pOut->pMipInfo[i].pixelPitch  = pOut->pMipInfo[i].pitch;
312                         pOut->pMipInfo[i].pixelHeight = pOut->pMipInfo[i].height;
313 
314                         GetElemLib()->RestoreSurfaceInfo(elemMode,
315                                                          expandX,
316                                                          expandY,
317                                                          &pixelBits,
318                                                          &pOut->pMipInfo[i].pixelPitch,
319                                                          &pOut->pMipInfo[i].pixelHeight);
320                     }
321                 }
322 
323                 if (localIn.flags.qbStereo && (pOut->pStereoInfo != NULL))
324                 {
325                     ComputeQbStereoInfo(pOut);
326                 }
327             }
328 
329             SetEquationIndex(&localIn, pOut);
330         }
331     }
332 
333     return returnCode;
334 }
335 
336 /**
337 ************************************************************************************************************************
338 *   Lib::GetPossibleSwizzleModes
339 *
340 *   @brief
341 *       Populates pOut with a list of the possible swizzle modes for the described surface.
342 *
343 *   @return
344 *       ADDR_E_RETURNCODE
345 ************************************************************************************************************************
346 */
GetPossibleSwizzleModes(const ADDR3_GET_POSSIBLE_SWIZZLE_MODE_INPUT * pIn,ADDR3_GET_POSSIBLE_SWIZZLE_MODE_OUTPUT * pOut) const347 ADDR_E_RETURNCODE Lib::GetPossibleSwizzleModes(
348     const ADDR3_GET_POSSIBLE_SWIZZLE_MODE_INPUT*  pIn,
349     ADDR3_GET_POSSIBLE_SWIZZLE_MODE_OUTPUT*       pOut
350     ) const
351 {
352     ADDR_E_RETURNCODE returnCode = ADDR_OK;
353 
354     if (GetFillSizeFieldsFlags() == TRUE)
355     {
356         if ((pIn->size  != sizeof(ADDR3_GET_POSSIBLE_SWIZZLE_MODE_INPUT)) ||
357             (pOut->size != sizeof(ADDR3_GET_POSSIBLE_SWIZZLE_MODE_OUTPUT)))
358         {
359             returnCode = ADDR_PARAMSIZEMISMATCH;
360         }
361     }
362 
363     if ((returnCode == ADDR_OK) && (HwlValidateNonSwModeParams(pIn) == FALSE))
364     {
365         returnCode = ADDR_INVALIDPARAMS;
366     }
367 
368     if (returnCode == ADDR_OK)
369     {
370         returnCode = HwlGetPossibleSwizzleModes(pIn, pOut);
371     }
372 
373     return returnCode;
374 }
375 
376 /**
377 ************************************************************************************************************************
378 *   Lib::ComputeBlockDimensionForSurf
379 *
380 *   @brief
381 *       Internal function to get block width/height/depth in elements from surface input params.
382 *
383 *   @return
384 *       VOID
385 ************************************************************************************************************************
386 */
ComputeBlockDimensionForSurf(const ADDR3_COMPUTE_SURFACE_INFO_PARAMS_INPUT * pIn,ADDR_EXTENT3D * pExtent) const387 VOID Lib::ComputeBlockDimensionForSurf(
388     const ADDR3_COMPUTE_SURFACE_INFO_PARAMS_INPUT* pIn,
389     ADDR_EXTENT3D*                                 pExtent
390     ) const
391 {
392     const ADDR3_COMPUTE_SURFACE_INFO_INPUT* pSurfInfo   = pIn->pSurfInfo;
393     const UINT_32                           log2BlkSize = GetBlockSizeLog2(pSurfInfo->swizzleMode);
394 
395     HwlCalcBlockSize(pIn, pExtent);
396 }
397 
398 /**
399 ************************************************************************************************************************
400 *   Lib::GetMipTailDim
401 *
402 *   @brief
403 *       Internal function to get out max dimension of first level in mip tail
404 *
405 *   @return
406 *       Max Width/Height/Depth value of the first mip fitted in mip tail
407 ************************************************************************************************************************
408 */
GetMipTailDim(const ADDR3_COMPUTE_SURFACE_INFO_PARAMS_INPUT * pIn,const ADDR_EXTENT3D & blockDims) const409 ADDR_EXTENT3D Lib::GetMipTailDim(
410     const ADDR3_COMPUTE_SURFACE_INFO_PARAMS_INPUT* pIn,
411     const ADDR_EXTENT3D&                           blockDims
412     ) const
413 {
414     return HwlGetMipInTailMaxSize(pIn, blockDims);
415 }
416 
417 /**
418 ************************************************************************************************************************
419 *   Lib::ComputeSurfaceAddrFromCoord
420 *
421 *   @brief
422 *       Interface function stub of ComputeSurfaceAddrFromCoord.
423 *
424 *   @return
425 *       ADDR_E_RETURNCODE
426 ************************************************************************************************************************
427 */
ComputeSurfaceAddrFromCoord(const ADDR3_COMPUTE_SURFACE_ADDRFROMCOORD_INPUT * pIn,ADDR3_COMPUTE_SURFACE_ADDRFROMCOORD_OUTPUT * pOut) const428 ADDR_E_RETURNCODE Lib::ComputeSurfaceAddrFromCoord(
429     const ADDR3_COMPUTE_SURFACE_ADDRFROMCOORD_INPUT* pIn,    ///< [in] input structure
430     ADDR3_COMPUTE_SURFACE_ADDRFROMCOORD_OUTPUT*      pOut    ///< [out] output structure
431     ) const
432 {
433     ADDR_E_RETURNCODE returnCode = ADDR_OK;
434 
435     if (GetFillSizeFieldsFlags() == TRUE)
436     {
437         if ((pIn->size != sizeof(ADDR3_COMPUTE_SURFACE_ADDRFROMCOORD_INPUT)) ||
438             (pOut->size != sizeof(ADDR3_COMPUTE_SURFACE_ADDRFROMCOORD_OUTPUT)))
439         {
440             returnCode = ADDR_PARAMSIZEMISMATCH;
441         }
442     }
443 
444     ADDR3_COMPUTE_SURFACE_ADDRFROMCOORD_INPUT localIn = *pIn;
445     localIn.unAlignedDims.width  = Max(pIn->unAlignedDims.width,  1u);
446     localIn.unAlignedDims.height = Max(pIn->unAlignedDims.height, 1u);
447     localIn.unAlignedDims.depth  = Max(pIn->unAlignedDims.depth,  1u);
448     localIn.numMipLevels         = Max(pIn->numMipLevels,         1u);
449     localIn.numSamples           = Max(pIn->numSamples,           1u);
450 
451     if ((localIn.bpp < 8)                               ||
452         (localIn.bpp > 128)                             ||
453         ((localIn.bpp % 8) != 0)                        ||
454         (localIn.sample >= localIn.numSamples)          ||
455         (localIn.slice >= localIn.unAlignedDims.depth)  ||
456         (localIn.mipId >= localIn.numMipLevels)         ||
457         (IsTex3d(localIn.resourceType)                  &&
458         (Valid3DMipSliceIdConstraint(localIn.unAlignedDims.depth, localIn.mipId, localIn.slice) == FALSE)))
459     {
460         returnCode = ADDR_INVALIDPARAMS;
461     }
462 
463     if (returnCode == ADDR_OK)
464     {
465         if (IsLinear(localIn.swizzleMode))
466         {
467             returnCode = ComputeSurfaceAddrFromCoordLinear(&localIn, pOut);
468         }
469         else
470         {
471             returnCode = ComputeSurfaceAddrFromCoordTiled(&localIn, pOut);
472         }
473 
474         if (returnCode == ADDR_OK)
475         {
476             pOut->prtBlockIndex = static_cast<UINT_32>(pOut->addr / (64 * 1024));
477         }
478     }
479 
480     return returnCode;
481 }
482 
483 /**
484 ************************************************************************************************************************
485 *   Lib::ComputeSurfaceAddrFromCoord
486 *
487 *   @brief
488 *       Interface function stub of Addr3ComputePipeBankXor.
489 *
490 *   @return
491 *       ADDR_E_RETURNCODE
492 ************************************************************************************************************************
493 */
ComputePipeBankXor(const ADDR3_COMPUTE_PIPEBANKXOR_INPUT * pIn,ADDR3_COMPUTE_PIPEBANKXOR_OUTPUT * pOut)494 ADDR_E_RETURNCODE Lib::ComputePipeBankXor(
495     const ADDR3_COMPUTE_PIPEBANKXOR_INPUT* pIn,
496     ADDR3_COMPUTE_PIPEBANKXOR_OUTPUT*      pOut)
497 {
498     ADDR_E_RETURNCODE returnCode;
499 
500     if ((GetFillSizeFieldsFlags() == TRUE) &&
501         ((pIn->size  != sizeof(ADDR3_COMPUTE_PIPEBANKXOR_INPUT)) ||
502          (pOut->size != sizeof(ADDR3_COMPUTE_PIPEBANKXOR_OUTPUT))))
503     {
504         returnCode = ADDR_INVALIDPARAMS;
505     }
506     else
507     {
508         returnCode = HwlComputePipeBankXor(pIn, pOut);
509     }
510 
511     return returnCode;
512 }
513 
514 /**
515 ************************************************************************************************************************
516 *   Lib::ComputeSurfaceAddrFromCoordLinear
517 *
518 *   @brief
519 *       Internal function to calculate address from coord for linear swizzle surface
520 *
521 *   @return
522 *       ADDR_E_RETURNCODE
523 ************************************************************************************************************************
524 */
ComputeSurfaceAddrFromCoordLinear(const ADDR3_COMPUTE_SURFACE_ADDRFROMCOORD_INPUT * pIn,ADDR3_COMPUTE_SURFACE_ADDRFROMCOORD_OUTPUT * pOut) const525 ADDR_E_RETURNCODE Lib::ComputeSurfaceAddrFromCoordLinear(
526      const ADDR3_COMPUTE_SURFACE_ADDRFROMCOORD_INPUT* pIn,    ///< [in] input structure
527      ADDR3_COMPUTE_SURFACE_ADDRFROMCOORD_OUTPUT*      pOut    ///< [out] output structure
528      ) const
529 {
530     ADDR_E_RETURNCODE returnCode = ADDR_OK;
531     BOOL_32 valid = (pIn->numSamples <= 1);
532 
533     if (valid)
534     {
535         if (IsTex1d(pIn->resourceType))
536         {
537             valid = (pIn->y == 0);
538         }
539     }
540 
541     if (valid)
542     {
543         ADDR3_COMPUTE_SURFACE_INFO_INPUT  surfInfoIn = {0};
544 
545         surfInfoIn.size         = sizeof(surfInfoIn);
546         surfInfoIn.flags        = pIn->flags;
547         surfInfoIn.swizzleMode  = ADDR3_LINEAR;
548         surfInfoIn.resourceType = pIn->resourceType;
549         surfInfoIn.format       = ADDR_FMT_INVALID;
550         surfInfoIn.bpp          = pIn->bpp;
551         surfInfoIn.width        = Max(pIn->unAlignedDims.width,  1u);
552         surfInfoIn.height       = Max(pIn->unAlignedDims.height, 1u);
553         surfInfoIn.numSlices    = Max(pIn->unAlignedDims.depth,  1u);
554         surfInfoIn.numMipLevels = Max(pIn->numMipLevels,         1u);
555         surfInfoIn.numSamples   = Max(pIn->numSamples,           1u);
556 
557         if (surfInfoIn.numMipLevels <= 1)
558         {
559             surfInfoIn.pitchInElement = pIn->pitchInElement;
560         }
561 
562         returnCode = HwlComputeSurfaceAddrFromCoordLinear(pIn, &surfInfoIn, pOut);
563     }
564 
565     if (valid == FALSE)
566     {
567         returnCode = ADDR_INVALIDPARAMS;
568     }
569 
570     return returnCode;
571 }
572 
573 /**
574 ************************************************************************************************************************
575 *   Lib::ComputeSurfaceAddrFromCoordTiled
576 *
577 *   @brief
578 *       Internal function to calculate address from coord for tiled swizzle surface
579 *
580 *   @return
581 *       ADDR_E_RETURNCODE
582 ************************************************************************************************************************
583 */
ComputeSurfaceAddrFromCoordTiled(const ADDR3_COMPUTE_SURFACE_ADDRFROMCOORD_INPUT * pIn,ADDR3_COMPUTE_SURFACE_ADDRFROMCOORD_OUTPUT * pOut) const584 ADDR_E_RETURNCODE Lib::ComputeSurfaceAddrFromCoordTiled(
585      const ADDR3_COMPUTE_SURFACE_ADDRFROMCOORD_INPUT* pIn,    ///< [in] input structure
586      ADDR3_COMPUTE_SURFACE_ADDRFROMCOORD_OUTPUT*      pOut    ///< [out] output structure
587      ) const
588 {
589     return HwlComputeSurfaceAddrFromCoordTiled(pIn, pOut);
590 }
591 
592 /**
593 ************************************************************************************************************************
594 *   Lib::ComputeNonBlockCompressedView
595 *
596 *   @brief
597 *       Interface function stub of Addr3ComputeNonBlockCompressedView.
598 *
599 *   @return
600 *       ADDR_E_RETURNCODE
601 ************************************************************************************************************************
602 */
ComputeNonBlockCompressedView(const ADDR3_COMPUTE_NONBLOCKCOMPRESSEDVIEW_INPUT * pIn,ADDR3_COMPUTE_NONBLOCKCOMPRESSEDVIEW_OUTPUT * pOut)603 ADDR_E_RETURNCODE Lib::ComputeNonBlockCompressedView(
604     const ADDR3_COMPUTE_NONBLOCKCOMPRESSEDVIEW_INPUT* pIn,
605     ADDR3_COMPUTE_NONBLOCKCOMPRESSEDVIEW_OUTPUT*      pOut)
606 {
607     ADDR_E_RETURNCODE returnCode;
608 
609     if ((GetFillSizeFieldsFlags() == TRUE) &&
610         ((pIn->size  != sizeof(ADDR3_COMPUTE_NONBLOCKCOMPRESSEDVIEW_INPUT)) ||
611          (pOut->size != sizeof(ADDR3_COMPUTE_NONBLOCKCOMPRESSEDVIEW_OUTPUT))))
612     {
613         returnCode = ADDR_INVALIDPARAMS;
614     }
615     else if (Is3dSwizzle(pIn->swizzleMode))
616     {
617         // 3D volume images using ADDR3_XX_3D is currently not supported.
618         returnCode = ADDR_NOTSUPPORTED;
619     }
620     else
621     {
622         returnCode = HwlComputeNonBlockCompressedView(pIn, pOut);
623     }
624 
625     return returnCode;
626 }
627 
628 /**
629 ************************************************************************************************************************
630 *   Lib::ComputeSubResourceOffsetForSwizzlePattern
631 *
632 *   @brief
633 *       Interface function stub of Addr3ComputeSubResourceOffsetForSwizzlePattern.
634 *
635 *   @return
636 *       ADDR_E_RETURNCODE
637 ************************************************************************************************************************
638 */
ComputeSubResourceOffsetForSwizzlePattern(const ADDR3_COMPUTE_SUBRESOURCE_OFFSET_FORSWIZZLEPATTERN_INPUT * pIn,ADDR3_COMPUTE_SUBRESOURCE_OFFSET_FORSWIZZLEPATTERN_OUTPUT * pOut)639 ADDR_E_RETURNCODE Lib::ComputeSubResourceOffsetForSwizzlePattern(
640     const ADDR3_COMPUTE_SUBRESOURCE_OFFSET_FORSWIZZLEPATTERN_INPUT* pIn,
641     ADDR3_COMPUTE_SUBRESOURCE_OFFSET_FORSWIZZLEPATTERN_OUTPUT*      pOut)
642 {
643     ADDR_E_RETURNCODE returnCode = ADDR_OK;
644 
645     if ((GetFillSizeFieldsFlags() == TRUE) &&
646         ((pIn->size  != sizeof(ADDR3_COMPUTE_SUBRESOURCE_OFFSET_FORSWIZZLEPATTERN_INPUT)) ||
647          (pOut->size != sizeof(ADDR3_COMPUTE_SUBRESOURCE_OFFSET_FORSWIZZLEPATTERN_OUTPUT))))
648     {
649         returnCode = ADDR_INVALIDPARAMS;
650     }
651     else
652     {
653         HwlComputeSubResourceOffsetForSwizzlePattern(pIn, pOut);
654     }
655 
656     return returnCode;
657 }
658 
659 /**
660 ************************************************************************************************************************
661 *   Lib::ComputeSlicePipeBankXor
662 *
663 *   @brief
664 *       Interface function stub of Addr3ComputeSlicePipeBankXor.
665 *
666 *   @return
667 *       ADDR_E_RETURNCODE
668 ************************************************************************************************************************
669 */
ComputeSlicePipeBankXor(const ADDR3_COMPUTE_SLICE_PIPEBANKXOR_INPUT * pIn,ADDR3_COMPUTE_SLICE_PIPEBANKXOR_OUTPUT * pOut)670 ADDR_E_RETURNCODE Lib::ComputeSlicePipeBankXor(
671     const ADDR3_COMPUTE_SLICE_PIPEBANKXOR_INPUT* pIn,
672     ADDR3_COMPUTE_SLICE_PIPEBANKXOR_OUTPUT*      pOut)
673 {
674     ADDR_E_RETURNCODE returnCode;
675 
676     if ((GetFillSizeFieldsFlags() == TRUE) &&
677         ((pIn->size  != sizeof(ADDR3_COMPUTE_SLICE_PIPEBANKXOR_INPUT)) ||
678          (pOut->size != sizeof(ADDR3_COMPUTE_SLICE_PIPEBANKXOR_OUTPUT))))
679     {
680         returnCode = ADDR_INVALIDPARAMS;
681     }
682     if ((pIn->bpe != 0) &&
683         (pIn->bpe != 8) &&
684         (pIn->bpe != 16) &&
685         (pIn->bpe != 32) &&
686         (pIn->bpe != 64) &&
687         (pIn->bpe != 128))
688     {
689         returnCode = ADDR_INVALIDPARAMS;
690     }
691     else
692     {
693         returnCode = HwlComputeSlicePipeBankXor(pIn, pOut);
694     }
695 
696     return returnCode;
697 }
698 
699 /**
700 ************************************************************************************************************************
701 *   Lib::UseCustomHeight
702 *
703 *   @brief
704 *       Determines if the calculations for this surface should use minimal HW values or user-specified values.
705 *
706 *   @return
707 *       Returns TRUE if the user-specified alignment should be used
708 ************************************************************************************************************************
709 */
UseCustomHeight(const ADDR3_COMPUTE_SURFACE_INFO_INPUT * pIn) const710 BOOL_32 Lib::UseCustomHeight(
711     const ADDR3_COMPUTE_SURFACE_INFO_INPUT*  pIn
712     ) const
713 {
714     return ((pIn->numMipLevels <= 1)   &&
715             IsLinear(pIn->swizzleMode) &&
716             (pIn->sliceAlign > 0));
717 }
718 
719 /**
720 ************************************************************************************************************************
721 *   Lib::UseCustomPitch
722 *
723 *   @brief
724 *       Determines if the calculations for this surface should use minimal HW values or user-specified values.
725 *
726 *   @return
727 *       Returns TRUE if the user-specified pitch should be used
728 ************************************************************************************************************************
729 */
UseCustomPitch(const ADDR3_COMPUTE_SURFACE_INFO_INPUT * pIn) const730 BOOL_32 Lib::UseCustomPitch(
731     const ADDR3_COMPUTE_SURFACE_INFO_INPUT*  pIn
732     ) const
733 {
734     return ((pIn->numMipLevels <= 1)   &&
735             IsLinear(pIn->swizzleMode) &&
736             (pIn->pitchInElement > 0));
737 }
738 
739 /**
740 ************************************************************************************************************************
741 *   Lib::CanTrimLinearPadding
742 *
743 *   @brief
744 *       Determines if the calculations for this surface can omit extra trailing padding for linear surfaces.
745 *
746 *   @return
747 *       Returns TRUE if the trailing padding can be omitted.
748 ************************************************************************************************************************
749 */
CanTrimLinearPadding(const ADDR3_COMPUTE_SURFACE_INFO_INPUT * pIn) const750 BOOL_32 Lib::CanTrimLinearPadding(
751     const ADDR3_COMPUTE_SURFACE_INFO_INPUT*  pIn
752     ) const
753 {
754     return ((IsTex3d(pIn->resourceType) == FALSE) &&
755             (pIn->numSlices <= 1)                 &&
756             IsLinear(pIn->swizzleMode));
757 }
758 
759 /**
760 ************************************************************************************************************************
761 *   Lib::ApplyCustomizedPitchHeight
762 *
763 *   @brief
764 *       Helper function to override hw required row pitch/slice pitch by customrized one
765 *
766 *   @return
767 *       ADDR_E_RETURNCODE
768 ************************************************************************************************************************
769 */
ApplyCustomizedPitchHeight(const ADDR3_COMPUTE_SURFACE_INFO_INPUT * pIn,ADDR3_COMPUTE_SURFACE_INFO_OUTPUT * pOut) const770 ADDR_E_RETURNCODE Lib::ApplyCustomizedPitchHeight(
771     const ADDR3_COMPUTE_SURFACE_INFO_INPUT* pIn,    ///< [in] input structure
772     ADDR3_COMPUTE_SURFACE_INFO_OUTPUT*      pOut
773     ) const
774 {
775     ADDR_E_RETURNCODE returnCode = ADDR_OK;
776 
777     const UINT_32  elementBytes = pIn->bpp >> 3;
778 
779     // Normal pitch of image data
780     const UINT_32  pitchAlignmentBytes    = 1 << GetBlockSizeLog2(pIn->swizzleMode, TRUE);
781     const UINT_32  pitchAlignmentElements = pitchAlignmentBytes / elementBytes;
782     pOut->pitch = PowTwoAlign(pIn->width, pitchAlignmentElements);
783 
784     // Pitch of image data used for slice sizing (same except for linear images)
785     const UINT_32  pitchSliceAlignmentBytes    = 1 << GetBlockSizeLog2(pIn->swizzleMode, CanTrimLinearPadding(pIn));
786     const UINT_32  pitchSliceAlignmentElements = pitchSliceAlignmentBytes / elementBytes;
787     pOut->pitchForSlice = PowTwoAlign(pIn->width, pitchSliceAlignmentElements);
788 
789     UINT_32 heightAlign = pOut->blockExtent.height;
790 
791     if (pIn->flags.qbStereo)
792     {
793         UINT_32 rightXor = 0;
794 
795         returnCode = HwlComputeStereoInfo(pIn, &heightAlign, &rightXor);
796 
797         if (returnCode == ADDR_OK)
798         {
799             pOut->pStereoInfo->rightSwizzle = rightXor;
800         }
801     }
802 
803     pOut->height = PowTwoAlign(pIn->height, heightAlign);
804 
805     // Custom pitches / alignments are only possible with single mip level / linear images; otherwise,
806     // ignore those parameters.
807     if ((returnCode == ADDR_OK) && UseCustomPitch(pIn))
808     {
809         // Their requested pitch has to meet the pitch alignment constraints applied by the HW.
810         if ((pIn->pitchInElement % pitchAlignmentElements) != 0)
811         {
812             returnCode = ADDR_INVALIDPARAMS;
813         }
814         // And their pitch can't be less than the minimum
815         else if (pIn->pitchInElement < pOut->pitch)
816         {
817             returnCode = ADDR_INVALIDPARAMS;
818         }
819         else
820         {
821             pOut->pitch = pIn->pitchInElement;
822             pOut->pitchForSlice = PowTwoAlign(pIn->pitchInElement, pitchSliceAlignmentElements);
823         }
824     }
825 
826     if ((returnCode == ADDR_OK) && UseCustomHeight(pIn))
827     {
828         // Note: if a custom slice align is present, it must be an even multiple
829         // of pitchForSlice, not just pitch.
830         UINT_32 customizedHeight = pIn->sliceAlign / elementBytes / pOut->pitchForSlice;
831 
832         if ((pIn->numSlices > 1) && (customizedHeight * elementBytes * pOut->pitchForSlice != pIn->sliceAlign))
833         {
834             returnCode = ADDR_INVALIDPARAMS;
835         }
836         else if ((pIn->numSlices > 1) && (pOut->height != customizedHeight))
837         {
838             returnCode = ADDR_INVALIDPARAMS;
839         }
840         else if ((pIn->height * elementBytes * pOut->pitch) > pIn->sliceAlign)
841         {
842             // If we only have one slice/depth, then we don't need an even multiple, but the slice size must still
843             // fit all the pixel data. The one provided is too small!
844             returnCode = ADDR_INVALIDPARAMS;
845         }
846         else
847         {
848             // For the single-slice case, the customized height could have been rounded down below the height since
849             // we allow non-multiples of pitch here, so take the max.
850             pOut->height = Max(pOut->height, customizedHeight);
851         }
852     }
853 
854     return returnCode;
855 }
856 
857 /**
858 ************************************************************************************************************************
859 *   Lib::ComputeQbStereoInfo
860 *
861 *   @brief
862 *       Get quad buffer stereo information
863 *   @return
864 *       N/A
865 ************************************************************************************************************************
866 */
ComputeQbStereoInfo(ADDR3_COMPUTE_SURFACE_INFO_OUTPUT * pOut) const867 VOID Lib::ComputeQbStereoInfo(
868     ADDR3_COMPUTE_SURFACE_INFO_OUTPUT* pOut   ///< [in,out] updated pOut+pStereoInfo
869     ) const
870 {
871     ADDR_ASSERT(pOut->bpp >= 8);
872     ADDR_ASSERT((pOut->surfSize % pOut->baseAlign) == 0);
873 
874     // Save original height
875     pOut->pStereoInfo->eyeHeight = pOut->height;
876 
877     // Right offset
878     pOut->pStereoInfo->rightOffset = static_cast<UINT_32>(pOut->surfSize);
879 
880     // Double height
881     pOut->height <<= 1;
882 
883     ADDR_ASSERT(pOut->height <= MaxSurfaceHeight);
884 
885     pOut->pixelHeight <<= 1;
886 
887     // Double size
888     pOut->surfSize  <<= 1;
889     pOut->sliceSize <<= 1;
890 }
891 
892 } // V3
893 } // Addr
894