• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2 ************************************************************************************************************************
3 *
4 *  Copyright (C) 2007-2024 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 < MaxNumMsaaRates; 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 = ComputeSurfaceInfoSanityCheck(&localIn);
282     }
283 
284     if (returnCode == ADDR_OK)
285     {
286         returnCode = HwlComputeSurfaceInfo(&localIn, pOut);
287 
288         if (returnCode == ADDR_OK)
289         {
290             pOut->bpp         = localIn.bpp;
291             pOut->pixelPitch  = pOut->pitch;
292             pOut->pixelHeight = pOut->height;
293 
294             if (localIn.format != ADDR_FMT_INVALID)
295             {
296                 UINT_32 pixelBits = pOut->pixelBits;
297 
298                 GetElemLib()->RestoreSurfaceInfo(elemMode,
299                                                  expandX,
300                                                  expandY,
301                                                  &pOut->pixelBits,
302                                                  &pOut->pixelPitch,
303                                                  &pOut->pixelHeight);
304 
305                 GetElemLib()->RestoreSurfaceInfo(elemMode,
306                                                  expandX,
307                                                  expandY,
308                                                  &pixelBits,
309                                                  &pOut->pixelMipChainPitch,
310                                                  &pOut->pixelMipChainHeight);
311 
312                 if ((localIn.numMipLevels > 1) && (pOut->pMipInfo != NULL))
313                 {
314                     for (UINT_32 i = 0; i < localIn.numMipLevels; i++)
315                     {
316                         pOut->pMipInfo[i].pixelPitch  = pOut->pMipInfo[i].pitch;
317                         pOut->pMipInfo[i].pixelHeight = pOut->pMipInfo[i].height;
318 
319                         GetElemLib()->RestoreSurfaceInfo(elemMode,
320                                                          expandX,
321                                                          expandY,
322                                                          &pixelBits,
323                                                          &pOut->pMipInfo[i].pixelPitch,
324                                                          &pOut->pMipInfo[i].pixelHeight);
325                     }
326                 }
327 
328                 if (localIn.flags.qbStereo && (pOut->pStereoInfo != NULL))
329                 {
330                     ComputeQbStereoInfo(pOut);
331                 }
332             }
333 
334             SetEquationIndex(&localIn, pOut);
335         }
336     }
337 
338     return returnCode;
339 }
340 
341 /**
342 ************************************************************************************************************************
343 *   Lib::GetPossibleSwizzleModes
344 *
345 *   @brief
346 *       Populates pOut with a list of the possible swizzle modes for the described surface.
347 *
348 *   @return
349 *       ADDR_E_RETURNCODE
350 ************************************************************************************************************************
351 */
GetPossibleSwizzleModes(const ADDR3_GET_POSSIBLE_SWIZZLE_MODE_INPUT * pIn,ADDR3_GET_POSSIBLE_SWIZZLE_MODE_OUTPUT * pOut) const352 ADDR_E_RETURNCODE Lib::GetPossibleSwizzleModes(
353     const ADDR3_GET_POSSIBLE_SWIZZLE_MODE_INPUT*  pIn,
354     ADDR3_GET_POSSIBLE_SWIZZLE_MODE_OUTPUT*       pOut
355     ) const
356 {
357     ADDR_E_RETURNCODE returnCode = ADDR_OK;
358 
359     if (GetFillSizeFieldsFlags() == TRUE)
360     {
361         if ((pIn->size  != sizeof(ADDR3_GET_POSSIBLE_SWIZZLE_MODE_INPUT)) ||
362             (pOut->size != sizeof(ADDR3_GET_POSSIBLE_SWIZZLE_MODE_OUTPUT)))
363         {
364             returnCode = ADDR_PARAMSIZEMISMATCH;
365         }
366     }
367 
368     if ((returnCode == ADDR_OK) && (HwlValidateNonSwModeParams(pIn) == FALSE))
369     {
370         returnCode = ADDR_INVALIDPARAMS;
371     }
372 
373     if (returnCode == ADDR_OK)
374     {
375         returnCode = HwlGetPossibleSwizzleModes(pIn, pOut);
376     }
377 
378     return returnCode;
379 }
380 
381 /**
382 ************************************************************************************************************************
383 *   Lib::ComputeBlockDimensionForSurf
384 *
385 *   @brief
386 *       Internal function to get block width/height/depth in elements from surface input params.
387 *
388 *   @return
389 *       VOID
390 ************************************************************************************************************************
391 */
ComputeBlockDimensionForSurf(const ADDR3_COMPUTE_SURFACE_INFO_PARAMS_INPUT * pIn,ADDR_EXTENT3D * pExtent) const392 VOID Lib::ComputeBlockDimensionForSurf(
393     const ADDR3_COMPUTE_SURFACE_INFO_PARAMS_INPUT* pIn,
394     ADDR_EXTENT3D*                                 pExtent
395     ) const
396 {
397     const ADDR3_COMPUTE_SURFACE_INFO_INPUT* pSurfInfo   = pIn->pSurfInfo;
398     const UINT_32                           log2BlkSize = GetBlockSizeLog2(pSurfInfo->swizzleMode);
399 
400     HwlCalcBlockSize(pIn, pExtent);
401 }
402 
403 /**
404 ************************************************************************************************************************
405 *   Lib::GetMipTailDim
406 *
407 *   @brief
408 *       Internal function to get out max dimension of first level in mip tail
409 *
410 *   @return
411 *       Max Width/Height/Depth value of the first mip fitted in mip tail
412 ************************************************************************************************************************
413 */
GetMipTailDim(const ADDR3_COMPUTE_SURFACE_INFO_PARAMS_INPUT * pIn,const ADDR_EXTENT3D & blockDims) const414 ADDR_EXTENT3D Lib::GetMipTailDim(
415     const ADDR3_COMPUTE_SURFACE_INFO_PARAMS_INPUT* pIn,
416     const ADDR_EXTENT3D&                           blockDims
417     ) const
418 {
419     return HwlGetMipInTailMaxSize(pIn, blockDims);
420 }
421 
422 /**
423 ************************************************************************************************************************
424 *   Lib::ComputeSurfaceAddrFromCoord
425 *
426 *   @brief
427 *       Interface function stub of ComputeSurfaceAddrFromCoord.
428 *
429 *   @return
430 *       ADDR_E_RETURNCODE
431 ************************************************************************************************************************
432 */
ComputeSurfaceAddrFromCoord(const ADDR3_COMPUTE_SURFACE_ADDRFROMCOORD_INPUT * pIn,ADDR3_COMPUTE_SURFACE_ADDRFROMCOORD_OUTPUT * pOut) const433 ADDR_E_RETURNCODE Lib::ComputeSurfaceAddrFromCoord(
434     const ADDR3_COMPUTE_SURFACE_ADDRFROMCOORD_INPUT* pIn,    ///< [in] input structure
435     ADDR3_COMPUTE_SURFACE_ADDRFROMCOORD_OUTPUT*      pOut    ///< [out] output structure
436     ) const
437 {
438     ADDR_E_RETURNCODE returnCode = ADDR_OK;
439 
440     if (GetFillSizeFieldsFlags() == TRUE)
441     {
442         if ((pIn->size != sizeof(ADDR3_COMPUTE_SURFACE_ADDRFROMCOORD_INPUT)) ||
443             (pOut->size != sizeof(ADDR3_COMPUTE_SURFACE_ADDRFROMCOORD_OUTPUT)))
444         {
445             returnCode = ADDR_PARAMSIZEMISMATCH;
446         }
447     }
448 
449     ADDR3_COMPUTE_SURFACE_ADDRFROMCOORD_INPUT localIn = *pIn;
450     localIn.unAlignedDims.width  = Max(pIn->unAlignedDims.width,  1u);
451     localIn.unAlignedDims.height = Max(pIn->unAlignedDims.height, 1u);
452     localIn.unAlignedDims.depth  = Max(pIn->unAlignedDims.depth,  1u);
453     localIn.numMipLevels         = Max(pIn->numMipLevels,         1u);
454     localIn.numSamples           = Max(pIn->numSamples,           1u);
455 
456     if ((localIn.bpp < 8)                               ||
457         (localIn.bpp > 128)                             ||
458         ((localIn.bpp % 8) != 0)                        ||
459         (localIn.sample >= localIn.numSamples)          ||
460         (localIn.slice >= localIn.unAlignedDims.depth)  ||
461         (localIn.mipId >= localIn.numMipLevels)         ||
462         (IsTex3d(localIn.resourceType)                  &&
463         (Valid3DMipSliceIdConstraint(localIn.unAlignedDims.depth, localIn.mipId, localIn.slice) == FALSE)))
464     {
465         returnCode = ADDR_INVALIDPARAMS;
466     }
467 
468     if (returnCode == ADDR_OK)
469     {
470         if (IsLinear(localIn.swizzleMode))
471         {
472             returnCode = ComputeSurfaceAddrFromCoordLinear(&localIn, pOut);
473         }
474         else
475         {
476             returnCode = ComputeSurfaceAddrFromCoordTiled(&localIn, pOut);
477         }
478 
479         if (returnCode == ADDR_OK)
480         {
481             pOut->prtBlockIndex = static_cast<UINT_32>(pOut->addr / (64 * 1024));
482         }
483     }
484 
485     return returnCode;
486 }
487 
488 /**
489 ************************************************************************************************************************
490 *   Lib::CopyLinearSurface
491 *
492 *   @brief
493 *       Implements uncompressed linear copies between memory and images.
494 *
495 *   @return
496 *       ADDR_E_RETURNCODE
497 ************************************************************************************************************************
498 */
CopyLinearSurface(const ADDR3_COPY_MEMSURFACE_INPUT * pIn,const ADDR3_COPY_MEMSURFACE_REGION * pRegions,UINT_32 regionCount,bool surfaceIsDst) const499 ADDR_E_RETURNCODE Lib::CopyLinearSurface(
500     const ADDR3_COPY_MEMSURFACE_INPUT*  pIn,
501     const ADDR3_COPY_MEMSURFACE_REGION* pRegions,
502     UINT_32                             regionCount,
503     bool                                surfaceIsDst) const
504 {
505     ADDR3_COMPUTE_SURFACE_INFO_INPUT  localIn  = {0};
506     ADDR3_COMPUTE_SURFACE_INFO_OUTPUT localOut = {0};
507     ADDR3_MIP_INFO                    mipInfo[Addr3MaxMipLevels] = {{0}};
508     ADDR_ASSERT(pIn->numMipLevels <= Addr3MaxMipLevels);
509     ADDR_E_RETURNCODE returnCode = ADDR_OK;
510 
511     if (pIn->numSamples > 1)
512     {
513         returnCode = ADDR_INVALIDPARAMS;
514     }
515 
516     localIn.size         = sizeof(localIn);
517     localIn.flags        = pIn->flags;
518     localIn.swizzleMode  = ADDR3_LINEAR;
519     localIn.resourceType = pIn->resourceType;
520     localIn.format       = pIn->format;
521     localIn.bpp          = pIn->bpp;
522     localIn.width        = Max(pIn->unAlignedDims.width,  1u);
523     localIn.height       = Max(pIn->unAlignedDims.height, 1u);
524     localIn.numSlices    = Max(pIn->unAlignedDims.depth,  1u);
525     localIn.numMipLevels = Max(pIn->numMipLevels,         1u);
526     localIn.numSamples   = Max(pIn->numSamples,           1u);
527 
528     if (localIn.numMipLevels <= 1)
529     {
530         localIn.pitchInElement = pIn->pitchInElement;
531     }
532 
533     localOut.size     = sizeof(localOut);
534     localOut.pMipInfo = mipInfo;
535 
536     if (returnCode == ADDR_OK)
537     {
538         returnCode = ComputeSurfaceInfo(&localIn, &localOut);
539     }
540 
541     if (returnCode == ADDR_OK)
542     {
543         for (UINT_32 regionIdx = 0; regionIdx < regionCount; regionIdx++)
544         {
545             const ADDR3_COPY_MEMSURFACE_REGION* pCurRegion = &pRegions[regionIdx];
546 
547             void* pMipBase = VoidPtrInc(pIn->pMappedSurface,
548                                         (pIn->singleSubres ? 0 : mipInfo[pCurRegion->mipId].offset));
549 
550             const size_t lineSizeBytes = (localIn.bpp >> 3) * pCurRegion->copyDims.width;
551             const size_t lineImgPitchBytes = (localIn.bpp >> 3) * mipInfo[pCurRegion->mipId].pitch;
552 
553             for (UINT_32 sliceIdx = 0; sliceIdx < pCurRegion->copyDims.depth; sliceIdx++)
554             {
555                 UINT_32 sliceCoord = sliceIdx + pCurRegion->slice;
556                 size_t imgOffsetInMip = (localOut.sliceSize * sliceCoord) +
557                                         (lineImgPitchBytes * pCurRegion->y) +
558                                         (pCurRegion->x * (pIn->bpp >> 3));
559                 size_t memOffset = sliceIdx * pCurRegion->memSlicePitch;
560 
561                 for (UINT_32 yIdx = 0; yIdx < pCurRegion->copyDims.height; yIdx++)
562                 {
563                     if (surfaceIsDst)
564                     {
565                         memcpy(VoidPtrInc(pMipBase, imgOffsetInMip),
566                                VoidPtrInc(pCurRegion->pMem, memOffset),
567                                lineSizeBytes);
568                     }
569                     else
570                     {
571                         memcpy(VoidPtrInc(pCurRegion->pMem, memOffset),
572                                VoidPtrInc(pMipBase, imgOffsetInMip),
573                                lineSizeBytes);
574                     }
575 
576                     imgOffsetInMip += lineImgPitchBytes;
577                     memOffset      += pCurRegion->memRowPitch;
578                 }
579             }
580         }
581     }
582 
583     return returnCode;
584 }
585 
586 /**
587 ************************************************************************************************************************
588 *   Lib::CopyMemToSurface
589 *
590 *   @brief
591 *       Interface function stub of Addr3CopyMemToSurface.
592 *
593 *   @return
594 *       ADDR_E_RETURNCODE
595 ************************************************************************************************************************
596 */
CopyMemToSurface(const ADDR3_COPY_MEMSURFACE_INPUT * pIn,const ADDR3_COPY_MEMSURFACE_REGION * pRegions,UINT_32 regionCount) const597 ADDR_E_RETURNCODE Lib::CopyMemToSurface(
598     const ADDR3_COPY_MEMSURFACE_INPUT*  pIn,
599     const ADDR3_COPY_MEMSURFACE_REGION* pRegions,
600     UINT_32                             regionCount) const
601 {
602     ADDR_E_RETURNCODE returnCode = ADDR_OK;
603 
604     if ((regionCount == 0) || (pRegions == NULL))
605     {
606         returnCode = ADDR_INVALIDPARAMS;
607     }
608     else if (GetFillSizeFieldsFlags() == TRUE)
609     {
610         if (pIn->size  != sizeof(ADDR3_COPY_MEMSURFACE_INPUT))
611         {
612             returnCode = ADDR_INVALIDPARAMS;
613         }
614         else
615         {
616             UINT_32 baseSlice    = pRegions[0].slice;
617             UINT_32 baseMip      = pRegions[0].mipId;
618             BOOL_32 singleSubres = pIn->singleSubres;
619             for (UINT_32 i = 0; i < regionCount; i++)
620             {
621                 if (pRegions[i].size != sizeof(ADDR3_COPY_MEMSURFACE_REGION))
622                 {
623                     returnCode = ADDR_INVALIDPARAMS;
624                     break;
625                 }
626                 if (singleSubres &&
627                     ((pRegions[i].copyDims.depth != 1) ||
628                      (pRegions[i].slice != baseSlice)  ||
629                      (pRegions[i].mipId != baseMip)))
630                 {
631                     // Copy will cover multiple/interleaved subresources, a
632                     // mapped pointer to a single subres cannot be valid.
633                     returnCode = ADDR_INVALIDPARAMS;
634                     break;
635                 }
636             }
637         }
638     }
639 
640     if (returnCode == ADDR_OK)
641     {
642         if (IsLinear(pIn->swizzleMode))
643         {
644             returnCode = CopyLinearSurface(pIn, pRegions, regionCount, true);
645         }
646         else
647         {
648             returnCode = HwlCopyMemToSurface(pIn, pRegions, regionCount);
649         }
650     }
651 
652     return returnCode;
653 }
654 
655 /**
656 ************************************************************************************************************************
657 *   Lib::CopySurfaceToMem
658 *
659 *   @brief
660 *       Interface function stub of Addr3CopySurfaceToMem.
661 *
662 *   @return
663 *       ADDR_E_RETURNCODE
664 ************************************************************************************************************************
665 */
CopySurfaceToMem(const ADDR3_COPY_MEMSURFACE_INPUT * pIn,const ADDR3_COPY_MEMSURFACE_REGION * pRegions,UINT_32 regionCount) const666 ADDR_E_RETURNCODE Lib::CopySurfaceToMem(
667     const ADDR3_COPY_MEMSURFACE_INPUT*  pIn,
668     const ADDR3_COPY_MEMSURFACE_REGION* pRegions,
669     UINT_32                             regionCount) const
670 {
671     ADDR_E_RETURNCODE returnCode = ADDR_OK;
672 
673     if (regionCount == 0)
674     {
675         returnCode = ADDR_INVALIDPARAMS;
676     }
677     else if (GetFillSizeFieldsFlags() == TRUE)
678     {
679         if (pIn->size  != sizeof(ADDR3_COPY_MEMSURFACE_INPUT))
680         {
681             returnCode = ADDR_INVALIDPARAMS;
682         }
683         else
684         {
685             UINT_32 baseSlice    = pRegions[0].slice;
686             UINT_32 baseMip      = pRegions[0].mipId;
687             BOOL_32 singleSubres = pIn->singleSubres;
688             for (UINT_32 i = 0; i < regionCount; i++)
689             {
690                 if (pRegions[i].size != sizeof(ADDR3_COPY_MEMSURFACE_REGION))
691                 {
692                     returnCode = ADDR_INVALIDPARAMS;
693                     break;
694                 }
695                 if (singleSubres &&
696                     ((pRegions[i].copyDims.depth != 1) ||
697                      (pRegions[i].slice != baseSlice)  ||
698                      (pRegions[i].mipId != baseMip)))
699                 {
700                     // Copy will cover multiple/interleaved subresources, a
701                     // mapped pointer to a single subres cannot be valid.
702                     returnCode = ADDR_INVALIDPARAMS;
703                     break;
704                 }
705             }
706         }
707     }
708 
709     if (returnCode == ADDR_OK)
710     {
711         if (IsLinear(pIn->swizzleMode))
712         {
713             returnCode = CopyLinearSurface(pIn, pRegions, regionCount, false);
714         }
715         else
716         {
717             returnCode = HwlCopySurfaceToMem(pIn, pRegions, regionCount);
718         }
719     }
720 
721     return returnCode;
722 }
723 
724 /**
725 ************************************************************************************************************************
726 *   Lib::ComputeSurfaceAddrFromCoord
727 *
728 *   @brief
729 *       Interface function stub of Addr3ComputePipeBankXor.
730 *
731 *   @return
732 *       ADDR_E_RETURNCODE
733 ************************************************************************************************************************
734 */
ComputePipeBankXor(const ADDR3_COMPUTE_PIPEBANKXOR_INPUT * pIn,ADDR3_COMPUTE_PIPEBANKXOR_OUTPUT * pOut)735 ADDR_E_RETURNCODE Lib::ComputePipeBankXor(
736     const ADDR3_COMPUTE_PIPEBANKXOR_INPUT* pIn,
737     ADDR3_COMPUTE_PIPEBANKXOR_OUTPUT*      pOut)
738 {
739     ADDR_E_RETURNCODE returnCode;
740 
741     if ((GetFillSizeFieldsFlags() == TRUE) &&
742         ((pIn->size  != sizeof(ADDR3_COMPUTE_PIPEBANKXOR_INPUT)) ||
743          (pOut->size != sizeof(ADDR3_COMPUTE_PIPEBANKXOR_OUTPUT))))
744     {
745         returnCode = ADDR_INVALIDPARAMS;
746     }
747     else
748     {
749         returnCode = HwlComputePipeBankXor(pIn, pOut);
750     }
751 
752     return returnCode;
753 }
754 
755 /**
756 ************************************************************************************************************************
757 *   Lib::ComputeSurfaceAddrFromCoordLinear
758 *
759 *   @brief
760 *       Internal function to calculate address from coord for linear swizzle surface
761 *
762 *   @return
763 *       ADDR_E_RETURNCODE
764 ************************************************************************************************************************
765 */
ComputeSurfaceAddrFromCoordLinear(const ADDR3_COMPUTE_SURFACE_ADDRFROMCOORD_INPUT * pIn,ADDR3_COMPUTE_SURFACE_ADDRFROMCOORD_OUTPUT * pOut) const766 ADDR_E_RETURNCODE Lib::ComputeSurfaceAddrFromCoordLinear(
767      const ADDR3_COMPUTE_SURFACE_ADDRFROMCOORD_INPUT* pIn,    ///< [in] input structure
768      ADDR3_COMPUTE_SURFACE_ADDRFROMCOORD_OUTPUT*      pOut    ///< [out] output structure
769      ) const
770 {
771     ADDR_E_RETURNCODE returnCode = ADDR_OK;
772     BOOL_32 valid = (pIn->numSamples <= 1);
773 
774     if (valid)
775     {
776         if (IsTex1d(pIn->resourceType))
777         {
778             valid = (pIn->y == 0);
779         }
780     }
781 
782     if (valid)
783     {
784         ADDR3_COMPUTE_SURFACE_INFO_INPUT  surfInfoIn = {0};
785 
786         surfInfoIn.size         = sizeof(surfInfoIn);
787         surfInfoIn.flags        = pIn->flags;
788         surfInfoIn.swizzleMode  = ADDR3_LINEAR;
789         surfInfoIn.resourceType = pIn->resourceType;
790         surfInfoIn.format       = ADDR_FMT_INVALID;
791         surfInfoIn.bpp          = pIn->bpp;
792         surfInfoIn.width        = Max(pIn->unAlignedDims.width,  1u);
793         surfInfoIn.height       = Max(pIn->unAlignedDims.height, 1u);
794         surfInfoIn.numSlices    = Max(pIn->unAlignedDims.depth,  1u);
795         surfInfoIn.numMipLevels = Max(pIn->numMipLevels,         1u);
796         surfInfoIn.numSamples   = Max(pIn->numSamples,           1u);
797 
798         if (surfInfoIn.numMipLevels <= 1)
799         {
800             surfInfoIn.pitchInElement = pIn->pitchInElement;
801         }
802 
803         returnCode = HwlComputeSurfaceAddrFromCoordLinear(pIn, &surfInfoIn, pOut);
804     }
805 
806     if (valid == FALSE)
807     {
808         returnCode = ADDR_INVALIDPARAMS;
809     }
810 
811     return returnCode;
812 }
813 
814 /**
815 ************************************************************************************************************************
816 *   Lib::ComputeSurfaceAddrFromCoordTiled
817 *
818 *   @brief
819 *       Internal function to calculate address from coord for tiled swizzle surface
820 *
821 *   @return
822 *       ADDR_E_RETURNCODE
823 ************************************************************************************************************************
824 */
ComputeSurfaceAddrFromCoordTiled(const ADDR3_COMPUTE_SURFACE_ADDRFROMCOORD_INPUT * pIn,ADDR3_COMPUTE_SURFACE_ADDRFROMCOORD_OUTPUT * pOut) const825 ADDR_E_RETURNCODE Lib::ComputeSurfaceAddrFromCoordTiled(
826      const ADDR3_COMPUTE_SURFACE_ADDRFROMCOORD_INPUT* pIn,    ///< [in] input structure
827      ADDR3_COMPUTE_SURFACE_ADDRFROMCOORD_OUTPUT*      pOut    ///< [out] output structure
828      ) const
829 {
830     return HwlComputeSurfaceAddrFromCoordTiled(pIn, pOut);
831 }
832 
833 /**
834 ************************************************************************************************************************
835 *   Lib::ComputeNonBlockCompressedView
836 *
837 *   @brief
838 *       Interface function stub of Addr3ComputeNonBlockCompressedView.
839 *
840 *   @return
841 *       ADDR_E_RETURNCODE
842 ************************************************************************************************************************
843 */
ComputeNonBlockCompressedView(const ADDR3_COMPUTE_NONBLOCKCOMPRESSEDVIEW_INPUT * pIn,ADDR3_COMPUTE_NONBLOCKCOMPRESSEDVIEW_OUTPUT * pOut)844 ADDR_E_RETURNCODE Lib::ComputeNonBlockCompressedView(
845     const ADDR3_COMPUTE_NONBLOCKCOMPRESSEDVIEW_INPUT* pIn,
846     ADDR3_COMPUTE_NONBLOCKCOMPRESSEDVIEW_OUTPUT*      pOut)
847 {
848     ADDR_E_RETURNCODE returnCode;
849 
850     if ((GetFillSizeFieldsFlags() == TRUE) &&
851         ((pIn->size  != sizeof(ADDR3_COMPUTE_NONBLOCKCOMPRESSEDVIEW_INPUT)) ||
852          (pOut->size != sizeof(ADDR3_COMPUTE_NONBLOCKCOMPRESSEDVIEW_OUTPUT))))
853     {
854         returnCode = ADDR_INVALIDPARAMS;
855     }
856     else if (Is3dSwizzle(pIn->swizzleMode))
857     {
858         // 3D volume images using ADDR3_XX_3D is currently not supported.
859         returnCode = ADDR_NOTSUPPORTED;
860     }
861     else
862     {
863         returnCode = HwlComputeNonBlockCompressedView(pIn, pOut);
864     }
865 
866     return returnCode;
867 }
868 
869 /**
870 ************************************************************************************************************************
871 *   Lib::ComputeSubResourceOffsetForSwizzlePattern
872 *
873 *   @brief
874 *       Interface function stub of Addr3ComputeSubResourceOffsetForSwizzlePattern.
875 *
876 *   @return
877 *       ADDR_E_RETURNCODE
878 ************************************************************************************************************************
879 */
ComputeSubResourceOffsetForSwizzlePattern(const ADDR3_COMPUTE_SUBRESOURCE_OFFSET_FORSWIZZLEPATTERN_INPUT * pIn,ADDR3_COMPUTE_SUBRESOURCE_OFFSET_FORSWIZZLEPATTERN_OUTPUT * pOut)880 ADDR_E_RETURNCODE Lib::ComputeSubResourceOffsetForSwizzlePattern(
881     const ADDR3_COMPUTE_SUBRESOURCE_OFFSET_FORSWIZZLEPATTERN_INPUT* pIn,
882     ADDR3_COMPUTE_SUBRESOURCE_OFFSET_FORSWIZZLEPATTERN_OUTPUT*      pOut)
883 {
884     ADDR_E_RETURNCODE returnCode = ADDR_OK;
885 
886     if ((GetFillSizeFieldsFlags() == TRUE) &&
887         ((pIn->size  != sizeof(ADDR3_COMPUTE_SUBRESOURCE_OFFSET_FORSWIZZLEPATTERN_INPUT)) ||
888          (pOut->size != sizeof(ADDR3_COMPUTE_SUBRESOURCE_OFFSET_FORSWIZZLEPATTERN_OUTPUT))))
889     {
890         returnCode = ADDR_INVALIDPARAMS;
891     }
892     else
893     {
894         HwlComputeSubResourceOffsetForSwizzlePattern(pIn, pOut);
895     }
896 
897     return returnCode;
898 }
899 
900 /**
901 ************************************************************************************************************************
902 *   Lib::ComputeSlicePipeBankXor
903 *
904 *   @brief
905 *       Interface function stub of Addr3ComputeSlicePipeBankXor.
906 *
907 *   @return
908 *       ADDR_E_RETURNCODE
909 ************************************************************************************************************************
910 */
ComputeSlicePipeBankXor(const ADDR3_COMPUTE_SLICE_PIPEBANKXOR_INPUT * pIn,ADDR3_COMPUTE_SLICE_PIPEBANKXOR_OUTPUT * pOut)911 ADDR_E_RETURNCODE Lib::ComputeSlicePipeBankXor(
912     const ADDR3_COMPUTE_SLICE_PIPEBANKXOR_INPUT* pIn,
913     ADDR3_COMPUTE_SLICE_PIPEBANKXOR_OUTPUT*      pOut)
914 {
915     ADDR_E_RETURNCODE returnCode;
916 
917     if ((GetFillSizeFieldsFlags() == TRUE) &&
918         ((pIn->size  != sizeof(ADDR3_COMPUTE_SLICE_PIPEBANKXOR_INPUT)) ||
919          (pOut->size != sizeof(ADDR3_COMPUTE_SLICE_PIPEBANKXOR_OUTPUT))))
920     {
921         returnCode = ADDR_INVALIDPARAMS;
922     }
923     if ((pIn->bpe != 0) &&
924         (pIn->bpe != 8) &&
925         (pIn->bpe != 16) &&
926         (pIn->bpe != 32) &&
927         (pIn->bpe != 64) &&
928         (pIn->bpe != 128))
929     {
930         returnCode = ADDR_INVALIDPARAMS;
931     }
932     else
933     {
934         returnCode = HwlComputeSlicePipeBankXor(pIn, pOut);
935     }
936 
937     return returnCode;
938 }
939 
940 /**
941 ************************************************************************************************************************
942 *   Lib::UseCustomHeight
943 *
944 *   @brief
945 *       Determines if the calculations for this surface should use minimal HW values or user-specified values.
946 *
947 *   @return
948 *       Returns TRUE if the user-specified alignment should be used
949 ************************************************************************************************************************
950 */
UseCustomHeight(const ADDR3_COMPUTE_SURFACE_INFO_INPUT * pIn) const951 BOOL_32 Lib::UseCustomHeight(
952     const ADDR3_COMPUTE_SURFACE_INFO_INPUT*  pIn
953     ) const
954 {
955     return ((pIn->numMipLevels <= 1)   &&
956             IsLinear(pIn->swizzleMode) &&
957             (pIn->sliceAlign > 0));
958 }
959 
960 /**
961 ************************************************************************************************************************
962 *   Lib::UseCustomPitch
963 *
964 *   @brief
965 *       Determines if the calculations for this surface should use minimal HW values or user-specified values.
966 *
967 *   @return
968 *       Returns TRUE if the user-specified pitch should be used
969 ************************************************************************************************************************
970 */
UseCustomPitch(const ADDR3_COMPUTE_SURFACE_INFO_INPUT * pIn) const971 BOOL_32 Lib::UseCustomPitch(
972     const ADDR3_COMPUTE_SURFACE_INFO_INPUT*  pIn
973     ) const
974 {
975     return ((pIn->numMipLevels <= 1)   &&
976             IsLinear(pIn->swizzleMode) &&
977             (pIn->pitchInElement > 0));
978 }
979 
980 /**
981 ************************************************************************************************************************
982 *   Lib::CanTrimLinearPadding
983 *
984 *   @brief
985 *       Determines if the calculations for this surface can omit extra trailing padding for linear surfaces.
986 *
987 *   @return
988 *       Returns TRUE if the trailing padding can be omitted.
989 ************************************************************************************************************************
990 */
CanTrimLinearPadding(const ADDR3_COMPUTE_SURFACE_INFO_INPUT * pIn) const991 BOOL_32 Lib::CanTrimLinearPadding(
992     const ADDR3_COMPUTE_SURFACE_INFO_INPUT*  pIn
993     ) const
994 {
995     return ((IsTex3d(pIn->resourceType) == FALSE) &&
996             (pIn->numSlices <= 1)                 &&
997             IsLinear(pIn->swizzleMode));
998 }
999 
1000 /**
1001 ************************************************************************************************************************
1002 *   Lib::ApplyCustomizedPitchHeight
1003 *
1004 *   @brief
1005 *       Helper function to override hw required row pitch/slice pitch by customrized one
1006 *
1007 *   @return
1008 *       ADDR_E_RETURNCODE
1009 ************************************************************************************************************************
1010 */
ApplyCustomizedPitchHeight(const ADDR3_COMPUTE_SURFACE_INFO_INPUT * pIn,ADDR3_COMPUTE_SURFACE_INFO_OUTPUT * pOut) const1011 ADDR_E_RETURNCODE Lib::ApplyCustomizedPitchHeight(
1012     const ADDR3_COMPUTE_SURFACE_INFO_INPUT* pIn,    ///< [in] input structure
1013     ADDR3_COMPUTE_SURFACE_INFO_OUTPUT*      pOut
1014     ) const
1015 {
1016     ADDR_E_RETURNCODE returnCode = ADDR_OK;
1017 
1018     const UINT_32  elementBytes = pIn->bpp >> 3;
1019 
1020     UINT_32  pitchAlignmentElements      = pOut->blockExtent.width;
1021     UINT_32  pitchSliceAlignmentElements = pOut->blockExtent.width;
1022 
1023     if (IsLinear(pIn->swizzleMode))
1024     {
1025         // Normal pitch of image data
1026         const UINT_32  pitchAlignmentBytes    = 1 << GetBlockSizeLog2(pIn->swizzleMode, TRUE);
1027         pitchAlignmentElements = pitchAlignmentBytes / elementBytes;
1028 
1029         // Pitch of image data used for slice sizing
1030         const UINT_32  pitchSliceAlignmentBytes    = 1 << GetBlockSizeLog2(pIn->swizzleMode, CanTrimLinearPadding(pIn));
1031         pitchSliceAlignmentElements = pitchSliceAlignmentBytes / elementBytes;
1032     }
1033 
1034     pOut->pitch         = PowTwoAlign(pIn->width, pitchAlignmentElements);
1035     pOut->pitchForSlice = PowTwoAlign(pIn->width, pitchSliceAlignmentElements);
1036 
1037     UINT_32 heightAlign = pOut->blockExtent.height;
1038 
1039     if (pIn->flags.qbStereo)
1040     {
1041         UINT_32 rightXor = 0;
1042 
1043         returnCode = HwlComputeStereoInfo(pIn, &heightAlign, &rightXor);
1044 
1045         if (returnCode == ADDR_OK)
1046         {
1047             pOut->pStereoInfo->rightSwizzle = rightXor;
1048         }
1049     }
1050 
1051     pOut->height = PowTwoAlign(pIn->height, heightAlign);
1052 
1053     // Custom pitches / alignments are only possible with single mip level / linear images; otherwise,
1054     // ignore those parameters.
1055     if ((returnCode == ADDR_OK) && UseCustomPitch(pIn))
1056     {
1057         // Their requested pitch has to meet the pitch alignment constraints applied by the HW.
1058         if ((pIn->pitchInElement % pitchAlignmentElements) != 0)
1059         {
1060             returnCode = ADDR_INVALIDPARAMS;
1061         }
1062         // And their pitch can't be less than the minimum
1063         else if (pIn->pitchInElement < pOut->pitch)
1064         {
1065             returnCode = ADDR_INVALIDPARAMS;
1066         }
1067         else
1068         {
1069             pOut->pitch = pIn->pitchInElement;
1070             pOut->pitchForSlice = PowTwoAlign(pIn->pitchInElement, pitchSliceAlignmentElements);
1071         }
1072     }
1073 
1074     if ((returnCode == ADDR_OK) && UseCustomHeight(pIn))
1075     {
1076         // Note: if a custom slice align is present, it must be an even multiple
1077         // of pitchForSlice, not just pitch.
1078         UINT_32 customizedHeight = pIn->sliceAlign / elementBytes / pOut->pitchForSlice;
1079 
1080         if ((pIn->numSlices > 1) && (customizedHeight * elementBytes * pOut->pitchForSlice != pIn->sliceAlign))
1081         {
1082             returnCode = ADDR_INVALIDPARAMS;
1083         }
1084         else if ((pIn->numSlices > 1) && (pOut->height != customizedHeight))
1085         {
1086             returnCode = ADDR_INVALIDPARAMS;
1087         }
1088         else if ((pIn->height * elementBytes * pOut->pitch) > pIn->sliceAlign)
1089         {
1090             // If we only have one slice/depth, then we don't need an even multiple, but the slice size must still
1091             // fit all the pixel data. The one provided is too small!
1092             returnCode = ADDR_INVALIDPARAMS;
1093         }
1094         else
1095         {
1096             // For the single-slice case, the customized height could have been rounded down below the height since
1097             // we allow non-multiples of pitch here, so take the max.
1098             pOut->height = Max(pOut->height, customizedHeight);
1099         }
1100     }
1101 
1102     return returnCode;
1103 }
1104 
1105 
1106 /**
1107 ************************************************************************************************************************
1108 *   Lib::ComputeQbStereoInfo
1109 *
1110 *   @brief
1111 *       Get quad buffer stereo information
1112 *   @return
1113 *       N/A
1114 ************************************************************************************************************************
1115 */
ComputeQbStereoInfo(ADDR3_COMPUTE_SURFACE_INFO_OUTPUT * pOut) const1116 VOID Lib::ComputeQbStereoInfo(
1117     ADDR3_COMPUTE_SURFACE_INFO_OUTPUT* pOut   ///< [in,out] updated pOut+pStereoInfo
1118     ) const
1119 {
1120     ADDR_ASSERT(pOut->bpp >= 8);
1121     ADDR_ASSERT((pOut->surfSize % pOut->baseAlign) == 0);
1122 
1123     // Save original height
1124     pOut->pStereoInfo->eyeHeight = pOut->height;
1125 
1126     // Right offset
1127     pOut->pStereoInfo->rightOffset = static_cast<UINT_32>(pOut->surfSize);
1128 
1129     // Double height
1130     pOut->height <<= 1;
1131 
1132     ADDR_ASSERT(pOut->height <= MaxSurfaceHeight);
1133 
1134     pOut->pixelHeight <<= 1;
1135 
1136     // Double size
1137     pOut->surfSize  <<= 1;
1138     pOut->sliceSize <<= 1;
1139 }
1140 
1141 /**
1142 ************************************************************************************************************************
1143 *   Lib::ComputeSurfaceInfoSanityCheck
1144 *
1145 *   @brief
1146 *       Internal function to do basic sanity check before compute surface info
1147 *
1148 *   @return
1149 *       ADDR_E_RETURNCODE
1150 ************************************************************************************************************************
1151 */
ComputeSurfaceInfoSanityCheck(const ADDR3_COMPUTE_SURFACE_INFO_INPUT * pIn) const1152 ADDR_E_RETURNCODE Lib::ComputeSurfaceInfoSanityCheck(
1153     const ADDR3_COMPUTE_SURFACE_INFO_INPUT*  pIn   ///< [in] input structure
1154     ) const
1155 {
1156     ADDR3_GET_POSSIBLE_SWIZZLE_MODE_INPUT localIn = {};
1157     localIn.size         = sizeof(ADDR3_GET_POSSIBLE_SWIZZLE_MODE_INPUT);
1158     localIn.flags        = pIn->flags;
1159     localIn.resourceType = pIn->resourceType;
1160     localIn.bpp          = pIn->bpp;
1161     localIn.width        = pIn->width;
1162     localIn.height       = pIn->height;
1163     localIn.numSlices    = pIn->numSlices;
1164     localIn.numMipLevels = pIn->numMipLevels;
1165     localIn.numSamples   = pIn->numSamples;
1166 
1167     return HwlValidateNonSwModeParams(&localIn) ? ADDR_OK : ADDR_INVALIDPARAMS;
1168 }
1169 
1170 } // V3
1171 } // Addr
1172