1 /*
2 ************************************************************************************************************************
3 *
4 *  Copyright (C) 2007-2022 Advanced Micro Devices, Inc.  All rights reserved.
5 *
6 * Permission is hereby granted, free of charge, to any person obtaining a
7 * copy of this software and associated documentation files (the "Software"),
8 * to deal in the Software without restriction, including without limitation
9 * the rights to use, copy, modify, merge, publish, distribute, sublicense,
10 * and/or sell copies of the Software, and to permit persons to whom the
11 * Software is furnished to do so, subject to the following conditions:
12 *
13 * The above copyright notice and this permission notice shall be included in
14 * all copies or substantial portions of the Software.
15 *
16 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
17 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
18 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
19 * THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR
20 * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
21 * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
22 * OTHER DEALINGS IN THE SOFTWARE
23 *
24 ***********************************************************************************************************************/
25 
26 /**
27 ****************************************************************************************************
28 * @file  addr1lib.cpp
29 * @brief Contains the implementation for the Addr::V1::Lib base class.
30 ****************************************************************************************************
31 */
32 
33 #include "addrinterface.h"
34 #include "addrlib1.h"
35 #include "addrcommon.h"
36 
37 namespace Addr
38 {
39 namespace V1
40 {
41 
42 ////////////////////////////////////////////////////////////////////////////////////////////////////
43 //                               Static Const Member
44 ////////////////////////////////////////////////////////////////////////////////////////////////////
45 
46 const TileModeFlags Lib::ModeFlags[ADDR_TM_COUNT] =
47 {// T   L  1  2  3  P  Pr B
48     {1, 1, 0, 0, 0, 0, 0, 0}, // ADDR_TM_LINEAR_GENERAL
49     {1, 1, 0, 0, 0, 0, 0, 0}, // ADDR_TM_LINEAR_ALIGNED
50     {1, 0, 1, 0, 0, 0, 0, 0}, // ADDR_TM_1D_TILED_THIN1
51     {4, 0, 1, 0, 0, 0, 0, 0}, // ADDR_TM_1D_TILED_THICK
52     {1, 0, 0, 1, 0, 0, 0, 0}, // ADDR_TM_2D_TILED_THIN1
53     {1, 0, 0, 1, 0, 0, 0, 0}, // ADDR_TM_2D_TILED_THIN2
54     {1, 0, 0, 1, 0, 0, 0, 0}, // ADDR_TM_2D_TILED_THIN4
55     {4, 0, 0, 1, 0, 0, 0, 0}, // ADDR_TM_2D_TILED_THICK
56     {1, 0, 0, 1, 0, 0, 0, 1}, // ADDR_TM_2B_TILED_THIN1
57     {1, 0, 0, 1, 0, 0, 0, 1}, // ADDR_TM_2B_TILED_THIN2
58     {1, 0, 0, 1, 0, 0, 0, 1}, // ADDR_TM_2B_TILED_THIN4
59     {4, 0, 0, 1, 0, 0, 0, 1}, // ADDR_TM_2B_TILED_THICK
60     {1, 0, 0, 1, 1, 0, 0, 0}, // ADDR_TM_3D_TILED_THIN1
61     {4, 0, 0, 1, 1, 0, 0, 0}, // ADDR_TM_3D_TILED_THICK
62     {1, 0, 0, 1, 1, 0, 0, 1}, // ADDR_TM_3B_TILED_THIN1
63     {4, 0, 0, 1, 1, 0, 0, 1}, // ADDR_TM_3B_TILED_THICK
64     {8, 0, 0, 1, 0, 0, 0, 0}, // ADDR_TM_2D_TILED_XTHICK
65     {8, 0, 0, 1, 1, 0, 0, 0}, // ADDR_TM_3D_TILED_XTHICK
66     {1, 0, 0, 0, 0, 0, 0, 0}, // ADDR_TM_POWER_SAVE
67     {1, 0, 0, 1, 0, 1, 1, 0}, // ADDR_TM_PRT_TILED_THIN1
68     {1, 0, 0, 1, 0, 1, 0, 0}, // ADDR_TM_PRT_2D_TILED_THIN1
69     {1, 0, 0, 1, 1, 1, 0, 0}, // ADDR_TM_PRT_3D_TILED_THIN1
70     {4, 0, 0, 1, 0, 1, 1, 0}, // ADDR_TM_PRT_TILED_THICK
71     {4, 0, 0, 1, 0, 1, 0, 0}, // ADDR_TM_PRT_2D_TILED_THICK
72     {4, 0, 0, 1, 1, 1, 0, 0}, // ADDR_TM_PRT_3D_TILED_THICK
73     {0, 0, 0, 0, 0, 0, 0, 0}, // ADDR_TM_UNKNOWN
74 };
75 
76 ////////////////////////////////////////////////////////////////////////////////////////////////////
77 //                               Constructor/Destructor
78 ////////////////////////////////////////////////////////////////////////////////////////////////////
79 
80 /**
81 ****************************************************************************************************
82 *   Lib::AddrLib1
83 *
84 *   @brief
85 *       Constructor for the AddrLib1 class
86 *
87 ****************************************************************************************************
88 */
Lib()89 Lib::Lib()
90     :
91     Addr::Lib()
92 {
93 }
94 
95 /**
96 ****************************************************************************************************
97 *   Lib::Lib
98 *
99 *   @brief
100 *       Constructor for the Addr::V1::Lib class with hClient as parameter
101 *
102 ****************************************************************************************************
103 */
Lib(const Client * pClient)104 Lib::Lib(const Client* pClient)
105     :
106     Addr::Lib(pClient)
107 {
108 }
109 
110 /**
111 ****************************************************************************************************
112 *   Lib::~AddrLib1
113 *
114 *   @brief
115 *       Destructor for the AddrLib1 class
116 *
117 ****************************************************************************************************
118 */
~Lib()119 Lib::~Lib()
120 {
121 }
122 
123 /**
124 ****************************************************************************************************
125 *   Lib::GetLib
126 *
127 *   @brief
128 *       Get AddrLib1 pointer
129 *
130 *   @return
131 *      An Addr::V1::Lib class pointer
132 ****************************************************************************************************
133 */
GetLib(ADDR_HANDLE hLib)134 Lib* Lib::GetLib(
135     ADDR_HANDLE hLib)   ///< [in] handle of ADDR_HANDLE
136 {
137     Addr::Lib* pAddrLib = Addr::Lib::GetLib(hLib);
138     if ((pAddrLib != NULL) &&
139         ((pAddrLib->GetChipFamily() == ADDR_CHIP_FAMILY_IVLD) ||
140          (pAddrLib->GetChipFamily() > ADDR_CHIP_FAMILY_VI)))
141     {
142         // only valid and pre-VI ASIC can use AddrLib1 function.
143         ADDR_ASSERT_ALWAYS();
144         hLib = NULL;
145     }
146     return static_cast<Lib*>(hLib);
147 }
148 
149 
150 ////////////////////////////////////////////////////////////////////////////////////////////////////
151 //                               Surface Methods
152 ////////////////////////////////////////////////////////////////////////////////////////////////////
153 
154 
155 /**
156 ****************************************************************************************************
157 *   Lib::ComputeSurfaceInfo
158 *
159 *   @brief
160 *       Interface function stub of AddrComputeSurfaceInfo.
161 *
162 *   @return
163 *       ADDR_E_RETURNCODE
164 ****************************************************************************************************
165 */
ComputeSurfaceInfo(const ADDR_COMPUTE_SURFACE_INFO_INPUT * pIn,ADDR_COMPUTE_SURFACE_INFO_OUTPUT * pOut) const166 ADDR_E_RETURNCODE Lib::ComputeSurfaceInfo(
167      const ADDR_COMPUTE_SURFACE_INFO_INPUT* pIn,    ///< [in] input structure
168      ADDR_COMPUTE_SURFACE_INFO_OUTPUT*      pOut    ///< [out] output structure
169      ) const
170 {
171     ADDR_E_RETURNCODE returnCode = ADDR_OK;
172 
173     if (GetFillSizeFieldsFlags() == TRUE)
174     {
175         if ((pIn->size != sizeof(ADDR_COMPUTE_SURFACE_INFO_INPUT)) ||
176             (pOut->size != sizeof(ADDR_COMPUTE_SURFACE_INFO_OUTPUT)))
177         {
178             returnCode = ADDR_PARAMSIZEMISMATCH;
179         }
180     }
181 
182     // We suggest client do sanity check but a check here is also good
183     if (pIn->bpp > 128)
184     {
185         returnCode = ADDR_INVALIDPARAMS;
186     }
187 
188     if ((pIn->tileMode == ADDR_TM_UNKNOWN) && (pIn->mipLevel > 0))
189     {
190         returnCode = ADDR_INVALIDPARAMS;
191     }
192 
193     // Thick modes don't support multisample
194     if ((Thickness(pIn->tileMode) > 1) && (pIn->numSamples > 1))
195     {
196         returnCode = ADDR_INVALIDPARAMS;
197     }
198 
199     if (returnCode == ADDR_OK)
200     {
201         // Get a local copy of input structure and only reference pIn for unadjusted values
202         ADDR_COMPUTE_SURFACE_INFO_INPUT localIn = *pIn;
203         ADDR_TILEINFO tileInfoNull = {0};
204 
205         if (UseTileInfo())
206         {
207             // If the original input has a valid ADDR_TILEINFO pointer then copy its contents.
208             // Otherwise the default 0's in tileInfoNull are used.
209             if (pIn->pTileInfo)
210             {
211                 tileInfoNull = *pIn->pTileInfo;
212             }
213             localIn.pTileInfo  = &tileInfoNull;
214         }
215 
216         localIn.numSamples = (pIn->numSamples == 0) ? 1 : pIn->numSamples;
217 
218         // Do mipmap check first
219         // If format is BCn, pre-pad dimension to power-of-two according to HWL
220         ComputeMipLevel(&localIn);
221 
222         if (m_configFlags.checkLast2DLevel)
223         {
224             // Save this level's original height in pixels
225             pOut->height = pIn->height;
226         }
227 
228         UINT_32 expandX = 1;
229         UINT_32 expandY = 1;
230         ElemMode elemMode;
231 
232         // Save outputs that may not go through HWL
233         pOut->pixelBits = localIn.bpp;
234         pOut->numSamples = localIn.numSamples;
235         pOut->last2DLevel = FALSE;
236         pOut->tcCompatible = FALSE;
237 
238 #if !ALT_TEST
239         if (localIn.numSamples > 1)
240         {
241             ADDR_ASSERT(localIn.mipLevel == 0);
242         }
243 #endif
244 
245         if (localIn.format != ADDR_FMT_INVALID) // Set format to INVALID will skip this conversion
246         {
247             // Get compression/expansion factors and element mode
248             // (which indicates compression/expansion
249             localIn.bpp = GetElemLib()->GetBitsPerPixel(localIn.format,
250                                                         &elemMode,
251                                                         &expandX,
252                                                         &expandY);
253 
254             // Special flag for 96 bit surface. 96 (or 48 if we support) bit surface's width is
255             // pre-multiplied by 3 and bpp is divided by 3. So pitch alignment for linear-
256             // aligned does not meet 64-pixel in real. We keep special handling in hwl since hw
257             // restrictions are different.
258             // Also Mip 1+ needs an element pitch of 32 bits so we do not need this workaround
259             // but we use this flag to skip RestoreSurfaceInfo below
260 
261             if ((elemMode == ADDR_EXPANDED) && (expandX > 1))
262             {
263                 ADDR_ASSERT(IsLinear(localIn.tileMode));
264             }
265 
266             GetElemLib()->AdjustSurfaceInfo(elemMode,
267                                             expandX,
268                                             expandY,
269                                             &localIn.bpp,
270                                             &localIn.basePitch,
271                                             &localIn.width,
272                                             &localIn.height);
273 
274             // Overwrite these parameters if we have a valid format
275         }
276         else if (localIn.bpp != 0)
277         {
278             localIn.width  = (localIn.width != 0) ? localIn.width : 1;
279             localIn.height = (localIn.height != 0) ? localIn.height : 1;
280         }
281         else // Rule out some invalid parameters
282         {
283             ADDR_ASSERT_ALWAYS();
284 
285             returnCode = ADDR_INVALIDPARAMS;
286         }
287 
288         // Check mipmap after surface expansion
289         if (returnCode == ADDR_OK)
290         {
291             returnCode = PostComputeMipLevel(&localIn, pOut);
292         }
293 
294         if (returnCode == ADDR_OK)
295         {
296             if (UseTileIndex(localIn.tileIndex))
297             {
298                 // Make sure pTileInfo is not NULL
299                 ADDR_ASSERT(localIn.pTileInfo);
300 
301                 UINT_32 numSamples = GetNumFragments(localIn.numSamples, localIn.numFrags);
302 
303                 INT_32 macroModeIndex = TileIndexNoMacroIndex;
304 
305                 if (localIn.tileIndex != TileIndexLinearGeneral)
306                 {
307                     // Try finding a macroModeIndex
308                     macroModeIndex = HwlComputeMacroModeIndex(localIn.tileIndex,
309                                                               localIn.flags,
310                                                               localIn.bpp,
311                                                               numSamples,
312                                                               localIn.pTileInfo,
313                                                               &localIn.tileMode,
314                                                               &localIn.tileType);
315                 }
316 
317                 // If macroModeIndex is not needed, then call HwlSetupTileCfg to get tile info
318                 if (macroModeIndex == TileIndexNoMacroIndex)
319                 {
320                     returnCode = HwlSetupTileCfg(localIn.bpp,
321                                                  localIn.tileIndex, macroModeIndex,
322                                                  localIn.pTileInfo,
323                                                  &localIn.tileMode, &localIn.tileType);
324                 }
325                 // If macroModeIndex is invalid, then assert this is not macro tiled
326                 else if (macroModeIndex == TileIndexInvalid)
327                 {
328                     ADDR_ASSERT(!IsMacroTiled(localIn.tileMode));
329                 }
330 
331                 pOut->macroModeIndex = macroModeIndex;
332             }
333         }
334 
335         if (returnCode == ADDR_OK)
336         {
337             localIn.flags.dccPipeWorkaround = localIn.flags.dccCompatible;
338 
339             if (localIn.tileMode == ADDR_TM_UNKNOWN)
340             {
341                 // HWL layer may override tile mode if necessary
342                 HwlSelectTileMode(&localIn);
343             }
344             else
345             {
346                 // HWL layer may override tile mode if necessary
347                 HwlOverrideTileMode(&localIn);
348 
349                 // Optimize tile mode if possible
350                 OptimizeTileMode(&localIn);
351             }
352         }
353 
354         // Call main function to compute surface info
355         if (returnCode == ADDR_OK)
356         {
357             returnCode = HwlComputeSurfaceInfo(&localIn, pOut);
358         }
359 
360         if (returnCode == ADDR_OK)
361         {
362             // Since bpp might be changed we just pass it through
363             pOut->bpp  = localIn.bpp;
364 
365             // Also original width/height/bpp
366             pOut->pixelPitch    = pOut->pitch;
367             pOut->pixelHeight   = pOut->height;
368 
369 #if DEBUG
370             if (localIn.flags.display)
371             {
372                 ADDR_ASSERT((pOut->pitchAlign % 32) == 0);
373             }
374 #endif //DEBUG
375 
376             if (localIn.format != ADDR_FMT_INVALID)
377             {
378                 //
379                 // Note: For 96 bit surface, the pixelPitch returned might be an odd number, but it
380                 // is okay to program texture pitch as HW's mip calculator would multiply 3 first,
381                 // then do the appropriate paddings (linear alignment requirement and possible the
382                 // nearest power-of-two for mipmaps), which results in the original pitch.
383                 //
384                 GetElemLib()->RestoreSurfaceInfo(elemMode,
385                                                  expandX,
386                                                  expandY,
387                                                  &localIn.bpp,
388                                                  &pOut->pixelPitch,
389                                                  &pOut->pixelHeight);
390             }
391 
392             if (localIn.flags.qbStereo)
393             {
394                 if (pOut->pStereoInfo)
395                 {
396                     ComputeQbStereoInfo(pOut);
397                 }
398             }
399 
400             if (localIn.flags.volume) // For volume sliceSize equals to all z-slices
401             {
402                 pOut->sliceSize = pOut->surfSize;
403             }
404             else // For array: sliceSize is likely to have slice-padding (the last one)
405             {
406                 pOut->sliceSize = pOut->surfSize / pOut->depth;
407 
408                 // array or cubemap
409                 if (pIn->numSlices > 1)
410                 {
411                     // If this is the last slice then add the padding size to this slice
412                     if (pIn->slice == (pIn->numSlices - 1))
413                     {
414                         pOut->sliceSize += pOut->sliceSize * (pOut->depth - pIn->numSlices);
415                     }
416                     else if (m_configFlags.checkLast2DLevel)
417                     {
418                         // Reset last2DLevel flag if this is not the last array slice
419                         pOut->last2DLevel = FALSE;
420                     }
421                 }
422             }
423 
424             pOut->pitchTileMax = pOut->pitch / 8 - 1;
425             pOut->heightTileMax = pOut->height / 8 - 1;
426             pOut->sliceTileMax = pOut->pitch * pOut->height / 64 - 1;
427         }
428     }
429 
430     ValidBaseAlignments(pOut->baseAlign);
431 
432     return returnCode;
433 }
434 
435 /**
436 ****************************************************************************************************
437 *   Lib::ComputeSurfaceInfo
438 *
439 *   @brief
440 *       Interface function stub of AddrComputeSurfaceInfo.
441 *
442 *   @return
443 *       ADDR_E_RETURNCODE
444 ****************************************************************************************************
445 */
ComputeSurfaceAddrFromCoord(const ADDR_COMPUTE_SURFACE_ADDRFROMCOORD_INPUT * pIn,ADDR_COMPUTE_SURFACE_ADDRFROMCOORD_OUTPUT * pOut) const446 ADDR_E_RETURNCODE Lib::ComputeSurfaceAddrFromCoord(
447     const ADDR_COMPUTE_SURFACE_ADDRFROMCOORD_INPUT* pIn,    ///< [in] input structure
448     ADDR_COMPUTE_SURFACE_ADDRFROMCOORD_OUTPUT*      pOut    ///< [out] output structure
449     ) const
450 {
451     ADDR_E_RETURNCODE returnCode = ADDR_OK;
452 
453     if (GetFillSizeFieldsFlags() == TRUE)
454     {
455         if ((pIn->size != sizeof(ADDR_COMPUTE_SURFACE_ADDRFROMCOORD_INPUT)) ||
456             (pOut->size != sizeof(ADDR_COMPUTE_SURFACE_ADDRFROMCOORD_OUTPUT)))
457         {
458             returnCode = ADDR_PARAMSIZEMISMATCH;
459         }
460     }
461 
462     if (returnCode == ADDR_OK)
463     {
464         ADDR_TILEINFO tileInfoNull;
465         ADDR_COMPUTE_SURFACE_ADDRFROMCOORD_INPUT input;
466 
467         if (UseTileIndex(pIn->tileIndex))
468         {
469             input = *pIn;
470             // Use temp tile info for calcalation
471             input.pTileInfo = &tileInfoNull;
472 
473             const ADDR_SURFACE_FLAGS flags = {{0}};
474             UINT_32 numSamples = GetNumFragments(pIn->numSamples, pIn->numFrags);
475 
476             // Try finding a macroModeIndex
477             INT_32 macroModeIndex = HwlComputeMacroModeIndex(input.tileIndex,
478                                                              flags,
479                                                              input.bpp,
480                                                              numSamples,
481                                                              input.pTileInfo,
482                                                              &input.tileMode,
483                                                              &input.tileType);
484 
485             // If macroModeIndex is not needed, then call HwlSetupTileCfg to get tile info
486             if (macroModeIndex == TileIndexNoMacroIndex)
487             {
488                 returnCode = HwlSetupTileCfg(input.bpp, input.tileIndex, macroModeIndex,
489                                              input.pTileInfo, &input.tileMode, &input.tileType);
490             }
491             // If macroModeIndex is invalid, then assert this is not macro tiled
492             else if (macroModeIndex == TileIndexInvalid)
493             {
494                 ADDR_ASSERT(!IsMacroTiled(input.tileMode));
495             }
496 
497             // Change the input structure
498             pIn = &input;
499         }
500 
501         if (returnCode == ADDR_OK)
502         {
503             returnCode = HwlComputeSurfaceAddrFromCoord(pIn, pOut);
504 
505             if (returnCode == ADDR_OK)
506             {
507                 pOut->prtBlockIndex = static_cast<UINT_32>(pOut->addr / (64 * 1024));
508             }
509         }
510     }
511 
512     return returnCode;
513 }
514 
515 /**
516 ****************************************************************************************************
517 *   Lib::ComputeSurfaceCoordFromAddr
518 *
519 *   @brief
520 *       Interface function stub of ComputeSurfaceCoordFromAddr.
521 *
522 *   @return
523 *       ADDR_E_RETURNCODE
524 ****************************************************************************************************
525 */
ComputeSurfaceCoordFromAddr(const ADDR_COMPUTE_SURFACE_COORDFROMADDR_INPUT * pIn,ADDR_COMPUTE_SURFACE_COORDFROMADDR_OUTPUT * pOut) const526 ADDR_E_RETURNCODE Lib::ComputeSurfaceCoordFromAddr(
527     const ADDR_COMPUTE_SURFACE_COORDFROMADDR_INPUT* pIn,    ///< [in] input structure
528     ADDR_COMPUTE_SURFACE_COORDFROMADDR_OUTPUT*      pOut    ///< [out] output structure
529     ) const
530 {
531     ADDR_E_RETURNCODE returnCode = ADDR_OK;
532 
533     if (GetFillSizeFieldsFlags() == TRUE)
534     {
535         if ((pIn->size != sizeof(ADDR_COMPUTE_SURFACE_COORDFROMADDR_INPUT)) ||
536             (pOut->size != sizeof(ADDR_COMPUTE_SURFACE_COORDFROMADDR_OUTPUT)))
537         {
538             returnCode = ADDR_PARAMSIZEMISMATCH;
539         }
540     }
541 
542     if (returnCode == ADDR_OK)
543     {
544         ADDR_TILEINFO tileInfoNull;
545         ADDR_COMPUTE_SURFACE_COORDFROMADDR_INPUT input;
546 
547         if (UseTileIndex(pIn->tileIndex))
548         {
549             input = *pIn;
550             // Use temp tile info for calcalation
551             input.pTileInfo = &tileInfoNull;
552 
553             const ADDR_SURFACE_FLAGS flags = {{0}};
554             UINT_32 numSamples = GetNumFragments(pIn->numSamples, pIn->numFrags);
555 
556             // Try finding a macroModeIndex
557             INT_32 macroModeIndex = HwlComputeMacroModeIndex(input.tileIndex,
558                                                              flags,
559                                                              input.bpp,
560                                                              numSamples,
561                                                              input.pTileInfo,
562                                                              &input.tileMode,
563                                                              &input.tileType);
564 
565             // If macroModeIndex is not needed, then call HwlSetupTileCfg to get tile info
566             if (macroModeIndex == TileIndexNoMacroIndex)
567             {
568                 returnCode = HwlSetupTileCfg(input.bpp, input.tileIndex, macroModeIndex,
569                                              input.pTileInfo, &input.tileMode, &input.tileType);
570             }
571             // If macroModeIndex is invalid, then assert this is not macro tiled
572             else if (macroModeIndex == TileIndexInvalid)
573             {
574                 ADDR_ASSERT(!IsMacroTiled(input.tileMode));
575             }
576 
577             // Change the input structure
578             pIn = &input;
579         }
580 
581         if (returnCode == ADDR_OK)
582         {
583             returnCode = HwlComputeSurfaceCoordFromAddr(pIn, pOut);
584         }
585     }
586 
587     return returnCode;
588 }
589 
590 /**
591 ****************************************************************************************************
592 *   Lib::ComputeSliceTileSwizzle
593 *
594 *   @brief
595 *       Interface function stub of ComputeSliceTileSwizzle.
596 *
597 *   @return
598 *       ADDR_E_RETURNCODE
599 ****************************************************************************************************
600 */
ComputeSliceTileSwizzle(const ADDR_COMPUTE_SLICESWIZZLE_INPUT * pIn,ADDR_COMPUTE_SLICESWIZZLE_OUTPUT * pOut) const601 ADDR_E_RETURNCODE Lib::ComputeSliceTileSwizzle(
602     const ADDR_COMPUTE_SLICESWIZZLE_INPUT*  pIn,    ///< [in] input structure
603     ADDR_COMPUTE_SLICESWIZZLE_OUTPUT*       pOut    ///< [out] output structure
604     ) const
605 {
606     ADDR_E_RETURNCODE returnCode = ADDR_OK;
607 
608     if (GetFillSizeFieldsFlags() == TRUE)
609     {
610         if ((pIn->size != sizeof(ADDR_COMPUTE_SLICESWIZZLE_INPUT)) ||
611             (pOut->size != sizeof(ADDR_COMPUTE_SLICESWIZZLE_OUTPUT)))
612         {
613             returnCode = ADDR_PARAMSIZEMISMATCH;
614         }
615     }
616 
617     if (returnCode == ADDR_OK)
618     {
619         ADDR_TILEINFO tileInfoNull;
620         ADDR_COMPUTE_SLICESWIZZLE_INPUT input;
621 
622         if (UseTileIndex(pIn->tileIndex))
623         {
624             input = *pIn;
625             // Use temp tile info for calcalation
626             input.pTileInfo = &tileInfoNull;
627 
628             returnCode = HwlSetupTileCfg(0, input.tileIndex, input.macroModeIndex,
629                                          input.pTileInfo, &input.tileMode);
630             // Change the input structure
631             pIn = &input;
632         }
633 
634         if (returnCode == ADDR_OK)
635         {
636             returnCode = HwlComputeSliceTileSwizzle(pIn, pOut);
637         }
638     }
639 
640     return returnCode;
641 }
642 
643 /**
644 ****************************************************************************************************
645 *   Lib::ExtractBankPipeSwizzle
646 *
647 *   @brief
648 *       Interface function stub of AddrExtractBankPipeSwizzle.
649 *
650 *   @return
651 *       ADDR_E_RETURNCODE
652 ****************************************************************************************************
653 */
ExtractBankPipeSwizzle(const ADDR_EXTRACT_BANKPIPE_SWIZZLE_INPUT * pIn,ADDR_EXTRACT_BANKPIPE_SWIZZLE_OUTPUT * pOut) const654 ADDR_E_RETURNCODE Lib::ExtractBankPipeSwizzle(
655     const ADDR_EXTRACT_BANKPIPE_SWIZZLE_INPUT*  pIn,    ///< [in] input structure
656     ADDR_EXTRACT_BANKPIPE_SWIZZLE_OUTPUT*       pOut    ///< [out] output structure
657     ) const
658 {
659     ADDR_E_RETURNCODE returnCode = ADDR_OK;
660 
661     if (GetFillSizeFieldsFlags() == TRUE)
662     {
663         if ((pIn->size != sizeof(ADDR_EXTRACT_BANKPIPE_SWIZZLE_INPUT)) ||
664             (pOut->size != sizeof(ADDR_EXTRACT_BANKPIPE_SWIZZLE_OUTPUT)))
665         {
666             returnCode = ADDR_PARAMSIZEMISMATCH;
667         }
668     }
669 
670     if (returnCode == ADDR_OK)
671     {
672         ADDR_TILEINFO tileInfoNull;
673         ADDR_EXTRACT_BANKPIPE_SWIZZLE_INPUT input;
674 
675         if (UseTileIndex(pIn->tileIndex))
676         {
677             input = *pIn;
678             // Use temp tile info for calcalation
679             input.pTileInfo = &tileInfoNull;
680 
681             returnCode = HwlSetupTileCfg(0, input.tileIndex, input.macroModeIndex, input.pTileInfo);
682             // Change the input structure
683             pIn = &input;
684         }
685 
686         if (returnCode == ADDR_OK)
687         {
688             returnCode = HwlExtractBankPipeSwizzle(pIn, pOut);
689         }
690     }
691 
692     return returnCode;
693 }
694 
695 /**
696 ****************************************************************************************************
697 *   Lib::CombineBankPipeSwizzle
698 *
699 *   @brief
700 *       Interface function stub of AddrCombineBankPipeSwizzle.
701 *
702 *   @return
703 *       ADDR_E_RETURNCODE
704 ****************************************************************************************************
705 */
CombineBankPipeSwizzle(const ADDR_COMBINE_BANKPIPE_SWIZZLE_INPUT * pIn,ADDR_COMBINE_BANKPIPE_SWIZZLE_OUTPUT * pOut) const706 ADDR_E_RETURNCODE Lib::CombineBankPipeSwizzle(
707     const ADDR_COMBINE_BANKPIPE_SWIZZLE_INPUT*  pIn,    ///< [in] input structure
708     ADDR_COMBINE_BANKPIPE_SWIZZLE_OUTPUT*       pOut    ///< [out] output structure
709     ) const
710 {
711     ADDR_E_RETURNCODE returnCode = ADDR_OK;
712 
713     if (GetFillSizeFieldsFlags() == TRUE)
714     {
715         if ((pIn->size != sizeof(ADDR_COMPUTE_FMASK_INFO_INPUT)) ||
716             (pOut->size != sizeof(ADDR_COMPUTE_FMASK_INFO_OUTPUT)))
717         {
718             returnCode = ADDR_PARAMSIZEMISMATCH;
719         }
720     }
721 
722     if (returnCode == ADDR_OK)
723     {
724         ADDR_TILEINFO tileInfoNull;
725         ADDR_COMBINE_BANKPIPE_SWIZZLE_INPUT input;
726 
727         if (UseTileIndex(pIn->tileIndex))
728         {
729             input = *pIn;
730             // Use temp tile info for calcalation
731             input.pTileInfo = &tileInfoNull;
732 
733             returnCode = HwlSetupTileCfg(0, input.tileIndex, input.macroModeIndex, input.pTileInfo);
734             // Change the input structure
735             pIn = &input;
736         }
737 
738         if (returnCode == ADDR_OK)
739         {
740             returnCode = HwlCombineBankPipeSwizzle(pIn->bankSwizzle,
741                                                    pIn->pipeSwizzle,
742                                                    pIn->pTileInfo,
743                                                    pIn->baseAddr,
744                                                    &pOut->tileSwizzle);
745         }
746     }
747 
748     return returnCode;
749 }
750 
751 /**
752 ****************************************************************************************************
753 *   Lib::ComputeBaseSwizzle
754 *
755 *   @brief
756 *       Interface function stub of AddrCompueBaseSwizzle.
757 *   @return
758 *       ADDR_E_RETURNCODE
759 ****************************************************************************************************
760 */
ComputeBaseSwizzle(const ADDR_COMPUTE_BASE_SWIZZLE_INPUT * pIn,ADDR_COMPUTE_BASE_SWIZZLE_OUTPUT * pOut) const761 ADDR_E_RETURNCODE Lib::ComputeBaseSwizzle(
762     const ADDR_COMPUTE_BASE_SWIZZLE_INPUT*  pIn,
763     ADDR_COMPUTE_BASE_SWIZZLE_OUTPUT* pOut) const
764 {
765     ADDR_E_RETURNCODE returnCode = ADDR_OK;
766 
767     if (GetFillSizeFieldsFlags() == TRUE)
768     {
769         if ((pIn->size != sizeof(ADDR_COMPUTE_BASE_SWIZZLE_INPUT)) ||
770             (pOut->size != sizeof(ADDR_COMPUTE_BASE_SWIZZLE_OUTPUT)))
771         {
772             returnCode = ADDR_PARAMSIZEMISMATCH;
773         }
774     }
775 
776     if (returnCode == ADDR_OK)
777     {
778         ADDR_TILEINFO tileInfoNull;
779         ADDR_COMPUTE_BASE_SWIZZLE_INPUT input;
780 
781         if (UseTileIndex(pIn->tileIndex))
782         {
783             input = *pIn;
784             // Use temp tile info for calcalation
785             input.pTileInfo = &tileInfoNull;
786 
787             returnCode = HwlSetupTileCfg(0, input.tileIndex, input.macroModeIndex, input.pTileInfo);
788             // Change the input structure
789             pIn = &input;
790         }
791 
792         if (returnCode == ADDR_OK)
793         {
794             if (IsMacroTiled(pIn->tileMode))
795             {
796                 returnCode = HwlComputeBaseSwizzle(pIn, pOut);
797             }
798             else
799             {
800                 pOut->tileSwizzle = 0;
801             }
802         }
803     }
804 
805     return returnCode;
806 }
807 
808 /**
809 ****************************************************************************************************
810 *   Lib::ComputeFmaskInfo
811 *
812 *   @brief
813 *       Interface function stub of ComputeFmaskInfo.
814 *
815 *   @return
816 *       ADDR_E_RETURNCODE
817 ****************************************************************************************************
818 */
ComputeFmaskInfo(const ADDR_COMPUTE_FMASK_INFO_INPUT * pIn,ADDR_COMPUTE_FMASK_INFO_OUTPUT * pOut)819 ADDR_E_RETURNCODE Lib::ComputeFmaskInfo(
820     const ADDR_COMPUTE_FMASK_INFO_INPUT*    pIn,    ///< [in] input structure
821     ADDR_COMPUTE_FMASK_INFO_OUTPUT*         pOut    ///< [out] output structure
822     )
823 {
824     ADDR_E_RETURNCODE returnCode = ADDR_OK;
825 
826     if (GetFillSizeFieldsFlags() == TRUE)
827     {
828         if ((pIn->size != sizeof(ADDR_COMPUTE_FMASK_INFO_INPUT)) ||
829             (pOut->size != sizeof(ADDR_COMPUTE_FMASK_INFO_OUTPUT)))
830         {
831             returnCode = ADDR_PARAMSIZEMISMATCH;
832         }
833     }
834 
835     // No thick MSAA
836     if (Thickness(pIn->tileMode) > 1)
837     {
838         returnCode = ADDR_INVALIDPARAMS;
839     }
840 
841     if (returnCode == ADDR_OK)
842     {
843         ADDR_TILEINFO tileInfoNull;
844         ADDR_COMPUTE_FMASK_INFO_INPUT input;
845 
846         if (UseTileIndex(pIn->tileIndex))
847         {
848             input = *pIn;
849 
850             if (pOut->pTileInfo)
851             {
852                 // Use temp tile info for calcalation
853                 input.pTileInfo = pOut->pTileInfo;
854             }
855             else
856             {
857                 input.pTileInfo = &tileInfoNull;
858             }
859 
860             ADDR_SURFACE_FLAGS flags = {{0}};
861             flags.fmask = 1;
862 
863             // Try finding a macroModeIndex
864             INT_32 macroModeIndex = HwlComputeMacroModeIndex(pIn->tileIndex,
865                                                              flags,
866                                                              HwlComputeFmaskBits(pIn, NULL),
867                                                              pIn->numSamples,
868                                                              input.pTileInfo,
869                                                              &input.tileMode);
870 
871             // If macroModeIndex is not needed, then call HwlSetupTileCfg to get tile info
872             if (macroModeIndex == TileIndexNoMacroIndex)
873             {
874                 returnCode = HwlSetupTileCfg(0, input.tileIndex, macroModeIndex,
875                                              input.pTileInfo, &input.tileMode);
876             }
877 
878             ADDR_ASSERT(macroModeIndex != TileIndexInvalid);
879 
880             // Change the input structure
881             pIn = &input;
882         }
883 
884         if (returnCode == ADDR_OK)
885         {
886             if (pIn->numSamples > 1)
887             {
888                 returnCode = HwlComputeFmaskInfo(pIn, pOut);
889             }
890             else
891             {
892                 memset(pOut, 0, sizeof(ADDR_COMPUTE_FMASK_INFO_OUTPUT));
893 
894                 returnCode = ADDR_INVALIDPARAMS;
895             }
896         }
897     }
898 
899     ValidBaseAlignments(pOut->baseAlign);
900 
901     return returnCode;
902 }
903 
904 /**
905 ****************************************************************************************************
906 *   Lib::ComputeFmaskAddrFromCoord
907 *
908 *   @brief
909 *       Interface function stub of ComputeFmaskAddrFromCoord.
910 *
911 *   @return
912 *       ADDR_E_RETURNCODE
913 ****************************************************************************************************
914 */
ComputeFmaskAddrFromCoord(const ADDR_COMPUTE_FMASK_ADDRFROMCOORD_INPUT * pIn,ADDR_COMPUTE_FMASK_ADDRFROMCOORD_OUTPUT * pOut) const915 ADDR_E_RETURNCODE Lib::ComputeFmaskAddrFromCoord(
916     const ADDR_COMPUTE_FMASK_ADDRFROMCOORD_INPUT*   pIn,    ///< [in] input structure
917     ADDR_COMPUTE_FMASK_ADDRFROMCOORD_OUTPUT*        pOut    ///< [out] output structure
918     ) const
919 {
920     ADDR_E_RETURNCODE returnCode = ADDR_OK;
921 
922     if (GetFillSizeFieldsFlags() == TRUE)
923     {
924         if ((pIn->size != sizeof(ADDR_COMPUTE_FMASK_ADDRFROMCOORD_INPUT)) ||
925             (pOut->size != sizeof(ADDR_COMPUTE_FMASK_ADDRFROMCOORD_OUTPUT)))
926         {
927             returnCode = ADDR_PARAMSIZEMISMATCH;
928         }
929     }
930 
931     if (returnCode == ADDR_OK)
932     {
933         ADDR_ASSERT(pIn->numSamples > 1);
934 
935         if (pIn->numSamples > 1)
936         {
937             returnCode = HwlComputeFmaskAddrFromCoord(pIn, pOut);
938         }
939         else
940         {
941             returnCode = ADDR_INVALIDPARAMS;
942         }
943     }
944 
945     return returnCode;
946 }
947 
948 /**
949 ****************************************************************************************************
950 *   Lib::ComputeFmaskCoordFromAddr
951 *
952 *   @brief
953 *       Interface function stub of ComputeFmaskAddrFromCoord.
954 *
955 *   @return
956 *       ADDR_E_RETURNCODE
957 ****************************************************************************************************
958 */
ComputeFmaskCoordFromAddr(const ADDR_COMPUTE_FMASK_COORDFROMADDR_INPUT * pIn,ADDR_COMPUTE_FMASK_COORDFROMADDR_OUTPUT * pOut) const959 ADDR_E_RETURNCODE Lib::ComputeFmaskCoordFromAddr(
960     const ADDR_COMPUTE_FMASK_COORDFROMADDR_INPUT*  pIn,     ///< [in] input structure
961     ADDR_COMPUTE_FMASK_COORDFROMADDR_OUTPUT* pOut           ///< [out] output structure
962     ) const
963 {
964     ADDR_E_RETURNCODE returnCode = ADDR_OK;
965 
966     if (GetFillSizeFieldsFlags() == TRUE)
967     {
968         if ((pIn->size != sizeof(ADDR_COMPUTE_FMASK_COORDFROMADDR_INPUT)) ||
969             (pOut->size != sizeof(ADDR_COMPUTE_FMASK_COORDFROMADDR_OUTPUT)))
970         {
971             returnCode = ADDR_PARAMSIZEMISMATCH;
972         }
973     }
974 
975     if (returnCode == ADDR_OK)
976     {
977         ADDR_ASSERT(pIn->numSamples > 1);
978 
979         if (pIn->numSamples > 1)
980         {
981             returnCode = HwlComputeFmaskCoordFromAddr(pIn, pOut);
982         }
983         else
984         {
985             returnCode = ADDR_INVALIDPARAMS;
986         }
987     }
988 
989     return returnCode;
990 }
991 
992 /**
993 ****************************************************************************************************
994 *   Lib::ConvertTileInfoToHW
995 *
996 *   @brief
997 *       Convert tile info from real value to HW register value in HW layer
998 *
999 *   @return
1000 *       ADDR_E_RETURNCODE
1001 ****************************************************************************************************
1002 */
ConvertTileInfoToHW(const ADDR_CONVERT_TILEINFOTOHW_INPUT * pIn,ADDR_CONVERT_TILEINFOTOHW_OUTPUT * pOut) const1003 ADDR_E_RETURNCODE Lib::ConvertTileInfoToHW(
1004     const ADDR_CONVERT_TILEINFOTOHW_INPUT* pIn, ///< [in] input structure
1005     ADDR_CONVERT_TILEINFOTOHW_OUTPUT* pOut      ///< [out] output structure
1006     ) const
1007 {
1008     ADDR_E_RETURNCODE returnCode = ADDR_OK;
1009 
1010     if (GetFillSizeFieldsFlags() == TRUE)
1011     {
1012         if ((pIn->size != sizeof(ADDR_CONVERT_TILEINFOTOHW_INPUT)) ||
1013             (pOut->size != sizeof(ADDR_CONVERT_TILEINFOTOHW_OUTPUT)))
1014         {
1015             returnCode = ADDR_PARAMSIZEMISMATCH;
1016         }
1017     }
1018 
1019     if (returnCode == ADDR_OK)
1020     {
1021         ADDR_TILEINFO tileInfoNull;
1022         ADDR_CONVERT_TILEINFOTOHW_INPUT input;
1023         // if pIn->reverse is TRUE, indices are ignored
1024         if (pIn->reverse == FALSE && UseTileIndex(pIn->tileIndex))
1025         {
1026             input = *pIn;
1027             input.pTileInfo = &tileInfoNull;
1028 
1029             returnCode = HwlSetupTileCfg(input.bpp, input.tileIndex,
1030                                          input.macroModeIndex, input.pTileInfo);
1031 
1032             pIn = &input;
1033         }
1034 
1035         if (returnCode == ADDR_OK)
1036         {
1037             returnCode = HwlConvertTileInfoToHW(pIn, pOut);
1038         }
1039     }
1040 
1041     return returnCode;
1042 }
1043 
1044 /**
1045 ****************************************************************************************************
1046 *   Lib::ConvertTileIndex
1047 *
1048 *   @brief
1049 *       Convert tile index to tile mode/type/info
1050 *
1051 *   @return
1052 *       ADDR_E_RETURNCODE
1053 ****************************************************************************************************
1054 */
ConvertTileIndex(const ADDR_CONVERT_TILEINDEX_INPUT * pIn,ADDR_CONVERT_TILEINDEX_OUTPUT * pOut) const1055 ADDR_E_RETURNCODE Lib::ConvertTileIndex(
1056     const ADDR_CONVERT_TILEINDEX_INPUT* pIn, ///< [in] input structure
1057     ADDR_CONVERT_TILEINDEX_OUTPUT* pOut      ///< [out] output structure
1058     ) const
1059 {
1060     ADDR_E_RETURNCODE returnCode = ADDR_OK;
1061 
1062     if (GetFillSizeFieldsFlags() == TRUE)
1063     {
1064         if ((pIn->size != sizeof(ADDR_CONVERT_TILEINDEX_INPUT)) ||
1065             (pOut->size != sizeof(ADDR_CONVERT_TILEINDEX_OUTPUT)))
1066         {
1067             returnCode = ADDR_PARAMSIZEMISMATCH;
1068         }
1069     }
1070 
1071     if (returnCode == ADDR_OK)
1072     {
1073 
1074         returnCode = HwlSetupTileCfg(pIn->bpp, pIn->tileIndex, pIn->macroModeIndex,
1075                                      pOut->pTileInfo, &pOut->tileMode, &pOut->tileType);
1076 
1077         if (returnCode == ADDR_OK && pIn->tileInfoHw)
1078         {
1079             ADDR_CONVERT_TILEINFOTOHW_INPUT hwInput = {0};
1080             ADDR_CONVERT_TILEINFOTOHW_OUTPUT hwOutput = {0};
1081 
1082             hwInput.pTileInfo = pOut->pTileInfo;
1083             hwInput.tileIndex = -1;
1084             hwOutput.pTileInfo = pOut->pTileInfo;
1085 
1086             returnCode = HwlConvertTileInfoToHW(&hwInput, &hwOutput);
1087         }
1088     }
1089 
1090     return returnCode;
1091 }
1092 
1093 /**
1094 ****************************************************************************************************
1095 *   Lib::GetMacroModeIndex
1096 *
1097 *   @brief
1098 *       Get macro mode index based on input info
1099 *
1100 *   @return
1101 *       ADDR_E_RETURNCODE
1102 ****************************************************************************************************
1103 */
GetMacroModeIndex(const ADDR_GET_MACROMODEINDEX_INPUT * pIn,ADDR_GET_MACROMODEINDEX_OUTPUT * pOut) const1104 ADDR_E_RETURNCODE Lib::GetMacroModeIndex(
1105     const ADDR_GET_MACROMODEINDEX_INPUT* pIn, ///< [in] input structure
1106     ADDR_GET_MACROMODEINDEX_OUTPUT*      pOut ///< [out] output structure
1107     ) const
1108 {
1109     ADDR_E_RETURNCODE returnCode = ADDR_OK;
1110 
1111     if (GetFillSizeFieldsFlags())
1112     {
1113         if ((pIn->size != sizeof(ADDR_GET_MACROMODEINDEX_INPUT)) ||
1114             (pOut->size != sizeof(ADDR_GET_MACROMODEINDEX_OUTPUT)))
1115         {
1116             returnCode = ADDR_PARAMSIZEMISMATCH;
1117         }
1118     }
1119 
1120     if (returnCode == ADDR_OK)
1121     {
1122         ADDR_TILEINFO tileInfo = {0};
1123         pOut->macroModeIndex = HwlComputeMacroModeIndex(pIn->tileIndex, pIn->flags, pIn->bpp,
1124                                                         pIn->numFrags, &tileInfo);
1125     }
1126 
1127     return returnCode;
1128 }
1129 
1130 /**
1131 ****************************************************************************************************
1132 *   Lib::ConvertTileIndex1
1133 *
1134 *   @brief
1135 *       Convert tile index to tile mode/type/info
1136 *
1137 *   @return
1138 *       ADDR_E_RETURNCODE
1139 ****************************************************************************************************
1140 */
ConvertTileIndex1(const ADDR_CONVERT_TILEINDEX1_INPUT * pIn,ADDR_CONVERT_TILEINDEX_OUTPUT * pOut) const1141 ADDR_E_RETURNCODE Lib::ConvertTileIndex1(
1142     const ADDR_CONVERT_TILEINDEX1_INPUT* pIn,   ///< [in] input structure
1143     ADDR_CONVERT_TILEINDEX_OUTPUT* pOut         ///< [out] output structure
1144     ) const
1145 {
1146     ADDR_E_RETURNCODE returnCode = ADDR_OK;
1147 
1148     if (GetFillSizeFieldsFlags() == TRUE)
1149     {
1150         if ((pIn->size != sizeof(ADDR_CONVERT_TILEINDEX1_INPUT)) ||
1151             (pOut->size != sizeof(ADDR_CONVERT_TILEINDEX_OUTPUT)))
1152         {
1153             returnCode = ADDR_PARAMSIZEMISMATCH;
1154         }
1155     }
1156 
1157     if (returnCode == ADDR_OK)
1158     {
1159         ADDR_SURFACE_FLAGS flags = {{0}};
1160 
1161         HwlComputeMacroModeIndex(pIn->tileIndex, flags, pIn->bpp, pIn->numSamples,
1162                                  pOut->pTileInfo, &pOut->tileMode, &pOut->tileType);
1163 
1164         if (pIn->tileInfoHw)
1165         {
1166             ADDR_CONVERT_TILEINFOTOHW_INPUT hwInput = {0};
1167             ADDR_CONVERT_TILEINFOTOHW_OUTPUT hwOutput = {0};
1168 
1169             hwInput.pTileInfo = pOut->pTileInfo;
1170             hwInput.tileIndex = -1;
1171             hwOutput.pTileInfo = pOut->pTileInfo;
1172 
1173             returnCode = HwlConvertTileInfoToHW(&hwInput, &hwOutput);
1174         }
1175     }
1176 
1177     return returnCode;
1178 }
1179 
1180 /**
1181 ****************************************************************************************************
1182 *   Lib::GetTileIndex
1183 *
1184 *   @brief
1185 *       Get tile index from tile mode/type/info
1186 *
1187 *   @return
1188 *       ADDR_E_RETURNCODE
1189 ****************************************************************************************************
1190 */
GetTileIndex(const ADDR_GET_TILEINDEX_INPUT * pIn,ADDR_GET_TILEINDEX_OUTPUT * pOut) const1191 ADDR_E_RETURNCODE Lib::GetTileIndex(
1192     const ADDR_GET_TILEINDEX_INPUT* pIn, ///< [in] input structure
1193     ADDR_GET_TILEINDEX_OUTPUT* pOut      ///< [out] output structure
1194     ) const
1195 {
1196     ADDR_E_RETURNCODE returnCode = ADDR_OK;
1197 
1198     if (GetFillSizeFieldsFlags() == TRUE)
1199     {
1200         if ((pIn->size != sizeof(ADDR_GET_TILEINDEX_INPUT)) ||
1201             (pOut->size != sizeof(ADDR_GET_TILEINDEX_OUTPUT)))
1202         {
1203             returnCode = ADDR_PARAMSIZEMISMATCH;
1204         }
1205     }
1206 
1207     if (returnCode == ADDR_OK)
1208     {
1209         returnCode = HwlGetTileIndex(pIn, pOut);
1210     }
1211 
1212     return returnCode;
1213 }
1214 
1215 /**
1216 ****************************************************************************************************
1217 *   Lib::Thickness
1218 *
1219 *   @brief
1220 *       Get tile mode thickness
1221 *
1222 *   @return
1223 *       Tile mode thickness
1224 ****************************************************************************************************
1225 */
Thickness(AddrTileMode tileMode)1226 UINT_32 Lib::Thickness(
1227     AddrTileMode tileMode)    ///< [in] tile mode
1228 {
1229     return ModeFlags[tileMode].thickness;
1230 }
1231 
1232 
1233 
1234 ////////////////////////////////////////////////////////////////////////////////////////////////////
1235 //                               CMASK/HTILE
1236 ////////////////////////////////////////////////////////////////////////////////////////////////////
1237 
1238 /**
1239 ****************************************************************************************************
1240 *   Lib::ComputeHtileInfo
1241 *
1242 *   @brief
1243 *       Interface function stub of AddrComputeHtilenfo
1244 *
1245 *   @return
1246 *       ADDR_E_RETURNCODE
1247 ****************************************************************************************************
1248 */
ComputeHtileInfo(const ADDR_COMPUTE_HTILE_INFO_INPUT * pIn,ADDR_COMPUTE_HTILE_INFO_OUTPUT * pOut) const1249 ADDR_E_RETURNCODE Lib::ComputeHtileInfo(
1250     const ADDR_COMPUTE_HTILE_INFO_INPUT*    pIn,    ///< [in] input structure
1251     ADDR_COMPUTE_HTILE_INFO_OUTPUT*         pOut    ///< [out] output structure
1252     ) const
1253 {
1254     ADDR_E_RETURNCODE returnCode = ADDR_OK;
1255 
1256     BOOL_32 isWidth8  = (pIn->blockWidth == 8) ? TRUE : FALSE;
1257     BOOL_32 isHeight8 = (pIn->blockHeight == 8) ? TRUE : FALSE;
1258 
1259     if (GetFillSizeFieldsFlags() == TRUE)
1260     {
1261         if ((pIn->size != sizeof(ADDR_COMPUTE_HTILE_INFO_INPUT)) ||
1262             (pOut->size != sizeof(ADDR_COMPUTE_HTILE_INFO_OUTPUT)))
1263         {
1264             returnCode = ADDR_PARAMSIZEMISMATCH;
1265         }
1266     }
1267 
1268     if (returnCode == ADDR_OK)
1269     {
1270         ADDR_TILEINFO tileInfoNull;
1271         ADDR_COMPUTE_HTILE_INFO_INPUT input;
1272 
1273         if (UseTileIndex(pIn->tileIndex))
1274         {
1275             input = *pIn;
1276             // Use temp tile info for calcalation
1277             input.pTileInfo = &tileInfoNull;
1278 
1279             returnCode = HwlSetupTileCfg(0, input.tileIndex, input.macroModeIndex, input.pTileInfo);
1280 
1281             // Change the input structure
1282             pIn = &input;
1283         }
1284 
1285         if (returnCode == ADDR_OK)
1286         {
1287             if (pIn->flags.tcCompatible)
1288             {
1289                 const UINT_32 sliceSize = pIn->pitch * pIn->height * 4 / (8 * 8);
1290                 const UINT_32 align     = HwlGetPipes(pIn->pTileInfo) * pIn->pTileInfo->banks * m_pipeInterleaveBytes;
1291 
1292                 if (pIn->numSlices > 1)
1293                 {
1294                     const UINT_32 surfBytes = (sliceSize * pIn->numSlices);
1295 
1296                     pOut->sliceSize        = sliceSize;
1297                     pOut->htileBytes       = pIn->flags.skipTcCompatSizeAlign ?
1298                                              surfBytes : PowTwoAlign(surfBytes, align);
1299                     pOut->sliceInterleaved = ((sliceSize % align) != 0) ? TRUE : FALSE;
1300                 }
1301                 else
1302                 {
1303                     pOut->sliceSize        = pIn->flags.skipTcCompatSizeAlign ?
1304                                              sliceSize : PowTwoAlign(sliceSize, align);
1305                     pOut->htileBytes       = pOut->sliceSize;
1306                     pOut->sliceInterleaved = FALSE;
1307                 }
1308 
1309                 pOut->nextMipLevelCompressible = ((sliceSize % align) == 0) ? TRUE : FALSE;
1310 
1311                 pOut->pitch       = pIn->pitch;
1312                 pOut->height      = pIn->height;
1313                 pOut->baseAlign   = align;
1314                 pOut->macroWidth  = 0;
1315                 pOut->macroHeight = 0;
1316                 pOut->bpp         = 32;
1317             }
1318             else
1319             {
1320                 pOut->bpp = ComputeHtileInfo(pIn->flags,
1321                                              pIn->pitch,
1322                                              pIn->height,
1323                                              pIn->numSlices,
1324                                              pIn->isLinear,
1325                                              isWidth8,
1326                                              isHeight8,
1327                                              pIn->pTileInfo,
1328                                              &pOut->pitch,
1329                                              &pOut->height,
1330                                              &pOut->htileBytes,
1331                                              &pOut->macroWidth,
1332                                              &pOut->macroHeight,
1333                                              &pOut->sliceSize,
1334                                              &pOut->baseAlign);
1335             }
1336         }
1337     }
1338 
1339     ValidMetaBaseAlignments(pOut->baseAlign);
1340 
1341     return returnCode;
1342 }
1343 
1344 /**
1345 ****************************************************************************************************
1346 *   Lib::ComputeCmaskInfo
1347 *
1348 *   @brief
1349 *       Interface function stub of AddrComputeCmaskInfo
1350 *
1351 *   @return
1352 *       ADDR_E_RETURNCODE
1353 ****************************************************************************************************
1354 */
ComputeCmaskInfo(const ADDR_COMPUTE_CMASK_INFO_INPUT * pIn,ADDR_COMPUTE_CMASK_INFO_OUTPUT * pOut) const1355 ADDR_E_RETURNCODE Lib::ComputeCmaskInfo(
1356     const ADDR_COMPUTE_CMASK_INFO_INPUT*    pIn,    ///< [in] input structure
1357     ADDR_COMPUTE_CMASK_INFO_OUTPUT*         pOut    ///< [out] output structure
1358     ) const
1359 {
1360     ADDR_E_RETURNCODE returnCode = ADDR_OK;
1361 
1362     if (GetFillSizeFieldsFlags() == TRUE)
1363     {
1364         if ((pIn->size != sizeof(ADDR_COMPUTE_CMASK_INFO_INPUT)) ||
1365             (pOut->size != sizeof(ADDR_COMPUTE_CMASK_INFO_OUTPUT)))
1366         {
1367             returnCode = ADDR_PARAMSIZEMISMATCH;
1368         }
1369     }
1370 
1371     if (returnCode == ADDR_OK)
1372     {
1373         ADDR_TILEINFO tileInfoNull;
1374         ADDR_COMPUTE_CMASK_INFO_INPUT input;
1375 
1376         if (UseTileIndex(pIn->tileIndex))
1377         {
1378             input = *pIn;
1379             // Use temp tile info for calcalation
1380             input.pTileInfo = &tileInfoNull;
1381 
1382             returnCode = HwlSetupTileCfg(0, input.tileIndex, input.macroModeIndex, input.pTileInfo);
1383 
1384             // Change the input structure
1385             pIn = &input;
1386         }
1387 
1388         if (returnCode == ADDR_OK)
1389         {
1390             returnCode = ComputeCmaskInfo(pIn->flags,
1391                                           pIn->pitch,
1392                                           pIn->height,
1393                                           pIn->numSlices,
1394                                           pIn->isLinear,
1395                                           pIn->pTileInfo,
1396                                           &pOut->pitch,
1397                                           &pOut->height,
1398                                           &pOut->cmaskBytes,
1399                                           &pOut->macroWidth,
1400                                           &pOut->macroHeight,
1401                                           &pOut->sliceSize,
1402                                           &pOut->baseAlign,
1403                                           &pOut->blockMax);
1404         }
1405     }
1406 
1407     ValidMetaBaseAlignments(pOut->baseAlign);
1408 
1409     return returnCode;
1410 }
1411 
1412 /**
1413 ****************************************************************************************************
1414 *   Lib::ComputeDccInfo
1415 *
1416 *   @brief
1417 *       Interface function to compute DCC key info
1418 *
1419 *   @return
1420 *       return code of HwlComputeDccInfo
1421 ****************************************************************************************************
1422 */
ComputeDccInfo(const ADDR_COMPUTE_DCCINFO_INPUT * pIn,ADDR_COMPUTE_DCCINFO_OUTPUT * pOut) const1423 ADDR_E_RETURNCODE Lib::ComputeDccInfo(
1424     const ADDR_COMPUTE_DCCINFO_INPUT*    pIn,    ///< [in] input structure
1425     ADDR_COMPUTE_DCCINFO_OUTPUT*         pOut    ///< [out] output structure
1426     ) const
1427 {
1428     ADDR_E_RETURNCODE ret = ADDR_OK;
1429 
1430     if (GetFillSizeFieldsFlags() == TRUE)
1431     {
1432         if ((pIn->size != sizeof(ADDR_COMPUTE_DCCINFO_INPUT)) ||
1433             (pOut->size != sizeof(ADDR_COMPUTE_DCCINFO_OUTPUT)))
1434         {
1435             ret = ADDR_PARAMSIZEMISMATCH;
1436         }
1437     }
1438 
1439     if (ret == ADDR_OK)
1440     {
1441         ADDR_COMPUTE_DCCINFO_INPUT input;
1442 
1443         if (UseTileIndex(pIn->tileIndex))
1444         {
1445             input = *pIn;
1446 
1447             ret = HwlSetupTileCfg(input.bpp, input.tileIndex, input.macroModeIndex,
1448                                   &input.tileInfo, &input.tileMode);
1449 
1450             pIn = &input;
1451         }
1452 
1453         if (ret == ADDR_OK)
1454         {
1455             ret = HwlComputeDccInfo(pIn, pOut);
1456 
1457             ValidMetaBaseAlignments(pOut->dccRamBaseAlign);
1458         }
1459     }
1460 
1461     return ret;
1462 }
1463 
1464 /**
1465 ****************************************************************************************************
1466 *   Lib::ComputeHtileAddrFromCoord
1467 *
1468 *   @brief
1469 *       Interface function stub of AddrComputeHtileAddrFromCoord
1470 *
1471 *   @return
1472 *       ADDR_E_RETURNCODE
1473 ****************************************************************************************************
1474 */
ComputeHtileAddrFromCoord(const ADDR_COMPUTE_HTILE_ADDRFROMCOORD_INPUT * pIn,ADDR_COMPUTE_HTILE_ADDRFROMCOORD_OUTPUT * pOut) const1475 ADDR_E_RETURNCODE Lib::ComputeHtileAddrFromCoord(
1476     const ADDR_COMPUTE_HTILE_ADDRFROMCOORD_INPUT*   pIn,    ///< [in] input structure
1477     ADDR_COMPUTE_HTILE_ADDRFROMCOORD_OUTPUT*        pOut    ///< [out] output structure
1478     ) const
1479 {
1480     ADDR_E_RETURNCODE returnCode = ADDR_OK;
1481 
1482     BOOL_32 isWidth8  = (pIn->blockWidth == 8) ? TRUE : FALSE;
1483     BOOL_32 isHeight8 = (pIn->blockHeight == 8) ? TRUE : FALSE;
1484 
1485     if (GetFillSizeFieldsFlags() == TRUE)
1486     {
1487         if ((pIn->size != sizeof(ADDR_COMPUTE_HTILE_ADDRFROMCOORD_INPUT)) ||
1488             (pOut->size != sizeof(ADDR_COMPUTE_HTILE_ADDRFROMCOORD_OUTPUT)))
1489         {
1490             returnCode = ADDR_PARAMSIZEMISMATCH;
1491         }
1492     }
1493 
1494     if (returnCode == ADDR_OK)
1495     {
1496         ADDR_TILEINFO tileInfoNull;
1497         ADDR_COMPUTE_HTILE_ADDRFROMCOORD_INPUT input;
1498 
1499         if (UseTileIndex(pIn->tileIndex))
1500         {
1501             input = *pIn;
1502             // Use temp tile info for calcalation
1503             input.pTileInfo = &tileInfoNull;
1504 
1505             returnCode = HwlSetupTileCfg(0, input.tileIndex, input.macroModeIndex, input.pTileInfo);
1506 
1507             // Change the input structure
1508             pIn = &input;
1509         }
1510 
1511         if (returnCode == ADDR_OK)
1512         {
1513             if (pIn->flags.tcCompatible)
1514             {
1515                 HwlComputeHtileAddrFromCoord(pIn, pOut);
1516             }
1517             else
1518             {
1519                 pOut->addr = HwlComputeXmaskAddrFromCoord(pIn->pitch,
1520                                                           pIn->height,
1521                                                           pIn->x,
1522                                                           pIn->y,
1523                                                           pIn->slice,
1524                                                           pIn->numSlices,
1525                                                           1,
1526                                                           pIn->isLinear,
1527                                                           isWidth8,
1528                                                           isHeight8,
1529                                                           pIn->pTileInfo,
1530                                                           &pOut->bitPosition);
1531             }
1532         }
1533     }
1534 
1535     return returnCode;
1536 
1537 }
1538 
1539 /**
1540 ****************************************************************************************************
1541 *   Lib::ComputeHtileCoordFromAddr
1542 *
1543 *   @brief
1544 *       Interface function stub of AddrComputeHtileCoordFromAddr
1545 *
1546 *   @return
1547 *       ADDR_E_RETURNCODE
1548 ****************************************************************************************************
1549 */
ComputeHtileCoordFromAddr(const ADDR_COMPUTE_HTILE_COORDFROMADDR_INPUT * pIn,ADDR_COMPUTE_HTILE_COORDFROMADDR_OUTPUT * pOut) const1550 ADDR_E_RETURNCODE Lib::ComputeHtileCoordFromAddr(
1551     const ADDR_COMPUTE_HTILE_COORDFROMADDR_INPUT*   pIn,    ///< [in] input structure
1552     ADDR_COMPUTE_HTILE_COORDFROMADDR_OUTPUT*        pOut    ///< [out] output structure
1553     ) const
1554 {
1555     ADDR_E_RETURNCODE returnCode = ADDR_OK;
1556 
1557     BOOL_32 isWidth8  = (pIn->blockWidth == 8) ? TRUE : FALSE;
1558     BOOL_32 isHeight8 = (pIn->blockHeight == 8) ? TRUE : FALSE;
1559 
1560     if (GetFillSizeFieldsFlags() == TRUE)
1561     {
1562         if ((pIn->size != sizeof(ADDR_COMPUTE_HTILE_COORDFROMADDR_INPUT)) ||
1563             (pOut->size != sizeof(ADDR_COMPUTE_HTILE_COORDFROMADDR_OUTPUT)))
1564         {
1565             returnCode = ADDR_PARAMSIZEMISMATCH;
1566         }
1567     }
1568 
1569     if (returnCode == ADDR_OK)
1570     {
1571         ADDR_TILEINFO tileInfoNull;
1572         ADDR_COMPUTE_HTILE_COORDFROMADDR_INPUT input;
1573 
1574         if (UseTileIndex(pIn->tileIndex))
1575         {
1576             input = *pIn;
1577             // Use temp tile info for calcalation
1578             input.pTileInfo = &tileInfoNull;
1579 
1580             returnCode = HwlSetupTileCfg(0, input.tileIndex, input.macroModeIndex, input.pTileInfo);
1581 
1582             // Change the input structure
1583             pIn = &input;
1584         }
1585 
1586         if (returnCode == ADDR_OK)
1587         {
1588             HwlComputeXmaskCoordFromAddr(pIn->addr,
1589                                          pIn->bitPosition,
1590                                          pIn->pitch,
1591                                          pIn->height,
1592                                          pIn->numSlices,
1593                                          1,
1594                                          pIn->isLinear,
1595                                          isWidth8,
1596                                          isHeight8,
1597                                          pIn->pTileInfo,
1598                                          &pOut->x,
1599                                          &pOut->y,
1600                                          &pOut->slice);
1601         }
1602     }
1603 
1604     return returnCode;
1605 }
1606 
1607 /**
1608 ****************************************************************************************************
1609 *   Lib::ComputeCmaskAddrFromCoord
1610 *
1611 *   @brief
1612 *       Interface function stub of AddrComputeCmaskAddrFromCoord
1613 *
1614 *   @return
1615 *       ADDR_E_RETURNCODE
1616 ****************************************************************************************************
1617 */
ComputeCmaskAddrFromCoord(const ADDR_COMPUTE_CMASK_ADDRFROMCOORD_INPUT * pIn,ADDR_COMPUTE_CMASK_ADDRFROMCOORD_OUTPUT * pOut) const1618 ADDR_E_RETURNCODE Lib::ComputeCmaskAddrFromCoord(
1619     const ADDR_COMPUTE_CMASK_ADDRFROMCOORD_INPUT*   pIn,    ///< [in] input structure
1620     ADDR_COMPUTE_CMASK_ADDRFROMCOORD_OUTPUT*        pOut    ///< [out] output structure
1621     ) const
1622 {
1623     ADDR_E_RETURNCODE returnCode = ADDR_OK;
1624 
1625     if (GetFillSizeFieldsFlags() == TRUE)
1626     {
1627         if ((pIn->size != sizeof(ADDR_COMPUTE_CMASK_ADDRFROMCOORD_INPUT)) ||
1628             (pOut->size != sizeof(ADDR_COMPUTE_CMASK_ADDRFROMCOORD_OUTPUT)))
1629         {
1630             returnCode = ADDR_PARAMSIZEMISMATCH;
1631         }
1632     }
1633 
1634     if (returnCode == ADDR_OK)
1635     {
1636         ADDR_TILEINFO tileInfoNull;
1637         ADDR_COMPUTE_CMASK_ADDRFROMCOORD_INPUT input;
1638 
1639         if (UseTileIndex(pIn->tileIndex))
1640         {
1641             input = *pIn;
1642             // Use temp tile info for calcalation
1643             input.pTileInfo = &tileInfoNull;
1644 
1645             returnCode = HwlSetupTileCfg(0, input.tileIndex, input.macroModeIndex, input.pTileInfo);
1646 
1647             // Change the input structure
1648             pIn = &input;
1649         }
1650 
1651         if (returnCode == ADDR_OK)
1652         {
1653             if (pIn->flags.tcCompatible == TRUE)
1654             {
1655                 returnCode = HwlComputeCmaskAddrFromCoord(pIn, pOut);
1656             }
1657             else
1658             {
1659                 pOut->addr = HwlComputeXmaskAddrFromCoord(pIn->pitch,
1660                                                           pIn->height,
1661                                                           pIn->x,
1662                                                           pIn->y,
1663                                                           pIn->slice,
1664                                                           pIn->numSlices,
1665                                                           2,
1666                                                           pIn->isLinear,
1667                                                           FALSE, //this is cmask, isWidth8 is not needed
1668                                                           FALSE, //this is cmask, isHeight8 is not needed
1669                                                           pIn->pTileInfo,
1670                                                           &pOut->bitPosition);
1671             }
1672 
1673         }
1674     }
1675 
1676     return returnCode;
1677 }
1678 
1679 /**
1680 ****************************************************************************************************
1681 *   Lib::ComputeCmaskCoordFromAddr
1682 *
1683 *   @brief
1684 *       Interface function stub of AddrComputeCmaskCoordFromAddr
1685 *
1686 *   @return
1687 *       ADDR_E_RETURNCODE
1688 ****************************************************************************************************
1689 */
ComputeCmaskCoordFromAddr(const ADDR_COMPUTE_CMASK_COORDFROMADDR_INPUT * pIn,ADDR_COMPUTE_CMASK_COORDFROMADDR_OUTPUT * pOut) const1690 ADDR_E_RETURNCODE Lib::ComputeCmaskCoordFromAddr(
1691     const ADDR_COMPUTE_CMASK_COORDFROMADDR_INPUT*   pIn,    ///< [in] input structure
1692     ADDR_COMPUTE_CMASK_COORDFROMADDR_OUTPUT*        pOut    ///< [out] output structure
1693     ) const
1694 {
1695     ADDR_E_RETURNCODE returnCode = ADDR_OK;
1696 
1697     if (GetFillSizeFieldsFlags() == TRUE)
1698     {
1699         if ((pIn->size != sizeof(ADDR_COMPUTE_CMASK_COORDFROMADDR_INPUT)) ||
1700             (pOut->size != sizeof(ADDR_COMPUTE_CMASK_COORDFROMADDR_OUTPUT)))
1701         {
1702             returnCode = ADDR_PARAMSIZEMISMATCH;
1703         }
1704     }
1705 
1706     if (returnCode == ADDR_OK)
1707     {
1708         ADDR_TILEINFO tileInfoNull;
1709         ADDR_COMPUTE_CMASK_COORDFROMADDR_INPUT input;
1710 
1711         if (UseTileIndex(pIn->tileIndex))
1712         {
1713             input = *pIn;
1714             // Use temp tile info for calcalation
1715             input.pTileInfo = &tileInfoNull;
1716 
1717             returnCode = HwlSetupTileCfg(0, input.tileIndex, input.macroModeIndex, input.pTileInfo);
1718 
1719             // Change the input structure
1720             pIn = &input;
1721         }
1722 
1723         if (returnCode == ADDR_OK)
1724         {
1725             HwlComputeXmaskCoordFromAddr(pIn->addr,
1726                                          pIn->bitPosition,
1727                                          pIn->pitch,
1728                                          pIn->height,
1729                                          pIn->numSlices,
1730                                          2,
1731                                          pIn->isLinear,
1732                                          FALSE,
1733                                          FALSE,
1734                                          pIn->pTileInfo,
1735                                          &pOut->x,
1736                                          &pOut->y,
1737                                          &pOut->slice);
1738         }
1739     }
1740 
1741     return returnCode;
1742 }
1743 
1744 /**
1745 ****************************************************************************************************
1746 *   Lib::ComputeTileDataWidthAndHeight
1747 *
1748 *   @brief
1749 *       Compute the squared cache shape for per-tile data (CMASK and HTILE)
1750 *
1751 *   @return
1752 *       N/A
1753 *
1754 *   @note
1755 *       MacroWidth and macroHeight are measured in pixels
1756 ****************************************************************************************************
1757 */
ComputeTileDataWidthAndHeight(UINT_32 bpp,UINT_32 cacheBits,ADDR_TILEINFO * pTileInfo,UINT_32 * pMacroWidth,UINT_32 * pMacroHeight) const1758 VOID Lib::ComputeTileDataWidthAndHeight(
1759     UINT_32         bpp,             ///< [in] bits per pixel
1760     UINT_32         cacheBits,       ///< [in] bits of cache
1761     ADDR_TILEINFO*  pTileInfo,       ///< [in] Tile info
1762     UINT_32*        pMacroWidth,     ///< [out] macro tile width
1763     UINT_32*        pMacroHeight     ///< [out] macro tile height
1764     ) const
1765 {
1766     UINT_32 height = 1;
1767     UINT_32 width  = cacheBits / bpp;
1768     UINT_32 pipes  = HwlGetPipes(pTileInfo);
1769 
1770     // Double height until the macro-tile is close to square
1771     // Height can only be doubled if width is even
1772 
1773     while ((width > height * 2 * pipes) && !(width & 1))
1774     {
1775         width  /= 2;
1776         height *= 2;
1777     }
1778 
1779     *pMacroWidth  = 8 * width;
1780     *pMacroHeight = 8 * height * pipes;
1781 
1782     // Note: The above iterative comptuation is equivalent to the following
1783     //
1784     //int log2_height = ((log2(cacheBits)-log2(bpp)-log2(pipes))/2);
1785     //int macroHeight = pow2( 3+log2(pipes)+log2_height );
1786 }
1787 
1788 /**
1789 ****************************************************************************************************
1790 *   Lib::HwlComputeTileDataWidthAndHeightLinear
1791 *
1792 *   @brief
1793 *       Compute the squared cache shape for per-tile data (CMASK and HTILE) for linear layout
1794 *
1795 *   @return
1796 *       N/A
1797 *
1798 *   @note
1799 *       MacroWidth and macroHeight are measured in pixels
1800 ****************************************************************************************************
1801 */
HwlComputeTileDataWidthAndHeightLinear(UINT_32 * pMacroWidth,UINT_32 * pMacroHeight,UINT_32 bpp,ADDR_TILEINFO * pTileInfo) const1802 VOID Lib::HwlComputeTileDataWidthAndHeightLinear(
1803     UINT_32*        pMacroWidth,     ///< [out] macro tile width
1804     UINT_32*        pMacroHeight,    ///< [out] macro tile height
1805     UINT_32         bpp,             ///< [in] bits per pixel
1806     ADDR_TILEINFO*  pTileInfo        ///< [in] tile info
1807     ) const
1808 {
1809     ADDR_ASSERT(bpp != 4);              // Cmask does not support linear layout prior to SI
1810     *pMacroWidth  = 8 * 512 / bpp;      // Align width to 512-bit memory accesses
1811     *pMacroHeight = 8 * m_pipes;        // Align height to number of pipes
1812 }
1813 
1814 /**
1815 ****************************************************************************************************
1816 *   Lib::ComputeHtileInfo
1817 *
1818 *   @brief
1819 *       Compute htile pitch,width, bytes per 2D slice
1820 *
1821 *   @return
1822 *       Htile bpp i.e. How many bits for an 8x8 tile
1823 *       Also returns by output parameters:
1824 *       *Htile pitch, height, total size in bytes, macro-tile dimensions and slice size*
1825 ****************************************************************************************************
1826 */
ComputeHtileInfo(ADDR_HTILE_FLAGS flags,UINT_32 pitchIn,UINT_32 heightIn,UINT_32 numSlices,BOOL_32 isLinear,BOOL_32 isWidth8,BOOL_32 isHeight8,ADDR_TILEINFO * pTileInfo,UINT_32 * pPitchOut,UINT_32 * pHeightOut,UINT_64 * pHtileBytes,UINT_32 * pMacroWidth,UINT_32 * pMacroHeight,UINT_64 * pSliceSize,UINT_32 * pBaseAlign) const1827 UINT_32 Lib::ComputeHtileInfo(
1828     ADDR_HTILE_FLAGS flags,             ///< [in] htile flags
1829     UINT_32          pitchIn,           ///< [in] pitch input
1830     UINT_32          heightIn,          ///< [in] height input
1831     UINT_32          numSlices,         ///< [in] number of slices
1832     BOOL_32          isLinear,          ///< [in] if it is linear mode
1833     BOOL_32          isWidth8,          ///< [in] if htile block width is 8
1834     BOOL_32          isHeight8,         ///< [in] if htile block height is 8
1835     ADDR_TILEINFO*   pTileInfo,         ///< [in] Tile info
1836     UINT_32*         pPitchOut,         ///< [out] pitch output
1837     UINT_32*         pHeightOut,        ///< [out] height output
1838     UINT_64*         pHtileBytes,       ///< [out] bytes per 2D slice
1839     UINT_32*         pMacroWidth,       ///< [out] macro-tile width in pixels
1840     UINT_32*         pMacroHeight,      ///< [out] macro-tile width in pixels
1841     UINT_64*         pSliceSize,        ///< [out] slice size in bytes
1842     UINT_32*         pBaseAlign         ///< [out] base alignment
1843     ) const
1844 {
1845 
1846     UINT_32 macroWidth;
1847     UINT_32 macroHeight;
1848     UINT_32 baseAlign;
1849     UINT_64 surfBytes;
1850     UINT_64 sliceBytes;
1851 
1852     numSlices = Max(1u, numSlices);
1853 
1854     const UINT_32 bpp = HwlComputeHtileBpp(isWidth8, isHeight8);
1855     const UINT_32 cacheBits = HtileCacheBits;
1856 
1857     if (isLinear)
1858     {
1859         HwlComputeTileDataWidthAndHeightLinear(&macroWidth,
1860                                                &macroHeight,
1861                                                bpp,
1862                                                pTileInfo);
1863     }
1864     else
1865     {
1866         ComputeTileDataWidthAndHeight(bpp,
1867                                       cacheBits,
1868                                       pTileInfo,
1869                                       &macroWidth,
1870                                       &macroHeight);
1871     }
1872 
1873     *pPitchOut = PowTwoAlign(pitchIn,  macroWidth);
1874     *pHeightOut = PowTwoAlign(heightIn,  macroHeight);
1875 
1876     baseAlign = HwlComputeHtileBaseAlign(flags.tcCompatible, isLinear, pTileInfo);
1877 
1878     surfBytes = HwlComputeHtileBytes(*pPitchOut,
1879                                      *pHeightOut,
1880                                      bpp,
1881                                      isLinear,
1882                                      numSlices,
1883                                      &sliceBytes,
1884                                      baseAlign);
1885 
1886     *pHtileBytes = surfBytes;
1887 
1888     //
1889     // Use SafeAssign since they are optional
1890     //
1891     SafeAssign(pMacroWidth, macroWidth);
1892 
1893     SafeAssign(pMacroHeight, macroHeight);
1894 
1895     SafeAssign(pSliceSize,  sliceBytes);
1896 
1897     SafeAssign(pBaseAlign, baseAlign);
1898 
1899     return bpp;
1900 }
1901 
1902 /**
1903 ****************************************************************************************************
1904 *   Lib::ComputeCmaskBaseAlign
1905 *
1906 *   @brief
1907 *       Compute cmask base alignment
1908 *
1909 *   @return
1910 *       Cmask base alignment
1911 ****************************************************************************************************
1912 */
ComputeCmaskBaseAlign(ADDR_CMASK_FLAGS flags,ADDR_TILEINFO * pTileInfo) const1913 UINT_32 Lib::ComputeCmaskBaseAlign(
1914     ADDR_CMASK_FLAGS flags,           ///< [in] Cmask flags
1915     ADDR_TILEINFO*   pTileInfo        ///< [in] Tile info
1916     ) const
1917 {
1918     UINT_32 baseAlign = m_pipeInterleaveBytes * HwlGetPipes(pTileInfo);
1919 
1920     if (flags.tcCompatible)
1921     {
1922         ADDR_ASSERT(pTileInfo != NULL);
1923         if (pTileInfo)
1924         {
1925             baseAlign *= pTileInfo->banks;
1926         }
1927     }
1928 
1929     return baseAlign;
1930 }
1931 
1932 /**
1933 ****************************************************************************************************
1934 *   Lib::ComputeCmaskBytes
1935 *
1936 *   @brief
1937 *       Compute cmask size in bytes
1938 *
1939 *   @return
1940 *       Cmask size in bytes
1941 ****************************************************************************************************
1942 */
ComputeCmaskBytes(UINT_32 pitch,UINT_32 height,UINT_32 numSlices) const1943 UINT_64 Lib::ComputeCmaskBytes(
1944     UINT_32 pitch,        ///< [in] pitch
1945     UINT_32 height,       ///< [in] height
1946     UINT_32 numSlices     ///< [in] number of slices
1947     ) const
1948 {
1949     return BITS_TO_BYTES(static_cast<UINT_64>(pitch) * height * numSlices * CmaskElemBits) /
1950         MicroTilePixels;
1951 }
1952 
1953 /**
1954 ****************************************************************************************************
1955 *   Lib::ComputeCmaskInfo
1956 *
1957 *   @brief
1958 *       Compute cmask pitch,width, bytes per 2D slice
1959 *
1960 *   @return
1961 *       BlockMax. Also by output parameters: Cmask pitch,height, total size in bytes,
1962 *       macro-tile dimensions
1963 ****************************************************************************************************
1964 */
ComputeCmaskInfo(ADDR_CMASK_FLAGS flags,UINT_32 pitchIn,UINT_32 heightIn,UINT_32 numSlices,BOOL_32 isLinear,ADDR_TILEINFO * pTileInfo,UINT_32 * pPitchOut,UINT_32 * pHeightOut,UINT_64 * pCmaskBytes,UINT_32 * pMacroWidth,UINT_32 * pMacroHeight,UINT_64 * pSliceSize,UINT_32 * pBaseAlign,UINT_32 * pBlockMax) const1965 ADDR_E_RETURNCODE Lib::ComputeCmaskInfo(
1966     ADDR_CMASK_FLAGS flags,            ///< [in] cmask flags
1967     UINT_32          pitchIn,           ///< [in] pitch input
1968     UINT_32          heightIn,          ///< [in] height input
1969     UINT_32          numSlices,         ///< [in] number of slices
1970     BOOL_32          isLinear,          ///< [in] is linear mode
1971     ADDR_TILEINFO*   pTileInfo,         ///< [in] Tile info
1972     UINT_32*         pPitchOut,         ///< [out] pitch output
1973     UINT_32*         pHeightOut,        ///< [out] height output
1974     UINT_64*         pCmaskBytes,       ///< [out] bytes per 2D slice
1975     UINT_32*         pMacroWidth,       ///< [out] macro-tile width in pixels
1976     UINT_32*         pMacroHeight,      ///< [out] macro-tile width in pixels
1977     UINT_64*         pSliceSize,        ///< [out] slice size in bytes
1978     UINT_32*         pBaseAlign,        ///< [out] base alignment
1979     UINT_32*         pBlockMax          ///< [out] block max == slice / 128 / 128 - 1
1980     ) const
1981 {
1982     UINT_32 macroWidth;
1983     UINT_32 macroHeight;
1984     UINT_32 baseAlign;
1985     UINT_64 surfBytes;
1986     UINT_64 sliceBytes;
1987 
1988     numSlices = Max(1u, numSlices);
1989 
1990     const UINT_32 bpp = CmaskElemBits;
1991     const UINT_32 cacheBits = CmaskCacheBits;
1992 
1993     ADDR_E_RETURNCODE returnCode = ADDR_OK;
1994 
1995     if (isLinear)
1996     {
1997         HwlComputeTileDataWidthAndHeightLinear(&macroWidth,
1998                                                &macroHeight,
1999                                                bpp,
2000                                                pTileInfo);
2001     }
2002     else
2003     {
2004         ComputeTileDataWidthAndHeight(bpp,
2005                                       cacheBits,
2006                                       pTileInfo,
2007                                       &macroWidth,
2008                                       &macroHeight);
2009     }
2010 
2011     *pPitchOut = (pitchIn + macroWidth - 1) & ~(macroWidth - 1);
2012     *pHeightOut = (heightIn + macroHeight - 1) & ~(macroHeight - 1);
2013 
2014 
2015     sliceBytes = ComputeCmaskBytes(*pPitchOut,
2016                                    *pHeightOut,
2017                                    1);
2018 
2019     baseAlign = ComputeCmaskBaseAlign(flags, pTileInfo);
2020 
2021     while (sliceBytes % baseAlign)
2022     {
2023         *pHeightOut += macroHeight;
2024 
2025         sliceBytes = ComputeCmaskBytes(*pPitchOut,
2026                                        *pHeightOut,
2027                                        1);
2028     }
2029 
2030     surfBytes = sliceBytes * numSlices;
2031 
2032     *pCmaskBytes = surfBytes;
2033 
2034     //
2035     // Use SafeAssign since they are optional
2036     //
2037     SafeAssign(pMacroWidth, macroWidth);
2038 
2039     SafeAssign(pMacroHeight, macroHeight);
2040 
2041     SafeAssign(pBaseAlign, baseAlign);
2042 
2043     SafeAssign(pSliceSize, sliceBytes);
2044 
2045     UINT_32 slice = (*pPitchOut) * (*pHeightOut);
2046     UINT_32 blockMax = slice / 128 / 128 - 1;
2047 
2048 #if DEBUG
2049     if (slice % (64*256) != 0)
2050     {
2051         ADDR_ASSERT_ALWAYS();
2052     }
2053 #endif //DEBUG
2054 
2055     UINT_32 maxBlockMax = HwlGetMaxCmaskBlockMax();
2056 
2057     if (blockMax > maxBlockMax)
2058     {
2059         blockMax = maxBlockMax;
2060         returnCode = ADDR_INVALIDPARAMS;
2061     }
2062 
2063     SafeAssign(pBlockMax, blockMax);
2064 
2065     return returnCode;
2066 }
2067 
2068 /**
2069 ****************************************************************************************************
2070 *   Lib::ComputeXmaskCoordYFromPipe
2071 *
2072 *   @brief
2073 *       Compute the Y coord from pipe number for cmask/htile
2074 *
2075 *   @return
2076 *       Y coordinate
2077 *
2078 ****************************************************************************************************
2079 */
ComputeXmaskCoordYFromPipe(UINT_32 pipe,UINT_32 x) const2080 UINT_32 Lib::ComputeXmaskCoordYFromPipe(
2081     UINT_32         pipe,       ///< [in] pipe number
2082     UINT_32         x           ///< [in] x coordinate
2083     ) const
2084 {
2085     UINT_32 pipeBit0;
2086     UINT_32 pipeBit1;
2087     UINT_32 xBit0;
2088     UINT_32 xBit1;
2089     UINT_32 yBit0;
2090     UINT_32 yBit1;
2091 
2092     UINT_32 y = 0;
2093 
2094     UINT_32 numPipes = m_pipes; // SI has its implementation
2095     //
2096     // Convert pipe + x to y coordinate.
2097     //
2098     switch (numPipes)
2099     {
2100         case 1:
2101             //
2102             // 1 pipe
2103             //
2104             // p0 = 0
2105             //
2106             y = 0;
2107             break;
2108         case 2:
2109             //
2110             // 2 pipes
2111             //
2112             // p0 = x0 ^ y0
2113             //
2114             // y0 = p0 ^ x0
2115             //
2116             pipeBit0 = pipe & 0x1;
2117 
2118             xBit0 = x & 0x1;
2119 
2120             yBit0 = pipeBit0 ^ xBit0;
2121 
2122             y = yBit0;
2123             break;
2124         case 4:
2125             //
2126             // 4 pipes
2127             //
2128             // p0 = x1 ^ y0
2129             // p1 = x0 ^ y1
2130             //
2131             // y0 = p0 ^ x1
2132             // y1 = p1 ^ x0
2133             //
2134             pipeBit0 =  pipe & 0x1;
2135             pipeBit1 = (pipe & 0x2) >> 1;
2136 
2137             xBit0 =  x & 0x1;
2138             xBit1 = (x & 0x2) >> 1;
2139 
2140             yBit0 = pipeBit0 ^ xBit1;
2141             yBit1 = pipeBit1 ^ xBit0;
2142 
2143             y = (yBit0 |
2144                  (yBit1 << 1));
2145             break;
2146         case 8:
2147             //
2148             // 8 pipes
2149             //
2150             // r600 and r800 have different method
2151             //
2152             y = HwlComputeXmaskCoordYFrom8Pipe(pipe, x);
2153             break;
2154         default:
2155             break;
2156     }
2157     return y;
2158 }
2159 
2160 /**
2161 ****************************************************************************************************
2162 *   Lib::HwlComputeXmaskCoordFromAddr
2163 *
2164 *   @brief
2165 *       Compute the coord from an address of a cmask/htile
2166 *
2167 *   @return
2168 *       N/A
2169 *
2170 *   @note
2171 *       This method is reused by htile, so rename to Xmask
2172 ****************************************************************************************************
2173 */
HwlComputeXmaskCoordFromAddr(UINT_64 addr,UINT_32 bitPosition,UINT_32 pitch,UINT_32 height,UINT_32 numSlices,UINT_32 factor,BOOL_32 isLinear,BOOL_32 isWidth8,BOOL_32 isHeight8,ADDR_TILEINFO * pTileInfo,UINT_32 * pX,UINT_32 * pY,UINT_32 * pSlice) const2174 VOID Lib::HwlComputeXmaskCoordFromAddr(
2175     UINT_64         addr,           ///< [in] address
2176     UINT_32         bitPosition,    ///< [in] bitPosition in a byte
2177     UINT_32         pitch,          ///< [in] pitch
2178     UINT_32         height,         ///< [in] height
2179     UINT_32         numSlices,      ///< [in] number of slices
2180     UINT_32         factor,         ///< [in] factor that indicates cmask or htile
2181     BOOL_32         isLinear,       ///< [in] linear or tiled HTILE layout
2182     BOOL_32         isWidth8,       ///< [in] TRUE if width is 8, FALSE means 4. It's register value
2183     BOOL_32         isHeight8,      ///< [in] TRUE if width is 8, FALSE means 4. It's register value
2184     ADDR_TILEINFO*  pTileInfo,      ///< [in] Tile info
2185     UINT_32*        pX,             ///< [out] x coord
2186     UINT_32*        pY,             ///< [out] y coord
2187     UINT_32*        pSlice          ///< [out] slice index
2188     ) const
2189 {
2190     UINT_32 pipe;
2191     UINT_32 numPipes;
2192     UINT_32 numGroupBits;
2193     UINT_32 numPipeBits;
2194     UINT_32 macroTilePitch;
2195     UINT_32 macroTileHeight;
2196 
2197     UINT_64 bitAddr;
2198 
2199     UINT_32 microTileCoordY;
2200 
2201     UINT_32 elemBits;
2202 
2203     UINT_32 pitchAligned = pitch;
2204     UINT_32 heightAligned = height;
2205     UINT_64 totalBytes;
2206 
2207     UINT_64 elemOffset;
2208 
2209     UINT_64 macroIndex;
2210     UINT_32 microIndex;
2211 
2212     UINT_64 macroNumber;
2213     UINT_32 microNumber;
2214 
2215     UINT_32 macroX;
2216     UINT_32 macroY;
2217     UINT_32 macroZ;
2218 
2219     UINT_32 microX;
2220     UINT_32 microY;
2221 
2222     UINT_32 tilesPerMacro;
2223     UINT_32 macrosPerPitch;
2224     UINT_32 macrosPerSlice;
2225 
2226     //
2227     // Extract pipe.
2228     //
2229     numPipes = HwlGetPipes(pTileInfo);
2230     pipe = ComputePipeFromAddr(addr, numPipes);
2231 
2232     //
2233     // Compute the number of group and pipe bits.
2234     //
2235     numGroupBits = Log2(m_pipeInterleaveBytes);
2236     numPipeBits  = Log2(numPipes);
2237 
2238     UINT_32 groupBits = 8 * m_pipeInterleaveBytes;
2239     UINT_32 pipes = numPipes;
2240 
2241 
2242     //
2243     // Compute the micro tile size, in bits. And macro tile pitch and height.
2244     //
2245     if (factor == 2) //CMASK
2246     {
2247         ADDR_CMASK_FLAGS flags = {{0}};
2248 
2249         elemBits = CmaskElemBits;
2250 
2251         ComputeCmaskInfo(flags,
2252                          pitch,
2253                          height,
2254                          numSlices,
2255                          isLinear,
2256                          pTileInfo,
2257                          &pitchAligned,
2258                          &heightAligned,
2259                          &totalBytes,
2260                          &macroTilePitch,
2261                          &macroTileHeight);
2262     }
2263     else  //HTILE
2264     {
2265         ADDR_HTILE_FLAGS flags = {{0}};
2266 
2267         if (factor != 1)
2268         {
2269             factor = 1;
2270         }
2271 
2272         elemBits = HwlComputeHtileBpp(isWidth8, isHeight8);
2273 
2274         ComputeHtileInfo(flags,
2275                          pitch,
2276                          height,
2277                          numSlices,
2278                          isLinear,
2279                          isWidth8,
2280                          isHeight8,
2281                          pTileInfo,
2282                          &pitchAligned,
2283                          &heightAligned,
2284                          &totalBytes,
2285                          &macroTilePitch,
2286                          &macroTileHeight);
2287     }
2288 
2289     // Should use aligned dims
2290     //
2291     pitch = pitchAligned;
2292     height = heightAligned;
2293 
2294 
2295     //
2296     // Convert byte address to bit address.
2297     //
2298     bitAddr = BYTES_TO_BITS(addr) + bitPosition;
2299 
2300 
2301     //
2302     // Remove pipe bits from address.
2303     //
2304 
2305     bitAddr = (bitAddr % groupBits) + ((bitAddr/groupBits/pipes)*groupBits);
2306 
2307 
2308     elemOffset = bitAddr / elemBits;
2309 
2310     tilesPerMacro = (macroTilePitch/factor) * macroTileHeight / MicroTilePixels >> numPipeBits;
2311 
2312     macrosPerPitch = pitch / (macroTilePitch/factor);
2313     macrosPerSlice = macrosPerPitch * height / macroTileHeight;
2314 
2315     macroIndex = elemOffset / factor / tilesPerMacro;
2316     microIndex = static_cast<UINT_32>(elemOffset % (tilesPerMacro * factor));
2317 
2318     macroNumber = macroIndex * factor + microIndex % factor;
2319     microNumber = microIndex / factor;
2320 
2321     macroX = static_cast<UINT_32>((macroNumber % macrosPerPitch));
2322     macroY = static_cast<UINT_32>((macroNumber % macrosPerSlice) / macrosPerPitch);
2323     macroZ = static_cast<UINT_32>((macroNumber / macrosPerSlice));
2324 
2325 
2326     microX = microNumber % (macroTilePitch / factor / MicroTileWidth);
2327     microY = (microNumber / (macroTilePitch / factor / MicroTileHeight));
2328 
2329     *pX = macroX * (macroTilePitch/factor) + microX * MicroTileWidth;
2330     *pY = macroY * macroTileHeight + (microY * MicroTileHeight << numPipeBits);
2331     *pSlice = macroZ;
2332 
2333     microTileCoordY = ComputeXmaskCoordYFromPipe(pipe,
2334                                                  *pX/MicroTileWidth);
2335 
2336 
2337     //
2338     // Assemble final coordinates.
2339     //
2340     *pY += microTileCoordY * MicroTileHeight;
2341 
2342 }
2343 
2344 /**
2345 ****************************************************************************************************
2346 *   Lib::HwlComputeXmaskAddrFromCoord
2347 *
2348 *   @brief
2349 *       Compute the address from an address of cmask (prior to si)
2350 *
2351 *   @return
2352 *       Address in bytes
2353 *
2354 ****************************************************************************************************
2355 */
HwlComputeXmaskAddrFromCoord(UINT_32 pitch,UINT_32 height,UINT_32 x,UINT_32 y,UINT_32 slice,UINT_32 numSlices,UINT_32 factor,BOOL_32 isLinear,BOOL_32 isWidth8,BOOL_32 isHeight8,ADDR_TILEINFO * pTileInfo,UINT_32 * pBitPosition) const2356 UINT_64 Lib::HwlComputeXmaskAddrFromCoord(
2357     UINT_32        pitch,          ///< [in] pitch
2358     UINT_32        height,         ///< [in] height
2359     UINT_32        x,              ///< [in] x coord
2360     UINT_32        y,              ///< [in] y coord
2361     UINT_32        slice,          ///< [in] slice/depth index
2362     UINT_32        numSlices,      ///< [in] number of slices
2363     UINT_32        factor,         ///< [in] factor that indicates cmask(2) or htile(1)
2364     BOOL_32        isLinear,       ///< [in] linear or tiled HTILE layout
2365     BOOL_32        isWidth8,       ///< [in] TRUE if width is 8, FALSE means 4. It's register value
2366     BOOL_32        isHeight8,      ///< [in] TRUE if width is 8, FALSE means 4. It's register value
2367     ADDR_TILEINFO* pTileInfo,      ///< [in] Tile info
2368     UINT_32*       pBitPosition    ///< [out] bit position inside a byte
2369     ) const
2370 {
2371     UINT_64 addr;
2372     UINT_32 numGroupBits;
2373     UINT_32 numPipeBits;
2374     UINT_32 newPitch = 0;
2375     UINT_32 newHeight = 0;
2376     UINT_64 sliceBytes = 0;
2377     UINT_64 totalBytes = 0;
2378     UINT_64 sliceOffset;
2379     UINT_32 pipe;
2380     UINT_32 macroTileWidth;
2381     UINT_32 macroTileHeight;
2382     UINT_32 macroTilesPerRow;
2383     UINT_32 macroTileBytes;
2384     UINT_32 macroTileIndexX;
2385     UINT_32 macroTileIndexY;
2386     UINT_64 macroTileOffset;
2387     UINT_32 pixelBytesPerRow;
2388     UINT_32 pixelOffsetX;
2389     UINT_32 pixelOffsetY;
2390     UINT_32 pixelOffset;
2391     UINT_64 totalOffset;
2392     UINT_64 offsetLo;
2393     UINT_64 offsetHi;
2394     UINT_64 groupMask;
2395 
2396 
2397     UINT_32 elemBits = 0;
2398 
2399     UINT_32 numPipes = m_pipes; // This function is accessed prior to si only
2400 
2401     if (factor == 2) //CMASK
2402     {
2403         elemBits = CmaskElemBits;
2404 
2405         // For asics before SI, cmask is always tiled
2406         isLinear = FALSE;
2407     }
2408     else //HTILE
2409     {
2410         if (factor != 1) // Fix compile warning
2411         {
2412             factor = 1;
2413         }
2414 
2415         elemBits = HwlComputeHtileBpp(isWidth8, isHeight8);
2416     }
2417 
2418     //
2419     // Compute the number of group bits and pipe bits.
2420     //
2421     numGroupBits = Log2(m_pipeInterleaveBytes);
2422     numPipeBits  = Log2(numPipes);
2423 
2424     //
2425     // Compute macro tile dimensions.
2426     //
2427     if (factor == 2) // CMASK
2428     {
2429         ADDR_CMASK_FLAGS flags = {{0}};
2430 
2431         ComputeCmaskInfo(flags,
2432                          pitch,
2433                          height,
2434                          numSlices,
2435                          isLinear,
2436                          pTileInfo,
2437                          &newPitch,
2438                          &newHeight,
2439                          &totalBytes,
2440                          &macroTileWidth,
2441                          &macroTileHeight);
2442 
2443         sliceBytes = totalBytes / numSlices;
2444     }
2445     else // HTILE
2446     {
2447         ADDR_HTILE_FLAGS flags = {{0}};
2448 
2449         ComputeHtileInfo(flags,
2450                          pitch,
2451                          height,
2452                          numSlices,
2453                          isLinear,
2454                          isWidth8,
2455                          isHeight8,
2456                          pTileInfo,
2457                          &newPitch,
2458                          &newHeight,
2459                          &totalBytes,
2460                          &macroTileWidth,
2461                          &macroTileHeight,
2462                          &sliceBytes);
2463     }
2464 
2465     sliceOffset = slice * sliceBytes;
2466 
2467     //
2468     // Get the pipe.  Note that neither slice rotation nor pipe swizzling apply for CMASK.
2469     //
2470     pipe = ComputePipeFromCoord(x,
2471                                 y,
2472                                 0,
2473                                 ADDR_TM_2D_TILED_THIN1,
2474                                 0,
2475                                 FALSE,
2476                                 pTileInfo);
2477 
2478     //
2479     // Compute the number of macro tiles per row.
2480     //
2481     macroTilesPerRow = newPitch / macroTileWidth;
2482 
2483     //
2484     // Compute the number of bytes per macro tile.
2485     //
2486     macroTileBytes = BITS_TO_BYTES((macroTileWidth * macroTileHeight * elemBits) / MicroTilePixels);
2487 
2488     //
2489     // Compute the offset to the macro tile containing the specified coordinate.
2490     //
2491     macroTileIndexX = x / macroTileWidth;
2492     macroTileIndexY = y / macroTileHeight;
2493     macroTileOffset = ((macroTileIndexY * macroTilesPerRow) + macroTileIndexX) * macroTileBytes;
2494 
2495     //
2496     // Compute the pixel offset within the macro tile.
2497     //
2498     pixelBytesPerRow = BITS_TO_BYTES(macroTileWidth * elemBits) / MicroTileWidth;
2499 
2500     //
2501     // The nibbles are interleaved (see below), so the part of the offset relative to the x
2502     // coordinate repeats halfway across the row. (Not for HTILE)
2503     //
2504     if (factor == 2)
2505     {
2506         pixelOffsetX = (x % (macroTileWidth / 2)) / MicroTileWidth;
2507     }
2508     else
2509     {
2510         pixelOffsetX = (x % (macroTileWidth)) / MicroTileWidth * BITS_TO_BYTES(elemBits);
2511     }
2512 
2513     //
2514     // Compute the y offset within the macro tile.
2515     //
2516     pixelOffsetY = (((y % macroTileHeight) / MicroTileHeight) / numPipes) * pixelBytesPerRow;
2517 
2518     pixelOffset = pixelOffsetX + pixelOffsetY;
2519 
2520     //
2521     // Combine the slice offset and macro tile offset with the pixel offset, accounting for the
2522     // pipe bits in the middle of the address.
2523     //
2524     totalOffset = ((sliceOffset + macroTileOffset) >> numPipeBits) + pixelOffset;
2525 
2526     //
2527     // Split the offset to put some bits below the pipe bits and some above.
2528     //
2529     groupMask = (1 << numGroupBits) - 1;
2530     offsetLo  = totalOffset &  groupMask;
2531     offsetHi  = (totalOffset & ~groupMask) << numPipeBits;
2532 
2533     //
2534     // Assemble the address from its components.
2535     //
2536     addr  = offsetLo;
2537     addr |= offsetHi;
2538     // This is to remove warning with /analyze option
2539     UINT_32 pipeBits = pipe << numGroupBits;
2540     addr |= pipeBits;
2541 
2542     //
2543     // Compute the bit position.  The lower nibble is used when the x coordinate within the macro
2544     // tile is less than half of the macro tile width, and the upper nibble is used when the x
2545     // coordinate within the macro tile is greater than or equal to half the macro tile width.
2546     //
2547     *pBitPosition = ((x % macroTileWidth) < (macroTileWidth / factor)) ? 0 : 4;
2548 
2549     return addr;
2550 }
2551 
2552 ////////////////////////////////////////////////////////////////////////////////////////////////////
2553 //                               Surface Addressing Shared
2554 ////////////////////////////////////////////////////////////////////////////////////////////////////
2555 
2556 /**
2557 ****************************************************************************************************
2558 *   Lib::ComputeSurfaceAddrFromCoordLinear
2559 *
2560 *   @brief
2561 *       Compute address from coord for linear surface
2562 *
2563 *   @return
2564 *       Address in bytes
2565 *
2566 ****************************************************************************************************
2567 */
ComputeSurfaceAddrFromCoordLinear(UINT_32 x,UINT_32 y,UINT_32 slice,UINT_32 sample,UINT_32 bpp,UINT_32 pitch,UINT_32 height,UINT_32 numSlices,UINT_32 * pBitPosition) const2568 UINT_64 Lib::ComputeSurfaceAddrFromCoordLinear(
2569     UINT_32  x,              ///< [in] x coord
2570     UINT_32  y,              ///< [in] y coord
2571     UINT_32  slice,          ///< [in] slice/depth index
2572     UINT_32  sample,         ///< [in] sample index
2573     UINT_32  bpp,            ///< [in] bits per pixel
2574     UINT_32  pitch,          ///< [in] pitch
2575     UINT_32  height,         ///< [in] height
2576     UINT_32  numSlices,      ///< [in] number of slices
2577     UINT_32* pBitPosition    ///< [out] bit position inside a byte
2578     ) const
2579 {
2580     const UINT_64 sliceSize = static_cast<UINT_64>(pitch) * height;
2581 
2582     UINT_64 sliceOffset = (slice + sample * numSlices)* sliceSize;
2583     UINT_64 rowOffset   = static_cast<UINT_64>(y) * pitch;
2584     UINT_64 pixOffset   = x;
2585 
2586     UINT_64 addr = (sliceOffset + rowOffset + pixOffset) * bpp;
2587 
2588     *pBitPosition = static_cast<UINT_32>(addr % 8);
2589     addr /= 8;
2590 
2591     return addr;
2592 }
2593 
2594 /**
2595 ****************************************************************************************************
2596 *   Lib::ComputeSurfaceCoordFromAddrLinear
2597 *
2598 *   @brief
2599 *       Compute the coord from an address of a linear surface
2600 *
2601 *   @return
2602 *       N/A
2603 ****************************************************************************************************
2604 */
ComputeSurfaceCoordFromAddrLinear(UINT_64 addr,UINT_32 bitPosition,UINT_32 bpp,UINT_32 pitch,UINT_32 height,UINT_32 numSlices,UINT_32 * pX,UINT_32 * pY,UINT_32 * pSlice,UINT_32 * pSample) const2605 VOID Lib::ComputeSurfaceCoordFromAddrLinear(
2606     UINT_64  addr,           ///< [in] address
2607     UINT_32  bitPosition,    ///< [in] bitPosition in a byte
2608     UINT_32  bpp,            ///< [in] bits per pixel
2609     UINT_32  pitch,          ///< [in] pitch
2610     UINT_32  height,         ///< [in] height
2611     UINT_32  numSlices,      ///< [in] number of slices
2612     UINT_32* pX,             ///< [out] x coord
2613     UINT_32* pY,             ///< [out] y coord
2614     UINT_32* pSlice,         ///< [out] slice/depth index
2615     UINT_32* pSample         ///< [out] sample index
2616     ) const
2617 {
2618     const UINT_64 sliceSize = static_cast<UINT_64>(pitch) * height;
2619     const UINT_64 linearOffset = (BYTES_TO_BITS(addr) + bitPosition) / bpp;
2620 
2621     *pX = static_cast<UINT_32>((linearOffset % sliceSize) % pitch);
2622     *pY = static_cast<UINT_32>((linearOffset % sliceSize) / pitch % height);
2623     *pSlice  = static_cast<UINT_32>((linearOffset / sliceSize) % numSlices);
2624     *pSample = static_cast<UINT_32>((linearOffset / sliceSize) / numSlices);
2625 }
2626 
2627 /**
2628 ****************************************************************************************************
2629 *   Lib::ComputeSurfaceCoordFromAddrMicroTiled
2630 *
2631 *   @brief
2632 *       Compute the coord from an address of a micro tiled surface
2633 *
2634 *   @return
2635 *       N/A
2636 ****************************************************************************************************
2637 */
ComputeSurfaceCoordFromAddrMicroTiled(UINT_64 addr,UINT_32 bitPosition,UINT_32 bpp,UINT_32 pitch,UINT_32 height,UINT_32 numSamples,AddrTileMode tileMode,UINT_32 tileBase,UINT_32 compBits,UINT_32 * pX,UINT_32 * pY,UINT_32 * pSlice,UINT_32 * pSample,AddrTileType microTileType,BOOL_32 isDepthSampleOrder) const2638 VOID Lib::ComputeSurfaceCoordFromAddrMicroTiled(
2639     UINT_64         addr,               ///< [in] address
2640     UINT_32         bitPosition,        ///< [in] bitPosition in a byte
2641     UINT_32         bpp,                ///< [in] bits per pixel
2642     UINT_32         pitch,              ///< [in] pitch
2643     UINT_32         height,             ///< [in] height
2644     UINT_32         numSamples,         ///< [in] number of samples
2645     AddrTileMode    tileMode,           ///< [in] tile mode
2646     UINT_32         tileBase,           ///< [in] base offset within a tile
2647     UINT_32         compBits,           ///< [in] component bits actually needed(for planar surface)
2648     UINT_32*        pX,                 ///< [out] x coord
2649     UINT_32*        pY,                 ///< [out] y coord
2650     UINT_32*        pSlice,             ///< [out] slice/depth index
2651     UINT_32*        pSample,            ///< [out] sample index,
2652     AddrTileType    microTileType,      ///< [in] micro tiling order
2653     BOOL_32         isDepthSampleOrder  ///< [in] TRUE if in depth sample order
2654     ) const
2655 {
2656     UINT_64 bitAddr;
2657     UINT_32 microTileThickness;
2658     UINT_32 microTileBits;
2659     UINT_64 sliceBits;
2660     UINT_64 rowBits;
2661     UINT_32 sliceIndex;
2662     UINT_32 microTileCoordX;
2663     UINT_32 microTileCoordY;
2664     UINT_32 pixelOffset;
2665     UINT_32 pixelCoordX = 0;
2666     UINT_32 pixelCoordY = 0;
2667     UINT_32 pixelCoordZ = 0;
2668     UINT_32 pixelCoordS = 0;
2669 
2670     //
2671     // Convert byte address to bit address.
2672     //
2673     bitAddr = BYTES_TO_BITS(addr) + bitPosition;
2674 
2675     //
2676     // Compute the micro tile size, in bits.
2677     //
2678     switch (tileMode)
2679     {
2680         case ADDR_TM_1D_TILED_THICK:
2681             microTileThickness = ThickTileThickness;
2682             break;
2683         default:
2684             microTileThickness = 1;
2685             break;
2686     }
2687 
2688     microTileBits = MicroTilePixels * microTileThickness * bpp * numSamples;
2689 
2690     //
2691     // Compute number of bits per slice and number of bits per row of micro tiles.
2692     //
2693     sliceBits = static_cast<UINT_64>(pitch) * height * microTileThickness * bpp * numSamples;
2694 
2695     rowBits   = (pitch / MicroTileWidth) * microTileBits;
2696 
2697     //
2698     // Extract the slice index.
2699     //
2700     sliceIndex = static_cast<UINT_32>(bitAddr / sliceBits);
2701     bitAddr -= sliceIndex * sliceBits;
2702 
2703     //
2704     // Extract the y coordinate of the micro tile.
2705     //
2706     microTileCoordY = static_cast<UINT_32>(bitAddr / rowBits) * MicroTileHeight;
2707     bitAddr -= (microTileCoordY / MicroTileHeight) * rowBits;
2708 
2709     //
2710     // Extract the x coordinate of the micro tile.
2711     //
2712     microTileCoordX = static_cast<UINT_32>(bitAddr / microTileBits) * MicroTileWidth;
2713 
2714     //
2715     // Compute the pixel offset within the micro tile.
2716     //
2717     pixelOffset = static_cast<UINT_32>(bitAddr % microTileBits);
2718 
2719     //
2720     // Extract pixel coordinates from the offset.
2721     //
2722     HwlComputePixelCoordFromOffset(pixelOffset,
2723                                    bpp,
2724                                    numSamples,
2725                                    tileMode,
2726                                    tileBase,
2727                                    compBits,
2728                                    &pixelCoordX,
2729                                    &pixelCoordY,
2730                                    &pixelCoordZ,
2731                                    &pixelCoordS,
2732                                    microTileType,
2733                                    isDepthSampleOrder);
2734 
2735     //
2736     // Assemble final coordinates.
2737     //
2738     *pX     = microTileCoordX + pixelCoordX;
2739     *pY     = microTileCoordY + pixelCoordY;
2740     *pSlice = (sliceIndex * microTileThickness) + pixelCoordZ;
2741     *pSample = pixelCoordS;
2742 
2743     if (microTileThickness > 1)
2744     {
2745         *pSample = 0;
2746     }
2747 }
2748 
2749 /**
2750 ****************************************************************************************************
2751 *   Lib::ComputePipeFromAddr
2752 *
2753 *   @brief
2754 *       Compute the pipe number from an address
2755 *
2756 *   @return
2757 *       Pipe number
2758 *
2759 ****************************************************************************************************
2760 */
ComputePipeFromAddr(UINT_64 addr,UINT_32 numPipes) const2761 UINT_32 Lib::ComputePipeFromAddr(
2762     UINT_64 addr,        ///< [in] address
2763     UINT_32 numPipes     ///< [in] number of banks
2764     ) const
2765 {
2766     UINT_32 pipe;
2767 
2768     UINT_32 groupBytes = m_pipeInterleaveBytes; //just different terms
2769 
2770     // R600
2771     // The LSBs of the address are arranged as follows:
2772     //   bank | pipe | group
2773     //
2774     // To get the pipe number, shift off the group bits and mask the pipe bits.
2775     //
2776 
2777     // R800
2778     // The LSBs of the address are arranged as follows:
2779     //   bank | bankInterleave | pipe | pipeInterleave
2780     //
2781     // To get the pipe number, shift off the pipe interleave bits and mask the pipe bits.
2782     //
2783 
2784     pipe = static_cast<UINT_32>(addr >> Log2(groupBytes)) & (numPipes - 1);
2785 
2786     return pipe;
2787 }
2788 
2789 /**
2790 ****************************************************************************************************
2791 *   Lib::ComputeMicroTileEquation
2792 *
2793 *   @brief
2794 *       Compute micro tile equation
2795 *
2796 *   @return
2797 *       If equation can be computed
2798 *
2799 ****************************************************************************************************
2800 */
ComputeMicroTileEquation(UINT_32 log2BytesPP,AddrTileMode tileMode,AddrTileType microTileType,ADDR_EQUATION * pEquation) const2801 ADDR_E_RETURNCODE Lib::ComputeMicroTileEquation(
2802     UINT_32         log2BytesPP,    ///< [in] log2 of bytes per pixel
2803     AddrTileMode    tileMode,       ///< [in] tile mode
2804     AddrTileType    microTileType,  ///< [in] pixel order in display/non-display mode
2805     ADDR_EQUATION*  pEquation       ///< [out] equation
2806     ) const
2807 {
2808     ADDR_E_RETURNCODE retCode = ADDR_OK;
2809 
2810     for (UINT_32 i = 0; i < log2BytesPP; i++)
2811     {
2812         pEquation->addr[i].valid = 1;
2813         pEquation->addr[i].channel = 0;
2814         pEquation->addr[i].index = i;
2815     }
2816 
2817     ADDR_CHANNEL_SETTING* pixelBit = &pEquation->addr[log2BytesPP];
2818 
2819     ADDR_CHANNEL_SETTING x0 = InitChannel(1, 0, log2BytesPP + 0);
2820     ADDR_CHANNEL_SETTING x1 = InitChannel(1, 0, log2BytesPP + 1);
2821     ADDR_CHANNEL_SETTING x2 = InitChannel(1, 0, log2BytesPP + 2);
2822     ADDR_CHANNEL_SETTING y0 = InitChannel(1, 1, 0);
2823     ADDR_CHANNEL_SETTING y1 = InitChannel(1, 1, 1);
2824     ADDR_CHANNEL_SETTING y2 = InitChannel(1, 1, 2);
2825     ADDR_CHANNEL_SETTING z0 = InitChannel(1, 2, 0);
2826     ADDR_CHANNEL_SETTING z1 = InitChannel(1, 2, 1);
2827     ADDR_CHANNEL_SETTING z2 = InitChannel(1, 2, 2);
2828 
2829     UINT_32 thickness = Thickness(tileMode);
2830     UINT_32 bpp = 1 << (log2BytesPP + 3);
2831 
2832     if (microTileType != ADDR_THICK)
2833     {
2834         if (microTileType == ADDR_DISPLAYABLE)
2835         {
2836             switch (bpp)
2837             {
2838                 case 8:
2839                     pixelBit[0] = x0;
2840                     pixelBit[1] = x1;
2841                     pixelBit[2] = x2;
2842                     pixelBit[3] = y1;
2843                     pixelBit[4] = y0;
2844                     pixelBit[5] = y2;
2845                     break;
2846                 case 16:
2847                     pixelBit[0] = x0;
2848                     pixelBit[1] = x1;
2849                     pixelBit[2] = x2;
2850                     pixelBit[3] = y0;
2851                     pixelBit[4] = y1;
2852                     pixelBit[5] = y2;
2853                     break;
2854                 case 32:
2855                     pixelBit[0] = x0;
2856                     pixelBit[1] = x1;
2857                     pixelBit[2] = y0;
2858                     pixelBit[3] = x2;
2859                     pixelBit[4] = y1;
2860                     pixelBit[5] = y2;
2861                     break;
2862                 case 64:
2863                     pixelBit[0] = x0;
2864                     pixelBit[1] = y0;
2865                     pixelBit[2] = x1;
2866                     pixelBit[3] = x2;
2867                     pixelBit[4] = y1;
2868                     pixelBit[5] = y2;
2869                     break;
2870                 case 128:
2871                     pixelBit[0] = y0;
2872                     pixelBit[1] = x0;
2873                     pixelBit[2] = x1;
2874                     pixelBit[3] = x2;
2875                     pixelBit[4] = y1;
2876                     pixelBit[5] = y2;
2877                     break;
2878                 default:
2879                     ADDR_ASSERT_ALWAYS();
2880                     break;
2881             }
2882         }
2883         else if (microTileType == ADDR_NON_DISPLAYABLE || microTileType == ADDR_DEPTH_SAMPLE_ORDER)
2884         {
2885             pixelBit[0] = x0;
2886             pixelBit[1] = y0;
2887             pixelBit[2] = x1;
2888             pixelBit[3] = y1;
2889             pixelBit[4] = x2;
2890             pixelBit[5] = y2;
2891         }
2892         else if (microTileType == ADDR_ROTATED)
2893         {
2894             ADDR_ASSERT(thickness == 1);
2895 
2896             switch (bpp)
2897             {
2898                 case 8:
2899                     pixelBit[0] = y0;
2900                     pixelBit[1] = y1;
2901                     pixelBit[2] = y2;
2902                     pixelBit[3] = x1;
2903                     pixelBit[4] = x0;
2904                     pixelBit[5] = x2;
2905                     break;
2906                 case 16:
2907                     pixelBit[0] = y0;
2908                     pixelBit[1] = y1;
2909                     pixelBit[2] = y2;
2910                     pixelBit[3] = x0;
2911                     pixelBit[4] = x1;
2912                     pixelBit[5] = x2;
2913                     break;
2914                 case 32:
2915                     pixelBit[0] = y0;
2916                     pixelBit[1] = y1;
2917                     pixelBit[2] = x0;
2918                     pixelBit[3] = y2;
2919                     pixelBit[4] = x1;
2920                     pixelBit[5] = x2;
2921                     break;
2922                 case 64:
2923                     pixelBit[0] = y0;
2924                     pixelBit[1] = x0;
2925                     pixelBit[2] = y1;
2926                     pixelBit[3] = x1;
2927                     pixelBit[4] = x2;
2928                     pixelBit[5] = y2;
2929                     break;
2930                 default:
2931                     retCode = ADDR_NOTSUPPORTED;
2932                     break;
2933             }
2934         }
2935 
2936         if (thickness > 1)
2937         {
2938             pixelBit[6] = z0;
2939             pixelBit[7] = z1;
2940             pEquation->numBits = 8 + log2BytesPP;
2941         }
2942         else
2943         {
2944             pEquation->numBits = 6 + log2BytesPP;
2945         }
2946     }
2947     else // ADDR_THICK
2948     {
2949         ADDR_ASSERT(thickness > 1);
2950 
2951         switch (bpp)
2952         {
2953             case 8:
2954             case 16:
2955                 pixelBit[0] = x0;
2956                 pixelBit[1] = y0;
2957                 pixelBit[2] = x1;
2958                 pixelBit[3] = y1;
2959                 pixelBit[4] = z0;
2960                 pixelBit[5] = z1;
2961                 break;
2962             case 32:
2963                 pixelBit[0] = x0;
2964                 pixelBit[1] = y0;
2965                 pixelBit[2] = x1;
2966                 pixelBit[3] = z0;
2967                 pixelBit[4] = y1;
2968                 pixelBit[5] = z1;
2969                 break;
2970             case 64:
2971             case 128:
2972                 pixelBit[0] = x0;
2973                 pixelBit[1] = y0;
2974                 pixelBit[2] = z0;
2975                 pixelBit[3] = x1;
2976                 pixelBit[4] = y1;
2977                 pixelBit[5] = z1;
2978                 break;
2979             default:
2980                 ADDR_ASSERT_ALWAYS();
2981                 break;
2982         }
2983 
2984         pixelBit[6] = x2;
2985         pixelBit[7] = y2;
2986         pEquation->numBits = 8 + log2BytesPP;
2987     }
2988 
2989     if (thickness == 8)
2990     {
2991         pixelBit[8] = z2;
2992         pEquation->numBits = 9 + log2BytesPP;
2993     }
2994 
2995     // stackedDepthSlices is used for addressing mode that a tile block contains multiple slices,
2996     // which is not supported by our address lib
2997     pEquation->stackedDepthSlices = FALSE;
2998 
2999     return retCode;
3000 }
3001 
3002 /**
3003 ****************************************************************************************************
3004 *   Lib::ComputePixelIndexWithinMicroTile
3005 *
3006 *   @brief
3007 *       Compute the pixel index inside a micro tile of surface
3008 *
3009 *   @return
3010 *       Pixel index
3011 *
3012 ****************************************************************************************************
3013 */
ComputePixelIndexWithinMicroTile(UINT_32 x,UINT_32 y,UINT_32 z,UINT_32 bpp,AddrTileMode tileMode,AddrTileType microTileType) const3014 UINT_32 Lib::ComputePixelIndexWithinMicroTile(
3015     UINT_32         x,              ///< [in] x coord
3016     UINT_32         y,              ///< [in] y coord
3017     UINT_32         z,              ///< [in] slice/depth index
3018     UINT_32         bpp,            ///< [in] bits per pixel
3019     AddrTileMode    tileMode,       ///< [in] tile mode
3020     AddrTileType    microTileType   ///< [in] pixel order in display/non-display mode
3021     ) const
3022 {
3023     UINT_32 pixelBit0 = 0;
3024     UINT_32 pixelBit1 = 0;
3025     UINT_32 pixelBit2 = 0;
3026     UINT_32 pixelBit3 = 0;
3027     UINT_32 pixelBit4 = 0;
3028     UINT_32 pixelBit5 = 0;
3029     UINT_32 pixelBit6 = 0;
3030     UINT_32 pixelBit7 = 0;
3031     UINT_32 pixelBit8 = 0;
3032     UINT_32 pixelNumber;
3033 
3034     UINT_32 x0 = _BIT(x, 0);
3035     UINT_32 x1 = _BIT(x, 1);
3036     UINT_32 x2 = _BIT(x, 2);
3037     UINT_32 y0 = _BIT(y, 0);
3038     UINT_32 y1 = _BIT(y, 1);
3039     UINT_32 y2 = _BIT(y, 2);
3040     UINT_32 z0 = _BIT(z, 0);
3041     UINT_32 z1 = _BIT(z, 1);
3042     UINT_32 z2 = _BIT(z, 2);
3043 
3044     UINT_32 thickness = Thickness(tileMode);
3045 
3046     // Compute the pixel number within the micro tile.
3047 
3048     if (microTileType != ADDR_THICK)
3049     {
3050         if (microTileType == ADDR_DISPLAYABLE)
3051         {
3052             switch (bpp)
3053             {
3054                 case 8:
3055                     pixelBit0 = x0;
3056                     pixelBit1 = x1;
3057                     pixelBit2 = x2;
3058                     pixelBit3 = y1;
3059                     pixelBit4 = y0;
3060                     pixelBit5 = y2;
3061                     break;
3062                 case 16:
3063                     pixelBit0 = x0;
3064                     pixelBit1 = x1;
3065                     pixelBit2 = x2;
3066                     pixelBit3 = y0;
3067                     pixelBit4 = y1;
3068                     pixelBit5 = y2;
3069                     break;
3070                 case 32:
3071                     pixelBit0 = x0;
3072                     pixelBit1 = x1;
3073                     pixelBit2 = y0;
3074                     pixelBit3 = x2;
3075                     pixelBit4 = y1;
3076                     pixelBit5 = y2;
3077                     break;
3078                 case 64:
3079                     pixelBit0 = x0;
3080                     pixelBit1 = y0;
3081                     pixelBit2 = x1;
3082                     pixelBit3 = x2;
3083                     pixelBit4 = y1;
3084                     pixelBit5 = y2;
3085                     break;
3086                 case 128:
3087                     pixelBit0 = y0;
3088                     pixelBit1 = x0;
3089                     pixelBit2 = x1;
3090                     pixelBit3 = x2;
3091                     pixelBit4 = y1;
3092                     pixelBit5 = y2;
3093                     break;
3094                 default:
3095                     ADDR_ASSERT_ALWAYS();
3096                     break;
3097             }
3098         }
3099         else if (microTileType == ADDR_NON_DISPLAYABLE || microTileType == ADDR_DEPTH_SAMPLE_ORDER)
3100         {
3101             pixelBit0 = x0;
3102             pixelBit1 = y0;
3103             pixelBit2 = x1;
3104             pixelBit3 = y1;
3105             pixelBit4 = x2;
3106             pixelBit5 = y2;
3107         }
3108         else if (microTileType == ADDR_ROTATED)
3109         {
3110             ADDR_ASSERT(thickness == 1);
3111 
3112             switch (bpp)
3113             {
3114                 case 8:
3115                     pixelBit0 = y0;
3116                     pixelBit1 = y1;
3117                     pixelBit2 = y2;
3118                     pixelBit3 = x1;
3119                     pixelBit4 = x0;
3120                     pixelBit5 = x2;
3121                     break;
3122                 case 16:
3123                     pixelBit0 = y0;
3124                     pixelBit1 = y1;
3125                     pixelBit2 = y2;
3126                     pixelBit3 = x0;
3127                     pixelBit4 = x1;
3128                     pixelBit5 = x2;
3129                     break;
3130                 case 32:
3131                     pixelBit0 = y0;
3132                     pixelBit1 = y1;
3133                     pixelBit2 = x0;
3134                     pixelBit3 = y2;
3135                     pixelBit4 = x1;
3136                     pixelBit5 = x2;
3137                     break;
3138                 case 64:
3139                     pixelBit0 = y0;
3140                     pixelBit1 = x0;
3141                     pixelBit2 = y1;
3142                     pixelBit3 = x1;
3143                     pixelBit4 = x2;
3144                     pixelBit5 = y2;
3145                     break;
3146                 default:
3147                     ADDR_ASSERT_ALWAYS();
3148                     break;
3149             }
3150         }
3151 
3152         if (thickness > 1)
3153         {
3154             pixelBit6 = z0;
3155             pixelBit7 = z1;
3156         }
3157     }
3158     else // ADDR_THICK
3159     {
3160         ADDR_ASSERT(thickness > 1);
3161 
3162         switch (bpp)
3163         {
3164             case 8:
3165             case 16:
3166                 pixelBit0 = x0;
3167                 pixelBit1 = y0;
3168                 pixelBit2 = x1;
3169                 pixelBit3 = y1;
3170                 pixelBit4 = z0;
3171                 pixelBit5 = z1;
3172                 break;
3173             case 32:
3174                 pixelBit0 = x0;
3175                 pixelBit1 = y0;
3176                 pixelBit2 = x1;
3177                 pixelBit3 = z0;
3178                 pixelBit4 = y1;
3179                 pixelBit5 = z1;
3180                 break;
3181             case 64:
3182             case 128:
3183                 pixelBit0 = x0;
3184                 pixelBit1 = y0;
3185                 pixelBit2 = z0;
3186                 pixelBit3 = x1;
3187                 pixelBit4 = y1;
3188                 pixelBit5 = z1;
3189                 break;
3190             default:
3191                 ADDR_ASSERT_ALWAYS();
3192                 break;
3193         }
3194 
3195         pixelBit6 = x2;
3196         pixelBit7 = y2;
3197     }
3198 
3199     if (thickness == 8)
3200     {
3201         pixelBit8 = z2;
3202     }
3203 
3204     pixelNumber = ((pixelBit0     ) |
3205                    (pixelBit1 << 1) |
3206                    (pixelBit2 << 2) |
3207                    (pixelBit3 << 3) |
3208                    (pixelBit4 << 4) |
3209                    (pixelBit5 << 5) |
3210                    (pixelBit6 << 6) |
3211                    (pixelBit7 << 7) |
3212                    (pixelBit8 << 8));
3213 
3214     return pixelNumber;
3215 }
3216 
3217 /**
3218 ****************************************************************************************************
3219 *   Lib::AdjustPitchAlignment
3220 *
3221 *   @brief
3222 *       Adjusts pitch alignment for flipping surface
3223 *
3224 *   @return
3225 *       N/A
3226 *
3227 ****************************************************************************************************
3228 */
AdjustPitchAlignment(ADDR_SURFACE_FLAGS flags,UINT_32 * pPitchAlign) const3229 VOID Lib::AdjustPitchAlignment(
3230     ADDR_SURFACE_FLAGS  flags,      ///< [in] Surface flags
3231     UINT_32*            pPitchAlign ///< [out] Pointer to pitch alignment
3232     ) const
3233 {
3234     // Display engine hardwires lower 5 bit of GRPH_PITCH to ZERO which means 32 pixel alignment
3235     // Maybe it will be fixed in future but let's make it general for now.
3236     if (flags.display || flags.overlay)
3237     {
3238         *pPitchAlign = PowTwoAlign(*pPitchAlign, 32);
3239 
3240         if(flags.display)
3241         {
3242             *pPitchAlign = Max(m_minPitchAlignPixels, *pPitchAlign);
3243         }
3244     }
3245 }
3246 
3247 /**
3248 ****************************************************************************************************
3249 *   Lib::PadDimensions
3250 *
3251 *   @brief
3252 *       Helper function to pad dimensions
3253 *
3254 *   @return
3255 *       N/A
3256 *
3257 ****************************************************************************************************
3258 */
PadDimensions(AddrTileMode tileMode,UINT_32 bpp,ADDR_SURFACE_FLAGS flags,UINT_32 numSamples,ADDR_TILEINFO * pTileInfo,UINT_32 padDims,UINT_32 mipLevel,UINT_32 * pPitch,UINT_32 * pPitchAlign,UINT_32 * pHeight,UINT_32 heightAlign,UINT_32 * pSlices,UINT_32 sliceAlign) const3259 VOID Lib::PadDimensions(
3260     AddrTileMode        tileMode,    ///< [in] tile mode
3261     UINT_32             bpp,         ///< [in] bits per pixel
3262     ADDR_SURFACE_FLAGS  flags,       ///< [in] surface flags
3263     UINT_32             numSamples,  ///< [in] number of samples
3264     ADDR_TILEINFO*      pTileInfo,   ///< [in,out] bank structure.
3265     UINT_32             padDims,     ///< [in] Dimensions to pad valid value 1,2,3
3266     UINT_32             mipLevel,    ///< [in] MipLevel
3267     UINT_32*            pPitch,      ///< [in,out] pitch in pixels
3268     UINT_32*            pPitchAlign, ///< [in,out] pitch align could be changed in HwlPadDimensions
3269     UINT_32*            pHeight,     ///< [in,out] height in pixels
3270     UINT_32             heightAlign, ///< [in] height alignment
3271     UINT_32*            pSlices,     ///< [in,out] number of slices
3272     UINT_32             sliceAlign   ///< [in] number of slice alignment
3273     ) const
3274 {
3275     UINT_32 pitchAlign = *pPitchAlign;
3276     UINT_32 thickness = Thickness(tileMode);
3277 
3278     ADDR_ASSERT(padDims <= 3);
3279 
3280     //
3281     // Override padding for mip levels
3282     //
3283     if (mipLevel > 0)
3284     {
3285         if (flags.cube)
3286         {
3287             // for cubemap, we only pad when client call with 6 faces as an identity
3288             if (*pSlices > 1)
3289             {
3290                 padDims = 3; // we should pad cubemap sub levels when we treat it as 3d texture
3291             }
3292             else
3293             {
3294                 padDims = 2;
3295             }
3296         }
3297     }
3298 
3299     // Any possibilities that padDims is 0?
3300     if (padDims == 0)
3301     {
3302         padDims = 3;
3303     }
3304 
3305     if (IsPow2(pitchAlign))
3306     {
3307         *pPitch = PowTwoAlign((*pPitch), pitchAlign);
3308     }
3309     else // add this code to pass unit test, r600 linear mode is not align bpp to pow2 for linear
3310     {
3311         *pPitch += pitchAlign - 1;
3312         *pPitch /= pitchAlign;
3313         *pPitch *= pitchAlign;
3314     }
3315 
3316     if (padDims > 1)
3317     {
3318         if (IsPow2(heightAlign))
3319         {
3320             *pHeight = PowTwoAlign((*pHeight), heightAlign);
3321         }
3322         else
3323         {
3324             *pHeight += heightAlign - 1;
3325             *pHeight /= heightAlign;
3326             *pHeight *= heightAlign;
3327         }
3328     }
3329 
3330     if (padDims > 2 || thickness > 1)
3331     {
3332         // for cubemap single face, we do not pad slices.
3333         // if we pad it, the slice number should be set to 6 and current mip level > 1
3334         if (flags.cube && (!m_configFlags.noCubeMipSlicesPad || flags.cubeAsArray))
3335         {
3336             *pSlices = NextPow2(*pSlices);
3337         }
3338 
3339         // normal 3D texture or arrays or cubemap has a thick mode? (Just pass unit test)
3340         if (thickness > 1)
3341         {
3342             *pSlices = PowTwoAlign((*pSlices), sliceAlign);
3343         }
3344 
3345     }
3346 
3347     HwlPadDimensions(tileMode,
3348                      bpp,
3349                      flags,
3350                      numSamples,
3351                      pTileInfo,
3352                      mipLevel,
3353                      pPitch,
3354                      pPitchAlign,
3355                      *pHeight,
3356                      heightAlign);
3357 }
3358 
3359 
3360 /**
3361 ****************************************************************************************************
3362 *   Lib::HwlPreHandleBaseLvl3xPitch
3363 *
3364 *   @brief
3365 *       Pre-handler of 3x pitch (96 bit) adjustment
3366 *
3367 *   @return
3368 *       Expected pitch
3369 ****************************************************************************************************
3370 */
HwlPreHandleBaseLvl3xPitch(const ADDR_COMPUTE_SURFACE_INFO_INPUT * pIn,UINT_32 expPitch) const3371 UINT_32 Lib::HwlPreHandleBaseLvl3xPitch(
3372     const ADDR_COMPUTE_SURFACE_INFO_INPUT*  pIn,        ///< [in] input
3373     UINT_32                                 expPitch    ///< [in] pitch
3374     ) const
3375 {
3376     ADDR_ASSERT(pIn->width == expPitch);
3377     //
3378     // If pitch is pre-multiplied by 3, we retrieve original one here to get correct miplevel size
3379     //
3380     if (ElemLib::IsExpand3x(pIn->format) &&
3381         pIn->mipLevel == 0 &&
3382         pIn->tileMode == ADDR_TM_LINEAR_ALIGNED)
3383     {
3384         expPitch /= 3;
3385         expPitch = NextPow2(expPitch);
3386     }
3387 
3388     return expPitch;
3389 }
3390 
3391 /**
3392 ****************************************************************************************************
3393 *   Lib::HwlPostHandleBaseLvl3xPitch
3394 *
3395 *   @brief
3396 *       Post-handler of 3x pitch adjustment
3397 *
3398 *   @return
3399 *       Expected pitch
3400 ****************************************************************************************************
3401 */
HwlPostHandleBaseLvl3xPitch(const ADDR_COMPUTE_SURFACE_INFO_INPUT * pIn,UINT_32 expPitch) const3402 UINT_32 Lib::HwlPostHandleBaseLvl3xPitch(
3403     const ADDR_COMPUTE_SURFACE_INFO_INPUT*  pIn,        ///< [in] input
3404     UINT_32                                 expPitch    ///< [in] pitch
3405     ) const
3406 {
3407     //
3408     // 96 bits surface of sub levels require element pitch of 32 bits instead
3409     // So we just return pitch in 32 bit pixels without timing 3
3410     //
3411     if (ElemLib::IsExpand3x(pIn->format) &&
3412         pIn->mipLevel == 0 &&
3413         pIn->tileMode == ADDR_TM_LINEAR_ALIGNED)
3414     {
3415         expPitch *= 3;
3416     }
3417 
3418     return expPitch;
3419 }
3420 
3421 
3422 /**
3423 ****************************************************************************************************
3424 *   Lib::IsMacroTiled
3425 *
3426 *   @brief
3427 *       Check if the tile mode is macro tiled
3428 *
3429 *   @return
3430 *       TRUE if it is macro tiled (2D/2B/3D/3B)
3431 ****************************************************************************************************
3432 */
IsMacroTiled(AddrTileMode tileMode)3433 BOOL_32 Lib::IsMacroTiled(
3434     AddrTileMode tileMode)  ///< [in] tile mode
3435 {
3436    return ModeFlags[tileMode].isMacro;
3437 }
3438 
3439 /**
3440 ****************************************************************************************************
3441 *   Lib::IsMacro3dTiled
3442 *
3443 *   @brief
3444 *       Check if the tile mode is 3D macro tiled
3445 *
3446 *   @return
3447 *       TRUE if it is 3D macro tiled
3448 ****************************************************************************************************
3449 */
IsMacro3dTiled(AddrTileMode tileMode)3450 BOOL_32 Lib::IsMacro3dTiled(
3451     AddrTileMode tileMode)  ///< [in] tile mode
3452 {
3453     return ModeFlags[tileMode].isMacro3d;
3454 }
3455 
3456 /**
3457 ****************************************************************************************************
3458 *   Lib::IsMicroTiled
3459 *
3460 *   @brief
3461 *       Check if the tile mode is micro tiled
3462 *
3463 *   @return
3464 *       TRUE if micro tiled
3465 ****************************************************************************************************
3466 */
IsMicroTiled(AddrTileMode tileMode)3467 BOOL_32 Lib::IsMicroTiled(
3468     AddrTileMode tileMode)  ///< [in] tile mode
3469 {
3470     return ModeFlags[tileMode].isMicro;
3471 }
3472 
3473 /**
3474 ****************************************************************************************************
3475 *   Lib::IsLinear
3476 *
3477 *   @brief
3478 *       Check if the tile mode is linear
3479 *
3480 *   @return
3481 *       TRUE if linear
3482 ****************************************************************************************************
3483 */
IsLinear(AddrTileMode tileMode)3484 BOOL_32 Lib::IsLinear(
3485     AddrTileMode tileMode)  ///< [in] tile mode
3486 {
3487     return ModeFlags[tileMode].isLinear;
3488 }
3489 
3490 /**
3491 ****************************************************************************************************
3492 *   Lib::IsPrtNoRotationTileMode
3493 *
3494 *   @brief
3495 *       Return TRUE if it is prt tile without rotation
3496 *   @note
3497 *       This function just used by CI
3498 ****************************************************************************************************
3499 */
IsPrtNoRotationTileMode(AddrTileMode tileMode)3500 BOOL_32 Lib::IsPrtNoRotationTileMode(
3501     AddrTileMode tileMode)
3502 {
3503     return ModeFlags[tileMode].isPrtNoRotation;
3504 }
3505 
3506 /**
3507 ****************************************************************************************************
3508 *   Lib::IsPrtTileMode
3509 *
3510 *   @brief
3511 *       Return TRUE if it is prt tile
3512 *   @note
3513 *       This function just used by CI
3514 ****************************************************************************************************
3515 */
IsPrtTileMode(AddrTileMode tileMode)3516 BOOL_32 Lib::IsPrtTileMode(
3517     AddrTileMode tileMode)
3518 {
3519     return ModeFlags[tileMode].isPrt;
3520 }
3521 
3522 /**
3523 ****************************************************************************************************
3524 *   Lib::ComputeMipLevel
3525 *
3526 *   @brief
3527 *       Compute mipmap level width/height/slices
3528 *   @return
3529 *      N/A
3530 ****************************************************************************************************
3531 */
ComputeMipLevel(ADDR_COMPUTE_SURFACE_INFO_INPUT * pIn) const3532 VOID Lib::ComputeMipLevel(
3533     ADDR_COMPUTE_SURFACE_INFO_INPUT* pIn ///< [in,out] Input structure
3534     ) const
3535 {
3536     // Check if HWL has handled
3537     BOOL_32 hwlHandled = FALSE;
3538 
3539     if (ElemLib::IsBlockCompressed(pIn->format))
3540     {
3541         if (pIn->mipLevel == 0)
3542         {
3543             // DXTn's level 0 must be multiple of 4
3544             // But there are exceptions:
3545             // 1. Internal surface creation in hostblt/vsblt/etc...
3546             // 2. Runtime doesn't reject ATI1/ATI2 whose width/height are not multiple of 4
3547             pIn->width = PowTwoAlign(pIn->width, 4);
3548             pIn->height = PowTwoAlign(pIn->height, 4);
3549         }
3550     }
3551 
3552     hwlHandled = HwlComputeMipLevel(pIn);
3553 }
3554 
3555 /**
3556 ****************************************************************************************************
3557 *   Lib::DegradeTo1D
3558 *
3559 *   @brief
3560 *       Check if surface can be degraded to 1D
3561 *   @return
3562 *       TRUE if degraded
3563 ****************************************************************************************************
3564 */
DegradeTo1D(UINT_32 width,UINT_32 height,UINT_32 macroTilePitchAlign,UINT_32 macroTileHeightAlign)3565 BOOL_32 Lib::DegradeTo1D(
3566     UINT_32 width,                  ///< surface width
3567     UINT_32 height,                 ///< surface height
3568     UINT_32 macroTilePitchAlign,    ///< macro tile pitch align
3569     UINT_32 macroTileHeightAlign    ///< macro tile height align
3570     )
3571 {
3572     BOOL_32 degrade = ((width < macroTilePitchAlign) || (height < macroTileHeightAlign));
3573 
3574     // Check whether 2D tiling still has too much footprint
3575     if (degrade == FALSE)
3576     {
3577         // Only check width and height as slices are aligned to thickness
3578         UINT_64 unalignedSize = width * height;
3579 
3580         UINT_32 alignedPitch = PowTwoAlign(width, macroTilePitchAlign);
3581         UINT_32 alignedHeight = PowTwoAlign(height, macroTileHeightAlign);
3582         UINT_64 alignedSize = alignedPitch * alignedHeight;
3583 
3584         // alignedSize > 1.5 * unalignedSize
3585         if (2 * alignedSize > 3 * unalignedSize)
3586         {
3587             degrade = TRUE;
3588         }
3589     }
3590 
3591     return degrade;
3592 }
3593 
3594 /**
3595 ****************************************************************************************************
3596 *   Lib::OptimizeTileMode
3597 *
3598 *   @brief
3599 *       Check if base level's tile mode can be optimized (degraded)
3600 *   @return
3601 *       N/A
3602 ****************************************************************************************************
3603 */
OptimizeTileMode(ADDR_COMPUTE_SURFACE_INFO_INPUT * pInOut) const3604 VOID Lib::OptimizeTileMode(
3605     ADDR_COMPUTE_SURFACE_INFO_INPUT*  pInOut     ///< [in, out] structure for surface info
3606     ) const
3607 {
3608     AddrTileMode tileMode = pInOut->tileMode;
3609 
3610     BOOL_32 doOpt = (pInOut->flags.opt4Space == TRUE) ||
3611                     (pInOut->flags.minimizeAlignment == TRUE) ||
3612                     (pInOut->maxBaseAlign != 0);
3613 
3614     BOOL_32 convertToPrt = FALSE;
3615 
3616     // Optimization can only be done on level 0 and samples <= 1
3617     if ((doOpt == TRUE)                     &&
3618         (pInOut->mipLevel == 0)             &&
3619         (IsPrtTileMode(tileMode) == FALSE)  &&
3620         (pInOut->flags.prt == FALSE))
3621     {
3622         UINT_32 width = pInOut->width;
3623         UINT_32 height = pInOut->height;
3624         UINT_32 thickness = Thickness(tileMode);
3625         BOOL_32 macroTiledOK = TRUE;
3626         UINT_32 macroWidthAlign = 0;
3627         UINT_32 macroHeightAlign = 0;
3628         UINT_32 macroSizeAlign = 0;
3629 
3630         if (IsMacroTiled(tileMode))
3631         {
3632             macroTiledOK = HwlGetAlignmentInfoMacroTiled(pInOut,
3633                                                          &macroWidthAlign,
3634                                                          &macroHeightAlign,
3635                                                          &macroSizeAlign);
3636         }
3637 
3638         if (macroTiledOK)
3639         {
3640             if ((pInOut->flags.display == FALSE) &&
3641                 (pInOut->flags.opt4Space == TRUE) &&
3642                 (pInOut->numSamples <= 1))
3643             {
3644                 // Check if linear mode is optimal
3645                 if ((pInOut->height == 1) &&
3646                     (IsLinear(tileMode) == FALSE) &&
3647                     (ElemLib::IsBlockCompressed(pInOut->format) == FALSE) &&
3648                     (pInOut->flags.depth == FALSE) &&
3649                     (pInOut->flags.stencil == FALSE) &&
3650                     (m_configFlags.disableLinearOpt == FALSE) &&
3651                     (pInOut->flags.disableLinearOpt == FALSE))
3652                 {
3653                     tileMode = ADDR_TM_LINEAR_ALIGNED;
3654                 }
3655                 else if (IsMacroTiled(tileMode) && (pInOut->flags.tcCompatible == FALSE))
3656                 {
3657                     if (DegradeTo1D(width, height, macroWidthAlign, macroHeightAlign))
3658                     {
3659                         tileMode = (thickness == 1) ?
3660                                    ADDR_TM_1D_TILED_THIN1 : ADDR_TM_1D_TILED_THICK;
3661                     }
3662                     else if ((thickness > 1) && (pInOut->flags.disallowLargeThickDegrade == 0))
3663                     {
3664                         // As in the following HwlComputeSurfaceInfo, thick modes may be degraded to
3665                         // thinner modes, we should re-evaluate whether the corresponding
3666                         // thinner modes should be degraded. If so, we choose 1D thick mode instead.
3667                         tileMode = DegradeLargeThickTile(pInOut->tileMode, pInOut->bpp);
3668 
3669                         if (tileMode != pInOut->tileMode)
3670                         {
3671                             // Get thickness again after large thick degrade
3672                             thickness = Thickness(tileMode);
3673 
3674                             ADDR_COMPUTE_SURFACE_INFO_INPUT input = *pInOut;
3675                             input.tileMode = tileMode;
3676 
3677                             macroTiledOK = HwlGetAlignmentInfoMacroTiled(&input,
3678                                                                          &macroWidthAlign,
3679                                                                          &macroHeightAlign,
3680                                                                          &macroSizeAlign);
3681 
3682                             if (macroTiledOK &&
3683                                 DegradeTo1D(width, height, macroWidthAlign, macroHeightAlign))
3684                             {
3685                                 tileMode = ADDR_TM_1D_TILED_THICK;
3686                             }
3687                         }
3688                     }
3689                 }
3690             }
3691 
3692             if (macroTiledOK)
3693             {
3694                 if ((pInOut->flags.minimizeAlignment == TRUE) &&
3695                     (pInOut->numSamples <= 1) &&
3696                     (IsMacroTiled(tileMode) == TRUE))
3697                 {
3698                     UINT_32 macroSize = PowTwoAlign(width, macroWidthAlign) *
3699                                         PowTwoAlign(height, macroHeightAlign);
3700                     UINT_32 microSize = PowTwoAlign(width, MicroTileWidth) *
3701                                         PowTwoAlign(height, MicroTileHeight);
3702 
3703                     if (macroSize > microSize)
3704                     {
3705                         tileMode = (thickness == 1) ?
3706                                    ADDR_TM_1D_TILED_THIN1 : ADDR_TM_1D_TILED_THICK;
3707                     }
3708                 }
3709 
3710                 if ((pInOut->maxBaseAlign != 0) &&
3711                     (IsMacroTiled(tileMode) == TRUE))
3712                 {
3713                     if (macroSizeAlign > pInOut->maxBaseAlign)
3714                     {
3715                         if (pInOut->numSamples > 1)
3716                         {
3717                             ADDR_ASSERT(pInOut->maxBaseAlign >= Block64K);
3718 
3719                             convertToPrt = TRUE;
3720                         }
3721                         else if (pInOut->maxBaseAlign < Block64K)
3722                         {
3723                             tileMode = (thickness == 1) ?
3724                                        ADDR_TM_1D_TILED_THIN1 : ADDR_TM_1D_TILED_THICK;
3725                         }
3726                         else
3727                         {
3728                             convertToPrt = TRUE;
3729                         }
3730                     }
3731                 }
3732             }
3733         }
3734     }
3735 
3736     if (convertToPrt)
3737     {
3738         if ((pInOut->flags.matchStencilTileCfg == TRUE) && (pInOut->numSamples <= 1))
3739         {
3740             pInOut->tileMode = ADDR_TM_1D_TILED_THIN1;
3741         }
3742         else
3743         {
3744             HwlSetPrtTileMode(pInOut);
3745         }
3746     }
3747     else if (tileMode != pInOut->tileMode)
3748     {
3749         pInOut->tileMode = tileMode;
3750     }
3751 
3752     HwlOptimizeTileMode(pInOut);
3753 }
3754 
3755 /**
3756 ****************************************************************************************************
3757 *   Lib::DegradeLargeThickTile
3758 *
3759 *   @brief
3760 *       Check if the thickness needs to be reduced if a tile is too large
3761 *   @return
3762 *       The degraded tile mode (unchanged if not degraded)
3763 ****************************************************************************************************
3764 */
DegradeLargeThickTile(AddrTileMode tileMode,UINT_32 bpp) const3765 AddrTileMode Lib::DegradeLargeThickTile(
3766     AddrTileMode tileMode,
3767     UINT_32 bpp) const
3768 {
3769     // Override tilemode
3770     // When tile_width (8) * tile_height (8) * thickness * element_bytes is > row_size,
3771     // it is better to just use THIN mode in this case
3772     UINT_32 thickness = Thickness(tileMode);
3773 
3774     if (thickness > 1 && m_configFlags.allowLargeThickTile == 0)
3775     {
3776         UINT_32 tileSize = MicroTilePixels * thickness * (bpp >> 3);
3777 
3778         if (tileSize > m_rowSize)
3779         {
3780             switch (tileMode)
3781             {
3782                 case ADDR_TM_2D_TILED_XTHICK:
3783                     if ((tileSize >> 1) <= m_rowSize)
3784                     {
3785                         tileMode = ADDR_TM_2D_TILED_THICK;
3786                         break;
3787                     }
3788                     // else fall through
3789                 case ADDR_TM_2D_TILED_THICK:
3790                     tileMode    = ADDR_TM_2D_TILED_THIN1;
3791                     break;
3792 
3793                 case ADDR_TM_3D_TILED_XTHICK:
3794                     if ((tileSize >> 1) <= m_rowSize)
3795                     {
3796                         tileMode = ADDR_TM_3D_TILED_THICK;
3797                         break;
3798                     }
3799                     // else fall through
3800                 case ADDR_TM_3D_TILED_THICK:
3801                     tileMode    = ADDR_TM_3D_TILED_THIN1;
3802                     break;
3803 
3804                 case ADDR_TM_PRT_TILED_THICK:
3805                     tileMode    = ADDR_TM_PRT_TILED_THIN1;
3806                     break;
3807 
3808                 case ADDR_TM_PRT_2D_TILED_THICK:
3809                     tileMode    = ADDR_TM_PRT_2D_TILED_THIN1;
3810                     break;
3811 
3812                 case ADDR_TM_PRT_3D_TILED_THICK:
3813                     tileMode    = ADDR_TM_PRT_3D_TILED_THIN1;
3814                     break;
3815 
3816                 default:
3817                     break;
3818             }
3819         }
3820     }
3821 
3822     return tileMode;
3823 }
3824 
3825 /**
3826 ****************************************************************************************************
3827 *   Lib::PostComputeMipLevel
3828 *   @brief
3829 *       Compute MipLevel info (including level 0) after surface adjustment
3830 *   @return
3831 *       ADDR_E_RETURNCODE
3832 ****************************************************************************************************
3833 */
PostComputeMipLevel(ADDR_COMPUTE_SURFACE_INFO_INPUT * pIn,ADDR_COMPUTE_SURFACE_INFO_OUTPUT * pOut) const3834 ADDR_E_RETURNCODE Lib::PostComputeMipLevel(
3835     ADDR_COMPUTE_SURFACE_INFO_INPUT*    pIn,   ///< [in,out] Input structure
3836     ADDR_COMPUTE_SURFACE_INFO_OUTPUT*   pOut   ///< [out] Output structure
3837     ) const
3838 {
3839     // Mipmap including level 0 must be pow2 padded since either SI hw expects so or it is
3840     // required by CFX  for Hw Compatibility between NI and SI. Otherwise it is only needed for
3841     // mipLevel > 0. Any h/w has different requirement should implement its own virtual function
3842 
3843     if (pIn->flags.pow2Pad)
3844     {
3845         pIn->width      = NextPow2(pIn->width);
3846         pIn->height     = NextPow2(pIn->height);
3847         pIn->numSlices  = NextPow2(pIn->numSlices);
3848     }
3849     else if (pIn->mipLevel > 0)
3850     {
3851         pIn->width      = NextPow2(pIn->width);
3852         pIn->height     = NextPow2(pIn->height);
3853 
3854         if (!pIn->flags.cube)
3855         {
3856             pIn->numSlices = NextPow2(pIn->numSlices);
3857         }
3858 
3859         // for cubemap, we keep its value at first
3860     }
3861 
3862     return ADDR_OK;
3863 }
3864 
3865 /**
3866 ****************************************************************************************************
3867 *   Lib::HwlSetupTileCfg
3868 *
3869 *   @brief
3870 *       Map tile index to tile setting.
3871 *   @return
3872 *       ADDR_E_RETURNCODE
3873 ****************************************************************************************************
3874 */
HwlSetupTileCfg(UINT_32 bpp,INT_32 index,INT_32 macroModeIndex,ADDR_TILEINFO * pInfo,AddrTileMode * pMode,AddrTileType * pType) const3875 ADDR_E_RETURNCODE Lib::HwlSetupTileCfg(
3876     UINT_32         bpp,              ///< Bits per pixel
3877     INT_32          index,            ///< [in] Tile index
3878     INT_32          macroModeIndex,   ///< [in] Index in macro tile mode table(CI)
3879     ADDR_TILEINFO*  pInfo,            ///< [out] Tile Info
3880     AddrTileMode*   pMode,            ///< [out] Tile mode
3881     AddrTileType*   pType             ///< [out] Tile type
3882     ) const
3883 {
3884     return ADDR_NOTSUPPORTED;
3885 }
3886 
3887 /**
3888 ****************************************************************************************************
3889 *   Lib::HwlGetPipes
3890 *
3891 *   @brief
3892 *       Get number pipes
3893 *   @return
3894 *       num pipes
3895 ****************************************************************************************************
3896 */
HwlGetPipes(const ADDR_TILEINFO * pTileInfo) const3897 UINT_32 Lib::HwlGetPipes(
3898     const ADDR_TILEINFO* pTileInfo    ///< [in] Tile info
3899     ) const
3900 {
3901     //pTileInfo can be NULL when asic is 6xx and 8xx.
3902     return m_pipes;
3903 }
3904 
3905 /**
3906 ****************************************************************************************************
3907 *   Lib::ComputeQbStereoInfo
3908 *
3909 *   @brief
3910 *       Get quad buffer stereo information
3911 *   @return
3912 *       N/A
3913 ****************************************************************************************************
3914 */
ComputeQbStereoInfo(ADDR_COMPUTE_SURFACE_INFO_OUTPUT * pOut) const3915 VOID Lib::ComputeQbStereoInfo(
3916     ADDR_COMPUTE_SURFACE_INFO_OUTPUT*       pOut    ///< [in,out] updated pOut+pStereoInfo
3917     ) const
3918 {
3919     ADDR_ASSERT(pOut->bpp >= 8);
3920     ADDR_ASSERT((pOut->surfSize % pOut->baseAlign) == 0);
3921 
3922     // Save original height
3923     pOut->pStereoInfo->eyeHeight = pOut->height;
3924 
3925     // Right offset
3926     pOut->pStereoInfo->rightOffset = static_cast<UINT_32>(pOut->surfSize);
3927 
3928     pOut->pStereoInfo->rightSwizzle = HwlComputeQbStereoRightSwizzle(pOut);
3929     // Double height
3930     pOut->height <<= 1;
3931     pOut->pixelHeight <<= 1;
3932 
3933     // Double size
3934     pOut->surfSize <<= 1;
3935 
3936     // Right start address meets the base align since it is guaranteed by AddrLib1
3937 
3938     // 1D surface on SI may break this rule, but we can force it to meet by checking .qbStereo.
3939 }
3940 
3941 
3942 /**
3943 ****************************************************************************************************
3944 *   Lib::ComputePrtInfo
3945 *
3946 *   @brief
3947 *       Compute prt surface related info
3948 *
3949 *   @return
3950 *       ADDR_E_RETURNCODE
3951 ****************************************************************************************************
3952 */
ComputePrtInfo(const ADDR_PRT_INFO_INPUT * pIn,ADDR_PRT_INFO_OUTPUT * pOut) const3953 ADDR_E_RETURNCODE Lib::ComputePrtInfo(
3954     const ADDR_PRT_INFO_INPUT*  pIn,
3955     ADDR_PRT_INFO_OUTPUT*       pOut) const
3956 {
3957     ADDR_ASSERT(pOut != NULL);
3958 
3959     ADDR_E_RETURNCODE returnCode = ADDR_OK;
3960 
3961     UINT_32     expandX = 1;
3962     UINT_32     expandY = 1;
3963     ElemMode    elemMode;
3964 
3965     UINT_32     bpp = GetElemLib()->GetBitsPerPixel(pIn->format,
3966                                                     &elemMode,
3967                                                     &expandX,
3968                                                     &expandY);
3969 
3970     if (bpp <8 || bpp == 24 || bpp == 48 || bpp == 96)
3971     {
3972         returnCode = ADDR_INVALIDPARAMS;
3973     }
3974 
3975     UINT_32     numFrags = pIn->numFrags;
3976     ADDR_ASSERT(numFrags <= 8);
3977 
3978     UINT_32     tileWidth = 0;
3979     UINT_32     tileHeight = 0;
3980     if (returnCode == ADDR_OK)
3981     {
3982         // 3D texture without depth or 2d texture
3983         if (pIn->baseMipDepth > 1 || pIn->baseMipHeight > 1)
3984         {
3985             if (bpp == 8)
3986             {
3987                 tileWidth = 256;
3988                 tileHeight = 256;
3989             }
3990             else if (bpp == 16)
3991             {
3992                 tileWidth = 256;
3993                 tileHeight = 128;
3994             }
3995             else if (bpp == 32)
3996             {
3997                 tileWidth = 128;
3998                 tileHeight = 128;
3999             }
4000             else if (bpp == 64)
4001             {
4002                 // assume it is BC1/4
4003                 tileWidth = 512;
4004                 tileHeight = 256;
4005 
4006                 if (elemMode == ADDR_UNCOMPRESSED)
4007                 {
4008                     tileWidth = 128;
4009                     tileHeight = 64;
4010                 }
4011             }
4012             else if (bpp == 128)
4013             {
4014                 // assume it is BC2/3/5/6H/7
4015                 tileWidth = 256;
4016                 tileHeight = 256;
4017 
4018                 if (elemMode == ADDR_UNCOMPRESSED)
4019                 {
4020                     tileWidth = 64;
4021                     tileHeight = 64;
4022                 }
4023             }
4024 
4025             if (numFrags == 2)
4026             {
4027                 tileWidth = tileWidth / 2;
4028             }
4029             else if (numFrags == 4)
4030             {
4031                 tileWidth = tileWidth / 2;
4032                 tileHeight = tileHeight / 2;
4033             }
4034             else if (numFrags == 8)
4035             {
4036                 tileWidth = tileWidth / 4;
4037                 tileHeight = tileHeight / 2;
4038             }
4039         }
4040         else    // 1d
4041         {
4042             tileHeight = 1;
4043             if (bpp == 8)
4044             {
4045                 tileWidth = 65536;
4046             }
4047             else if (bpp == 16)
4048             {
4049                 tileWidth = 32768;
4050             }
4051             else if (bpp == 32)
4052             {
4053                 tileWidth = 16384;
4054             }
4055             else if (bpp == 64)
4056             {
4057                 tileWidth = 8192;
4058             }
4059             else if (bpp == 128)
4060             {
4061                 tileWidth = 4096;
4062             }
4063         }
4064     }
4065 
4066     pOut->prtTileWidth = tileWidth;
4067     pOut->prtTileHeight = tileHeight;
4068 
4069     return returnCode;
4070 }
4071 
4072 } // V1
4073 } // Addr
4074