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